From bdb6000bb45ea81befc563c83f9314c602c716d2 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 6 Dec 2022 23:41:34 -0500 Subject: [PATCH] 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 e81b18b4..f40eea29 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 fe0ddce1..ccf7e162 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: * - * We use the state of the pin to determine which way we - * have to go. + * - The front-end mixer can introduce an inversion depending on the frequency + * tuning configuration. * - * 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; + * - 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. + * + * 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 7779972d..e41982c5 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 ae12c238..120831c4 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);