From 8aa79e9fe5bcdd6e492c146ed9ac614e6db18302 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Fri, 26 Aug 2022 05:47:22 -0400 Subject: [PATCH 01/31] h1r9: use timer to detect external clock frequency --- firmware/common/clkin.c | 114 +++++++++++++++++++++++++++++++ firmware/common/clkin.h | 30 ++++++++ firmware/common/hackrf_core.c | 6 +- firmware/hackrf-common.cmake | 2 + firmware/hackrf_usb/hackrf_usb.c | 4 ++ 5 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 firmware/common/clkin.c create mode 100644 firmware/common/clkin.h diff --git a/firmware/common/clkin.c b/firmware/common/clkin.c new file mode 100644 index 000000000..bef8b8a98 --- /dev/null +++ b/firmware/common/clkin.c @@ -0,0 +1,114 @@ +/* + * Copyright 2022 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "gpdma.h" +#include +#include +#include +#include + +#define CLOCK_CYCLES_1_MS (204000) +#define MEASUREMENT_WINDOW_MS (50) +#define MEASUREMENT_CYCLES (CLOCK_CYCLES_1_MS * MEASUREMENT_WINDOW_MS) + +/* DMA linked list item */ +typedef struct { + uint32_t src; + uint32_t dest; + uint32_t next_lli; + uint32_t control; +} dma_lli; + +/* timer control register configuration sequence */ +typedef struct { + uint32_t first_tcr; + uint32_t second_tcr; +} tcr_sequence; + +dma_lli timer_dma_lli; +tcr_sequence reset; + +void clkin_detect_init(void) +{ + /* Timer3 triggers periodic measurement */ + timer_set_prescaler(TIMER3, 0); + timer_set_mode(TIMER3, TIMER_CTCR_MODE_TIMER); + TIMER3_MCR = TIMER_MCR_MR0R; + TIMER3_EMR = TIMER_EMR_EM0 | TIMER_EMR_EM3 | + (TIMER_EMR_EMC_SET << TIMER_EMR_EMC0_SHIFT) | + (TIMER_EMR_EMC_TOGGLE << TIMER_EMR_EMC3_SHIFT); + TIMER3_MR3 = MEASUREMENT_CYCLES; + TIMER3_MR0 = MEASUREMENT_CYCLES; + + /* Timer0 counts CLKIN */ + timer_set_prescaler(TIMER0, 0); + TIMER0_CCR = TIMER_CCR_CAP3RE; + GIMA_CAP0_3_IN = 0x20; // T3_MAT3 + + /* measure CLKIN signal on P2_5, pin 91, CTIN_2 */ + TIMER0_CTCR = TIMER_CTCR_MODE_COUNTER_RISING | TIMER_CTCR_CINSEL_CAPN_2; + scu_pinmux(P2_5, SCU_GPIO_PDN | SCU_CONF_FUNCTION1); + GIMA_CAP0_2_IN = 0x00; // CTIN_2 + + // temporarily testing with T0_CAP1, P1_12, pin 56, P28 pin 4 + //TIMER0_CTCR = TIMER_CTCR_MODE_COUNTER_RISING | TIMER_CTCR_CINSEL_CAPN_1; + //scu_pinmux(P1_12, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); + //GIMA_CAP0_1_IN = 0x20; // T0_CAP1 + + reset.first_tcr = TIMER_TCR_CEN | TIMER_TCR_CRST; + reset.second_tcr = TIMER_TCR_CEN; + timer_dma_lli.src = (uint32_t) & (reset); + timer_dma_lli.dest = (uint32_t) & (TIMER0_TCR); + timer_dma_lli.next_lli = (uint32_t) & (timer_dma_lli); + timer_dma_lli.control = GPDMA_CCONTROL_TRANSFERSIZE(2) | + GPDMA_CCONTROL_SBSIZE(0) // 1 + | GPDMA_CCONTROL_DBSIZE(0) // 1 + | GPDMA_CCONTROL_SWIDTH(2) // 32-bit word + | GPDMA_CCONTROL_DWIDTH(2) // 32-bit word + | GPDMA_CCONTROL_S(0) // AHB Master 0 + | GPDMA_CCONTROL_D(1) // AHB Master 1 + | GPDMA_CCONTROL_SI(1) // increment source + | GPDMA_CCONTROL_DI(0) // do not increment destination + | GPDMA_CCONTROL_PROT1(0) // user mode + | GPDMA_CCONTROL_PROT2(0) // not bufferable + | GPDMA_CCONTROL_PROT3(0) // not cacheable + | GPDMA_CCONTROL_I(0); // interrupt disabled + gpdma_controller_enable(); + GPDMA_C0SRCADDR = timer_dma_lli.src; + GPDMA_C0DESTADDR = timer_dma_lli.dest; + GPDMA_C0LLI = timer_dma_lli.next_lli; + GPDMA_C0CONTROL = timer_dma_lli.control; + GPDMA_C0CONFIG = GPDMA_CCONFIG_DESTPERIPHERAL(0x7) // T3_MAT0 + | GPDMA_CCONFIG_FLOWCNTRL(1) // memory-to-peripheral + | GPDMA_CCONFIG_H(0); // do not halt + gpdma_channel_enable(0); + + /* start counting */ + timer_reset(TIMER0); + timer_reset(TIMER3); + timer_enable_counter(TIMER0); + timer_enable_counter(TIMER3); +} + +uint32_t clkin_frequency(void) +{ + return TIMER0_CR3 * (1000 / MEASUREMENT_WINDOW_MS); +}; diff --git a/firmware/common/clkin.h b/firmware/common/clkin.h new file mode 100644 index 000000000..2f2fa274c --- /dev/null +++ b/firmware/common/clkin.h @@ -0,0 +1,30 @@ +/* + * Copyright 2022 Great Scott Gadgets + * + * 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 __CLKIN_H__ +#define __CLKIN_H__ + +#include + +void clkin_detect_init(void); +uint32_t clkin_frequency(void); + +#endif //__CLKIN_H__ diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index bc0bb4b33..e0f4a8803 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -727,7 +727,7 @@ void cpu_clock_init(void) CCU1_CLK_APB3_ADC1_CFG = 0; CCU1_CLK_APB3_CAN0_CFG = 0; CCU1_CLK_APB3_DAC_CFG = 0; - CCU1_CLK_M4_DMA_CFG = 0; + //CCU1_CLK_M4_DMA_CFG = 0; CCU1_CLK_M4_EMC_CFG = 0; CCU1_CLK_M4_EMCDIV_CFG = 0; CCU1_CLK_M4_ETHERNET_CFG = 0; @@ -737,10 +737,10 @@ void cpu_clock_init(void) // CCU1_CLK_M4_SCT_CFG = 0; CCU1_CLK_M4_SDIO_CFG = 0; CCU1_CLK_M4_SPIFI_CFG = 0; - CCU1_CLK_M4_TIMER0_CFG = 0; + //CCU1_CLK_M4_TIMER0_CFG = 0; CCU1_CLK_M4_TIMER1_CFG = 0; CCU1_CLK_M4_TIMER2_CFG = 0; - CCU1_CLK_M4_TIMER3_CFG = 0; + //CCU1_CLK_M4_TIMER3_CFG = 0; CCU1_CLK_M4_UART1_CFG = 0; CCU1_CLK_M4_USART0_CFG = 0; CCU1_CLK_M4_USART2_CFG = 0; diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index e72319238..ddc76a19d 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -185,6 +185,8 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/hackrf_ui.c ${PATH_HACKRF_FIRMWARE_COMMON}/platform_detect.c ${PATH_HACKRF_FIRMWARE_COMMON}/firmware_info.c + ${PATH_HACKRF_FIRMWARE_COMMON}/clkin.c + ${PATH_HACKRF_FIRMWARE_COMMON}/gpdma.c ) if(BOARD STREQUAL "RAD1O") diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 56dd3ebcd..893ecd539 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -55,6 +56,7 @@ #include "portapack.h" #include "hackrf_ui.h" #include "platform_detect.h" +#include "clkin.h" extern uint32_t __m0_start__; extern uint32_t __m0_end__; @@ -286,6 +288,8 @@ int main(void) } operacake_init(operacake_allow_gpio); + clkin_detect_init(); + while (true) { transceiver_request_t request; From 6d48671084ce2cf7c31ecf1ff96db9d8a914d0cc Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 6 Sep 2022 07:28:15 -0400 Subject: [PATCH 02/31] 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 e0f4a8803..122dcae0e 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 e24007eb8..54f3e63d7 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 3ca6fd75c..804f0784e 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 394a6dd57..d7d97fdb9 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 bacf79355..493cc73be 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 } From 1f73f2fd2519b2c513f1206955f65f1fdadd937d Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 8 Sep 2022 03:33:47 -0400 Subject: [PATCH 03/31] h1r9: add Si5351A support --- firmware/common/hackrf_core.c | 123 +++++++++++++++++++++++++--------- firmware/common/si5351c.c | 57 +++++++++++----- 2 files changed, 131 insertions(+), 49 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 122dcae0e..0d313df09 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -36,6 +36,7 @@ #include "i2c_lpc.h" #include "cpld_jtag.h" #include "platform_detect.h" +#include "clkin.h" #include #include #include @@ -414,14 +415,26 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom) MSx_P2 = (128 * b) % c; MSx_P3 = c; - /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ - 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(&clock_gen, 1, 0, 0, 0, 0); //p1 doesn't matter - - /* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */ - si5351c_configure_multisynth(&clock_gen, 2, 0, 0, 0, 0); //p1 doesn't matter + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + /* + * On HackRF One r9 all sample clocks are externally derived + * from MS1/CLK1 operating at twice the sample rate. + */ + si5351c_configure_multisynth(&clock_gen, 1, MSx_P1, MSx_P2, MSx_P3, 0); + } else { + /* + * On other platforms the clock generator produces three + * different sample clocks, all derived from multisynth 0. + */ + /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ + 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(&clock_gen, 1, 0, 0, 0, 0); //p1 doesn't matter + + /* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */ + si5351c_configure_multisynth(&clock_gen, 2, 0, 0, 0, 0); //p1 doesn't matter + } if (streaming) { sgpio_cpld_stream_enable(&sgpio_config); @@ -482,14 +495,38 @@ bool sample_rate_set(const uint32_t sample_rate_hz) return false; } - /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ - si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); - - /* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ - 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(&clock_gen, 2, p1, 0, 1, 0); //p1 doesn't matter + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + /* + * On HackRF One r9 all sample clocks are externally derived + * from MS1/CLK1 operating at twice the sample rate. + */ + si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 0); + } else { + /* + * On other platforms the clock generator produces three + * different sample clocks, all derived from multisynth 0. + */ + /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ + si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); + + /* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ + 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( + &clock_gen, + 2, + p1, + 0, + 1, + 0); //p1 doesn't matter + } return true; } @@ -596,7 +633,12 @@ void cpu_clock_init(void) si5351c_configure_pll_multisynth(&clock_gen); /* - * Clocks: + * Clocks on HackRF One r9: + * CLK0 -> MAX5864/CPLD/SGPIO (sample clocks) + * CLK1 -> RFFC5072/MAX2837 + * CLK2 -> External Clock Output/LPC43xx (power down at boot) + * + * Clocks on other platforms: * CLK0 -> MAX5864/CPLD * CLK1 -> CPLD * CLK2 -> SGPIO @@ -607,22 +649,33 @@ void cpu_clock_init(void) * CLK7 -> LPC43xx (uses a 12MHz crystal by default) */ - /* MS4/CLK4 is the source for the RFFC5071 mixer (MAX2837 on rad1o). */ - si5351c_configure_multisynth( - &clock_gen, - 4, - 20 * 128 - 512, - 0, - 1, - 0); /* 800/20 = 40MHz */ - /* MS5/CLK5 is the source for the MAX2837 clock input (MAX2871 on rad1o). */ - si5351c_configure_multisynth( - &clock_gen, - 5, - 20 * 128 - 512, - 0, - 1, - 0); /* 800/20 = 40MHz */ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + /* MS0/CLK0 is the reference for both RFFC5071 and MAX2837. */ + si5351c_configure_multisynth( + &clock_gen, + 0, + 20 * 128 - 512, + 0, + 1, + 0); /* 800/20 = 40MHz */ + } else { + /* MS4/CLK4 is the source for the RFFC5071 mixer (MAX2837 on rad1o). */ + si5351c_configure_multisynth( + &clock_gen, + 4, + 20 * 128 - 512, + 0, + 1, + 0); /* 800/20 = 40MHz */ + /* MS5/CLK5 is the source for the MAX2837 clock input (MAX2871 on rad1o). */ + si5351c_configure_multisynth( + &clock_gen, + 5, + 20 * 128 - 512, + 0, + 1, + 0); /* 800/20 = 40MHz */ + } /* MS6/CLK6 is unused. */ /* MS7/CLK7 is unused. */ @@ -766,6 +819,10 @@ void cpu_clock_init(void) // CCU2_CLK_APLL_CFG = 0; // CCU2_CLK_SDIO_CFG = 0; #endif + + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + clkin_detect_init(); + } } clock_source_t activate_best_clock_source(void) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index d7d97fdb9..09f1ba6a0 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -191,7 +191,7 @@ void si5351c_configure_clock_control( const enum pll_sources source) { uint8_t pll; - uint8_t clk3_ctrl; + uint8_t clkout_ctrl; #ifdef RAD1O (void) source; @@ -201,31 +201,29 @@ void si5351c_configure_clock_control( #if (defined JAWBREAKER || defined HACKRF_ONE) if (source == PLL_SOURCE_CLKIN) { - if (detected_platform() < BOARD_ID_HACKRF1_R9) { + /* 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) { + if (detected_platform() == BOARD_ID_HACKRF1_R9) { gpio_clear(&gpio_h1r9_clkin_en); } } #endif if (clkout_enabled) { - clk3_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | + clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA); } else { - clk3_ctrl = SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE; + clkout_ctrl = SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE; } /* Clock to CPU is deactivated as it is not used and creates noise */ @@ -241,7 +239,7 @@ void si5351c_configure_clock_control( SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA), - clk3_ctrl, + clkout_ctrl, SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA) | SI5351C_CLK_INV, @@ -249,18 +247,28 @@ void si5351c_configure_clock_control( SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA), SI5351C_CLK_POWERDOWN | - SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/ - , + SI5351C_CLK_INT_MODE, /* not connected, but: PLL A int mode */ SI5351C_CLK_POWERDOWN | - SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/ + SI5351C_CLK_INT_MODE /* not connected, but: PLL B int mode */ }; + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + data[1] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC_A | + SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | + SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA); + data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC_A | + SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | + SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA); + data[3] = clkout_ctrl; + data[4] = SI5351C_CLK_POWERDOWN; + data[5] = SI5351C_CLK_POWERDOWN; + data[6] = SI5351C_CLK_POWERDOWN; + } si5351c_write(drv, data, sizeof(data)); } #define SI5351C_CLK_ENABLE(x) (0 << x) #define SI5351C_CLK_DISABLE(x) (1 << x) #define SI5351C_REG_OUTPUT_EN (3) -#define SI5351C_REG_CLK3_CTRL (19) void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) { @@ -270,8 +278,19 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) uint8_t value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | SI5351C_CLK_ENABLE(2) | SI5351C_CLK_ENABLE(4) | SI5351C_CLK_ENABLE(5) | SI5351C_CLK_DISABLE(6) | SI5351C_CLK_DISABLE(7); + uint8_t clkout = 3; - value |= (clkout_enabled) ? SI5351C_CLK_ENABLE(3) : SI5351C_CLK_DISABLE(3); + /* HackRF One r9 has only three clock generator outputs. */ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + clkout = 2; + value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | + SI5351C_CLK_DISABLE(3) | SI5351C_CLK_DISABLE(4) | + SI5351C_CLK_DISABLE(5) | SI5351C_CLK_DISABLE(6) | + SI5351C_CLK_DISABLE(7); + } + + value |= (clkout_enabled) ? SI5351C_CLK_ENABLE(clkout) : + SI5351C_CLK_DISABLE(clkout); uint8_t data[] = {SI5351C_REG_OUTPUT_EN, value}; si5351c_write(drv, data, sizeof(data)); @@ -325,8 +344,14 @@ void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable) { clkout_enabled = (enable > 0); + //FIXME this should be somewhere else + uint8_t clkout = 3; + /* HackRF One r9 has only three clock generator outputs. */ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + clkout = 2; + } /* Configure clock to 10MHz */ - si5351c_configure_multisynth(drv, 3, 80 * 128 - 512, 0, 1, 0); + si5351c_configure_multisynth(drv, clkout, 80 * 128 - 512, 0, 1, 0); si5351c_configure_clock_control(drv, active_clock_source); si5351c_enable_clock_outputs(drv); From 4ffe3658be3d5f5955ff8a8e5bf8f6fcc37a6b94 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sat, 10 Sep 2022 16:57:15 -0400 Subject: [PATCH 04/31] h1r9: add max2839_target.c --- firmware/common/max2839_target.c | 98 ++++++++++++++++++++++++++++++++ firmware/common/max2839_target.h | 32 +++++++++++ 2 files changed, 130 insertions(+) create mode 100644 firmware/common/max2839_target.c create mode 100644 firmware/common/max2839_target.h diff --git a/firmware/common/max2839_target.c b/firmware/common/max2839_target.c new file mode 100644 index 000000000..356313e94 --- /dev/null +++ b/firmware/common/max2839_target.c @@ -0,0 +1,98 @@ +/* + * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2014 Jared Boone + * Copyright 2012 Will Code + * + * 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 "max2839_target.h" + +#include +#include "hackrf_core.h" + +void max2839_target_init(max2839_driver_t* const drv) +{ + /* Configure SSP1 Peripheral (to be moved later in SSP driver) */ + scu_pinmux(SCU_SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(SCU_SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); + + scu_pinmux(SCU_XCVR_CS, SCU_GPIO_FAST); + + /* + * Configure XCVR_CTL GPIO pins. + * + * The RXTX pin is also known as RXENABLE because of its use on the + * MAX2837 which had a separate TXENABLE. On MAX2839 a single RXTX pin + * switches between RX (high) and TX (low) modes. + */ + scu_pinmux(SCU_XCVR_ENABLE, SCU_GPIO_FAST); + scu_pinmux(SCU_XCVR_RXENABLE, SCU_GPIO_FAST); + + /* Set GPIO pins as outputs. */ + gpio_output(drv->gpio_enable); + gpio_output(drv->gpio_rxtx); +} + +void max2839_target_set_mode(max2839_driver_t* const drv, const max2839_mode_t new_mode) +{ + /* MAX2839_MODE_SHUTDOWN: + * All circuit blocks are powered down, except the 4-wire serial bus + * and its internal programmable registers. + * + * MAX2839_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. + * + * MAX2839_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. + * + * MAX2839_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. + */ + + switch (new_mode) { + default: + case MAX2839_MODE_SHUTDOWN: + gpio_clear(drv->gpio_enable); + gpio_clear(drv->gpio_rxtx); + break; + case MAX2839_MODE_STANDBY: + gpio_clear(drv->gpio_enable); + gpio_set(drv->gpio_rxtx); + break; + case MAX2839_MODE_TX: + gpio_set(drv->gpio_enable); + gpio_clear(drv->gpio_rxtx); + break; + case MAX2839_MODE_RX: + gpio_set(drv->gpio_enable); + gpio_set(drv->gpio_rxtx); + break; + } + drv->mode = new_mode; +} diff --git a/firmware/common/max2839_target.h b/firmware/common/max2839_target.h new file mode 100644 index 000000000..894882436 --- /dev/null +++ b/firmware/common/max2839_target.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2014 Jared Boone + * Copyright 2012 Will Code + * + * 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 __MAX2839_TARGET_H +#define __MAX2839_TARGET_H + +#include "max2839.h" + +void max2839_target_init(max2839_driver_t* const drv); +void max2839_target_set_mode(max2839_driver_t* const drv, const max2839_mode_t new_mode); + +#endif // __MAX2839_TARGET_H From b61c30a50d59c92900ad4d42ae9bbf84a62b6ef4 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sat, 17 Sep 2022 11:59:44 -0400 Subject: [PATCH 05/31] h1r9: bring-up wip --- firmware/common/hackrf_core.c | 49 +++++++++++++++++++------------ firmware/common/platform_detect.c | 6 ++-- firmware/common/rf_path.c | 2 ++ 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 0d313df09..6f707c26e 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -142,8 +142,9 @@ 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); +static struct gpio_t gpio_h1r9_rx = GPIO(0, 7); +static struct gpio_t gpio_h1r9_no_rx_amp_pwr = GPIO(3, 6); +static struct gpio_t gpio_h1r9_1v8_enable = GPIO(1, 12); #endif // clang-format on @@ -500,7 +501,7 @@ bool sample_rate_set(const uint32_t sample_rate_hz) * On HackRF One r9 all sample clocks are externally derived * from MS1/CLK1 operating at twice the sample rate. */ - si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 0); + si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 0); } else { /* * On other platforms the clock generator produces three @@ -877,13 +878,6 @@ 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. @@ -928,13 +922,13 @@ void pin_setup(void) gpio_output(&gpio_led[3]); #endif + disable_1v8_power(); if (detected_platform() == BOARD_ID_HACKRF1_R9) { - //gpio_1v8_enable = GPIO(1, 12); - disable_1v8_power(); - gpio_output(&gpio_1v8_enable); +#ifdef HACKRF_ONE + gpio_output(&gpio_h1r9_1v8_enable); scu_pinmux(P2_12, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); +#endif } else { - disable_1v8_power(); gpio_output(&gpio_1v8_enable); scu_pinmux(SCU_PINMUX_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); } @@ -966,12 +960,17 @@ void pin_setup(void) /* enable input on SCL and SDA pins */ SCU_SFSI2C0 = SCU_I2C0_NOMINAL; - spi_bus_start(&spi_bus_ssp1, &ssp_config_max2837); + //FIXME + //spi_bus_start(&spi_bus_ssp1, &ssp_config_max2837); mixer_bus_setup(&mixer); - rf_path.gpio_rx = &gpio_h1r9_rx; - rf_path.gpio_no_rx_amp_pwr = &gpio_h1r9_no_rx_amp_pwr; +#ifdef HACKRF_ONE + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + rf_path.gpio_rx = &gpio_h1r9_rx; + rf_path.gpio_no_rx_amp_pwr = &gpio_h1r9_no_rx_amp_pwr; + } +#endif rf_path_pin_setup(&rf_path); /* Configure external clock in */ @@ -982,12 +981,24 @@ void pin_setup(void) void enable_1v8_power(void) { - gpio_set(&gpio_1v8_enable); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { +#ifdef HACKRF_ONE + gpio_set(&gpio_h1r9_1v8_enable); +#endif + } else { + gpio_set(&gpio_1v8_enable); + } } void disable_1v8_power(void) { - gpio_clear(&gpio_1v8_enable); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { +#ifdef HACKRF_ONE + gpio_clear(&gpio_h1r9_1v8_enable); +#endif + } else { + gpio_clear(&gpio_1v8_enable); + } } #ifdef HACKRF_ONE diff --git a/firmware/common/platform_detect.c b/firmware/common/platform_detect.c index 5430c5d82..ee9b8d543 100644 --- a/firmware/common/platform_detect.c +++ b/firmware/common/platform_detect.c @@ -42,13 +42,13 @@ static struct gpio_t gpio3_6_on_P6_10 = GPIO(3, 6); * Jawbreaker has a pull-down on P6_10 and nothing on P5_0. * rad1o has a pull-down on P6_10 and a pull-down on P5_0. * HackRF One OG has a pull-down on P6_10 and a pull-up on P5_0. - * HackRF One r9 has a pull-up on P6_10 and a pull-down on P5_0. + * HackRF One r9 has a pull-up on P6_10 and a pull-up on P5_0. //FIXME temporary */ #define JAWBREAKER_RESISTORS (P6_10_PDN) #define RAD1O_RESISTORS (P6_10_PDN | P5_0_PDN) #define HACKRF1_OG_RESISTORS (P6_10_PDN | P5_0_PUP) -#define HACKRF1_R9_RESISTORS (P6_10_PUP | P5_0_PDN) +#define HACKRF1_R9_RESISTORS (P6_10_PUP | P5_0_PUP) /* * LEDs are configured so that they flash if the detected hardware platform is @@ -165,7 +165,7 @@ void detect_hardware_platform(void) platform = BOARD_ID_HACKRF1_OG; break; case HACKRF1_R9_RESISTORS: - if (!(supported_platform() & PLATFORM_HACKRF1_R9)) { + if (!(supported_platform() & PLATFORM_HACKRF1_OG)) { //FIXME temporary halt_and_flash(3000000); } platform = BOARD_ID_HACKRF1_R9; diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 804f0784e..592224b14 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -96,7 +96,9 @@ * microcontroller. */ +#ifdef HACKRF_ONE static struct gpio_t gpio_h1r9_no_ant_pwr = GPIO(2, 4); //FIXME max2837_tx_enable conflict +#endif #ifdef HACKRF_ONE static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) From dcb9cd1beb59c4e4b306b10efc716ded3666d413 Mon Sep 17 00:00:00 2001 From: grvvy Date: Tue, 13 Sep 2022 14:48:20 -0600 Subject: [PATCH 06/31] h1r9: add preliminary MAX2839 register definitions --- firmware/common/max2839_regs.def | 210 +++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 firmware/common/max2839_regs.def diff --git a/firmware/common/max2839_regs.def b/firmware/common/max2839_regs.def new file mode 100644 index 000000000..b1f34bfb8 --- /dev/null +++ b/firmware/common/max2839_regs.def @@ -0,0 +1,210 @@ +/* -*- mode: c -*- */ + +#ifndef __MAX2839_REGS_DEF +#define __MAX2839_REGS_DEF + +/* Generate static inline accessors that operate on the global + * regs. Done this way to (1) allow defs to be scraped out and used + * elsewhere, e.g. in scripts, (2) to avoid dealing with endian + * (structs). This may be used in firmware, or on host predefined + * register loads. */ + +#define MAX2839_REG_SET_CLEAN(_d, _r) (_d->regs_dirty &= ~(1UL<<_r)) +#define MAX2839_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(max2839_driver_t* const _d) { \ + return (_d->regs[r] >> (o-l+1)) & ((1<regs[r] &= ~(((1<regs[r] |= ((v&((1< Date: Tue, 13 Sep 2022 15:22:47 -0600 Subject: [PATCH 07/31] h1r9: add preliminary MAX2839 driver and accompanying header file; add some convenience macros to regs_def --- firmware/common/max2839.c | 276 +++++++++++++++++++++++++++++++ firmware/common/max2839.h | 97 +++++++++++ firmware/common/max2839_regs.def | 20 +++ 3 files changed, 393 insertions(+) create mode 100644 firmware/common/max2839.c create mode 100644 firmware/common/max2839.h diff --git a/firmware/common/max2839.c b/firmware/common/max2839.c new file mode 100644 index 000000000..b10e9881f --- /dev/null +++ b/firmware/common/max2839.c @@ -0,0 +1,276 @@ +/* + * 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 max2839.c' prints out what test + * program would do if it had a real spi library + * + * 'gcc -DTEST -DBUS_PIRATE -O2 -o test max2839.c' prints out bus + * pirate commands to do the same thing. + */ + +#include +#include +#include "max2839.h" +#include "max2839_regs.def" // private register def macros + +/* Default register values. */ +static const uint16_t max2839_regs_default[MAX2839_NUM_REGS] = { + 0x000, /* 0 */ + 0x00C, /* 1 */ + 0x080, /* 2 */ + 0x1b9, /* 3 */ + 0x3e6, /* 4 */ + 0x100, /* 5 */ + 0x000, /* 6 */ + 0x208, /* 7 */ + 0x220, /* 8 */ + 0x018, /* 9 */ + 0x00c, /* 10 */ + 0x004, /* 11 */ + 0x24f, /* 12 */ + 0x150, /* 13 */ + 0x3c5, /* 14 */ + 0x201, /* 15 */ + 0x01c, /* 16 */ + 0x155, /* 17 */ + 0x155, /* 18 */ + 0x153, /* 19 */ + 0x249, /* 20 */ + /* + * Charge Pump Common Mode Enable bit (0) of register 21 must be set or TX + * does not work. Page 1 of the SPI doc says not to set it (0x02c), but + * page 21 says it should be set by default (0x02d). + */ + 0x02d, /* 21 */ + 0x1a9, /* 22 */ + 0x24f, /* 23 */ + 0x180, /* 24 */ + 0x000, /* 25 */ + 0x3c0, /* 26 */ + 0x200, /* 27 */ + 0x0c0, /* 28 */ + 0x03f, /* 29 */ + 0x380, /* 30 */ + 0x340}; /* 31 */ + +/* Set up all registers according to defaults specified in docs. */ +static void max2839_init(max2839_driver_t* const drv) +{ + drv->target_init(drv); + max2839_set_mode(drv, MAX2839_MODE_SHUTDOWN); + + memcpy(drv->regs, max2839_regs_default, sizeof(drv->regs)); + drv->regs_dirty = 0xffffffff; + + /* Write default register values to chip. */ + 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 max2839_setup(max2839_driver_t* const drv) +{ + max2839_init(drv); + // TODO + max2839_regs_commit(drv); +} + +static uint16_t max2839_read(max2839_driver_t* const drv, uint8_t r) +{ + uint16_t value = (1 << 15) | (r << 10); + spi_bus_transfer(drv->bus, &value, 1); + return value & 0x3ff; +} + +static void max2839_write(max2839_driver_t* const drv, uint8_t r, uint16_t v) +{ + uint16_t value = (r << 10) | (v & 0x3ff); + spi_bus_transfer(drv->bus, &value, 1); +} + +uint16_t max2839_reg_read(max2839_driver_t* const drv, uint8_t r) +{ + if ((drv->regs_dirty >> r) & 0x1) { + drv->regs[r] = max2839_read(drv, r); + }; + return drv->regs[r]; +} + +void max2839_reg_write(max2839_driver_t* const drv, uint8_t r, uint16_t v) +{ + drv->regs[r] = v; + max2839_write(drv, r, v); + MAX2839_REG_SET_CLEAN(drv, r); +} + +static inline void max2839_reg_commit(max2839_driver_t* const drv, uint8_t r) +{ + max2839_reg_write(drv, r, drv->regs[r]); +} + +void max2839_regs_commit(max2839_driver_t* const drv) +{ + int r; + for (r = 0; r < MAX2839_NUM_REGS; r++) { + if ((drv->regs_dirty >> r) & 0x1) { + max2839_reg_commit(drv, r); + } + } +} + +void max2839_set_mode(max2839_driver_t* const drv, const max2839_mode_t new_mode) +{ + drv->set_mode(drv, new_mode); +} + +max2839_mode_t max2839_mode(max2839_driver_t* const drv) +{ + return drv->mode; +} + +void max2839_start(max2839_driver_t* const drv) +{ + set_MAX2839_EN_SPI(drv, 1); + max2839_regs_commit(drv); + max2839_set_mode(drv, MAX2839_MODE_STANDBY); +} + +void max2839_tx(max2839_driver_t* const drv) +{ + // TODO + max2839_regs_commit(drv); + max2839_set_mode(drv, MAX2839_MODE_TX); +} + +void max2839_rx(max2839_driver_t* const drv) +{ + // TODO + max2839_regs_commit(drv); + max2839_set_mode(drv, MAX2839_MODE_RX); +} + +void max2839_stop(max2839_driver_t* const drv) +{ + // TODO + max2839_regs_commit(drv); + max2839_set_mode(drv, MAX2839_MODE_SHUTDOWN); +} + +void max2839_set_frequency(max2839_driver_t* const drv, uint32_t freq) +{ + // TODO +} + +typedef struct { + uint32_t bandwidth_hz; + uint32_t ft; +} max2839_ft_t; + +// clang-format off +static const max2839_ft_t max2839_ft[] = { + { 1750000, MAX2839_FT_1_75M }, + { 2500000, MAX2839_FT_2_5M }, + { 3500000, MAX2839_FT_3_5M }, + { 5000000, MAX2839_FT_5M }, + { 5500000, MAX2839_FT_5_5M }, + { 6000000, MAX2839_FT_6M }, + { 7000000, MAX2839_FT_7M }, + { 8000000, MAX2839_FT_8M }, + { 9000000, MAX2839_FT_9M }, + { 10000000, MAX2839_FT_10M }, + { 12000000, MAX2839_FT_12M }, + { 14000000, MAX2839_FT_14M }, + { 15000000, MAX2839_FT_15M }, + { 20000000, MAX2839_FT_20M }, + { 24000000, MAX2839_FT_24M }, + { 28000000, MAX2839_FT_28M }, + { 0, 0 }, +}; +//clang-format on + +uint32_t max2839_set_lpf_bandwidth(max2839_driver_t* const drv, const uint32_t bandwidth_hz) { + const max2839_ft_t* p = max2839_ft; + while( p->bandwidth_hz != 0 ) { + if( p->bandwidth_hz >= bandwidth_hz ) { + break; + } + p++; + } + + if( p->bandwidth_hz != 0 ) { + set_MAX2839_FT(drv, p->ft); + max2839_regs_commit(drv); + } + + return p->bandwidth_hz; +} + +bool max2839_set_lna_gain(max2839_driver_t* const drv, const uint32_t gain_db) { + uint16_t val; + // TODO: validate steps here + switch(gain_db){ + case 40: + val = MAX2839_LNAgain_MAX; + break; + case 32: + val = MAX2839_LNAgain_M8; + break; + case 24: + val = MAX2839_LNAgain_M16; + break; + case 8: + val = MAX2839_LNAgain_M32; + break; + default: + return false; + } + set_MAX2839_LNAgain(drv, val); + max2839_reg_commit(drv, 1); + return true; +} + +bool max2839_set_vga_gain(max2839_driver_t* const drv, const uint32_t gain_db) { + if( (gain_db & 0x1) || gain_db > 62) {/* 0b11111*2 */ + return false; +} + + set_MAX2839_VGA(drv, 31-(gain_db >> 1) ); + max2839_reg_commit(drv, 5); + return true; +} + +bool max2839_set_txvga_gain(max2839_driver_t* const drv, const uint32_t gain_db) { + uint16_t val=0; + if(gain_db <16){ + val = 31-gain_db; + val |= (1 << 5); // bit6: 16db + } else{ + val = 31-(gain_db-16); + } + + set_MAX2839_TXVGA_GAIN(drv, val); + max2839_reg_commit(drv, 29); + return true; +} diff --git a/firmware/common/max2839.h b/firmware/common/max2839.h new file mode 100644 index 000000000..915c365aa --- /dev/null +++ b/firmware/common/max2839.h @@ -0,0 +1,97 @@ +/* + * 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 __MAX2839_H +#define __MAX2839_H + +#include +#include + +#include "gpio.h" +#include "spi_bus.h" + +/* 32 registers, each containing 10 bits of data. */ +#define MAX2839_NUM_REGS 32 +#define MAX2839_DATA_REGS_MAX_VALUE 1024 + +typedef enum { + MAX2839_MODE_SHUTDOWN, + MAX2839_MODE_CLKOUT, + MAX2839_MODE_STANDBY, + MAX2839_MODE_RX, + MAX2839_MODE_TX, + MAX2839_MODE_RX_CAL, + MAX2839_MODE_TX_CAL, +} max2839_mode_t; + +struct max2839_driver_t; +typedef struct max2839_driver_t max2839_driver_t; + +struct max2839_driver_t { + spi_bus_t* const bus; + gpio_t gpio_enable; + gpio_t gpio_rx_enable; + gpio_t gpio_tx_enable; + void (*target_init)(max2839_driver_t* const drv); + void (*set_mode)(max2839_driver_t* const drv, const max2839_mode_t new_mode); + max2839_mode_t mode; + uint16_t regs[MAX2839_NUM_REGS]; + uint32_t regs_dirty; +}; + +/* Initialize chip. */ +extern void max2839_setup(max2839_driver_t* const drv); + +/* Read a register via SPI. Save a copy to memory and return + * value. Mark clean. */ +extern uint16_t max2839_reg_read(max2839_driver_t* const drv, uint8_t r); + +/* Write value to register via SPI and save a copy to memory. Mark + * clean. */ +extern void max2839_reg_write(max2839_driver_t* const drv, uint8_t r, uint16_t v); + +/* Write all dirty registers via SPI from memory. Mark all clean. Some + * operations require registers to be written in a certain order. Use + * provided routines for those operations. */ +extern void max2839_regs_commit(max2839_driver_t* const drv); + +max2839_mode_t max2839_mode(max2839_driver_t* const drv); +void max2839_set_mode(max2839_driver_t* const drv, const max2839_mode_t new_mode); + +/* Turn on/off all chip functions. Does not control oscillator and CLKOUT */ +extern void max2839_start(max2839_driver_t* const drv); +extern void max2839_stop(max2839_driver_t* const drv); + +/* Set frequency in Hz. Frequency setting is a multi-step function + * where order of register writes matters. */ +extern void max2839_set_frequency(max2839_driver_t* const drv, uint32_t freq); +uint32_t max2839_set_lpf_bandwidth( + max2839_driver_t* const drv, + const uint32_t bandwidth_hz); +bool max2839_set_lna_gain(max2839_driver_t* const drv, const uint32_t gain_db); +bool max2839_set_vga_gain(max2839_driver_t* const drv, const uint32_t gain_db); +bool max2839_set_txvga_gain(max2839_driver_t* const drv, const uint32_t gain_db); + +extern void max2839_tx(max2839_driver_t* const drv); +extern void max2839_rx(max2839_driver_t* const drv); + +#endif // __MAX2839_H diff --git a/firmware/common/max2839_regs.def b/firmware/common/max2839_regs.def index b1f34bfb8..9bc724106 100644 --- a/firmware/common/max2839_regs.def +++ b/firmware/common/max2839_regs.def @@ -54,9 +54,29 @@ __MREG__(MAX2839_RESERVED_6,4,1,2) __MREG__(MAX2839_LPF_CUTOFF,4,3,2) __MREG__(MAX2839_RESERVED_7,4,5,2) __MREG__(MAX2839_LPF_RF_BAND,4,9,4) +#define MAX2839_FT_1_75M 0 +#define MAX2839_FT_2_5M 1 +#define MAX2839_FT_3_5M 2 +#define MAX2839_FT_5M 3 +#define MAX2839_FT_5_5M 4 +#define MAX2839_FT_6M 5 +#define MAX2839_FT_7M 6 +#define MAX2839_FT_8M 7 +#define MAX2839_FT_9M 8 +#define MAX2839_FT_10M 9 +#define MAX2839_FT_12M 10 +#define MAX2839_FT_14M 11 +#define MAX2839_FT_15M 12 +#define MAX2839_FT_20M 13 +#define MAX2839_FT_24M 14 +#define MAX2839_FT_28M 15 /* REG 5 */ __MREG__(MAX2839_LNA1gain_SPI,5,1,2) +#define MAX2839_LNAgain_MAX 0b000 // Pad in 8dB steps, bits reversed +#define MAX2839_LNAgain_M8 0b001 +#define MAX2839_LNAgain_M16 0b010 +#define MAX2839_LNAgain_M32 0b011 __MREG__(MAX2839_Rx1_VGAgain,5,7,6) __MREG__(MAX2839_LPFblock_MODE,5,9,2) From 14183a96eac0c34e06f290a8b0f0d62e26534488 Mon Sep 17 00:00:00 2001 From: grvvy Date: Wed, 14 Sep 2022 12:49:45 -0600 Subject: [PATCH 08/31] h1r9: implement additional MAX2839 functions, change some mreg definition names, fix RF gain control math --- firmware/common/max2839.c | 94 +++++++++++++++++++++++--------- firmware/common/max2839_regs.def | 36 +++++++----- 2 files changed, 91 insertions(+), 39 deletions(-) diff --git a/firmware/common/max2839.c b/firmware/common/max2839.c index b10e9881f..c21cf93da 100644 --- a/firmware/common/max2839.c +++ b/firmware/common/max2839.c @@ -56,11 +56,6 @@ static const uint16_t max2839_regs_default[MAX2839_NUM_REGS] = { 0x155, /* 18 */ 0x153, /* 19 */ 0x249, /* 20 */ - /* - * Charge Pump Common Mode Enable bit (0) of register 21 must be set or TX - * does not work. Page 1 of the SPI doc says not to set it (0x02c), but - * page 21 says it should be set by default (0x02d). - */ 0x02d, /* 21 */ 0x1a9, /* 22 */ 0x24f, /* 23 */ @@ -83,7 +78,7 @@ static void max2839_init(max2839_driver_t* const drv) drv->regs_dirty = 0xffffffff; /* Write default register values to chip. */ - max2837_regs_commit(drv); + max2839_regs_commit(drv); } /* @@ -152,35 +147,85 @@ max2839_mode_t max2839_mode(max2839_driver_t* const drv) void max2839_start(max2839_driver_t* const drv) { - set_MAX2839_EN_SPI(drv, 1); + set_MAX2839_chip_enable(drv, 1); max2839_regs_commit(drv); max2839_set_mode(drv, MAX2839_MODE_STANDBY); } void max2839_tx(max2839_driver_t* const drv) { - // TODO + set_MAX2839_LPFblock_MODE(drv, MAX2839_ModeCtrl_TxLPF); max2839_regs_commit(drv); max2839_set_mode(drv, MAX2839_MODE_TX); } void max2839_rx(max2839_driver_t* const drv) { - // TODO + set_MAX2839_LPFblock_MODE(drv, MAX2839_ModeCtrl_RxLPF); max2839_regs_commit(drv); max2839_set_mode(drv, MAX2839_MODE_RX); } void max2839_stop(max2839_driver_t* const drv) { - // TODO + set_MAX2839_chip_enable(drv, 0); max2839_regs_commit(drv); max2839_set_mode(drv, MAX2839_MODE_SHUTDOWN); } void max2839_set_frequency(max2839_driver_t* const drv, uint32_t freq) { - // TODO + uint8_t band; + uint8_t lna_band; + uint32_t div_frac; + uint32_t div_int; + uint32_t div_rem; + uint32_t div_cmp; + int i; + + /* Select band. Allow tuning outside specified bands. */ + if (freq < 2400000000U) { + band = MAX2839_LOGEN_BSW_2_3; + lna_band = MAX2839_LNAband_2_4; + } else if (freq < 2500000000U) { + band = MAX2839_LOGEN_BSW_2_4; + lna_band = MAX2839_LNAband_2_4; + } else if (freq < 2600000000U) { + band = MAX2839_LOGEN_BSW_2_5; + lna_band = MAX2839_LNAband_2_6; + } else { + band = MAX2839_LOGEN_BSW_2_6; + lna_band = MAX2839_LNAband_2_6; + } + + /* ASSUME 40MHz PLL. Ratio = F*(4/3)/40,000,000 = F/30,000,000 */ + div_int = freq / 30000000; + div_rem = freq % 30000000; + div_frac = 0; + div_cmp = 30000000; + for (i = 0; i < 20; i++) { + div_frac <<= 1; + div_cmp >>= 1; + if (div_rem > div_cmp) { + div_frac |= 0x1; + div_rem -= div_cmp; + } + } + + /* Band settings */ + set_MAX2839_LOGEN_BSW(drv, band); + set_MAX2839_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_MAX2839_SYN_INT(drv, div_int); + set_MAX2839_SYN_FRAC_HI(drv, (div_frac >> 10) & 0x3ff); + max2839_regs_commit(drv); + set_MAX2839_SYN_FRAC_LO(drv, div_frac & 0x3ff); + max2839_regs_commit(drv); } typedef struct { @@ -229,25 +274,27 @@ uint32_t max2839_set_lpf_bandwidth(max2839_driver_t* const drv, const uint32_t b bool max2839_set_lna_gain(max2839_driver_t* const drv, const uint32_t gain_db) { uint16_t val; - // TODO: validate steps here switch(gain_db){ case 40: - val = MAX2839_LNAgain_MAX; + val = MAX2839_LNA1gain_MAX; break; case 32: - val = MAX2839_LNAgain_M8; + val = MAX2839_LNA1gain_M8; break; case 24: - val = MAX2839_LNAgain_M16; + val = MAX2839_LNA1gain_M16; break; case 8: - val = MAX2839_LNAgain_M32; + val = MAX2839_LNA1gain_M32; + break; + case 0: + val = MAX2839_LNA1gain_M32; break; default: return false; } - set_MAX2839_LNAgain(drv, val); - max2839_reg_commit(drv, 1); + set_MAX2839_LNA1gain(drv, val); + max2839_reg_commit(drv, 5); return true; } @@ -256,21 +303,16 @@ bool max2839_set_vga_gain(max2839_driver_t* const drv, const uint32_t gain_db) { return false; } - set_MAX2839_VGA(drv, 31-(gain_db >> 1) ); + set_MAX2839_Rx1_VGAgain(drv, (63-gain_db)); max2839_reg_commit(drv, 5); return true; } bool max2839_set_txvga_gain(max2839_driver_t* const drv, const uint32_t gain_db) { uint16_t val=0; - if(gain_db <16){ - val = 31-gain_db; - val |= (1 << 5); // bit6: 16db - } else{ - val = 31-(gain_db-16); - } + val = 63-gain_db; - set_MAX2839_TXVGA_GAIN(drv, val); + set_MAX2839_TX_VGA_GAIN(drv, val); max2839_reg_commit(drv, 29); return true; } diff --git a/firmware/common/max2839_regs.def b/firmware/common/max2839_regs.def index 9bc724106..821d1dda6 100644 --- a/firmware/common/max2839_regs.def +++ b/firmware/common/max2839_regs.def @@ -31,7 +31,9 @@ static inline void set_##n(max2839_driver_t* const _d, uint16_t v) { \ __MREG__(MAX2839_RESERVED_1, 0,9,10) /* REG 1 */ -__MREG__(MAX2839_LNAtune,1,1,2) +__MREG__(MAX2839_LNAband,1,1,2) +#define MAX2839_LNAband_2_4 0 // 2.3-2.5 GHz +#define MAX2839_LNAband_2_6 1 // 2.5-2.7 GHz __MREG__(MAX2839_RESERVED_2,1,2,1) __MREG__(MAX2839_MIMO_SELECT,1,3,1) __MREG__(MAX2839_iqerr_trim,1,9,6) @@ -53,7 +55,7 @@ __MREG__(MAX2839_RESERVED_5,3,9,10) __MREG__(MAX2839_RESERVED_6,4,1,2) __MREG__(MAX2839_LPF_CUTOFF,4,3,2) __MREG__(MAX2839_RESERVED_7,4,5,2) -__MREG__(MAX2839_LPF_RF_BAND,4,9,4) +__MREG__(MAX2839_FT,4,9,4) #define MAX2839_FT_1_75M 0 #define MAX2839_FT_2_5M 1 #define MAX2839_FT_3_5M 2 @@ -72,13 +74,17 @@ __MREG__(MAX2839_LPF_RF_BAND,4,9,4) #define MAX2839_FT_28M 15 /* REG 5 */ -__MREG__(MAX2839_LNA1gain_SPI,5,1,2) -#define MAX2839_LNAgain_MAX 0b000 // Pad in 8dB steps, bits reversed -#define MAX2839_LNAgain_M8 0b001 -#define MAX2839_LNAgain_M16 0b010 -#define MAX2839_LNAgain_M32 0b011 +__MREG__(MAX2839_LNA1gain,5,1,2) +#define MAX2839_LNA1gain_MAX 0b000 // Pad in 8dB steps, bits reversed +#define MAX2839_LNA1gain_M8 0b001 +#define MAX2839_LNA1gain_M16 0b010 +#define MAX2839_LNA1gain_M32 0b011 __MREG__(MAX2839_Rx1_VGAgain,5,7,6) __MREG__(MAX2839_LPFblock_MODE,5,9,2) +#define MAX2839_ModeCtrl_RxCalibration 0 +#define MAX2839_ModeCtrl_RxLPF 1 +#define MAX2839_ModeCtrl_TxLPF 2 +#define MAX2839_ModeCtrl_LPFTrim 3 /* REG 6 */ __MREG__(MAX2839_LNA2gain_SPI,6,1,2) @@ -146,7 +152,7 @@ __MREG__(MAX2839_RESERVED_15,15,8,2) __MREG__(MAX2839_RXHP_highpass_corner,15,9,1) /* REG 16 */ -__MREG__(MAX2839_chip_disable,16,0,1) +__MREG__(MAX2839_chip_enable,16,0,1) __MREG__(MAX2839_RXTX_calibration_enable,16,1,1) __MREG__(MAX2839_RESERVED_16,16,5,4) __MREG__(MAX2839_PA_bias_DAC_SPI_enable,16,6,1) @@ -154,14 +160,18 @@ __MREG__(MAX2839_PA_bias_DAC_TX_mode_enable,16,7,1) __MREG__(MAX2839_RESERVED_17,16,9,2) /* REG 17 */ -__MREG__(MAX2839_SYNTH_20bit_FDR_UH,17,9,10) +__MREG__(MAX2839_SYN_FRAC_LO,17,9,10) /* REG 18 */ -__MREG__(MAX2839_SYNTH_20bit_FDR_LH,18,9,10) +__MREG__(MAX2839_SYN_FRAC_HI,18,9,10) /* REG 19 */ -__MREG__(MAX2839_SYNTH_8bit_IDR,19,7,8) -__MREG__(MAX2839_LO_Gen_Band_Switch,19,9,2) +__MREG__(MAX2839_SYN_INT,19,7,8) +__MREG__(MAX2839_LOGEN_BSW,19,9,2) +#define MAX2839_LOGEN_BSW_2_3 0 // 2300 - <2400 MHz +#define MAX2839_LOGEN_BSW_2_4 1 // 2400 - <2500 MHz +#define MAX2839_LOGEN_BSW_2_5 2 // 2500 - <2600 MHz +#define MAX2839_LOGEN_BSW_2_6 3 // 2600 - <2700 MHz /* REG 20 */ __MREG__(MAX2839_RESERVED_18,20,0,1) @@ -213,7 +223,7 @@ __MREG__(MAX2839_PADAC_Output_Current_Ctrl,28,5,6) __MREG__(MAX2839_PADAC_TurnOn_Delay_Ctrl,28,9,4) /* REG 29 */ -__MREG__(MAX2839_TX_VGA_SPI_Gain_Ctrl_Addr27,29,5,6) +__MREG__(MAX2839_TX_VGA_GAIN,29,5,6) __MREG__(MAX2839_RESERVED_29,29,9,4) /* REG 30 */ From 3738270e4f2767dfc628f4ca89c25a151af2aae6 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sat, 17 Sep 2022 14:43:48 -0400 Subject: [PATCH 09/31] h1r9: use MAX2839 --- firmware/common/hackrf_core.c | 49 ++++++++++++++++++++--- firmware/common/hackrf_core.h | 4 ++ firmware/common/max2839.h | 3 +- firmware/common/max2839_regs.def | 68 ++++++++++++++++---------------- firmware/common/rf_path.c | 9 ++++- firmware/hackrf-common.cmake | 2 + 6 files changed, 91 insertions(+), 44 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 6f707c26e..a88e1695b 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -28,6 +28,8 @@ #include "spi_ssp.h" #include "max2837.h" #include "max2837_target.h" +#include "max2839.h" +#include "max2839_target.h" #include "max5864.h" #include "max5864_target.h" #include "w25q80bv.h" @@ -189,6 +191,20 @@ const ssp_config_t ssp_config_max2837 = { .gpio_select = &gpio_max2837_select, }; +const ssp_config_t ssp_config_max2839 = { + /* FIXME speed up once everything is working reliably */ + /* + // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + const uint8_t serial_clock_rate = 32; + const uint8_t clock_prescale_rate = 128; + */ + // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + .data_bits = SSP_DATA_16BITS, + .serial_clock_rate = 21, + .clock_prescale_rate = 2, + .gpio_select = &gpio_max2837_select, +}; + const ssp_config_t ssp_config_max5864 = { /* FIXME speed up once everything is working reliably */ /* @@ -205,7 +221,7 @@ const ssp_config_t ssp_config_max5864 = { spi_bus_t spi_bus_ssp1 = { .obj = (void*) SSP1_BASE, - .config = &ssp_config_max2837, + .config = &ssp_config_max5864, .start = spi_ssp_start, .stop = spi_ssp_stop, .transfer = spi_ssp_transfer, @@ -221,6 +237,14 @@ max2837_driver_t max2837 = { .set_mode = max2837_target_set_mode, }; +max2839_driver_t max2839 = { + .bus = &spi_bus_ssp1, + .gpio_enable = &gpio_max2837_enable, + .gpio_rxtx = &gpio_max2837_rx_enable, + .target_init = max2839_target_init, + .set_mode = max2839_target_set_mode, +}; + max5864_driver_t max5864 = { .bus = &spi_bus_ssp1, .target_init = max5864_target_init, @@ -534,7 +558,12 @@ bool sample_rate_set(const uint32_t sample_rate_hz) bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz) { - uint32_t bandwidth_hz_real = max2837_set_lpf_bandwidth(&max2837, bandwidth_hz); + uint32_t bandwidth_hz_real; + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + bandwidth_hz_real = max2839_set_lpf_bandwidth(&max2839, bandwidth_hz); + } else { + bandwidth_hz_real = max2837_set_lpf_bandwidth(&max2837, bandwidth_hz); + } if (bandwidth_hz_real) { hackrf_ui()->set_filter_bw(bandwidth_hz_real); @@ -636,7 +665,7 @@ void cpu_clock_init(void) /* * Clocks on HackRF One r9: * CLK0 -> MAX5864/CPLD/SGPIO (sample clocks) - * CLK1 -> RFFC5072/MAX2837 + * CLK1 -> RFFC5072/MAX2839 * CLK2 -> External Clock Output/LPC43xx (power down at boot) * * Clocks on other platforms: @@ -651,7 +680,7 @@ void cpu_clock_init(void) */ if (detected_platform() == BOARD_ID_HACKRF1_R9) { - /* MS0/CLK0 is the reference for both RFFC5071 and MAX2837. */ + /* MS0/CLK0 is the reference for both RFFC5071 and MAX2839. */ si5351c_configure_multisynth( &clock_gen, 0, @@ -868,6 +897,11 @@ void ssp1_set_mode_max2837(void) spi_bus_start(max2837.bus, &ssp_config_max2837); } +void ssp1_set_mode_max2839(void) +{ + spi_bus_start(max2839.bus, &ssp_config_max2839); +} + void ssp1_set_mode_max5864(void) { spi_bus_start(max5864.bus, &ssp_config_max5864); @@ -960,8 +994,11 @@ void pin_setup(void) /* enable input on SCL and SDA pins */ SCU_SFSI2C0 = SCU_I2C0_NOMINAL; - //FIXME - //spi_bus_start(&spi_bus_ssp1, &ssp_config_max2837); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + spi_bus_start(&spi_bus_ssp1, &ssp_config_max2839); + } else { + spi_bus_start(&spi_bus_ssp1, &ssp_config_max2837); + } mixer_bus_setup(&mixer); diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 54f3e63d7..8045b1d26 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -35,6 +35,7 @@ extern "C" { #include "spi_ssp.h" #include "max2837.h" +#include "max2839.h" #include "max5864.h" #include "mixer.h" #include "w25q80bv.h" @@ -267,9 +268,11 @@ void delay_us_at_mhz(uint32_t us, uint32_t mhz); extern si5351c_driver_t clock_gen; extern const ssp_config_t ssp_config_w25q80bv; extern const ssp_config_t ssp_config_max2837; +extern const ssp_config_t ssp_config_max2839; extern const ssp_config_t ssp_config_max5864; extern max2837_driver_t max2837; +extern max2839_driver_t max2839; //FIXME xcvr hal extern max5864_driver_t max5864; extern mixer_driver_t mixer; extern w25q80bv_driver_t spi_flash; @@ -280,6 +283,7 @@ extern i2c_bus_t i2c0; void cpu_clock_init(void); void ssp1_set_mode_max2837(void); +void ssp1_set_mode_max2839(void); void ssp1_set_mode_max5864(void); void pin_setup(void); diff --git a/firmware/common/max2839.h b/firmware/common/max2839.h index 915c365aa..dd7e7f3a2 100644 --- a/firmware/common/max2839.h +++ b/firmware/common/max2839.h @@ -49,8 +49,7 @@ typedef struct max2839_driver_t max2839_driver_t; struct max2839_driver_t { spi_bus_t* const bus; gpio_t gpio_enable; - gpio_t gpio_rx_enable; - gpio_t gpio_tx_enable; + gpio_t gpio_rxtx; void (*target_init)(max2839_driver_t* const drv); void (*set_mode)(max2839_driver_t* const drv, const max2839_mode_t new_mode); max2839_mode_t mode; diff --git a/firmware/common/max2839_regs.def b/firmware/common/max2839_regs.def index 821d1dda6..25ce449ef 100644 --- a/firmware/common/max2839_regs.def +++ b/firmware/common/max2839_regs.def @@ -28,13 +28,13 @@ static inline void set_##n(max2839_driver_t* const _d, uint16_t v) { \ } /* REG 0 */ -__MREG__(MAX2839_RESERVED_1, 0,9,10) +__MREG__(MAX2839_RESERVED_0_9,0,9,10) /* REG 1 */ __MREG__(MAX2839_LNAband,1,1,2) #define MAX2839_LNAband_2_4 0 // 2.3-2.5 GHz #define MAX2839_LNAband_2_6 1 // 2.5-2.7 GHz -__MREG__(MAX2839_RESERVED_2,1,2,1) +__MREG__(MAX2839_RESERVED_1_2,1,2,1) __MREG__(MAX2839_MIMO_SELECT,1,3,1) __MREG__(MAX2839_iqerr_trim,1,9,6) // TODO: D9:D4 but shows only 5 bits for values? @@ -44,17 +44,17 @@ __MREG__(MAX2839_iqerr_trim,1,9,6) /* REG 2 */ __MREG__(MAX2839_LNAgain_SPI,2,0,1) -__MREG__(MAX2839_RESERVED_3,2,1,1) +__MREG__(MAX2839_RESERVED_2_1,2,1,1) __MREG__(MAX2839_RX_IQ_SPI,2,2,1) -__MREG__(MAX2839_RESERVED_4,2,9,7) +__MREG__(MAX2839_RESERVED_2_9,2,9,7) /* REG 3 */ -__MREG__(MAX2839_RESERVED_5,3,9,10) +__MREG__(MAX2839_RESERVED_3_9,3,9,10) /* REG 4 */ -__MREG__(MAX2839_RESERVED_6,4,1,2) +__MREG__(MAX2839_RESERVED_4_1,4,1,2) __MREG__(MAX2839_LPF_CUTOFF,4,3,2) -__MREG__(MAX2839_RESERVED_7,4,5,2) +__MREG__(MAX2839_RESERVED_4_5,4,5,2) __MREG__(MAX2839_FT,4,9,4) #define MAX2839_FT_1_75M 0 #define MAX2839_FT_2_5M 1 @@ -92,36 +92,36 @@ __MREG__(MAX2839_Rx2_VGAgain,6,7,6) __MREG__(MAX2839_RX_VGAoutput,6,9,2) /* REG 7 */ -__MREG__(MAX2839_RESERVED_7,7,0,1) +__MREG__(MAX2839_RESERVED_7_0,7,0,1) __MREG__(MAX2839_RSSIselect,7,1,1) __MREG__(MAX2839_RSSImode,7,2,1) -__MREG__(MAX2839_RESERVED_8,7,6,4) +__MREG__(MAX2839_RESERVED_7_6,7,6,4) __MREG__(MAX2839_RXBBI_RXBBQ,7,7,1) -__MREG__(MAX2839_RESERVED_9,7,8,1) +__MREG__(MAX2839_RESERVED_7_8,7,8,1) __MREG__(MAX2839_RSSIinput,7,9,1) /* REG 8 */ -__MREG__(MAX2839_RESERVED_8,8,0,1) +__MREG__(MAX2839_RESERVED_8_0,8,0,1) __MREG__(MAX2839_VGAgain_SPI,8,1,1) __MREG__(MAX2839_LPFmode,8,2,1) -__MREG__(MAX2839_RESERVED_9,8,9,7) +__MREG__(MAX2839_RESERVED_8_9,8,9,7) /* REG 9 */ __MREG__(MAX2839_Temperature_ADC,9,0,1) __MREG__(MAX2839_Temperature_Clk_En,9,1,1) -__MREG__(MAX2839_RESERVED_10,9,2,1) +__MREG__(MAX2839_RESERVED_9_2,9,2,1) __MREG__(MAX2839_DOUT_Drive_Sel,9,3,1) __MREG__(MAX2839_DOUT_3state_Ctrl,9,4,1) __MREG__(MAX2839_DOUT_Pin_Sel,9,7,3) -__MREG__(MAX2839_RESERVED_11,9,9,2) +__MREG__(MAX2839_RESERVED_9_9,9,9,2) /* REG 10 */ __MREG__(MAX2839_TX_AM_gain,10,1,2) __MREG__(MAX2839_TX_AM_bandwidth,10,4,3) -__MREG__(MAX2839_RESERVED_12,10,9,5) +__MREG__(MAX2839_RESERVED_10_9,10,9,5) /* REG 11 */ -__MREG__(MAX2839_RESERVED_13,11,9,10) +__MREG__(MAX2839_RESERVED_11_9,11,9,10) /* REG 12 */ __MREG__(MAX2839_RXVGA_10M_RXEN_duration,12,1,2) @@ -146,18 +146,18 @@ __MREG__(MAX2839_PA_DRV_DAC,14,9,1) /* REG 15 */ __MREG__(MAX2839_RXVGA_HPFSM_Clk_Divider,15,0,1) -__MREG__(MAX2839_RESERVED_14,15,5,5) +__MREG__(MAX2839_RESERVED_15_5,15,5,5) __MREG__(MAX2839_RXHP_sequence_bypass,15,6,1) -__MREG__(MAX2839_RESERVED_15,15,8,2) +__MREG__(MAX2839_RESERVED_15_8,15,8,2) __MREG__(MAX2839_RXHP_highpass_corner,15,9,1) /* REG 16 */ __MREG__(MAX2839_chip_enable,16,0,1) __MREG__(MAX2839_RXTX_calibration_enable,16,1,1) -__MREG__(MAX2839_RESERVED_16,16,5,4) +__MREG__(MAX2839_RESERVED_16_5,16,5,4) __MREG__(MAX2839_PA_bias_DAC_SPI_enable,16,6,1) __MREG__(MAX2839_PA_bias_DAC_TX_mode_enable,16,7,1) -__MREG__(MAX2839_RESERVED_17,16,9,2) +__MREG__(MAX2839_RESERVED_16_9,16,9,2) /* REG 17 */ __MREG__(MAX2839_SYN_FRAC_LO,17,9,10) @@ -174,14 +174,14 @@ __MREG__(MAX2839_LOGEN_BSW,19,9,2) #define MAX2839_LOGEN_BSW_2_6 3 // 2600 - <2700 MHz /* REG 20 */ -__MREG__(MAX2839_RESERVED_18,20,0,1) +__MREG__(MAX2839_RESERVED_20_0,20,0,1) __MREG__(MAX2839_Reference_Divider_Ratio,20,2,2) -__MREG__(MAX2839_RESERVED_19,20,4,2) +__MREG__(MAX2839_RESERVED_20_4,20,4,2) __MREG__(MAX2839_CLKOUT_Buffer_Drive,20,5,1) -__MREG__(MAX2839_RESERVED_20,20,9,4) +__MREG__(MAX2839_RESERVED_20_9,20,9,4) /* REG 21 */ -__MREG__(MAX2839_RESERVED_21,21,9,10) +__MREG__(MAX2839_RESERVED_21_9,21,9,10) /* REG 22 */ __MREG__(MAX2839_VAS_Operating_Mode_Select,22,0,1) @@ -189,26 +189,26 @@ __MREG__(MAX2839_VAS_Relock_Mode_Select,22,1,1) __MREG__(MAX2839_VAS_Clk_Divide_Ratio,22,4,3) __MREG__(MAX2839_VAS_Delay_Counter_Ratio,22,6,2) __MREG__(MAX2839_VAS_Addr17_Trigger_Enable,22,7,1) -__MREG__(MAX2839_RESERVED_22,22,9,2) +__MREG__(MAX2839_RESERVED_22_9,22,9,2) /* REG 23 */ __MREG__(MAX2839_VAS_Subband_SPI_Overwrite,23,4,5) __MREG__(MAX2839_Crystal_Oscillator_Bias_Select,23,6,2) -__MREG__(MAX2839_RESERVED_23,23,9,3) +__MREG__(MAX2839_RESERVED_23_9,23,9,3) /* REG 24 */ __MREG__(MAX2839_Crystal_Oscillator_Freq_Tuning,24,6,7) -__MREG__(MAX2839_RESERVED_24,24,7,1) +__MREG__(MAX2839_RESERVED_24_7,24,7,1) __MREG__(MAX2839_CLKOUT_Divide_Ratio,24,8,1) __MREG__(MAX2839_Crystal_Oscillator_Core_Enable,24,9,1) /* REG 25 */ -__MREG__(MAX2839_RESERVED_25,25,9,10) +__MREG__(MAX2839_RESERVED_25_9,25,9,10) /* REG 26 */ -__MREG__(MAX2839_RESERVED_26,26,2,3) +__MREG__(MAX2839_RESERVED_26_2,26,2,3) __MREG__(MAX2839_LOGEN_RXTX_Gm_Enable,26,3,1) -__MREG__(MAX2839_RESERVED_27,26,5,2) +__MREG__(MAX2839_RESERVED_26_5,26,5,2) __MREG__(MAX2839_VAS_Test_Signal_Select,26,9,4) /* REG 27 */ @@ -216,7 +216,7 @@ __MREG__(MAX2839_TX_LO_IQ_Phase_SPI_Adjust_Addr27,27,5,6) __MREG__(MAX2839_TX_LO_IQ_Phase_SPI_Adjust_Enable,27,6,1) __MREG__(MAX2839_TX_VGA_Gain_SPI_Ctrl_Enable,27,7,1) __MREG__(MAX2839_TX_DC_Offset_SPI_Adjust_Enable,27,8,1) -__MREG__(MAX2839_RESERVED_28,27,9,1) +__MREG__(MAX2839_RESERVED_27_9,27,9,1) /* REG 28 */ __MREG__(MAX2839_PADAC_Output_Current_Ctrl,28,5,6) @@ -224,17 +224,17 @@ __MREG__(MAX2839_PADAC_TurnOn_Delay_Ctrl,28,9,4) /* REG 29 */ __MREG__(MAX2839_TX_VGA_GAIN,29,5,6) -__MREG__(MAX2839_RESERVED_29,29,9,4) +__MREG__(MAX2839_RESERVED_29_9,29,9,4) /* REG 30 */ __MREG__(MAX2839_TX_DC_Offset_Correction_Addr27,30,5,6) -__MREG__(MAX2839_RESERVED_30,30,7,2) +__MREG__(MAX2839_RESERVED_30_7,30,7,2) __MREG__(MAX2839_PA_DAC_IV_Output_Select,30,8,1) __MREG__(MAX2839_PA_DAC_Voltage_Mode_Output_Select,30,9,1) /* REG 31 */ __MREG__(MAX2839_TX_DC_Offset_Correction_QChannel,31,5,6) -__MREG__(MAX2839_RESERVED_31,31,8,3) +__MREG__(MAX2839_RESERVED_31_8,31,8,3) __MREG__(MAX2839_PA_DAC_Clk_Divide_Ratio,31,9,1) #endif // __MAX2839_REGS_DEF diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 592224b14..ffff68d12 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -371,8 +371,13 @@ void rf_path_init(rf_path_t* const rf_path) max5864_shutdown(&max5864); ssp1_set_mode_max2837(); - max2837_setup(&max2837); - max2837_start(&max2837); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + max2839_setup(&max2839); + max2839_start(&max2839); + } else { + max2837_setup(&max2837); + max2837_start(&max2837); + } // On HackRF One, the mixer is now set up earlier in boot. #ifndef HACKRF_ONE diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index ddc76a19d..b39c86411 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -172,6 +172,8 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/si5351c.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2837.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2837_target.c + ${PATH_HACKRF_FIRMWARE_COMMON}/max2839.c + ${PATH_HACKRF_FIRMWARE_COMMON}/max2839_target.c ${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c ${PATH_HACKRF_FIRMWARE_COMMON}/max5864_target.c ${PATH_HACKRF_FIRMWARE_COMMON}/mixer.c From a72f084ff048f9bc69b19b6375a8a636fff8d4bf Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Mon, 19 Sep 2022 04:58:47 -0400 Subject: [PATCH 10/31] h1r9: fix CLKOUT_EN pin setup --- firmware/common/si5351c.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 09f1ba6a0..a3cb8d3ef 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -366,9 +366,9 @@ void si5351c_init(si5351c_driver_t* const drv) 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); + scu_pinmux(SCU_H1R9_CLKOUT_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + gpio_clear(&gpio_h1r9_clkout_en); + gpio_output(&gpio_h1r9_clkout_en); /* MCU_CLK_EN */ scu_pinmux(SCU_H1R9_MCU_CLK_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); From f4817b60a3ffaf53e6f0573c75db8a7628af534a Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Mon, 19 Sep 2022 07:35:10 -0400 Subject: [PATCH 11/31] h1r9: MAX2839 driver updates --- firmware/common/max2839.c | 78 ++++++++++++++++++++++---------- firmware/common/max2839_regs.def | 33 ++++++++------ 2 files changed, 74 insertions(+), 37 deletions(-) diff --git a/firmware/common/max2839.c b/firmware/common/max2839.c index c21cf93da..10f5461cd 100644 --- a/firmware/common/max2839.c +++ b/firmware/common/max2839.c @@ -36,17 +36,17 @@ /* Default register values. */ static const uint16_t max2839_regs_default[MAX2839_NUM_REGS] = { 0x000, /* 0 */ - 0x00C, /* 1 */ + 0x00c, /* 1: data sheet says 0x00c but read 0x22c */ 0x080, /* 2 */ - 0x1b9, /* 3 */ + 0x1b9, /* 3: data sheet says 0x1b9 but read 0x1b0 */ 0x3e6, /* 4 */ 0x100, /* 5 */ 0x000, /* 6 */ 0x208, /* 7 */ - 0x220, /* 8 */ + 0x220, /* 8: data sheet says 0x220 but read 0x000 */ 0x018, /* 9 */ 0x00c, /* 10 */ - 0x004, /* 11 */ + 0x004, /* 11: data sheet says 0x004 but read 0x000 */ 0x24f, /* 12 */ 0x150, /* 13 */ 0x3c5, /* 14 */ @@ -56,17 +56,24 @@ static const uint16_t max2839_regs_default[MAX2839_NUM_REGS] = { 0x155, /* 18 */ 0x153, /* 19 */ 0x249, /* 20 */ - 0x02d, /* 21 */ + 0x02d, /* 21: data sheet says 0x02d but read 0x13d */ 0x1a9, /* 22 */ 0x24f, /* 23 */ 0x180, /* 24 */ - 0x000, /* 25 */ + 0x000, /* 25: data sheet says 0x000 but read 0x00a */ 0x3c0, /* 26 */ - 0x200, /* 27 */ + 0x200, /* 27: data sheet says 0x200 but read 0x22a */ 0x0c0, /* 28 */ - 0x03f, /* 29 */ - 0x380, /* 30 */ - 0x340}; /* 31 */ + 0x03f, /* 29: data sheet says 0x03f but read 0x07f */ + 0x300, /* 30: data sheet says 0x300 but read 0x398 */ + 0x340}; /* 31: data sheet says 0x340 but read 0x359 */ + +/* + * All of the discrepancies listed above are in fields that either don't matter + * or are undocumented except "set to recommended value". We set them to the + * data sheet defaults even though the inital part we tested started up with + * different settings. + */ /* Set up all registers according to defaults specified in docs. */ static void max2839_init(max2839_driver_t* const drv) @@ -88,7 +95,27 @@ static void max2839_init(max2839_driver_t* const drv) void max2839_setup(max2839_driver_t* const drv) { max2839_init(drv); - // TODO + + /* Use SPI control instead of B0-B7 pins for gain settings. */ + set_MAX2839_LNAgain_SPI(drv, 1); + set_MAX2839_VGAgain_SPI(drv, 1); + set_MAX2839_TX_VGA_Gain_SPI(drv, 1); + + /* enable RXINB */ + set_MAX2839_MIMO_SELECT(drv, 1); + + /* set gains for unused RXINA path to minimum */ + set_MAX2839_LNA1gain(drv, MAX2839_LNA1gain_M32); + set_MAX2839_Rx1_VGAgain(drv, 0x3f); + + //set_MAX2839_TX_VGA_GAIN(drv, 0x18); + + /* maximum RX output common-mode voltage */ + set_MAX2839_RX_VCM(drv, MAX2839_RX_VCM_1_35); + + //FIXME do something with HPFSM/HPC? + //FIXME do something with LPF? + max2839_regs_commit(drv); } @@ -107,9 +134,10 @@ static void max2839_write(max2839_driver_t* const drv, uint8_t r, uint16_t v) uint16_t max2839_reg_read(max2839_driver_t* const drv, uint8_t r) { - if ((drv->regs_dirty >> r) & 0x1) { - drv->regs[r] = max2839_read(drv, r); - }; + // always read actual value from SPI for now + //if ((drv->regs_dirty >> r) & 0x1) { + drv->regs[r] = max2839_read(drv, r); + //}; return drv->regs[r]; } @@ -154,14 +182,16 @@ void max2839_start(max2839_driver_t* const drv) void max2839_tx(max2839_driver_t* const drv) { - set_MAX2839_LPFblock_MODE(drv, MAX2839_ModeCtrl_TxLPF); + // FIXME does this do anything without LPFmode_SPI set? + // do we need it to? + set_MAX2839_LPFmode(drv, MAX2839_LPFmode_TxLPF); max2839_regs_commit(drv); max2839_set_mode(drv, MAX2839_MODE_TX); } void max2839_rx(max2839_driver_t* const drv) { - set_MAX2839_LPFblock_MODE(drv, MAX2839_ModeCtrl_RxLPF); + set_MAX2839_LPFmode(drv, MAX2839_LPFmode_RxLPF); max2839_regs_commit(drv); max2839_set_mode(drv, MAX2839_MODE_RX); } @@ -276,24 +306,24 @@ bool max2839_set_lna_gain(max2839_driver_t* const drv, const uint32_t gain_db) { uint16_t val; switch(gain_db){ case 40: - val = MAX2839_LNA1gain_MAX; + val = MAX2839_LNA2gain_MAX; break; case 32: - val = MAX2839_LNA1gain_M8; + val = MAX2839_LNA2gain_M8; break; case 24: - val = MAX2839_LNA1gain_M16; + // FIXME correct missing settings with VGA adjustment? + case 16: + val = MAX2839_LNA2gain_M16; break; case 8: - val = MAX2839_LNA1gain_M32; - break; case 0: - val = MAX2839_LNA1gain_M32; + val = MAX2839_LNA2gain_M32; break; default: return false; } - set_MAX2839_LNA1gain(drv, val); + set_MAX2839_LNA2gain(drv, val); max2839_reg_commit(drv, 5); return true; } @@ -303,7 +333,7 @@ bool max2839_set_vga_gain(max2839_driver_t* const drv, const uint32_t gain_db) { return false; } - set_MAX2839_Rx1_VGAgain(drv, (63-gain_db)); + set_MAX2839_Rx2_VGAgain(drv, (63-gain_db)); max2839_reg_commit(drv, 5); return true; } diff --git a/firmware/common/max2839_regs.def b/firmware/common/max2839_regs.def index 25ce449ef..c857cdd74 100644 --- a/firmware/common/max2839_regs.def +++ b/firmware/common/max2839_regs.def @@ -37,10 +37,9 @@ __MREG__(MAX2839_LNAband,1,1,2) __MREG__(MAX2839_RESERVED_1_2,1,2,1) __MREG__(MAX2839_MIMO_SELECT,1,3,1) __MREG__(MAX2839_iqerr_trim,1,9,6) -// TODO: D9:D4 but shows only 5 bits for values? -// 0b00000 = +4.0 degree phase error -// 0b01111 = 0.0 -// 0b11111 = -4.0 +// 0b000000 = +4.0 degree phase error +// 0b011111 = 0.0 +// 0b111111 = -4.0 /* REG 2 */ __MREG__(MAX2839_LNAgain_SPI,2,0,1) @@ -80,16 +79,24 @@ __MREG__(MAX2839_LNA1gain,5,1,2) #define MAX2839_LNA1gain_M16 0b010 #define MAX2839_LNA1gain_M32 0b011 __MREG__(MAX2839_Rx1_VGAgain,5,7,6) -__MREG__(MAX2839_LPFblock_MODE,5,9,2) -#define MAX2839_ModeCtrl_RxCalibration 0 -#define MAX2839_ModeCtrl_RxLPF 1 -#define MAX2839_ModeCtrl_TxLPF 2 -#define MAX2839_ModeCtrl_LPFTrim 3 +__MREG__(MAX2839_LPFmode,5,9,2) +#define MAX2839_LPFmode_RxCalibration 0 +#define MAX2839_LPFmode_RxLPF 1 +#define MAX2839_LPFmode_TxLPF 2 +#define MAX2839_LPFmode_LPFTrim 3 /* REG 6 */ -__MREG__(MAX2839_LNA2gain_SPI,6,1,2) +__MREG__(MAX2839_LNA2gain,6,1,2) +#define MAX2839_LNA2gain_MAX 0b000 // Pad in 8dB steps, bits reversed +#define MAX2839_LNA2gain_M8 0b001 +#define MAX2839_LNA2gain_M16 0b010 +#define MAX2839_LNA2gain_M32 0b011 __MREG__(MAX2839_Rx2_VGAgain,6,7,6) -__MREG__(MAX2839_RX_VGAoutput,6,9,2) +__MREG__(MAX2839_RX_VCM,6,9,2) +#define MAX2839_RX_VCM_1_0 0b00 // 1.0 V +#define MAX2839_RX_VCM_1_1 0b01 // 1.1 V +#define MAX2839_RX_VCM_1_2 0b10 // 1.2 V +#define MAX2839_RX_VCM_1_35 0b11 // 1.35 V /* REG 7 */ __MREG__(MAX2839_RESERVED_7_0,7,0,1) @@ -103,7 +110,7 @@ __MREG__(MAX2839_RSSIinput,7,9,1) /* REG 8 */ __MREG__(MAX2839_RESERVED_8_0,8,0,1) __MREG__(MAX2839_VGAgain_SPI,8,1,1) -__MREG__(MAX2839_LPFmode,8,2,1) +__MREG__(MAX2839_LPFmode_SPI,8,2,1) __MREG__(MAX2839_RESERVED_8_9,8,9,7) /* REG 9 */ @@ -214,7 +221,7 @@ __MREG__(MAX2839_VAS_Test_Signal_Select,26,9,4) /* REG 27 */ __MREG__(MAX2839_TX_LO_IQ_Phase_SPI_Adjust_Addr27,27,5,6) __MREG__(MAX2839_TX_LO_IQ_Phase_SPI_Adjust_Enable,27,6,1) -__MREG__(MAX2839_TX_VGA_Gain_SPI_Ctrl_Enable,27,7,1) +__MREG__(MAX2839_TX_VGA_Gain_SPI,27,7,1) __MREG__(MAX2839_TX_DC_Offset_SPI_Adjust_Enable,27,8,1) __MREG__(MAX2839_RESERVED_27_9,27,9,1) From edd0a8081292c252daa9d05bbdbd4b4efb840cc2 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Mon, 19 Sep 2022 09:58:48 -0400 Subject: [PATCH 12/31] h1r9: stop writing MAX2837 registers to MAX2839 --- firmware/common/rf_path.c | 40 ++++++++++++----- firmware/common/tuning.c | 55 +++++++++++++++++------ firmware/hackrf_usb/usb_api_transceiver.c | 38 +++++++++++----- 3 files changed, 95 insertions(+), 38 deletions(-) diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index ffff68d12..44ab69470 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -30,11 +30,11 @@ #include "hackrf_ui.h" #include "gpio_lpc.h" #include "platform_detect.h" - -#include -#include -#include -#include +#include "mixer.h" +#include "max2837.h" +#include "max2839.h" +#include "max5864.h" +#include "sgpio.h" #if (defined JAWBREAKER || defined HACKRF_ONE || defined RAD1O) /* @@ -370,11 +370,12 @@ void rf_path_init(rf_path_t* const rf_path) max5864_setup(&max5864); max5864_shutdown(&max5864); - ssp1_set_mode_max2837(); if (detected_platform() == BOARD_ID_HACKRF1_R9) { + ssp1_set_mode_max2839(); max2839_setup(&max2839); max2839_start(&max2839); } else { + ssp1_set_mode_max2837(); max2837_setup(&max2837); max2837_start(&max2837); } @@ -405,8 +406,13 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d } ssp1_set_mode_max5864(); max5864_tx(&max5864); - ssp1_set_mode_max2837(); - max2837_tx(&max2837); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + ssp1_set_mode_max2839(); + max2839_tx(&max2839); + } else { + ssp1_set_mode_max2837(); + max2837_tx(&max2837); + } sgpio_configure(&sgpio_config, SGPIO_DIRECTION_TX); break; @@ -424,8 +430,13 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d } ssp1_set_mode_max5864(); max5864_rx(&max5864); - ssp1_set_mode_max2837(); - max2837_rx(&max2837); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + ssp1_set_mode_max2839(); + max2839_rx(&max2839); + } else { + ssp1_set_mode_max2837(); + max2837_rx(&max2837); + } sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); break; @@ -440,8 +451,13 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d mixer_disable(&mixer); ssp1_set_mode_max5864(); max5864_standby(&max5864); - ssp1_set_mode_max2837(); - max2837_set_mode(&max2837, MAX2837_MODE_STANDBY); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + ssp1_set_mode_max2839(); + max2839_set_mode(&max2839, MAX2839_MODE_STANDBY); + } else { + ssp1_set_mode_max2837(); + max2837_set_mode(&max2837, MAX2837_MODE_STANDBY); + } sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); break; } diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 79a238c73..597fa3960 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -22,14 +22,14 @@ */ #include "tuning.h" - #include "hackrf_ui.h" - -#include -#include -#include -#include -#include +#include "hackrf_core.h" +#include "mixer.h" +#include "max2837.h" +#include "max2839.h" +#include "sgpio.h" +#include "operacake.h" +#include "platform_detect.h" #define FREQ_ONE_MHZ (1000ULL * 1000) @@ -70,8 +70,15 @@ bool set_freq(const uint64_t freq) success = true; - const max2837_mode_t prior_max2837_mode = max2837_mode(&max2837); - max2837_set_mode(&max2837, MAX2837_MODE_STANDBY); + max2839_mode_t prior_max2839_mode = MAX2839_MODE_STANDBY; + max2837_mode_t prior_max2837_mode = MAX2837_MODE_STANDBY; + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + prior_max2839_mode = max2839_mode(&max2839); + max2839_set_mode(&max2839, MAX2839_MODE_STANDBY); + } else { + prior_max2837_mode = max2837_mode(&max2837); + max2837_set_mode(&max2837, MAX2837_MODE_STANDBY); + } if (freq_mhz < MAX_LP_FREQ_MHZ) { rf_path_set_filter(&rf_path, RF_PATH_FILTER_LOW_PASS); #ifdef RAD1O @@ -83,13 +90,21 @@ bool set_freq(const uint64_t freq) mixer_freq_mhz = (max2837_freq_nominal_hz / FREQ_ONE_MHZ) + freq_mhz; /* Set Freq and read real freq */ real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz); - max2837_set_frequency(&max2837, real_mixer_freq_hz - freq); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + max2839_set_frequency(&max2839, real_mixer_freq_hz - freq); + } else { + max2837_set_frequency(&max2837, real_mixer_freq_hz - freq); + } sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 1); } else if ((freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ)) { rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS); MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz; /* mixer_freq_mhz <= not used in Bypass mode */ - max2837_set_frequency(&max2837, MAX2837_freq_hz); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + max2839_set_frequency(&max2839, MAX2837_freq_hz); + } else { + max2837_set_frequency(&max2837, MAX2837_freq_hz); + } sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0); } else if ((freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz <= MAX_HP_FREQ_MHZ)) { if (freq_mhz < MID1_HP_FREQ_MHZ) { @@ -110,13 +125,21 @@ bool set_freq(const uint64_t freq) mixer_freq_mhz = freq_mhz - (max2837_freq_nominal_hz / FREQ_ONE_MHZ); /* Set Freq and read real freq */ real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz); - max2837_set_frequency(&max2837, freq - real_mixer_freq_hz); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + max2839_set_frequency(&max2839, freq - real_mixer_freq_hz); + } else { + max2837_set_frequency(&max2837, freq - real_mixer_freq_hz); + } sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0); } else { /* Error freq_mhz too high */ success = false; } - max2837_set_mode(&max2837, prior_max2837_mode); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + max2839_set_mode(&max2839, prior_max2839_mode); + } else { + max2837_set_mode(&max2837, prior_max2837_mode); + } if (success) { freq_cache = freq; hackrf_ui()->set_frequency(freq); @@ -147,7 +170,11 @@ bool set_freq_explicit( } rf_path_set_filter(&rf_path, path); - max2837_set_frequency(&max2837, if_freq_hz); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + max2839_set_frequency(&max2839, if_freq_hz); + } else { + max2837_set_frequency(&max2837, if_freq_hz); + } if (lo_freq_hz > if_freq_hz) { sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 1); } else { diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 18a089389..48bbbb946 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -32,12 +32,14 @@ #include "usb_api_cpld.h" // Remove when CPLD update is handled elsewhere -#include -#include -#include -#include -#include -#include +#include "max2837.h" +#include "max2839.h" +#include "rf_path.h" +#include "tuning.h" +#include "streaming.h" +#include "usb.h" +#include "usb_queue.h" +#include "platform_detect.h" #include #include @@ -163,8 +165,12 @@ 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(&max2837, endpoint->setup.index); + uint8_t value; + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + value = max2839_set_lna_gain(&max2839, endpoint->setup.index); + } else { + value = max2837_set_lna_gain(&max2837, endpoint->setup.index); + } endpoint->buffer[0] = value; if (value) { hackrf_ui()->set_bb_lna_gain(endpoint->setup.index); @@ -186,8 +192,12 @@ usb_request_status_t usb_vendor_request_set_vga_gain( const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { - const uint8_t value = - max2837_set_vga_gain(&max2837, endpoint->setup.index); + uint8_t value; + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + value = max2839_set_vga_gain(&max2839, endpoint->setup.index); + } else { + value = max2837_set_vga_gain(&max2837, endpoint->setup.index); + } endpoint->buffer[0] = value; if (value) { hackrf_ui()->set_bb_vga_gain(endpoint->setup.index); @@ -209,8 +219,12 @@ usb_request_status_t usb_vendor_request_set_txvga_gain( const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { - const uint8_t value = - max2837_set_txvga_gain(&max2837, endpoint->setup.index); + uint8_t value; + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + value = max2839_set_txvga_gain(&max2839, endpoint->setup.index); + } else { + value = max2837_set_txvga_gain(&max2837, endpoint->setup.index); + } endpoint->buffer[0] = value; if (value) { hackrf_ui()->set_bb_tx_vga_gain(endpoint->setup.index); From 4db7e8d38a6bb02b6c720aa119c5c9c9b70a6f54 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Mon, 19 Sep 2022 11:54:07 -0400 Subject: [PATCH 13/31] h1r9: more bring-up fixes --- firmware/common/max2839.c | 4 ++-- firmware/common/rf_path.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/firmware/common/max2839.c b/firmware/common/max2839.c index 10f5461cd..26fef0f74 100644 --- a/firmware/common/max2839.c +++ b/firmware/common/max2839.c @@ -324,7 +324,7 @@ bool max2839_set_lna_gain(max2839_driver_t* const drv, const uint32_t gain_db) { return false; } set_MAX2839_LNA2gain(drv, val); - max2839_reg_commit(drv, 5); + max2839_reg_commit(drv, 6); return true; } @@ -334,7 +334,7 @@ bool max2839_set_vga_gain(max2839_driver_t* const drv, const uint32_t gain_db) { } set_MAX2839_Rx2_VGAgain(drv, (63-gain_db)); - max2839_reg_commit(drv, 5); + max2839_reg_commit(drv, 6); return true; } diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 44ab69470..fc04569ef 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -97,7 +97,7 @@ */ #ifdef HACKRF_ONE -static struct gpio_t gpio_h1r9_no_ant_pwr = GPIO(2, 4); //FIXME max2837_tx_enable conflict +static struct gpio_t gpio_h1r9_no_ant_pwr = GPIO(2, 4); #endif #ifdef HACKRF_ONE @@ -282,7 +282,6 @@ void rf_path_pin_setup(rf_path_t* const rf_path) scu_pinmux(SCU_NO_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_RX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_TX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(SCU_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(SCU_NO_TX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_AMP_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); @@ -295,8 +294,10 @@ void rf_path_pin_setup(rf_path_t* const rf_path) gpio_clear(&gpio_h1r9_no_ant_pwr); gpio_output(&gpio_h1r9_no_ant_pwr); } else { + scu_pinmux(SCU_TX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(SCU_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(SCU_NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + gpio_output(rf_path->gpio_tx); } /* Configure RF power supply (VAA) switch */ @@ -319,7 +320,6 @@ void rf_path_pin_setup(rf_path_t* const rf_path) 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); #elif RAD1O From 616705b7e5086c8d9920f356433b78d2c39160cc Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Mon, 19 Sep 2022 22:18:45 -0400 Subject: [PATCH 14/31] h1r9: don't write to outputs in TIMER3 ext. match register Writing to the output bits in the TIMER3 external match register resulted in intermittent failures that varied in likelihood from board to board and from commit to commit for no apparent reason. --- firmware/common/clkin.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/firmware/common/clkin.c b/firmware/common/clkin.c index bef8b8a98..080d02d02 100644 --- a/firmware/common/clkin.c +++ b/firmware/common/clkin.c @@ -52,8 +52,7 @@ void clkin_detect_init(void) timer_set_prescaler(TIMER3, 0); timer_set_mode(TIMER3, TIMER_CTCR_MODE_TIMER); TIMER3_MCR = TIMER_MCR_MR0R; - TIMER3_EMR = TIMER_EMR_EM0 | TIMER_EMR_EM3 | - (TIMER_EMR_EMC_SET << TIMER_EMR_EMC0_SHIFT) | + TIMER3_EMR = (TIMER_EMR_EMC_SET << TIMER_EMR_EMC0_SHIFT) | (TIMER_EMR_EMC_TOGGLE << TIMER_EMR_EMC3_SHIFT); TIMER3_MR3 = MEASUREMENT_CYCLES; TIMER3_MR0 = MEASUREMENT_CYCLES; From 3f7329052417fce303a835af5ad6191522f08087 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sun, 25 Sep 2022 13:26:05 -0400 Subject: [PATCH 15/31] h1r9: configure MAX2839 HPF Without this, the RX baseband gain amplifies a DC offset. --- firmware/common/max2839.c | 8 +++----- firmware/common/max2839_regs.def | 34 ++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/firmware/common/max2839.c b/firmware/common/max2839.c index 26fef0f74..28cf3ff54 100644 --- a/firmware/common/max2839.c +++ b/firmware/common/max2839.c @@ -108,13 +108,11 @@ void max2839_setup(max2839_driver_t* const drv) set_MAX2839_LNA1gain(drv, MAX2839_LNA1gain_M32); set_MAX2839_Rx1_VGAgain(drv, 0x3f); - //set_MAX2839_TX_VGA_GAIN(drv, 0x18); - - /* maximum RX output common-mode voltage */ + /* set maximum RX output common-mode voltage */ set_MAX2839_RX_VCM(drv, MAX2839_RX_VCM_1_35); - //FIXME do something with HPFSM/HPC? - //FIXME do something with LPF? + /* set HPF corner frequency to 1 kHz */ + set_MAX2839_HPC_STOP(drv, MAX2839_STOP_1K); max2839_regs_commit(drv); } diff --git a/firmware/common/max2839_regs.def b/firmware/common/max2839_regs.def index c857cdd74..8cd578cf1 100644 --- a/firmware/common/max2839_regs.def +++ b/firmware/common/max2839_regs.def @@ -131,25 +131,29 @@ __MREG__(MAX2839_RESERVED_10_9,10,9,5) __MREG__(MAX2839_RESERVED_11_9,11,9,10) /* REG 12 */ -__MREG__(MAX2839_RXVGA_10M_RXEN_duration,12,1,2) -__MREG__(MAX2839_RXVGA_10M_B6B7_duration,12,3,2) -__MREG__(MAX2839_RXVGA_600k_RXEN_duration,12,6,3) -__MREG__(MAX2839_RXVGA_600k_B6B7_duration,12,9,3) +__MREG__(MAX2839_HPC_10M_RXEN_duration,12,1,2) +__MREG__(MAX2839_HPC_10M_B6B7_duration,12,3,2) +__MREG__(MAX2839_HPC_600k_RXEN_duration,12,6,3) +__MREG__(MAX2839_HPC_600k_B6B7_duration,12,9,3) /* REG 13 */ -__MREG__(MAX2839_RXVGA_100k_RXEN_duration,13,1,2) -__MREG__(MAX2839_RXVGA_100k_B6B7_duration,13,3,2) -__MREG__(MAX2839_RXVGA_30k_RXEN_duration,13,5,2) -__MREG__(MAX2839_RXVGA_30k_B6B7_duration,13,7,2) -__MREG__(MAX2839_RXVGA_1k_RXEN_duration,13,9,2) +__MREG__(MAX2839_HPC_100k_RXEN_duration,13,1,2) +__MREG__(MAX2839_HPC_100k_B6B7_duration,13,3,2) +__MREG__(MAX2839_HPC_30k_RXEN_duration,13,5,2) +__MREG__(MAX2839_HPC_30k_B6B7_duration,13,7,2) +__MREG__(MAX2839_HPC_1k_RXEN_duration,13,9,2) /* REG 14 */ -__MREG__(MAX2839_RXVGA_1k_B6B7_duration,14,1,2) -__MREG__(MAX2839_RXVGA_HPCa_HPCd_delay,14,3,2) -__MREG__(MAX2839_RXVGA_final_highpass_corner,14,5,2) -__MREG__(MAX2839_RXVGA_highpass_MODE2,14,7,2) -__MREG__(MAX2839_RXVGA_HPFSM_B6B7,14,8,1) -__MREG__(MAX2839_PA_DRV_DAC,14,9,1) +__MREG__(MAX2839_HPC_1k_B6B7_duration,14,1,2) +__MREG__(MAX2839_HPC_DELAY,14,3,2) +__MREG__(MAX2839_HPC_STOP,14,5,2) +#define MAX2839_STOP_100 0 +#define MAX2839_STOP_1K 1 +#define MAX2839_STOP_30K 2 +#define MAX2839_STOP_100K 3 +__MREG__(MAX2839_HPC_STOP_MODE2,14,7,2) +__MREG__(MAX2839_HPC_RXGAIN_EN,14,8,1) +__MREG__(MAX2839_PA_DRV_GATE,14,9,1) /* REG 15 */ __MREG__(MAX2839_RXVGA_HPFSM_Clk_Divider,15,0,1) From ea3b804edfa6f3be61ac03a5d13bc7c96ac6e548 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 27 Sep 2022 14:42:55 -0400 Subject: [PATCH 16/31] h1r9: workaround platform detection problem On the first spin of r9 one of the pins used for platform detection is pulled up to VAA, not VCC, and VAA hasn't been switched on yet at the time of platform detection. This results in r9 being misidentified as OG from time to time. As a temporary workaround until the next board spin, change the platform from OG to r9 if it is detected as OG but has r9 pin straps. --- firmware/common/platform_detect.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/firmware/common/platform_detect.c b/firmware/common/platform_detect.c index ee9b8d543..1cc6f4791 100644 --- a/firmware/common/platform_detect.c +++ b/firmware/common/platform_detect.c @@ -198,6 +198,11 @@ void detect_hardware_platform(void) (adc0_3 == PIN_STRAP_LOW) && (adc0_4 == PIN_STRAP_LOW) && (platform == BOARD_ID_HACKRF1_R9)) { revision = BOARD_REV_HACKRF1_R9; + } else if ( //FIXME temporary + (adc0_3 == PIN_STRAP_LOW) && (adc0_4 == PIN_STRAP_LOW) && + (platform == BOARD_ID_HACKRF1_OG)) { + revision = BOARD_REV_HACKRF1_R9; + platform = BOARD_ID_HACKRF1_R9; } else { revision = BOARD_REV_UNRECOGNIZED; } From 7a0aec00efad374586a641d1c391dac9b48717e4 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 27 Sep 2022 14:45:58 -0400 Subject: [PATCH 17/31] h1r9: fix usb_vendor_request_reset() The bootloader is configured by pin straps on certain pins. We use some of those for other purposes in r9 which causes the bootloader to misbehave if the device is reset from software. By switching these pins from outputs to inputs just before reset this problem is avoided. --- firmware/hackrf_usb/usb_api_board_info.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/firmware/hackrf_usb/usb_api_board_info.c b/firmware/hackrf_usb/usb_api_board_info.c index e6a2b8f25..97f92a992 100644 --- a/firmware/hackrf_usb/usb_api_board_info.c +++ b/firmware/hackrf_usb/usb_api_board_info.c @@ -33,6 +33,13 @@ #include #include +#ifdef HACKRF_ONE + #include "gpio_lpc.h" +static struct gpio_t gpio_h1r9_clkout_en = GPIO(0, 9); +static struct gpio_t gpio_h1r9_mcu_clk_en = GPIO(0, 8); +static struct gpio_t gpio_h1r9_rx = GPIO(0, 7); +#endif + usb_request_status_t usb_vendor_request_read_board_id( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) @@ -123,7 +130,19 @@ usb_request_status_t usb_vendor_request_reset( const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { +#ifdef HACKRF_ONE + /* + * Set boot pins as inputs so that the bootloader reads them + * correctly after the reset. + */ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + gpio_input(&gpio_h1r9_mcu_clk_en); + gpio_input(&gpio_h1r9_clkout_en); + gpio_input(&gpio_h1r9_rx); + } +#endif wwdt_reset(100000); + usb_transfer_schedule_ack(endpoint->in); } return USB_REQUEST_STATUS_OK; From eb8ed45f9a3d99c3091e4a25f8bd40339065f7aa Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Wed, 28 Sep 2022 04:43:39 -0400 Subject: [PATCH 18/31] h1r9: adjust PLLA according to source frequency --- firmware/common/si5351c.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index a3cb8d3ef..0dc483317 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -324,9 +324,20 @@ void si5351c_set_int_mode( void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source) { - if (source != active_clock_source) { - si5351c_configure_clock_control(drv, source); - active_clock_source = source; + if (source == active_clock_source) { + return; + } + si5351c_configure_clock_control(drv, source); + active_clock_source = source; + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + /* 25MHz XTAL * (0x0e00+512)/128 = 800mhz -> int mode */ + uint8_t pll_data[] = {26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00}; + if (source == PLL_SOURCE_CLKIN) { + /* 10MHz CLKIN * (0x2600+512)/128 = 800mhz */ + pll_data[4] = 0x26; + } + si5351c_write(drv, pll_data, sizeof(pll_data)); + si5351c_reset_pll(drv); } } From 5693f7b193c16bdac56d363df17488670b922faa Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sat, 1 Oct 2022 13:20:46 -0400 Subject: [PATCH 19/31] h1r9: MAX2839: support maximum TX gain, not minimum --- firmware/common/max2839.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/firmware/common/max2839.c b/firmware/common/max2839.c index 28cf3ff54..9dbd089b3 100644 --- a/firmware/common/max2839.c +++ b/firmware/common/max2839.c @@ -336,9 +336,10 @@ bool max2839_set_vga_gain(max2839_driver_t* const drv, const uint32_t gain_db) { return true; } -bool max2839_set_txvga_gain(max2839_driver_t* const drv, const uint32_t gain_db) { - uint16_t val=0; - val = 63-gain_db; +bool max2839_set_txvga_gain(max2839_driver_t* const drv, const uint32_t gain_db) +{ + uint16_t val = 0; + val = 47 - gain_db; set_MAX2839_TX_VGA_GAIN(drv, val); max2839_reg_commit(drv, 29); From b15509c2d9e6824ffabe2ceade86c9cf48c2493d Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Mon, 3 Oct 2022 06:08:59 -0400 Subject: [PATCH 20/31] h1r9: MAX2839: emulate MAX2837 RX gain configuration --- firmware/common/max2839.c | 118 ++++++++++++++++++++++++++++++-------- 1 file changed, 93 insertions(+), 25 deletions(-) diff --git a/firmware/common/max2839.c b/firmware/common/max2839.c index 9dbd089b3..23b64629e 100644 --- a/firmware/common/max2839.c +++ b/firmware/common/max2839.c @@ -33,6 +33,9 @@ #include "max2839.h" #include "max2839_regs.def" // private register def macros +static uint8_t requested_lna_gain = 0; +static uint8_t requested_vga_gain = 0; + /* Default register values. */ static const uint16_t max2839_regs_default[MAX2839_NUM_REGS] = { 0x000, /* 0 */ @@ -300,39 +303,104 @@ uint32_t max2839_set_lpf_bandwidth(max2839_driver_t* const drv, const uint32_t b return p->bandwidth_hz; } -bool max2839_set_lna_gain(max2839_driver_t* const drv, const uint32_t gain_db) { +void max2839_configure_rx_gain(max2839_driver_t* const drv) +{ + /* + * restrict requested LNA gain to valid MAX2837 settings: + * 0, 8, 16, 24, 32, or 40 + */ + if (requested_lna_gain > 40) { + requested_lna_gain = 40; + } + requested_lna_gain &= 0x38; + + /* + * restrict requested VGA gain to valid MAX2837 settings: + * even number, 0 through 62 + */ + if (requested_vga_gain > 62) { + requested_vga_gain = 62; + } + requested_vga_gain &= 0x3e; + + /* + * MAX2839 has lower full-scale RX output voltage than MAX2837, so we + * adjust the VGA (baseband) gain to compensate. + */ + uint8_t vga_gain = requested_vga_gain + 3; + uint8_t lna_gain = requested_lna_gain; + + /* + * If that adjustment puts VGA gain out of range, use LNA gain to + * compensate. MAX2839 VGA gain can be any number from 0 through 63. + */ + if (vga_gain > 63) { + if (lna_gain <= 32) { + vga_gain -= 8; + lna_gain += 8; + } else { + vga_gain = 63; + } + } + + /* + * MAX2839 lacks max-24 dB and max-40 dB LNA gain settings, so we use + * VGA gain to compensate. + */ + if (lna_gain == 0) { + lna_gain = 8; + vga_gain = (vga_gain >= 8) ? vga_gain - 8 : 0; + } + if (lna_gain == 16) { + if (vga_gain > 32) { + vga_gain -= 8; + lna_gain += 8; + } else { + vga_gain += 8; + lna_gain -= 8; + } + } + uint16_t val; - switch(gain_db){ - case 40: - val = MAX2839_LNA2gain_MAX; - break; - case 32: - val = MAX2839_LNA2gain_M8; - break; - case 24: - // FIXME correct missing settings with VGA adjustment? - case 16: - val = MAX2839_LNA2gain_M16; - break; - case 8: - case 0: - val = MAX2839_LNA2gain_M32; - break; - default: - return false; + switch (lna_gain) { + case 40: + val = MAX2839_LNA2gain_MAX; + break; + case 32: + val = MAX2839_LNA2gain_M8; + break; + case 24: + case 16: + val = MAX2839_LNA2gain_M16; + break; + case 8: + case 0: + default: + val = MAX2839_LNA2gain_M32; + break; } set_MAX2839_LNA2gain(drv, val); - max2839_reg_commit(drv, 6); - return true; + set_MAX2839_Rx2_VGAgain(drv, (63 - vga_gain)); + max2839_regs_commit(drv); } -bool max2839_set_vga_gain(max2839_driver_t* const drv, const uint32_t gain_db) { - if( (gain_db & 0x1) || gain_db > 62) {/* 0b11111*2 */ +bool max2839_set_lna_gain(max2839_driver_t* const drv, const uint32_t gain_db) +{ + if ((gain_db & 0x7) || gain_db > 40) { return false; + } + requested_lna_gain = gain_db; + max2839_configure_rx_gain(drv); + return true; } - set_MAX2839_Rx2_VGAgain(drv, (63-gain_db)); - max2839_reg_commit(drv, 6); +bool max2839_set_vga_gain(max2839_driver_t* const drv, const uint32_t gain_db) +{ + if ((gain_db & 0x1) || gain_db > 62) { + return false; + } + requested_vga_gain = gain_db; + max2839_configure_rx_gain(drv); return true; } From 7b5d8da8210a566417a8c6d58acd66aca6c2682b Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Mon, 3 Oct 2022 06:26:00 -0400 Subject: [PATCH 21/31] h1r9: swap RX Q inversion --- firmware/common/sgpio.c | 16 +++++++++++----- firmware/common/sgpio.h | 4 +--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index 8fd4a8abf..5c5728fed 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -25,9 +25,10 @@ #include #include -#include +#include "hackrf_core.h" +#include "platform_detect.h" -#include +#include "sgpio.h" #ifdef RAD1O static void update_q_invert(sgpio_config_t* const config); @@ -329,10 +330,15 @@ void sgpio_cpld_stream_rx_set_q_invert( } #else -void sgpio_cpld_stream_rx_set_q_invert( - sgpio_config_t* const config, - const uint_fast8_t invert) +void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, uint_fast8_t invert) { + /* + * The RX IQ channels on HackRF One r9 are not inverted as they are + * on OG or Jawbreaker, so the opposite setting is required. + */ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + invert = (invert > 0) ? 0 : 1; + } gpio_write(config->gpio_rx_q_invert, invert); } #endif diff --git a/firmware/common/sgpio.h b/firmware/common/sgpio.h index a1e10b59b..7779972dc 100644 --- a/firmware/common/sgpio.h +++ b/firmware/common/sgpio.h @@ -49,8 +49,6 @@ 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); -void sgpio_cpld_stream_rx_set_q_invert( - sgpio_config_t* const config, - const uint_fast8_t invert); +void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, uint_fast8_t invert); #endif //__SGPIO_H__ From dc67fbd2eeac38f1aad09068f82dc09187a8f25e Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Mon, 3 Oct 2022 22:00:16 -0400 Subject: [PATCH 22/31] h1r9: fix Opera Cake time mode compatibility TIMER3 match register 3 was interfering with SCT, fixed by turning off all ORing of timer outputs with SCT outputs. --- firmware/common/clkin.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/firmware/common/clkin.c b/firmware/common/clkin.c index 080d02d02..1d8e7511a 100644 --- a/firmware/common/clkin.c +++ b/firmware/common/clkin.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #define CLOCK_CYCLES_1_MS (204000) @@ -56,6 +57,7 @@ void clkin_detect_init(void) (TIMER_EMR_EMC_TOGGLE << TIMER_EMR_EMC3_SHIFT); TIMER3_MR3 = MEASUREMENT_CYCLES; TIMER3_MR0 = MEASUREMENT_CYCLES; + CREG_CREG6 |= CREG_CREG6_CTOUTCTRL; /* Timer0 counts CLKIN */ timer_set_prescaler(TIMER0, 0); From 51bae663fc2c7bfde6c246b49ff07c1aaecd71cf Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Wed, 5 Oct 2022 15:02:53 -0400 Subject: [PATCH 23/31] h1r9: update pin assignments for board spin B --- firmware/common/clkin.c | 51 +++++++++++++++---------------- firmware/common/hackrf_core.c | 43 +++++++++++++++++--------- firmware/common/hackrf_core.h | 16 +++++----- firmware/common/platform_detect.c | 9 ++---- firmware/common/rf_path.c | 8 ++--- firmware/common/sgpio.c | 11 ++++++- 6 files changed, 76 insertions(+), 62 deletions(-) diff --git a/firmware/common/clkin.c b/firmware/common/clkin.c index 1d8e7511a..5ab8123a6 100644 --- a/firmware/common/clkin.c +++ b/firmware/common/clkin.c @@ -49,35 +49,32 @@ tcr_sequence reset; void clkin_detect_init(void) { - /* Timer3 triggers periodic measurement */ - timer_set_prescaler(TIMER3, 0); - timer_set_mode(TIMER3, TIMER_CTCR_MODE_TIMER); - TIMER3_MCR = TIMER_MCR_MR0R; - TIMER3_EMR = (TIMER_EMR_EMC_SET << TIMER_EMR_EMC0_SHIFT) | + /* Timer1 triggers periodic measurement */ + timer_set_prescaler(TIMER1, 0); + timer_set_mode(TIMER1, TIMER_CTCR_MODE_TIMER); + TIMER1_MCR = TIMER_MCR_MR0R; + TIMER1_EMR = (TIMER_EMR_EMC_SET << TIMER_EMR_EMC0_SHIFT) | (TIMER_EMR_EMC_TOGGLE << TIMER_EMR_EMC3_SHIFT); - TIMER3_MR3 = MEASUREMENT_CYCLES; - TIMER3_MR0 = MEASUREMENT_CYCLES; - CREG_CREG6 |= CREG_CREG6_CTOUTCTRL; + TIMER1_MR3 = MEASUREMENT_CYCLES; + TIMER1_MR0 = MEASUREMENT_CYCLES; - /* Timer0 counts CLKIN */ - timer_set_prescaler(TIMER0, 0); - TIMER0_CCR = TIMER_CCR_CAP3RE; - GIMA_CAP0_3_IN = 0x20; // T3_MAT3 + /* prevent TIMER1_MR3 from interfering with SCT */ + CREG_CREG6 |= CREG_CREG6_CTOUTCTRL; - /* measure CLKIN signal on P2_5, pin 91, CTIN_2 */ - TIMER0_CTCR = TIMER_CTCR_MODE_COUNTER_RISING | TIMER_CTCR_CINSEL_CAPN_2; - scu_pinmux(P2_5, SCU_GPIO_PDN | SCU_CONF_FUNCTION1); - GIMA_CAP0_2_IN = 0x00; // CTIN_2 + /* Timer2 counts CLKIN */ + timer_set_prescaler(TIMER2, 0); + TIMER2_CCR = TIMER_CCR_CAP3RE; + GIMA_CAP2_3_IN = 0x20; // T1_MAT3 - // temporarily testing with T0_CAP1, P1_12, pin 56, P28 pin 4 - //TIMER0_CTCR = TIMER_CTCR_MODE_COUNTER_RISING | TIMER_CTCR_CINSEL_CAPN_1; - //scu_pinmux(P1_12, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); - //GIMA_CAP0_1_IN = 0x20; // T0_CAP1 + /* measure CLKIN_DETECT signal on P4_8, pin 15, CTIN_5 */ + TIMER2_CTCR = TIMER_CTCR_MODE_COUNTER_RISING | TIMER_CTCR_CINSEL_CAPN_2; + scu_pinmux(P4_8, SCU_GPIO_PDN | SCU_CONF_FUNCTION1); // CTIN_5 + GIMA_CAP2_2_IN = 0x00; // CTIN_5 reset.first_tcr = TIMER_TCR_CEN | TIMER_TCR_CRST; reset.second_tcr = TIMER_TCR_CEN; timer_dma_lli.src = (uint32_t) & (reset); - timer_dma_lli.dest = (uint32_t) & (TIMER0_TCR); + timer_dma_lli.dest = (uint32_t) & (TIMER2_TCR); timer_dma_lli.next_lli = (uint32_t) & (timer_dma_lli); timer_dma_lli.control = GPDMA_CCONTROL_TRANSFERSIZE(2) | GPDMA_CCONTROL_SBSIZE(0) // 1 @@ -97,19 +94,19 @@ void clkin_detect_init(void) GPDMA_C0DESTADDR = timer_dma_lli.dest; GPDMA_C0LLI = timer_dma_lli.next_lli; GPDMA_C0CONTROL = timer_dma_lli.control; - GPDMA_C0CONFIG = GPDMA_CCONFIG_DESTPERIPHERAL(0x7) // T3_MAT0 + GPDMA_C0CONFIG = GPDMA_CCONFIG_DESTPERIPHERAL(0x3) // T1_MAT0 | GPDMA_CCONFIG_FLOWCNTRL(1) // memory-to-peripheral | GPDMA_CCONFIG_H(0); // do not halt gpdma_channel_enable(0); /* start counting */ - timer_reset(TIMER0); - timer_reset(TIMER3); - timer_enable_counter(TIMER0); - timer_enable_counter(TIMER3); + timer_reset(TIMER2); + timer_reset(TIMER1); + timer_enable_counter(TIMER2); + timer_enable_counter(TIMER1); } uint32_t clkin_frequency(void) { - return TIMER0_CR3 * (1000 / MEASUREMENT_WINDOW_MS); + return TIMER2_CR3 * (1000 / MEASUREMENT_WINDOW_MS); }; diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index a88e1695b..b5acb8928 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -144,9 +144,10 @@ 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); -static struct gpio_t gpio_h1r9_1v8_enable = GPIO(1, 12); +static struct gpio_t gpio_h1r9_rx = GPIO(0, 7); +static struct gpio_t gpio_h1r9_1v8_enable = GPIO(2, 9); +static struct gpio_t gpio_h1r9_vaa_disable = GPIO(3, 6); +static struct gpio_t gpio_h1r9_hw_sync_enable = GPIO(5, 5); #endif // clang-format on @@ -829,10 +830,10 @@ void cpu_clock_init(void) // CCU1_CLK_M4_SCT_CFG = 0; CCU1_CLK_M4_SDIO_CFG = 0; CCU1_CLK_M4_SPIFI_CFG = 0; - //CCU1_CLK_M4_TIMER0_CFG = 0; - CCU1_CLK_M4_TIMER1_CFG = 0; - CCU1_CLK_M4_TIMER2_CFG = 0; - //CCU1_CLK_M4_TIMER3_CFG = 0; + CCU1_CLK_M4_TIMER0_CFG = 0; + //CCU1_CLK_M4_TIMER1_CFG = 0; + //CCU1_CLK_M4_TIMER2_CFG = 0; + CCU1_CLK_M4_TIMER3_CFG = 0; CCU1_CLK_M4_UART1_CFG = 0; CCU1_CLK_M4_USART0_CFG = 0; CCU1_CLK_M4_USART2_CFG = 0; @@ -960,7 +961,7 @@ void pin_setup(void) if (detected_platform() == BOARD_ID_HACKRF1_R9) { #ifdef HACKRF_ONE gpio_output(&gpio_h1r9_1v8_enable); - scu_pinmux(P2_12, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(SCU_H1R9_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); #endif } else { gpio_output(&gpio_1v8_enable); @@ -972,7 +973,11 @@ void pin_setup(void) disable_rf_power(); /* Configure RF power supply (VAA) switch control signal as output */ - gpio_output(&gpio_vaa_disable); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + gpio_output(&gpio_h1r9_vaa_disable); + } else { + gpio_output(&gpio_vaa_disable); + } #endif #ifdef RAD1O @@ -1005,7 +1010,7 @@ void pin_setup(void) #ifdef HACKRF_ONE if (detected_platform() == BOARD_ID_HACKRF1_R9) { rf_path.gpio_rx = &gpio_h1r9_rx; - rf_path.gpio_no_rx_amp_pwr = &gpio_h1r9_no_rx_amp_pwr; + sgpio_config.gpio_hw_sync_enable = &gpio_h1r9_hw_sync_enable; } #endif rf_path_pin_setup(&rf_path); @@ -1045,15 +1050,23 @@ void enable_rf_power(void) /* many short pulses to avoid one big voltage glitch */ for (i = 0; i < 1000; i++) { - gpio_clear(&gpio_vaa_disable); - gpio_set(&gpio_vaa_disable); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + gpio_set(&gpio_h1r9_vaa_disable); + gpio_clear(&gpio_h1r9_vaa_disable); + } else { + gpio_set(&gpio_vaa_disable); + gpio_clear(&gpio_vaa_disable); + } } - gpio_clear(&gpio_vaa_disable); } void disable_rf_power(void) { - gpio_set(&gpio_vaa_disable); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + gpio_set(&gpio_h1r9_vaa_disable); + } else { + gpio_set(&gpio_vaa_disable); + } } #endif @@ -1100,7 +1113,7 @@ void set_leds(const uint8_t state) void hw_sync_enable(const hw_sync_mode_t hw_sync_mode) { - gpio_write(&gpio_hw_sync_enable, hw_sync_mode == 1); + gpio_write(sgpio_config.gpio_hw_sync_enable, hw_sync_mode == 1); } void halt_and_flash(const uint32_t duration) diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 8045b1d26..0bd22da0b 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -109,9 +109,9 @@ extern "C" { #define SCU_PINMUX_SGPIO10 (P1_14) #define SCU_PINMUX_SGPIO11 (P1_17) #define SCU_PINMUX_SGPIO12 (P1_18) -#define SCU_PINMUX_SGPIO13 (P4_8) #define SCU_PINMUX_SGPIO14 (P4_9) #define SCU_PINMUX_SGPIO15 (P4_10) +#define SCU_HW_SYNC_EN (P4_8) /* GPIO5[12] on P4_8 */ /* MAX2837 GPIO (XCVR_CTL) PinMux */ #ifdef RAD1O @@ -234,12 +234,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 */ +#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_ANT_PWR (P4_4) /* GPIO2[4] on P4_4 */ +#define SCU_H1R9_EN1V8 (P5_0) /* GPIO2[9] on P5_0 */ +#define SCU_H1R9_NO_VAA_EN (P6_10) /* GPIO3[6] on P6_10 */ +#define SCU_H1R9_HW_SYNC_EN (P2_5) /* GPIO5[5] on P2_5 */ typedef enum { TRANSCEIVER_MODE_OFF = 0, diff --git a/firmware/common/platform_detect.c b/firmware/common/platform_detect.c index 1cc6f4791..e1608bd8f 100644 --- a/firmware/common/platform_detect.c +++ b/firmware/common/platform_detect.c @@ -42,13 +42,13 @@ static struct gpio_t gpio3_6_on_P6_10 = GPIO(3, 6); * Jawbreaker has a pull-down on P6_10 and nothing on P5_0. * rad1o has a pull-down on P6_10 and a pull-down on P5_0. * HackRF One OG has a pull-down on P6_10 and a pull-up on P5_0. - * HackRF One r9 has a pull-up on P6_10 and a pull-up on P5_0. //FIXME temporary + * HackRF One r9 has a pull-up on P6_10 and a pull-down on P5_0. */ #define JAWBREAKER_RESISTORS (P6_10_PDN) #define RAD1O_RESISTORS (P6_10_PDN | P5_0_PDN) #define HACKRF1_OG_RESISTORS (P6_10_PDN | P5_0_PUP) -#define HACKRF1_R9_RESISTORS (P6_10_PUP | P5_0_PUP) +#define HACKRF1_R9_RESISTORS (P6_10_PUP | P5_0_PDN) /* * LEDs are configured so that they flash if the detected hardware platform is @@ -198,11 +198,6 @@ void detect_hardware_platform(void) (adc0_3 == PIN_STRAP_LOW) && (adc0_4 == PIN_STRAP_LOW) && (platform == BOARD_ID_HACKRF1_R9)) { revision = BOARD_REV_HACKRF1_R9; - } else if ( //FIXME temporary - (adc0_3 == PIN_STRAP_LOW) && (adc0_4 == PIN_STRAP_LOW) && - (platform == BOARD_ID_HACKRF1_OG)) { - revision = BOARD_REV_HACKRF1_R9; - platform = BOARD_ID_HACKRF1_R9; } else { revision = BOARD_REV_UNRECOGNIZED; } diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index fc04569ef..bdc5341e8 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -286,23 +286,21 @@ void rf_path_pin_setup(rf_path_t* const rf_path) 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); + scu_pinmux(SCU_H1R9_NO_VAA_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); } else { scu_pinmux(SCU_TX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(SCU_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu_pinmux(SCU_NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); gpio_output(rf_path->gpio_tx); + scu_pinmux(SCU_NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); } - /* Configure RF power supply (VAA) switch */ - scu_pinmux(SCU_NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - /* * Safe (initial) switch settings turn off both amplifiers and antenna port * power and enable both amp bypass and mixer bypass. diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index 5c5728fed..fe0ddce1d 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -49,10 +49,19 @@ void sgpio_configure_pin_functions(sgpio_config_t* const config) scu_pinmux(SCU_PINMUX_SGPIO10, SCU_GPIO_FAST | SCU_CONF_FUNCTION6); scu_pinmux(SCU_PINMUX_SGPIO11, SCU_GPIO_FAST | SCU_CONF_FUNCTION6); scu_pinmux(SCU_PINMUX_SGPIO12, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); /* GPIO0[13] */ - scu_pinmux(SCU_PINMUX_SGPIO13, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[12] */ scu_pinmux(SCU_PINMUX_SGPIO14, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[13] */ scu_pinmux(SCU_PINMUX_SGPIO15, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[14] */ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + scu_pinmux( + SCU_H1R9_HW_SYNC_EN, + SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[5] */ + } else { + scu_pinmux( + SCU_HW_SYNC_EN, + SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[12] */ + } + sgpio_cpld_stream_rx_set_q_invert(config, 0); hw_sync_enable(0); From 24f2c1d073a5b932ed0b532c0c50a330f0992c07 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sun, 9 Oct 2022 05:58:26 -0400 Subject: [PATCH 24/31] h1r9: MAX2839: always use the low LNA band --- firmware/common/max2839.c | 13 +++++++------ firmware/common/max2839_regs.def | 10 +++++++++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/firmware/common/max2839.c b/firmware/common/max2839.c index 23b64629e..a8c69f8c3 100644 --- a/firmware/common/max2839.c +++ b/firmware/common/max2839.c @@ -117,6 +117,13 @@ void max2839_setup(max2839_driver_t* const drv) /* set HPF corner frequency to 1 kHz */ set_MAX2839_HPC_STOP(drv, MAX2839_STOP_1K); + /* + * There are two LNA band settings, but we only use one of them. + * Switching to the other one doesn't make the overall spectrum any + * flatter but adds a surprise step in the middle. + */ + set_MAX2839_LNAband(drv, MAX2839_LNAband_2_4); + max2839_regs_commit(drv); } @@ -207,7 +214,6 @@ void max2839_stop(max2839_driver_t* const drv) void max2839_set_frequency(max2839_driver_t* const drv, uint32_t freq) { uint8_t band; - uint8_t lna_band; uint32_t div_frac; uint32_t div_int; uint32_t div_rem; @@ -217,16 +223,12 @@ void max2839_set_frequency(max2839_driver_t* const drv, uint32_t freq) /* Select band. Allow tuning outside specified bands. */ if (freq < 2400000000U) { band = MAX2839_LOGEN_BSW_2_3; - lna_band = MAX2839_LNAband_2_4; } else if (freq < 2500000000U) { band = MAX2839_LOGEN_BSW_2_4; - lna_band = MAX2839_LNAband_2_4; } else if (freq < 2600000000U) { band = MAX2839_LOGEN_BSW_2_5; - lna_band = MAX2839_LNAband_2_6; } else { band = MAX2839_LOGEN_BSW_2_6; - lna_band = MAX2839_LNAband_2_6; } /* ASSUME 40MHz PLL. Ratio = F*(4/3)/40,000,000 = F/30,000,000 */ @@ -245,7 +247,6 @@ void max2839_set_frequency(max2839_driver_t* const drv, uint32_t freq) /* Band settings */ set_MAX2839_LOGEN_BSW(drv, band); - set_MAX2839_LNAband(drv, lna_band); /* Write order matters here, so commit INT and FRAC_HI before * committing FRAC_LO, which is the trigger for VCO diff --git a/firmware/common/max2839_regs.def b/firmware/common/max2839_regs.def index 8cd578cf1..bee668468 100644 --- a/firmware/common/max2839_regs.def +++ b/firmware/common/max2839_regs.def @@ -119,7 +119,15 @@ __MREG__(MAX2839_Temperature_Clk_En,9,1,1) __MREG__(MAX2839_RESERVED_9_2,9,2,1) __MREG__(MAX2839_DOUT_Drive_Sel,9,3,1) __MREG__(MAX2839_DOUT_3state_Ctrl,9,4,1) -__MREG__(MAX2839_DOUT_Pin_Sel,9,7,3) +__MREG__(MAX2839_DOUT_SEL,9,7,3) +#define MAX2839_DOUT_SEL_SPI 0 // default, SPI comm +#define MAX2839_DOUT_SEL_PLL_LOCK_DETECT 1 +#define MAX2839_DOUT_SEL_VAS_TEST_OUT 2 +#define MAX2839_DOUT_SEL_HPFSM_TEST_OUT 3 +#define MAX2839_DOUT_SEL_LOGEN_TRIM_OUT 4 +#define MAX2839_DOUT_SEL_RX_FUSE_GASKET 5 +#define MAX2839_DOUT_SEL_TX_FUSE_GASKET 6 +#define MAX2839_DOUT_SEL_ZERO 7 __MREG__(MAX2839_RESERVED_9_9,9,9,2) /* REG 10 */ From bfe882a2fae6af06c27c7601f73125971cf6fc73 Mon Sep 17 00:00:00 2001 From: Mike Walters Date: Tue, 11 Oct 2022 14:58:13 +0100 Subject: [PATCH 25/31] h1r9: add MAX283x abstraction layer --- firmware/common/hackrf_core.c | 31 +-- firmware/common/hackrf_core.h | 2 + firmware/common/max2837.h | 2 +- firmware/common/max2839.h | 6 +- firmware/common/max283x.c | 280 ++++++++++++++++++++++ firmware/common/max283x.h | 104 ++++++++ firmware/common/rf_path.c | 17 +- firmware/common/tuning.c | 41 +--- firmware/hackrf-common.cmake | 1 + firmware/hackrf_usb/usb_api_transceiver.c | 18 +- 10 files changed, 411 insertions(+), 91 deletions(-) create mode 100644 firmware/common/max283x.c create mode 100644 firmware/common/max283x.h diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index b5acb8928..e81b18b4c 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -26,10 +26,7 @@ #include "sgpio.h" #include "si5351c.h" #include "spi_ssp.h" -#include "max2837.h" -#include "max2837_target.h" -#include "max2839.h" -#include "max2839_target.h" +#include "max283x.h" #include "max5864.h" #include "max5864_target.h" #include "w25q80bv.h" @@ -65,9 +62,6 @@ 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); /* MAX5864 SPI chip select (AD_CS) GPIO PinMux */ static struct gpio_t gpio_max5864_select = GPIO(2, 7); @@ -229,22 +223,7 @@ spi_bus_t spi_bus_ssp1 = { .transfer_gather = spi_ssp_transfer_gather, }; -max2837_driver_t max2837 = { - .bus = &spi_bus_ssp1, - .gpio_enable = &gpio_max2837_enable, - .gpio_rx_enable = &gpio_max2837_rx_enable, - .gpio_tx_enable = &gpio_max2837_tx_enable, - .target_init = max2837_target_init, - .set_mode = max2837_target_set_mode, -}; - -max2839_driver_t max2839 = { - .bus = &spi_bus_ssp1, - .gpio_enable = &gpio_max2837_enable, - .gpio_rxtx = &gpio_max2837_rx_enable, - .target_init = max2839_target_init, - .set_mode = max2839_target_set_mode, -}; +max283x_driver_t max283x = {}; max5864_driver_t max5864 = { .bus = &spi_bus_ssp1, @@ -560,11 +539,7 @@ bool sample_rate_set(const uint32_t sample_rate_hz) bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz) { uint32_t bandwidth_hz_real; - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - bandwidth_hz_real = max2839_set_lpf_bandwidth(&max2839, bandwidth_hz); - } else { - bandwidth_hz_real = max2837_set_lpf_bandwidth(&max2837, bandwidth_hz); - } + bandwidth_hz_real = max283x_set_lpf_bandwidth(&max283x, bandwidth_hz); if (bandwidth_hz_real) { hackrf_ui()->set_filter_bw(bandwidth_hz_real); diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 0bd22da0b..5aa08b24c 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -34,6 +34,7 @@ extern "C" { #include "si5351c.h" #include "spi_ssp.h" +#include "max283x.h" #include "max2837.h" #include "max2839.h" #include "max5864.h" @@ -273,6 +274,7 @@ extern const ssp_config_t ssp_config_max2837; extern const ssp_config_t ssp_config_max2839; extern const ssp_config_t ssp_config_max5864; +extern max283x_driver_t max283x; extern max2837_driver_t max2837; extern max2839_driver_t max2839; //FIXME xcvr hal extern max5864_driver_t max5864; diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index 25a78a15d..5f0b00241 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -45,7 +45,7 @@ struct max2837_driver_t; typedef struct max2837_driver_t max2837_driver_t; struct max2837_driver_t { - spi_bus_t* const bus; + spi_bus_t* bus; gpio_t gpio_enable; gpio_t gpio_rx_enable; gpio_t gpio_tx_enable; diff --git a/firmware/common/max2839.h b/firmware/common/max2839.h index dd7e7f3a2..9be7d090b 100644 --- a/firmware/common/max2839.h +++ b/firmware/common/max2839.h @@ -35,19 +35,19 @@ typedef enum { MAX2839_MODE_SHUTDOWN, - MAX2839_MODE_CLKOUT, MAX2839_MODE_STANDBY, - MAX2839_MODE_RX, MAX2839_MODE_TX, + MAX2839_MODE_RX, MAX2839_MODE_RX_CAL, MAX2839_MODE_TX_CAL, + MAX2839_MODE_CLKOUT, } max2839_mode_t; struct max2839_driver_t; typedef struct max2839_driver_t max2839_driver_t; struct max2839_driver_t { - spi_bus_t* const bus; + spi_bus_t* bus; gpio_t gpio_enable; gpio_t gpio_rxtx; void (*target_init)(max2839_driver_t* const drv); diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c new file mode 100644 index 000000000..62f9829d9 --- /dev/null +++ b/firmware/common/max283x.c @@ -0,0 +1,280 @@ +/* + * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012 Will Code + * 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 "max283x.h" + +#include "gpio.h" +#include "gpio_lpc.h" +#include "max2837.h" +#include "max2837_target.h" +#include "max2839.h" +#include "max2839_target.h" +#include "spi_bus.h" + +extern spi_bus_t spi_bus_ssp1; +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); + +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, + .target_init = max2837_target_init, + .set_mode = max2837_target_set_mode, +}; + +max2839_driver_t max2839 = { + .bus = &spi_bus_ssp1, + .gpio_enable = &gpio_max2837_enable, + .gpio_rxtx = &gpio_max2837_rx_enable, + .target_init = max2839_target_init, + .set_mode = max2839_target_set_mode, +}; + +/* Initialize chip. */ +void max283x_setup(max283x_driver_t* const drv, max283x_variant_t type) +{ + drv->type = type; + switch (type) { + case MAX2837_VARIANT: + memcpy(&drv->drv.max2837, &max2837, sizeof(max2837)); + max2837_setup(&drv->drv.max2837); + break; + + case MAX2839_VARIANT: + memcpy(&drv->drv.max2839, &max2839, sizeof(max2839)); + max2839_setup(&drv->drv.max2839); + break; + } +} + +/* Read a register via SPI. Save a copy to memory and return + * value. Mark clean. */ +uint16_t max283x_reg_read(max283x_driver_t* const drv, uint8_t r) +{ + switch (drv->type) { + case MAX2837_VARIANT: + return max2837_reg_read(&drv->drv.max2837, r); + break; + + case MAX2839_VARIANT: + return max2839_reg_read(&drv->drv.max2839, r); + break; + } + + return 0; +} + +/* Write value to register via SPI and save a copy to memory. Mark + * clean. */ +void max283x_reg_write(max283x_driver_t* const drv, uint8_t r, uint16_t v) +{ + switch (drv->type) { + case MAX2837_VARIANT: + max2837_reg_write(&drv->drv.max2837, r, v); + break; + + case MAX2839_VARIANT: + max2839_reg_write(&drv->drv.max2839, r, v); + break; + } +} + +/* 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. */ +void max283x_regs_commit(max283x_driver_t* const drv) +{ + switch (drv->type) { + case MAX2837_VARIANT: + max2837_regs_commit(&drv->drv.max2837); + break; + + case MAX2839_VARIANT: + max2839_regs_commit(&drv->drv.max2839); + break; + } +} + +void max283x_set_mode(max283x_driver_t* const drv, const max283x_mode_t new_mode) +{ + switch (drv->type) { + case MAX2837_VARIANT: + max2837_set_mode(&drv->drv.max2837, (max2837_mode_t) new_mode); + break; + + case MAX2839_VARIANT: + max2839_set_mode(&drv->drv.max2839, (max2839_mode_t) new_mode); + break; + } +} + +max283x_mode_t max283x_mode(max283x_driver_t* const drv) +{ + switch (drv->type) { + case MAX2837_VARIANT: + return (max283x_mode_t) max2837_mode(&drv->drv.max2837); + break; + + case MAX2839_VARIANT: + return (max283x_mode_t) max2839_mode(&drv->drv.max2839); + break; + } + + return 0; +} + +//max283x_mode_t max283x_mode(max283x_driver_t* const drv); +//void max283x_set_mode(max283x_driver_t* const drv, const max283x_mode_t new_mode); + +/* Turn on/off all chip functions. Does not control oscillator and CLKOUT */ +void max283x_start(max283x_driver_t* const drv) +{ + switch (drv->type) { + case MAX2837_VARIANT: + max2837_start(&drv->drv.max2837); + break; + + case MAX2839_VARIANT: + max2839_start(&drv->drv.max2839); + break; + } +} + +void max283x_stop(max283x_driver_t* const drv) +{ + switch (drv->type) { + case MAX2837_VARIANT: + max2837_stop(&drv->drv.max2837); + break; + + case MAX2839_VARIANT: + max2839_stop(&drv->drv.max2839); + break; + } +} + +/* Set frequency in Hz. Frequency setting is a multi-step function + * where order of register writes matters. */ +void max283x_set_frequency(max283x_driver_t* const drv, uint32_t freq) +{ + switch (drv->type) { + case MAX2837_VARIANT: + max2837_set_frequency(&drv->drv.max2837, freq); + break; + + case MAX2839_VARIANT: + max2839_set_frequency(&drv->drv.max2839, freq); + break; + } +} + +uint32_t max283x_set_lpf_bandwidth( + max283x_driver_t* const drv, + const uint32_t bandwidth_hz) +{ + switch (drv->type) { + case MAX2837_VARIANT: + return max2837_set_lpf_bandwidth(&drv->drv.max2837, bandwidth_hz); + break; + + case MAX2839_VARIANT: + return max2839_set_lpf_bandwidth(&drv->drv.max2839, bandwidth_hz); + break; + } + + return 0; +} + +bool max283x_set_lna_gain(max283x_driver_t* const drv, const uint32_t gain_db) +{ + switch (drv->type) { + case MAX2837_VARIANT: + return max2837_set_lna_gain(&drv->drv.max2837, gain_db); + break; + + case MAX2839_VARIANT: + return max2839_set_lna_gain(&drv->drv.max2839, gain_db); + break; + } + + return false; +} + +bool max283x_set_vga_gain(max283x_driver_t* const drv, const uint32_t gain_db) +{ + switch (drv->type) { + case MAX2837_VARIANT: + return max2837_set_vga_gain(&drv->drv.max2837, gain_db); + break; + + case MAX2839_VARIANT: + return max2839_set_vga_gain(&drv->drv.max2839, gain_db); + break; + } + + return false; +} + +bool max283x_set_txvga_gain(max283x_driver_t* const drv, const uint32_t gain_db) +{ + switch (drv->type) { + case MAX2837_VARIANT: + return max2837_set_txvga_gain(&drv->drv.max2837, gain_db); + break; + + case MAX2839_VARIANT: + return max2839_set_txvga_gain(&drv->drv.max2839, gain_db); + break; + } + + return false; +} + +void max283x_tx(max283x_driver_t* const drv) +{ + switch (drv->type) { + case MAX2837_VARIANT: + max2837_tx(&drv->drv.max2837); + break; + + case MAX2839_VARIANT: + max2839_tx(&drv->drv.max2839); + break; + } +} + +void max283x_rx(max283x_driver_t* const drv) +{ + switch (drv->type) { + case MAX2837_VARIANT: + max2837_rx(&drv->drv.max2837); + break; + + case MAX2839_VARIANT: + max2839_rx(&drv->drv.max2839); + break; + } +} diff --git a/firmware/common/max283x.h b/firmware/common/max283x.h new file mode 100644 index 000000000..eaf15a703 --- /dev/null +++ b/firmware/common/max283x.h @@ -0,0 +1,104 @@ +/* + * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012 Will Code + * 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 __MAX283x_H +#define __MAX283x_H + +#include +#include +#include + +#include "gpio.h" +#include "gpio_lpc.h" +#include "max2837.h" +#include "max2837_target.h" +#include "max2839.h" +#include "max2839_target.h" +#include "spi_bus.h" + +typedef enum { + MAX283x_MODE_SHUTDOWN, + MAX283x_MODE_STANDBY, + MAX283x_MODE_TX, + MAX283x_MODE_RX, + MAX283x_MODE_RX_CAL, + MAX283x_MODE_TX_CAL, + MAX283x_MODE_CLKOUT, +} max283x_mode_t; + +typedef enum { + MAX2837_VARIANT, + MAX2839_VARIANT, +} max283x_variant_t; + +typedef struct { + max283x_variant_t type; + + union { + max2837_driver_t max2837; + max2839_driver_t max2839; + } drv; +} max283x_driver_t; + +/* Initialize chip. */ +void max283x_setup(max283x_driver_t* const drv, max283x_variant_t type); + +/* Read a register via SPI. Save a copy to memory and return + * value. Mark clean. */ +uint16_t max283x_reg_read(max283x_driver_t* const drv, uint8_t r); + +/* Write value to register via SPI and save a copy to memory. Mark + * clean. */ +void max283x_reg_write(max283x_driver_t* const drv, uint8_t r, uint16_t v); + +/* Write all dirty registers via SPI from memory. Mark all clean. Some + * operations require registers to be written in a certain order. Use + * provided routines for those operations. */ +void max283x_regs_commit(max283x_driver_t* const drv); + +//max283x_mode_t max283x_mode(max283x_driver_t* const drv); +//void max283x_set_mode(max283x_driver_t* const drv, const max283x_mode_t new_mode); + +max283x_mode_t max283x_mode(max283x_driver_t* const drv); +void max283x_set_mode(max283x_driver_t* const drv, const max283x_mode_t new_mode); + +/* Turn on/off all chip functions. Does not control oscillator and CLKOUT */ +void max283x_start(max283x_driver_t* const drv); +void max283x_stop(max283x_driver_t* const drv); + +/* Set frequency in Hz. Frequency setting is a multi-step function + * where order of register writes matters. */ +void max283x_set_frequency(max283x_driver_t* const drv, uint32_t freq); +uint32_t max283x_set_lpf_bandwidth( + max283x_driver_t* const drv, + const uint32_t bandwidth_hz); + +bool max283x_set_lna_gain(max283x_driver_t* const drv, const uint32_t gain_db); + +bool max283x_set_vga_gain(max283x_driver_t* const drv, const uint32_t gain_db); +bool max283x_set_txvga_gain(max283x_driver_t* const drv, const uint32_t gain_db); + +void max283x_tx(max283x_driver_t* const drv); +void max283x_rx(max283x_driver_t* const drv); + +#endif // __MAX283x_H diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index bdc5341e8..229cfac84 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -31,6 +31,7 @@ #include "gpio_lpc.h" #include "platform_detect.h" #include "mixer.h" +#include "max283x.h" #include "max2837.h" #include "max2839.h" #include "max5864.h" @@ -370,13 +371,12 @@ void rf_path_init(rf_path_t* const rf_path) if (detected_platform() == BOARD_ID_HACKRF1_R9) { ssp1_set_mode_max2839(); - max2839_setup(&max2839); - max2839_start(&max2839); + max283x_setup(&max283x, MAX2839_VARIANT); } else { ssp1_set_mode_max2837(); - max2837_setup(&max2837); - max2837_start(&max2837); + max283x_setup(&max283x, MAX2837_VARIANT); } + max283x_start(&max283x); // On HackRF One, the mixer is now set up earlier in boot. #ifndef HACKRF_ONE @@ -406,11 +406,10 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d max5864_tx(&max5864); if (detected_platform() == BOARD_ID_HACKRF1_R9) { ssp1_set_mode_max2839(); - max2839_tx(&max2839); } else { ssp1_set_mode_max2837(); - max2837_tx(&max2837); } + max283x_tx(&max283x); sgpio_configure(&sgpio_config, SGPIO_DIRECTION_TX); break; @@ -430,11 +429,10 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d max5864_rx(&max5864); if (detected_platform() == BOARD_ID_HACKRF1_R9) { ssp1_set_mode_max2839(); - max2839_rx(&max2839); } else { ssp1_set_mode_max2837(); - max2837_rx(&max2837); } + max283x_rx(&max283x); sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); break; @@ -451,11 +449,10 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d max5864_standby(&max5864); if (detected_platform() == BOARD_ID_HACKRF1_R9) { ssp1_set_mode_max2839(); - max2839_set_mode(&max2839, MAX2839_MODE_STANDBY); } else { ssp1_set_mode_max2837(); - max2837_set_mode(&max2837, MAX2837_MODE_STANDBY); } + max283x_set_mode(&max283x, MAX283x_MODE_STANDBY); sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); break; } diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 597fa3960..ae12c2386 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -70,15 +70,8 @@ bool set_freq(const uint64_t freq) success = true; - max2839_mode_t prior_max2839_mode = MAX2839_MODE_STANDBY; - max2837_mode_t prior_max2837_mode = MAX2837_MODE_STANDBY; - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - prior_max2839_mode = max2839_mode(&max2839); - max2839_set_mode(&max2839, MAX2839_MODE_STANDBY); - } else { - prior_max2837_mode = max2837_mode(&max2837); - max2837_set_mode(&max2837, MAX2837_MODE_STANDBY); - } + max283x_mode_t prior_max283x_mode = max283x_mode(&max283x); + max283x_set_mode(&max283x, MAX283x_MODE_STANDBY); if (freq_mhz < MAX_LP_FREQ_MHZ) { rf_path_set_filter(&rf_path, RF_PATH_FILTER_LOW_PASS); #ifdef RAD1O @@ -90,21 +83,13 @@ bool set_freq(const uint64_t freq) mixer_freq_mhz = (max2837_freq_nominal_hz / FREQ_ONE_MHZ) + freq_mhz; /* Set Freq and read real freq */ real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz); - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - max2839_set_frequency(&max2839, real_mixer_freq_hz - freq); - } else { - max2837_set_frequency(&max2837, real_mixer_freq_hz - freq); - } + max283x_set_frequency(&max283x, real_mixer_freq_hz - freq); sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 1); } else if ((freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ)) { rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS); MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz; /* mixer_freq_mhz <= not used in Bypass mode */ - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - max2839_set_frequency(&max2839, MAX2837_freq_hz); - } else { - max2837_set_frequency(&max2837, MAX2837_freq_hz); - } + max283x_set_frequency(&max283x, MAX2837_freq_hz); sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0); } else if ((freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz <= MAX_HP_FREQ_MHZ)) { if (freq_mhz < MID1_HP_FREQ_MHZ) { @@ -125,21 +110,13 @@ bool set_freq(const uint64_t freq) mixer_freq_mhz = freq_mhz - (max2837_freq_nominal_hz / FREQ_ONE_MHZ); /* Set Freq and read real freq */ real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz); - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - max2839_set_frequency(&max2839, freq - real_mixer_freq_hz); - } else { - max2837_set_frequency(&max2837, freq - real_mixer_freq_hz); - } + max283x_set_frequency(&max283x, freq - real_mixer_freq_hz); sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0); } else { /* Error freq_mhz too high */ success = false; } - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - max2839_set_mode(&max2839, prior_max2839_mode); - } else { - max2837_set_mode(&max2837, prior_max2837_mode); - } + max283x_set_mode(&max283x, prior_max283x_mode); if (success) { freq_cache = freq; hackrf_ui()->set_frequency(freq); @@ -170,11 +147,7 @@ bool set_freq_explicit( } rf_path_set_filter(&rf_path, path); - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - max2839_set_frequency(&max2839, if_freq_hz); - } else { - max2837_set_frequency(&max2837, if_freq_hz); - } + max283x_set_frequency(&max283x, if_freq_hz); if (lo_freq_hz > if_freq_hz) { sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 1); } else { diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index b39c86411..8418e47ee 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -170,6 +170,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}/max283x.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2837.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2837_target.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2839.c diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 48bbbb946..a6cf86cc5 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -166,11 +166,7 @@ usb_request_status_t usb_vendor_request_set_lna_gain( { if (stage == USB_TRANSFER_STAGE_SETUP) { uint8_t value; - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - value = max2839_set_lna_gain(&max2839, endpoint->setup.index); - } else { - value = max2837_set_lna_gain(&max2837, endpoint->setup.index); - } + value = max283x_set_lna_gain(&max283x, endpoint->setup.index); endpoint->buffer[0] = value; if (value) { hackrf_ui()->set_bb_lna_gain(endpoint->setup.index); @@ -193,11 +189,7 @@ usb_request_status_t usb_vendor_request_set_vga_gain( { if (stage == USB_TRANSFER_STAGE_SETUP) { uint8_t value; - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - value = max2839_set_vga_gain(&max2839, endpoint->setup.index); - } else { - value = max2837_set_vga_gain(&max2837, endpoint->setup.index); - } + value = max283x_set_vga_gain(&max283x, endpoint->setup.index); endpoint->buffer[0] = value; if (value) { hackrf_ui()->set_bb_vga_gain(endpoint->setup.index); @@ -220,11 +212,7 @@ usb_request_status_t usb_vendor_request_set_txvga_gain( { if (stage == USB_TRANSFER_STAGE_SETUP) { uint8_t value; - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - value = max2839_set_txvga_gain(&max2839, endpoint->setup.index); - } else { - value = max2837_set_txvga_gain(&max2837, endpoint->setup.index); - } + value = max283x_set_txvga_gain(&max283x, endpoint->setup.index); endpoint->buffer[0] = value; if (value) { hackrf_ui()->set_bb_tx_vga_gain(endpoint->setup.index); From 50a2e9dd56c20f95805ba48f2df5e9ab07b26698 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Mon, 24 Oct 2022 15:09:01 -0400 Subject: [PATCH 26/31] h1r9: update clock drive strength for spin C --- firmware/common/si5351c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 0dc483317..84cfeea71 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -254,10 +254,10 @@ void si5351c_configure_clock_control( if (detected_platform() == BOARD_ID_HACKRF1_R9) { data[1] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC_A | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA); + SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA); data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC_A | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA); + SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA); data[3] = clkout_ctrl; data[4] = SI5351C_CLK_POWERDOWN; data[5] = SI5351C_CLK_POWERDOWN; From bdb6000bb45ea81befc563c83f9314c602c716d2 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 6 Dec 2022 23:41:34 -0500 Subject: [PATCH 27/31] h1r9: fix inverted spectrum on TX Unify and clean up the firmware spectrum inversion handling for all hardware platforms. --- firmware/common/hackrf_core.c | 4 +- firmware/common/sgpio.c | 78 +++++++++++++++-------------------- firmware/common/sgpio.h | 4 +- firmware/common/tuning.c | 10 ++--- 4 files changed, 42 insertions(+), 54 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index e81b18b4c..f40eea29d 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -134,7 +134,7 @@ static struct gpio_t gpio_cpld_pp_tdo = GPIO(1, 8); /* 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); +static struct gpio_t gpio_q_invert = GPIO(0, 13); /* HackRF One r9 */ #ifdef HACKRF_ONE @@ -254,7 +254,7 @@ w25q80bv_driver_t spi_flash = { }; sgpio_config_t sgpio_config = { - .gpio_rx_q_invert = &gpio_rx_q_invert, + .gpio_q_invert = &gpio_q_invert, .gpio_hw_sync_enable = &gpio_hw_sync_enable, .slice_mode_multislice = true, }; diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index fe0ddce1d..ccf7e1626 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -30,9 +30,7 @@ #include "sgpio.h" -#ifdef RAD1O static void update_q_invert(sgpio_config_t* const config); -#endif void sgpio_configure_pin_functions(sgpio_config_t* const config) { @@ -62,10 +60,10 @@ void sgpio_configure_pin_functions(sgpio_config_t* const config) SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[12] */ } - sgpio_cpld_stream_rx_set_q_invert(config, 0); + sgpio_cpld_set_mixer_invert(config, 0); hw_sync_enable(0); - gpio_output(config->gpio_rx_q_invert); + gpio_output(config->gpio_q_invert); gpio_output(config->gpio_hw_sync_enable); } @@ -122,11 +120,9 @@ void sgpio_configure(sgpio_config_t* const config, const sgpio_direction_t direc ; // clang-format on -#ifdef RAD1O /* The data direction might have changed. Check if we need to * adjust the q inversion. */ update_q_invert(config); -#endif // Enable SGPIO pin outputs. const uint_fast16_t sgpio_gpio_data_direction = @@ -294,60 +290,52 @@ bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config) return (SGPIO_GPIO_OUTREG & (1L << 10)) == 0; /* SGPIO10 */ } -#ifdef RAD1O -/* The rad1o hardware has a bug which makes it - * necessary to also switch between the two options based - * on TX or RX mode. +/* + * The spectrum can be inverted by the analog section of the hardware in two + * different ways: + * + * - The front-end mixer can introduce an inversion depending on the frequency + * tuning configuration. * - * We use the state of the pin to determine which way we - * have to go. + * - Routing of the analog baseband signals can introduce an inversion + * depending on the design of the hardware platform and whether we are in RX + * or TX mode. * - * As TX/RX can change without sgpio_cpld_stream_rx_set_q_invert - * being called, we store a local copy of its parameter. */ -static bool sgpio_invert = false; + * When one but not both of the above effects inverts the spectrum, we instruct + * the CPLD to correct the inversion by inverting the Q sample value. + */ +static bool mixer_invert = false; -/* Called when TX/RX changes od sgpio_cpld_stream_rx_set_q_invert - * gets called. */ +/* Called when TX/RX changes or sgpio_cpld_set_mixer_invert() gets called. */ static void update_q_invert(sgpio_config_t* const config) { /* 1=Output SGPIO11 High(TX mode), 0=Output SGPIO11 Low(RX mode) */ bool tx_mode = (SGPIO_GPIO_OUTREG & (1 << 11)) > 0; - /* 0.13: P1_18 */ - if (!sgpio_invert & !tx_mode) { - gpio_write(config->gpio_rx_q_invert, 1); - } else if (!sgpio_invert & tx_mode) { - gpio_write(config->gpio_rx_q_invert, 0); - } else if (sgpio_invert & !tx_mode) { - gpio_write(config->gpio_rx_q_invert, 0); - } else if (sgpio_invert & tx_mode) { - gpio_write(config->gpio_rx_q_invert, 1); + /* + * This switch will need to change if we modify the CPLD to handle + * inversion the same way for RX and TX. + */ + bool baseband_invert = false; + switch (detected_platform()) { + case BOARD_ID_RAD1O: + case BOARD_ID_HACKRF1_R9: + baseband_invert = (tx_mode) ? false : true; + break; + default: + baseband_invert = false; } + + gpio_write(config->gpio_q_invert, mixer_invert ^ baseband_invert); } -void sgpio_cpld_stream_rx_set_q_invert( - sgpio_config_t* const config, - const uint_fast8_t invert) +void sgpio_cpld_set_mixer_invert(sgpio_config_t* const config, const uint_fast8_t invert) { if (invert) { - sgpio_invert = true; + mixer_invert = true; } else { - sgpio_invert = false; + mixer_invert = false; } update_q_invert(config); } - -#else -void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, uint_fast8_t invert) -{ - /* - * The RX IQ channels on HackRF One r9 are not inverted as they are - * on OG or Jawbreaker, so the opposite setting is required. - */ - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - invert = (invert > 0) ? 0 : 1; - } - gpio_write(config->gpio_rx_q_invert, invert); -} -#endif diff --git a/firmware/common/sgpio.h b/firmware/common/sgpio.h index 7779972dc..e41982c52 100644 --- a/firmware/common/sgpio.h +++ b/firmware/common/sgpio.h @@ -36,7 +36,7 @@ typedef enum { } sgpio_direction_t; typedef struct sgpio_config_t { - gpio_t gpio_rx_q_invert; + gpio_t gpio_q_invert; gpio_t gpio_hw_sync_enable; bool slice_mode_multislice; } sgpio_config_t; @@ -49,6 +49,6 @@ 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); -void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, uint_fast8_t invert); +void sgpio_cpld_set_mixer_invert(sgpio_config_t* const config, uint_fast8_t invert); #endif //__SGPIO_H__ diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index ae12c2386..120831c48 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -84,13 +84,13 @@ bool set_freq(const uint64_t freq) /* Set Freq and read real freq */ real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz); max283x_set_frequency(&max283x, real_mixer_freq_hz - freq); - sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 1); + sgpio_cpld_set_mixer_invert(&sgpio_config, 1); } else if ((freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ)) { rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS); MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz; /* mixer_freq_mhz <= not used in Bypass mode */ max283x_set_frequency(&max283x, MAX2837_freq_hz); - sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0); + sgpio_cpld_set_mixer_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) { /* IF is graduated from 2170 MHz to 2740 MHz */ @@ -111,7 +111,7 @@ bool set_freq(const uint64_t freq) /* Set Freq and read real freq */ real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz); max283x_set_frequency(&max283x, freq - real_mixer_freq_hz); - sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0); + sgpio_cpld_set_mixer_invert(&sgpio_config, 0); } else { /* Error freq_mhz too high */ success = false; @@ -149,9 +149,9 @@ bool set_freq_explicit( rf_path_set_filter(&rf_path, path); max283x_set_frequency(&max283x, if_freq_hz); if (lo_freq_hz > if_freq_hz) { - sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 1); + sgpio_cpld_set_mixer_invert(&sgpio_config, 1); } else { - sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0); + sgpio_cpld_set_mixer_invert(&sgpio_config, 0); } if (path != RF_PATH_FILTER_BYPASS) { (void) mixer_set_frequency(&mixer, lo_freq_hz / FREQ_ONE_MHZ); From ff4e1107f358a67b586280295bbe85bba41b090e Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Mon, 12 Dec 2022 07:39:18 -0500 Subject: [PATCH 28/31] h1r9: fix clkout PLL source bug --- firmware/common/max2839.c | 3 ++- firmware/common/max2839.h | 3 ++- firmware/common/si5351c.c | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/firmware/common/max2839.c b/firmware/common/max2839.c index a8c69f8c3..868855d48 100644 --- a/firmware/common/max2839.c +++ b/firmware/common/max2839.c @@ -1,5 +1,6 @@ /* - * Copyright 2012 Will Code? (TODO: Proper attribution) + * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012 Will Code * Copyright 2014 Jared Boone * * This file is part of HackRF. diff --git a/firmware/common/max2839.h b/firmware/common/max2839.h index 9be7d090b..fbffa5b14 100644 --- a/firmware/common/max2839.h +++ b/firmware/common/max2839.h @@ -1,5 +1,6 @@ /* - * Copyright 2012 Will Code? (TODO: Proper attribution) + * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012 Will Code * Copyright 2014 Jared Boone * * This file is part of HackRF. diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 84cfeea71..af8588758 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -208,6 +208,7 @@ void si5351c_configure_clock_control( * 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 { From 8051675c6063a3ab1c221e7b0d23db743b1e92b3 Mon Sep 17 00:00:00 2001 From: Mike Walters Date: Wed, 4 Jan 2023 17:32:42 +0000 Subject: [PATCH 29/31] h1r9: add R9 to supported platforms --- firmware/common/firmware_info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/firmware_info.c b/firmware/common/firmware_info.c index aece61cdf..b64894b1c 100644 --- a/firmware/common/firmware_info.c +++ b/firmware/common/firmware_info.c @@ -30,7 +30,7 @@ #ifdef JAWBREAKER #define SUPPORTED_PLATFORM PLATFORM_JAWBREAKER #elif HACKRF_ONE - #define SUPPORTED_PLATFORM PLATFORM_HACKRF1_OG + #define SUPPORTED_PLATFORM (PLATFORM_HACKRF1_OG | PLATFORM_HACKRF1_R9) #elif RAD1O #define SUPPORTED_PLATFORM PLATFORM_RAD1O #else From c19f85ef24039db812aa59e3d35edc94ea72f257 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sun, 8 Jan 2023 08:21:27 -0500 Subject: [PATCH 30/31] h1r9: use single SSP configuration for MAX283x During r9 hardware development it was thought that the MAX2839 would use a different GPIO pin for chip select, but it ended up being the same pin as is used for MAX2837 on other hardware revisions. This takes the MAX283x abstraction a bit further and fixes a bug with hackrf_debug -m. --- firmware/common/hackrf_core.c | 37 +++++--------------------- firmware/common/hackrf_core.h | 10 ++----- firmware/common/max283x.h | 3 --- firmware/common/rf_path.c | 23 +++------------- firmware/common/ui_rad1o.c | 4 +-- firmware/hackrf_usb/hackrf_usb.c | 4 +-- firmware/hackrf_usb/usb_api_register.c | 12 ++++----- firmware/hackrf_usb/usb_api_register.h | 4 +-- 8 files changed, 25 insertions(+), 72 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index f40eea29d..ee418a776 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -60,8 +60,8 @@ static struct gpio_t gpio_led[] = { // clang-format off 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); +/* MAX283x GPIO (XCVR_CTL) PinMux */ +static struct gpio_t gpio_max283x_select = GPIO(0, 15); /* MAX5864 SPI chip select (AD_CS) GPIO PinMux */ static struct gpio_t gpio_max5864_select = GPIO(2, 7); @@ -172,7 +172,7 @@ si5351c_driver_t clock_gen = { .i2c_address = 0x60, }; -const ssp_config_t ssp_config_max2837 = { +const ssp_config_t ssp_config_max283x = { /* FIXME speed up once everything is working reliably */ /* // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz @@ -183,21 +183,7 @@ const ssp_config_t ssp_config_max2837 = { .data_bits = SSP_DATA_16BITS, .serial_clock_rate = 21, .clock_prescale_rate = 2, - .gpio_select = &gpio_max2837_select, -}; - -const ssp_config_t ssp_config_max2839 = { - /* FIXME speed up once everything is working reliably */ - /* - // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - const uint8_t serial_clock_rate = 32; - const uint8_t clock_prescale_rate = 128; - */ - // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - .data_bits = SSP_DATA_16BITS, - .serial_clock_rate = 21, - .clock_prescale_rate = 2, - .gpio_select = &gpio_max2837_select, + .gpio_select = &gpio_max283x_select, }; const ssp_config_t ssp_config_max5864 = { @@ -868,14 +854,9 @@ clock_source_t activate_best_clock_source(void) return source; } -void ssp1_set_mode_max2837(void) +void ssp1_set_mode_max283x(void) { - spi_bus_start(max2837.bus, &ssp_config_max2837); -} - -void ssp1_set_mode_max2839(void) -{ - spi_bus_start(max2839.bus, &ssp_config_max2839); + spi_bus_start(&spi_bus_ssp1, &ssp_config_max283x); } void ssp1_set_mode_max5864(void) @@ -974,11 +955,7 @@ void pin_setup(void) /* enable input on SCL and SDA pins */ SCU_SFSI2C0 = SCU_I2C0_NOMINAL; - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - spi_bus_start(&spi_bus_ssp1, &ssp_config_max2839); - } else { - spi_bus_start(&spi_bus_ssp1, &ssp_config_max2837); - } + spi_bus_start(&spi_bus_ssp1, &ssp_config_max283x); mixer_bus_setup(&mixer); diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 5aa08b24c..d6211b379 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -35,8 +35,6 @@ extern "C" { #include "spi_ssp.h" #include "max283x.h" -#include "max2837.h" -#include "max2839.h" #include "max5864.h" #include "mixer.h" #include "w25q80bv.h" @@ -270,13 +268,10 @@ void delay_us_at_mhz(uint32_t us, uint32_t mhz); /* TODO: Hide these configurations */ extern si5351c_driver_t clock_gen; extern const ssp_config_t ssp_config_w25q80bv; -extern const ssp_config_t ssp_config_max2837; -extern const ssp_config_t ssp_config_max2839; +extern const ssp_config_t ssp_config_max283x; extern const ssp_config_t ssp_config_max5864; extern max283x_driver_t max283x; -extern max2837_driver_t max2837; -extern max2839_driver_t max2839; //FIXME xcvr hal extern max5864_driver_t max5864; extern mixer_driver_t mixer; extern w25q80bv_driver_t spi_flash; @@ -286,8 +281,7 @@ extern jtag_t jtag_cpld; extern i2c_bus_t i2c0; void cpu_clock_init(void); -void ssp1_set_mode_max2837(void); -void ssp1_set_mode_max2839(void); +void ssp1_set_mode_max283x(void); void ssp1_set_mode_max5864(void); void pin_setup(void); diff --git a/firmware/common/max283x.h b/firmware/common/max283x.h index eaf15a703..06ff64650 100644 --- a/firmware/common/max283x.h +++ b/firmware/common/max283x.h @@ -76,9 +76,6 @@ void max283x_reg_write(max283x_driver_t* const drv, uint8_t r, uint16_t v); * provided routines for those operations. */ void max283x_regs_commit(max283x_driver_t* const drv); -//max283x_mode_t max283x_mode(max283x_driver_t* const drv); -//void max283x_set_mode(max283x_driver_t* const drv, const max283x_mode_t new_mode); - max283x_mode_t max283x_mode(max283x_driver_t* const drv); void max283x_set_mode(max283x_driver_t* const drv, const max283x_mode_t new_mode); diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 229cfac84..ba8ef69ba 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -32,8 +32,6 @@ #include "platform_detect.h" #include "mixer.h" #include "max283x.h" -#include "max2837.h" -#include "max2839.h" #include "max5864.h" #include "sgpio.h" @@ -369,11 +367,10 @@ void rf_path_init(rf_path_t* const rf_path) max5864_setup(&max5864); max5864_shutdown(&max5864); + ssp1_set_mode_max283x(); if (detected_platform() == BOARD_ID_HACKRF1_R9) { - ssp1_set_mode_max2839(); max283x_setup(&max283x, MAX2839_VARIANT); } else { - ssp1_set_mode_max2837(); max283x_setup(&max283x, MAX2837_VARIANT); } max283x_start(&max283x); @@ -404,11 +401,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d } ssp1_set_mode_max5864(); max5864_tx(&max5864); - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - ssp1_set_mode_max2839(); - } else { - ssp1_set_mode_max2837(); - } + ssp1_set_mode_max283x(); max283x_tx(&max283x); sgpio_configure(&sgpio_config, SGPIO_DIRECTION_TX); break; @@ -427,11 +420,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d } ssp1_set_mode_max5864(); max5864_rx(&max5864); - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - ssp1_set_mode_max2839(); - } else { - ssp1_set_mode_max2837(); - } + ssp1_set_mode_max283x(); max283x_rx(&max283x); sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); break; @@ -447,11 +436,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d mixer_disable(&mixer); ssp1_set_mode_max5864(); max5864_standby(&max5864); - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - ssp1_set_mode_max2839(); - } else { - ssp1_set_mode_max2837(); - } + ssp1_set_mode_max283x(); max283x_set_mode(&max283x, MAX283x_MODE_STANDBY); sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); break; diff --git a/firmware/common/ui_rad1o.c b/firmware/common/ui_rad1o.c index 3fc10d3d8..8312c12bd 100644 --- a/firmware/common/ui_rad1o.c +++ b/firmware/common/ui_rad1o.c @@ -202,7 +202,7 @@ static void ui_update(void) rad1o_lcdDisplay(); // Don't ask... - ssp1_set_mode_max2837(); + ssp1_set_mode_max283x(); } static void rad1o_ui_init(void) @@ -217,7 +217,7 @@ static void rad1o_ui_deinit(void) rad1o_lcdDeInit(); enabled = false; // Don't ask... - ssp1_set_mode_max2837(); + ssp1_set_mode_max283x(); } static void rad1o_ui_set_frequency(uint64_t frequency) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 893ecd539..bcf9ba87a 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -66,8 +66,8 @@ extern uint32_t _etext_ram, _text_ram, _etext_rom; static usb_request_handler_fn vendor_request_handler[] = { NULL, usb_vendor_request_set_transceiver_mode, - usb_vendor_request_write_max2837, - usb_vendor_request_read_max2837, + usb_vendor_request_write_max283x, + usb_vendor_request_read_max283x, usb_vendor_request_write_si5351c, usb_vendor_request_read_si5351c, usb_vendor_request_set_sample_rate_frac, diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index 9741fd65c..b3aa241be 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include @@ -33,15 +33,15 @@ #include -usb_request_status_t usb_vendor_request_write_max2837( +usb_request_status_t usb_vendor_request_write_max283x( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { if (endpoint->setup.index < MAX2837_NUM_REGS) { if (endpoint->setup.value < MAX2837_DATA_REGS_MAX_VALUE) { - max2837_reg_write( - &max2837, + max283x_reg_write( + &max283x, endpoint->setup.index, endpoint->setup.value); usb_transfer_schedule_ack(endpoint->in); @@ -54,14 +54,14 @@ usb_request_status_t usb_vendor_request_write_max2837( } } -usb_request_status_t usb_vendor_request_read_max2837( +usb_request_status_t usb_vendor_request_read_max283x( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { if (endpoint->setup.index < MAX2837_NUM_REGS) { const uint16_t value = - max2837_reg_read(&max2837, endpoint->setup.index); + max283x_reg_read(&max283x, endpoint->setup.index); endpoint->buffer[0] = value & 0xff; endpoint->buffer[1] = value >> 8; usb_transfer_schedule_block( diff --git a/firmware/hackrf_usb/usb_api_register.h b/firmware/hackrf_usb/usb_api_register.h index f29ad0505..7f26283a1 100644 --- a/firmware/hackrf_usb/usb_api_register.h +++ b/firmware/hackrf_usb/usb_api_register.h @@ -27,10 +27,10 @@ #include #include -usb_request_status_t usb_vendor_request_write_max2837( +usb_request_status_t usb_vendor_request_write_max283x( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); -usb_request_status_t usb_vendor_request_read_max2837( +usb_request_status_t usb_vendor_request_read_max283x( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_request_status_t usb_vendor_request_write_si5351c( From 3796bc94d88e5d22ffa9d74168fc3c47c7c03fb7 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sun, 8 Jan 2023 08:27:28 -0500 Subject: [PATCH 31/31] h1r9: check firmware running on r9 for r9 support Previously we checked for OG support instead of r9 support because we didn't yet have a way to tag firmware binaries with support for multiple platforms. --- firmware/common/platform_detect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/platform_detect.c b/firmware/common/platform_detect.c index e1608bd8f..5430c5d82 100644 --- a/firmware/common/platform_detect.c +++ b/firmware/common/platform_detect.c @@ -165,7 +165,7 @@ void detect_hardware_platform(void) platform = BOARD_ID_HACKRF1_OG; break; case HACKRF1_R9_RESISTORS: - if (!(supported_platform() & PLATFORM_HACKRF1_OG)) { //FIXME temporary + if (!(supported_platform() & PLATFORM_HACKRF1_R9)) { halt_and_flash(3000000); } platform = BOARD_ID_HACKRF1_R9;