h1r9: fix inverted spectrum on TX
Unify and clean up the firmware spectrum inversion handling for all hardware platforms.
This commit is contained in:

committed by
Mike Walters

parent
50a2e9dd56
commit
bdb6000bb4
@ -134,7 +134,7 @@ static struct gpio_t gpio_cpld_pp_tdo = GPIO(1, 8);
|
|||||||
|
|
||||||
/* other CPLD interface GPIO pins */
|
/* other CPLD interface GPIO pins */
|
||||||
static struct gpio_t gpio_hw_sync_enable = GPIO(5, 12);
|
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 */
|
/* HackRF One r9 */
|
||||||
#ifdef HACKRF_ONE
|
#ifdef HACKRF_ONE
|
||||||
@ -254,7 +254,7 @@ w25q80bv_driver_t spi_flash = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
sgpio_config_t sgpio_config = {
|
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,
|
.gpio_hw_sync_enable = &gpio_hw_sync_enable,
|
||||||
.slice_mode_multislice = true,
|
.slice_mode_multislice = true,
|
||||||
};
|
};
|
||||||
|
@ -30,9 +30,7 @@
|
|||||||
|
|
||||||
#include "sgpio.h"
|
#include "sgpio.h"
|
||||||
|
|
||||||
#ifdef RAD1O
|
|
||||||
static void update_q_invert(sgpio_config_t* const config);
|
static void update_q_invert(sgpio_config_t* const config);
|
||||||
#endif
|
|
||||||
|
|
||||||
void sgpio_configure_pin_functions(sgpio_config_t* const config)
|
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] */
|
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);
|
hw_sync_enable(0);
|
||||||
|
|
||||||
gpio_output(config->gpio_rx_q_invert);
|
gpio_output(config->gpio_q_invert);
|
||||||
gpio_output(config->gpio_hw_sync_enable);
|
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
|
// clang-format on
|
||||||
|
|
||||||
#ifdef RAD1O
|
|
||||||
/* The data direction might have changed. Check if we need to
|
/* The data direction might have changed. Check if we need to
|
||||||
* adjust the q inversion. */
|
* adjust the q inversion. */
|
||||||
update_q_invert(config);
|
update_q_invert(config);
|
||||||
#endif
|
|
||||||
|
|
||||||
// Enable SGPIO pin outputs.
|
// Enable SGPIO pin outputs.
|
||||||
const uint_fast16_t sgpio_gpio_data_direction =
|
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 */
|
return (SGPIO_GPIO_OUTREG & (1L << 10)) == 0; /* SGPIO10 */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RAD1O
|
/*
|
||||||
/* The rad1o hardware has a bug which makes it
|
* The spectrum can be inverted by the analog section of the hardware in two
|
||||||
* necessary to also switch between the two options based
|
* different ways:
|
||||||
* on TX or RX mode.
|
|
||||||
*
|
*
|
||||||
* We use the state of the pin to determine which way we
|
* - The front-end mixer can introduce an inversion depending on the frequency
|
||||||
* have to go.
|
* tuning configuration.
|
||||||
*
|
*
|
||||||
* As TX/RX can change without sgpio_cpld_stream_rx_set_q_invert
|
* - Routing of the analog baseband signals can introduce an inversion
|
||||||
* being called, we store a local copy of its parameter. */
|
* depending on the design of the hardware platform and whether we are in RX
|
||||||
static bool sgpio_invert = false;
|
* 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
|
/* Called when TX/RX changes or sgpio_cpld_set_mixer_invert() gets called. */
|
||||||
* gets called. */
|
|
||||||
static void update_q_invert(sgpio_config_t* const config)
|
static void update_q_invert(sgpio_config_t* const config)
|
||||||
{
|
{
|
||||||
/* 1=Output SGPIO11 High(TX mode), 0=Output SGPIO11 Low(RX mode) */
|
/* 1=Output SGPIO11 High(TX mode), 0=Output SGPIO11 Low(RX mode) */
|
||||||
bool tx_mode = (SGPIO_GPIO_OUTREG & (1 << 11)) > 0;
|
bool tx_mode = (SGPIO_GPIO_OUTREG & (1 << 11)) > 0;
|
||||||
|
|
||||||
/* 0.13: P1_18 */
|
/*
|
||||||
if (!sgpio_invert & !tx_mode) {
|
* This switch will need to change if we modify the CPLD to handle
|
||||||
gpio_write(config->gpio_rx_q_invert, 1);
|
* inversion the same way for RX and TX.
|
||||||
} else if (!sgpio_invert & tx_mode) {
|
*/
|
||||||
gpio_write(config->gpio_rx_q_invert, 0);
|
bool baseband_invert = false;
|
||||||
} else if (sgpio_invert & !tx_mode) {
|
switch (detected_platform()) {
|
||||||
gpio_write(config->gpio_rx_q_invert, 0);
|
case BOARD_ID_RAD1O:
|
||||||
} else if (sgpio_invert & tx_mode) {
|
case BOARD_ID_HACKRF1_R9:
|
||||||
gpio_write(config->gpio_rx_q_invert, 1);
|
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(
|
void sgpio_cpld_set_mixer_invert(sgpio_config_t* const config, const uint_fast8_t invert)
|
||||||
sgpio_config_t* const config,
|
|
||||||
const uint_fast8_t invert)
|
|
||||||
{
|
{
|
||||||
if (invert) {
|
if (invert) {
|
||||||
sgpio_invert = true;
|
mixer_invert = true;
|
||||||
} else {
|
} else {
|
||||||
sgpio_invert = false;
|
mixer_invert = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_q_invert(config);
|
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
|
|
||||||
|
@ -36,7 +36,7 @@ typedef enum {
|
|||||||
} sgpio_direction_t;
|
} sgpio_direction_t;
|
||||||
|
|
||||||
typedef struct sgpio_config_t {
|
typedef struct sgpio_config_t {
|
||||||
gpio_t gpio_rx_q_invert;
|
gpio_t gpio_q_invert;
|
||||||
gpio_t gpio_hw_sync_enable;
|
gpio_t gpio_hw_sync_enable;
|
||||||
bool slice_mode_multislice;
|
bool slice_mode_multislice;
|
||||||
} sgpio_config_t;
|
} 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);
|
void sgpio_cpld_stream_disable(sgpio_config_t* const config);
|
||||||
bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config);
|
bool sgpio_cpld_stream_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__
|
#endif //__SGPIO_H__
|
||||||
|
@ -84,13 +84,13 @@ bool set_freq(const uint64_t freq)
|
|||||||
/* Set Freq and read real freq */
|
/* Set Freq and read real freq */
|
||||||
real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz);
|
real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz);
|
||||||
max283x_set_frequency(&max283x, real_mixer_freq_hz - freq);
|
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)) {
|
} else if ((freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ)) {
|
||||||
rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS);
|
rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS);
|
||||||
MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz;
|
MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz;
|
||||||
/* mixer_freq_mhz <= not used in Bypass mode */
|
/* mixer_freq_mhz <= not used in Bypass mode */
|
||||||
max283x_set_frequency(&max283x, MAX2837_freq_hz);
|
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)) {
|
} else if ((freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz <= MAX_HP_FREQ_MHZ)) {
|
||||||
if (freq_mhz < MID1_HP_FREQ_MHZ) {
|
if (freq_mhz < MID1_HP_FREQ_MHZ) {
|
||||||
/* IF is graduated from 2170 MHz to 2740 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 */
|
/* Set Freq and read real freq */
|
||||||
real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz);
|
real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz);
|
||||||
max283x_set_frequency(&max283x, freq - real_mixer_freq_hz);
|
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 {
|
} else {
|
||||||
/* Error freq_mhz too high */
|
/* Error freq_mhz too high */
|
||||||
success = false;
|
success = false;
|
||||||
@ -149,9 +149,9 @@ bool set_freq_explicit(
|
|||||||
rf_path_set_filter(&rf_path, path);
|
rf_path_set_filter(&rf_path, path);
|
||||||
max283x_set_frequency(&max283x, if_freq_hz);
|
max283x_set_frequency(&max283x, if_freq_hz);
|
||||||
if (lo_freq_hz > 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 {
|
} 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) {
|
if (path != RF_PATH_FILTER_BYPASS) {
|
||||||
(void) mixer_set_frequency(&mixer, lo_freq_hz / FREQ_ONE_MHZ);
|
(void) mixer_set_frequency(&mixer, lo_freq_hz / FREQ_ONE_MHZ);
|
||||||
|
Reference in New Issue
Block a user