From 980c87417ea741f1d1273966c6e40276b4c7489d Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 30 Dec 2025 18:07:18 -0500 Subject: [PATCH 01/20] Clean up compiler warnings --- firmware/common/tuning.c | 6 +----- firmware/hackrf_usb/usb_api_selftest.c | 2 ++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 7e65af6f..72f54f3d 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -70,16 +70,14 @@ #endif +#ifndef PRALINE static uint32_t max2837_freq_nominal_hz = 2560000000; -uint64_t freq_cache = 100000000; - /* * Set freq/tuning between 0MHz to 7250 MHz (less than 16bits really used) * hz between 0 to 999999 Hz (not checked) * return false on error or true if success. */ -#ifndef PRALINE bool set_freq(const uint64_t freq) { bool success; @@ -137,7 +135,6 @@ bool set_freq(const uint64_t freq) } max283x_set_mode(&max283x, prior_max283x_mode); if (success) { - freq_cache = freq; hackrf_ui()->set_frequency(freq); #ifdef HACKRF_ONE operacake_set_range(freq_mhz); @@ -216,7 +213,6 @@ uint64_t tuning_set_frequency(const tune_config_t* cfg, const uint64_t freq) } max2831_set_mode(&max283x, prior_max2831_mode); - freq_cache = freq; hackrf_ui()->set_frequency(freq); operacake_set_range(freq_mhz); return true; diff --git a/firmware/hackrf_usb/usb_api_selftest.c b/firmware/hackrf_usb/usb_api_selftest.c index 98ee83d5..1bafbe00 100644 --- a/firmware/hackrf_usb/usb_api_selftest.c +++ b/firmware/hackrf_usb/usb_api_selftest.c @@ -53,6 +53,7 @@ void append(char** dest, size_t* capacity, const char* str) } } +#ifdef PRALINE static const char* test_result_to_str(test_result_t result) { switch (result) { @@ -67,6 +68,7 @@ static const char* test_result_to_str(test_result_t result) } return "????"; } +#endif void generate_selftest_report(void) { From f6c23be2d9afc023f12dce7bdb971b161bfd7942 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 30 Dec 2025 11:19:11 -0500 Subject: [PATCH 02/20] Set default MAX2831 RX HPF to 30 kHz The 100 Hz setting that is recommended by the data sheet doesn't seem to work correctly. The other settings would be appropriate only with the extended precision RX gateware. The 600 kHz setting seems like it should be useful with higher sample rates, but it increases LPF roll-off. --- firmware/common/max2831.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/max2831.c b/firmware/common/max2831.c index 15b14bdb..e1619a63 100644 --- a/firmware/common/max2831.c +++ b/firmware/common/max2831.c @@ -83,7 +83,7 @@ void max2831_setup(max2831_driver_t* const drv) //set_MAX2831_TXVGA_GAIN(0x3f); /* maximum gain */ set_MAX2831_TXVGA_GAIN(drv, 0x00); /* minimum gain */ - //set_MAX2831_RX_HPF_SEL(drv, MAX2831_RX_HPF_100_HZ); + set_MAX2831_RX_HPF_SEL(drv, MAX2831_RX_HPF_30_KHZ); set_MAX2831_LNA_GAIN(drv, MAX2831_LNA_GAIN_MAX); /* maximum gain */ set_MAX2831_RXVGA_GAIN(drv, 0x18); From d5361ea523a81fa2b85fcc87d85880495b68944f Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 30 Dec 2025 18:14:28 -0500 Subject: [PATCH 03/20] Don't use doubles in firmware The FPU supports only single-precision floats. --- firmware/common/radio.c | 9 +++++++-- firmware/common/radio.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 30db6872..1bd4af43 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -39,8 +39,13 @@ radio_error_t radio_set_sample_rate( radio_config_t* config = &radio->channel[chan_id].config; - // TODO get the actual tuned frequency from sample_rate_frac_set - sample_rate.hz = (double) sample_rate.num / (double) sample_rate.div; + /* + * Store the sample rate rounded to the nearest Hz for convenience. + */ + if (sample_rate.div == 0) { + return RADIO_ERR_INVALID_PARAM; + } + sample_rate.hz = (sample_rate.num + (sample_rate.div >> 1)) / sample_rate.div; if (config->mode == TRANSCEIVER_MODE_OFF) { config->sample_rate[element] = sample_rate; diff --git a/firmware/common/radio.h b/firmware/common/radio.h index caeca0b3..b6285cfb 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -77,7 +77,7 @@ typedef enum { typedef struct { uint32_t num; uint32_t div; - double hz; + uint32_t hz; } radio_sample_rate_t; typedef struct { From c9c5e1bddd8445526d94715778e54ab686eb5475 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 23 Dec 2025 15:12:36 -0500 Subject: [PATCH 04/20] Enable DC block by default --- firmware/common/fpga.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/firmware/common/fpga.c b/firmware/common/fpga.c index 41c766f6..a3f96216 100644 --- a/firmware/common/fpga.c +++ b/firmware/common/fpga.c @@ -29,7 +29,11 @@ void fpga_init(fpga_driver_t* const drv) { // Standard bitstream default register values. - set_FPGA_STANDARD_CTRL(drv, 0); + set_FPGA_STANDARD_CTRL_DC_BLOCK(drv, true); + set_FPGA_STANDARD_CTRL_QUARTER_SHIFT_EN(drv, false); + set_FPGA_STANDARD_CTRL_QUARTER_SHIFT_UP(drv, false); + set_FPGA_STANDARD_CTRL_PRBS(drv, false); + set_FPGA_STANDARD_CTRL_TRIGGER_EN(drv, false); set_FPGA_STANDARD_TX_CTRL(drv, 0); // TODO support the other bitstreams From 4580824866cde43a7d8d601f40ab7d5107affd92 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 30 Dec 2025 19:42:42 -0500 Subject: [PATCH 05/20] Don't commit to table-based tuning for non-praline --- firmware/common/radio.c | 2 +- firmware/common/tune_config.h | 5 +---- firmware/common/tuning.c | 15 --------------- firmware/common/tuning.h | 4 +++- 4 files changed, 5 insertions(+), 21 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 1bd4af43..5cd95ad3 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -212,7 +212,7 @@ radio_error_t radio_set_frequency( case TRANSCEIVER_MODE_RX_SWEEP: case TRANSCEIVER_MODE_TX: // TODO return if, of components so we can support them in the getter - real_hz = tuning_set_frequency(max283x_tune_config, frequency.hz); + real_hz = set_freq(frequency.hz); break; default: return RADIO_ERR_INVALID_CONFIG; diff --git a/firmware/common/tune_config.h b/firmware/common/tune_config.h index cbbbe431..203473e7 100644 --- a/firmware/common/tune_config.h +++ b/firmware/common/tune_config.h @@ -22,16 +22,13 @@ #ifndef __TUNE_CONFIG_H__ #define __TUNE_CONFIG_H__ +#ifdef PRALINE typedef struct { uint16_t rf_range_end_mhz; uint16_t if_mhz; bool high_lo; } tune_config_t; -#ifndef PRALINE -// TODO maybe one day? -static const tune_config_t max283x_tune_config[] = {}; -#else // clang-format off /* tuning table optimized for TX */ static const tune_config_t max2831_tune_config_tx[] = { diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 72f54f3d..2f1d0cac 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -143,22 +143,7 @@ bool set_freq(const uint64_t freq) return success; } -uint64_t tuning_set_frequency(const tune_config_t* config, const uint64_t frequency_hz) -{ - (void) config; - - bool result = set_freq(frequency_hz); - if (!result) { - return 0; - } - - return frequency_hz; -} #else -bool set_freq(const uint64_t freq) -{ - return tuning_set_frequency(max2831_tune_config_rx_sweep, freq) != 0; -} uint64_t tuning_set_frequency(const tune_config_t* cfg, const uint64_t freq) { diff --git a/firmware/common/tuning.h b/firmware/common/tuning.h index 76bbb5b3..ef62cafb 100644 --- a/firmware/common/tuning.h +++ b/firmware/common/tuning.h @@ -30,12 +30,14 @@ #include #include -bool set_freq(const uint64_t freq); // TODO deprecate +bool set_freq(const uint64_t freq); bool set_freq_explicit( const uint64_t if_freq_hz, const uint64_t lo_freq_hz, const rf_path_filter_t path); +#ifdef PRALINE uint64_t tuning_set_frequency(const tune_config_t* config, const uint64_t frequency_hz); +#endif #endif /*__TUNING_H__*/ From 8e14cf6b0c00586c0982f4f81502e7150dfa3560 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 30 Dec 2025 19:52:05 -0500 Subject: [PATCH 06/20] Make tuning_set_frequency() return type consistent --- firmware/common/radio.c | 15 ++++++--------- firmware/common/tuning.c | 2 +- firmware/common/tuning.h | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 5cd95ad3..dafb6d45 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -205,14 +205,13 @@ radio_error_t radio_set_frequency( } // auto-tune - uint64_t real_hz; + bool ok; #ifndef PRALINE switch (config->mode) { case TRANSCEIVER_MODE_RX: case TRANSCEIVER_MODE_RX_SWEEP: case TRANSCEIVER_MODE_TX: - // TODO return if, of components so we can support them in the getter - real_hz = set_freq(frequency.hz); + ok = set_freq(frequency.hz); break; default: return RADIO_ERR_INVALID_CONFIG; @@ -220,24 +219,22 @@ radio_error_t radio_set_frequency( #else switch (config->mode) { case TRANSCEIVER_MODE_RX: - real_hz = tuning_set_frequency(max2831_tune_config_rx, frequency.hz); + ok = tuning_set_frequency(max2831_tune_config_rx, frequency.hz); break; case TRANSCEIVER_MODE_RX_SWEEP: - real_hz = - tuning_set_frequency(max2831_tune_config_rx_sweep, frequency.hz); + ok = tuning_set_frequency(max2831_tune_config_rx_sweep, frequency.hz); break; case TRANSCEIVER_MODE_TX: - real_hz = tuning_set_frequency(max2831_tune_config_tx, frequency.hz); + ok = tuning_set_frequency(max2831_tune_config_tx, frequency.hz); break; default: return RADIO_ERR_INVALID_CONFIG; } #endif - if (real_hz == 0) { + if (!ok) { return RADIO_ERR_INVALID_PARAM; } - frequency.hz = real_hz; config->frequency[element] = frequency; return RADIO_OK; } diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 2f1d0cac..f9021653 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -145,7 +145,7 @@ bool set_freq(const uint64_t freq) #else -uint64_t tuning_set_frequency(const tune_config_t* cfg, const uint64_t freq) +bool tuning_set_frequency(const tune_config_t* cfg, const uint64_t freq) { bool found; uint64_t mixer_freq_hz; diff --git a/firmware/common/tuning.h b/firmware/common/tuning.h index ef62cafb..189bf7d9 100644 --- a/firmware/common/tuning.h +++ b/firmware/common/tuning.h @@ -37,7 +37,7 @@ bool set_freq_explicit( const rf_path_filter_t path); #ifdef PRALINE -uint64_t tuning_set_frequency(const tune_config_t* config, const uint64_t frequency_hz); +bool tuning_set_frequency(const tune_config_t* config, const uint64_t frequency_hz); #endif #endif /*__TUNING_H__*/ From 0ab032c4fc42342d5b60d822f9ff87dc81a821d9 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 30 Dec 2025 20:10:10 -0500 Subject: [PATCH 07/20] Rename hw_sync to trigger Replace hw_sync_mode_t with bool. --- firmware/common/fpga.c | 4 ++-- firmware/common/fpga.h | 2 +- firmware/common/hackrf_core.c | 16 ++++++++-------- firmware/common/hackrf_core.h | 6 +++--- firmware/common/radio.c | 11 ++++------- firmware/common/radio.h | 15 +++------------ firmware/common/sgpio.c | 8 ++++---- firmware/common/sgpio.h | 2 +- firmware/hackrf_usb/usb_api_transceiver.c | 7 +++---- firmware/hackrf_usb/usb_api_transceiver.h | 1 - 10 files changed, 29 insertions(+), 43 deletions(-) diff --git a/firmware/common/fpga.c b/firmware/common/fpga.c index a3f96216..069d1a09 100644 --- a/firmware/common/fpga.c +++ b/firmware/common/fpga.c @@ -82,10 +82,10 @@ void fpga_regs_commit(fpga_driver_t* const drv) } } -void fpga_set_hw_sync_enable(fpga_driver_t* const drv, const hw_sync_mode_t hw_sync_mode) +void fpga_set_trigger_enable(fpga_driver_t* const drv, const bool enable) { fpga_reg_read(drv, FPGA_STANDARD_CTRL); - set_FPGA_STANDARD_CTRL_TRIGGER_EN(drv, hw_sync_mode == 1); + set_FPGA_STANDARD_CTRL_TRIGGER_EN(drv, enable & 0b1); fpga_regs_commit(drv); } diff --git a/firmware/common/fpga.h b/firmware/common/fpga.h index 84edfcb9..be29b7c8 100644 --- a/firmware/common/fpga.h +++ b/firmware/common/fpga.h @@ -63,7 +63,7 @@ extern void fpga_reg_write(fpga_driver_t* const drv, uint8_t r, uint8_t v); * provided routines for those operations. */ extern void fpga_regs_commit(fpga_driver_t* const drv); -void fpga_set_hw_sync_enable(fpga_driver_t* const drv, const hw_sync_mode_t hw_sync_mode); +void fpga_set_trigger_enable(fpga_driver_t* const drv, const bool enable); void fpga_set_rx_dc_block_enable(fpga_driver_t* const drv, const bool enable); void fpga_set_rx_decimation_ratio(fpga_driver_t* const drv, const uint8_t value); void fpga_set_rx_quarter_shift_mode( diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 5568451f..23868b0f 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -170,7 +170,7 @@ static struct gpio_t gpio_cpld_pp_tdo = GPIO(1, 8); /* other CPLD interface GPIO pins */ #ifndef PRALINE -static struct gpio_t gpio_hw_sync_enable = GPIO(5, 12); +static struct gpio_t gpio_trigger_enable = GPIO(5, 12); #endif static struct gpio_t gpio_q_invert = GPIO(0, 13); @@ -179,7 +179,7 @@ static struct gpio_t gpio_q_invert = GPIO(0, 13); 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); +static struct gpio_t gpio_h1r9_trigger_enable = GPIO(5, 5); #endif #ifdef PRALINE @@ -324,7 +324,7 @@ w25q80bv_driver_t spi_flash = { sgpio_config_t sgpio_config = { .gpio_q_invert = &gpio_q_invert, #ifndef PRALINE - .gpio_hw_sync_enable = &gpio_hw_sync_enable, + .gpio_trigger_enable = &gpio_trigger_enable, #endif .slice_mode_multislice = true, }; @@ -375,7 +375,7 @@ radio_t radio = { .mode = TRANSCEIVER_MODE_OFF, .clock[RADIO_CLOCK_CLKIN] = {.enable = false}, .clock[RADIO_CLOCK_CLKOUT] = {.enable = false}, - .trigger_mode = HW_SYNC_MODE_OFF, + .trigger_enable = false, }, .clock_source = CLOCK_SOURCE_HACKRF, }, @@ -1198,7 +1198,7 @@ void pin_setup(void) #ifdef HACKRF_ONE if (detected_platform() == BOARD_ID_HACKRF1_R9) { rf_path.gpio_rx = &gpio_h1r9_rx; - sgpio_config.gpio_hw_sync_enable = &gpio_h1r9_hw_sync_enable; + sgpio_config.gpio_trigger_enable = &gpio_h1r9_trigger_enable; } #endif @@ -1360,12 +1360,12 @@ void set_leds(const uint8_t state) } } -void hw_sync_enable(const hw_sync_mode_t hw_sync_mode) +void trigger_enable(const bool enable) { #ifndef PRALINE - gpio_write(sgpio_config.gpio_hw_sync_enable, hw_sync_mode == 1); + gpio_write(sgpio_config.gpio_trigger_enable, enable); #else - fpga_set_hw_sync_enable(&fpga, hw_sync_mode); + fpga_set_trigger_enable(&fpga, enable); #endif } diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index b6a9c1b5..301cb7aa 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -179,7 +179,7 @@ extern "C" { #define SCU_PINMUX_SGPIO15_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) #endif -#define SCU_HW_SYNC_EN (P4_8) /* GPIO5[12] on P4_8 */ +#define SCU_TRIGGER_EN (P4_8) /* GPIO5[12] on P4_8 */ /* MAX2837 GPIO (XCVR_CTL) PinMux */ #ifdef RAD1O @@ -387,7 +387,7 @@ extern "C" { #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 */ +#define SCU_H1R9_TRIGGER_EN (P2_5) /* GPIO5[5] on P2_5 */ void delay(uint32_t duration); void delay_us_at_mhz(uint32_t us, uint32_t mhz); @@ -460,7 +460,7 @@ void led_off(const led_t led); void led_toggle(const led_t led); void set_leds(const uint8_t state); -void hw_sync_enable(const hw_sync_mode_t hw_sync_mode); +void trigger_enable(const bool enable); void halt_and_flash(const uint32_t duration); diff --git a/firmware/common/radio.c b/firmware/common/radio.c index dafb6d45..d0cfed70 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -321,20 +321,17 @@ radio_clock_t radio_get_clock( return radio->channel[chan_id].config.clock[element]; } -radio_error_t radio_set_trigger_mode( - radio_t* radio, - radio_chan_id chan_id, - hw_sync_mode_t mode) +radio_error_t radio_set_trigger_enable(radio_t* radio, radio_chan_id chan_id, bool enable) { radio_config_t* config = &radio->channel[chan_id].config; - config->trigger_mode = mode; + config->trigger_enable = enable; return RADIO_OK; } -hw_sync_mode_t radio_get_trigger_mode(radio_t* radio, radio_chan_id chan_id) +bool radio_get_trigger_enable(radio_t* radio, radio_chan_id chan_id) { - return radio->channel[chan_id].config.trigger_mode; + return radio->channel[chan_id].config.trigger_enable; } transceiver_mode_t radio_get_mode(radio_t* radio, radio_chan_id chan_id) diff --git a/firmware/common/radio.h b/firmware/common/radio.h index b6285cfb..83ff6134 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -106,12 +106,6 @@ typedef struct { bool enable; } radio_clock_t; -// legacy type, moved from hackrf_core -typedef enum { - HW_SYNC_MODE_OFF = 0, - HW_SYNC_MODE_ON = 1, -} hw_sync_mode_t; - // legacy type, moved from hackrf_core typedef enum { CLOCK_SOURCE_HACKRF = 0, @@ -158,7 +152,7 @@ typedef struct { radio_clock_t clock[RADIO_CLOCK_COUNT]; // trigger elements - hw_sync_mode_t trigger_mode; + bool trigger_enable; // currently active transceiver mode transceiver_mode_t mode; @@ -245,11 +239,8 @@ radio_clock_t radio_get_clock( radio_chan_id chan_id, radio_clock_id element); -radio_error_t radio_set_trigger_mode( - radio_t* radio, - radio_chan_id chan_id, - hw_sync_mode_t mode); -hw_sync_mode_t radio_get_trigger_mode(radio_t* radio, radio_chan_id chan_id); +radio_error_t radio_set_trigger_enable(radio_t* radio, radio_chan_id chan_id, bool enable); +bool radio_get_trigger_enable(radio_t* radio, radio_chan_id chan_id); transceiver_mode_t radio_get_mode(radio_t* radio, radio_chan_id chan_id); rf_path_direction_t radio_get_direction(radio_t* radio, radio_chan_id chan_id); diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index ea2a0d9f..50b98d77 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -52,11 +52,11 @@ void sgpio_configure_pin_functions(sgpio_config_t* const config) if (detected_platform() == BOARD_ID_HACKRF1_R9) { scu_pinmux( - SCU_H1R9_HW_SYNC_EN, + SCU_H1R9_TRIGGER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[5] */ } else { scu_pinmux( - SCU_HW_SYNC_EN, + SCU_TRIGGER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[12] */ } @@ -64,8 +64,8 @@ void sgpio_configure_pin_functions(sgpio_config_t* const config) gpio_output(config->gpio_q_invert); #ifndef PRALINE - hw_sync_enable(0); - gpio_output(config->gpio_hw_sync_enable); + trigger_enable(false); + gpio_output(config->gpio_trigger_enable); #endif } diff --git a/firmware/common/sgpio.h b/firmware/common/sgpio.h index 6b2773da..0d8e9f0f 100644 --- a/firmware/common/sgpio.h +++ b/firmware/common/sgpio.h @@ -38,7 +38,7 @@ typedef enum { typedef struct sgpio_config_t { gpio_t gpio_q_invert; #ifndef PRALINE - gpio_t gpio_hw_sync_enable; + gpio_t gpio_trigger_enable; #endif bool slice_mode_multislice; } sgpio_config_t; diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 0858a6ff..cbc8e293 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -376,8 +376,7 @@ void transceiver_startup(const transceiver_mode_t mode) } activate_best_clock_source(); - hw_sync_mode_t trigger_mode = radio_get_trigger_mode(&radio, RADIO_CHANNEL0); - hw_sync_enable(trigger_mode); + trigger_enable(radio_get_trigger_enable(&radio, RADIO_CHANNEL0)); } usb_request_status_t usb_vendor_request_set_transceiver_mode( @@ -407,10 +406,10 @@ usb_request_status_t usb_vendor_request_set_hw_sync_mode( const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { - radio_error_t result = radio_set_trigger_mode( + radio_error_t result = radio_set_trigger_enable( &radio, RADIO_CHANNEL0, - endpoint->setup.value); + endpoint->setup.value != 0); if (result == RADIO_OK) { usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; diff --git a/firmware/hackrf_usb/usb_api_transceiver.h b/firmware/hackrf_usb/usb_api_transceiver.h index 9fb54c2e..e06d6c16 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.h +++ b/firmware/hackrf_usb/usb_api_transceiver.h @@ -35,7 +35,6 @@ typedef struct { extern volatile transceiver_request_t transceiver_request; -void set_hw_sync_mode(const hw_sync_mode_t new_hw_sync_mode); usb_request_status_t usb_vendor_request_set_transceiver_mode( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); From df6543073b849e563d82939cfec0f430093516aa Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 30 Dec 2025 16:28:05 -0500 Subject: [PATCH 08/20] Add HackRF Pro to firmware/README --- firmware/README | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/firmware/README b/firmware/README index 8235e816..50a9e45e 100644 --- a/firmware/README +++ b/firmware/README @@ -28,6 +28,7 @@ $ cmake .. $ make $ hackrf_spiflash -w hackrf_usb.bin +If you have a HackRF Pro, add -DBOARD=PRALINE to the cmake command. If you have a Jawbreaker, add -DBOARD=JAWBREAKER to the cmake command. If you have a rad1o, use -DBOARD=RAD1O instead. @@ -48,9 +49,9 @@ For loading firmware into RAM with DFU you will need: http://dfu-util.sourceforge.net/ -To start up HackRF One in DFU mode, hold down the DFU button while powering it -on or while pressing and releasing the RESET button. Release the DFU button -after the 3V3 LED illuminates. +To start up HackRF One or HackRF Pro in DFU mode, hold down the DFU button +while powering it on or while pressing and releasing the RESET button. Release +the DFU button after the 3V3 LED illuminates. A .dfu file is built by default when building firmware. Alternatively you can use a known good .dfu file from a release package. Load the firmware into RAM From 10e8b0d9344b90a3244766e178bb7daaa19a5962 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 30 Dec 2025 20:35:25 -0500 Subject: [PATCH 09/20] Decimate automatically in RX and RX sweep modes --- firmware/common/hackrf_core.c | 3 +++ firmware/common/radio.c | 29 +++++++++++++++++++++++++++++ firmware/common/radio.h | 6 ++++++ 3 files changed, 38 insertions(+) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 23868b0f..fdaecf2b 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -376,6 +376,9 @@ radio_t radio = { .clock[RADIO_CLOCK_CLKIN] = {.enable = false}, .clock[RADIO_CLOCK_CLKOUT] = {.enable = false}, .trigger_enable = false, +#ifdef PRALINE + .resampling_n = 0, +#endif }, .clock_source = CLOCK_SOURCE_HACKRF, }, diff --git a/firmware/common/radio.c b/firmware/common/radio.c index d0cfed70..5f323a13 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -52,7 +52,36 @@ radio_error_t radio_set_sample_rate( return RADIO_OK; } +#ifdef PRALINE + #define MAX_AFE_RATE 40000000 + #define MAX_N 5 + uint8_t n = 0; // resampling ratio is 2**n + if ((config->mode == TRANSCEIVER_MODE_RX) || + (config->mode == TRANSCEIVER_MODE_RX_SWEEP)) { + n = 1; + uint32_t afe_rate_x2 = 2 * sample_rate.hz; + while ((afe_rate_x2 <= MAX_AFE_RATE) && (n < MAX_N)) { + afe_rate_x2 <<= 1; + n++; + } + fpga_set_rx_decimation_ratio(&fpga, n); + } + config->resampling_n = n; + bool ok = sample_rate_frac_set(sample_rate.num << n, sample_rate.div); + if (ok) { + config->sample_rate[element] = sample_rate; + radio_channel_t* channel = &radio->channel[chan_id]; + radio_frequency_t frequency = + radio_get_frequency(radio, channel->id, RADIO_FREQUENCY_RF); + ok = radio_set_frequency( + radio, + channel->id, + RADIO_FREQUENCY_RF, + frequency); + } +#else bool ok = sample_rate_frac_set(sample_rate.num, sample_rate.div); +#endif if (!ok) { return RADIO_ERR_INVALID_PARAM; } diff --git a/firmware/common/radio.h b/firmware/common/radio.h index 83ff6134..2b054bd2 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -156,6 +156,12 @@ typedef struct { // currently active transceiver mode transceiver_mode_t mode; + +#ifdef PRALINE + // resampling ratio is 2**n + uint8_t resampling_n; +#endif + } radio_config_t; typedef struct radio_channel_t { From 7e1c17593d9d19ccb271b0e0df0d5cbcddbff6b5 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 30 Dec 2025 21:42:01 -0500 Subject: [PATCH 10/20] Move tuning config search to radio_set_frequency() --- firmware/common/radio.c | 20 +++++++++++++++++--- firmware/common/tuning.c | 15 --------------- firmware/common/tuning.h | 2 ++ 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 5f323a13..ed09ad25 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -246,19 +246,33 @@ radio_error_t radio_set_frequency( return RADIO_ERR_INVALID_CONFIG; } #else + const tune_config_t* tune_config; switch (config->mode) { case TRANSCEIVER_MODE_RX: - ok = tuning_set_frequency(max2831_tune_config_rx, frequency.hz); + tune_config = max2831_tune_config_rx; break; case TRANSCEIVER_MODE_RX_SWEEP: - ok = tuning_set_frequency(max2831_tune_config_rx_sweep, frequency.hz); + tune_config = max2831_tune_config_rx_sweep; break; case TRANSCEIVER_MODE_TX: - ok = tuning_set_frequency(max2831_tune_config_tx, frequency.hz); + tune_config = max2831_tune_config_tx; break; default: return RADIO_ERR_INVALID_CONFIG; } + bool found = false; + for (; (tune_config->rf_range_end_mhz != 0) || (tune_config->if_mhz != 0); + tune_config++) { + if (tune_config->rf_range_end_mhz > (frequency.hz / FREQ_ONE_MHZ)) { + found = true; + break; + } + } + if (!found) { + return RADIO_ERR_INVALID_PARAM; + } + + ok = tuning_set_frequency(tune_config, frequency.hz); #endif if (!ok) { return RADIO_ERR_INVALID_PARAM; diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index f9021653..fa11a6fc 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -32,8 +32,6 @@ #include "operacake.h" #include "platform_detect.h" -#define FREQ_ONE_MHZ (1000ULL * 1000) - #ifndef PRALINE #define MIN_LP_FREQ_MHZ (0) @@ -147,7 +145,6 @@ bool set_freq(const uint64_t freq) bool tuning_set_frequency(const tune_config_t* cfg, const uint64_t freq) { - bool found; uint64_t mixer_freq_hz; uint64_t real_mixer_freq_hz; @@ -157,18 +154,6 @@ bool tuning_set_frequency(const tune_config_t* cfg, const uint64_t freq) const uint16_t freq_mhz = freq / FREQ_ONE_MHZ; - found = false; - for (; cfg->rf_range_end_mhz != 0; cfg++) { - if (cfg->rf_range_end_mhz > freq_mhz) { - found = true; - break; - } - } - - if (!found) { - return false; - } - max2831_mode_t prior_max2831_mode = max2831_mode(&max283x); max2831_set_mode(&max283x, MAX2831_MODE_STANDBY); diff --git a/firmware/common/tuning.h b/firmware/common/tuning.h index 189bf7d9..1d521f84 100644 --- a/firmware/common/tuning.h +++ b/firmware/common/tuning.h @@ -30,6 +30,8 @@ #include #include +#define FREQ_ONE_MHZ (1000ULL * 1000) + bool set_freq(const uint64_t freq); bool set_freq_explicit( const uint64_t if_freq_hz, From fc4b9aca683f0fc733b368be732649d99ba1c252 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 30 Dec 2025 21:34:03 -0500 Subject: [PATCH 11/20] Implement automatic offset tuning Add RX tuning table --- firmware/common/fpga.h | 2 +- firmware/common/radio.c | 13 +- firmware/common/tune_config.h | 507 ++++++++++++++++++++++------------ firmware/common/tuning.c | 30 +- firmware/common/tuning.h | 5 +- 5 files changed, 372 insertions(+), 185 deletions(-) diff --git a/firmware/common/fpga.h b/firmware/common/fpga.h index be29b7c8..fb4270a8 100644 --- a/firmware/common/fpga.h +++ b/firmware/common/fpga.h @@ -23,7 +23,7 @@ #define __FPGA_H #include -#include "hackrf_core.h" +#include "ice40_spi.h" /* Up to 6 registers, each containing up to 8 bits of data */ #define FPGA_NUM_REGS 6 diff --git a/firmware/common/radio.c b/firmware/common/radio.c index ed09ad25..e23902a1 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -225,6 +225,13 @@ radio_error_t radio_set_frequency( frequency.if_hz, frequency.lo_hz, frequency.path); +#ifdef PRALINE + if (ok) { + fpga_set_rx_quarter_shift_mode( + &fpga, + FPGA_QUARTER_SHIFT_MODE_NONE); + } +#endif if (!ok) { return RADIO_ERR_INVALID_PARAM; } @@ -272,7 +279,11 @@ radio_error_t radio_set_frequency( return RADIO_ERR_INVALID_PARAM; } - ok = tuning_set_frequency(tune_config, frequency.hz); + fpga_set_rx_quarter_shift_mode(&fpga, tune_config->shift); + uint32_t offset = (config->sample_rate[RADIO_SAMPLE_RATE_CLOCKGEN].hz + << config->resampling_n) / + 8; + ok = tuning_set_frequency(tune_config, frequency.hz, offset); #endif if (!ok) { return RADIO_ERR_INVALID_PARAM; diff --git a/firmware/common/tune_config.h b/firmware/common/tune_config.h index 203473e7..c24cc3a5 100644 --- a/firmware/common/tune_config.h +++ b/firmware/common/tune_config.h @@ -23,195 +23,354 @@ #define __TUNE_CONFIG_H__ #ifdef PRALINE + #include "fpga.h" + typedef struct { uint16_t rf_range_end_mhz; uint16_t if_mhz; bool high_lo; + fpga_quarter_shift_mode_t shift; } tune_config_t; // clang-format off /* tuning table optimized for TX */ static const tune_config_t max2831_tune_config_tx[] = { - { 2100, 2375, true }, - { 2175, 2325, false }, - { 2320, 2525, false }, - { 2580, 0, false }, - { 3000, 2325, false }, - { 3100, 2375, false }, - { 3200, 2425, false }, - { 3350, 2375, false }, - { 3500, 2475, false }, - { 3550, 2425, false }, - { 3650, 2325, false }, - { 3700, 2375, false }, - { 3850, 2425, false }, - { 3925, 2375, false }, - { 4600, 2325, false }, - { 4700, 2375, false }, - { 4800, 2425, false }, - { 5100, 2375, false }, - { 5850, 2525, false }, - { 6500, 2325, false }, - { 6750, 2375, false }, - { 6850, 2425, false }, - { 6950, 2475, false }, - { 7000, 2525, false }, - { 7251, 2575, false }, - { 0, 0, false }, + { 2100, 2375, true, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2175, 2325, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2320, 2525, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2580, 0, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3000, 2325, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3100, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3200, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3350, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3500, 2475, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3550, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3650, 2325, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3700, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3850, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3925, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4600, 2325, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4700, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4800, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5100, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5850, 2525, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 6500, 2325, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 6750, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 6850, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 6950, 2475, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 7000, 2525, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 7251, 2575, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 0, 0, false, 0 }, }; /* tuning table optimized for 20 Msps interleaved RX sweep mode */ static const tune_config_t max2831_tune_config_rx_sweep[] = { - { 140, 2330, false }, - { 424, 2570, true }, - { 557, 2520, true }, - { 593, 2380, true }, - { 776, 2360, true }, - { 846, 2570, true }, - { 926, 2500, true }, - { 1055, 2380, true }, - { 1175, 2360, true }, - { 1391, 2340, true }, - { 1529, 2570, true }, - { 1671, 2520, true }, - { 1979, 2380, true }, - { 2150, 2330, true }, - { 2160, 2550, false }, - { 2170, 2560, false }, - { 2179, 2570, false }, - { 2184, 2520, false }, - { 2187, 2560, false }, - { 2194, 2530, false }, - { 2203, 2540, false }, - { 2212, 2550, false }, - { 2222, 2560, false }, - { 2231, 2570, false }, - { 2233, 2530, false }, - { 2237, 2520, false }, - { 2241, 2550, false }, - { 2245, 2570, false }, - { 2250, 2560, false }, - { 2252, 2550, false }, - { 2258, 2570, false }, - { 2261, 2560, false }, - { 2266, 2540, false }, - { 2271, 2570, false }, - { 2275, 2550, false }, - { 2280, 2500, false }, - { 2284, 2560, false }, - { 2285, 2530, false }, - { 2289, 2510, false }, - { 2293, 2570, false }, - { 2294, 2540, false }, - { 2298, 2520, false }, - { 2301, 2570, false }, - { 2302, 2550, false }, - { 2307, 2530, false }, - { 2308, 2560, false }, - { 2312, 2560, false }, - { 2316, 2540, false }, - { 2317, 2570, false }, - { 2320, 2570, false }, - { 2580, 0, false }, - { 2585, 2360, false }, - { 2588, 2340, false }, - { 2594, 2350, false }, - { 2606, 2330, false }, - { 2617, 2340, false }, - { 2627, 2350, false }, - { 2638, 2360, false }, - { 2649, 2370, false }, - { 2659, 2380, false }, - { 2664, 2350, false }, - { 2675, 2360, false }, - { 2686, 2370, false }, - { 2697, 2380, false }, - { 2705, 2350, false }, - { 2716, 2360, false }, - { 2728, 2370, false }, - { 2739, 2380, false }, - { 2757, 2330, false }, - { 2779, 2350, false }, - { 2790, 2360, false }, - { 2801, 2370, false }, - { 2812, 2380, false }, - { 2821, 2570, false }, - { 2831, 2520, false }, - { 2852, 2330, false }, - { 2874, 2350, false }, - { 2897, 2370, false }, - { 2913, 2510, false }, - { 2925, 2570, false }, - { 2937, 2530, false }, - { 2948, 2540, false }, - { 2960, 2550, false }, - { 2975, 2330, false }, - { 2988, 2340, false }, - { 3002, 2330, false }, - { 3014, 2360, false }, - { 3027, 2370, false }, - { 3041, 2500, false }, - { 3052, 2510, false }, - { 3064, 2520, false }, - { 3082, 2500, false }, - { 3107, 2520, false }, - { 3132, 2540, false }, - { 3157, 2560, false }, - { 3170, 2570, false }, - { 3192, 2500, false }, - { 3216, 2340, false }, - { 3270, 2330, false }, - { 3319, 2370, false }, - { 3341, 2340, false }, - { 3370, 2330, false }, - { 3400, 2350, false }, - { 3430, 2370, false }, - { 3464, 2520, false }, - { 3491, 2540, false }, - { 3519, 2560, false }, - { 3553, 2510, false }, - { 3595, 2540, false }, - { 3638, 2570, false }, - { 3665, 2540, false }, - { 3685, 2560, false }, - { 3726, 2330, false }, - { 3790, 2370, false }, - { 3910, 2350, false }, - { 4014, 2510, false }, - { 4123, 2380, false }, - { 4191, 2550, false }, - { 4349, 2510, false }, - { 4452, 2570, false }, - { 4579, 2500, false }, - { 4707, 2570, false }, - { 4831, 2560, false }, - { 4851, 2570, false }, - { 4871, 2560, false }, - { 4891, 2570, false }, - { 4911, 2540, false }, - { 4931, 2550, false }, - { 4951, 2560, false }, - { 5044, 2330, false }, - { 5065, 2340, false }, - { 5174, 2330, false }, - { 5285, 2380, false }, - { 5449, 2340, false }, - { 5574, 2510, false }, - { 5717, 2340, false }, - { 5892, 2530, false }, - { 6096, 2350, false }, - { 6254, 2560, false }, - { 6625, 2340, false }, - { 6764, 2540, false }, - { 6930, 2530, false }, - { 7251, 2570, false }, - { 0, 0, false }, + { 140, 2330, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 424, 2570, true, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 557, 2520, true, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 593, 2380, true, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 776, 2360, true, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 846, 2570, true, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 926, 2500, true, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 1055, 2380, true, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 1175, 2360, true, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 1391, 2340, true, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 1529, 2570, true, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 1671, 2520, true, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 1979, 2380, true, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2150, 2330, true, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2160, 2550, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2170, 2560, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2179, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2184, 2520, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2187, 2560, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2194, 2530, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2203, 2540, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2212, 2550, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2222, 2560, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2231, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2233, 2530, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2237, 2520, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2241, 2550, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2245, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2250, 2560, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2252, 2550, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2258, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2261, 2560, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2266, 2540, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2271, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2275, 2550, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2280, 2500, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2284, 2560, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2285, 2530, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2289, 2510, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2293, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2294, 2540, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2298, 2520, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2301, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2302, 2550, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2307, 2530, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2308, 2560, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2312, 2560, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2316, 2540, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2317, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2320, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2580, 0, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2585, 2360, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2588, 2340, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2594, 2350, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2606, 2330, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2617, 2340, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2627, 2350, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2638, 2360, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2649, 2370, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2659, 2380, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2664, 2350, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2675, 2360, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2686, 2370, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2697, 2380, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2705, 2350, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2716, 2360, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2728, 2370, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2739, 2380, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2757, 2330, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2779, 2350, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2790, 2360, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2801, 2370, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2812, 2380, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2821, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2831, 2520, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2852, 2330, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2874, 2350, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2897, 2370, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2913, 2510, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2925, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2937, 2530, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2948, 2540, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2960, 2550, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2975, 2330, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2988, 2340, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3002, 2330, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3014, 2360, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3027, 2370, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3041, 2500, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3052, 2510, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3064, 2520, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3082, 2500, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3107, 2520, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3132, 2540, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3157, 2560, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3170, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3192, 2500, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3216, 2340, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3270, 2330, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3319, 2370, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3341, 2340, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3370, 2330, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3400, 2350, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3430, 2370, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3464, 2520, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3491, 2540, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3519, 2560, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3553, 2510, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3595, 2540, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3638, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3665, 2540, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3685, 2560, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3726, 2330, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3790, 2370, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3910, 2350, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4014, 2510, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4123, 2380, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4191, 2550, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4349, 2510, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4452, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4579, 2500, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4707, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4831, 2560, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4851, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4871, 2560, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4891, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4911, 2540, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4931, 2550, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4951, 2560, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5044, 2330, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5065, 2340, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5174, 2330, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5285, 2380, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5449, 2340, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5574, 2510, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5717, 2340, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5892, 2530, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 6096, 2350, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 6254, 2560, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 6625, 2340, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 6764, 2540, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 6930, 2530, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 7251, 2570, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 0, 0, false, 0 }, }; -// TODO these are just copies of max2831_tune_config_rx_sweep for now -#define max2831_tune_config_rx max2831_tune_config_rx_sweep - // clang-format on - +/* tuning table optimized for RX */ +static const tune_config_t max2831_tune_config_rx[] = { + { 50, 2320, true, FPGA_QUARTER_SHIFT_MODE_UP }, + { 100, 2320, true, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 140, 2320, true, FPGA_QUARTER_SHIFT_MODE_UP }, + { 406, 2560, true, FPGA_QUARTER_SHIFT_MODE_UP }, + { 511, 2380, true, FPGA_QUARTER_SHIFT_MODE_UP }, + { 578, 2560, true, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 741, 2340, true, FPGA_QUARTER_SHIFT_MODE_UP }, + { 861, 2560, true, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 921, 2560, true, FPGA_QUARTER_SHIFT_MODE_UP }, + { 1049, 2340, true, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 1169, 2380, true, FPGA_QUARTER_SHIFT_MODE_UP }, + { 1360, 2340, true, FPGA_QUARTER_SHIFT_MODE_UP }, + { 1544, 2560, true, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 1675, 2560, true, FPGA_QUARTER_SHIFT_MODE_UP }, + { 1992, 2380, true, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2070, 2340, true, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2161, 2540, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2180, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2188, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2194, 2520, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2195, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2205, 2520, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2213, 2540, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2215, 2500, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2222, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2232, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2234, 2520, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2240, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2245, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2247, 2520, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2251, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2257, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2258, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2262, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2265, 2540, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2270, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2275, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2279, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2280, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2282, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2284, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2289, 2520, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2292, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2293, 2540, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2299, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2300, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2302, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2307, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2315, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2320, 2520, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2380, 0, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2440, 0, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2500, 0, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2580, 0, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2583, 2360, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2584, 2380, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2587, 2340, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2593, 2340, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2607, 2340, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2609, 2360, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2615, 2360, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2627, 2340, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2629, 2360, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2631, 2380, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2644, 2340, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2649, 2380, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2651, 2380, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2654, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2665, 2360, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2669, 2380, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2672, 2360, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2682, 2340, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2687, 2380, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2692, 2340, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2695, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2705, 2360, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2707, 2380, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2712, 2340, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2717, 2520, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2728, 2380, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2730, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2734, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2758, 2340, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2780, 2360, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2787, 2520, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2802, 2380, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2809, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2822, 2380, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2831, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2854, 2340, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2875, 2360, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2898, 2380, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2918, 2380, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2936, 2520, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2944, 2380, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2959, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2976, 2340, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2985, 2500, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 3003, 2340, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3009, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3027, 2380, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3034, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3050, 2380, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 3069, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3094, 2520, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3119, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3144, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3169, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 3180, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3204, 2340, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3232, 2360, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3292, 2340, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 3340, 2380, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 3369, 2340, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3399, 2360, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3429, 2380, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3464, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3489, 2520, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3512, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3551, 2500, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 3582, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3611, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3639, 2520, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3729, 2340, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 3817, 2380, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 3942, 2360, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 4049, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 4134, 2500, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 4194, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 4353, 2520, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 4449, 2360, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 4562, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 4672, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 4769, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 4849, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 4889, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 4929, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 4969, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 5009, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 5049, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 5092, 2360, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 5209, 2340, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 5298, 2380, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 5468, 2340, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 5582, 2520, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 5702, 2340, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 5888, 2520, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 6092, 2340, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 6240, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 6609, 2340, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 6752, 2380, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 6930, 2520, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 7000, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 7070, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 7251, 2580, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 0, 0, false, 0 }, +}; +// clang-format on #endif #endif /*__TUNE_CONFIG_H__*/ diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index fa11a6fc..e1a1d951 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -143,7 +143,10 @@ bool set_freq(const uint64_t freq) #else -bool tuning_set_frequency(const tune_config_t* cfg, const uint64_t freq) +bool tuning_set_frequency( + const tune_config_t* cfg, + const uint64_t freq, + const uint32_t offset) { uint64_t mixer_freq_hz; uint64_t real_mixer_freq_hz; @@ -154,31 +157,42 @@ bool tuning_set_frequency(const tune_config_t* cfg, const uint64_t freq) const uint16_t freq_mhz = freq / FREQ_ONE_MHZ; + uint64_t rf = freq; + if (cfg->shift == FPGA_QUARTER_SHIFT_MODE_DOWN) { + if (offset > rf) { + rf = offset - rf; + } else { + rf = rf - offset; + } + } else if (cfg->shift == FPGA_QUARTER_SHIFT_MODE_UP) { + rf = rf + offset; + } + max2831_mode_t prior_max2831_mode = max2831_mode(&max283x); max2831_set_mode(&max283x, MAX2831_MODE_STANDBY); if (cfg->if_mhz == 0) { rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS); - max2831_set_frequency(&max283x, freq); + max2831_set_frequency(&max283x, rf); sgpio_cpld_set_mixer_invert(&sgpio_config, 0); } else if (cfg->if_mhz > freq_mhz) { rf_path_set_filter(&rf_path, RF_PATH_FILTER_LOW_PASS); if (cfg->high_lo) { - mixer_freq_hz = FREQ_ONE_MHZ * cfg->if_mhz + freq; + mixer_freq_hz = FREQ_ONE_MHZ * cfg->if_mhz + rf; real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_hz); - max2831_set_frequency(&max283x, real_mixer_freq_hz - freq); + max2831_set_frequency(&max283x, real_mixer_freq_hz - rf); sgpio_cpld_set_mixer_invert(&sgpio_config, 1); } else { - mixer_freq_hz = FREQ_ONE_MHZ * cfg->if_mhz - freq; + mixer_freq_hz = FREQ_ONE_MHZ * cfg->if_mhz - rf; real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_hz); - max2831_set_frequency(&max283x, real_mixer_freq_hz + freq); + max2831_set_frequency(&max283x, real_mixer_freq_hz + rf); sgpio_cpld_set_mixer_invert(&sgpio_config, 0); } } else { rf_path_set_filter(&rf_path, RF_PATH_FILTER_HIGH_PASS); - mixer_freq_hz = freq - FREQ_ONE_MHZ * cfg->if_mhz; + mixer_freq_hz = rf - FREQ_ONE_MHZ * cfg->if_mhz; real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_hz); - max2831_set_frequency(&max283x, freq - real_mixer_freq_hz); + max2831_set_frequency(&max283x, rf - real_mixer_freq_hz); sgpio_cpld_set_mixer_invert(&sgpio_config, 0); } diff --git a/firmware/common/tuning.h b/firmware/common/tuning.h index 1d521f84..863fe6a0 100644 --- a/firmware/common/tuning.h +++ b/firmware/common/tuning.h @@ -39,7 +39,10 @@ bool set_freq_explicit( const rf_path_filter_t path); #ifdef PRALINE -bool tuning_set_frequency(const tune_config_t* config, const uint64_t frequency_hz); +bool tuning_set_frequency( + const tune_config_t* cfg, + const uint64_t freq, + const uint32_t offset); #endif #endif /*__TUNING_H__*/ From d8a9d445f5bafcdfcc84f8184f5836563f296efb Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 30 Dec 2025 21:36:11 -0500 Subject: [PATCH 12/20] Rename tuning config tables --- firmware/common/radio.c | 6 +++--- firmware/common/tune_config.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index e23902a1..0b669393 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -256,13 +256,13 @@ radio_error_t radio_set_frequency( const tune_config_t* tune_config; switch (config->mode) { case TRANSCEIVER_MODE_RX: - tune_config = max2831_tune_config_rx; + tune_config = praline_tune_config_rx; break; case TRANSCEIVER_MODE_RX_SWEEP: - tune_config = max2831_tune_config_rx_sweep; + tune_config = praline_tune_config_rx_sweep; break; case TRANSCEIVER_MODE_TX: - tune_config = max2831_tune_config_tx; + tune_config = praline_tune_config_tx; break; default: return RADIO_ERR_INVALID_CONFIG; diff --git a/firmware/common/tune_config.h b/firmware/common/tune_config.h index c24cc3a5..be55dfea 100644 --- a/firmware/common/tune_config.h +++ b/firmware/common/tune_config.h @@ -34,7 +34,7 @@ typedef struct { // clang-format off /* tuning table optimized for TX */ -static const tune_config_t max2831_tune_config_tx[] = { +static const tune_config_t praline_tune_config_tx[] = { { 2100, 2375, true, FPGA_QUARTER_SHIFT_MODE_NONE }, { 2175, 2325, false, FPGA_QUARTER_SHIFT_MODE_NONE }, { 2320, 2525, false, FPGA_QUARTER_SHIFT_MODE_NONE }, @@ -64,7 +64,7 @@ static const tune_config_t max2831_tune_config_tx[] = { }; /* tuning table optimized for 20 Msps interleaved RX sweep mode */ -static const tune_config_t max2831_tune_config_rx_sweep[] = { +static const tune_config_t praline_tune_config_rx_sweep[] = { { 140, 2330, false, FPGA_QUARTER_SHIFT_MODE_NONE }, { 424, 2570, true, FPGA_QUARTER_SHIFT_MODE_NONE }, { 557, 2520, true, FPGA_QUARTER_SHIFT_MODE_NONE }, @@ -212,7 +212,7 @@ static const tune_config_t max2831_tune_config_rx_sweep[] = { }; /* tuning table optimized for RX */ -static const tune_config_t max2831_tune_config_rx[] = { +static const tune_config_t praline_tune_config_rx[] = { { 50, 2320, true, FPGA_QUARTER_SHIFT_MODE_UP }, { 100, 2320, true, FPGA_QUARTER_SHIFT_MODE_DOWN }, { 140, 2320, true, FPGA_QUARTER_SHIFT_MODE_UP }, From 1ad8adb4497ed06cb6e81403e8c106054e88016a Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 30 Dec 2025 21:57:58 -0500 Subject: [PATCH 13/20] Automatically configure Praline baseband LPF For compatibility with old host software, the analog baseband filter is automatically selected based on the sample rate and offset tuning configuration. The bandwidth set by legacy vendor request is ignored. --- firmware/common/hackrf_core.c | 1 + firmware/common/radio.c | 37 ++++++++++++++++++++++++++++------- firmware/common/radio.h | 4 ++++ 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index fdaecf2b..065cf72d 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -378,6 +378,7 @@ radio_t radio = { .trigger_enable = false, #ifdef PRALINE .resampling_n = 0, + .shift = FPGA_QUARTER_SHIFT_MODE_NONE, #endif }, .clock_source = CLOCK_SOURCE_HACKRF, diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 0b669393..5bcdd8cf 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -116,17 +116,22 @@ radio_error_t radio_set_filter( return RADIO_OK; } - uint32_t real_hz; #ifndef PRALINE - real_hz = max283x_set_lpf_bandwidth(&max283x, filter.hz); + max283x_set_lpf_bandwidth(&max283x, filter.hz); #else - real_hz = max2831_set_lpf_bandwidth(&max283x, filter.hz); -#endif - if (real_hz == 0) { - return RADIO_ERR_INVALID_PARAM; + uint32_t lpf_bandwidth = + (config->sample_rate[RADIO_SAMPLE_RATE_CLOCKGEN].hz * 3) / 8; + uint32_t offset = 0; + if (config->shift != FPGA_QUARTER_SHIFT_MODE_NONE) { + offset = (config->sample_rate[RADIO_SAMPLE_RATE_CLOCKGEN].hz + << config->resampling_n) / + 8; } + lpf_bandwidth += offset * 2; + max2831_set_lpf_bandwidth(&max283x, lpf_bandwidth); +#endif - config->filter[element] = (radio_filter_t){.hz = real_hz}; + config->filter[element] = filter; return RADIO_OK; } @@ -230,6 +235,17 @@ radio_error_t radio_set_frequency( fpga_set_rx_quarter_shift_mode( &fpga, FPGA_QUARTER_SHIFT_MODE_NONE); + config->shift = FPGA_QUARTER_SHIFT_MODE_NONE; + radio_channel_t* channel = &radio->channel[chan_id]; + radio_filter_t filter = radio_get_filter( + radio, + channel->id, + RADIO_FILTER_BASEBAND); + ok = radio_set_filter( + radio, + channel->id, + RADIO_FILTER_BASEBAND, + filter); } #endif if (!ok) { @@ -280,10 +296,17 @@ radio_error_t radio_set_frequency( } fpga_set_rx_quarter_shift_mode(&fpga, tune_config->shift); + config->shift = tune_config->shift; uint32_t offset = (config->sample_rate[RADIO_SAMPLE_RATE_CLOCKGEN].hz << config->resampling_n) / 8; ok = tuning_set_frequency(tune_config, frequency.hz, offset); + if (ok) { + radio_channel_t* channel = &radio->channel[chan_id]; + radio_filter_t filter = + radio_get_filter(radio, channel->id, RADIO_FILTER_BASEBAND); + ok = radio_set_filter(radio, channel->id, RADIO_FILTER_BASEBAND, filter); + } #endif if (!ok) { return RADIO_ERR_INVALID_PARAM; diff --git a/firmware/common/radio.h b/firmware/common/radio.h index 2b054bd2..60e2cc4d 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -28,6 +28,7 @@ #include #include "rf_path.h" +#include "fpga.h" typedef enum { RADIO_OK = 1, @@ -160,6 +161,9 @@ typedef struct { #ifdef PRALINE // resampling ratio is 2**n uint8_t resampling_n; + + // quarter-rate shift configuration for offset tuning + fpga_quarter_shift_mode_t shift; #endif } radio_config_t; From 5766678b6fd2921f44cbb314f0f27892e9a8c368 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 30 Dec 2025 22:04:07 -0500 Subject: [PATCH 14/20] Don't repeat tuning and baseband filter setting --- firmware/common/radio.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 5bcdd8cf..ab65ef9e 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -474,6 +474,23 @@ radio_error_t radio_switch_mode( return result; } + /* + * Because of offset tuning on Praline, the sample rate can affect the + * tuning configuration, so radio_set_sample_rate() calls + * radio_set_frequency(). Also because of offset tuning, the tuning + * configuration can affect the baseband filter bandwidth (in addition + * to the filter bandwidth being automatically based on the sample + * rate), so radio_set_frequency() calls radio_set_filter(). + */ +#ifndef PRALINE + // tuning frequency + radio_frequency_t frequency = + radio_get_frequency(radio, channel->id, RADIO_FREQUENCY_RF); + result = radio_set_frequency(radio, channel->id, RADIO_FREQUENCY_RF, frequency); + if (result != RADIO_OK) { + return result; + } + // baseband filter bandwidth radio_filter_t filter = radio_get_filter(radio, channel->id, RADIO_FILTER_BASEBAND); @@ -481,6 +498,7 @@ radio_error_t radio_switch_mode( if (result != RADIO_OK) { return result; } +#endif // rf_amp enable radio_gain_t enable = radio_get_gain(radio, channel->id, RADIO_GAIN_RF_AMP); @@ -521,14 +539,6 @@ radio_error_t radio_switch_mode( return result; } - // tuning frequency - radio_frequency_t frequency = - radio_get_frequency(radio, channel->id, RADIO_FREQUENCY_RF); - result = radio_set_frequency(radio, channel->id, RADIO_FREQUENCY_RF, frequency); - if (result != RADIO_OK) { - return result; - } - // finally, set the rf path direction rf_path_set_direction(&rf_path, direction); From 636f8bde6ed59e71c59831a07a81c87425f5180c Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 30 Dec 2025 22:07:30 -0500 Subject: [PATCH 15/20] Add special tuning configuration case at 0 Hz --- firmware/common/radio.c | 3 ++- firmware/common/tune_config.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index ab65ef9e..d1441847 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -286,7 +286,8 @@ radio_error_t radio_set_frequency( bool found = false; for (; (tune_config->rf_range_end_mhz != 0) || (tune_config->if_mhz != 0); tune_config++) { - if (tune_config->rf_range_end_mhz > (frequency.hz / FREQ_ONE_MHZ)) { + if ((frequency.hz == 0) || + (tune_config->rf_range_end_mhz > (frequency.hz / FREQ_ONE_MHZ))) { found = true; break; } diff --git a/firmware/common/tune_config.h b/firmware/common/tune_config.h index be55dfea..05c1b34a 100644 --- a/firmware/common/tune_config.h +++ b/firmware/common/tune_config.h @@ -213,6 +213,7 @@ static const tune_config_t praline_tune_config_rx_sweep[] = { /* tuning table optimized for RX */ static const tune_config_t praline_tune_config_rx[] = { + { 0, 2360, true, FPGA_QUARTER_SHIFT_MODE_NONE }, { 50, 2320, true, FPGA_QUARTER_SHIFT_MODE_UP }, { 100, 2320, true, FPGA_QUARTER_SHIFT_MODE_DOWN }, { 140, 2320, true, FPGA_QUARTER_SHIFT_MODE_UP }, From ed2e2ce2d2ce27466920507d919dd6e13edca81f Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Wed, 31 Dec 2025 14:05:13 -0500 Subject: [PATCH 16/20] Use consistent feedback divider in RFFC5072 --- firmware/common/rffc5071.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 8079e465..2e1d7c41 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -247,19 +247,22 @@ uint64_t rffc5071_config_synth(rffc5071_driver_t* const drv, uint64_t lo) fvco = lo << n_lo; - /* higher divider and charge pump current required above - * 3.2GHz. Programming guide says these values (fbkdiv, n, - * maybe pump?) can be changed back after enable in order to - * improve phase noise, since the VCO will already be stable - * and will be unaffected. */ + /* + * Higher charge pump leakage setting is required above 3.2 GHz. + */ if (fvco > (3200 * FREQ_ONE_MHZ)) { - fbkdivlog = 2; set_RFFC5071_PLLCPL(drv, 3); } else { - fbkdivlog = 1; set_RFFC5071_PLLCPL(drv, 2); } + /* + * Supposedly fbkdivlog can be set to 1 when VCO is below 3.2 GHz, but + * this has resulted in tuning instability on some boards, most evident + * in RX sweep mode. + */ + fbkdivlog = 2; + uint64_t tmp_n = (fvco << (24ULL - fbkdivlog)) / REF_FREQ; /* Round to nearest step = ref_MHz / 2**s. For s=6, step=625000 Hz */ From 994910098205ea75999639b77bbdee773f62c0ea Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 1 Jan 2026 15:41:23 -0500 Subject: [PATCH 17/20] Don't try to self-test during clockgen shutdown --- firmware/common/hackrf_core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 065cf72d..5d59da00 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -979,7 +979,6 @@ void clock_gen_init(void) void clock_gen_shutdown(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); From 9e0e0eb81c3744f1aeffabe03c508ef831358d76 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 1 Jan 2026 15:58:03 -0500 Subject: [PATCH 18/20] Increase maximum self-test buffer size Closes #1617 --- host/libhackrf/src/hackrf.c | 2 +- host/libhackrf/src/hackrf.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 0588dbca..799e4250 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -1238,7 +1238,7 @@ int ADDCALL hackrf_read_selftest(hackrf_device* device, hackrf_selftest* selftes sizeof(hackrf_selftest), 0); - if (result < sizeof(hackrf_selftest)) { + if (result < 2) { last_libusb_error = result; return HACKRF_ERROR_LIBUSB; } else { diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index 6327e246..95f4d5ae 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -1081,7 +1081,7 @@ typedef struct { */ typedef struct { bool pass; - char msg[511]; + char msg[4095]; } hackrf_selftest; /** From eb9b1e0ffe06381f77ef37a5ac2e283dce6adf0b Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Fri, 2 Jan 2026 16:27:54 -0500 Subject: [PATCH 19/20] Improve tuning tables --- firmware/common/tune_config.h | 98 +++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 40 deletions(-) diff --git a/firmware/common/tune_config.h b/firmware/common/tune_config.h index 05c1b34a..dd21d028 100644 --- a/firmware/common/tune_config.h +++ b/firmware/common/tune_config.h @@ -36,24 +36,49 @@ typedef struct { /* tuning table optimized for TX */ static const tune_config_t praline_tune_config_tx[] = { { 2100, 2375, true, FPGA_QUARTER_SHIFT_MODE_NONE }, - { 2175, 2325, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2105, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2115, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2130, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2150, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2160, 2475, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2175, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2190, 2475, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2195, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2210, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2248, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2265, 2525, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 2300, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, { 2320, 2525, false, FPGA_QUARTER_SHIFT_MODE_NONE }, { 2580, 0, false, FPGA_QUARTER_SHIFT_MODE_NONE }, { 3000, 2325, false, FPGA_QUARTER_SHIFT_MODE_NONE }, - { 3100, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3140, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, { 3200, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, - { 3350, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3280, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3340, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3420, 2475, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3480, 2525, false, FPGA_QUARTER_SHIFT_MODE_NONE }, { 3500, 2475, false, FPGA_QUARTER_SHIFT_MODE_NONE }, - { 3550, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, - { 3650, 2325, false, FPGA_QUARTER_SHIFT_MODE_NONE }, - { 3700, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, - { 3850, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, - { 3925, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, - { 4600, 2325, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3595, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3625, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3670, 2475, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3710, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3760, 2525, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3790, 2475, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3860, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 3915, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4000, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4055, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 4125, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, { 4700, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, { 4800, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, - { 5100, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, - { 5850, 2525, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5000, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5260, 2475, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5465, 2525, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5560, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5720, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5860, 2475, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 5970, 2575, false, FPGA_QUARTER_SHIFT_MODE_NONE }, + { 6000, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, { 6500, 2325, false, FPGA_QUARTER_SHIFT_MODE_NONE }, { 6750, 2375, false, FPGA_QUARTER_SHIFT_MODE_NONE }, { 6850, 2425, false, FPGA_QUARTER_SHIFT_MODE_NONE }, @@ -230,40 +255,33 @@ static const tune_config_t praline_tune_config_rx[] = { { 1675, 2560, true, FPGA_QUARTER_SHIFT_MODE_UP }, { 1992, 2380, true, FPGA_QUARTER_SHIFT_MODE_DOWN }, { 2070, 2340, true, FPGA_QUARTER_SHIFT_MODE_DOWN }, - { 2161, 2540, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, - { 2180, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, - { 2188, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2194, 2520, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, - { 2195, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2150, 2360, true, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2168, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2185, 2580, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2202, 2580, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, { 2205, 2520, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2213, 2540, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, - { 2215, 2500, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, - { 2222, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2232, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, - { 2234, 2520, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2216, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2223, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2234, 2580, false, FPGA_QUARTER_SHIFT_MODE_UP }, { 2240, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2245, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2247, 2520, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, - { 2251, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2257, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2258, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, - { 2262, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2251, 2580, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2258, 2580, false, FPGA_QUARTER_SHIFT_MODE_UP }, { 2265, 2540, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, - { 2270, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2275, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2279, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2280, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2282, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2271, 2580, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2273, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2275, 2580, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2280, 2500, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, { 2284, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2289, 2520, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2292, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2289, 2580, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, { 2293, 2540, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, - { 2299, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2300, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, - { 2302, 2560, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2307, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2315, 2500, false, FPGA_QUARTER_SHIFT_MODE_UP }, - { 2320, 2520, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2298, 2520, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2300, 2580, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2302, 2540, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2309, 2560, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2311, 2580, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2314, 2540, false, FPGA_QUARTER_SHIFT_MODE_UP }, + { 2315, 2540, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, + { 2320, 2580, false, FPGA_QUARTER_SHIFT_MODE_UP }, { 2380, 0, false, FPGA_QUARTER_SHIFT_MODE_UP }, { 2440, 0, false, FPGA_QUARTER_SHIFT_MODE_DOWN }, { 2500, 0, false, FPGA_QUARTER_SHIFT_MODE_UP }, From b225a8a7e344f7d74042333923f2744cf8bda056 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sat, 3 Jan 2026 19:03:15 -0500 Subject: [PATCH 20/20] Fix RFFC5072 GPO bug on Jawbreaker --- firmware/common/rffc5071.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 2e1d7c41..161e74ec 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -122,8 +122,10 @@ void rffc5071_setup(rffc5071_driver_t* const drv) /* GPOs are active at all times */ set_RFFC5071_GATE(drv, 1); +#ifdef PRALINE /* Enable GPO Lock output signal */ set_RFFC5071_LOCK(drv, 1); +#endif rffc5071_regs_commit(drv); }