From 06c1163d646792f25ba05403ba42860770e72808 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 26 Jan 2026 20:12:40 +0000 Subject: [PATCH 001/238] Provide access to the larger SPI flash on Praline. --- firmware/common/w25q80bv.c | 5 ++ host/hackrf-tools/src/hackrf_spiflash.c | 82 +++++++++++++++---------- host/libhackrf/src/hackrf.c | 4 +- 3 files changed, 58 insertions(+), 33 deletions(-) diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index fe09a2e8..08480138 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -59,8 +59,13 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv) uint8_t device_id; drv->page_len = 256U; +#ifdef PRALINE + drv->num_pages = 16384U; + drv->num_bytes = 4194304U; +#else drv->num_pages = 4096U; drv->num_bytes = 1048576U; +#endif drv->target_init(drv); diff --git a/host/hackrf-tools/src/hackrf_spiflash.c b/host/hackrf-tools/src/hackrf_spiflash.c index 46ad1cef..f6409280 100644 --- a/host/hackrf-tools/src/hackrf_spiflash.c +++ b/host/hackrf-tools/src/hackrf_spiflash.c @@ -38,8 +38,12 @@ typedef int32_t ssize_t; #endif #endif +/* 32 Mbit flash */ +#define PRALINE_FLASH_LENGTH 0x400000 /* 8 Mbit flash */ -#define MAX_LENGTH 0x100000 +#define OTHER_FLASH_LENGTH 0x100000 + +#define MAX_LENGTH PRALINE_FLASH_LENGTH static struct option long_options[] = { {"address", required_argument, 0, 'a'}, @@ -61,13 +65,15 @@ static struct option long_options[] = { * If you're already running firmware that reports the wrong ID * I can't help you, but you can use the -i optionto ignore (or DFU) */ -int compatibility_check_og(uint8_t* data, int length, hackrf_device* device) +int compatibility_check_og( + uint8_t* data, + int length, + hackrf_device* device, + uint8_t board_id) { int str_len, i, j; bool match = false; - uint8_t board_id; char* dev_str; - hackrf_board_id_read(device, &board_id); switch (board_id) { case BOARD_ID_JAWBREAKER: dev_str = "HackRF Jawbreaker"; @@ -112,17 +118,14 @@ int compatibility_check_og(uint8_t* data, int length, hackrf_device* device) #define FROM_LE32(x) ((x)[0] | ((x)[1] << 8) | ((x)[2] << 16) | ((x)[3] << 24)) #define FROM_LE16(x) ((x)[0] | ((x)[1] << 8)) -int compatibility_check(uint8_t* data, int length, hackrf_device* device) +int compatibility_check(uint8_t* data, int length, hackrf_device* device, uint8_t board_id) { - uint8_t board_id; - hackrf_board_id_read(device, &board_id); - uint8_t* fw_info = data + FW_INFO_LOCATION; if (strncmp((char*) fw_info + FW_MAGIC_OFFSET, "HACKRFFW", 8) != 0) { // Couldn't find firmware info structure, // revert to old compatibility check method if possible. if (board_id != BOARD_ID_HACKRF1_R9) { - return compatibility_check_og(data, length, device); + return compatibility_check_og(data, length, device, board_id); } return EXIT_FAILURE; @@ -187,7 +190,7 @@ static void usage() printf("Usage:\n"); printf("\t-h, --help: this help\n"); printf("\t-a, --address : starting address (default: 0)\n"); - printf("\t-l, --length : number of bytes to read (default: %d)\n", MAX_LENGTH); + printf("\t-l, --length : number of bytes to read (default: all)\n"); printf("\t-r, --read : Read data into file.\n"); printf("\t-w, --write : Write data from file.\n"); printf("\t-i, --no-check: Skip check for firmware compatibility with target device.\n"); @@ -202,8 +205,10 @@ int main(int argc, char** argv) { int opt; uint8_t status[2]; + uint8_t board_id; uint32_t address = 0; - uint32_t length = MAX_LENGTH; + uint32_t length; + uint32_t flash_length; uint32_t tmp_length; uint16_t xfer_len = 0; const char* path = NULL; @@ -221,6 +226,7 @@ int main(int argc, char** argv) bool reset = false; bool read_status = false; bool clear_status = false; + bool length_specified = false; uint16_t usb_api; while ((opt = getopt_long( @@ -236,6 +242,7 @@ int main(int argc, char** argv) case 'l': result = parse_u32(optarg, &length); + length_specified = true; break; case 'r': @@ -316,30 +323,12 @@ int main(int argc, char** argv) 0, SEEK_END); /* Not really portable but work on major OS Linux/Win32 */ length = ftell(infile); + length_specified = true; /* Move to start */ rewind(infile); printf("File size %d bytes.\n", length); } - if (length == 0) { - fprintf(stderr, "Requested transfer of zero bytes.\n"); - if (infile != NULL) { - fclose(infile); - } - usage(); - return EXIT_FAILURE; - } - - if ((length > MAX_LENGTH) || (address > MAX_LENGTH) || - ((address + length) > MAX_LENGTH)) { - fprintf(stderr, "Request exceeds size of flash memory.\n"); - if (infile != NULL) { - fclose(infile); - } - usage(); - return EXIT_FAILURE; - } - if (read) { infile = fopen(path, "wb"); if (infile == NULL) { @@ -366,6 +355,37 @@ int main(int argc, char** argv) return EXIT_FAILURE; } + hackrf_board_id_read(device, &board_id); + + if (board_id == BOARD_ID_PRALINE) { + flash_length = PRALINE_FLASH_LENGTH; + } else { + flash_length = OTHER_FLASH_LENGTH; + } + + if (!length_specified) { + length = flash_length - address; + } + + if (length == 0) { + fprintf(stderr, "Requested transfer of zero bytes.\n"); + if (infile != NULL) { + fclose(infile); + } + usage(); + return EXIT_FAILURE; + } + + if ((length > flash_length) || (address > flash_length) || + ((address + length) > flash_length)) { + fprintf(stderr, "Request exceeds size of flash memory.\n"); + if (infile != NULL) { + fclose(infile); + } + usage(); + return EXIT_FAILURE; + } + if (read_status) { result = hackrf_spiflash_status(device, status); if (result != HACKRF_SUCCESS) { @@ -453,7 +473,7 @@ int main(int argc, char** argv) } if (!ignore_compat_check) { printf("Checking target device compatibility\n"); - result = compatibility_check(data, length, device); + result = compatibility_check(data, length, device, board_id); if (result) { printf("Compatibility test failed.\n"); fclose(infile); diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 5aab1991..3ada04b2 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -1515,7 +1515,7 @@ int ADDCALL hackrf_spiflash_write( { int result; - if (address > 0x0FFFFF) { + if ((address + length) > 0x400000) { return HACKRF_ERROR_INVALID_PARAM; } @@ -1546,7 +1546,7 @@ int ADDCALL hackrf_spiflash_read( { int result; - if (address > 0x0FFFFF) { + if ((address + length) > 0x400000) { return HACKRF_ERROR_INVALID_PARAM; } From e6ca4d9b71173cc935ad184d9afa0fb6d49e09b7 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 29 Jan 2026 22:16:11 -0500 Subject: [PATCH 002/238] Set libhackrf version to 0.9.2 --- host/libhackrf/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/libhackrf/CMakeLists.txt b/host/libhackrf/CMakeLists.txt index ccc7f89d..37f124e6 100644 --- a/host/libhackrf/CMakeLists.txt +++ b/host/libhackrf/CMakeLists.txt @@ -20,7 +20,7 @@ cmake_minimum_required(VERSION 3.10.0) project( libhackrf LANGUAGES C - VERSION 0.9.1) + VERSION 0.9.2) include(GNUInstallDirs) include(${PROJECT_SOURCE_DIR}/../cmake/set_release.cmake) set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules) From 3233cd56cfdda9a156c3a97e7da05c21a89a69a0 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 29 Jan 2026 22:19:42 -0500 Subject: [PATCH 003/238] Set USB API version to 1.10 --- firmware/hackrf_usb/usb_descriptor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/usb_descriptor.c b/firmware/hackrf_usb/usb_descriptor.c index 70c4daf1..68b2ea81 100644 --- a/firmware/hackrf_usb/usb_descriptor.c +++ b/firmware/hackrf_usb/usb_descriptor.c @@ -37,7 +37,7 @@ #define USB_PRODUCT_ID (0xFFFF) #endif -#define USB_API_VERSION (0x0109) +#define USB_API_VERSION (0x0110) #define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF) From a0066ded5101d949146fa4db227a096d604dabc9 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 29 Jan 2026 22:21:45 -0500 Subject: [PATCH 004/238] Set version to 2026.01.3 --- ci-scripts/hackrf_test.py | 2 +- firmware/hackrf-common.cmake | 2 +- host/cmake/set_release.cmake | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci-scripts/hackrf_test.py b/ci-scripts/hackrf_test.py index 3b304156..e8d04fa9 100644 --- a/ci-scripts/hackrf_test.py +++ b/ci-scripts/hackrf_test.py @@ -1219,7 +1219,7 @@ def get_version(): version = subprocess.run(["git", "log", "-n" "1", "--format=%h"], capture_output=True, encoding="utf-8", timeout=TIMEOUT) if version.returncode != 0: - return "2026.01.2+" + return "2026.01.3" elif version.returncode == 0: dirty = subprocess.run(["git", "status", "-s", "--untracked-files=no"], capture_output=True, encoding="utf-8", timeout=TIMEOUT) diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 877e8a85..fed1d66b 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -64,7 +64,7 @@ if (NOT DEFINED VERSION) OUTPUT_STRIP_TRAILING_WHITESPACE ) if (GIT_VERSION_FOUND) - set(VERSION "2026.01.2+") + set(VERSION "2026.01.3") else (GIT_VERSION_FOUND) set(VERSION "git-${GIT_VERSION}") endif (GIT_VERSION_FOUND) diff --git a/host/cmake/set_release.cmake b/host/cmake/set_release.cmake index ecc0ad69..ea0ec000 100644 --- a/host/cmake/set_release.cmake +++ b/host/cmake/set_release.cmake @@ -8,7 +8,7 @@ if(NOT DEFINED RELEASE) OUTPUT_STRIP_TRAILING_WHITESPACE ) if (GIT_EXIT_VALUE) - set(RELEASE "2026.01.2+") + set(RELEASE "2026.01.3") else (GIT_EXIT_VALUE) execute_process( COMMAND git status -s --untracked-files=no From a7dc78612f8d36d96cdfd12467fc7519ff26464a Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 29 Jan 2026 23:03:34 -0500 Subject: [PATCH 005/238] Set version to 2026.01.3+ --- ci-scripts/hackrf_test.py | 2 +- firmware/hackrf-common.cmake | 2 +- host/cmake/set_release.cmake | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci-scripts/hackrf_test.py b/ci-scripts/hackrf_test.py index e8d04fa9..b4f1d9b1 100644 --- a/ci-scripts/hackrf_test.py +++ b/ci-scripts/hackrf_test.py @@ -1219,7 +1219,7 @@ def get_version(): version = subprocess.run(["git", "log", "-n" "1", "--format=%h"], capture_output=True, encoding="utf-8", timeout=TIMEOUT) if version.returncode != 0: - return "2026.01.3" + return "2026.01.3+" elif version.returncode == 0: dirty = subprocess.run(["git", "status", "-s", "--untracked-files=no"], capture_output=True, encoding="utf-8", timeout=TIMEOUT) diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index fed1d66b..788f66c0 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -64,7 +64,7 @@ if (NOT DEFINED VERSION) OUTPUT_STRIP_TRAILING_WHITESPACE ) if (GIT_VERSION_FOUND) - set(VERSION "2026.01.3") + set(VERSION "2026.01.3+") else (GIT_VERSION_FOUND) set(VERSION "git-${GIT_VERSION}") endif (GIT_VERSION_FOUND) diff --git a/host/cmake/set_release.cmake b/host/cmake/set_release.cmake index ea0ec000..60111b95 100644 --- a/host/cmake/set_release.cmake +++ b/host/cmake/set_release.cmake @@ -8,7 +8,7 @@ if(NOT DEFINED RELEASE) OUTPUT_STRIP_TRAILING_WHITESPACE ) if (GIT_EXIT_VALUE) - set(RELEASE "2026.01.3") + set(RELEASE "2026.01.3+") else (GIT_EXIT_VALUE) execute_process( COMMAND git status -s --untracked-files=no From 1ee45eaaa2f5c29f6c4f4781ddf54039d49e01a3 Mon Sep 17 00:00:00 2001 From: stafur Date: Thu, 5 Feb 2026 11:36:56 -0500 Subject: [PATCH 006/238] Toolchain 9.2.1 support fix (#1666) Added -B arm flag to firmware/hackrf_usb/CMakeLists.txt to support builds with v9.2.1 toolchains. --- firmware/hackrf_usb/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/firmware/hackrf_usb/CMakeLists.txt b/firmware/hackrf_usb/CMakeLists.txt index 2b797339..3ab1beed 100644 --- a/firmware/hackrf_usb/CMakeLists.txt +++ b/firmware/hackrf_usb/CMakeLists.txt @@ -38,6 +38,7 @@ add_custom_command( COMMAND ${CMAKE_OBJCOPY} -I binary -O elf32-littlearm + -B arm --rename-section .data=.rom_only "fpga.bin" ${PATH_PRALINE_FPGA_OBJ} DEPENDS ${PATH_PRALINE_FPGA_BIN} From ead77b91cff75876fd4f03efff39bc1b80af879d Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 6 Feb 2026 16:47:47 +0000 Subject: [PATCH 007/238] Always use void argument type for functions taking no arguments. --- firmware/common/fault_handler.c | 6 +++--- firmware/common/fpga.h | 6 +++--- firmware/common/fpga_selftest.c | 6 +++--- firmware/common/gpdma.c | 2 +- firmware/common/gpdma.h | 2 +- firmware/common/gpio.h | 2 +- firmware/common/gpio_lpc.c | 2 +- firmware/common/ice40_spi.c | 6 +++--- firmware/common/m0_sleep.c | 2 +- firmware/common/operacake_sctimer.c | 6 +++--- firmware/common/operacake_sctimer.h | 6 +++--- firmware/common/portapack.c | 32 ++++++++++++++--------------- firmware/common/rad1o/decoder.c | 2 +- firmware/common/rad1o/display.c | 4 ++-- firmware/common/ui_portapack.c | 4 ++-- firmware/common/ui_portapack.h | 2 +- firmware/common/usb.c | 6 +++--- firmware/hackrf_usb/hackrf_usb.c | 2 +- 18 files changed, 49 insertions(+), 49 deletions(-) diff --git a/firmware/common/fault_handler.c b/firmware/common/fault_handler.c index 413ce8a8..63c868d8 100644 --- a/firmware/common/fault_handler.c +++ b/firmware/common/fault_handler.c @@ -73,17 +73,17 @@ __attribute__((used)) void hard_fault_handler_c(uint32_t* args) while (1) {} } -void mem_manage_handler() +void mem_manage_handler(void) { while (1) {} } -void bus_fault_handler() +void bus_fault_handler(void) { while (1) {} } -void usage_fault_handler() +void usage_fault_handler(void) { while (1) {} } diff --git a/firmware/common/fpga.h b/firmware/common/fpga.h index fb4270a8..b7bb90bb 100644 --- a/firmware/common/fpga.h +++ b/firmware/common/fpga.h @@ -76,8 +76,8 @@ void fpga_set_tx_nco_enable(fpga_driver_t* const drv, const bool enable); void fpga_set_tx_nco_pstep(fpga_driver_t* const drv, const uint8_t phase_increment); bool fpga_image_load(unsigned int index); -bool fpga_spi_selftest(); -bool fpga_sgpio_selftest(); -bool fpga_if_xcvr_selftest(); +bool fpga_spi_selftest(void); +bool fpga_sgpio_selftest(void); +bool fpga_if_xcvr_selftest(void); #endif // __FPGA_H diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index 287c6adc..c5162448 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -50,7 +50,7 @@ static int rx_samples(const unsigned int num_samples, uint32_t max_cycles) return rc; } -bool fpga_spi_selftest() +bool fpga_spi_selftest(void) { // Skip if FPGA configuration failed. if (selftest.fpga_image_load != PASSED) { @@ -81,7 +81,7 @@ static uint8_t lfsr_advance(uint8_t v) return (v << 1) | feedback; } -bool fpga_sgpio_selftest() +bool fpga_sgpio_selftest(void) { bool timeout = false; @@ -168,7 +168,7 @@ static bool in_range(int value, int expected, int error) return (value > min) && (value < max); } -bool fpga_if_xcvr_selftest() +bool fpga_if_xcvr_selftest(void) { bool timeout = false; diff --git a/firmware/common/gpdma.c b/firmware/common/gpdma.c index ac51f432..42ba78b4 100644 --- a/firmware/common/gpdma.c +++ b/firmware/common/gpdma.c @@ -24,7 +24,7 @@ #include -void gpdma_controller_enable() +void gpdma_controller_enable(void) { GPDMA_CONFIG |= GPDMA_CONFIG_E(1); while ((GPDMA_CONFIG & GPDMA_CONFIG_E_MASK) == 0) {} diff --git a/firmware/common/gpdma.h b/firmware/common/gpdma.h index e14b0c41..053f83a8 100644 --- a/firmware/common/gpdma.h +++ b/firmware/common/gpdma.h @@ -28,7 +28,7 @@ #include -void gpdma_controller_enable(); +void gpdma_controller_enable(void); void gpdma_channel_enable(const uint_fast8_t channel); void gpdma_channel_disable(const uint_fast8_t channel); diff --git a/firmware/common/gpio.h b/firmware/common/gpio.h index 868fc628..a492e62b 100644 --- a/firmware/common/gpio.h +++ b/firmware/common/gpio.h @@ -27,7 +27,7 @@ typedef const struct gpio_t* gpio_t; -void gpio_init(); +void gpio_init(void); void gpio_set(gpio_t gpio); void gpio_clear(gpio_t gpio); void gpio_toggle(gpio_t gpio); diff --git a/firmware/common/gpio_lpc.c b/firmware/common/gpio_lpc.c index d05b7fa8..7407cc39 100644 --- a/firmware/common/gpio_lpc.c +++ b/firmware/common/gpio_lpc.c @@ -24,7 +24,7 @@ #include -void gpio_init() +void gpio_init(void) { for (size_t i = 0; i < 8; i++) { GPIO_LPC_PORT(i)->dir = 0; diff --git a/firmware/common/ice40_spi.c b/firmware/common/ice40_spi.c index d3ac713c..25a3061f 100644 --- a/firmware/common/ice40_spi.c +++ b/firmware/common/ice40_spi.c @@ -54,17 +54,17 @@ void ice40_spi_write(ice40_spi_driver_t* const drv, uint8_t r, uint16_t v) spi_bus_transfer(drv->bus, value, 3); } -static void spi_ssp1_wait_for_tx_fifo_not_full() +static void spi_ssp1_wait_for_tx_fifo_not_full(void) { while ((SSP_SR(SSP1_BASE) & SSP_SR_TNF) == 0) {} } -static void spi_ssp1_wait_for_rx_fifo_not_empty() +static void spi_ssp1_wait_for_rx_fifo_not_empty(void) { while ((SSP_SR(SSP1_BASE) & SSP_SR_RNE) == 0) {} } -static void spi_ssp1_wait_for_not_busy() +static void spi_ssp1_wait_for_not_busy(void) { while (SSP_SR(SSP1_BASE) & SSP_SR_BSY) {} } diff --git a/firmware/common/m0_sleep.c b/firmware/common/m0_sleep.c index 722c6f10..09067bc6 100644 --- a/firmware/common/m0_sleep.c +++ b/firmware/common/m0_sleep.c @@ -20,7 +20,7 @@ * Boston, MA 02110-1301, USA. */ -int main() +int main(void) { while (1) {} } diff --git a/firmware/common/operacake_sctimer.c b/firmware/common/operacake_sctimer.c index fca5d03b..cecfb989 100644 --- a/firmware/common/operacake_sctimer.c +++ b/firmware/common/operacake_sctimer.c @@ -55,7 +55,7 @@ static uint32_t default_output = 0; * On Praline, instead, MS0/CLK1 (SCT_CLK) is configured to output its * clock (f=2 * sample clock) to the SCTimer. */ -void operacake_sctimer_init() +void operacake_sctimer_init(void) { // We start by resetting the SCTimer RESET_CTRL1 = RESET_CTRL1_SCT_RST; @@ -216,7 +216,7 @@ void operacake_sctimer_set_dwell_times(struct operacake_dwell_times* times, int SCT_CTRL &= ~SCT_CTRL_HALT_L(1); } -void operacake_sctimer_stop() +void operacake_sctimer_stop(void) { // Halt timer SCT_CTRL |= SCT_CTRL_HALT_L(1); @@ -228,7 +228,7 @@ void operacake_sctimer_stop() * called by set_transceiver_mode so the HackRF starts capturing with the * same antenna selected each time. */ -void operacake_sctimer_reset_state() +void operacake_sctimer_reset_state(void) { SCT_CTRL |= SCT_CTRL_HALT_L(1); diff --git a/firmware/common/operacake_sctimer.h b/firmware/common/operacake_sctimer.h index 6c5d0f61..805b3cf9 100644 --- a/firmware/common/operacake_sctimer.h +++ b/firmware/common/operacake_sctimer.h @@ -32,10 +32,10 @@ struct operacake_dwell_times { uint8_t port; }; -void operacake_sctimer_init(); +void operacake_sctimer_init(void); void operacake_sctimer_enable(bool enable); void operacake_sctimer_set_dwell_times(struct operacake_dwell_times* times, int n); -void operacake_sctimer_stop(); -void operacake_sctimer_reset_state(); +void operacake_sctimer_stop(void); +void operacake_sctimer_reset_state(void); #endif /* __OPERACAKE_SCTIMER_H */ diff --git a/firmware/common/portapack.c b/firmware/common/portapack.c index e123affa..7b84b432 100644 --- a/firmware/common/portapack.c +++ b/firmware/common/portapack.c @@ -70,7 +70,7 @@ static portapack_if_t portapack_if = { #define GPIO_DATA_SHIFT (8) static const uint32_t gpio_data_mask = 0xFFU << GPIO_DATA_SHIFT; -static void portapack_data_mask_set() +static void portapack_data_mask_set(void) { portapack_if.gpio_port_data->mask = ~gpio_data_mask; } @@ -87,13 +87,13 @@ static void portapack_data_write_high(const uint32_t value) portapack_if.gpio_port_data->mpin = value; } -static void portapack_dir_read() +static void portapack_dir_read(void) { portapack_if.gpio_port_data->dir &= ~gpio_data_mask; gpio_set(portapack_if.gpio_dir); } -static void portapack_dir_write() +static void portapack_dir_write(void) { gpio_clear(portapack_if.gpio_dir); portapack_if.gpio_port_data->dir |= gpio_data_mask; @@ -105,32 +105,32 @@ static void portapack_dir_write() */ } -__attribute__((unused)) static void portapack_lcd_rd_assert() +__attribute__((unused)) static void portapack_lcd_rd_assert(void) { gpio_clear(portapack_if.gpio_lcd_rdx); } -static void portapack_lcd_rd_deassert() +static void portapack_lcd_rd_deassert(void) { gpio_set(portapack_if.gpio_lcd_rdx); } -static void portapack_lcd_wr_assert() +static void portapack_lcd_wr_assert(void) { gpio_clear(portapack_if.gpio_lcd_wrx); } -static void portapack_lcd_wr_deassert() +static void portapack_lcd_wr_deassert(void) { gpio_set(portapack_if.gpio_lcd_wrx); } -static void portapack_io_stb_assert() +static void portapack_io_stb_assert(void) { gpio_clear(portapack_if.gpio_io_stbx); } -static void portapack_io_stb_deassert() +static void portapack_io_stb_deassert(void) { gpio_set(portapack_if.gpio_io_stbx); } @@ -188,7 +188,7 @@ static void portapack_io_write(const bool address, const uint_fast16_t value) portapack_io_stb_deassert(); } -static void portapack_if_init() +static void portapack_if_init(void) { portapack_data_mask_set(); portapack_data_write_high(0); @@ -242,7 +242,7 @@ static void portapack_lcd_data_write_command_and_data( } } -static void portapack_lcd_sleep_out() +static void portapack_lcd_sleep_out(void) { const uint8_t cmd_11[] = {}; portapack_lcd_data_write_command_and_data(0x11, cmd_11, ARRAY_SIZEOF(cmd_11)); @@ -252,13 +252,13 @@ static void portapack_lcd_sleep_out() portapack_sleep_milliseconds(120); } -static void portapack_lcd_display_on() +static void portapack_lcd_display_on(void) { const uint8_t cmd_29[] = {}; portapack_lcd_data_write_command_and_data(0x29, cmd_29, ARRAY_SIZEOF(cmd_29)); } -static void portapack_lcd_ramwr_start() +static void portapack_lcd_ramwr_start(void) { const uint8_t cmd_2c[] = {}; portapack_lcd_data_write_command_and_data(0x2c, cmd_2c, ARRAY_SIZEOF(cmd_2c)); @@ -306,13 +306,13 @@ static void portapack_lcd_write_pixels_color(const ui_color_t c, size_t n) } } -static void portapack_lcd_wake() +static void portapack_lcd_wake(void) { portapack_lcd_sleep_out(); portapack_lcd_display_on(); } -static void portapack_lcd_reset() +static void portapack_lcd_reset(void) { portapack_lcd_reset_state(false); portapack_sleep_milliseconds(1); @@ -322,7 +322,7 @@ static void portapack_lcd_reset() portapack_sleep_milliseconds(120); } -static void portapack_lcd_init() +static void portapack_lcd_init(void) { // LCDs are configured for IM[2:0] = 001 // 8080-I system, 16-bit parallel bus diff --git a/firmware/common/rad1o/decoder.c b/firmware/common/rad1o/decoder.c index 46791756..b5450194 100644 --- a/firmware/common/rad1o/decoder.c +++ b/firmware/common/rad1o/decoder.c @@ -12,7 +12,7 @@ static const uint8_t* data; static uint8_t charBuf[MAXCHR]; // Get next nibble -static uint8_t gnn() +static uint8_t gnn(void) { static uint8_t byte; uint8_t val; diff --git a/firmware/common/rad1o/display.c b/firmware/common/rad1o/display.c index 517db0a0..6e1cf198 100644 --- a/firmware/common/rad1o/display.c +++ b/firmware/common/rad1o/display.c @@ -30,7 +30,7 @@ static uint8_t lcdBuffer[RESX * RESY]; static bool isTurned; -static void select() +static void select(void) { /* * The LCD requires 9-Bit frames @@ -58,7 +58,7 @@ static void select() gpio_clear(&gpio_lcd_cs); } -static void deselect() +static void deselect(void) { gpio_set(&gpio_lcd_cs); } diff --git a/firmware/common/ui_portapack.c b/firmware/common/ui_portapack.c index 9918157c..3e8d3013 100644 --- a/firmware/common/ui_portapack.c +++ b/firmware/common/ui_portapack.c @@ -489,7 +489,7 @@ static void portapack_radio_path_item_update( static rf_path_direction_t portapack_direction = RF_PATH_DIRECTION_OFF; static bool portapack_lna_on = false; -static void portapack_radio_path_redraw() +static void portapack_radio_path_redraw(void) { for (size_t i = 0; i < ARRAY_SIZEOF(radio_draw_list); i++) { portapack_draw_radio_path_item(i); @@ -736,7 +736,7 @@ const hackrf_ui_t portapack_hackrf_ui = { &portapack_ui_operacake_gpio_compatible, }; -const hackrf_ui_t* portapack_hackrf_ui_init() +const hackrf_ui_t* portapack_hackrf_ui_init(void) { if (portapack()) { return &portapack_hackrf_ui; diff --git a/firmware/common/ui_portapack.h b/firmware/common/ui_portapack.h index d712c895..0565cf6a 100644 --- a/firmware/common/ui_portapack.h +++ b/firmware/common/ui_portapack.h @@ -25,6 +25,6 @@ #include "hackrf_ui.h" -const hackrf_ui_t* portapack_hackrf_ui_init() __attribute__((weak)); +const hackrf_ui_t* portapack_hackrf_ui_init(void) __attribute__((weak)); #endif /*__UI_PORTAPACK_H__*/ diff --git a/firmware/common/usb.c b/firmware/common/usb.c index 9188da73..85795ec9 100644 --- a/firmware/common/usb.c +++ b/firmware/common/usb.c @@ -67,7 +67,7 @@ static uint_fast8_t usb_endpoint_number(const uint_fast8_t endpoint_address) return (endpoint_address & 0xF); } -void usb_peripheral_reset() +void usb_peripheral_reset(void) { RESET_CTRL0 = RESET_CTRL0_USB0_RST; RESET_CTRL0 = 0; @@ -75,7 +75,7 @@ void usb_peripheral_reset() while ((RESET_ACTIVE_STATUS0 & RESET_CTRL0_USB0_RST) == 0) {} } -void usb_phy_enable() +void usb_phy_enable(void) { CREG_CREG0 &= ~CREG_CREG0_USB0PHY; } @@ -634,7 +634,7 @@ static void usb_check_for_transfer_events(void) } } -void usb0_isr() +void usb0_isr(void) { const uint32_t status = usb_get_status(); diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 0b5d303a..5206541a 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -239,7 +239,7 @@ static bool cpld_jtag_sram_load(jtag_t* const jtag) } #endif -static void m0_rom_to_ram() +static void m0_rom_to_ram(void) { uint32_t* dest = &__ram_m0_start__; From 2ffcc908fbc7c232a514c681fa2a7a644fe97a7e Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 6 Feb 2026 16:49:28 +0000 Subject: [PATCH 008/238] Enable -Wstrict-prototypes warnings. --- firmware/hackrf-common.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 788f66c0..f5cb1bf4 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -92,7 +92,7 @@ SET(LDSCRIPT_M4_RAM "-T${PATH_HACKRF_FIRMWARE_COMMON}/${MCU_PARTNO}_M4_memory.ld SET(LDSCRIPT_M0 "-T${PATH_HACKRF_FIRMWARE_COMMON}/LPC43xx_M0_memory.ld -Tlibopencm3_lpc43xx_m0.ld") -SET(CFLAGS_COMMON "-Os -g3 -Wall -Wextra ${HACKRF_OPTS} -fno-common -MD") +SET(CFLAGS_COMMON "-Os -g3 -Wall -Wextra -Wstrict-prototypes ${HACKRF_OPTS} -fno-common -MD") SET(LDFLAGS_COMMON "-nostartfiles -Wl,--gc-sections") if(V STREQUAL "1") From afb6d1372f438b8c2970f5b1aa26b61c3d41a585 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 6 Feb 2026 17:54:50 +0000 Subject: [PATCH 009/238] Move delay functions out of hackrf_core. --- firmware/blinky/blinky.c | 1 + firmware/common/delay.c | 42 +++++++++++++++++++++++++++++ firmware/common/delay.h | 34 +++++++++++++++++++++++ firmware/common/fpga_selftest.c | 1 + firmware/common/hackrf_core.c | 21 +-------------- firmware/common/hackrf_core.h | 3 --- firmware/common/ice40_spi.c | 1 + firmware/common/operacake_sctimer.c | 1 + firmware/common/platform_detect.c | 1 + firmware/common/portapack.c | 1 + firmware/common/rad1o/display.c | 1 + firmware/common/rffc5071.c | 1 + firmware/hackrf-common.cmake | 1 + firmware/hackrf_usb/hackrf_usb.c | 1 + 14 files changed, 87 insertions(+), 23 deletions(-) create mode 100644 firmware/common/delay.c create mode 100644 firmware/common/delay.h diff --git a/firmware/blinky/blinky.c b/firmware/blinky/blinky.c index 95b1173e..6d071c97 100644 --- a/firmware/blinky/blinky.c +++ b/firmware/blinky/blinky.c @@ -21,6 +21,7 @@ #include "hackrf_core.h" #include "platform_detect.h" +#include "delay.h" int main(void) { diff --git a/firmware/common/delay.c b/firmware/common/delay.c new file mode 100644 index 00000000..8d2045ed --- /dev/null +++ b/firmware/common/delay.c @@ -0,0 +1,42 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "delay.h" + +void delay(uint32_t duration) +{ + uint32_t i; + + for (i = 0; i < duration; i++) { + __asm__("nop"); + } +} + +void delay_us_at_mhz(uint32_t us, uint32_t mhz) +{ + // The loop below takes 3 cycles per iteration. + uint32_t loop_iterations = (us * mhz) / 3; + asm volatile("start%=:\n" + " subs %[ITERATIONS], #1\n" // 1 cycle + " bpl start%=\n" // 2 cycles + : + : [ITERATIONS] "r"(loop_iterations)); +} diff --git a/firmware/common/delay.h b/firmware/common/delay.h new file mode 100644 index 00000000..123141ba --- /dev/null +++ b/firmware/common/delay.h @@ -0,0 +1,34 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __DELAY_H +#define __DELAY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void delay(uint32_t duration); +void delay_us_at_mhz(uint32_t us, uint32_t mhz); + +#endif /* __DELAY_H */ diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index 287c6adc..fd63ea77 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -24,6 +24,7 @@ #include "streaming.h" #include "selftest.h" #include "fpga.h" +#include "delay.h" // USB buffer used during selftests. #define USB_BULK_BUFFER_SIZE 0x8000 diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 5d59da00..0a420536 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -23,6 +23,7 @@ #include "hackrf_core.h" #include "hackrf_ui.h" +#include "delay.h" #include "sgpio.h" #include "si5351c.h" #include "spi_ssp.h" @@ -441,26 +442,6 @@ jtag_t jtag_cpld = { .gpio = &jtag_gpio_cpld, }; -void delay(uint32_t duration) -{ - uint32_t i; - - for (i = 0; i < duration; i++) { - __asm__("nop"); - } -} - -void delay_us_at_mhz(uint32_t us, uint32_t mhz) -{ - // The loop below takes 3 cycles per iteration. - uint32_t loop_iterations = (us * mhz) / 3; - asm volatile("start%=:\n" - " subs %[ITERATIONS], #1\n" // 1 cycle - " bpl start%=\n" // 2 cycles - : - : [ITERATIONS] "r"(loop_iterations)); -} - /* GCD algo from wikipedia */ /* http://en.wikipedia.org/wiki/Greatest_common_divisor */ static uint32_t gcd(uint32_t u, uint32_t v) diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 301cb7aa..6bc8e909 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -389,9 +389,6 @@ extern "C" { #define SCU_H1R9_NO_VAA_EN (P6_10) /* GPIO3[6] on P6_10 */ #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); - /* TODO: Hide these configurations */ extern si5351c_driver_t clock_gen; extern const ssp_config_t ssp_config_w25q80bv; diff --git a/firmware/common/ice40_spi.c b/firmware/common/ice40_spi.c index d3ac713c..1bc38261 100644 --- a/firmware/common/ice40_spi.c +++ b/firmware/common/ice40_spi.c @@ -23,6 +23,7 @@ #include #include "hackrf_core.h" +#include "delay.h" void ice40_spi_target_init(ice40_spi_driver_t* const drv) { diff --git a/firmware/common/operacake_sctimer.c b/firmware/common/operacake_sctimer.c index fca5d03b..1b297cbd 100644 --- a/firmware/common/operacake_sctimer.c +++ b/firmware/common/operacake_sctimer.c @@ -29,6 +29,7 @@ #include #include #include "sct.h" +#include "delay.h" #define U1CTRL_SET SCT_OUT14_SET #define U1CTRL_CLR SCT_OUT14_CLR diff --git a/firmware/common/platform_detect.c b/firmware/common/platform_detect.c index ec00a3b8..199878d8 100644 --- a/firmware/common/platform_detect.c +++ b/firmware/common/platform_detect.c @@ -23,6 +23,7 @@ #include "firmware_info.h" #include "gpio_lpc.h" #include "hackrf_core.h" +#include "delay.h" #include "adc.h" #include diff --git a/firmware/common/portapack.c b/firmware/common/portapack.c index e123affa..035d95f0 100644 --- a/firmware/common/portapack.c +++ b/firmware/common/portapack.c @@ -24,6 +24,7 @@ #include "hackrf_core.h" #include "gpio_lpc.h" +#include "delay.h" #include diff --git a/firmware/common/rad1o/display.c b/firmware/common/rad1o/display.c index 517db0a0..b8e512b9 100644 --- a/firmware/common/rad1o/display.c +++ b/firmware/common/rad1o/display.c @@ -2,6 +2,7 @@ #include "gpio_lpc.h" #include "hackrf_core.h" +#include "delay.h" #include #include diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 541dde2a..959fbc27 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -39,6 +39,7 @@ #include #include "hackrf_core.h" +#include "delay.h" /* Default register values from vendor documentation or software. */ static const uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = { diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 788f66c0..70cc9fe8 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -168,6 +168,7 @@ endmacro() macro(DeclareTargets) SET(SRC_M4 ${SRC_M4} + ${PATH_HACKRF_FIRMWARE_COMMON}/delay.c ${PATH_HACKRF_FIRMWARE_COMMON}/hackrf_core.c ${PATH_HACKRF_FIRMWARE_COMMON}/sgpio.c ${PATH_HACKRF_FIRMWARE_COMMON}/rf_path.c diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 0b5d303a..718e3bb9 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -62,6 +62,7 @@ #include "clkin.h" #include "fpga.h" #include "selftest.h" +#include "delay.h" extern uint32_t __m0_start__; extern uint32_t __m0_end__; From 84aed3a67ce7e514dcbaa536e6c3aa70b825e3e5 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 6 Feb 2026 20:58:00 +0000 Subject: [PATCH 010/238] Add -Wold-style-definition to compiler flags. --- firmware/hackrf-common.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index f5cb1bf4..5e4de182 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -92,7 +92,7 @@ SET(LDSCRIPT_M4_RAM "-T${PATH_HACKRF_FIRMWARE_COMMON}/${MCU_PARTNO}_M4_memory.ld SET(LDSCRIPT_M0 "-T${PATH_HACKRF_FIRMWARE_COMMON}/LPC43xx_M0_memory.ld -Tlibopencm3_lpc43xx_m0.ld") -SET(CFLAGS_COMMON "-Os -g3 -Wall -Wextra -Wstrict-prototypes ${HACKRF_OPTS} -fno-common -MD") +SET(CFLAGS_COMMON "-Os -g3 -Wall -Wextra -Wstrict-prototypes -Wold-style-definition ${HACKRF_OPTS} -fno-common -MD") SET(LDFLAGS_COMMON "-nostartfiles -Wl,--gc-sections") if(V STREQUAL "1") From a246f9a35a0e602d3b6470aa71a257eddd7470e1 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 6 Feb 2026 21:22:03 +0000 Subject: [PATCH 011/238] Add 'nonstring' attribute to firmware_info magic field. Fixes compiler warnings such as: firmware_info.c:49:18: warning: initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute (9 chars into 8 available) [-Wunterminated-string-initialization] 49 | .magic = "HACKRFFW", | ^~~~~~~~~~ --- firmware/common/firmware_info.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/firmware_info.h b/firmware/common/firmware_info.h index 99706dfb..fb087008 100644 --- a/firmware/common/firmware_info.h +++ b/firmware/common/firmware_info.h @@ -25,7 +25,7 @@ #include struct firmware_info_t { - char magic[8]; + __attribute__((nonstring)) char magic[8]; uint16_t struct_version; uint16_t dfu_mode; uint32_t supported_platform; From 3ef784b83027beb22779375f730d188407859dc7 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 6 Feb 2026 17:59:25 +0000 Subject: [PATCH 012/238] Add delay loop implementation for M0 core. --- firmware/common/delay.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/firmware/common/delay.c b/firmware/common/delay.c index 8d2045ed..ceb7693e 100644 --- a/firmware/common/delay.c +++ b/firmware/common/delay.c @@ -32,6 +32,7 @@ void delay(uint32_t duration) void delay_us_at_mhz(uint32_t us, uint32_t mhz) { +#if defined(LPC43XX_M4) // The loop below takes 3 cycles per iteration. uint32_t loop_iterations = (us * mhz) / 3; asm volatile("start%=:\n" @@ -39,4 +40,15 @@ void delay_us_at_mhz(uint32_t us, uint32_t mhz) " bpl start%=\n" // 2 cycles : : [ITERATIONS] "r"(loop_iterations)); +#elif defined(LPC43XX_M0) + // The loop below takes 4 cycles per iteration. + uint32_t loop_iterations = (us * mhz) / 4; + asm volatile("start%=:\n" + " sub %[ITERATIONS], #1\n" // 1 cycle + " bpl start%=\n" // 3 cycles + : + : [ITERATIONS] "r"(loop_iterations)); +#else + #error "No delay loop implementation" +#endif } From bce1b871c6cd134563a74325193044f4205aaff4 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 9 Feb 2026 19:08:06 +0000 Subject: [PATCH 013/238] Update libopencm3 for recent compiler warning fixes. --- firmware/libopencm3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/libopencm3 b/firmware/libopencm3 index cfc2f345..a0bb9979 160000 --- a/firmware/libopencm3 +++ b/firmware/libopencm3 @@ -1 +1 @@ -Subproject commit cfc2f3451486f6f05cc5e05ff6b5308269980fe3 +Subproject commit a0bb997968bf57c87f2aa4e389a63219580bb5c3 From cc63a764ab67cf5f06d74460e3cddd0aa06ae478 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 11 Feb 2026 19:13:32 +0000 Subject: [PATCH 014/238] Don't allocate large LZ4 buffers on stack; use some dedicated RAM. (#1670) --- firmware/common/LPC43xx_M0_memory.ld | 2 +- firmware/common/LPC43xx_M4_memory.ld | 17 ++++++++++---- firmware/common/fpga_image.c | 18 ++++++++------ firmware/common/ice40_spi.c | 6 ++--- firmware/common/lz4_buf.h | 35 ++++++++++++++++++++++++++++ 5 files changed, 62 insertions(+), 16 deletions(-) create mode 100644 firmware/common/lz4_buf.h diff --git a/firmware/common/LPC43xx_M0_memory.ld b/firmware/common/LPC43xx_M0_memory.ld index cbf04d5e..5a873132 100644 --- a/firmware/common/LPC43xx_M0_memory.ld +++ b/firmware/common/LPC43xx_M0_memory.ld @@ -22,5 +22,5 @@ MEMORY { - ram (rwx) : ORIGIN = 0x00000000, LENGTH = 28K + ram (rwx) : ORIGIN = 0x00000000, LENGTH = 20K } diff --git a/firmware/common/LPC43xx_M4_memory.ld b/firmware/common/LPC43xx_M4_memory.ld index b49e8cb9..933fa854 100644 --- a/firmware/common/LPC43xx_M4_memory.ld +++ b/firmware/common/LPC43xx_M4_memory.ld @@ -23,16 +23,23 @@ MEMORY { /* Physical address in Flash used to copy Code from Flash to RAM */ - rom_flash (rx) : ORIGIN = 0x80000000, LENGTH = 1M - ram_m0 (rwx) : ORIGIN = 0x20000000, LENGTH = 28K - ram_shared (rwx) : ORIGIN = 0x20007000, LENGTH = 4K - ram_usb (rwx) : ORIGIN = 0x20008000, LENGTH = 32K - /* ram_usb: USB buffer. Straddles two blocks of RAM + rom_flash (rx) : ORIGIN = 0x80000000, LENGTH = 1M + /* Buffers for LZ4 decompression */ + ram_lz4_in (rwx) : ORIGIN = 0x20000000, LENGTH = 4K + ram_lz4_out (rwx) : ORIGIN = 0x20001000, LENGTH = 4K + /* RAM for M0 code */ + ram_m0 (rwx) : ORIGIN = 0x20002000, LENGTH = 20K + /* RAM shared between M0 and M4 */ + ram_shared (rwx) : ORIGIN = 0x20007000, LENGTH = 4K + /* USB buffer. Straddles two blocks of RAM * to get performance benefit of having two USB buffers addressable * simultaneously (on two different buses of the AHB multilayer matrix) */ + ram_usb (rwx) : ORIGIN = 0x20008000, LENGTH = 32K } usb_bulk_buffer = ORIGIN(ram_usb); +lz4_in_buf = ORIGIN(ram_lz4_in); +lz4_out_buf = ORIGIN(ram_lz4_out); m0_state = ORIGIN(ram_shared); PROVIDE(__ram_m0_start__ = ORIGIN(ram_m0)); diff --git a/firmware/common/fpga_image.c b/firmware/common/fpga_image.c index ddac8595..a70906b8 100644 --- a/firmware/common/fpga_image.c +++ b/firmware/common/fpga_image.c @@ -21,6 +21,7 @@ #include "hackrf_core.h" #include "lz4_blk.h" +#include "lz4_buf.h" #include "selftest.h" // FPGA bitstreams blob. @@ -32,7 +33,6 @@ struct fpga_image_read_ctx { uint32_t addr; size_t next_block_sz; uint8_t init_flag; - uint8_t buffer[4096 + 2]; }; static size_t fpga_image_read_block_cb(void* _ctx, uint8_t* out_buffer) @@ -41,10 +41,12 @@ static size_t fpga_image_read_block_cb(void* _ctx, uint8_t* out_buffer) struct fpga_image_read_ctx* ctx = _ctx; size_t block_sz = ctx->next_block_sz; + uint8_t block_sz_buf[2]; + // first iteration: read first block size if (ctx->init_flag == 0) { - w25q80bv_read(&spi_flash, ctx->addr, 2, ctx->buffer); - block_sz = ctx->buffer[0] | (ctx->buffer[1] << 8); + w25q80bv_read(&spi_flash, ctx->addr, 2, block_sz_buf); + block_sz = block_sz_buf[0] | block_sz_buf[1] << 8; ctx->addr += 2; ctx->init_flag = 1; } @@ -54,12 +56,14 @@ static size_t fpga_image_read_block_cb(void* _ctx, uint8_t* out_buffer) return 0; // Read compressed block (and the next block size) from flash. - w25q80bv_read(&spi_flash, ctx->addr, block_sz + 2, ctx->buffer); - ctx->addr += block_sz + 2; - ctx->next_block_sz = ctx->buffer[block_sz] | (ctx->buffer[block_sz + 1] << 8); + w25q80bv_read(&spi_flash, ctx->addr, block_sz, lz4_in_buf); + ctx->addr += block_sz; + w25q80bv_read(&spi_flash, ctx->addr, 2, block_sz_buf); + ctx->next_block_sz = block_sz_buf[0] | block_sz_buf[1] << 8; + ctx->addr += 2; // Decompress block. - return lz4_blk_decompress(ctx->buffer, out_buffer, block_sz); + return lz4_blk_decompress(lz4_in_buf, out_buffer, block_sz); } bool fpga_image_load(unsigned int index) diff --git a/firmware/common/ice40_spi.c b/firmware/common/ice40_spi.c index 241d9cd9..344bb0e6 100644 --- a/firmware/common/ice40_spi.c +++ b/firmware/common/ice40_spi.c @@ -23,6 +23,7 @@ #include #include "hackrf_core.h" +#include "lz4_buf.h" #include "delay.h" void ice40_spi_target_init(ice40_spi_driver_t* const drv) @@ -104,14 +105,13 @@ bool ice40_spi_syscfg_program( // Send configuration image serially on SPI_SI to iCE40, most-significant bit // first, on falling edge of SPI_SCK. - uint8_t out_buffer[4096] = {0}; gpio_clear(drv->gpio_select); for (;;) { - size_t read_sz = read_block_cb(read_ctx, out_buffer); + size_t read_sz = read_block_cb(read_ctx, lz4_out_buf); if (read_sz == 0) break; for (size_t j = 0; j < read_sz; j++) { - spi_ssp1_transfer_word(out_buffer[j]); + spi_ssp1_transfer_word(lz4_out_buf[j]); } } diff --git a/firmware/common/lz4_buf.h b/firmware/common/lz4_buf.h new file mode 100644 index 00000000..b9dec589 --- /dev/null +++ b/firmware/common/lz4_buf.h @@ -0,0 +1,35 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __LZ4_BUF_H +#define __LZ4_BUF_H + +#include + +#define LZ4_BUFFER_SIZE 0x1000 + +/* Addresses of these buffers are set in linker script. If you change the name + * of these buffers, you must also adjust the linker script. */ + +extern uint8_t lz4_in_buf[LZ4_BUFFER_SIZE]; +extern uint8_t lz4_out_buf[LZ4_BUFFER_SIZE]; + +#endif /*__LZ4_BUF_H */ From 8d1b1a5f9aa34b226b262824a2c03e8ac1e9721f Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 19 Feb 2026 00:02:56 +0000 Subject: [PATCH 015/238] Rename gpio.not to gpio.inv to avoid conflict with C++ keyword. --- firmware/common/gpio_lpc.c | 2 +- firmware/common/gpio_lpc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/common/gpio_lpc.c b/firmware/common/gpio_lpc.c index 7407cc39..6e639d8d 100644 --- a/firmware/common/gpio_lpc.c +++ b/firmware/common/gpio_lpc.c @@ -43,7 +43,7 @@ void gpio_clear(gpio_t gpio) void gpio_toggle(gpio_t gpio) { - gpio->port->not = gpio->mask; + gpio->port->inv = gpio->mask; } void gpio_output(gpio_t gpio) diff --git a/firmware/common/gpio_lpc.h b/firmware/common/gpio_lpc.h index f51ffd2b..ed181651 100644 --- a/firmware/common/gpio_lpc.h +++ b/firmware/common/gpio_lpc.h @@ -45,7 +45,7 @@ typedef struct gpio_port_t { uint32_t _reserved4[31]; volatile uint32_t clr; /* +0x280 */ uint32_t _reserved5[31]; - volatile uint32_t not ; /* +0x300 */ + volatile uint32_t inv; /* +0x300 */ } gpio_port_t; struct gpio_t { From 19d00fb5f991689f29c29c7f9cfeb75e425479c3 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sat, 24 Jan 2026 11:38:20 -0500 Subject: [PATCH 016/238] Remove full-duplex support for RFFC5071 This eliminates unnecessary disable/enable cycles for our half-duplex RFFC5072. --- firmware/common/mixer.c | 30 ------------------------------ firmware/common/mixer.h | 5 ----- firmware/common/rf_path.c | 4 +--- firmware/common/rffc5071.c | 33 ++++----------------------------- firmware/common/rffc5071.h | 5 ----- 5 files changed, 5 insertions(+), 72 deletions(-) diff --git a/firmware/common/mixer.c b/firmware/common/mixer.c index e9c512fe..e29869c6 100644 --- a/firmware/common/mixer.c +++ b/firmware/common/mixer.c @@ -115,36 +115,6 @@ uint64_t mixer_set_frequency(mixer_driver_t* const mixer, uint64_t hz) #endif } -void mixer_tx(mixer_driver_t* const mixer) -{ -#if (defined JAWBREAKER || defined HACKRF_ONE || defined PRALINE) - rffc5071_tx(mixer); -#endif -#ifdef RAD1O - (void) mixer; -#endif -} - -void mixer_rx(mixer_driver_t* const mixer) -{ -#if (defined JAWBREAKER || defined HACKRF_ONE || defined PRALINE) - rffc5071_rx(mixer); -#endif -#ifdef RAD1O - (void) mixer; -#endif -} - -void mixer_rxtx(mixer_driver_t* const mixer) -{ -#if (defined JAWBREAKER || defined HACKRF_ONE || defined PRALINE) - rffc5071_rxtx(mixer); -#endif -#ifdef RAD1O - (void) mixer; -#endif -} - void mixer_enable(mixer_driver_t* const mixer) { #if (defined JAWBREAKER || defined HACKRF_ONE || defined PRALINE) diff --git a/firmware/common/mixer.h b/firmware/common/mixer.h index fc732275..06ca88f5 100644 --- a/firmware/common/mixer.h +++ b/firmware/common/mixer.h @@ -40,11 +40,6 @@ extern void mixer_setup(mixer_driver_t* const mixer); /* Set frequency (Hz). */ extern uint64_t mixer_set_frequency(mixer_driver_t* const mixer, uint64_t hz); -/* Set up rx only, tx only, or full duplex. Chip should be disabled - * before _tx, _rx, or _rxtx are called. */ -extern void mixer_tx(mixer_driver_t* const mixer); -extern void mixer_rx(mixer_driver_t* const mixer); -extern void mixer_rxtx(mixer_driver_t* const mixer); extern void mixer_enable(mixer_driver_t* const mixer); extern void mixer_disable(mixer_driver_t* const mixer); extern void mixer_set_gpo(mixer_driver_t* const drv, uint8_t gpo); diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 5f41ec0c..463942ca 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -477,7 +477,6 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d /* TX amplifier is in path, be sure to enable TX amplifier. */ rf_path->switchctrl &= ~SWITCHCTRL_NO_TX_AMP_PWR; } - mixer_tx(&mixer); if (rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS) { mixer_disable(&mixer); } else { @@ -500,7 +499,6 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d /* RX amplifier is in path, be sure to enable RX amplifier. */ rf_path->switchctrl &= ~SWITCHCTRL_NO_RX_AMP_PWR; } - mixer_rx(&mixer); if (rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS) { mixer_disable(&mixer); } else { @@ -620,4 +618,4 @@ void rf_path_set_antenna(rf_path_t* const rf_path, const uint_fast8_t enable) switchctrl_set(rf_path, rf_path->switchctrl); hackrf_ui()->set_antenna_bias(enable); -} \ No newline at end of file +} diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 959fbc27..6680b5c5 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -118,6 +118,10 @@ void rffc5071_setup(rffc5071_driver_t* const drv) /* GPOs are active at all times */ set_RFFC5071_GATE(drv, 1); + /* mixer 2 used for both RX and TX */ + set_RFFC5071_FULLD(drv, 0); + set_RFFC5071_MODE(drv, 1); + #if defined(PRALINE) || defined(HACKRF_ONE) /* Enable GPO Lock output signal */ set_RFFC5071_LOCK(drv, 1); @@ -223,35 +227,6 @@ void rffc5071_regs_commit(rffc5071_driver_t* const drv) } } -void rffc5071_tx(rffc5071_driver_t* const drv) -{ - set_RFFC5071_ENBL(drv, 0); - set_RFFC5071_FULLD(drv, 0); - set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */ - rffc5071_regs_commit(drv); -} - -void rffc5071_rx(rffc5071_driver_t* const drv) -{ - set_RFFC5071_ENBL(drv, 0); - set_RFFC5071_FULLD(drv, 0); - set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */ - rffc5071_regs_commit(drv); -} - -/* - * This function turns on both mixer (full-duplex) on the RFFC5071, but our - * current hardware designs do not support full-duplex operation. - */ -void rffc5071_rxtx(rffc5071_driver_t* const drv) -{ - set_RFFC5071_ENBL(drv, 0); - set_RFFC5071_FULLD(drv, 1); /* mixer 1 and mixer 2 (RXTX) */ - rffc5071_regs_commit(drv); - - rffc5071_enable(drv); -} - void rffc5071_disable(rffc5071_driver_t* const drv) { set_RFFC5071_ENBL(drv, 0); diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index 164f6324..f191b98d 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -62,11 +62,6 @@ extern void rffc5071_regs_commit(rffc5071_driver_t* const drv); /* Set frequency (Hz). */ extern uint64_t rffc5071_set_frequency(rffc5071_driver_t* const drv, uint64_t hz); -/* Set up rx only, tx only, or full duplex. Chip should be disabled - * before _tx, _rx, or _rxtx are called. */ -extern void rffc5071_tx(rffc5071_driver_t* const drv); -extern void rffc5071_rx(rffc5071_driver_t* const drv); -extern void rffc5071_rxtx(rffc5071_driver_t* const drv); extern void rffc5071_enable(rffc5071_driver_t* const drv); extern void rffc5071_disable(rffc5071_driver_t* const drv); From 72a96a77f878db3bf09949bf16d07266623ca6f8 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 13 Jan 2026 19:28:42 -0500 Subject: [PATCH 017/238] Call a sample rate a sample rate Previously we used "sample rate" to mean a rate that is twice the sample rate in several places in firmware. --- firmware/common/fpga_selftest.c | 4 ++-- firmware/common/hackrf_core.c | 12 +++++++++++- firmware/common/radio.c | 8 ++++---- firmware/hackrf_usb/usb_api_transceiver.c | 2 +- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index 3abd43e5..f3bb01c1 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -190,7 +190,7 @@ bool fpga_if_xcvr_selftest(void) max2831_set_frequency(&max283x, 2500000000); // Capture 1: 4 Msps, tone at 0.5 MHz, narrowband filter OFF - sample_rate_frac_set(4000000 * 2, 1); + sample_rate_frac_set(4000000, 1); delay_us_at_mhz(1000, 204); if (rx_samples(num_samples, 2000000) == -1) { timeout = true; @@ -213,7 +213,7 @@ bool fpga_if_xcvr_selftest(void) // Capture 3: 20 Msps, tone at 5 MHz, narrowband filter OFF fpga_set_tx_nco_pstep(&fpga, 255); - sample_rate_frac_set(20000000 * 2, 1); + sample_rate_frac_set(20000000, 1); narrowband_filter_set(0); delay_us_at_mhz(1000, 204); if (rx_samples(num_samples, 2000000) == -1) { diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 0a420536..1a0f0454 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -486,7 +486,17 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom) uint32_t a, b, c; uint32_t rem; - hackrf_ui()->set_sample_rate(rate_num / 2); + /* Round to the nearest Hz for display. */ + uint32_t rate_hz = (rate_num + (rate_denom >> 1)) / rate_denom; + hackrf_ui()->set_sample_rate(rate_hz); + + /* + * First double the sample rate so that we can produce a clock at twice + * the intended sample rate. The 2x clock is sometimes used directly, + * and it is divided by two in an output divider to produce the actual + * AFE clock. + */ + rate_num *= 2; /* Find best config */ a = (VCO_FREQ * rate_denom) / rate_num; diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 29aba95c..d7eeffb6 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -59,7 +59,7 @@ radio_error_t radio_set_sample_rate( if ((config->mode == TRANSCEIVER_MODE_RX) || (config->mode == TRANSCEIVER_MODE_RX_SWEEP)) { n = 1; - uint32_t afe_rate_x2 = 2 * sample_rate.hz; + uint32_t afe_rate_x2 = 4 * sample_rate.hz; while ((afe_rate_x2 <= MAX_AFE_RATE) && (n < MAX_N)) { afe_rate_x2 <<= 1; n++; @@ -120,12 +120,12 @@ radio_error_t radio_set_filter( max283x_set_lpf_bandwidth(&max283x, filter.hz); #else uint32_t lpf_bandwidth = - (config->sample_rate[RADIO_SAMPLE_RATE_CLOCKGEN].hz * 3) / 8; + (config->sample_rate[RADIO_SAMPLE_RATE_CLOCKGEN].hz * 3) / 4; 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; + 4; } lpf_bandwidth += offset * 2; max2831_set_lpf_bandwidth(&max283x, lpf_bandwidth); @@ -306,7 +306,7 @@ radio_error_t radio_set_frequency( config->shift = tune_config->shift; uint32_t offset = (config->sample_rate[RADIO_SAMPLE_RATE_CLOCKGEN].hz << config->resampling_n) / - 8; + 4; ok = tuning_set_frequency(tune_config, frequency.hz, offset); if (ok) { radio_channel_t* channel = &radio->channel[chan_id]; diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index cbc8e293..d72e57a1 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -177,7 +177,7 @@ usb_request_status_t usb_vendor_request_set_sample_rate_frac( RADIO_CHANNEL0, RADIO_SAMPLE_RATE_CLOCKGEN, (radio_sample_rate_t){ - .num = set_sample_r_params.freq_hz * 2, + .num = set_sample_r_params.freq_hz, .div = set_sample_r_params.divider, }); if (result == RADIO_OK) { From d60ebc2781ec0a67cac42e758e769b349c85afed Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 13 Jan 2026 18:54:10 -0500 Subject: [PATCH 018/238] Add clock generator power supply start-up comments --- firmware/hackrf_usb/hackrf_usb.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 7f0f495e..f8c55016 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -272,6 +272,11 @@ int main(void) #ifndef PRALINE enable_1v8_power(); #ifndef RAD1O + /* + * On rad1o, the clock generator power supply comes from the RF supply + * which is enabled later. On H1 and Jawbreaker, the clock generator is + * on the main 3V3 supply. + */ clock_gen_init(); #endif #else @@ -279,6 +284,10 @@ int main(void) #if !defined(DFU_MODE) && !defined(RAM_MODE) enable_1v2_power(); enable_rf_power(); + /* + * On Praline, the clock generator power supply comes from 3V3FPGA + * which is enabled when 1V2FPGA is turned on. + */ clock_gen_init(); #endif #endif From aaad548b0beacc6f7ba73ab4f1393ba199a551cf Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 10 Feb 2026 07:04:09 -0500 Subject: [PATCH 019/238] Track RFFC5071 enabled state Re-lock PLL when re-tuning while enabled --- firmware/common/rffc5071.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 6680b5c5..73ab70cd 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -41,6 +41,8 @@ #include "hackrf_core.h" #include "delay.h" +static bool enabled = false; + /* Default register values from vendor documentation or software. */ static const uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = { 0xfffb, /* 00 */ @@ -146,6 +148,7 @@ void rffc5071_lock_test(rffc5071_driver_t* const drv) for (int i = 0; i < NUM_LOCK_ATTEMPTS; i++) { // Tune to 100MHz. rffc5071_set_frequency(drv, 100000000); + rffc5071_enable(drv); // Wait 1ms. delay_us_at_mhz(1000, 204); @@ -153,6 +156,9 @@ void rffc5071_lock_test(rffc5071_driver_t* const drv) // Check for lock. lock = rffc5071_check_lock(drv); + rffc5071_disable(drv); + delay_us_at_mhz(100, 204); + selftest.mixer_locks[i] = lock; } @@ -229,14 +235,20 @@ void rffc5071_regs_commit(rffc5071_driver_t* const drv) void rffc5071_disable(rffc5071_driver_t* const drv) { - set_RFFC5071_ENBL(drv, 0); - rffc5071_regs_commit(drv); + if (enabled) { + set_RFFC5071_ENBL(drv, 0); + rffc5071_regs_commit(drv); + enabled = false; + } } void rffc5071_enable(rffc5071_driver_t* const drv) { - set_RFFC5071_ENBL(drv, 1); - rffc5071_regs_commit(drv); + if (!enabled) { + set_RFFC5071_ENBL(drv, 1); + rffc5071_regs_commit(drv); + enabled = true; + } } #define FREQ_ONE_MHZ (1000ULL * 1000ULL) @@ -308,9 +320,11 @@ uint64_t rffc5071_set_frequency(rffc5071_driver_t* const drv, uint64_t hz) { uint32_t tune_freq; - rffc5071_disable(drv); tune_freq = rffc5071_config_synth(drv, hz); - rffc5071_enable(drv); + if (enabled) { + set_RFFC5071_RELOK(drv, 1); + rffc5071_regs_commit(drv); + } return tune_freq; } From 547a851fbafdd555ce2451b63462192966fa2c3e Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Fri, 20 Feb 2026 11:28:56 -0500 Subject: [PATCH 020/238] Store radio configuration in register banks --- firmware/common/hackrf_core.c | 38 +- firmware/common/radio.c | 1184 ++++++++++++--------- firmware/common/radio.h | 369 ++++--- firmware/hackrf_usb/hackrf_usb.c | 3 +- firmware/hackrf_usb/usb_api_sweep.c | 14 +- firmware/hackrf_usb/usb_api_transceiver.c | 228 ++-- 6 files changed, 984 insertions(+), 852 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 1a0f0454..5509b9b1 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Jared Boone * Copyright 2013 Benjamin Vernoux * @@ -351,40 +351,7 @@ fpga_driver_t fpga = { }; #endif -radio_t radio = { - .channel[RADIO_CHANNEL0] = - { - .id = RADIO_CHANNEL0, - .config = - { - .sample_rate[RADIO_SAMPLE_RATE_CLOCKGEN] = - {.hz = 0}, - .filter[RADIO_FILTER_BASEBAND] = {.hz = 0}, - .frequency[RADIO_FREQUENCY_RF] = - { - .hz = 0, - .if_hz = 0, - .lo_hz = 0, - .path = 0, - }, - .gain[RADIO_GAIN_RF_AMP] = {.enable = 0}, - .gain[RADIO_GAIN_RX_LNA] = {.db = 0}, - .gain[RADIO_GAIN_RX_VGA] = {.db = 0}, - .gain[RADIO_GAIN_TX_VGA] = {.db = 0}, - .antenna[RADIO_ANTENNA_BIAS_TEE] = - {.enable = false}, - .mode = TRANSCEIVER_MODE_OFF, - .clock[RADIO_CLOCK_CLKIN] = {.enable = false}, - .clock[RADIO_CLOCK_CLKOUT] = {.enable = false}, - .trigger_enable = false, -#ifdef PRALINE - .resampling_n = 0, - .shift = FPGA_QUARTER_SHIFT_MODE_NONE, -#endif - }, - .clock_source = CLOCK_SOURCE_HACKRF, - }, -}; +radio_t radio; rf_path_t rf_path = { .switchctrl = 0, @@ -1009,7 +976,6 @@ clock_source_t activate_best_clock_source(void) &clock_gen, (source == CLOCK_SOURCE_HACKRF) ? PLL_SOURCE_XTAL : PLL_SOURCE_CLKIN); hackrf_ui()->set_clock_source(source); - radio.channel[RADIO_CHANNEL0].clock_source = source; return source; } diff --git a/firmware/common/radio.c b/firmware/common/radio.c index d7eeffb6..75def39b 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -1,7 +1,5 @@ /* - * Copyright 2012-2025 Great Scott Gadgets - * Copyright 2012 Jared Boone - * Copyright 2013 Benjamin Vernoux + * Copyright 2025-2026 Great Scott Gadgets * * This file is part of HackRF. * @@ -23,531 +21,759 @@ #include "hackrf_core.h" #include "tuning.h" - +#include "rf_path.h" +#include "fpga.h" +#include "platform_detect.h" #include "radio.h" -radio_error_t radio_set_sample_rate( - radio_t* radio, - radio_chan_id chan_id, - radio_sample_rate_id element, - radio_sample_rate_t sample_rate) +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +void radio_init(radio_t* const radio) { - // we only support the clock generator at the moment - if (element != RADIO_SAMPLE_RATE_CLOCKGEN) { - return RADIO_ERR_INVALID_ELEMENT; - } - - radio_config_t* config = &radio->channel[chan_id].config; - - /* - * 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; - 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 = 4 * sample_rate.hz; - while ((afe_rate_x2 <= MAX_AFE_RATE) && (n < MAX_N)) { - afe_rate_x2 <<= 1; - n++; + for (uint8_t bank = 0; bank < RADIO_NUM_BANKS; bank++) { + for (uint8_t reg = 0; reg < RADIO_NUM_REGS; reg++) { + radio->config[bank][reg] = RADIO_UNSET; } - 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; - } - - config->sample_rate[element] = sample_rate; - return RADIO_OK; + radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF; + radio->config[RADIO_BANK_ACTIVE][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF; + radio->config[RADIO_BANK_IDLE][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF; + radio->config[RADIO_BANK_RX][RADIO_OPMODE] = TRANSCEIVER_MODE_RX; + radio->config[RADIO_BANK_TX][RADIO_OPMODE] = TRANSCEIVER_MODE_TX; + radio->regs_dirty = 0; } -radio_sample_rate_t radio_get_sample_rate( - radio_t* radio, - radio_chan_id chan_id, - radio_sample_rate_id element) +static inline void mark_dirty(radio_t* const radio, radio_register_t reg) { - return radio->channel[chan_id].config.sample_rate[element]; + radio->regs_dirty |= (1 << reg); } -radio_error_t radio_set_filter( - radio_t* radio, - radio_chan_id chan_id, - radio_filter_id element, - radio_filter_t filter) +radio_error_t radio_reg_write( + radio_t* const radio, + const radio_register_bank_t bank, + const radio_register_t reg, + const uint64_t value) { - // we only support the baseband filter at the moment - if (element != RADIO_FILTER_BASEBAND) { - return RADIO_ERR_INVALID_ELEMENT; + if (reg > RADIO_NUM_REGS) { + return RADIO_ERR_INVALID_REGISTER; } - radio_config_t* config = &radio->channel[chan_id].config; - - if (config->mode == TRANSCEIVER_MODE_OFF) { - config->filter[element] = filter; - return RADIO_OK; - } - -#ifndef PRALINE - max283x_set_lpf_bandwidth(&max283x, filter.hz); -#else - uint32_t lpf_bandwidth = - (config->sample_rate[RADIO_SAMPLE_RATE_CLOCKGEN].hz * 3) / 4; - uint32_t offset = 0; - if (config->shift != FPGA_QUARTER_SHIFT_MODE_NONE) { - offset = (config->sample_rate[RADIO_SAMPLE_RATE_CLOCKGEN].hz - << config->resampling_n) / - 4; - } - lpf_bandwidth += offset * 2; - max2831_set_lpf_bandwidth(&max283x, lpf_bandwidth); -#endif - - config->filter[element] = filter; - return RADIO_OK; -} - -radio_filter_t radio_get_filter( - radio_t* radio, - radio_chan_id chan_id, - radio_filter_id element) -{ - return radio->channel[chan_id].config.filter[element]; -} - -radio_error_t radio_set_gain( - radio_t* radio, - radio_chan_id chan_id, - radio_gain_id element, - radio_gain_t gain) -{ - if (element > RADIO_GAIN_COUNT) { - return RADIO_ERR_INVALID_ELEMENT; - } - - radio_config_t* config = &radio->channel[chan_id].config; - - if (config->mode == TRANSCEIVER_MODE_OFF) { - config->gain[element] = gain; - return RADIO_OK; - } - - uint8_t real_db; - switch (element) { - case RADIO_GAIN_RF_AMP: - rf_path_set_lna(&rf_path, gain.enable); + switch (bank) { + case RADIO_BANK_ACTIVE: + mark_dirty(radio, reg); + /* fall through */ + case RADIO_BANK_IDLE: + case RADIO_BANK_RX: + case RADIO_BANK_TX: + radio->config[bank][reg] = value; break; - case RADIO_GAIN_RX_LNA: -#ifndef PRALINE - real_db = max283x_set_lna_gain(&max283x, gain.db); -#else - real_db = max2831_set_lna_gain(&max283x, gain.db); -#endif - if (real_db == 0) { - return RADIO_ERR_INVALID_PARAM; + case RADIO_BANK_ALL: + for (uint8_t b = 1; b < RADIO_NUM_BANKS; b++) { + radio->config[b][reg] = value; } - break; - case RADIO_GAIN_RX_VGA: -#ifndef PRALINE - real_db = max283x_set_vga_gain(&max283x, gain.db); -#else - real_db = max2831_set_vga_gain(&max283x, gain.db); -#endif - if (real_db == 0) { - return RADIO_ERR_INVALID_PARAM; - } - break; - case RADIO_GAIN_TX_VGA: -#ifndef PRALINE - real_db = max283x_set_txvga_gain(&max283x, gain.db); -#else - real_db = max2831_set_txvga_gain(&max283x, gain.db); -#endif - if (real_db == 0) { - return RADIO_ERR_INVALID_PARAM; - } - break; - } - - config->gain[element] = gain; - return RADIO_OK; -} - -radio_gain_t radio_get_gain(radio_t* radio, radio_chan_id chan_id, radio_gain_id element) -{ - return radio->channel[chan_id].config.gain[element]; -} - -static uint64_t applied_freq = 0xffffffffffffffff; - -radio_error_t radio_set_frequency( - radio_t* radio, - radio_chan_id chan_id, - radio_frequency_id element, - radio_frequency_t frequency) -{ - // we only support setting the final rf frequency at the moment - if (element != RADIO_FREQUENCY_RF) { - return RADIO_ERR_INVALID_ELEMENT; - } - - radio_config_t* config = &radio->channel[chan_id].config; - - if (config->mode == TRANSCEIVER_MODE_OFF) { - config->frequency[element] = frequency; - return RADIO_OK; - } - - // explicit - if (frequency.if_hz || frequency.lo_hz) { - bool ok = set_freq_explicit( - frequency.if_hz, - frequency.lo_hz, - frequency.path); -#ifdef PRALINE - if (ok) { - 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) { - return RADIO_ERR_INVALID_PARAM; - } - - config->frequency[element] = frequency; - return RADIO_OK; - } - - // auto-tune - if (frequency.hz == applied_freq) { - return RADIO_OK; - } - applied_freq = frequency.hz; - bool ok; -#ifndef PRALINE - switch (config->mode) { - case TRANSCEIVER_MODE_RX: - case TRANSCEIVER_MODE_RX_SWEEP: - case TRANSCEIVER_MODE_TX: - ok = set_freq(frequency.hz); + mark_dirty(radio, reg); break; default: - return RADIO_ERR_INVALID_CONFIG; - } -#else - const tune_config_t* tune_config; - switch (config->mode) { - case TRANSCEIVER_MODE_RX: - tune_config = praline_tune_config_rx; - break; - case TRANSCEIVER_MODE_RX_SWEEP: - tune_config = praline_tune_config_rx_sweep; - break; - case TRANSCEIVER_MODE_TX: - tune_config = praline_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 ((frequency.hz == 0) || - (tune_config->rf_range_end_mhz > (frequency.hz / FREQ_ONE_MHZ))) { - found = true; - break; - } - } - if (!found) { - return RADIO_ERR_INVALID_PARAM; + return RADIO_ERR_INVALID_BANK; } - 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) / - 4; - 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; - } - - config->frequency[element] = frequency; + radio_update(radio); return RADIO_OK; } -radio_frequency_t radio_get_frequency( - radio_t* radio, - radio_chan_id chan_id, - radio_frequency_id element) +uint64_t radio_reg_read( + radio_t* const radio, + const radio_register_bank_t bank, + const radio_register_t reg) { - return radio->channel[chan_id].config.frequency[element]; + return radio->config[bank][reg]; } -radio_error_t radio_set_antenna( - radio_t* radio, - radio_chan_id chan_id, - radio_antenna_id element, - radio_antenna_t value) +static bool radio_update_direction(radio_t* const radio, uint64_t* bank) { - if (element > RADIO_ANTENNA_COUNT) { - return RADIO_ERR_INVALID_ELEMENT; + const uint64_t requested = bank[RADIO_OPMODE]; + + if (requested == RADIO_UNSET) { + return false; } - radio_config_t* config = &radio->channel[chan_id].config; - - if (config->mode == TRANSCEIVER_MODE_OFF) { - config->antenna[element] = value; - return RADIO_OK; - } - - switch (element) { - case RADIO_ANTENNA_BIAS_TEE: - rf_path_set_antenna( - &rf_path, - config->antenna[RADIO_ANTENNA_BIAS_TEE].enable); - break; - } - - config->antenna[element] = value; - return RADIO_OK; -} - -radio_antenna_t radio_get_antenna( - radio_t* radio, - radio_chan_id chan_id, - radio_antenna_id element) -{ - return radio->channel[chan_id].config.antenna[element]; -} - -radio_error_t radio_set_clock( - radio_t* radio, - radio_chan_id chan_id, - radio_clock_id element, - radio_clock_t value) -{ - radio_config_t* config = &radio->channel[chan_id].config; - - if (element > RADIO_CLOCK_COUNT) { - return RADIO_ERR_INVALID_ELEMENT; - } - - // CLKIN is not supported as it is automatically detected from hardware state - if (element == RADIO_CLOCK_CLKIN) { - return RADIO_ERR_UNSUPPORTED_OPERATION; - } - - si5351c_clkout_enable(&clock_gen, value.enable); - - config->clock[element] = value; - return RADIO_OK; -} - -radio_clock_t radio_get_clock( - radio_t* radio, - radio_chan_id chan_id, - radio_clock_id element) -{ - if (element == RADIO_CLOCK_CLKIN) { - return (radio_clock_t){ - .enable = si5351c_clkin_signal_valid(&clock_gen), - }; - } - - return radio->channel[chan_id].config.clock[element]; -} - -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_enable = enable; - return RADIO_OK; -} - -bool radio_get_trigger_enable(radio_t* radio, radio_chan_id chan_id) -{ - return radio->channel[chan_id].config.trigger_enable; -} - -transceiver_mode_t radio_get_mode(radio_t* radio, radio_chan_id chan_id) -{ - return radio->channel[chan_id].config.mode; -} - -rf_path_direction_t radio_get_direction(radio_t* radio, radio_chan_id chan_id) -{ - radio_config_t* config = &radio->channel[chan_id].config; - - switch (config->mode) { - case TRANSCEIVER_MODE_RX: - case TRANSCEIVER_MODE_RX_SWEEP: - return RF_PATH_DIRECTION_RX; - case TRANSCEIVER_MODE_TX: - return RF_PATH_DIRECTION_TX; - default: - return RF_PATH_DIRECTION_OFF; - } -} - -clock_source_t radio_get_clock_source(radio_t* radio, radio_chan_id chan_id) -{ - return radio->channel[chan_id].clock_source; -} - -radio_error_t radio_switch_mode( - radio_t* radio, - radio_chan_id chan_id, - transceiver_mode_t mode) -{ - radio_error_t result; - radio_channel_t* channel = &radio->channel[chan_id]; - radio_config_t* config = &channel->config; - - // configure firmware direction from mode (but don't configure the hardware yet!) rf_path_direction_t direction; - switch (mode) { + switch (bank[RADIO_OPMODE]) { + case TRANSCEIVER_MODE_TX: + case TRANSCEIVER_MODE_SS: + direction = RF_PATH_DIRECTION_TX; + break; case TRANSCEIVER_MODE_RX: case TRANSCEIVER_MODE_RX_SWEEP: direction = RF_PATH_DIRECTION_RX; break; + default: + direction = RF_PATH_DIRECTION_OFF; + } + radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE] = requested; + rf_path_set_direction(&rf_path, direction); + return true; +} + +/* + * Convert sample rate in units of 1/(2**24) Hz to fraction. + */ +static inline uint64_t frac_sample_rate(const uint64_t rate) +{ + uint64_t num = rate; + uint64_t denom = 1 << 24; + while ((num & 1) == 0) { + num >>= 1; + denom >>= 1; + if (denom == 1) { + break; + } + } + return (denom << 32) | (num & 0xffffffff); +} + +static inline uint32_t numerator(const uint64_t frac) +{ + return frac & 0xffffffff; +} + +static inline uint32_t denominator(const uint64_t frac) +{ + return frac >> 32; +} + +/* + * Convert fractional sample rate to units of 1/(2**24) Hz. + */ +static inline uint64_t round_sample_rate(const uint64_t frac) +{ + uint64_t num = (uint64_t) numerator(frac) << 24; + uint32_t denom = denominator(frac); + if (denom == 0) { + denom = 1; + } + return (num + (denom >> 1)) / denom; +} + +#define MAX_AFE_RATE_HZ (40000000UL) + +static inline uint8_t compute_resample_log( + const uint32_t sample_rate_hz, + const uint64_t requested_n) +{ + if (detected_platform() != BOARD_ID_PRALINE) { + return 0; + } + const uint8_t min_n = 1; + uint8_t max_n = 5; + + if (requested_n != RADIO_UNSET) { + max_n = MIN(max_n, requested_n); + } + uint8_t n = min_n; // resampling ratio is 2**n + uint32_t afe_rate_x2 = 4 * sample_rate_hz; + while ((afe_rate_x2 <= MAX_AFE_RATE_HZ) && (n < max_n)) { + afe_rate_x2 <<= 1; + n++; + } + return n; +} + +#define MIN_MCU_RATE (200000ULL << 24) +#define MAX_MCU_RATE (21800000ULL << 24) +#define DEFAULT_MCU_RATE (10000000ULL << 24) + +static uint64_t applied_afe_rate = RADIO_UNSET; + +static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) +{ + uint64_t rate, frac, previous_n; + uint8_t n = 0; + bool new_rate = false; + + const uint64_t requested_frac = bank[RADIO_SAMPLE_RATE_FRAC]; + const uint64_t requested_rate = bank[RADIO_SAMPLE_RATE]; + const uint64_t requested_n = bank[RADIO_RESAMPLE_RX]; + + if (requested_rate != RADIO_UNSET) { + rate = MIN(requested_rate, MAX_MCU_RATE); + rate = MAX(rate, MIN_MCU_RATE); + frac = frac_sample_rate(rate); + } else if (requested_frac != RADIO_UNSET) { + frac = requested_frac; + if (round_sample_rate(frac) > MAX_MCU_RATE) { + frac = frac_sample_rate(MAX_MCU_RATE); + } + if (round_sample_rate(frac) < MIN_MCU_RATE) { + frac = frac_sample_rate(MIN_MCU_RATE); + } + rate = round_sample_rate(frac); + } else { + rate = radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE]; + if (rate == RADIO_UNSET) { + rate = DEFAULT_MCU_RATE; + } + frac = RADIO_UNSET; + } + + uint64_t opmode = bank[RADIO_OPMODE]; + if (opmode == RADIO_UNSET) { + opmode = radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]; + } + switch (opmode) { case TRANSCEIVER_MODE_TX: - direction = RF_PATH_DIRECTION_TX; + case TRANSCEIVER_MODE_SS: + previous_n = radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX]; + if (n != previous_n) { +#ifdef PRALINE + fpga_set_tx_interpolation_ratio(&fpga, n); +#endif + radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX] = n; + new_rate = true; + } break; default: - rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_OFF); - config->mode = mode; - return RADIO_OK; + /* + * Resampling is enabled only in RX mode to work around a + * spectrum inversion bug with TX interpolation. + */ + n = compute_resample_log(rate >> 24, requested_n); + previous_n = radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX]; + if (n != previous_n) { +#ifdef PRALINE + fpga_set_rx_decimation_ratio(&fpga, n); +#endif + radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX] = n; + new_rate = true; + } } - config->mode = mode; - // sample rate - radio_sample_rate_t sample_rate = - radio_get_sample_rate(radio, channel->id, RADIO_SAMPLE_RATE_CLOCKGEN); - result = radio_set_sample_rate( - radio, - channel->id, - RADIO_SAMPLE_RATE_CLOCKGEN, - sample_rate); - if (result != RADIO_OK) { - return result; + uint64_t afe_rate = rate << n; + uint64_t previous_afe_rate = RADIO_UNSET; + if (previous_n != RADIO_UNSET) { + previous_afe_rate = radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] + << previous_n; + } + + if (afe_rate != previous_afe_rate) { + sample_rate_frac_set(numerator(frac) << n, denominator(frac)); + applied_afe_rate = afe_rate; + radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE_FRAC] = frac; + radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] = rate; + new_rate = true; + } + + return new_rate; +} + +#define DEFAULT_RF (2450000000ULL << 24) + +static uint64_t applied_offset = RADIO_UNSET; + +#ifdef PRALINE +static const tune_config_t* select_tune_config(uint64_t opmode) +{ + switch (opmode) { + case TRANSCEIVER_MODE_TX: + case TRANSCEIVER_MODE_SS: + return praline_tune_config_tx; + case TRANSCEIVER_MODE_RX_SWEEP: + return praline_tune_config_rx_sweep; + default: + return praline_tune_config_rx; + } +} +#endif + +static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) +{ + uint8_t rotation = 0; + uint64_t requested_rf = bank[RADIO_FREQUENCY_RF]; + const uint64_t requested_if = bank[RADIO_FREQUENCY_IF]; + const uint64_t requested_lo = bank[RADIO_FREQUENCY_LO]; + const uint64_t requested_img_reject = bank[RADIO_IMAGE_REJECT]; + + bool set_if = (requested_if != RADIO_UNSET); + bool set_lo = (requested_lo != RADIO_UNSET); + bool set_img_reject = (requested_img_reject != RADIO_UNSET); + + if (set_if && set_lo && set_img_reject) { + bool new_if = + (requested_if != + radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF]); + bool new_lo = + (requested_lo != + radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_LO]); + bool new_img_reject = + (requested_img_reject != + radio->config[RADIO_BANK_APPLIED][RADIO_IMAGE_REJECT]); + if (new_if || new_lo || new_img_reject) { + set_freq_explicit( + requested_if >> 24, + requested_lo >> 24, + requested_img_reject); + radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF] = + requested_if; + radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_LO] = + requested_lo; + radio->config[RADIO_BANK_APPLIED][RADIO_IMAGE_REJECT] = + requested_img_reject; + radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF] = + RADIO_UNSET; + } +#ifdef PRALINE + const uint64_t requested_rotation = bank[RADIO_ROTATION]; + if (requested_rotation != RADIO_UNSET) { + rotation = requested_rotation; + } else if (radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION] != RADIO_UNSET) { + return true; + } + fpga_set_rx_quarter_shift_mode(&fpga, rotation >> 6); +#endif + radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION] = rotation; + return true; + } + + if (requested_rf == RADIO_UNSET) { + if (radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF] == + RADIO_UNSET) { + requested_rf = DEFAULT_RF; + } else { + return false; + } + } + + bool new_rf = + (radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF] != requested_rf); + uint64_t requested_rf_hz = requested_rf >> 24; +#ifdef PRALINE + if (applied_afe_rate == RADIO_UNSET) { + return false; + } + uint64_t opmode = bank[RADIO_OPMODE]; + if (opmode == RADIO_UNSET) { + opmode = radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]; + } + const tune_config_t* tune_config = select_tune_config(opmode); + const tune_config_t* applied_tune_config = + select_tune_config(radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]); + bool new_config = (applied_tune_config != tune_config); + while ((tune_config->rf_range_end_mhz != 0) || (tune_config->if_mhz != 0)) { + if ((requested_rf_hz == 0) || + (tune_config->rf_range_end_mhz > (requested_rf_hz / FREQ_ONE_MHZ))) { + break; + } + tune_config++; + } + bool new_rotation = + (radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION] != + ((uint64_t) tune_config->shift << 6)); + if (new_rotation) { + fpga_set_rx_quarter_shift_mode(&fpga, tune_config->shift); + radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION] = + tune_config->shift << 6; + } + uint64_t offset = applied_afe_rate / 4; + bool new_offset = (applied_offset != offset); + if (new_rotation || new_offset || new_config || new_rf) { + tuning_set_frequency(tune_config, requested_rf_hz, offset >> 24); + applied_offset = offset; + } +#else + if (new_rf) { + set_freq(requested_rf_hz); + } +#endif + radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF] = requested_rf; + radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF] = RADIO_UNSET; + radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_LO] = RADIO_UNSET; + radio->config[RADIO_BANK_APPLIED][RADIO_IMAGE_REJECT] = RADIO_UNSET; + return true; +} + +static uint32_t auto_bandwidth(radio_t* const radio, uint64_t opmode) +{ + uint64_t rotation = radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION]; + + uint32_t sample_rate_hz = DEFAULT_MCU_RATE >> 24; + if (radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] != RADIO_UNSET) { + sample_rate_hz = + radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] >> 24; + } + + uint32_t offset_hz = 0; + if ((rotation != 0) && (rotation != RADIO_UNSET) && + (applied_offset != RADIO_UNSET)) { + offset_hz = applied_offset >> 24; + } + + const uint32_t bb_bandwidth = (sample_rate_hz * 3) / 4; + const uint32_t lpf_bandwidth = bb_bandwidth + offset_hz * 2; + + switch (opmode) { + case TRANSCEIVER_MODE_TX: + case TRANSCEIVER_MODE_SS: + radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_TX] = bb_bandwidth; + break; + default: + radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_RX] = bb_bandwidth; + } + return lpf_bandwidth; +} + +static bool radio_update_bandwidth(radio_t* const radio, uint64_t* bank) +{ + bool new_bw = false; + uint64_t opmode = bank[RADIO_OPMODE]; + if (opmode == RADIO_UNSET) { + opmode = radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]; + } + +#ifdef PRALINE + /* Praline legacy mode always sets baseband bandwidth automatically. */ + (void) bank; + uint32_t lpf_bandwidth = auto_bandwidth(radio, opmode); + + switch (opmode) { + case TRANSCEIVER_MODE_TX: + case TRANSCEIVER_MODE_SS: + if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != + lpf_bandwidth) { + max2831_set_lpf_bandwidth(&max283x, lpf_bandwidth); + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = + lpf_bandwidth; + new_bw = true; + } + break; + default: + if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] != + lpf_bandwidth) { + max2831_set_lpf_bandwidth(&max283x, lpf_bandwidth); + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] = + lpf_bandwidth; + new_bw = true; + } + bool narrow_lpf_enable = false; + bool applied_narrow_lpf_enable = + radio->config[RADIO_BANK_APPLIED][RADIO_RX_NARROW_LPF]; + if (lpf_bandwidth <= 1750000) { + narrow_lpf_enable = true; + } + if (applied_narrow_lpf_enable != narrow_lpf_enable) { + narrowband_filter_set(narrow_lpf_enable); + radio->config[RADIO_BANK_APPLIED][RADIO_RX_NARROW_LPF] = + narrow_lpf_enable; + new_bw = true; + } + /* Always set HPF bandwidth to 30 kHz for now. */ + const max2831_rx_hpf_freq_t hpf_bandwidth = MAX2831_RX_HPF_30_KHZ; + if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] != + hpf_bandwidth) { + max2831_set_rx_hpf_frequency(&max283x, hpf_bandwidth); + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] = + hpf_bandwidth; + new_bw = true; + } + } +#else + uint64_t lpf_bandwidth; + lpf_bandwidth = bank[RADIO_XCVR_TX_LPF]; + if (lpf_bandwidth == RADIO_UNSET) { + lpf_bandwidth = bank[RADIO_XCVR_RX_LPF]; + } + if (lpf_bandwidth == RADIO_UNSET) { + lpf_bandwidth = bank[RADIO_BB_BANDWIDTH_TX]; + } + if (lpf_bandwidth == RADIO_UNSET) { + lpf_bandwidth = bank[RADIO_BB_BANDWIDTH_RX]; + } + if (lpf_bandwidth == RADIO_UNSET) { + lpf_bandwidth = radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF]; + } + if (lpf_bandwidth == RADIO_UNSET) { + lpf_bandwidth = auto_bandwidth(radio, opmode); + } + + if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != lpf_bandwidth) { + max283x_set_lpf_bandwidth(&max283x, lpf_bandwidth); + radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_RX] = lpf_bandwidth; + radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_TX] = lpf_bandwidth; + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = lpf_bandwidth; + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] = lpf_bandwidth; + new_bw = true; + } +#endif + return new_bw; +} + +#define DEFAULT_GAIN_RF (0) +#define DEFAULT_GAIN_IF (16) +#define DEFAULT_GAIN_BB (12) + +static bool radio_update_gain(radio_t* const radio, uint64_t* bank) +{ + bool new_gain = false; + uint64_t gain; + uint64_t opmode = bank[RADIO_OPMODE]; + if (opmode == RADIO_UNSET) { + opmode = radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]; } /* - * 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(). + * Because control signals are shared by the two RF amps, the setting + * for the active amp is reapplied at every opportunity. This ensures + * override of any setting from a previous operating mode. */ -#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; + switch (opmode) { + case TRANSCEIVER_MODE_TX: + case TRANSCEIVER_MODE_SS: + gain = bank[RADIO_GAIN_TX_RF]; + if (gain == RADIO_UNSET) { + gain = DEFAULT_GAIN_RF; + } + rf_path_set_lna(&rf_path, gain); + if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_RF] != gain) { + new_gain = true; + } + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_RF] = gain; + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_RF] = 0; + break; + case TRANSCEIVER_MODE_RX: + case TRANSCEIVER_MODE_RX_SWEEP: + gain = bank[RADIO_GAIN_RX_RF]; + if (gain == RADIO_UNSET) { + gain = DEFAULT_GAIN_RF; + } + rf_path_set_lna(&rf_path, gain); + if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_RF] != gain) { + new_gain = true; + } + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_RF] = gain; + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_RF] = 0; + break; + default: + rf_path_set_lna(&rf_path, 0); + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_RF] = 0; + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_RF] = 0; } - // baseband filter bandwidth - radio_filter_t filter = - radio_get_filter(radio, channel->id, RADIO_FILTER_BASEBAND); - result = radio_set_filter(radio, channel->id, RADIO_FILTER_BASEBAND, filter); - if (result != RADIO_OK) { - return result; - } + gain = bank[RADIO_GAIN_TX_IF]; + if ((gain != RADIO_UNSET) && + (gain != radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF])) { +#ifdef PRALINE + max2831_set_txvga_gain(&max283x, gain); +#else + max283x_set_txvga_gain(&max283x, gain); #endif - - // rf_amp enable - radio_gain_t enable = radio_get_gain(radio, channel->id, RADIO_GAIN_RF_AMP); - result = radio_set_gain(radio, channel->id, RADIO_GAIN_RF_AMP, enable); - if (result != RADIO_OK) { - return result; + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] = gain; + new_gain = true; + } else if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] == RADIO_UNSET) { +#ifdef PRALINE + max2831_set_txvga_gain(&max283x, DEFAULT_GAIN_IF); +#else + max283x_set_txvga_gain(&max283x, DEFAULT_GAIN_IF); +#endif + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] = DEFAULT_GAIN_IF; + new_gain = true; } - // gain - radio_gain_t gain; - if (config->mode == TRANSCEIVER_MODE_RX || - config->mode == TRANSCEIVER_MODE_RX_SWEEP) { - gain = radio_get_gain(radio, channel->id, RADIO_GAIN_RX_LNA); - result = radio_set_gain(radio, channel->id, RADIO_GAIN_RX_LNA, gain); - if (result != RADIO_OK) { - return result; - } - - gain = radio_get_gain(radio, channel->id, RADIO_GAIN_RX_VGA); - result = radio_set_gain(radio, channel->id, RADIO_GAIN_RX_VGA, gain); - if (result != RADIO_OK) { - return result; - } - - } else if (config->mode == TRANSCEIVER_MODE_TX) { - gain = radio_get_gain(radio, channel->id, RADIO_GAIN_TX_VGA); - result = radio_set_gain(radio, channel->id, RADIO_GAIN_TX_VGA, gain); - if (result != RADIO_OK) { - return result; - } + gain = bank[RADIO_GAIN_RX_IF]; + if ((gain != RADIO_UNSET) && + (gain != radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF])) { +#ifdef PRALINE + max2831_set_lna_gain(&max283x, gain); +#else + max283x_set_lna_gain(&max283x, gain); +#endif + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] = gain; + new_gain = true; + } else if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] == RADIO_UNSET) { +#ifdef PRALINE + max2831_set_lna_gain(&max283x, DEFAULT_GAIN_IF); +#else + max283x_set_lna_gain(&max283x, DEFAULT_GAIN_IF); +#endif + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] = DEFAULT_GAIN_IF; + new_gain = true; } - // antenna - radio_antenna_t bias_tee = - radio_get_antenna(radio, channel->id, RADIO_ANTENNA_BIAS_TEE); - result = radio_set_antenna(radio, channel->id, RADIO_ANTENNA_BIAS_TEE, bias_tee); - if (result != RADIO_OK) { - return result; + gain = bank[RADIO_GAIN_RX_BB]; + if ((gain != RADIO_UNSET) && + (gain != radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_BB])) { +#ifdef PRALINE + max2831_set_vga_gain(&max283x, gain); +#else + max283x_set_vga_gain(&max283x, gain); +#endif + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_BB] = gain; + new_gain = true; + } else if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_BB] == RADIO_UNSET) { +#ifdef PRALINE + max2831_set_vga_gain(&max283x, DEFAULT_GAIN_BB); +#else + max283x_set_vga_gain(&max283x, DEFAULT_GAIN_BB); +#endif + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_BB] = DEFAULT_GAIN_BB; + new_gain = true; } - // finally, set the rf path direction - rf_path_set_direction(&rf_path, direction); - - return RADIO_OK; + return new_gain; +} + +static bool radio_update_bias_tee(radio_t* const radio, uint64_t* bank) +{ + if (detected_platform() == BOARD_ID_JAWBREAKER) { + return false; + } + + const uint64_t requested = bank[RADIO_BIAS_TEE]; + const bool enable = requested; + + if (requested == RADIO_UNSET) { + return false; + } + + if (radio->config[RADIO_BANK_APPLIED][RADIO_BIAS_TEE] == (uint64_t) enable) { + return false; + } + + rf_path_set_antenna(&rf_path, enable); + radio->config[RADIO_BANK_APPLIED][RADIO_BIAS_TEE] = enable; + return true; +} + +static bool radio_update_trigger(radio_t* const radio, uint64_t* bank) +{ + const uint64_t requested = bank[RADIO_TRIGGER]; + bool enable = requested; + + if (requested == RADIO_UNSET) { + enable = false; + } + + if (radio->config[RADIO_BANK_APPLIED][RADIO_TRIGGER] == (uint64_t) enable) { + return false; + } + + trigger_enable(enable); + radio->config[RADIO_BANK_APPLIED][RADIO_TRIGGER] = enable; + return true; +} + +static bool radio_update_dc_block(radio_t* const radio, uint64_t* bank) +{ +#ifndef PRALINE + (void) radio; + (void) bank; + return false; +#else + const uint64_t requested = bank[RADIO_DC_BLOCK]; + bool enable = requested; + + if (requested == RADIO_UNSET) { + enable = true; + } + + if (radio->config[RADIO_BANK_APPLIED][RADIO_DC_BLOCK] == (uint64_t) enable) { + return false; + } + + fpga_set_rx_dc_block_enable(&fpga, enable); + radio->config[RADIO_BANK_APPLIED][RADIO_DC_BLOCK] = enable; + return true; +#endif +} + +bool radio_update(radio_t* const radio) +{ + uint64_t tmp_bank[RADIO_NUM_REGS]; + uint32_t dirty = radio->regs_dirty; + if (dirty == 0) { + return false; + } + radio->regs_dirty = 0; + memcpy(&tmp_bank[0], &(radio->config[RADIO_BANK_ACTIVE][0]), sizeof(tmp_bank)); + + bool dir = false; + bool rate = false; + bool freq = false; + bool bw = false; + bool gain = false; + bool bias = false; + bool trig = false; + bool dc = false; + + if ((dirty & + ((1 << RADIO_SAMPLE_RATE) | (1 << RADIO_SAMPLE_RATE_FRAC) | + (1 << RADIO_RESAMPLE_TX) | (1 << RADIO_RESAMPLE_RX))) || + ((detected_platform() == BOARD_ID_PRALINE) && + (dirty & (1 << RADIO_OPMODE)))) { + rate = radio_update_sample_rate(radio, &tmp_bank[0]); + } + if ((dirty & + ((1 << RADIO_FREQUENCY_RF) | (1 << RADIO_FREQUENCY_IF) | + (1 << RADIO_FREQUENCY_LO) | (1 << RADIO_IMAGE_REJECT) | + (1 << RADIO_ROTATION))) || + ((detected_platform() == BOARD_ID_PRALINE) && + (rate || (dirty & (1 << RADIO_OPMODE))))) { + freq = radio_update_frequency(radio, &tmp_bank[0]); + } + if ((dirty & + ((1 << RADIO_BB_BANDWIDTH_TX) | (1 << RADIO_BB_BANDWIDTH_RX) | + (1 << RADIO_XCVR_TX_LPF) | (1 << RADIO_XCVR_RX_LPF) | + (1 << RADIO_XCVR_RX_HPF) | (1 << RADIO_RX_NARROW_LPF))) || + ((detected_platform() == BOARD_ID_PRALINE) && (rate || freq))) { + bw = radio_update_bandwidth(radio, &tmp_bank[0]); + } + if (dirty & + ((1 << RADIO_GAIN_TX_RF) | (1 << RADIO_GAIN_TX_IF) | (1 << RADIO_GAIN_RX_RF) | + (1 << RADIO_GAIN_RX_IF) | (1 << RADIO_GAIN_RX_BB) | (1 << RADIO_OPMODE))) { + gain = radio_update_gain(radio, &tmp_bank[0]); + } + if (dirty & (1 << RADIO_BIAS_TEE)) { + bias = radio_update_bias_tee(radio, &tmp_bank[0]); + } + if (dirty & (1 << RADIO_TRIGGER)) { + trig = radio_update_trigger(radio, &tmp_bank[0]); + } + if (dirty & (1 << RADIO_DC_BLOCK)) { + dc = radio_update_dc_block(radio, &tmp_bank[0]); + } + if (dirty & (1 << RADIO_OPMODE)) { + dir = radio_update_direction(radio, &tmp_bank[0]); + } + + return trig || dir || rate || freq || bw || gain || bias || dc; +} + +void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode) +{ + radio_register_bank_t source_bank; + uint64_t value, previous; + + switch (mode) { + case TRANSCEIVER_MODE_RX_SWEEP: + case TRANSCEIVER_MODE_RX: + source_bank = RADIO_BANK_RX; + break; + case TRANSCEIVER_MODE_TX: + case TRANSCEIVER_MODE_SS: + source_bank = RADIO_BANK_TX; + break; + default: + source_bank = RADIO_BANK_IDLE; + } + + for (uint8_t reg = 0; reg < RADIO_NUM_REGS; reg++) { + value = radio->config[source_bank][reg]; + previous = radio->config[RADIO_BANK_ACTIVE][reg]; + if ((value != RADIO_UNSET) && (value != previous)) { + radio->config[RADIO_BANK_ACTIVE][reg] = value; + mark_dirty(radio, reg); + } + } + + mark_dirty(radio, RADIO_OPMODE); + radio_update(radio); } diff --git a/firmware/common/radio.h b/firmware/common/radio.h index 60e2cc4d..5922977f 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-2025 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Jared Boone * Copyright 2013 Benjamin Vernoux * @@ -27,53 +27,24 @@ #include #include -#include "rf_path.h" -#include "fpga.h" - typedef enum { RADIO_OK = 1, RADIO_ERR_INVALID_PARAM = -2, - RADIO_ERR_INVALID_CONFIG = -3, - RADIO_ERR_INVALID_CHANNEL = -4, - RADIO_ERR_INVALID_ELEMENT = -5, + RADIO_ERR_INVALID_BANK = -3, + RADIO_ERR_INVALID_REGISTER = -4, RADIO_ERR_UNSUPPORTED_OPERATION = -10, RADIO_ERR_UNIMPLEMENTED = -19, RADIO_ERR_OTHER = -9999, } radio_error_t; +/* radio configuration modes */ typedef enum { - RADIO_CHANNEL0 = 0x00, -} radio_chan_id; - -typedef enum { - RADIO_FILTER_BASEBAND = 0x00, -} radio_filter_id; - -typedef enum { - RADIO_SAMPLE_RATE_CLOCKGEN = 0x00, -} radio_sample_rate_id; - -typedef enum { - RADIO_FREQUENCY_RF = 0x00, - RADIO_FREQUENCY_IF = 0x01, - RADIO_FREQUENCY_OF = 0x02, -} radio_frequency_id; - -typedef enum { - RADIO_GAIN_RF_AMP = 0x00, - RADIO_GAIN_RX_LNA = 0x01, - RADIO_GAIN_RX_VGA = 0x02, - RADIO_GAIN_TX_VGA = 0x03, -} radio_gain_id; - -typedef enum { - RADIO_ANTENNA_BIAS_TEE = 0x00, -} radio_antenna_id; - -typedef enum { - RADIO_CLOCK_CLKIN = 0x00, - RADIO_CLOCK_CLKOUT = 0x01, -} radio_clock_id; + RADIO_CONFIG_LEGACY = 0, + RADIO_CONFIG_STANDARD = 1, + RADIO_CONFIG_EXT_PRECISION_RX = 2, + RADIO_CONFIG_EXT_PRECISION_TX = 3, + RADIO_CONFIG_HALF_PRECISION = 4, +} radio_config_mode_t; typedef struct { uint32_t num; @@ -81,32 +52,6 @@ typedef struct { uint32_t hz; } radio_sample_rate_t; -typedef struct { - uint64_t hz; -} radio_filter_t; - -typedef struct { - union { - bool enable; - uint8_t db; - }; -} radio_gain_t; - -typedef struct { - uint64_t hz; // desired frequency - uint64_t if_hz; // intermediate frequency - uint64_t lo_hz; // front-end local oscillator frequency - uint8_t path; // image rejection filter path -} radio_frequency_t; - -typedef struct { - bool enable; -} radio_antenna_t; - -typedef struct { - bool enable; -} radio_clock_t; - // legacy type, moved from hackrf_core typedef enum { CLOCK_SOURCE_HACKRF = 0, @@ -114,7 +59,6 @@ typedef enum { CLOCK_SOURCE_PORTAPACK = 2, } clock_source_t; -// legacy type, moved from usb_api_transceiver typedef enum { TRANSCEIVER_MODE_OFF = 0, TRANSCEIVER_MODE_RX = 1, @@ -124,142 +68,185 @@ typedef enum { TRANSCEIVER_MODE_RX_SWEEP = 5, } transceiver_mode_t; -#define RADIO_CHANNEL_COUNT 1 -#define RADIO_SAMPLE_RATE_COUNT 1 -#define RADIO_FILTER_COUNT 1 -#define RADIO_FREQUENCY_COUNT 4 -#define RADIO_GAIN_COUNT 4 -#define RADIO_ANTENNA_COUNT 1 -#define RADIO_CLOCK_COUNT 2 -#define RADIO_MODE_COUNT 6 +/** + * Configurable registers stored as uint64_t. Any register may be set to + * RADIO_UNSET. When not RADIO_UNSET, some registers are read as a specific type + * as noted. + */ +typedef enum { + /** + * Radio transceiver operating mode of type transceiver_mode_t. + */ + RADIO_OPMODE = 0, + /** + * Center frequency (as seen by MCU/host) in 1/(2**24) Hz. + */ + RADIO_FREQUENCY_RF = 1, + /** + * Intermediate frequency in 1/(2**24) Hz that the quadrature + * transceiver is tuned to. Overrides RADIO_FREQUENCY_RF if specified. + */ + RADIO_FREQUENCY_IF = 2, + /** + * Local oscillator frequency in 1/(2**24) Hz of the front-end mixer. + * Overrides RADIO_FREQUENCY_RF if specified. + */ + RADIO_FREQUENCY_LO = 3, + /** + * Image reject path of type rf_path_filter_t. Overrides + * RADIO_FREQUENCY_RF if specified. + */ + RADIO_IMAGE_REJECT = 4, + /** + * Digital frequency conversion of type uint8_t in tau/256 steps with + * respect to AFE clock. + */ + RADIO_ROTATION = 5, + /** + * Sample rate (as seen by MCU/host) in 1/(2**24) Hz. + */ + RADIO_SAMPLE_RATE = 6, + /** + * Sample rate (as seen by MCU/host) in fractional format. The + * numerator is stored in the low 32 bits. The denominator is stored in + * the high 32 bits. + */ + RADIO_SAMPLE_RATE_FRAC = 7, + /** + * Base two logarithm of TX decimation ratio (0 means a ratio of 1). + */ + RADIO_RESAMPLE_TX = 8, + /** + * Base two logarithm of RX decimation ratio (0 means a ratio of 1). + */ + RADIO_RESAMPLE_RX = 9, + /** + * TX RF amplifier enable of type bool. + */ + RADIO_GAIN_TX_RF = 10, + /** + * TX IF amplifier gain in dB. + */ + RADIO_GAIN_TX_IF = 11, + /** + * RX RF amplifier enable of type bool. + */ + RADIO_GAIN_RX_RF = 12, + /** + * RX IF amplifier gain in dB. + */ + RADIO_GAIN_RX_IF = 13, + /** + * RX baseband amplifier gain in dB. + */ + RADIO_GAIN_RX_BB = 14, + /** + * TX baseband bandwidth in Hz. This controls analog baseband filter + * settings but is specified as the desired bandwidth centered in + * digital baseband as seen by the MCU/host. + */ + RADIO_BB_BANDWIDTH_TX = 15, + /** + * RX baseband bandwidth in Hz. This controls analog baseband filter + * settings but is specified as the desired bandwidth centered in + * digital baseband as seen by the MCU/host. + */ + RADIO_BB_BANDWIDTH_RX = 16, + /** + * Quadrature transceiver TX baseband LPF bandwidth in Hz. If no + * rotation is performed, this is set to match RADIO_BB_BANDWIDTH. + * Currently unused. + */ + RADIO_XCVR_TX_LPF = 17, + /** + * Quadrature transceiver RX baseband LPF bandwidth in Hz. If no + * rotation is performed, this is set to match RADIO_BB_BANDWIDTH. + * Currently unused. + */ + RADIO_XCVR_RX_LPF = 18, + /** + * Quadrature transceiver RX baseband HPF bandwidth in Hz. Currently + * unused. + */ + RADIO_XCVR_RX_HPF = 19, + /** + * Narrowband RX analog baseband LPF enable of type bool. Currently unused. + */ + RADIO_RX_NARROW_LPF = 20, + /** + * RF port bias tee enable of type bool. + */ + RADIO_BIAS_TEE = 21, + /** + * Trigger input enable of type bool. + */ + RADIO_TRIGGER = 22, + /** + * DC block enable of type bool. + */ + RADIO_DC_BLOCK = 23, +} radio_register_t; -typedef struct { - // sample rate elements - radio_sample_rate_t sample_rate[RADIO_SAMPLE_RATE_COUNT]; - - // filter elements - radio_filter_t filter[RADIO_FILTER_COUNT]; - - // gain elements - radio_gain_t gain[RADIO_GAIN_COUNT]; - - // frequency elements - radio_frequency_t frequency[RADIO_FREQUENCY_COUNT]; - - // antenna elements - radio_antenna_t antenna[RADIO_ANTENNA_COUNT]; - - // clock elements - radio_clock_t clock[RADIO_CLOCK_COUNT]; - - // trigger elements - bool trigger_enable; - - // currently active transceiver mode - transceiver_mode_t mode; - -#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; - -typedef struct radio_channel_t { - radio_chan_id id; - radio_config_t config; - radio_config_t mode[RADIO_MODE_COUNT]; - clock_source_t clock_source; -} radio_channel_t; - -typedef struct radio_t { - radio_channel_t channel[RADIO_CHANNEL_COUNT]; -} radio_t; +#define RADIO_NUM_REGS (24) +#define RADIO_UNSET (0xffffffffffffffff) /** - * API Notes + * Register bank RADIO_BANK_ACTIVE stores the active configuration. Active + * register settings are copied to the applied register when applied. * - * - All radio_set_*() functions return a radio_error_t - * - radio_set_*() functions work as follows: - * - if the channel mode is TRANSCEIVER_MODE_OFF only the configuration will - * be updated, the hardware state will remain unaffected. - * - if the channel is something other than TRANSCEIVER_MODE_OFF both the - * configuration and hardware state will be updated. - * - this makes it possible to maintain multiple channel configurations and - * switch between them with a single call to radio_switch_mode() + * The other three banks store settings that will be applied when switching to + * that operating mode. + * + * RADIO_BANK_ALL may be used to write to all banks at once except for + * RADIO_BANK_APPLIED. */ +typedef enum { + RADIO_BANK_APPLIED = 0, + RADIO_BANK_ACTIVE = 1, + RADIO_BANK_IDLE = 2, + RADIO_BANK_RX = 3, + RADIO_BANK_TX = 4, + RADIO_BANK_ALL = 255, +} radio_register_bank_t; -radio_error_t radio_set_sample_rate( - radio_t* radio, - radio_chan_id chan_id, - radio_sample_rate_id element, - radio_sample_rate_t sample_rate); -radio_sample_rate_t radio_get_sample_rate( - radio_t* radio, - radio_chan_id chan_id, - radio_sample_rate_id element); +#define RADIO_NUM_BANKS (5) -radio_error_t radio_set_filter( - radio_t* radio, - radio_chan_id chan_id, - radio_filter_id element, - radio_filter_t filter); -radio_filter_t radio_get_filter( - radio_t* radio, - radio_chan_id chan_id, - radio_filter_id element); +typedef struct radio_t { + radio_config_mode_t config_mode; + uint64_t config[RADIO_NUM_BANKS][RADIO_NUM_REGS]; + volatile uint32_t regs_dirty; +} radio_t; -radio_error_t radio_set_frequency( - radio_t* radio, - radio_chan_id chan_id, - radio_frequency_id element, - radio_frequency_t frequency); -radio_frequency_t radio_get_frequency( - radio_t* radio, - radio_chan_id chan_id, - radio_frequency_id element); +void radio_init(radio_t* const radio); -radio_error_t radio_set_gain( - radio_t* radio, - radio_chan_id chan_id, - radio_gain_id element, - radio_gain_t gain); -radio_gain_t radio_get_gain(radio_t* radio, radio_chan_id chan_id, radio_gain_id element); +/** + * Write to one or more registers. Writes to RADIO_BANK_ACTIVE are applied at + * the next radio_update(). Writes to RADIO_BANK_APPLIED are not supported. + */ +radio_error_t radio_reg_write( + radio_t* const radio, + const radio_register_bank_t bank, + const radio_register_t reg, + const uint64_t value); -radio_error_t radio_set_antenna( - radio_t* radio, - radio_chan_id chan_id, - radio_antenna_id element, - radio_antenna_t value); -radio_antenna_t radio_get_antenna( - radio_t* radio, - radio_chan_id chan_id, - radio_antenna_id element); +/** + * Read from a register. + */ +uint64_t radio_reg_read( + radio_t* const radio, + const radio_register_bank_t bank, + const radio_register_t reg); -radio_error_t radio_set_clock( - radio_t* radio, - radio_chan_id chan_id, - radio_clock_id element, - radio_clock_t value); -radio_clock_t radio_get_clock( - radio_t* radio, - radio_chan_id chan_id, - radio_clock_id element); +/** + * Apply changes requested in RADIO_BANK_ACTIVE. + * Return true if any changes were applied. + */ +bool radio_update(radio_t* const radio); -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); -clock_source_t radio_get_clock_source(radio_t* radio, radio_chan_id chan_id); - -// apply the current channel configuration and switch to the given transceiver mode -radio_error_t radio_switch_mode( - radio_t* radio, - radio_chan_id chan_id, - transceiver_mode_t mode); +/** + * Switch to a new operating mode and apply complete configuration stored in + * the request bank for the new mode. + */ +void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode); #endif /*__RF_CONFIG_H__*/ diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index f8c55016..06e0079d 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Jared Boone * Copyright 2013 Benjamin Vernoux * @@ -318,6 +318,7 @@ int main(void) fpga_spi_selftest(); fpga_sgpio_selftest(); #endif + radio_init(&radio); #if (defined HACKRF_ONE || defined PRALINE) portapack_init(); diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index ae4e74b4..85aa5d7c 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 Great Scott Gadgets + * Copyright 2016-2026 Great Scott Gadgets * Copyright 2016 Mike Walters, Dominic Spill * * This file is part of HackRF. @@ -92,11 +92,11 @@ usb_request_status_t usb_vendor_request_init_sweep( ((uint16_t) (data[10 + i * 2]) << 8) + data[9 + i * 2]; } sweep_freq = (uint64_t) frequencies[0] * FREQ_GRANULARITY; - radio_set_frequency( + radio_reg_write( &radio, - RADIO_CHANNEL0, + RADIO_BANK_ACTIVE, RADIO_FREQUENCY_RF, - (radio_frequency_t){.hz = sweep_freq + offset}); + (sweep_freq + offset) << 24); usb_transfer_schedule_ack(endpoint->in); } return USB_REQUEST_STATUS_OK; @@ -220,11 +220,11 @@ void sweep_mode(uint32_t seq) } // Retune to new frequency. nvic_disable_irq(NVIC_USB0_IRQ); - radio_set_frequency( + radio_reg_write( &radio, - RADIO_CHANNEL0, + RADIO_BANK_ACTIVE, RADIO_FREQUENCY_RF, - (radio_frequency_t){.hz = sweep_freq + offset}); + (sweep_freq + offset) << 24); nvic_enable_irq(NVIC_USB0_IRQ); blocks_queued = 0; } diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index d72e57a1..76399ae9 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -78,24 +78,20 @@ usb_request_status_t usb_vendor_request_set_baseband_filter_bandwidth( if (stage == USB_TRANSFER_STAGE_SETUP) { const uint32_t bandwidth = (endpoint->setup.index << 16) | endpoint->setup.value; - radio_error_t result = radio_set_filter( + radio_reg_write( &radio, - RADIO_CHANNEL0, - RADIO_FILTER_BASEBAND, - (radio_filter_t){.hz = bandwidth}); - if (result == RADIO_OK) { - radio_filter_t real = radio_get_filter( - &radio, - RADIO_CHANNEL0, - RADIO_FILTER_BASEBAND); - hackrf_ui()->set_filter_bw(real.hz); - usb_transfer_schedule_ack(endpoint->in); - return USB_REQUEST_STATUS_OK; - } - return USB_REQUEST_STATUS_STALL; - } else { - return USB_REQUEST_STATUS_OK; + RADIO_BANK_ACTIVE, + RADIO_BB_BANDWIDTH_TX, + bandwidth); + radio_reg_write( + &radio, + RADIO_BANK_ACTIVE, + RADIO_BB_BANDWIDTH_RX, + bandwidth); + hackrf_ui()->set_filter_bw(bandwidth); + usb_transfer_schedule_ack(endpoint->in); } + return USB_REQUEST_STATUS_OK; } usb_request_status_t usb_vendor_request_set_freq( @@ -109,23 +105,28 @@ usb_request_status_t usb_vendor_request_set_freq( sizeof(set_freq_params_t), NULL, NULL); - return USB_REQUEST_STATUS_OK; } else if (stage == USB_TRANSFER_STAGE_DATA) { const uint64_t freq = set_freq_params.freq_mhz * 1000000ULL + set_freq_params.freq_hz; - radio_error_t result = radio_set_frequency( + radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_FREQUENCY_RF, freq << 24); + radio_reg_write( &radio, - RADIO_CHANNEL0, - RADIO_FREQUENCY_RF, - (radio_frequency_t){.hz = freq}); - if (result == RADIO_OK) { - usb_transfer_schedule_ack(endpoint->in); - return USB_REQUEST_STATUS_OK; - } - return USB_REQUEST_STATUS_STALL; - } else { - return USB_REQUEST_STATUS_OK; + RADIO_BANK_ACTIVE, + RADIO_FREQUENCY_IF, + RADIO_UNSET); + radio_reg_write( + &radio, + RADIO_BANK_ACTIVE, + RADIO_FREQUENCY_LO, + RADIO_UNSET); + radio_reg_write( + &radio, + RADIO_BANK_ACTIVE, + RADIO_IMAGE_REJECT, + RADIO_UNSET); + usb_transfer_schedule_ack(endpoint->in); } + return USB_REQUEST_STATUS_OK; } usb_request_status_t usb_vendor_request_set_freq_explicit( @@ -139,24 +140,25 @@ usb_request_status_t usb_vendor_request_set_freq_explicit( sizeof(struct set_freq_explicit_params), NULL, NULL); - return USB_REQUEST_STATUS_OK; } else if (stage == USB_TRANSFER_STAGE_DATA) { - radio_error_t result = radio_set_frequency( + radio_reg_write( &radio, - RADIO_CHANNEL0, - RADIO_FREQUENCY_RF, - (radio_frequency_t){ - .if_hz = explicit_params.if_freq_hz, - .lo_hz = explicit_params.lo_freq_hz, - .path = explicit_params.path}); - if (result == RADIO_OK) { - usb_transfer_schedule_ack(endpoint->in); - return USB_REQUEST_STATUS_OK; - } - return USB_REQUEST_STATUS_STALL; - } else { - return USB_REQUEST_STATUS_OK; + RADIO_BANK_ACTIVE, + RADIO_FREQUENCY_IF, + explicit_params.if_freq_hz << 24); + radio_reg_write( + &radio, + RADIO_BANK_ACTIVE, + RADIO_FREQUENCY_LO, + explicit_params.lo_freq_hz << 24); + radio_reg_write( + &radio, + RADIO_BANK_ACTIVE, + RADIO_IMAGE_REJECT, + explicit_params.path); + usb_transfer_schedule_ack(endpoint->in); } + return USB_REQUEST_STATUS_OK; } usb_request_status_t usb_vendor_request_set_sample_rate_frac( @@ -170,49 +172,34 @@ usb_request_status_t usb_vendor_request_set_sample_rate_frac( sizeof(set_sample_r_params_t), NULL, NULL); - return USB_REQUEST_STATUS_OK; } else if (stage == USB_TRANSFER_STAGE_DATA) { - radio_error_t result = radio_set_sample_rate( - &radio, - RADIO_CHANNEL0, - RADIO_SAMPLE_RATE_CLOCKGEN, - (radio_sample_rate_t){ - .num = set_sample_r_params.freq_hz, - .div = set_sample_r_params.divider, - }); - if (result == RADIO_OK) { - usb_transfer_schedule_ack(endpoint->in); - return USB_REQUEST_STATUS_OK; - } - return USB_REQUEST_STATUS_STALL; - } else { - return USB_REQUEST_STATUS_OK; + uint32_t numerator = set_sample_r_params.freq_hz; + uint64_t denominator = set_sample_r_params.divider; + uint64_t value = (denominator << 32) | numerator; + radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_SAMPLE_RATE_FRAC, value); + usb_transfer_schedule_ack(endpoint->in); } + return USB_REQUEST_STATUS_OK; } usb_request_status_t usb_vendor_request_set_amp_enable( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { - radio_gain_t off = {.enable = false}; - radio_gain_t on = {.enable = true}; - if (stage == USB_TRANSFER_STAGE_SETUP) { - switch (endpoint->setup.value) { - case 0: - radio_set_gain(&radio, RADIO_CHANNEL0, RADIO_GAIN_RF_AMP, off); - usb_transfer_schedule_ack(endpoint->in); - return USB_REQUEST_STATUS_OK; - case 1: - radio_set_gain(&radio, RADIO_CHANNEL0, RADIO_GAIN_RF_AMP, on); - usb_transfer_schedule_ack(endpoint->in); - return USB_REQUEST_STATUS_OK; - default: - return USB_REQUEST_STATUS_STALL; - } - } else { - return USB_REQUEST_STATUS_OK; + radio_reg_write( + &radio, + RADIO_BANK_ACTIVE, + RADIO_GAIN_TX_RF, + endpoint->setup.value); + radio_reg_write( + &radio, + RADIO_BANK_ACTIVE, + RADIO_GAIN_RX_RF, + endpoint->setup.value); + usb_transfer_schedule_ack(endpoint->in); } + return USB_REQUEST_STATUS_OK; } usb_request_status_t usb_vendor_request_set_lna_gain( @@ -220,13 +207,10 @@ usb_request_status_t usb_vendor_request_set_lna_gain( const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { - radio_gain_t gain = {.db = endpoint->setup.index}; - uint8_t value = - radio_set_gain(&radio, RADIO_CHANNEL0, RADIO_GAIN_RX_LNA, gain); - endpoint->buffer[0] = value; - if (value) { - hackrf_ui()->set_bb_lna_gain(endpoint->setup.index); - } + uint8_t gain = endpoint->setup.index; + radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_GAIN_RX_IF, gain); + endpoint->buffer[0] = RADIO_OK; + hackrf_ui()->set_bb_lna_gain(gain); usb_transfer_schedule_block( endpoint->in, &endpoint->buffer, @@ -234,7 +218,6 @@ usb_request_status_t usb_vendor_request_set_lna_gain( NULL, NULL); usb_transfer_schedule_ack(endpoint->out); - return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_OK; } @@ -244,13 +227,10 @@ usb_request_status_t usb_vendor_request_set_vga_gain( const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { - radio_gain_t gain = {.db = endpoint->setup.index}; - uint8_t value = - radio_set_gain(&radio, RADIO_CHANNEL0, RADIO_GAIN_RX_VGA, gain); - endpoint->buffer[0] = value; - if (value) { - hackrf_ui()->set_bb_vga_gain(endpoint->setup.index); - } + uint8_t gain = endpoint->setup.index; + radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_GAIN_RX_BB, gain); + endpoint->buffer[0] = RADIO_OK; + hackrf_ui()->set_bb_vga_gain(gain); usb_transfer_schedule_block( endpoint->in, &endpoint->buffer, @@ -258,7 +238,6 @@ usb_request_status_t usb_vendor_request_set_vga_gain( NULL, NULL); usb_transfer_schedule_ack(endpoint->out); - return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_OK; } @@ -268,13 +247,10 @@ usb_request_status_t usb_vendor_request_set_txvga_gain( const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { - radio_gain_t gain = {.db = endpoint->setup.index}; - uint8_t value = - radio_set_gain(&radio, RADIO_CHANNEL0, RADIO_GAIN_TX_VGA, gain); - endpoint->buffer[0] = value; - if (value) { - hackrf_ui()->set_bb_tx_vga_gain(endpoint->setup.index); - } + uint8_t gain = endpoint->setup.index; + radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_GAIN_TX_IF, gain); + endpoint->buffer[0] = RADIO_OK; + hackrf_ui()->set_bb_tx_vga_gain(gain); usb_transfer_schedule_block( endpoint->in, &endpoint->buffer, @@ -282,7 +258,6 @@ usb_request_status_t usb_vendor_request_set_txvga_gain( NULL, NULL); usb_transfer_schedule_ack(endpoint->out); - return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_OK; } @@ -291,33 +266,15 @@ usb_request_status_t usb_vendor_request_set_antenna_enable( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { - radio_antenna_t off = {.enable = false}; - radio_antenna_t on = {.enable = true}; - if (stage == USB_TRANSFER_STAGE_SETUP) { - switch (endpoint->setup.value) { - case 0: - radio_set_antenna( - &radio, - RADIO_CHANNEL0, - RADIO_ANTENNA_BIAS_TEE, - off); - usb_transfer_schedule_ack(endpoint->in); - return USB_REQUEST_STATUS_OK; - case 1: - radio_set_antenna( - &radio, - RADIO_CHANNEL0, - RADIO_ANTENNA_BIAS_TEE, - on); - usb_transfer_schedule_ack(endpoint->in); - return USB_REQUEST_STATUS_OK; - default: - return USB_REQUEST_STATUS_STALL; - } - } else { - return USB_REQUEST_STATUS_OK; + radio_reg_write( + &radio, + RADIO_BANK_ACTIVE, + RADIO_BIAS_TEE, + endpoint->setup.value); + usb_transfer_schedule_ack(endpoint->in); } + return USB_REQUEST_STATUS_OK; } static volatile uint32_t _tx_underrun_limit; @@ -348,13 +305,13 @@ void transceiver_shutdown(void) led_off(LED2); led_off(LED3); - radio_switch_mode(&radio, RADIO_CHANNEL0, TRANSCEIVER_MODE_OFF); + radio_switch_opmode(&radio, TRANSCEIVER_MODE_OFF); m0_set_mode(M0_MODE_IDLE); } void transceiver_startup(const transceiver_mode_t mode) { - radio_switch_mode(&radio, RADIO_CHANNEL0, mode); + radio_switch_opmode(&radio, mode); hackrf_ui()->set_transceiver_mode(mode); switch (mode) { @@ -376,7 +333,6 @@ void transceiver_startup(const transceiver_mode_t mode) } activate_best_clock_source(); - trigger_enable(radio_get_trigger_enable(&radio, RADIO_CHANNEL0)); } usb_request_status_t usb_vendor_request_set_transceiver_mode( @@ -406,18 +362,14 @@ 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_enable( + radio_reg_write( &radio, - RADIO_CHANNEL0, - endpoint->setup.value != 0); - if (result == RADIO_OK) { - usb_transfer_schedule_ack(endpoint->in); - return USB_REQUEST_STATUS_OK; - } - return USB_REQUEST_STATUS_STALL; - } else { - return USB_REQUEST_STATUS_OK; + RADIO_BANK_ACTIVE, + RADIO_TRIGGER, + endpoint->setup.value); + usb_transfer_schedule_ack(endpoint->in); } + return USB_REQUEST_STATUS_OK; } usb_request_status_t usb_vendor_request_set_tx_underrun_limit( From b4041dd550274b3437ed3dbadc8ed457e8b0d83e Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Wed, 11 Feb 2026 11:21:43 -0500 Subject: [PATCH 021/238] Add radio register access from host --- firmware/hackrf_usb/hackrf_usb.c | 2 + firmware/hackrf_usb/usb_api_register.c | 83 ++++++++++- firmware/hackrf_usb/usb_api_register.h | 8 +- firmware/hackrf_usb/usb_descriptor.c | 4 +- host/hackrf-tools/src/hackrf_debug.c | 186 +++++++++++++++++++++---- host/libhackrf/CMakeLists.txt | 3 +- host/libhackrf/src/hackrf.c | 74 +++++++++- host/libhackrf/src/hackrf.h | 34 ++++- 8 files changed, 357 insertions(+), 37 deletions(-) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 06e0079d..9986ceac 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -152,6 +152,8 @@ static usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_read_selftest, usb_vendor_request_adc_read, usb_vendor_request_test_rtc_osc, + usb_vendor_request_write_radio_reg, + usb_vendor_request_read_radio_reg, }; static const uint32_t vendor_request_handler_count = diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index 2cd57cb9..19360415 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Jared Boone * Copyright 2013 Benjamin Vernoux * @@ -283,3 +283,84 @@ usb_request_status_t usb_vendor_request_read_fpga_reg( return USB_REQUEST_STATUS_OK; } #endif + +/* + * Each register is transferred as a uint8_t register number followed by a + * little-endian uint64_t value for a total of 9 bytes. + */ +static uint8_t radio_reg_buf[RADIO_NUM_REGS * 9]; + +usb_request_status_t usb_vendor_request_write_radio_reg( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage) +{ + uint8_t bank; + if (stage == USB_TRANSFER_STAGE_SETUP) { + bank = endpoint->setup.index; + if (bank >= RADIO_NUM_BANKS) { + return USB_REQUEST_STATUS_STALL; + } + uint8_t num_regs = endpoint->setup.length / 9; + if ((num_regs == 0) || (num_regs > RADIO_NUM_REGS)) { + return USB_REQUEST_STATUS_STALL; + } + usb_transfer_schedule_block( + endpoint->out, + &radio_reg_buf, + endpoint->setup.length, + NULL, + NULL); + } else if (stage == USB_TRANSFER_STAGE_DATA) { + uint8_t address, i; + uint64_t value; + bank = endpoint->setup.index; + for (i = 0; i < endpoint->setup.length; i += 9) { + address = radio_reg_buf[i]; + value = radio_reg_buf[i + 1] | + ((uint64_t) radio_reg_buf[i + 2] << 8) | + ((uint64_t) radio_reg_buf[i + 3] << 16) | + ((uint64_t) radio_reg_buf[i + 4] << 24) | + ((uint64_t) radio_reg_buf[i + 5] << 32) | + ((uint64_t) radio_reg_buf[i + 6] << 40) | + ((uint64_t) radio_reg_buf[i + 7] << 48) | + ((uint64_t) radio_reg_buf[i + 8] << 56); + radio_error_t result = + radio_reg_write(&radio, bank, address, value); + if (result != RADIO_OK) { + return USB_REQUEST_STATUS_STALL; + } + } + usb_transfer_schedule_ack(endpoint->in); + } + return USB_REQUEST_STATUS_OK; +} + +usb_request_status_t usb_vendor_request_read_radio_reg( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage) +{ + if (stage == USB_TRANSFER_STAGE_SETUP) { + uint8_t bank = endpoint->setup.index; + uint8_t address = endpoint->setup.value; + if ((bank >= RADIO_NUM_BANKS) || (address >= RADIO_NUM_REGS)) { + return USB_REQUEST_STATUS_STALL; + } + uint64_t value = radio_reg_read(&radio, bank, address); + endpoint->buffer[0] = value & 0xff; + endpoint->buffer[1] = (value >> 8) & 0xff; + endpoint->buffer[2] = (value >> 16) & 0xff; + endpoint->buffer[3] = (value >> 24) & 0xff; + endpoint->buffer[4] = (value >> 32) & 0xff; + endpoint->buffer[5] = (value >> 40) & 0xff; + endpoint->buffer[6] = (value >> 48) & 0xff; + endpoint->buffer[7] = (value >> 56) & 0xff; + usb_transfer_schedule_block( + endpoint->in, + &endpoint->buffer, + 8, + NULL, + NULL); + usb_transfer_schedule_ack(endpoint->out); + } + return USB_REQUEST_STATUS_OK; +} diff --git a/firmware/hackrf_usb/usb_api_register.h b/firmware/hackrf_usb/usb_api_register.h index 8fc62c2c..07714b39 100644 --- a/firmware/hackrf_usb/usb_api_register.h +++ b/firmware/hackrf_usb/usb_api_register.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Jared Boone * Copyright 2013 Benjamin Vernoux * @@ -65,5 +65,11 @@ usb_request_status_t usb_vendor_request_read_fpga_reg( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); #endif +usb_request_status_t usb_vendor_request_write_radio_reg( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage); +usb_request_status_t usb_vendor_request_read_radio_reg( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage); #endif /* end of include guard: __USB_API_REGISTER_H__ */ diff --git a/firmware/hackrf_usb/usb_descriptor.c b/firmware/hackrf_usb/usb_descriptor.c index 68b2ea81..679a9589 100644 --- a/firmware/hackrf_usb/usb_descriptor.c +++ b/firmware/hackrf_usb/usb_descriptor.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Jared Boone * * This file is part of HackRF. @@ -37,7 +37,7 @@ #define USB_PRODUCT_ID (0xFFFF) #endif -#define USB_API_VERSION (0x0110) +#define USB_API_VERSION (0x0111) #define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF) diff --git a/host/hackrf-tools/src/hackrf_debug.c b/host/hackrf-tools/src/hackrf_debug.c index b3045b18..5f8785b5 100644 --- a/host/hackrf-tools/src/hackrf_debug.c +++ b/host/hackrf-tools/src/hackrf_debug.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Jared Boone * Copyright 2013 Benjamin Vernoux * Copyright 2017 Dominic Spill @@ -29,6 +29,7 @@ #include #include #include +#include #define REGISTER_INVALID 32767 @@ -39,13 +40,14 @@ enum parts { PART_RFFC5072 = 3, PART_MAX2831 = 4, PART_GATEWARE = 5, + PART_RADIO = 6, }; -int parse_int(char* s, uint32_t* const value) +int parse_int(char* s, uint64_t* const value) { uint_fast8_t base = 10; char* s_end; - long long_value; + long long ll_value; if (strlen(s) > 2) { if (s[0] == '0') { @@ -60,9 +62,9 @@ int parse_int(char* s, uint32_t* const value) } s_end = s; - long_value = strtol(s, &s_end, base); + ll_value = strtoull(s, &s_end, base); if ((s != s_end) && (*s_end == 0)) { - *value = (uint32_t) long_value; + *value = (uint64_t) ll_value; return HACKRF_SUCCESS; } else { return HACKRF_ERROR_INVALID_PARAM; @@ -473,7 +475,81 @@ int fpga_write_register( return result; } -int read_register(hackrf_device* device, uint8_t part, const uint16_t register_number) +int radio_read_register( + hackrf_device* device, + const uint8_t bank, + const uint16_t register_number) +{ + uint64_t register_value; + int result = hackrf_radio_read_register( + device, + bank, + (uint8_t) register_number, + ®ister_value); + + if (result == HACKRF_SUCCESS) { + printf("bank %d register [%2d] -> 0x%016" PRIx64 "\n", + bank, + register_number, + register_value); + } else { + printf("hackrf_radio_read_register() failed: %s (%d)\n", + hackrf_error_name(result), + result); + } + + return result; +} + +#define RADIO_NUM_REGS (24) + +int radio_read_registers(hackrf_device* device, const uint8_t bank) +{ + uint16_t register_number; + int result = HACKRF_SUCCESS; + + for (register_number = 0; register_number < RADIO_NUM_REGS; register_number++) { + result = radio_read_register(device, bank, register_number); + if (result != HACKRF_SUCCESS) { + break; + } + } + + return result; +} + +int radio_write_register( + hackrf_device* device, + const uint8_t bank, + const uint16_t register_number, + const uint64_t register_value) +{ + int result = HACKRF_SUCCESS; + result = hackrf_radio_write_register( + device, + bank, + (uint8_t) register_number, + register_value); + + if (result == HACKRF_SUCCESS) { + printf("bank %d 0x%016" PRIx64 " -> [%2d]\n", + bank, + register_value, + register_number); + } else { + printf("hackrf_radio_write_register() failed: %s (%d)\n", + hackrf_error_name(result), + result); + } + + return result; +} + +int read_register( + hackrf_device* device, + uint8_t part, + const uint8_t bank, + const uint16_t register_number) { switch (part) { case PART_MAX2837: @@ -485,11 +561,13 @@ int read_register(hackrf_device* device, uint8_t part, const uint16_t register_n return rffc5072_read_register(device, register_number); case PART_GATEWARE: return fpga_read_register(device, register_number); + case PART_RADIO: + return radio_read_register(device, bank, register_number); } return HACKRF_ERROR_INVALID_PARAM; } -int read_registers(hackrf_device* device, uint8_t part) +int read_registers(hackrf_device* device, uint8_t part, const uint8_t bank) { switch (part) { case PART_MAX2837: @@ -501,6 +579,8 @@ int read_registers(hackrf_device* device, uint8_t part) return rffc5072_read_registers(device); case PART_GATEWARE: return fpga_read_registers(device); + case PART_RADIO: + return radio_read_registers(device, bank); } return HACKRF_ERROR_INVALID_PARAM; } @@ -508,8 +588,9 @@ int read_registers(hackrf_device* device, uint8_t part) int write_register( hackrf_device* device, uint8_t part, + const uint8_t bank, const uint16_t register_number, - const uint16_t register_value) + const uint64_t register_value) { switch (part) { case PART_MAX2837: @@ -517,14 +598,25 @@ int write_register( return max283x_write_register( device, register_number, - register_value, + (uint16_t) register_value, part); case PART_SI5351C: - return si5351c_write_register(device, register_number, register_value); + return si5351c_write_register( + device, + register_number, + (uint16_t) register_value); case PART_RFFC5072: - return rffc5072_write_register(device, register_number, register_value); + return rffc5072_write_register( + device, + register_number, + (uint16_t) register_value); case PART_GATEWARE: - return fpga_write_register(device, register_number, register_value); + return fpga_write_register( + device, + register_number, + (uint16_t) register_value); + case PART_RADIO: + return radio_write_register(device, bank, register_number, register_value); } return HACKRF_ERROR_INVALID_PARAM; } @@ -579,6 +671,7 @@ static void usage() { printf("\nUsage:\n"); printf("\t-h, --help: this help\n"); + printf("\t-b, --bank : set register bank for read/write operations (default 0)\n"); printf("\t-n, --register : set register number for read/write operations\n"); printf("\t-r, --read: read register specified by last -n argument, or all registers\n"); printf("\t-w, --write : write register specified by last -n argument with value \n"); @@ -588,6 +681,7 @@ static void usage() printf("\t-s, --si5351c: target SI5351C\n"); printf("\t-f, --rffc5072: target RFFC5072\n"); printf("\t-g, --gateware: target gateware registers\n"); + printf("\t-i, --radio: target radio registers\n"); printf("\t-P, --fpga : load the n-th bitstream to the FPGA\n"); printf("\t-1, --p1 : P1 control\n"); printf("\t-2, --p2 : P2 control\n"); @@ -611,6 +705,7 @@ static void usage() static struct option long_options[] = { {"config", no_argument, 0, 'c'}, + {"bank", required_argument, 0, 'b'}, {"register", required_argument, 0, 'n'}, {"write", required_argument, 0, 'w'}, {"read", no_argument, 0, 'r'}, @@ -621,6 +716,7 @@ static struct option long_options[] = { {"si5351c", no_argument, 0, 's'}, {"rffc5072", no_argument, 0, 'f'}, {"gateware", no_argument, 0, 'g'}, + {"radio", no_argument, 0, 'i'}, {"fpga", required_argument, 0, 'P'}, {"p1", required_argument, 0, '1'}, {"p2", required_argument, 0, '2'}, @@ -641,8 +737,9 @@ int main(int argc, char** argv) { int opt; uint8_t board_id = BOARD_ID_UNDETECTED; - uint32_t register_number = REGISTER_INVALID; - uint32_t register_value; + int bank = -1; + uint64_t register_number = REGISTER_INVALID; + uint64_t register_value; hackrf_device* device = NULL; int option_index = 0; bool read = false; @@ -652,17 +749,17 @@ int main(int argc, char** argv) uint8_t part = PART_NONE; const char* serial_number = NULL; bool set_ui = false; - uint32_t ui_enable; + uint64_t ui_enable; bool set_leds = false; - uint32_t led_state; - uint32_t tx_limit; - uint32_t rx_limit; - uint32_t p1_state; - uint32_t p2_state; - uint32_t clkin_state; - uint32_t narrowband_state; - uint32_t bitstream_index; - uint32_t adc_channel; + uint64_t led_state; + uint64_t tx_limit; + uint64_t rx_limit; + uint64_t p1_state; + uint64_t p2_state; + uint64_t clkin_state; + uint64_t narrowband_state; + uint64_t bitstream_index; + uint64_t adc_channel; bool set_tx_limit = false; bool set_rx_limit = false; bool set_p1 = false; @@ -685,10 +782,16 @@ int main(int argc, char** argv) while ((opt = getopt_long( argc, argv, - "n:rw:d:cmsfg1:2:C:N:P:ST:R:h?u:l:ta:o", + "b:n:rw:d:cmsfgi1:2:C:N:P:ST:R:h?u:l:ta:o", long_options, &option_index)) != EOF) { switch (opt) { + case 'b': + uint64_t bank_arg; + result = parse_int(optarg, &bank_arg); + bank = (int) bank_arg; + break; + case 'n': result = parse_int(optarg, ®ister_number); break; @@ -755,6 +858,14 @@ int main(int argc, char** argv) part = PART_GATEWARE; break; + case 'i': + if (part != PART_NONE) { + fprintf(stderr, "Only one part can be specified.'\n"); + return EXIT_FAILURE; + } + part = PART_RADIO; + break; + case '1': set_p1 = true; result = parse_int(optarg, &p1_state); @@ -838,6 +949,16 @@ int main(int argc, char** argv) return EXIT_FAILURE; } + if ((bank > -1) && (part != PART_RADIO)) { + fprintf(stderr, "Bank valid only for radio.\n"); + usage(); + return EXIT_FAILURE; + } + + if ((bank == -1) && (part == PART_RADIO)) { + bank = 0; + } + if (!(write || read || dump_config || dump_state || set_tx_limit || set_rx_limit || set_ui || set_leds || set_p1 || set_p2 || set_clkin || set_narrowband || set_fpga_bitstream || read_selftest || test_rtc_osc || @@ -879,14 +1000,19 @@ int main(int argc, char** argv) } if (write) { - result = write_register(device, part, register_number, register_value); + result = write_register( + device, + part, + bank, + register_number, + register_value); } if (read) { if (register_number == REGISTER_INVALID) { - result = read_registers(device, part); + result = read_registers(device, part, bank); } else { - result = read_register(device, part, register_number); + result = read_register(device, part, bank, register_number); } } @@ -1025,8 +1151,8 @@ int main(int argc, char** argv) return EXIT_FAILURE; } printf("ADC0_%d (%s pin): %d\n", - adc_channel & 0x7, - adc_channel & 0x80 ? "alternate" : "dedicated", + ((uint8_t) adc_channel) & 0x7, + ((uint8_t) adc_channel) & 0x80 ? "alternate" : "dedicated", value); } diff --git a/host/libhackrf/CMakeLists.txt b/host/libhackrf/CMakeLists.txt index 37f124e6..61ad494c 100644 --- a/host/libhackrf/CMakeLists.txt +++ b/host/libhackrf/CMakeLists.txt @@ -1,3 +1,4 @@ +# Copyright 2012-2026 Great Scott Gadgets # Copyright 2012 Jared Boone # Copyright 2013 Benjamin Vernoux # @@ -20,7 +21,7 @@ cmake_minimum_required(VERSION 3.10.0) project( libhackrf LANGUAGES C - VERSION 0.9.2) + VERSION 0.10.0) include(GNUInstallDirs) include(${PROJECT_SOURCE_DIR}/../cmake/set_release.cmake) set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 3ada04b2..48a25868 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2012-2022 Great Scott Gadgets +Copyright (c) 2012-2026 Great Scott Gadgets Copyright (c) 2012, Jared Boone Copyright (c) 2013, Benjamin Vernoux @@ -45,11 +45,13 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI #define TO_LE64(x) __builtin_bswap64(x) #define FROM_LE16(x) __builtin_bswap16(x) #define FROM_LE32(x) __builtin_bswap32(x) + #define FROM_LE64(x) __builtin_bswap64(x) #else #define TO_LE(x) x #define TO_LE64(x) x #define FROM_LE16(x) x #define FROM_LE32(x) x + #define FROM_LE64(x) x #endif // TODO: Factor this into a shared #include so that firmware can use @@ -111,6 +113,8 @@ typedef enum { HACKRF_VENDOR_REQUEST_READ_SELFTEST = 56, HACKRF_VENDOR_REQUEST_READ_ADC = 57, HACKRF_VENDOR_REQUEST_TEST_RTC_OSC = 58, + HACKRF_VENDOR_REQUEST_RADIO_WRITE_REG = 59, + HACKRF_VENDOR_REQUEST_RADIO_READ_REG = 60, } hackrf_vendor_request; #define USB_CONFIG_STANDARD 0x1 @@ -3476,6 +3480,74 @@ int ADDCALL hackrf_set_fpga_bitstream(hackrf_device* device, const uint8_t index } } +int ADDCALL hackrf_radio_read_register( + hackrf_device* device, + const uint8_t bank, + const uint8_t register_number, + uint64_t* const value) +{ + USB_API_REQUIRED(device, 0x0111); + int result; + + const uint8_t length = sizeof(value); + result = libusb_control_transfer( + device->usb_device, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_RADIO_READ_REG, + register_number, + bank, + (unsigned char*) value, + length, + 0); + *value = FROM_LE64(*value); + + if (result < length) { + last_libusb_error = result; + return HACKRF_ERROR_LIBUSB; + } else { + return HACKRF_SUCCESS; + } +} + +int ADDCALL hackrf_radio_write_register( + hackrf_device* device, + const uint8_t bank, + const uint8_t register_number, + const uint64_t value) +{ + USB_API_REQUIRED(device, 0x0111); + int result; + + unsigned char data[9]; + data[0] = register_number; + data[1] = value & 0xff; + data[2] = (value >> 8) & 0xff; + data[3] = (value >> 16) & 0xff; + data[4] = (value >> 24) & 0xff; + data[5] = (value >> 32) & 0xff; + data[6] = (value >> 40) & 0xff; + data[7] = (value >> 48) & 0xff; + data[8] = (value >> 56) & 0xff; + + result = libusb_control_transfer( + device->usb_device, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | + LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_RADIO_WRITE_REG, + 0, + bank, + &data[0], + sizeof(data), + 0); + + if (result < 9) { + last_libusb_error = result; + return HACKRF_ERROR_LIBUSB; + } else { + return HACKRF_SUCCESS; + } +} + #ifdef __cplusplus } // __cplusplus defined. #endif diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index 0247e6ca..e00ba3ff 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2012-2022 Great Scott Gadgets +Copyright (c) 2012-2026 Great Scott Gadgets Copyright (c) 2012, Jared Boone Copyright (c) 2013, Benjamin Vernoux @@ -2354,6 +2354,38 @@ extern ADDAPI int ADDCALL hackrf_set_fpga_bitstream( hackrf_device* device, const uint8_t index); +/** + * Read a radio configuration register + * + * @param[in] device device to query + * @param[in] bank bank number to read + * @param[in] register_number register number to read + * @param[out] value value of the specified register + * @return @ref HACKRF_SUCCESS on success or @ref hackrf_error variant + * @ingroup debug + */ +extern ADDAPI int ADDCALL hackrf_radio_read_register( + hackrf_device* device, + const uint8_t bank, + const uint8_t register_number, + uint64_t* const value); + +/** + * Write to a radio configuration register + * + * @param[in] device device to write + * @param[in] bank bank number to write + * @param[in] register_number register number to write + * @param[out] value value to write in the specified register + * @return @ref HACKRF_SUCCESS on success or @ref hackrf_error variant + * @ingroup debug + */ +extern ADDAPI int ADDCALL hackrf_radio_write_register( + hackrf_device* device, + const uint8_t bank, + const uint8_t register_number, + const uint64_t value); + #ifdef __cplusplus } // __cplusplus defined. #endif From b1bfc246bf8a7459ceec42089b48a7e63a439474 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Fri, 20 Feb 2026 11:30:50 -0500 Subject: [PATCH 022/238] Do not apply radio configuration inside ISRs --- firmware/common/radio.c | 7 +++++++ firmware/hackrf_usb/hackrf_usb.c | 1 + firmware/hackrf_usb/usb_api_sweep.c | 4 ++++ firmware/hackrf_usb/usb_api_transceiver.c | 6 +++++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 75def39b..3f5e1a59 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -19,6 +19,8 @@ * Boston, MA 02110-1301, USA. */ +#include + #include "hackrf_core.h" #include "tuning.h" #include "rf_path.h" @@ -688,12 +690,15 @@ static bool radio_update_dc_block(radio_t* const radio, uint64_t* bank) bool radio_update(radio_t* const radio) { uint64_t tmp_bank[RADIO_NUM_REGS]; + nvic_disable_irq(NVIC_USB0_IRQ); uint32_t dirty = radio->regs_dirty; if (dirty == 0) { + nvic_enable_irq(NVIC_USB0_IRQ); return false; } radio->regs_dirty = 0; memcpy(&tmp_bank[0], &(radio->config[RADIO_BANK_ACTIVE][0]), sizeof(tmp_bank)); + nvic_enable_irq(NVIC_USB0_IRQ); bool dir = false; bool rate = false; @@ -765,6 +770,7 @@ void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode) source_bank = RADIO_BANK_IDLE; } + nvic_disable_irq(NVIC_USB0_IRQ); for (uint8_t reg = 0; reg < RADIO_NUM_REGS; reg++) { value = radio->config[source_bank][reg]; previous = radio->config[RADIO_BANK_ACTIVE][reg]; @@ -775,5 +781,6 @@ void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode) } mark_dirty(radio, RADIO_OPMODE); + nvic_enable_irq(NVIC_USB0_IRQ); radio_update(radio); } diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 9986ceac..d8934514 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -385,6 +385,7 @@ int main(void) nvic_disable_irq(NVIC_USB0_IRQ); request = transceiver_request; nvic_enable_irq(NVIC_USB0_IRQ); + radio_update(&radio); switch (request.mode) { case TRANSCEIVER_MODE_OFF: diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index 85aa5d7c..84a813a1 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -92,12 +92,16 @@ usb_request_status_t usb_vendor_request_init_sweep( ((uint16_t) (data[10 + i * 2]) << 8) + data[9 + i * 2]; } sweep_freq = (uint64_t) frequencies[0] * FREQ_GRANULARITY; + + nvic_disable_irq(NVIC_USB0_IRQ); radio_reg_write( &radio, RADIO_BANK_ACTIVE, RADIO_FREQUENCY_RF, (sweep_freq + offset) << 24); usb_transfer_schedule_ack(endpoint->in); + nvic_enable_irq(NVIC_USB0_IRQ); + radio_update(&radio); } return USB_REQUEST_STATUS_OK; } diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 76399ae9..6a72a1f4 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -420,6 +420,7 @@ void rx_mode(uint32_t seq) NULL); usb_count += USB_TRANSFER_SIZE; } + radio_update(&radio); } transceiver_shutdown(); @@ -456,6 +457,7 @@ void tx_mode(uint32_t seq) NULL); usb_count += USB_TRANSFER_SIZE; } + radio_update(&radio); } transceiver_shutdown(); @@ -465,5 +467,7 @@ void off_mode(uint32_t seq) { hackrf_ui()->set_transceiver_mode(TRANSCEIVER_MODE_OFF); - while (transceiver_request.seq == seq) {} + while (transceiver_request.seq == seq) { + radio_update(&radio); + } } From a2b2728234baaee862226a68ac38de6979c6dc9f Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 10 Feb 2026 12:00:02 -0500 Subject: [PATCH 023/238] Implement bias tee with radio registers --- firmware/common/radio.c | 2 +- firmware/common/rf_path.c | 4 - firmware/common/user_config.c | 112 ------------------------- firmware/common/user_config.h | 43 ---------- firmware/hackrf-common.cmake | 1 - firmware/hackrf_usb/usb_api_register.c | 38 ++++++++- 6 files changed, 37 insertions(+), 163 deletions(-) delete mode 100644 firmware/common/user_config.c delete mode 100644 firmware/common/user_config.h diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 3f5e1a59..482da9fb 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -736,7 +736,7 @@ bool radio_update(radio_t* const radio) (1 << RADIO_GAIN_RX_IF) | (1 << RADIO_GAIN_RX_BB) | (1 << RADIO_OPMODE))) { gain = radio_update_gain(radio, &tmp_bank[0]); } - if (dirty & (1 << RADIO_BIAS_TEE)) { + if (dirty & ((1 << RADIO_BIAS_TEE) | (1 << RADIO_OPMODE))) { bias = radio_update_bias_tee(radio, &tmp_bank[0]); } if (dirty & (1 << RADIO_TRIGGER)) { diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 463942ca..87f0bb94 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -35,7 +35,6 @@ #include "max283x.h" #include "max5864.h" #include "sgpio.h" -#include "user_config.h" #if (defined JAWBREAKER || defined HACKRF_ONE || defined RAD1O || defined PRALINE) /* @@ -467,9 +466,6 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d /* Turn off TX and RX amplifiers, then enable based on direction and bypass state. */ rf_path->switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_NO_RX_AMP_PWR; - // Perform any user-requested actions for mode switch - user_config_on_rf_path_direction_change(rf_path, direction); - switch (direction) { case RF_PATH_DIRECTION_TX: rf_path->switchctrl |= SWITCHCTRL_TX; diff --git a/firmware/common/user_config.c b/firmware/common/user_config.c deleted file mode 100644 index 6c1ba419..00000000 --- a/firmware/common/user_config.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2023 Jonathan Suite (GitHub: @ai6aj) - * - * This file is part of HackRF. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include "user_config.h" - -static user_config_user_opt_t user_direction_rx_bias_t_opts = RF_DIRECTION_USER_OPT_NOP; -static user_config_user_opt_t user_direction_tx_bias_t_opts = RF_DIRECTION_USER_OPT_NOP; -static user_config_user_opt_t user_direction_off_bias_t_opts = - RF_DIRECTION_USER_OPT_CLEAR; - -// Perform user-specified actions to Bias T power when transitioning modes -static void _rf_path_handle_user_bias_t_action(rf_path_t* const rf_path, int action) -{ - switch (action) { - case RF_DIRECTION_USER_OPT_SET: - rf_path_set_antenna(rf_path, 1); - break; - - case RF_DIRECTION_USER_OPT_CLEAR: - rf_path_set_antenna(rf_path, 0); - break; - - case RF_DIRECTION_USER_OPT_NOP: - default: - break; - } -} - -void user_config_on_rf_path_direction_change( - rf_path_t* const rf_path, - const rf_path_direction_t direction) -{ - switch (direction) { - case RF_PATH_DIRECTION_RX: - _rf_path_handle_user_bias_t_action(rf_path, user_direction_rx_bias_t_opts); - break; - - case RF_PATH_DIRECTION_TX: - _rf_path_handle_user_bias_t_action(rf_path, user_direction_tx_bias_t_opts); - break; - - case RF_PATH_DIRECTION_OFF: - default: - _rf_path_handle_user_bias_t_action( - rf_path, - user_direction_off_bias_t_opts); - break; - } -} - -void user_config_set_bias_t_opt( - const rf_path_direction_t direction, - const user_config_user_opt_t option) -{ - switch (direction) { - case RF_PATH_DIRECTION_RX: - user_direction_rx_bias_t_opts = option; - break; - - case RF_PATH_DIRECTION_TX: - user_direction_tx_bias_t_opts = option; - break; - - case RF_PATH_DIRECTION_OFF: - user_direction_off_bias_t_opts = option; - break; - - default: - break; - } -} - -/* - Bias T options are set as follows: - Bits 0,1: One of NOP (0), CLEAR (0b10), or SET (0b11) - Bit 2: 1=Set OFF behavior according to bits 0,1 0=Don't change - Bits 3,4: One of NOP (0), CLEAR (0b10), or SET (0b11) - Bit 5: 1=Set RX behavior according to bits 0,1 0=Don't change - Bits 6,7: One of NOP (0), CLEAR (0b10), or SET (0b11) - Bit 8: 1=Set TX behavior according to bits 0,1 0=Don't change - Bits 9-15: Ignored; set to 0 -*/ -void user_config_set_bias_t_opts(uint16_t value) -{ - if (value & 0x4) { - user_config_set_bias_t_opt(RF_PATH_DIRECTION_OFF, value & 0x3); - } - if (value & 0x20) { - user_config_set_bias_t_opt(RF_PATH_DIRECTION_RX, (value & 0x18) >> 3); - } - if (value & 0x100) { - user_config_set_bias_t_opt(RF_PATH_DIRECTION_TX, (value & 0xC0) >> 6); - } -} diff --git a/firmware/common/user_config.h b/firmware/common/user_config.h deleted file mode 100644 index 114ba0f3..00000000 --- a/firmware/common/user_config.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2023 Jonathan Suite (GitHub: @ai6aj) - * - * This file is part of HackRF. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __USER_CONFIG_H__ -#define __USER_CONFIG_H__ - -#include "rf_path.h" - -typedef enum { - RF_DIRECTION_USER_OPT_NOP, // No OPeration / Ignore the thing - RF_DIRECTION_USER_OPT_RESERVED, // Currently a NOP - RF_DIRECTION_USER_OPT_CLEAR, // Clear/Disable the thing - RF_DIRECTION_USER_OPT_SET, // Set/Enable the thing -} user_config_user_opt_t; - -void user_config_set_bias_t_opt( - const rf_path_direction_t direction, - const user_config_user_opt_t action); -void user_config_set_bias_t_opts(uint16_t value); - -void user_config_on_rf_path_direction_change( - rf_path_t* const rf_path, - const rf_path_direction_t direction); - -#endif \ No newline at end of file diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 67056d0d..ee6d5f15 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -188,7 +188,6 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/firmware_info.c ${PATH_HACKRF_FIRMWARE_COMMON}/clkin.c ${PATH_HACKRF_FIRMWARE_COMMON}/gpdma.c - ${PATH_HACKRF_FIRMWARE_COMMON}/user_config.c ${PATH_HACKRF_FIRMWARE_COMMON}/radio.c ${PATH_HACKRF_FIRMWARE_COMMON}/selftest.c ${PATH_HACKRF_FIRMWARE_COMMON}/m0_state.c diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index 19360415..48dd5e62 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -1,5 +1,6 @@ /* * Copyright 2012-2026 Great Scott Gadgets + * Copyright 2023 Jonathan Suite (GitHub: @ai6aj) * Copyright 2012 Jared Boone * Copyright 2013 Benjamin Vernoux * @@ -22,7 +23,6 @@ */ #include "usb_api_register.h" -#include #include #include #include @@ -241,12 +241,46 @@ usb_request_status_t usb_vendor_request_set_leds( return USB_REQUEST_STATUS_OK; } +typedef enum { + BIAS_TEE_OPT_NOP = 0, // No OPeration / Ignore the thing + BIAS_TEE_OPT_RESERVED = 1, // Currently a NOP + BIAS_TEE_OPT_CLEAR = 2, // Clear/Disable the thing + BIAS_TEE_OPT_SET = 3, // Set/Enable the thing +} bias_tee_opt_t; + +static void set_bias_tee_opt(const uint8_t bank, const bias_tee_opt_t option) +{ + uint64_t value; + + switch (option) { + case BIAS_TEE_OPT_CLEAR: + value = (uint64_t) false; + break; + case BIAS_TEE_OPT_SET: + value = (uint64_t) true; + break; + default: + value = RADIO_UNSET; + } + + radio_reg_write(&radio, bank, RADIO_BIAS_TEE, value); +} + usb_request_status_t usb_vendor_request_user_config_set_bias_t_opts( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { - user_config_set_bias_t_opts(endpoint->setup.value); + uint16_t value = endpoint->setup.value; + if (value & 0x4) { + set_bias_tee_opt(RADIO_BANK_IDLE, value & 0x3); + } + if (value & 0x20) { + set_bias_tee_opt(RADIO_BANK_RX, (value & 0x18) >> 3); + } + if (value & 0x100) { + set_bias_tee_opt(RADIO_BANK_TX, (value & 0xC0) >> 6); + } usb_transfer_schedule_ack(endpoint->in); } return USB_REQUEST_STATUS_OK; From 71cfa84165a7b7a4c783d53771282977a2439d8a Mon Sep 17 00:00:00 2001 From: grvvy Date: Fri, 20 Feb 2026 13:52:00 -0700 Subject: [PATCH 024/238] mount necessary files for usb command server communication --- Jenkinsfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 76718a59..978df696 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -11,7 +11,7 @@ pipeline { docker { image 'hackrf' reuseNode true - args '--group-add=20 --group-add=46 --device-cgroup-rule="c 189:* rmw" --device-cgroup-rule="c 166:* rmw" -v /dev/bus/usb:/dev/bus/usb -e TESTER=0000000000000000325866e629a25623 -e EUT=RunningFromRAM' + args '--group-add=20 --group-add=46 --device-cgroup-rule="c 189:* rmw" --device-cgroup-rule="c 166:* rmw" -v /dev/bus/usb:/dev/bus/usb -e TESTER=0000000000000000325866e629a25623 -e EUT=RunningFromRAM -v /tmp/req_pipe:/tmp/req_pipe -v /tmp/res_pipe:/tmp/res_pipe' } } steps { @@ -22,6 +22,7 @@ pipeline { sh './ci-scripts/test-host.sh' } sh 'hubs hackrf hackrf_dfu on' + sh 'sleep 1s' sh 'python3 ci-scripts/hackrf_test.py --unattended --ci --log log --rev r4 --manufacturer --hostdir host/build/hackrf-tools/src/ --fwupdate firmware/hackrf_usb/build/ --tester 0000000000000000325866e629a25623 --eut RunningFromRAM' sh 'hubs all off' retry(3) { From 161dc0a7b374fb878d728d333867e96f9dfc03d0 Mon Sep 17 00:00:00 2001 From: grvvy Date: Fri, 20 Feb 2026 13:53:23 -0700 Subject: [PATCH 025/238] move hub command from test script to Jenkinsfile for consistency --- Jenkinsfile | 4 ++++ ci-scripts/test-firmware-program.sh | 2 -- ci-scripts/test-host.sh | 2 -- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 978df696..5da39ebf 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -19,6 +19,8 @@ pipeline { sh './ci-scripts/install-firmware.sh' sh 'hubs all off' retry(3) { + sh 'hubs hackrf_dfu reset' + sh 'sleep 1s' sh './ci-scripts/test-host.sh' } sh 'hubs hackrf hackrf_dfu on' @@ -26,6 +28,8 @@ pipeline { sh 'python3 ci-scripts/hackrf_test.py --unattended --ci --log log --rev r4 --manufacturer --hostdir host/build/hackrf-tools/src/ --fwupdate firmware/hackrf_usb/build/ --tester 0000000000000000325866e629a25623 --eut RunningFromRAM' sh 'hubs all off' retry(3) { + sh 'hubs hackrf_dfu reset' + sh 'sleep 1s' sh 'python3 ci-scripts/test-sgpio-debug.py' } sh 'hubs all reset' diff --git a/ci-scripts/test-firmware-program.sh b/ci-scripts/test-firmware-program.sh index a9e786a7..26be84c6 100755 --- a/ci-scripts/test-firmware-program.sh +++ b/ci-scripts/test-firmware-program.sh @@ -1,6 +1,4 @@ #!/bin/bash -hubs hackrf_dfu reset -sleep 1s dfu-util --device 1fc9:000c --alt 0 --download firmware/hackrf_usb/build/hackrf_usb.dfu sleep 1s EXIT_CODE="$?" diff --git a/ci-scripts/test-host.sh b/ci-scripts/test-host.sh index 903fefd0..5cc8b621 100755 --- a/ci-scripts/test-host.sh +++ b/ci-scripts/test-host.sh @@ -1,6 +1,4 @@ #!/bin/bash -hubs hackrf_dfu reset -sleep 1s host/build/hackrf-tools/src/hackrf_info EXIT_CODE="$?" if [ "$EXIT_CODE" == "1" ] From c41cda0424e5084c7d38dc868de1d5efae280c79 Mon Sep 17 00:00:00 2001 From: grvvy Date: Wed, 25 Feb 2026 16:04:21 -0700 Subject: [PATCH 026/238] rename devices --- Jenkinsfile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 5da39ebf..b27cafc9 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -19,20 +19,19 @@ pipeline { sh './ci-scripts/install-firmware.sh' sh 'hubs all off' retry(3) { - sh 'hubs hackrf_dfu reset' + sh 'hubs h1_eut reset' sh 'sleep 1s' sh './ci-scripts/test-host.sh' } - sh 'hubs hackrf hackrf_dfu on' + sh 'hubs h1_tester h1_eut on' sh 'sleep 1s' sh 'python3 ci-scripts/hackrf_test.py --unattended --ci --log log --rev r4 --manufacturer --hostdir host/build/hackrf-tools/src/ --fwupdate firmware/hackrf_usb/build/ --tester 0000000000000000325866e629a25623 --eut RunningFromRAM' sh 'hubs all off' retry(3) { - sh 'hubs hackrf_dfu reset' + sh 'hubs h1_eut reset' sh 'sleep 1s' sh 'python3 ci-scripts/test-sgpio-debug.py' } - sh 'hubs all reset' } } } From 7f7974ce8feb7262cbe3adf3408263190572c85c Mon Sep 17 00:00:00 2001 From: grvvy Date: Wed, 25 Feb 2026 18:07:37 -0700 Subject: [PATCH 027/238] retry hackrf_test up to three times if it fails --- Jenkinsfile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index b27cafc9..1284ca4f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -23,10 +23,12 @@ pipeline { sh 'sleep 1s' sh './ci-scripts/test-host.sh' } - sh 'hubs h1_tester h1_eut on' - sh 'sleep 1s' - sh 'python3 ci-scripts/hackrf_test.py --unattended --ci --log log --rev r4 --manufacturer --hostdir host/build/hackrf-tools/src/ --fwupdate firmware/hackrf_usb/build/ --tester 0000000000000000325866e629a25623 --eut RunningFromRAM' - sh 'hubs all off' + retry(3) { + sh 'hubs h1_tester h1_eut reset' + sh 'sleep 1s' + sh 'python3 ci-scripts/hackrf_test.py --unattended --ci --log log --rev r4 --manufacturer --hostdir host/build/hackrf-tools/src/ --fwupdate firmware/hackrf_usb/build/ --tester 0000000000000000325866e629a25623 --eut RunningFromRAM' + sh 'hubs all off' + } retry(3) { sh 'hubs h1_eut reset' sh 'sleep 1s' From 73ab8bffb2eecf061b06a6b9c2a1ed4b1c15c3c1 Mon Sep 17 00:00:00 2001 From: grvvy Date: Thu, 26 Feb 2026 16:56:01 -0700 Subject: [PATCH 028/238] hackrf pro jenkins ci --- Jenkinsfile | 58 +- ...stall-firmware.sh => build_h1_firmware.sh} | 0 ci-scripts/build_hpro_firmware.sh | 8 + ci-scripts/hackrf_pro_test.py | 1680 +++++++++++++++++ .../{install-host.sh => install_host.sh} | 0 ci-scripts/{test-host.sh => test_host.sh} | 0 ...est-sgpio-debug.py => test_sgpio_debug.py} | 0 7 files changed, 1739 insertions(+), 7 deletions(-) rename ci-scripts/{install-firmware.sh => build_h1_firmware.sh} (100%) create mode 100755 ci-scripts/build_hpro_firmware.sh create mode 100644 ci-scripts/hackrf_pro_test.py rename ci-scripts/{install-host.sh => install_host.sh} (100%) rename ci-scripts/{test-host.sh => test_host.sh} (100%) rename ci-scripts/{test-sgpio-debug.py => test_sgpio_debug.py} (100%) diff --git a/Jenkinsfile b/Jenkinsfile index 1284ca4f..7079f972 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -6,33 +6,77 @@ pipeline { sh 'docker build -t hackrf https://github.com/greatscottgadgets/hackrf.git' } } - stage('Test Suite') { + stage('Test HackRF One') { agent { docker { image 'hackrf' reuseNode true - args '--group-add=20 --group-add=46 --device-cgroup-rule="c 189:* rmw" --device-cgroup-rule="c 166:* rmw" -v /dev/bus/usb:/dev/bus/usb -e TESTER=0000000000000000325866e629a25623 -e EUT=RunningFromRAM -v /tmp/req_pipe:/tmp/req_pipe -v /tmp/res_pipe:/tmp/res_pipe' + args '''--group-add=20 --group-add=46 --device-cgroup-rule="c 189:* rmw" \ + --device-cgroup-rule="c 166:* rmw" -v /dev/bus/usb:/dev/bus/usb \ + -e TESTER=0000000000000000325866e629a25623 -e EUT=RunningFromRAM \ + -v /tmp/req_pipe:/tmp/req_pipe -v /tmp/res_pipe:/tmp/res_pipe''' } } steps { - sh './ci-scripts/install-host.sh' - sh './ci-scripts/install-firmware.sh' + sh './ci-scripts/install_host.sh' + sh './ci-scripts/build_h1_firmware.sh' sh 'hubs all off' retry(3) { sh 'hubs h1_eut reset' sh 'sleep 1s' - sh './ci-scripts/test-host.sh' + sh './ci-scripts/test_host.sh' } retry(3) { sh 'hubs h1_tester h1_eut reset' sh 'sleep 1s' - sh 'python3 ci-scripts/hackrf_test.py --unattended --ci --log log --rev r4 --manufacturer --hostdir host/build/hackrf-tools/src/ --fwupdate firmware/hackrf_usb/build/ --tester 0000000000000000325866e629a25623 --eut RunningFromRAM' + sh '''python3 ci-scripts/hackrf_test.py --ci --log log \ + --hostdir host/build/hackrf-tools/src/ \ + --fwupdate firmware/hackrf_usb/build/ \ + --tester 0000000000000000325866e629a25623 \ + --eut RunningFromRAM --unattended --rev r4''' sh 'hubs all off' } retry(3) { sh 'hubs h1_eut reset' sh 'sleep 1s' - sh 'python3 ci-scripts/test-sgpio-debug.py' + sh 'python3 ci-scripts/test_sgpio_debug.py' + } + } + } + stage('Test HackRF Pro') { + agent { + docker { + image 'hackrf' + reuseNode true + args '''--group-add=20 --group-add=46 --device-cgroup-rule="c 189:* rmw" \ + --device-cgroup-rule="c 166:* rmw" -v /dev/bus/usb:/dev/bus/usb \ + -e TESTER=0000000000000000325866e629a25623 -e EUT=RunningFromRAM \ + -v /tmp/req_pipe:/tmp/req_pipe -v /tmp/res_pipe:/tmp/res_pipe''' + } + } + steps { + sh './ci-scripts/install_host.sh' + sh './ci-scripts/build_hpro_firmware.sh' + sh 'hubs all off' + retry(3) { + sh 'hubs hpro_eut reset' + sh 'sleep 1s' + sh './ci-scripts/test_host.sh' + } + retry(3) { + sh 'hubs hpro_tester hpro_eut reset' + sh 'sleep 1s' + sh '''python3 ci-scripts/hackrf_pro_test.py --ci --log log \ + --hostdir host/build/hackrf-tools/src \ + --fwupdate firmware/hackrf_usb/build \ + --tester 0000000000000000a06063c82338145f \ + --eut RunningFromRAM -p --rev r1.2''' + sh 'hubs all off' + } + retry(3) { + sh 'hubs hpro_eut reset' + sh 'sleep 1s' + sh 'python3 ci-scripts/test_sgpio_debug.py' } } } diff --git a/ci-scripts/install-firmware.sh b/ci-scripts/build_h1_firmware.sh similarity index 100% rename from ci-scripts/install-firmware.sh rename to ci-scripts/build_h1_firmware.sh diff --git a/ci-scripts/build_hpro_firmware.sh b/ci-scripts/build_hpro_firmware.sh new file mode 100755 index 00000000..8340d0ac --- /dev/null +++ b/ci-scripts/build_hpro_firmware.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e +git submodule init +git submodule update +cd firmware/hackrf_usb +cmake -DBOARD=PRALINE -B build +cmake --build build +cd ../.. diff --git a/ci-scripts/hackrf_pro_test.py b/ci-scripts/hackrf_pro_test.py new file mode 100644 index 00000000..5afd815c --- /dev/null +++ b/ci-scripts/hackrf_pro_test.py @@ -0,0 +1,1680 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import time +import os, shutil +import usb +from datetime import datetime +from dataclasses import dataclass +import argparse +import numpy as np +import traceback +import re + +DFU_UTIL = "/usr/bin/dfu-util" +TMP_DIR = "/tmp/" +WAVEFORM = TMP_DIR + "waveform100" +NOISE = TMP_DIR + "noise" +VENDOR_ID = 0x1d50 +PRODUCT_ID = 0x6089 +DFU_VENDOR_ID = 0x1fc9 +DFU_PRODUCT_ID = 0x000c +ONE_MHZ = 1000000 +TIMEOUT = 5 +MAX_PPM = 20 +MAX_BASELINE = -20 +SIGNAL_THRESHOLD = -25 +MAX_DC_DBC = -27 +MAX_M_DBC = -27 +MAX_MH2_DBC = -40 +MAX_H2_DBC = -39 +MAX_OTHER_DBC = -34 +LP2_CORRECTION = 10 +MAX_POWER = -10 +IF_REQUIRED_MIN = 2320 +IF_REQUIRED_MAX = 2580 +IF_TEST_RANGE = 256 +SLEEP_TIME = 0.05 # seconds to wait between start of TX and start of RX + +@dataclass +class TestCase(): + name: str + freq: int + amp: bool + direction: str + base_ecode: int + rx_lna_gain: int + rx_vga_gain: int + tx_gain: int + +# Try to keep rx_lna_gain and rx_vga_gain between 8 and 32. +bp1txamp = TestCase(name="BP1-TX-amp", freq=2500, amp=True, direction="tx", + base_ecode=320, rx_lna_gain=8, rx_vga_gain=16, tx_gain=5) +lp1txamp = TestCase(name="LP1-TX-amp", freq=915, amp=True, direction="tx", + base_ecode=420, rx_lna_gain=8, rx_vga_gain=16, tx_gain=14) +lp2txamp = TestCase(name="LP2-TX-amp", freq=12, amp=True, direction="tx", + base_ecode=2420, rx_lna_gain=8, rx_vga_gain=16, tx_gain=13) +hp1txamp = TestCase(name="HP1-TX-amp", freq=5995, amp=True, direction="tx", + base_ecode=520, rx_lna_gain=32, rx_vga_gain=16, tx_gain=18) + +bp1txnoamp = TestCase(name="BP1-TX-noamp", freq=2500, amp=False, direction="tx", + base_ecode=350, rx_lna_gain=16, rx_vga_gain=16, tx_gain=14) +lp1txnoamp = TestCase(name="LP1-TX-noamp", freq=915, amp=False, direction="tx", + base_ecode=450, rx_lna_gain=16, rx_vga_gain=12, tx_gain=27) +lp2txnoamp = TestCase(name="LP2-TX-noamp", freq=12, amp=False, direction="tx", + base_ecode=2450, rx_lna_gain=16, rx_vga_gain=18, tx_gain=20) +hp1txnoamp = TestCase(name="HP1-TX-noamp", freq=5995, amp=False, direction="tx", + base_ecode=550, rx_lna_gain=32, rx_vga_gain=24, tx_gain=19) + +# Much of the information in the RX test cases is a duplication of information +# in the TX test cases, but it's easier to keep legacy error codes this way. +bp1rxamp = TestCase(name="BP1-RX-amp", freq=2500, amp=True, direction="rx", + base_ecode=620, rx_lna_gain=8, rx_vga_gain=16, tx_gain=16) +lp1rxamp = TestCase(name="LP1-RX-amp", freq=915, amp=True, direction="rx", + base_ecode=720, rx_lna_gain=16, rx_vga_gain=16, tx_gain=18) +lp2rxamp = TestCase(name="LP2-RX-amp", freq=12, amp=True, direction="rx", + base_ecode=2720, rx_lna_gain=16, rx_vga_gain=16, tx_gain=18) +hp1rxamp = TestCase(name="HP1-RX-amp", freq=5995, amp=True, direction="rx", + base_ecode=820, rx_lna_gain=16, rx_vga_gain=28, tx_gain=38) + +bp1rxnoamp = TestCase(name="BP1-RX-noamp", freq=2500, amp=False, direction="rx", + base_ecode=650, rx_lna_gain=16, rx_vga_gain=16, tx_gain=15) +lp1rxnoamp = TestCase(name="LP1-RX-noamp", freq=915, amp=False, direction="rx", + base_ecode=750, rx_lna_gain=16, rx_vga_gain=16, tx_gain=35) +lp2rxnoamp = TestCase(name="LP2-RX-noamp", freq=12, amp=False, direction="rx", + base_ecode=2750, rx_lna_gain=16, rx_vga_gain=16, tx_gain=38) +hp1rxnoamp = TestCase(name="HP1-RX-noamp", freq=5995, amp=False, direction="rx", + base_ecode=850, rx_lna_gain=16, rx_vga_gain=36, tx_gain=46) + +praline_rf_test_cases = ( + bp1txamp, lp1txamp, lp2txamp, hp1txamp, + bp1txnoamp, lp1txnoamp, lp2txnoamp, hp1txnoamp, + bp1rxamp, lp1rxamp, lp2rxamp, hp1rxamp, + bp1rxnoamp, lp1rxnoamp, lp2rxnoamp, hp1rxnoamp) + +# Praline r1.1.0 requires different gain configuration +r110_bp1rxnoamp = TestCase(name="BP1-RX-noamp", freq=2500, amp=False, direction="rx", + base_ecode=650, rx_lna_gain=16, rx_vga_gain=16, tx_gain=15) +r110_lp1rxnoamp = TestCase(name="LP1-RX-noamp", freq=915, amp=False, direction="rx", + base_ecode=750, rx_lna_gain=16, rx_vga_gain=16, tx_gain=35) +r110_lp2rxnoamp = TestCase(name="LP2-RX-noamp", freq=12, amp=False, direction="rx", + base_ecode=2750, rx_lna_gain=16, rx_vga_gain=16, tx_gain=38) +r110_hp1rxnoamp = TestCase(name="HP1-RX-noamp", freq=5995, amp=False, direction="rx", + base_ecode=850, rx_lna_gain=16, rx_vga_gain=36, tx_gain=46) + +r110_bp1txamp = TestCase(name="BP1-TX-amp", freq=2500, amp=True, direction="tx", + base_ecode=320, rx_lna_gain=8, rx_vga_gain=16, tx_gain=5) +r110_lp1txamp = TestCase(name="LP1-TX-amp", freq=915, amp=True, direction="tx", + base_ecode=420, rx_lna_gain=8, rx_vga_gain=16, tx_gain=10) +r110_lp2txamp = TestCase(name="LP2-TX-amp", freq=12, amp=True, direction="tx", + base_ecode=2420, rx_lna_gain=8, rx_vga_gain=16, tx_gain=12) +r110_hp1txamp = TestCase(name="HP1-TX-amp", freq=5995, amp=True, direction="tx", + base_ecode=520, rx_lna_gain=32, rx_vga_gain=16, tx_gain=17) + +r110_bp1txnoamp = TestCase(name="BP1-TX-noamp", freq=2500, amp=False, direction="tx", + base_ecode=350, rx_lna_gain=16, rx_vga_gain=16, tx_gain=13) +r110_lp1txnoamp = TestCase(name="LP1-TX-noamp", freq=915, amp=False, direction="tx", + base_ecode=450, rx_lna_gain=16, rx_vga_gain=12, tx_gain=23) +r110_lp2txnoamp = TestCase(name="LP2-TX-noamp", freq=12, amp=False, direction="tx", + base_ecode=2450, rx_lna_gain=16, rx_vga_gain=18, tx_gain=18) +r110_hp1txnoamp = TestCase(name="HP1-TX-noamp", freq=5995, amp=False, direction="tx", + base_ecode=550, rx_lna_gain=32, rx_vga_gain=24, tx_gain=18) + +r110_bp1rxamp = TestCase(name="BP1-RX-amp", freq=2500, amp=True, direction="rx", + base_ecode=620, rx_lna_gain=8, rx_vga_gain=16, tx_gain=16) +r110_lp1rxamp = TestCase(name="LP1-RX-amp", freq=915, amp=True, direction="rx", + base_ecode=720, rx_lna_gain=16, rx_vga_gain=16, tx_gain=8) +r110_lp2rxamp = TestCase(name="LP2-RX-amp", freq=12, amp=True, direction="rx", + base_ecode=2720, rx_lna_gain=16, rx_vga_gain=16, tx_gain=10) +r110_hp1rxamp = TestCase(name="HP1-RX-amp", freq=5995, amp=True, direction="rx", + base_ecode=820, rx_lna_gain=16, rx_vga_gain=28, tx_gain=25) + +r110_bp1rxnoamp = TestCase(name="BP1-RX-noamp", freq=2500, amp=False, direction="rx", + base_ecode=650, rx_lna_gain=16, rx_vga_gain=16, tx_gain=15) +r110_lp1rxnoamp = TestCase(name="LP1-RX-noamp", freq=915, amp=False, direction="rx", + base_ecode=750, rx_lna_gain=16, rx_vga_gain=16, tx_gain=24) +r110_lp2rxnoamp = TestCase(name="LP2-RX-noamp", freq=12, amp=False, direction="rx", + base_ecode=2750, rx_lna_gain=16, rx_vga_gain=16, tx_gain=28) +r110_hp1rxnoamp = TestCase(name="HP1-RX-noamp", freq=5995, amp=False, direction="rx", + base_ecode=850, rx_lna_gain=16, rx_vga_gain=36, tx_gain=30) + +praline_r110_rf_test_cases = ( + r110_bp1txamp, r110_lp1txamp, r110_lp2txamp, r110_hp1txamp, + r110_bp1txnoamp, r110_lp1txnoamp, r110_lp2txnoamp, r110_hp1txnoamp, + r110_bp1rxamp, r110_lp1rxamp, r110_lp2rxamp, r110_hp1rxamp, + r110_bp1rxnoamp, r110_lp1rxnoamp, r110_lp2rxnoamp, r110_hp1rxnoamp) + +ifmin = TestCase(name="IF-min", freq=IF_REQUIRED_MIN, amp=None, direction=None, + base_ecode=None, rx_lna_gain=16, rx_vga_gain=16, tx_gain=12) +ifmax = TestCase(name="IF-max", freq=IF_REQUIRED_MAX, amp=None, direction=None, + base_ecode=None, rx_lna_gain=16, rx_vga_gain=16, tx_gain=18) + +ppm = TestCase(name="PPM", freq=2507, amp=False, direction=None, + base_ecode=None, rx_lna_gain=16, rx_vga_gain=16, tx_gain=18) + +noise = TestCase(name="Noise", freq=2550, amp=True, direction=None, + base_ecode=None, rx_lna_gain=40, rx_vga_gain=52, tx_gain=None) + +r9_tester_cal = [1.1, 0.4, 0.4, 1.1, 0.8, 0.2, 0.6, 1.6, -0.4, -1.2, -1.1, 1.1, -1.4, -0.9, 0.1, 1.8] +r9_eut_cal = [-1.1, -1.6, -1.4, -1.3, -1.3, -0.9, 0.1, 1.8, 0.8, 1.1, 0.9, -0.2, 0.9, 0.2, 0.6, 1.5] +og_tester_cal = [-0.4, -0.3, -0.2, -0.4, -0.8, -0.5, -0., -0.1, 1.4, 2., 1.6, -0.1, 1.5, 0.7, 0.5, -0.3] +og_eut_cal = [1.8, 1.8, 1.6, 2., 1.3, 0.7, 0.5, -0.3, 0.2, -0.3, -0.5, 1.2, -0.8, -0.5, -0., -0.1] + +emessages = { + 1: "Wrong device placed in DFU mode", + 2: "DFU device not found", + 3: "Failed to parse a serial number from hackrf_info", + 4: "No path to hackrf host tools found. Please provide a directory via --hostdir", + 5: """Specified TESTER binary directory must be different from the found EUT bin directory + If shared TESTER/EUT binary directory is intended, omit --testerdir""", + 6: "Unable to parse valid serial number from connected devices", + 7: "TESTER and EUT cannot be the same device", + 8: "Invalid TESTER unit, please use a HackRF One", + 9: "Invalid EUT unit, please use a HackRF Pro", + 10: "Clock readback failed", + 11: "SGPIO RX test failed", + 12: "Loopback test failed", + 13: "Self-test failed, see above", + 14: "FPGA configuration failed", + 15: "Multiple self-test failures, see above", + 16: "Mixer self-test failed", + 17: "Transceiver self-test failed", + 18: "32kHz oscillator test failed", + 19: "Too many devices found using unique host tool directory", + 20: "Factory TESTER device not found", + 21: "Factory EUT device not found", + 22: "SGPIO RX test timed out", + 23: "Loopback test timed out", + 24: "FPGA SPI test failed", + 60: "Unable to program firmware via DFU", + 65: "EUT not detected after DFU programming", + 70: "Unable to program SPI flash", + 75: "EUT not detected after flashing", + 76: "Unable to reset EUT", + 77: "Unable to reset TESTER", + 78: "EUT not detected after reset", + 79: "TESTER not detected after reset", + 80: "Could not find EUT", + 81: "Could not find TESTER", + 82: "Found multiple candidate EUTs", + 83: "Found multiple candidate TESTERs", + 84: "EUT running from RAM instead of flash", + 85: "TESTER running from RAM instead of flash", + 86: "Couldn't parse hackrf_info output", + 87: "hackrf_info command failed", + 88: "Incorrect EUT hardware revision", + 89: "Incorrect TESTER hardware revision", + 90: "EUT has incorrect manufacturer pin strap", + 91: "TESTER has incorrect manufacturer pin strap", + 92: "No HackRFs found", + 99: "Incorrect device name", + 100: "EUT couldn't verify clkgen register", + 101: "TESTER couldn't verify clkgen register", + 120: "EUT couldn't verify xcvr register", + 121: "TESTER couldn't verify xcvr register", + 140: "EUT couldn't verify mixer register", + 141: "TESTER couldn't verify mixer register", + 150: "Failed RX for IF verification", + 152: "Couldn't parse received power", + 154: "Received power out of bounds", + 160: "Insufficient IF range", + 170: "RX operation failed", + 172: "Couldn't parse hackrf_sweep output", + 180: "Subprocess timed out", + 190: "Failed to configure LEDs", + 200: "hackrf_clock command failed", + 210: "TESTER failed to detect EUT CLKOUT", + 211: "EUT failed to detect TESTER CLKOUT", + 212: "TESTER detected spurious CLKIN", + 213: "EUT detected spurious CLKIN", + 220: "Failed TESTER CLKIN activation RX", + 221: "Failed EUT CLKIN activation RX", + 230: "Failed TESTER PLL check", + 231: "Failed EUT PLL check", + 232: "TESTER PLL failed to lock", + 233: "EUT PLL failed to lock", + 240: "Clock synchronization failure", + 250: "Failed PPM detection sweep", + 252: "Couldn't parse PPM test sweep data", + 254: "TESTER couldn't detect PPM test transmission", + 255: "EUT couldn't detect PPM test transmission", + 260: "Frequency error exceeds limit", + 300: "Failed baseline RX", + 302: "Couldn't parse baseline RX power", + 306: "Baseline RX power too high", + 310: "Failed noise RX", + 311: "Couldn't parse noise RX power", + 312: "Noise RX power out of range", + 313: "Required noise gain out of range", + 315: "Couldn't read noise RX file", + 316: "Too little variation in ADC bit", + 317: "ADC bit correlates strongly with another bit", + 321: "Excessive TX DC offset in AMP txbp1", + 322: "insufficient signal strength in AMP txbp1", + 323: "AMP txbp1 clipping", + 325: "peak found at unexpected frequency in AMP txbp1", + 330: "harmonics detected in AMP txbp1", + 335: "neighbor magnitude exceeded in AMP txbp1", + 340: "neighbor magnitude exceeded in AMP txbp1", + 345: "spectrum mirrored or inverted in AMP txbp1", + 350: "excessive power out of channel in AMP txbp1", + 351: "Excessive TX DC offset in NOAMP txbp1", + 352: "insufficient signal strength in NOAMP txbp1", + 353: "NOAMP txbp1 clipping", + 355: "peak found at unexpected frequency in NOAMP txbp1", + 360: "harmonics detected in NOAMP txbp1", + 365: "neighbor magnitude exceeded in NOAMP txbp1", + 370: "neighbor magnitude exceeded in NOAMP txbp1", + 375: "spectrum mirrored or inverted in NOAMP txbp1", + 380: "excessive power out of channel in NOAMP txbp1", + 421: "Excessive TX DC offset in AMP txlp1", + 422: "insufficient signal strength in AMP txlp1", + 423: "AMP txlp1 clipping", + 425: "peak found at unexpected frequency in AMP txlp1", + 430: "harmonics detected in AMP txlp1", + 435: "neighbor magnitude exceeded in AMP txlp1", + 440: "neighbor magnitude exceeded in AMP txlp1", + 445: "spectrum mirrored or inverted in AMP txlp1", + 450: "excessive power out of channel in AMP txlp1", + 451: "Excessive TX DC offset in NOAMP txlp1", + 452: "insufficient signal strength in NOAMP txlp1", + 453: "NOAMP txlp1 clipping", + 455: "peak found at unexpected frequency in NOAMP txlp1", + 460: "harmonics detected in NOAMP txlp1", + 465: "neighbor magnitude exceeded in NOAMP txlp1", + 470: "neighbor magnitude exceeded in NOAMP txlp1", + 475: "spectrum mirrored or inverted in NOAMP txlp1", + 480: "excessive power out of channel in NOAMP txlp1", + 2421: "Excessive TX DC offset in AMP txlp2", + 2422: "insufficient signal strength in AMP txlp2", + 2423: "AMP txlp2 clipping", + 2425: "peak found at unexpected frequency in AMP txlp2", + 2430: "harmonics detected in AMP txlp2", + 2435: "neighbor magnitude exceeded in AMP txlp2", + 2440: "neighbor magnitude exceeded in AMP txlp2", + 2445: "spectrum mirrored or inverted in AMP txlp2", + 2450: "excessive power out of channel in AMP txlp2", + 2451: "Excessive TX DC offset in NOAMP txlp2", + 2452: "insufficient signal strength in NOAMP txlp2", + 2453: "NOAMP txlp2 clipping", + 2455: "peak found at unexpected frequency in NOAMP txlp2", + 2460: "harmonics detected in NOAMP txlp2", + 2465: "neighbor magnitude exceeded in NOAMP txlp2", + 2470: "neighbor magnitude exceeded in NOAMP txlp2", + 2475: "spectrum mirrored or inverted in NOAMP txlp2", + 2480: "excessive power out of channel in NOAMP txlp2", + 521: "Excessive TX DC offset in AMP txhp1", + 522: "insufficient signal strength in AMP txhp1", + 523: "AMP txhp1 clipping", + 525: "peak found at unexpected frequency in AMP txhp1", + 530: "harmonics detected in AMP txhp1", + 535: "neighbor magnitude exceeded in AMP txhp1", + 540: "neighbor magnitude exceeded in AMP txhp1", + 545: "spectrum mirrored or inverted in AMP txhp1", + 550: "excessive power out of channel in AMP txhp1", + 551: "Excessive TX DC offset in NOAMP txhp1", + 552: "insufficient signal strength in NOAMP txhp1", + 553: "NOAMP txhp1 clipping", + 555: "peak found at unexpected frequency in NOAMP txhp1", + 560: "harmonics detected in NOAMP txhp1", + 565: "neighbor magnitude exceeded in NOAMP txhp1", + 570: "neighbor magnitude exceeded in NOAMP txhp1", + 575: "spectrum mirrored or inverted in NOAMP txhp1", + 580: "excessive power out of channel in NOAMP txhp1", + 621: "Excessive TX DC offset in AMP rxbp1", + 622: "insufficient signal strength in AMP rxbp1", + 623: "AMP rxbp1 clipping", + 625: "peak found at unexpected frequency in AMP rxbp1", + 630: "harmonics detected in AMP rxbp1", + 635: "neighbor magnitude exceeded in AMP rxbp1", + 640: "neighbor magnitude exceeded in AMP rxbp1", + 645: "spectrum mirrored or inverted in AMP rxbp1", + 650: "excessive power out of channel in AMP rxbp1", + 651: "Excessive TX DC offset in NOAMP rxbp1", + 652: "insufficient signal strength in NOAMP rxbp1", + 653: "NOAMP rxbp1 clipping", + 655: "peak found at unexpected frequency in NOAMP rxbp1", + 660: "harmonics detected in NOAMP rxbp1", + 665: "neighbor magnitude exceeded in NOAMP rxbp1", + 670: "neighbor magnitude exceeded in NOAMP rxbp1", + 675: "spectrum mirrored or inverted in NOAMP rxbp1", + 680: "excessive power out of channel in NOAMP rxbp1", + 721: "Excessive TX DC offset in AMP rxlp1", + 722: "insufficient signal strength in AMP rxlp1", + 723: "AMP rxlp1 clipping", + 725: "peak found at unexpected frequency in AMP rxlp1", + 730: "harmonics detected in AMP rxlp1", + 735: "neighbor magnitude exceeded in AMP rxlp1", + 740: "neighbor magnitude exceeded in AMP rxlp1", + 745: "spectrum mirrored or inverted in AMP rxlp1", + 750: "excessive power out of channel in AMP rxlp1", + 751: "Excessive TX DC offset in NOAMP rxlp1", + 752: "insufficient signal strength in NOAMP rxlp1", + 753: "NOAMP rxlp1 clipping", + 755: "peak found at unexpected frequency in NOAMP rxlp1", + 760: "harmonics detected in NOAMP rxlp1", + 765: "neighbor magnitude exceeded in NOAMP rxlp1", + 770: "neighbor magnitude exceeded in NOAMP rxlp1", + 775: "spectrum mirrored or inverted in NOAMP rxlp1", + 780: "excessive power out of channel in NOAMP rxlp1", + 2721: "Excessive TX DC offset in AMP rxlp2", + 2722: "insufficient signal strength in AMP rxlp2", + 2723: "AMP rxlp2 clipping", + 2725: "peak found at unexpected frequency in AMP rxlp2", + 2730: "harmonics detected in AMP rxlp2", + 2735: "neighbor magnitude exceeded in AMP rxlp2", + 2740: "neighbor magnitude exceeded in AMP rxlp2", + 2745: "spectrum mirrored or inverted in AMP rxlp2", + 2750: "excessive power out of channel in AMP rxlp2", + 2751: "Excessive TX DC offset in NOAMP rxlp2", + 2752: "insufficient signal strength in NOAMP rxlp2", + 2753: "NOAMP rxlp2 clipping", + 2755: "peak found at unexpected frequency in NOAMP rxlp2", + 2760: "harmonics detected in NOAMP rxlp2", + 2765: "neighbor magnitude exceeded in NOAMP rxlp2", + 2770: "neighbor magnitude exceeded in NOAMP rxlp2", + 2775: "spectrum mirrored or inverted in NOAMP rxlp2", + 2780: "excessive power out of channel in NOAMP rxlp2", + 821: "Excessive TX DC offset in AMP rxhp1", + 822: "insufficient signal strength in AMP rxhp1", + 823: "AMP rxhp1 clipping", + 825: "peak found at unexpected frequency in AMP rxhp1", + 830: "harmonics detected in AMP rxhp1", + 835: "neighbor magnitude exceeded in AMP rxhp1", + 840: "neighbor magnitude exceeded in AMP rxhp1", + 845: "spectrum mirrored or inverted in AMP rxhp1", + 850: "excessive power out of channel in AMP rxhp1", + 851: "Excessive TX DC offset in NOAMP rxhp1", + 852: "insufficient signal strength in NOAMP rxhp1", + 853: "NOAMP rxhp1 clipping", + 855: "peak found at unexpected frequency in NOAMP rxhp1", + 860: "harmonics detected in NOAMP rxhp1", + 865: "neighbor magnitude exceeded in NOAMP rxhp1", + 870: "neighbor magnitude exceeded in NOAMP rxhp1", + 875: "spectrum mirrored or inverted in NOAMP rxhp1", + 880: "excessive power out of channel in NOAMP rxhp1", + 3000: "BP TX failure", + 3010: "BP RX failure", + 3020: "HP TX failure", + 3030: "HP RX failure", + 3040: "LP TX failure", + 3050: "LP RX failure", + 3060: "TX AMP failure", + 3070: "RX AMP failure", + 3080: "AMP bypass failure", + 3090: "LPF failure", + 3100: "HPF failure", + 3110: "mixer bypass failure", + 3120: "mixer failure", + 3130: "TX failure", + 3140: "RX failure", + 3150: "mixer TX failure", + 3160: "mixer RX failure", + 3170: "LP2 TX failure", + 3180: "LP2 RX failure", + 3190: "LP2 TX/RX failure", + 3200: "total RF failure", + 3210: "multiple RF failures, see list above", + 3220: "multiple clipping failures", + 3230: "TX clipping failure", + 3240: "RX clipping failure" +} + +def fail_rf(errors): + # check for combinations of RF errors + ecode = 0 + eset = set(errors) + + # error affects only bp tx + if ((322 in eset) and (422 not in eset) and (2422 not in eset) and (522 not in eset) and (622 not in eset) and (722 not in eset) and (2722 not in eset) and (822 not in eset)): + ecode = 3000 + errors.append(ecode) + + # error affects only bp rx + if ((322 not in eset) and (422 not in eset) and (2422 not in eset) and (522 not in eset) and (622 in eset) and (722 not in eset) and (2722 not in eset) and (822 not in eset)): + ecode = 3010 + errors.append(ecode) + + # error affects only hp tx + if ((322 not in eset) and (422 not in eset) and (2422 not in eset) and (522 in eset) and (622 not in eset) and (722 not in eset) and (2722 not in eset) and (822 not in eset)): + ecode = 3020 + errors.append(ecode) + + # error affects only hp rx + if ((322 not in eset) and (422 not in eset) and (2422 not in eset) and (522 not in eset) and (622 not in eset) and (722 not in eset) and (2722 not in eset) and (822 in eset)): + ecode = 3030 + errors.append(ecode) + + # error affects only lp tx (both lp1 and lp2) + if ((322 not in eset) and (422 in eset) and (2422 in eset) and (522 not in eset) and (622 not in eset) and (722 not in eset) and (2722 not in eset) and (822 not in eset)): + ecode = 3040 + errors.append(ecode) + + # error affects only lp rx (both lp1 and lp2) + if ((322 not in eset) and (422 not in eset) and (2422 not in eset) and (522 not in eset) and (622 not in eset) and (722 in eset) and (2722 in eset) and (822 not in eset)): + ecode = 3050 + errors.append(ecode) + + # error in tx amp path + if ((2422 in eset) and (352 not in eset) and (452 not in eset) and (2452 not in eset)): + ecode = 3060 + errors.append(ecode) + + # error in rx amp path + if ((2722 in eset) and (652 not in eset) and (752 not in eset) and (2752 not in eset)): + ecode = 3070 + errors.append(ecode) + + # error in amp bypass path + if ((352 in eset) and (452 in eset) and (2452 in eset) and (652 in eset) and (752 in eset) and (2752 in eset) and (322 not in eset) and (422 not in eset) and (2422 not in eset) and (622 not in eset) and (722 not in eset) and (2722 not in eset)): + ecode = 3080 + errors.append(ecode) + + # error in lpf path + if (((422 in eset) and (2422 in eset)) and ((722 in eset) and (2722 in eset)) and ((322 not in eset) and (622 not in eset)) and ((522 not in eset) and (822 not in eset))): + ecode = 3090 + errors.append(ecode) + + # error in hpf path + if (((522 in eset) and (822 in eset)) and ((322 not in eset) and (622 not in eset)) and ((422 not in eset) and (2422 not in eset) and (722 not in eset) and (2722 not in eset))): + ecode = 3100 + errors.append(ecode) + + # error affects both mixer bypass paths + if ((322 in eset) and (422 not in eset) and (2422 not in eset) and (522 not in eset) and (622 in eset) and (722 not in eset) and (2722 not in eset) and (822 not in eset)): + ecode = 3110 + errors.append(ecode) + + # error in mixer tx/rx + if ((322 not in eset) and ((422 in eset) or (2422 in eset)) and (522 in eset) and (622 not in eset) and ((722 in eset) or (2722 in eset) or (822 in eset))): + ecode = 3120 + errors.append(ecode) + + if ((322 not in eset) and ((422 in eset) or (2422 in eset) or (522 in eset)) and (622 not in eset) and ((722 in eset) and (2722 in eset) and (822 in eset))): + ecode = 3120 + errors.append(ecode) + + # error in all tx, no rx + if ((322 in eset) and (422 in eset) and (2422 in eset) and (522 in eset) and (622 not in eset) and (722 not in eset) and (2722 not in eset) and (822 not in eset) and (352 in eset) and (452 in eset) and (2452 in eset) and (552 in eset)): + ecode = 3130 + errors.append(ecode) + + # error in all rx, no tx + if ((322 not in eset) and (422 not in eset) and (2422 not in eset) and (522 not in eset) and (622 in eset) and (722 in eset) and (2722 in eset) and (822 in eset) and (652 in eset) and (752 in eset) and (2752 in eset) and (852 in eset)): + ecode = 3140 + errors.append(ecode) + + # error in all mixer tx + if ((322 not in eset) and (422 in eset) and (2422 in eset) and (522 in eset) and (622 not in eset) and (722 not in eset) and (2722 not in eset) and (822 not in eset)): + ecode = 3150 + errors.append(ecode) + + # error in all mixer rx + if ((322 not in eset) and (422 not in eset) and (2422 not in eset) and (522 not in eset) and (622 not in eset) and (722 in eset) and (2722 in eset) and (822 in eset)): + ecode = 3160 + errors.append(ecode) + + # error affecting only lp2 tx + if ((322 not in eset) and (422 not in eset) and (2422 in eset) and (522 not in eset) and (622 not in eset) and (722 not in eset) and (2722 not in eset) and (822 not in eset) and (2752 in eset)): + ecode = 3170 + errors.append(ecode) + + # error affecting only lp2 rx + if ((322 not in eset) and (422 not in eset) and (2422 not in eset) and (522 not in eset) and (622 not in eset) and (722 not in eset) and (2722 in eset) and (822 not in eset) and (2752 in eset)): + ecode = 3180 + errors.append(ecode) + + # error affecting only lp2 rx/tx + if ((322 not in eset) and (422 not in eset) and (2422 in eset) and (522 not in eset) and (622 not in eset) and (722 not in eset) and (2722 in eset) and (822 not in eset)): + ecode = 3190 + errors.append(ecode) + + # error in all rx/tx + if ((322 in eset) and (422 in eset) and (2422 in eset) and (522 in eset) and (622 in eset) and (722 in eset) and (2722 in eset) and (822 in eset)): + ecode = 3200 + errors.append(ecode) + + # If there are clipping failures, we can't trust the other RF results, so fail(). + tx_clipping_count = 0 + rx_clipping_count = 0 + for code in (323, 353, 423, 453, 2423, 2453, 523, 553): + if code in eset: + tx_clipping_count += 1 + for code in (623, 653, 723, 753, 2723, 2753, 823, 853): + if code in eset: + rx_clipping_count += 1 + if tx_clipping_count > 1 and rx_clipping_count == 0: + fail(3230) + elif tx_clipping_count == 0 and rx_clipping_count > 1: + fail(3240) + elif tx_clipping_count > 0 and rx_clipping_count > 0: + fail(3220) + + elif (not ecode) and (len(errors) > 1): + # multiple failures without a logical grouping + ecode = 3210 + errors.append(ecode) + + for error in errors[:-1]: + out(f"RF failure {error}: {emessages[error]}") + fail(errors[-1]) + +def log(message=""): + if args.log: + with open(args.log, "a") as log_file: + print(message, file=log_file) + return + +def out(message=""): + log(message) + print(message) + +def fail(error_code): + out(f"FAIL {error_code}: {emessages[error_code]}") + sys.exit(2) + +class HackRF: + def __init__(self, name, bin_dir, serial, mf_check, id=None, revision=None, unique_bin=False, factory_test=False): + self.name = name + self.bin_dir = bin_dir + self.unique_bin = unique_bin + self.id = None + self.revision = None + self.serial = None + self.clkout_connected = False + self.tester_cal = [0] * 16 + self.eut_cal = [0] * 16 + self.errors = [] + self.unit_number = 0 + self.partner = None + + if self.name == "TESTER": + self.unit_number = 1 + elif self.name == "EUT": + self.rf_test_cases = praline_rf_test_cases + else: + fail(99) + + info = subprocess.run([bin_dir + "/hackrf_info"], capture_output=True, + encoding="utf-8", timeout=TIMEOUT) + log(info.stdout + info.stderr) + if info.returncode != 0 or "failed" in info.stderr: + fail(87) + + # parse the hackrf_info output + count = info.stdout.count("Found HackRF") + if count < 1: + fail(92) + if count > 1 and self.name == "TESTER" and self.unique_bin: + fail(83) + if mf_check and "does not appear to have been manufactured by Great Scott Gadgets" in info.stdout: + fail(90 + self.unit_number) + + try: + sn = "" + devices_list = [d.strip() for d in info.stdout.split("Found HackRF") if d.strip()] + for device in devices_list: + sn_found = re.search(r'Serial number: \w+', device) + if sn_found: + sn = sn_found.group(0).split(': ')[1] + + id_found = re.search(r'Board ID Number: .', device) + if id_found: + id = id_found.group(0).split(': ')[1] + + rev_found = re.search(r'Hardware Revision: .+', device) + if rev_found: + rev = rev_found.group(0).split(': ')[1] + + if sn == serial: + self.serial = sn + self.id = id + self.revision = rev + break + + log(f"{self.name} Serial number: {self.serial}") + log(f"{self.name} Board ID: {self.id}") + log(f"{self.name} Hardware Revision: {self.revision}") + log(f"{self.name} binary directory {self.bin_dir}") + except: + log(traceback.format_exc()) + fail(6) + + if self.serial == None: + fail(80 + self.unit_number) + + if self.name == "TESTER" and factory_test and (self.id != "2" and self.id != "4"): + fail(8) + elif self.name == "EUT" and factory_test and self.id != "5": + fail(9) + + if revision and self.revision != revision: + fail(88 + self.unit_number) + + if self.revision == "r9": + self.tester_cal = r9_tester_cal + self.eut_cal = r9_eut_cal + else: + self.tester_cal = og_tester_cal + self.eut_cal = og_eut_cal + + if self.name == "EUT" and self.id == "5" and self.revision == "r1.1": + self.rf_test_cases = praline_r110_rf_test_cases + + def clkin(self): + if self.name == "EUT" and self.id == "5": + debug = subprocess.run([self.bin_dir + "/hackrf_debug", "-d", self.serial, + "-C", "0"]) + command = subprocess.run([self.bin_dir + "/hackrf_clock", "-i", "-d", + self.serial], capture_output=True, encoding="utf-8", + timeout=TIMEOUT) + if command.returncode != 0: + log(command.stdout + command.stderr) + out(f"{self.name} CLKIN request failed") + fail(200) + if "no clock signal detected" in command.stdout: + log(f"{self.name}: no clock signal detected") + return False + elif "clock signal detected" in command.stdout: + log(f"{self.name}: clock signal detected") + return True + else: + log(command.stdout + command.stderr) + out(f"Couldn't parse {self.name} CLKIN status") + fail(200) + + # Warning: Avoid clock loops by disabling your partner's CLKOUT before + # enabling your own. + def clkout(self, enable): + command = subprocess.run([self.bin_dir + "/hackrf_clock", "-o", + "1" if enable else "0", "-d", self.serial], capture_output=True, + encoding="utf-8", timeout=TIMEOUT) + if command.returncode != 0: + log(command.stdout + command.stderr) + out(f"{self.name} CLKOUT control failed") + fail(200) + + if self.partner and self.clkout_connected: + timeout = time.time() + 1 + while time.time() < timeout: + if self.partner.clkin() == enable: + break + if self.partner.clkin() != enable: + if enable: + fail(210 + self.unit_number) + else: + if self.name == "EUT": + out("Note: use --tcxo to use TCXO or external reference on TESTER") + fail(212 + self.unit_number) + + # transceiver operation to switch clock source + source = "CLKIN" if enable else "crystal" + log(f"switching {self.partner.name} to {source}") + receive = subprocess.run([self.partner.bin_dir + "/hackrf_transfer", "-d", + self.partner.serial, "-n1", "-r", "/dev/null", "-f", "2500000000", + "-a", "0", "-l", "0", "-g", "0"], capture_output=True, + encoding="utf-8", timeout=TIMEOUT) + if receive.returncode != 0: + log(receive.stdout + receive.stderr) + fail(220 + self.unit_number) + + # confirm that PLL locked to new source + expected_value = "0x01" if (enable and self.partner.revision != "r9") else "0x51" + timeout = time.time() + 1 + while time.time() < timeout: + debug = subprocess.run([self.partner.bin_dir + "/hackrf_debug", "-d", + self.partner.serial, "-srn0"], capture_output=True, + encoding="utf-8", timeout=TIMEOUT) + log(debug.stdout) + if debug.returncode != 0: + log(debug.stderr) + fail(230 + self.unit_number) + if expected_value in debug.stdout: + break + if expected_value not in debug.stdout: + fail(232 + self.unit_number) + time.sleep(0.1) + else: + time.sleep(0.2) + + def test_clkout(self): + assert self.clkout_connected + self.partner.clkout(False) + self.clkout(True) + frequency_error_ppm = self.clock_error_ppm() + log(f"{self.name}->{self.partner.name} CLK: {frequency_error_ppm} ppm") + if abs(frequency_error_ppm) > 1: + out(f"{self.partner.name} CLKIN: unexpected frequency error while synchronized") + fail(240) + + def test_clkin(self): + self.partner.test_clkout() + + def clock_error_ppm(self): + # ppm.freq is in MHz, but we use it as Hz for the FFT bin width, + # resulting in bins with a width of 1 ppm of the transmission + # frequency. + bin_width = str(ppm.freq) + tx_frequency = str(ppm.freq * ONE_MHZ) + sweep_range = f"{ppm.freq-1}:{ppm.freq+19}" + expected_bin = round(ONE_MHZ/ppm.freq) + + log(f"{self.name} transmitting to {self.partner.name} for PPM measurement") + transmit = subprocess.Popen([self.bin_dir + "/hackrf_transfer", "-d", + self.serial, "-c", "127", "-a", "0", "-x", f"{ppm.tx_gain}", "-f", + tx_frequency], stdout=subprocess.PIPE, stderr=subprocess.PIPE, + encoding="utf-8") + + time.sleep(SLEEP_TIME) + sweep = subprocess.run([self.partner.bin_dir + "/hackrf_sweep", "-d", + self.partner.serial, "-N", "13", "-w", bin_width, "-f", sweep_range, "-a", + "0", "-l", f"{ppm.rx_lna_gain}", "-g", f"{ppm.rx_vga_gain}"], + capture_output=True, encoding="utf-8", timeout=TIMEOUT) + if sweep.returncode != 0: + log(sweep.stdout + sweep.stderr) + fail(250) + + # parse the hackrf_sweep output + try: + rows = sweep.stdout.split("\n") + # Note: skipping data from the first twelve sweeps until issue #1230 is resolved. + row = rows[48].split(", ") + bins = [float(bin) for bin in row[6:]] + peak_bin = bins.index(max(bins)) + frequency_error_ppm = peak_bin - expected_bin + except: + log(sweep.stdout + sweep.stderr) + log(traceback.format_exc()) + fail(252) + + log(f"PPM max bin {peak_bin} power: {bins[peak_bin]}") + for row in rows[0:49:4]: + bins = [float(bin) for bin in row.split(", ")[6:]] + peak_bin = bins.index(max(bins)) + log(f"peak bin {peak_bin}: {bins[peak_bin]}") + if max(bins) < SIGNAL_THRESHOLD: + fail(254 + self.unit_number) + transmit.terminate() + tx_out, tx_err = transmit.communicate(timeout=TIMEOUT) + if transmit.returncode != 0: + log(tx_out + tx_err) + out(f"Warning: {self.name} PPM test transmit failed") + return frequency_error_ppm + + def test_xtal(self): + self.clkout(False) + self.partner.clkout(False) + frequency_error_ppm = self.clock_error_ppm() + log(f"{self.name} crystal frequency error: {frequency_error_ppm} ppm") + if abs(frequency_error_ppm) > MAX_PPM: + fail(260) + + def verify_register(self, target, address, value): + command = subprocess.run([self.bin_dir + "/hackrf_debug", + f"--{target}", "--register", address, "--read", "--device", + self.serial], capture_output=True, encoding="UTF-8") + log(f"Checking {target} register {address}") + if value in command.stdout: + return True + else: + log("Unexpected result:") + log(command.stdout + command.stderr) + return False + + def test_clkgen(self): + if not self.verify_register("si5351", "2", "0x03"): + fail(100 + self.unit_number) + + def test_mixer(self): + if not self.verify_register("rffc5072", "2", "0x9055"): + fail(140 + self.unit_number) + + def test_xcvr(self): + if not self.verify_register("max283", "28", "0x0c0"): + fail(120 + self.unit_number) + + def test_serial(self): + log(f"Testing {self.name} serial communications") + self.test_clkgen() + self.test_mixer() + self.test_xcvr() + + # Ensure that hackrf_transfer works and that the received power is within + # the expected range with no transmission active. + def baseline_rx(self, test_case): + # Test at the TX tuning frequency of measure_rf() + center_freq = (test_case.freq * ONE_MHZ) + 1500000 + receive = subprocess.run([self.bin_dir + "/hackrf_transfer", "-d", + self.serial, "-n10000", "-r", "/dev/null", "-f", + f"{center_freq}", "-a", "0", "-l", f"{test_case.rx_lna_gain}", + "-g", f"{test_case.rx_vga_gain}", "-b", + "1750000"], capture_output=True, encoding="utf-8", timeout=TIMEOUT) + if receive.returncode != 0: + log(receive.stdout + receive.stderr) + log(f"Failed {self.name} {test_case.name} baseline RX") + fail(300) + + output = str(receive.stderr).split() + try: + power = float(output[output.index("power") + 1]) + except: + log(receive.stdout + receive.stderr) + log(traceback.format_exc()) + log(f"Couldn't parse {self.name} {test_case.name} baseline RX power") + fail(302) + # The theoretical minimum power is about -48 dB. The expected power is + # about -30 dB. + log(f"{self.name} {test_case.name} baseline power: {power}") + if power > MAX_BASELINE: + fail(306) + + # Check the ADC for shorts or other unexpected behavior by sampling + # amplified noise. + def noise_rx(self, test_case): + num_samples = 1000 + log(f"Testing {self.name} {test_case.name}") + center_freq = test_case.freq * ONE_MHZ + + low_gain = 0 + high_gain = 16 + while high_gain > low_gain: + gain = (high_gain + low_gain) // 2 + receive = subprocess.run([self.bin_dir + "/hackrf_transfer", "-d", + self.serial, "-n", f"{num_samples*10}", "-r", f"{NOISE}", "-f", + f"{center_freq}", "-a", "1" if test_case.amp else "0", "-l", + f"{test_case.rx_lna_gain}", "-g", f"{gain*2 + 32}", "-b", + "28000000"], capture_output=True, encoding="utf-8", timeout=TIMEOUT) + if receive.returncode != 0: + log(receive.stdout + receive.stderr) + fail(310) + output = str(receive.stderr).split() + try: + power = float(output[output.index("power") + 1]) + except: + log(receive.stdout + receive.stderr) + log(traceback.format_exc()) + fail(311) + log(f"{self.name} {test_case.name} RX power at -g {gain*2 + 32}: {power}") + if power > -2: + high_gain = gain + elif power > -5: + break + else: + low_gain = gain + 1 + + # We want the power to be between -1 and -9 dB to ensure that all eight + # bits are flipped without much clipping. + if power < -9 or power > -1: + fail(312) + elif gain > 16 or gain < 4: + fail(313) + + bit_count = [0] * 8 + matches = [] + for bit in range(8): + matches.append([0] * 8) + + try: + file = open(f"{NOISE}", "rb") + data = file.read() + assert len(data) == num_samples * 20 + data = data[-num_samples*2:] + for byte in data: + for bit in range(8): + bit_count[bit] += (byte>>bit)&1 + for match_bit in range(bit + 1, 8): + if (byte>>bit)&1 == (byte>>match_bit)&1: + matches[bit][match_bit] += 1 + except: + fail(315) + log(f"{self.name} ADC bit counts: {bit_count}") + log(f"{self.name} ADC bit matches: {matches}") + for bit in range(7): + if bit_count[bit] < (0.2 * len(data)) or bit_count[bit] > (0.8 * len(data)): + log(f"{self.name} ADC bit {bit} set in {bit_count[bit]} out of {len(data)} bytes") + fail(316) + # Check for correlations between adjacent bits except between 6 and 7 (highest). + #for match_bit in range(bit + 1, 7): + for match_bit in range(bit + 1, 8): + if matches[bit][match_bit] > (0.999 * len(data)): + out(f"{self.name} ADC bit {bit} correlates with bit {match_bit}") + fail(317) + # DC bias can cause bit 7 to be predominantly unchanged, so only + # error if there is less than 1% variation. + if bit_count[7] < (0.001 * len(data)) or bit_count[bit] > (0.999 * len(data)): + out(f"{self.name} ADC bit 7 set in {bit_count[7]} out of {len(data)} bytes") + fail(316) + + def analyze_transfer(self, transfer, test_case): + # parse the hackrf_transfer output + output = str(transfer.stderr).split() + try: + power = float(output[output.index("power") + 1]) + except: + log(transfer.stdout + transfer.stderr) + log(traceback.format_exc()) + fail(152) + log(f"{test_case.name} power at {test_case.freq} MHz: {power}") + + if test_case.base_ecode: + if power < SIGNAL_THRESHOLD: + log(f"{test_case.name} signal not strong enough") + self.errors.append(test_case.base_ecode + 2) + if power > -3: + log(f"{test_case.name} signal clipping") + self.errors.append(test_case.base_ecode + 3) + elif power < -48 or power > 0: + fail(154) + return power + + # Verify that signal power at a given IF in MHz is detected. + def verify_if_tuning(self, test_case): + transmit = subprocess.Popen([self.bin_dir + "/hackrf_transfer", "-d", + self.serial, "-c", "127", "-a", "0", "-x", f"{test_case.tx_gain}", + "-i", f"{test_case.freq*ONE_MHZ}", "-m", "0", "-F"], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8") + + time.sleep(SLEEP_TIME) + receive = subprocess.run([self.partner.bin_dir + "/hackrf_transfer", "-d", + self.partner.serial, "-n10000", "-r", "/dev/null", "-f", + f"{(test_case.freq+1)*ONE_MHZ}", "-a", "0", "-l", + f"{test_case.rx_lna_gain}", "-g", f"{test_case.rx_vga_gain}", "-b", + "2500000"], capture_output=True, encoding="utf-8", timeout=TIMEOUT) + transmit.terminate() + if receive.returncode != 0: + log(receive.stdout + receive.stderr) + fail(150) + + power = self.analyze_transfer(receive, test_case) + + tx_out, tx_err = transmit.communicate(timeout=TIMEOUT) + if transmit.returncode != 0: + log(tx_out + tx_err) + out(f"Warning: {self.name} IF transmit failed") + return power > SIGNAL_THRESHOLD + + def test_if_range(self, min_case, max_case): + low_end = IF_REQUIRED_MIN - (IF_TEST_RANGE // 2) + min_freq = IF_REQUIRED_MIN + (IF_TEST_RANGE // 2) + while min_freq > low_end: + min_case.freq = (min_freq + low_end) // 2 + if self.verify_if_tuning(min_case): + min_freq = min_case.freq + else: + low_end = min_case.freq + 1 + + high_end = IF_REQUIRED_MAX + (IF_TEST_RANGE // 2) + max_freq = IF_REQUIRED_MAX - (IF_TEST_RANGE // 2) + while max_freq < high_end: + max_case.freq = (max_freq + high_end + 1) // 2 + if self.verify_if_tuning(max_case): + max_freq = max_case.freq + else: + high_end = max_case.freq - 1 + + log(f"{self.name} IF range: {min_freq}-{max_freq} MHz") + if min_freq > IF_REQUIRED_MIN or max_freq < IF_REQUIRED_MAX: + fail(160) + + def analyze_sweep(self, sweep, test_case): + eut_cal = self.eut_cal[self.rf_test_cases.index(test_case)] + tester_cal = self.partner.tester_cal[self.rf_test_cases.index(test_case)] + correction = LP2_CORRECTION if test_case.freq < 30 else 0 + + # parse the hackrf_sweep output + try: + rows = sweep.stdout.split("\n") + # Note: skipping data from the first twelve sweeps until issue #1230 is resolved. + bins = np.zeros(225) + # average 10 sweeps + row_count = 0 + for row in rows[48:88:4]: + bins += np.array([float(x) for x in row.split(", ")[6:231]]) + row_count += 1 + assert row_count == 10 + bins /= 10 + # log the raw hackrf_sweep data before calibration + log(f"{', '.join(rows[12].split(', ')[:6])}, {np.array2string(bins, separator=', ', max_line_width=3000)[1:-1]}") + # apply calibration + bins -= eut_cal + bins -= tester_cal + peak_bin = bins.argmax() + except: + log(sweep.stdout + sweep.stderr) + log(traceback.format_exc()) + out(f"Couldn't parse {test_case.name} sweep data") + fail(172) + + # ensure acceptable performance + log(f"peak ({peak_bin}) {test_case.name}: {bins[peak_bin]:.2f}") + if bins[peak_bin] < SIGNAL_THRESHOLD: + for row in rows[0:88:4]: + bins = [float(bin) for bin in row.split(", ")[6:]] + peak_bin = bins.index(max(bins)) + log(f"peak bin {peak_bin}: {bins[peak_bin]}") + log(f"{test_case.name} signal not strong enough") + self.errors.append(test_case.base_ecode + 2) + return bins[peak_bin] + elif bins[peak_bin] > MAX_POWER: + log(f"{test_case.name} signal clipping") + self.errors.append(test_case.base_ecode + 3) + return bins[peak_bin] + tx_dc_power_dbc = bins[112] - bins[peak_bin] + if tx_dc_power_dbc > MAX_DC_DBC + correction: + log(f"{test_case.name} excessive TX DC offset {tx_dc_power_dbc:.1f} dBc") + self.errors.append(test_case.base_ecode + 1) + if peak_bin == 157: + log(f"{test_case.name} TX spectrum inverted") + self.errors.append(test_case.base_ecode + 25) + return bins[peak_bin] + elif peak_bin == 112: + log(f"{test_case.name} peak found at DC") + self.errors.append(test_case.base_ecode + 1) + return bins[peak_bin] + elif peak_bin >= 52 and peak_bin < 67: + log(f"{test_case.name} peak found at adjacent frequency") + self.errors.append(test_case.base_ecode + 15) + return bins[peak_bin] + elif peak_bin > 67 and peak_bin <= 82: + log(f"{test_case.name} peak found at adjacent frequency") + self.errors.append(test_case.base_ecode + 20) + return bins[peak_bin] + elif peak_bin != 67: + log(f"{test_case.name} peak found at unexpected frequency") + self.errors.append(test_case.base_ecode + 5) + return bins[peak_bin] + + if bins[157] - bins[67] > MAX_M_DBC + correction: + log(f"{test_case.name} TX spectrum mirrored") + self.errors.append(test_case.base_ecode + 25) + if (bins[22] - bins[67]) > MAX_H2_DBC + correction: + log(f"{test_case.name} excessive TX harmonic (bin 22): {bins[22]}") + self.errors.append(test_case.base_ecode + 10) + if (bins[202] - bins[67]) > MAX_MH2_DBC + correction: + log(f"{test_case.name} excessive TX harmonic (bin 202): {bins[202]}") + self.errors.append(test_case.base_ecode + 10) + worst_other_dbc = -999 + worst_other_bin = 999 + for i in range(225): + # Skip various frequencies where spurs are expected (most of which have their own tests above). + if (i < 52 and i != 22) or (i > 82 and i < 111) or (i > 113 and i < 156) or (i > 158 and i != 202): + other_dbc = bins[i] - bins[67] + if other_dbc > worst_other_dbc: + worst_other_dbc = other_dbc + worst_other_bin = i + if worst_other_dbc > MAX_OTHER_DBC + correction: + log(f"{test_case.name} excessive power at unexpected frequency ({worst_other_bin}: {bins[worst_other_bin]})") + self.errors.append(test_case.base_ecode + 30) + log(f"h2 (22) {test_case.name}: {(bins[22] - bins[67]):.2f}") + log(f"DC (112) {test_case.name}: {(bins[112] - bins[67]):.2f}") + log(f"m (157) {test_case.name}: {(bins[157] - bins[67]):.2f}") + log(f"mh2 (202) {test_case.name}: {(bins[202] - bins[67]):.2f}") + log(f"other ({worst_other_bin}) {test_case.name}: {worst_other_dbc:.2f}") + #FIXME look in another row for RX inversion? + return bins[peak_bin] + + def measure_rf(self, test_case, sweep=True): + log(f"Executing RF test case {test_case.name}, sweep={sweep}") + if test_case.direction == "tx": + transmitter = self + tx_amp = "1" if test_case.amp else "0" + receiver = self.partner + rx_amp = "0" + elif test_case.direction == "rx": + transmitter = self.partner + tx_amp = "0" + receiver = self + rx_amp = "1" if test_case.amp else "0" + else: + out(f"Error: Invalid direction in {test_case.name}") + sys.exit(1) + + # The nominal test frequency (as specified in test_case) is 1 MHz above + # the low end of the sweep range. The transmitted signal is 500 kHz + # above the nominal frequency, and the tuning (center) frequency of the + # transmitting device is 1 MHz above that. + tx_center_freq = (test_case.freq * ONE_MHZ) + 1500000 + sweep_range = f"{test_case.freq-1}:{test_case.freq+19}" + + transmit = subprocess.Popen([transmitter.bin_dir + "/hackrf_transfer", "-d", + transmitter.serial, "-R", "-t", WAVEFORM, "-a", tx_amp, "-x", + f"{test_case.tx_gain}", "-f", str(tx_center_freq)], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8") + + time.sleep(SLEEP_TIME) + if sweep: + receive = subprocess.run([receiver.bin_dir + "/hackrf_sweep", + "-d", receiver.serial, "-N", "22", "-w", "22222", "-f", + sweep_range, "-a", rx_amp, "-l", f"{test_case.rx_lna_gain}", + "-g", f"{test_case.rx_vga_gain}"], capture_output=True, + encoding="utf-8", timeout=TIMEOUT) + else: + receive = subprocess.run([receiver.bin_dir + "/hackrf_transfer", + "-d", receiver.serial, "-n10000", "-r", "/dev/null", "-f", + f"{(test_case.freq)*ONE_MHZ}", "-a", rx_amp, "-l", + f"{test_case.rx_lna_gain}", "-g", f"{test_case.rx_vga_gain}", + "-b", "2500000"], capture_output=True, encoding="utf-8", + timeout=TIMEOUT) + transmit.terminate() + if receive.returncode != 0: + log(receive.stdout + receive.stderr) + log(f"{receiver.name} Failed RX, sweep={sweep}") + fail(170) + + if sweep: + rssi = self.analyze_sweep(receive, test_case) + else: + rssi = self.analyze_transfer(receive, test_case) + + tx_out, tx_err = transmit.communicate(timeout=TIMEOUT) + if transmit.returncode != 0: + log(tx_out + tx_err) + out(f"Warning: {transmitter.name} transmit failed") + return rssi + + def test_rf_preliminary(self): + results = [] + + for test_case in (self.rf_test_cases): + if test_case.amp == False: + if test_case.direction == "rx": + self.baseline_rx(test_case) + elif self.partner: + self.partner.baseline_rx(test_case) + + self.noise_rx(noise) + # FIXME test for RX DC offset? + + if not self.partner: + out("Skipping RF tests") + return + + for test_case in (self.rf_test_cases): + results.append(int(round(self.measure_rf(test_case, sweep=False) - (SIGNAL_THRESHOLD + 11)))) + + log(f"Preliminary results: {results}") + if self.errors: + fail_rf(self.errors) + + def test_rf(self): + assert self.partner + results = [] + + for test_case in (self.rf_test_cases): + results.append(int(round(self.measure_rf(test_case, sweep=True) - (SIGNAL_THRESHOLD + 5)))) + + log(f"RF results summary: {results}") + if self.errors: + fail_rf(self.errors) + + def activate_leds(self, enable): + if enable: + log(f"Activating {self.name} LEDs") + state = 7 + else: + state = 1 + # Always illuminate MCU LED on Praline. + if self.id == "5": + state |= 8 + command = subprocess.run([self.bin_dir + "/hackrf_debug", "-d", self.serial, "--leds", + f"{state}"], capture_output=True, encoding="utf-8", timeout=TIMEOUT) + if command.returncode != 0: + log(command.stdout + command.stderr) + log(f"Failed to configure {self.name} LEDs ({state})") + fail(190) + + def debug_selftest(self): + errors = [] + + debug = subprocess.run([self.bin_dir + "/hackrf_debug", "-to", "-d", self.serial], + capture_output=True, encoding="utf-8", timeout=TIMEOUT) + log(debug.stdout + debug.stderr) + + fpga_test_found = re.search(r'FPGA configuration: \w+', debug.stdout) + if fpga_test_found: + if fpga_test_found.group(0).split(': ')[-1] != "PASS": + errors.append(14) + else: + out("Failure to find FPGA configuration result. Wrong firmware version? Continuing...") + + # Check for FPGA SPI result only if FPGA configuration passed. + if len(errors) == 0: + sgpio_test_found = re.search(r'FPGA SPI: \w+', debug.stdout) + if sgpio_test_found: + if sgpio_test_found.group(0).split(': ')[-1] != "PASS": + errors.append(24) + else: + out("Failure to find FPGA SPI test result. Wrong firmware version? Continuing...") + + # Check for SGPIO result only if FPGA configuration and SPI passed. + if len(errors) == 0: + sgpio_test_found = re.search(r'SGPIO RX test: \w+', debug.stdout) + if sgpio_test_found: + if sgpio_test_found.group(0).split(': ')[-1] == "TIMEOUT": + errors.append(22) + elif sgpio_test_found.group(0).split(': ')[-1] == "FAIL": + errors.append(11) + else: + out("Failure to find sgpio test result. Wrong firmware version? Continuing...") + + # Check for loopback result only if FPGA, SPI, and SGPIO passed. + if len(errors) == 0: + loopback_test_found = re.search(r'Loopback test: \w+', debug.stdout) + if loopback_test_found: + if loopback_test_found.group(0).split(': ')[-1] == "TIMEOUT": + errors.append(23) + elif loopback_test_found.group(0).split(': ')[-1] == "FAIL": + errors.append(12) + else: + out("Failure to find loopback test result. Wrong firmware version? Continuing...") + + clock_found = re.search(r'Clock: \w+, \w+: \d, readback: \w+', debug.stdout) + if clock_found: + if clock_found.group(0).split(': ')[-1] != "OK": + errors.append(10) + else: + out("Failure to find clock results. Wrong firmware version? Continuing...") + + mixer_found = re.search(r'Mixer: \w+, ID: \d+', debug.stdout) + if mixer_found: + if mixer_found.group(0).split(': ')[-1] != "4416": + errors.append(16) + else: + out("Failure to find mixer results. Wrong firmware version? Continuing...") + + # Check for transceiver result only if FPGA configuration passed. + if 14 not in errors: + xcvr_found = re.search(r'Transceiver: \w+, RSSI mux test: \w+', debug.stdout) + if xcvr_found: + if xcvr_found.group(0).split(': ')[-1] != "PASS": + errors.append(17) + else: + out("Failure to find transceiver results. Wrong firmware version? Continuing...") + + rtc_found = re.search(r'RTC test result: \w+', debug.stdout) + if rtc_found: + if rtc_found.group(0).split(': ')[-1] != "PASS": + errors.append(18) + else: + out("Failure to find 32kHz oscillator results. Wrong firmware version? Continuing...") + + # Provide entire self-test report if there is an unrecognized self-test failure + if len(errors) == 0: + selftest_found = re.search(r'Self-test result: \w+', debug.stdout) + if selftest_found: + if selftest_found.group(0).split(': ')[-1] != "PASS": + out(debug.stdout) + fail(13) + else: + out("Failure to find selftest results. Wrong firmware version? Continuing...") + + # Report multiple self-test failures + if len(errors) > 1: + for error in errors: + out(f"Self-test failure {error}: {emessages[error]}") + fail(15) + + if len(errors) > 0: + fail(errors[-1]) + + def reset(self): + log(f"Resetting {self.name}") + spiflash = subprocess.run([self.bin_dir + "/hackrf_spiflash", "-d", self.serial, "-R"], + capture_output=True, encoding="utf-8", timeout=TIMEOUT) + if spiflash.returncode != 0: + log(spiflash.stdout + spiflash.stderr) + fail(76 + self.unit_number) + + then = time.time() + device_found = False + while time.time() < (then + 5): + time.sleep(1) + info = subprocess.run([self.bin_dir + "/hackrf_info"], + capture_output=True, timeout=TIMEOUT) + if self.serial in info.stdout.decode('utf-8', errors='ignore'): + device_found = True + break + time.sleep(0.1) + if not device_found: + fail(78 + self.unit_number) + + +# This waveform is a full-scale complex exponential with a frequency of -1/10 the +# sample rate. When transmitted at 10 Msps, the frequency is 1 MHz below the +# center frequency. + +def write_waveform(): + tx_bytes = b'\x7f\x00\x67\xb5\x27\x87\xd9\x87\x99\xb5\x81\x00\x99\x4b\xd9\x79\x27\x79\x67\x4b' + # defective waveform with DC offset: + #tx_bytes = b'\x7f\x10\x67\xa5\x27\x97\xd9\x97\x99\xc5\x81\x10\x99\x5b\xd9\x7f\x27\x7f\x67\x5b' + # defective waveform with missing Q channel: + #tx_bytes = b'\x7f\x00\x67\x00\x27\x00\xd9\x00\x99\x00\x81\x00\x99\x00\xd9\x00\x27\x00\x67\x00' + with open(WAVEFORM, "wb") as bin_file: + for i in range(50000): # 1MB file size + bin_file.write(tx_bytes) + + +def program(bin_dir, fw_dir, serial, unattended=False): + binary = "hackrf_usb.bin" + dfu_stub = "hackrf_usb.dfu" + + # EUTs in unattended (including Jenkins CI) setups have pins jumped to always boot into DFU mode, so resetting is undesirable + if unattended: + reset_write = "-w" + else: + reset_write = "-Rw" + + if not usb.core.find(idVendor=DFU_VENDOR_ID, idProduct=DFU_PRODUCT_ID): + print("ACTION REQUIRED: Press and release EUT RESET button while holding DFU button.") + while not usb.core.find(idVendor=DFU_VENDOR_ID, idProduct=DFU_PRODUCT_ID): + time.sleep(0.1) + + out("Programming EUT in DFU mode") + dfu = subprocess.run([f"{DFU_UTIL}", "--device", + f"{DFU_VENDOR_ID}:{DFU_PRODUCT_ID}", "--alt", "0", "--download", + f"{fw_dir}/{dfu_stub}"], capture_output=True, encoding="utf-8", + timeout=TIMEOUT) + log(dfu.stdout + dfu.stderr) + + #dfu-util: unable to read DFU status after completion (LIBUSB_ERROR_IO) + # despite successful download; present as of at least dfu-util 0.11 + if "Download done." not in dfu.stdout: + fail(60) + + # Wait for device to boot from DFU. + then = time.time() + dfu_device_found = False + while time.time() < (then + 50): + dfu_info = subprocess.run([bin_dir + "/hackrf_info"], capture_output=True, + encoding="utf-8", timeout=TIMEOUT) + + if "RunningFromRAM" in dfu_info.stdout: + if serial in dfu_info.stdout and serial != "RunningFromRAM": + fail(1) + else: + dfu_device_found = True + break + time.sleep(0.1) + if not dfu_device_found: + fail(2) + + out("Programming EUT SPI flash") + spiflash = subprocess.run([bin_dir + "/hackrf_spiflash", "-d", + "RunningFromRAM", reset_write, f"{fw_dir}/{binary}"], + capture_output=True, encoding="utf-8", timeout=TIMEOUT+20) + if spiflash.returncode != 0: + log(spiflash.stdout + spiflash.stderr) + fail(70) + + then = time.time() + device_found = False + while time.time() < (then + 5): + time.sleep(1) + flash_info = subprocess.run([bin_dir + "/hackrf_info"], capture_output=True, + timeout=TIMEOUT) + if serial == "RunningFromRAM" and not unattended: + try: + devices_list = [d.strip() for d in flash_info.stdout.decode('utf-8', errors='ignore').split("Found HackRF") if d.strip()] + for device in devices_list: + sn_found = re.search(r'Serial number: \w+', device) + if sn_found: + serial = sn_found.group(0).split(': ')[1] + except: + log(traceback.format_exc()) + fail(6) + if serial in flash_info.stdout.decode('utf-8', errors='ignore'): + device_found = True + break + time.sleep(0.1) + if not device_found: + fail(75) + + +def find_sn(name, bin_dir, factory_test, claimed_sns=[]): + while True: + sn_list = [] + info = subprocess.run([bin_dir + "/hackrf_info"], capture_output=True, + encoding="utf-8", timeout=TIMEOUT) + try: + sn = "" + devices_list = [d.strip() for d in info.stdout.split("Found HackRF") if d.strip()] + for device in devices_list: + sn_found = re.search(r'Serial number: \w+', device) + if sn_found: + new_sn = sn_found.group(0).split(': ')[1] + if new_sn not in claimed_sns: + sn_list.append(new_sn) + except: + log(traceback.format_exc()) + fail(6) + + if factory_test: + if len(sn_list) > 1: + fail(19) + elif len(sn_list) < 1: + if name == "TESTER": + fail(20) + elif name == "EUT": + fail(21) + else: + sn = sn_list[0] + break + else: + if len(sn_list) > 1: + out(f"\nPotential {name}(s) found:\n") + for i in range(len(sn_list)): + out(f"{i}: {sn_list[i]}") + choice = int(input(f"\nEnter the index of your target {name}s serial number: ")) + if 0 <= choice < len(sn_list): + sn = sn_list[choice] + break + else: + out("Incorrect choice, try again.") + elif len(sn_list) == 1: + sn = sn_list[0] + break + else: + fail(3) + return sn + + +def get_version(): + version = subprocess.run(["git", "log", "-n" "1", "--format=%h"], + capture_output=True, encoding="utf-8", timeout=TIMEOUT) + if version.returncode != 0: + return "2023.01.1+" + elif version.returncode == 0: + dirty = subprocess.run(["git", "status", "-s", "--untracked-files=no"], + capture_output=True, encoding="utf-8", timeout=TIMEOUT) + if dirty.stdout != "": + dirty_flag = "*" + else: + dirty_flag = "" + return f"git-{version.stdout.strip()}{dirty_flag}" + + +def main(): + + write_waveform() + + parser = argparse.ArgumentParser(description="Utility for testing HackRF One") + parser.add_argument("-c", "--noclk", action="store_true", help="skip CLKIN, CLKOUT, and PPM tests") + parser.add_argument("-i", "--noif", action="store_true", help="skip IF tuning range test") + parser.add_argument("-l", "--loop", action="store_true", help="repeat the test until terminated with ctrl-c") + parser.add_argument("-m", "--manufacturer", action="store_true", help="check the manufacturer of target devices") + parser.add_argument("-r", "--rev", metavar=" or \"any\"", type=str, + help="check EUT pin straps for specific hardware revision (default: \"r9\")", + default="r9") + parser.add_argument("-s", "--solo", action="store_true", help="perform limited tests on a single EUT with no TESTER") + parser.add_argument("-t", "--tcxo", action="store_true", help="skip CLKIN/CLKOUT tests and use TCXO instead") + parser.add_argument("-E", "--eut", metavar="", type=str, + help="EUT serial number") + parser.add_argument("-T", "--tester", metavar="", type=str, + help="TESTER serial number") + parser.add_argument("-f", "--fwupdate", metavar="", type=str, + help="update firmware with binaries from specified directory") + parser.add_argument("-H", "--hostdir", metavar="", type=str, + help="location of installed hackrf host tools, will attempt to find them if omitted") + parser.add_argument("-b", "--testerdir", metavar="", type=str, + help="necessary only if EUT/TESTER have separate host binaries") + parser.add_argument("-C", "--ci", action="store_true", help="For use with Jenkins CI user") + parser.add_argument("-p", "--praline", action="store_true", help="Force Praline mode") + parser.add_argument("-F", "--factory", action="store_true", help="Force factory test mode") + parser.add_argument("-u", "--unattended", action="store_true", help="For use with unattended hardware") + parser.add_argument("-L", "--log", metavar="", type=str, + help="log file location") + global args + args = parser.parse_args() + + if args.ci: + user = "jenkins" + else: + user = os.getlogin() + + if "any" in args.rev.lower(): + args.rev = None + elif args.rev.lower() == "r1" or args.rev.lower() == "r4": + args.rev = "older than r6" + + if args.hostdir: + eut_host_dir = args.hostdir + else: + try: + eut_host_dir = os.path.dirname(shutil.which('hackrf_info')) + except: + fail(4) + + if args.testerdir: + if args.testerdir == eut_host_dir: + fail(5) + else: + tester_host_dir = args.testerdir + else: + tester_host_dir = eut_host_dir + + unique_bin = (tester_host_dir != eut_host_dir) + count = 0 + + while True: + log() + log("================================") + log(datetime.now()) + log(sys.argv) + log(f"user: {user}") + log(f"version: {get_version()}") + log(f"pid: {os.getpid()}") + if args.loop: + log(f"repeat count: {count}") + log("================================") + log() + + if args.eut: + eut_sn = args.eut + else: + if args.tester: + eut_sn = find_sn("EUT", eut_host_dir, args.factory, [args.tester]) + else: + eut_sn = find_sn("EUT", eut_host_dir, args.factory) + if args.tester: + tester_sn = args.tester + else: + tester_sn = find_sn("TESTER", tester_host_dir, args.factory, [eut_sn]) + + if eut_sn == tester_sn: + fail(7) + + # TODO: check if the provided firmware directory exists + if args.fwupdate: + program(eut_host_dir, args.fwupdate, eut_sn, args.unattended) + eut_sn = find_sn("EUT", eut_host_dir, args.factory, [tester_sn]) + + if not args.rev: + out("Skipping EUT hardware revision check") + eut = HackRF("EUT", eut_host_dir, eut_sn, args.manufacturer, revision=args.rev, factory_test=args.factory) + + if args.solo: + tester = None + else: + tester = HackRF("TESTER", tester_host_dir, tester_sn, args.manufacturer, unique_bin=unique_bin, factory_test=args.factory) + tester.partner = eut + eut.partner = tester + + out("\nTest started, please wait...") + if args.solo: + eut.clkout_connected = False + elif args.noclk: + eut.clkout_connected = False + tester.clkout_connected = False + elif args.tcxo: + eut.clkout_connected = False + tester.clkout_connected = True + else: + eut.clkout_connected = True + tester.clkout_connected = True + + if count > 0 and not args.fwupdate: + eut.activate_leds(False) + + if not args.unattended: + eut.reset() + eut.debug_selftest() + # limited RF test without clock synchronization + eut.test_rf_preliminary() + + if args.noclk or args.solo: + out("Skipping CLKIN, CLKOUT, and PPM tests") + else: + eut.test_xtal() + if not args.tcxo: + eut.test_clkout() + eut.test_clkin() + + eut.clkout(False) + + if tester: + tester.clkout(True) + + if args.tcxo: + if args.solo: + out("Error: --solo is incompatible with --tcxo") + sys.exit(1) + if tester.clkin(): + out("Using TCXO on TESTER") + else: + out("Warning: No TCXO or external clock detected on TESTER") + out("Skipping CLKOUT test") + if not args.noclk and not eut.clkin(): + fail(211) + + # full RF test with clock synchronization + if tester: + eut.test_rf() + + if args.noif or args.solo: + out("Skipping IF tuning range test") + else: + eut.test_if_range(ifmin, ifmax) + + eut.activate_leds(True) + + if (args.solo or args.noif or args.noclk or args.tcxo or not args.rev): + out("Limited test complete") + else: + out("PASS if all 6 LEDs active with correct color") + + count += 1 + if not args.loop: + break + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + print() + out("KeyboardInterrupt") + sys.exit(0) + except subprocess.TimeoutExpired: + log(traceback.format_exc()) + fail(180) diff --git a/ci-scripts/install-host.sh b/ci-scripts/install_host.sh similarity index 100% rename from ci-scripts/install-host.sh rename to ci-scripts/install_host.sh diff --git a/ci-scripts/test-host.sh b/ci-scripts/test_host.sh similarity index 100% rename from ci-scripts/test-host.sh rename to ci-scripts/test_host.sh diff --git a/ci-scripts/test-sgpio-debug.py b/ci-scripts/test_sgpio_debug.py similarity index 100% rename from ci-scripts/test-sgpio-debug.py rename to ci-scripts/test_sgpio_debug.py From 66e148f1afbe9e5e80e5bd9b9442ae5cb18a7944 Mon Sep 17 00:00:00 2001 From: grvvy Date: Thu, 26 Feb 2026 17:47:38 -0700 Subject: [PATCH 029/238] switch from log() to out() to match hackrf one hackrf_test.py, update version string --- ci-scripts/hackrf_pro_test.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/ci-scripts/hackrf_pro_test.py b/ci-scripts/hackrf_pro_test.py index 5afd815c..50447ac0 100644 --- a/ci-scripts/hackrf_pro_test.py +++ b/ci-scripts/hackrf_pro_test.py @@ -633,12 +633,12 @@ class HackRF: self.revision = rev break - log(f"{self.name} Serial number: {self.serial}") - log(f"{self.name} Board ID: {self.id}") - log(f"{self.name} Hardware Revision: {self.revision}") - log(f"{self.name} binary directory {self.bin_dir}") + out(f"{self.name} Serial number: {self.serial}") + out(f"{self.name} Board ID: {self.id}") + out(f"{self.name} Hardware Revision: {self.revision}") + out(f"{self.name} binary directory {self.bin_dir}") except: - log(traceback.format_exc()) + out(traceback.format_exc()) fail(6) if self.serial == None: @@ -806,7 +806,7 @@ class HackRF: self.clkout(False) self.partner.clkout(False) frequency_error_ppm = self.clock_error_ppm() - log(f"{self.name} crystal frequency error: {frequency_error_ppm} ppm") + out(f"{self.name} crystal frequency error: {frequency_error_ppm} ppm") if abs(frequency_error_ppm) > MAX_PPM: fail(260) @@ -1013,7 +1013,7 @@ class HackRF: else: high_end = max_case.freq - 1 - log(f"{self.name} IF range: {min_freq}-{max_freq} MHz") + out(f"{self.name} IF range: {min_freq}-{max_freq} MHz") if min_freq > IF_REQUIRED_MIN or max_freq < IF_REQUIRED_MAX: fail(160) @@ -1204,13 +1204,13 @@ class HackRF: for test_case in (self.rf_test_cases): results.append(int(round(self.measure_rf(test_case, sweep=True) - (SIGNAL_THRESHOLD + 5)))) - log(f"RF results summary: {results}") + out(f"RF results summary: {results}") if self.errors: fail_rf(self.errors) def activate_leds(self, enable): if enable: - log(f"Activating {self.name} LEDs") + out(f"Activating {self.name} LEDs") state = 7 else: state = 1 @@ -1319,11 +1319,11 @@ class HackRF: fail(errors[-1]) def reset(self): - log(f"Resetting {self.name}") + out(f"Resetting {self.name}") spiflash = subprocess.run([self.bin_dir + "/hackrf_spiflash", "-d", self.serial, "-R"], capture_output=True, encoding="utf-8", timeout=TIMEOUT) if spiflash.returncode != 0: - log(spiflash.stdout + spiflash.stderr) + out(spiflash.stdout + spiflash.stderr) fail(76 + self.unit_number) then = time.time() @@ -1375,7 +1375,7 @@ def program(bin_dir, fw_dir, serial, unattended=False): f"{DFU_VENDOR_ID}:{DFU_PRODUCT_ID}", "--alt", "0", "--download", f"{fw_dir}/{dfu_stub}"], capture_output=True, encoding="utf-8", timeout=TIMEOUT) - log(dfu.stdout + dfu.stderr) + out(dfu.stdout + dfu.stderr) #dfu-util: unable to read DFU status after completion (LIBUSB_ERROR_IO) # despite successful download; present as of at least dfu-util 0.11 @@ -1483,7 +1483,7 @@ def get_version(): version = subprocess.run(["git", "log", "-n" "1", "--format=%h"], capture_output=True, encoding="utf-8", timeout=TIMEOUT) if version.returncode != 0: - return "2023.01.1+" + return "2026.01.3+" elif version.returncode == 0: dirty = subprocess.run(["git", "status", "-s", "--untracked-files=no"], capture_output=True, encoding="utf-8", timeout=TIMEOUT) From 6b2e0b6ec8f9fa1595b0ee010732117f31a39a84 Mon Sep 17 00:00:00 2001 From: grvvy Date: Thu, 26 Feb 2026 17:55:02 -0700 Subject: [PATCH 030/238] display transmit stdout and stderr for debugging --- ci-scripts/hackrf_pro_test.py | 2 +- ci-scripts/hackrf_test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/hackrf_pro_test.py b/ci-scripts/hackrf_pro_test.py index 50447ac0..bbe7e85f 100644 --- a/ci-scripts/hackrf_pro_test.py +++ b/ci-scripts/hackrf_pro_test.py @@ -1169,7 +1169,7 @@ class HackRF: tx_out, tx_err = transmit.communicate(timeout=TIMEOUT) if transmit.returncode != 0: - log(tx_out + tx_err) + out(tx_out + tx_err) out(f"Warning: {transmitter.name} transmit failed") return rssi diff --git a/ci-scripts/hackrf_test.py b/ci-scripts/hackrf_test.py index b4f1d9b1..42d0393d 100644 --- a/ci-scripts/hackrf_test.py +++ b/ci-scripts/hackrf_test.py @@ -1045,7 +1045,7 @@ class HackRF: tx_out, tx_err = transmit.communicate(timeout=TIMEOUT) if transmit.returncode != 0: - log(tx_out + tx_err) + out(tx_out + tx_err) out(f"Warning: {transmitter.name} transmit failed") return rssi From b6da7ddef6372ba87c820c3a818830f365de7a57 Mon Sep 17 00:00:00 2001 From: grvvy Date: Fri, 27 Feb 2026 13:01:07 -0700 Subject: [PATCH 031/238] wrap hub commands in timeout blocks --- Jenkinsfile | 108 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 99 insertions(+), 9 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 7079f972..31d8b64c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -20,14 +20,44 @@ pipeline { steps { sh './ci-scripts/install_host.sh' sh './ci-scripts/build_h1_firmware.sh' - sh 'hubs all off' + script { + try { + // Allow 10 seconds for the USB hub port power server to respond + timeout(time: 10, unit: 'SECONDS') { + sh 'hubs all off' + } + } catch (err) { + echo "USB hub port power server command timeout reached." + throw err + } + } retry(3) { - sh 'hubs h1_eut reset' + script { + try { + // Allow 10 seconds for the USB hub port power server to respond + timeout(time: 10, unit: 'SECONDS') { + sh 'hubs h1_eut reset' + } + } catch (err) { + echo "USB hub port power server command timeout reached." + throw err + } + } sh 'sleep 1s' sh './ci-scripts/test_host.sh' } retry(3) { - sh 'hubs h1_tester h1_eut reset' + script { + try { + // Allow 10 seconds for the USB hub port power server to respond + timeout(time: 10, unit: 'SECONDS') { + sh 'hubs h1_tester h1_eut reset' + } + } catch (err) { + echo "USB hub port power server command timeout reached." + throw err + } + } sh 'sleep 1s' sh '''python3 ci-scripts/hackrf_test.py --ci --log log \ --hostdir host/build/hackrf-tools/src/ \ @@ -37,7 +67,17 @@ pipeline { sh 'hubs all off' } retry(3) { - sh 'hubs h1_eut reset' + script { + try { + // Allow 10 seconds for the USB hub port power server to respond + timeout(time: 10, unit: 'SECONDS') { + sh 'hubs h1_eut reset' + } + } catch (err) { + echo "USB hub port power server command timeout reached." + throw err + } + } sh 'sleep 1s' sh 'python3 ci-scripts/test_sgpio_debug.py' } @@ -57,24 +97,74 @@ pipeline { steps { sh './ci-scripts/install_host.sh' sh './ci-scripts/build_hpro_firmware.sh' - sh 'hubs all off' + script { + try { + // Allow 10 seconds for the USB hub port power server to respond + timeout(time: 10, unit: 'SECONDS') { + sh 'hubs all off' + } + } catch (err) { + echo "USB hub port power server command timeout reached." + throw err + } + } retry(3) { - sh 'hubs hpro_eut reset' + script { + try { + // Allow 10 seconds for the USB hub port power server to respond + timeout(time: 10, unit: 'SECONDS') { + sh 'hubs hpro_eut reset' + } + } catch (err) { + echo "USB hub port power server command timeout reached." + throw err + } + } sh 'sleep 1s' sh './ci-scripts/test_host.sh' } retry(3) { - sh 'hubs hpro_tester hpro_eut reset' + script { + try { + // Allow 10 seconds for the USB hub port power server to respond + timeout(time: 10, unit: 'SECONDS') { + sh 'hubs hpro_tester hpro_eut reset' + } + } catch (err) { + echo "USB hub port power server command timeout reached." + throw err + } + } sh 'sleep 1s' sh '''python3 ci-scripts/hackrf_pro_test.py --ci --log log \ --hostdir host/build/hackrf-tools/src \ --fwupdate firmware/hackrf_usb/build \ --tester 0000000000000000a06063c82338145f \ --eut RunningFromRAM -p --rev r1.2''' - sh 'hubs all off' + script { + try { + // Allow 10 seconds for the USB hub port power server to respond + timeout(time: 10, unit: 'SECONDS') { + sh 'hubs all off' + } + } catch (err) { + echo "USB hub port power server command timeout reached." + throw err + } + } } retry(3) { - sh 'hubs hpro_eut reset' + script { + try { + // Allow 10 seconds for the USB hub port power server to respond + timeout(time: 10, unit: 'SECONDS') { + sh 'hubs hpro_eut reset' + } + } catch (err) { + echo "USB hub port power server command timeout reached." + throw err + } + } sh 'sleep 1s' sh 'python3 ci-scripts/test_sgpio_debug.py' } From caa2ef956599bc095b1472e137c0c4eefa4ada38 Mon Sep 17 00:00:00 2001 From: grvvy Date: Mon, 2 Mar 2026 17:20:29 -0700 Subject: [PATCH 032/238] increase hub command timeout duration, remove unnecessary build args --- Jenkinsfile | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 31d8b64c..83341b4b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -13,7 +13,6 @@ pipeline { reuseNode true args '''--group-add=20 --group-add=46 --device-cgroup-rule="c 189:* rmw" \ --device-cgroup-rule="c 166:* rmw" -v /dev/bus/usb:/dev/bus/usb \ - -e TESTER=0000000000000000325866e629a25623 -e EUT=RunningFromRAM \ -v /tmp/req_pipe:/tmp/req_pipe -v /tmp/res_pipe:/tmp/res_pipe''' } } @@ -23,7 +22,7 @@ pipeline { script { try { // Allow 10 seconds for the USB hub port power server to respond - timeout(time: 10, unit: 'SECONDS') { + timeout(time: 20, unit: 'SECONDS') { sh 'hubs all off' } } catch (err) { @@ -35,7 +34,7 @@ pipeline { script { try { // Allow 10 seconds for the USB hub port power server to respond - timeout(time: 10, unit: 'SECONDS') { + timeout(time: 20, unit: 'SECONDS') { sh 'hubs h1_eut reset' } } catch (err) { @@ -50,7 +49,7 @@ pipeline { script { try { // Allow 10 seconds for the USB hub port power server to respond - timeout(time: 10, unit: 'SECONDS') { + timeout(time: 20, unit: 'SECONDS') { sh 'hubs h1_tester h1_eut reset' } } catch (err) { @@ -70,7 +69,7 @@ pipeline { script { try { // Allow 10 seconds for the USB hub port power server to respond - timeout(time: 10, unit: 'SECONDS') { + timeout(time: 20, unit: 'SECONDS') { sh 'hubs h1_eut reset' } } catch (err) { @@ -90,7 +89,6 @@ pipeline { reuseNode true args '''--group-add=20 --group-add=46 --device-cgroup-rule="c 189:* rmw" \ --device-cgroup-rule="c 166:* rmw" -v /dev/bus/usb:/dev/bus/usb \ - -e TESTER=0000000000000000325866e629a25623 -e EUT=RunningFromRAM \ -v /tmp/req_pipe:/tmp/req_pipe -v /tmp/res_pipe:/tmp/res_pipe''' } } @@ -100,7 +98,7 @@ pipeline { script { try { // Allow 10 seconds for the USB hub port power server to respond - timeout(time: 10, unit: 'SECONDS') { + timeout(time: 20, unit: 'SECONDS') { sh 'hubs all off' } } catch (err) { @@ -112,7 +110,7 @@ pipeline { script { try { // Allow 10 seconds for the USB hub port power server to respond - timeout(time: 10, unit: 'SECONDS') { + timeout(time: 20, unit: 'SECONDS') { sh 'hubs hpro_eut reset' } } catch (err) { @@ -127,7 +125,7 @@ pipeline { script { try { // Allow 10 seconds for the USB hub port power server to respond - timeout(time: 10, unit: 'SECONDS') { + timeout(time: 20, unit: 'SECONDS') { sh 'hubs hpro_tester hpro_eut reset' } } catch (err) { @@ -144,7 +142,7 @@ pipeline { script { try { // Allow 10 seconds for the USB hub port power server to respond - timeout(time: 10, unit: 'SECONDS') { + timeout(time: 20, unit: 'SECONDS') { sh 'hubs all off' } } catch (err) { @@ -153,21 +151,6 @@ pipeline { } } } - retry(3) { - script { - try { - // Allow 10 seconds for the USB hub port power server to respond - timeout(time: 10, unit: 'SECONDS') { - sh 'hubs hpro_eut reset' - } - } catch (err) { - echo "USB hub port power server command timeout reached." - throw err - } - } - sh 'sleep 1s' - sh 'python3 ci-scripts/test_sgpio_debug.py' - } } } } From 0e04680435ae622ec5f29cb6addd12b0b7d527f7 Mon Sep 17 00:00:00 2001 From: grvvy Date: Mon, 2 Mar 2026 17:30:46 -0700 Subject: [PATCH 033/238] add timeouts to test script calls --- Jenkinsfile | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 83341b4b..4088e28e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -58,11 +58,21 @@ pipeline { } } sh 'sleep 1s' - sh '''python3 ci-scripts/hackrf_test.py --ci --log log \ - --hostdir host/build/hackrf-tools/src/ \ - --fwupdate firmware/hackrf_usb/build/ \ - --tester 0000000000000000325866e629a25623 \ - --eut RunningFromRAM --unattended --rev r4''' + script { + try { + // Allow 10 seconds for the USB hub port power server to respond + timeout(time: 10, unit: 'MINUTES') { + sh '''python3 ci-scripts/hackrf_test.py --ci --log log \ + --hostdir host/build/hackrf-tools/src/ \ + --fwupdate firmware/hackrf_usb/build/ \ + --tester 0000000000000000325866e629a25623 \ + --eut RunningFromRAM --unattended --rev r4''' + } + } catch (err) { + echo "HackRF One Test timeout reached." + throw err + } + } sh 'hubs all off' } retry(3) { @@ -134,11 +144,22 @@ pipeline { } } sh 'sleep 1s' - sh '''python3 ci-scripts/hackrf_pro_test.py --ci --log log \ - --hostdir host/build/hackrf-tools/src \ - --fwupdate firmware/hackrf_usb/build \ - --tester 0000000000000000a06063c82338145f \ - --eut RunningFromRAM -p --rev r1.2''' + script { + try { + // Allow 10 seconds for the USB hub port power server to respond + timeout(time: 10, unit: 'MINUTES') { + sh '''python3 ci-scripts/hackrf_pro_test.py --ci --log log \ + --hostdir host/build/hackrf-tools/src \ + --fwupdate firmware/hackrf_usb/build \ + --tester 0000000000000000a06063c82338145f \ + --eut RunningFromRAM -p --rev r1.2''' + } + } catch (err) { + echo "HackRF Pro Test timeout reached." + throw err + } + } + script { try { // Allow 10 seconds for the USB hub port power server to respond From 5fa6907c645c7a71deb6b9e0ae19cac47b4f7480 Mon Sep 17 00:00:00 2001 From: grvvy Date: Mon, 2 Mar 2026 19:00:19 -0700 Subject: [PATCH 034/238] improve timeout handling --- Jenkinsfile | 180 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 140 insertions(+), 40 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4088e28e..2ee5b9e5 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,3 +1,5 @@ +import org.jenkinsci.plugins.workflow.steps.FlowInterruptedException + pipeline { agent any stages { @@ -21,24 +23,44 @@ pipeline { sh './ci-scripts/build_h1_firmware.sh' script { try { - // Allow 10 seconds for the USB hub port power server to respond + // Allow 20 seconds for the USB hub port power server to respond timeout(time: 20, unit: 'SECONDS') { sh 'hubs all off' } - } catch (err) { - echo "USB hub port power server command timeout reached." + } catch (FlowInterruptedException err) { + // Check if the cause was specifically an exceeded timeout + def cause = err.getCauses().get(0) + if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { + echo "USB hub port power server command timeout reached." + throw err // Re-throw the exception to fail the build + } else { + echo "Build interrupted for another reason." + throw err // Re-throw the exception to fail the build + } + } catch (Exception err) { + echo "An unrelated error occurred: ${err.getMessage()}" throw err } } retry(3) { script { try { - // Allow 10 seconds for the USB hub port power server to respond + // Allow 20 seconds for the USB hub port power server to respond timeout(time: 20, unit: 'SECONDS') { sh 'hubs h1_eut reset' } - } catch (err) { - echo "USB hub port power server command timeout reached." + } catch (FlowInterruptedException err) { + // Check if the cause was specifically an exceeded timeout + def cause = err.getCauses().get(0) + if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { + echo "USB hub port power server command timeout reached." + throw err // Re-throw the exception to fail the build + } else { + echo "Build interrupted for another reason." + throw err // Re-throw the exception to fail the build + } + } catch (Exception err) { + echo "An unrelated error occurred: ${err.getMessage()}" throw err } } @@ -48,42 +70,92 @@ pipeline { retry(3) { script { try { - // Allow 10 seconds for the USB hub port power server to respond + // Allow 20 seconds for the USB hub port power server to respond timeout(time: 20, unit: 'SECONDS') { sh 'hubs h1_tester h1_eut reset' } - } catch (err) { - echo "USB hub port power server command timeout reached." + } catch (FlowInterruptedException err) { + // Check if the cause was specifically an exceeded timeout + def cause = err.getCauses().get(0) + if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { + echo "USB hub port power server command timeout reached." + throw err // Re-throw the exception to fail the build + } else { + echo "Build interrupted for another reason." + throw err // Re-throw the exception to fail the build + } + } catch (Exception err) { + echo "An unrelated error occurred: ${err.getMessage()}" throw err } } sh 'sleep 1s' script { try { - // Allow 10 seconds for the USB hub port power server to respond - timeout(time: 10, unit: 'MINUTES') { + // Allow 5 minutes for the test to run + timeout(time: 5, unit: 'MINUTES') { sh '''python3 ci-scripts/hackrf_test.py --ci --log log \ --hostdir host/build/hackrf-tools/src/ \ --fwupdate firmware/hackrf_usb/build/ \ --tester 0000000000000000325866e629a25623 \ --eut RunningFromRAM --unattended --rev r4''' } - } catch (err) { - echo "HackRF One Test timeout reached." + } catch (FlowInterruptedException err) { + // Check if the cause was specifically an exceeded timeout + def cause = err.getCauses().get(0) + if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { + echo "HackRF One Test timeout limit reached." + throw err // Re-throw the exception to fail the build + } else { + echo "Build interrupted for another reason." + throw err // Re-throw the exception to fail the build + } + } catch (Exception err) { + echo "An unrelated error occurred: ${err.getMessage()}" + throw err + } + } + script { + try { + // Allow 20 seconds for the USB hub port power server to respond + timeout(time: 20, unit: 'SECONDS') { + sh 'hubs all off' + } + } catch (FlowInterruptedException err) { + // Check if the cause was specifically an exceeded timeout + def cause = err.getCauses().get(0) + if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { + echo "USB hub port power server command timeout reached." + throw err // Re-throw the exception to fail the build + } else { + echo "Build interrupted for another reason." + throw err // Re-throw the exception to fail the build + } + } catch (Exception err) { + echo "An unrelated error occurred: ${err.getMessage()}" throw err } } - sh 'hubs all off' } retry(3) { script { try { - // Allow 10 seconds for the USB hub port power server to respond + // Allow 20 seconds for the USB hub port power server to respond timeout(time: 20, unit: 'SECONDS') { sh 'hubs h1_eut reset' } - } catch (err) { - echo "USB hub port power server command timeout reached." + } catch (FlowInterruptedException err) { + // Check if the cause was specifically an exceeded timeout + def cause = err.getCauses().get(0) + if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { + echo "USB hub port power server command timeout reached." + throw err // Re-throw the exception to fail the build + } else { + echo "Build interrupted for another reason." + throw err // Re-throw the exception to fail the build + } + } catch (Exception err) { + echo "An unrelated error occurred: ${err.getMessage()}" throw err } } @@ -107,24 +179,44 @@ pipeline { sh './ci-scripts/build_hpro_firmware.sh' script { try { - // Allow 10 seconds for the USB hub port power server to respond + // Allow 20 seconds for the USB hub port power server to respond timeout(time: 20, unit: 'SECONDS') { sh 'hubs all off' } - } catch (err) { - echo "USB hub port power server command timeout reached." + } catch (FlowInterruptedException err) { + // Check if the cause was specifically an exceeded timeout + def cause = err.getCauses().get(0) + if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { + echo "USB hub port power server command timeout reached." + throw err // Re-throw the exception to fail the build + } else { + echo "Build interrupted for another reason." + throw err // Re-throw the exception to fail the build + } + } catch (Exception err) { + echo "An unrelated error occurred: ${err.getMessage()}" throw err } } retry(3) { script { try { - // Allow 10 seconds for the USB hub port power server to respond + // Allow 20 seconds for the USB hub port power server to respond timeout(time: 20, unit: 'SECONDS') { sh 'hubs hpro_eut reset' } - } catch (err) { - echo "USB hub port power server command timeout reached." + } catch (FlowInterruptedException err) { + // Check if the cause was specifically an exceeded timeout + def cause = err.getCauses().get(0) + if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { + echo "USB hub port power server command timeout reached." + throw err // Re-throw the exception to fail the build + } else { + echo "Build interrupted for another reason." + throw err // Re-throw the exception to fail the build + } + } catch (Exception err) { + echo "An unrelated error occurred: ${err.getMessage()}" throw err } } @@ -138,36 +230,44 @@ pipeline { timeout(time: 20, unit: 'SECONDS') { sh 'hubs hpro_tester hpro_eut reset' } - } catch (err) { - echo "USB hub port power server command timeout reached." + } catch (FlowInterruptedException err) { + // Check if the cause was specifically an exceeded timeout + def cause = err.getCauses().get(0) + if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { + echo "USB hub port power server command timeout reached." + throw err // Re-throw the exception to fail the build + } else { + echo "Build interrupted for another reason." + throw err // Re-throw the exception to fail the build + } + } catch (Exception err) { + echo "An unrelated error occurred: ${err.getMessage()}" throw err } } sh 'sleep 1s' script { try { - // Allow 10 seconds for the USB hub port power server to respond - timeout(time: 10, unit: 'MINUTES') { + // Allow 5 minutes for the test to run + timeout(time: 5, unit: 'MINUTES') { sh '''python3 ci-scripts/hackrf_pro_test.py --ci --log log \ --hostdir host/build/hackrf-tools/src \ --fwupdate firmware/hackrf_usb/build \ --tester 0000000000000000a06063c82338145f \ --eut RunningFromRAM -p --rev r1.2''' } - } catch (err) { - echo "HackRF Pro Test timeout reached." - throw err - } - } - - script { - try { - // Allow 10 seconds for the USB hub port power server to respond - timeout(time: 20, unit: 'SECONDS') { - sh 'hubs all off' + } catch (FlowInterruptedException err) { + // Check if the cause was specifically an exceeded timeout + def cause = err.getCauses().get(0) + if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { + echo "HackRF Pro Test timeout limit reached." + throw err // Re-throw the exception to fail the build + } else { + echo "Build interrupted for another reason." + throw err // Re-throw the exception to fail the build } - } catch (err) { - echo "USB hub port power server command timeout reached." + } catch (Exception err) { + echo "An unrelated error occurred: ${err.getMessage()}" throw err } } From 5a07b8629bcd4a82a9959b3f6e647fd49f4f7a5a Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 26 Jan 2026 01:36:44 +0000 Subject: [PATCH 035/238] Rename 'struct gpio_t' to 'struct gpio' to distinguish from gpio_t. --- firmware/common/gpio.h | 2 +- firmware/common/gpio_lpc.h | 4 +- firmware/common/hackrf_core.c | 158 +++++++++++------------ firmware/common/max283x.c | 12 +- firmware/common/mixer.c | 30 ++--- firmware/common/operacake.c | 2 +- firmware/common/platform_detect.c | 14 +- firmware/common/portapack.c | 14 +- firmware/common/rad1o/display.c | 6 +- firmware/common/rf_path.c | 2 +- firmware/common/si5351c.c | 6 +- firmware/hackrf_usb/usb_api_board_info.c | 6 +- 12 files changed, 128 insertions(+), 128 deletions(-) diff --git a/firmware/common/gpio.h b/firmware/common/gpio.h index a492e62b..387b91a3 100644 --- a/firmware/common/gpio.h +++ b/firmware/common/gpio.h @@ -25,7 +25,7 @@ #include -typedef const struct gpio_t* gpio_t; +typedef const struct gpio* gpio_t; void gpio_init(void); void gpio_set(gpio_t gpio); diff --git a/firmware/common/gpio_lpc.h b/firmware/common/gpio_lpc.h index ed181651..f47e490a 100644 --- a/firmware/common/gpio_lpc.h +++ b/firmware/common/gpio_lpc.h @@ -32,7 +32,7 @@ * register #defines and API declarations into separate header files. */ -typedef struct gpio_port_t { +typedef struct gpio_port { volatile uint32_t dir; /* +0x000 */ uint32_t _reserved0[31]; volatile uint32_t mask; /* +0x080 */ @@ -48,7 +48,7 @@ typedef struct gpio_port_t { volatile uint32_t inv; /* +0x300 */ } gpio_port_t; -struct gpio_t { +struct gpio { const uint32_t mask; gpio_port_t* const port; volatile uint32_t* const gpio_w; diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 5509b9b1..1b60b13f 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -52,7 +52,7 @@ #include "gpio_lpc.h" /* GPIO Output PinMux */ -static struct gpio_t gpio_led[] = { +static struct gpio gpio_led[] = { GPIO(2, 1), GPIO(2, 2), GPIO(2, 8), @@ -66,134 +66,134 @@ static struct gpio_t gpio_led[] = { // clang-format off #ifndef PRALINE -static struct gpio_t gpio_1v8_enable = GPIO(3, 6); +static struct gpio gpio_1v8_enable = GPIO(3, 6); #else -static struct gpio_t gpio_1v2_enable = GPIO(4, 7); -static struct gpio_t gpio_3v3aux_enable_n = GPIO(5, 15); +static struct gpio gpio_1v2_enable = GPIO(4, 7); +static struct gpio gpio_3v3aux_enable_n = GPIO(5, 15); #endif /* MAX283x GPIO (XCVR_CTL / CS_XCVR) PinMux */ #ifdef PRALINE -static struct gpio_t gpio_max283x_select = GPIO(6, 28); +static struct gpio gpio_max283x_select = GPIO(6, 28); #else -static struct gpio_t gpio_max283x_select = GPIO(0, 15); +static struct gpio gpio_max283x_select = GPIO(0, 15); #endif /* MAX5864 SPI chip select (AD_CS / CS_AD) GPIO PinMux */ #ifdef PRALINE -static struct gpio_t gpio_max5864_select = GPIO(6, 30); +static struct gpio gpio_max5864_select = GPIO(6, 30); #else -static struct gpio_t gpio_max5864_select = GPIO(2, 7); +static struct gpio gpio_max5864_select = GPIO(2, 7); #endif /* RFFC5071 GPIO serial interface PinMux */ // #ifdef RAD1O -// static struct gpio_t gpio_rffc5072_select = GPIO(2, 13); -// static struct gpio_t gpio_rffc5072_clock = GPIO(5, 6); -// static struct gpio_t gpio_rffc5072_data = GPIO(3, 3); -// static struct gpio_t gpio_rffc5072_reset = GPIO(2, 14); +// static struct gpio gpio_rffc5072_select = GPIO(2, 13); +// static struct gpio gpio_rffc5072_clock = GPIO(5, 6); +// static struct gpio gpio_rffc5072_data = GPIO(3, 3); +// static struct gpio gpio_rffc5072_reset = GPIO(2, 14); // #endif /* RF supply (VAA) control */ #ifdef HACKRF_ONE -static struct gpio_t gpio_vaa_disable = GPIO(2, 9); +static struct gpio gpio_vaa_disable = GPIO(2, 9); #endif #ifdef PRALINE -static struct gpio_t gpio_vaa_disable = GPIO(4, 1); +static struct gpio gpio_vaa_disable = GPIO(4, 1); #endif #ifdef RAD1O -static struct gpio_t gpio_vaa_enable = GPIO(2, 9); +static struct gpio gpio_vaa_enable = GPIO(2, 9); #endif -static struct gpio_t gpio_w25q80bv_hold = GPIO(1, 14); -static struct gpio_t gpio_w25q80bv_wp = GPIO(1, 15); -static struct gpio_t gpio_w25q80bv_select = GPIO(5, 11); +static struct gpio gpio_w25q80bv_hold = GPIO(1, 14); +static struct gpio gpio_w25q80bv_wp = GPIO(1, 15); +static struct gpio gpio_w25q80bv_select = GPIO(5, 11); /* RF switch control */ #ifdef HACKRF_ONE -static struct gpio_t gpio_hp = GPIO(2, 0); -static struct gpio_t gpio_lp = GPIO(2, 10); -static struct gpio_t gpio_tx_mix_bp = GPIO(2, 11); -static struct gpio_t gpio_no_mix_bypass = GPIO(1, 0); -static struct gpio_t gpio_rx_mix_bp = GPIO(2, 12); -static struct gpio_t gpio_tx_amp = GPIO(2, 15); -static struct gpio_t gpio_tx = GPIO(5, 15); -static struct gpio_t gpio_mix_bypass = GPIO(5, 16); -static struct gpio_t gpio_rx = GPIO(5, 5); -static struct gpio_t gpio_no_tx_amp_pwr = GPIO(3, 5); -static struct gpio_t gpio_amp_bypass = GPIO(0, 14); -static struct gpio_t gpio_rx_amp = GPIO(1, 11); -static struct gpio_t gpio_no_rx_amp_pwr = GPIO(1, 12); +static struct gpio gpio_hp = GPIO(2, 0); +static struct gpio gpio_lp = GPIO(2, 10); +static struct gpio gpio_tx_mix_bp = GPIO(2, 11); +static struct gpio gpio_no_mix_bypass = GPIO(1, 0); +static struct gpio gpio_rx_mix_bp = GPIO(2, 12); +static struct gpio gpio_tx_amp = GPIO(2, 15); +static struct gpio gpio_tx = GPIO(5, 15); +static struct gpio gpio_mix_bypass = GPIO(5, 16); +static struct gpio gpio_rx = GPIO(5, 5); +static struct gpio gpio_no_tx_amp_pwr = GPIO(3, 5); +static struct gpio gpio_amp_bypass = GPIO(0, 14); +static struct gpio gpio_rx_amp = GPIO(1, 11); +static struct gpio gpio_no_rx_amp_pwr = GPIO(1, 12); #endif #ifdef RAD1O -static struct gpio_t gpio_tx_rx_n = GPIO(1, 11); -static struct gpio_t gpio_tx_rx = GPIO(0, 14); -static struct gpio_t gpio_by_mix = GPIO(1, 12); -static struct gpio_t gpio_by_mix_n = GPIO(2, 10); -static struct gpio_t gpio_by_amp = GPIO(1, 0); -static struct gpio_t gpio_by_amp_n = GPIO(5, 5); -static struct gpio_t gpio_mixer_en = GPIO(5, 16); -static struct gpio_t gpio_low_high_filt = GPIO(2, 11); -static struct gpio_t gpio_low_high_filt_n = GPIO(2, 12); -static struct gpio_t gpio_tx_amp = GPIO(2, 15); -static struct gpio_t gpio_rx_lna = GPIO(5, 15); +static struct gpio gpio_tx_rx_n = GPIO(1, 11); +static struct gpio gpio_tx_rx = GPIO(0, 14); +static struct gpio gpio_by_mix = GPIO(1, 12); +static struct gpio gpio_by_mix_n = GPIO(2, 10); +static struct gpio gpio_by_amp = GPIO(1, 0); +static struct gpio gpio_by_amp_n = GPIO(5, 5); +static struct gpio gpio_mixer_en = GPIO(5, 16); +static struct gpio gpio_low_high_filt = GPIO(2, 11); +static struct gpio gpio_low_high_filt_n = GPIO(2, 12); +static struct gpio gpio_tx_amp = GPIO(2, 15); +static struct gpio gpio_rx_lna = GPIO(5, 15); #endif #ifdef PRALINE -static struct gpio_t gpio_tx_en = GPIO(3, 4); -static struct gpio_t gpio_mix_en_n = GPIO(3, 2); -static struct gpio_t gpio_mix_en_n_r1_0 = GPIO(5, 6); -static struct gpio_t gpio_lpf_en = GPIO(4, 8); -static struct gpio_t gpio_rf_amp_en = GPIO(4, 9); -static struct gpio_t gpio_ant_bias_en_n = GPIO(1, 12); +static struct gpio gpio_tx_en = GPIO(3, 4); +static struct gpio gpio_mix_en_n = GPIO(3, 2); +static struct gpio gpio_mix_en_n_r1_0 = GPIO(5, 6); +static struct gpio gpio_lpf_en = GPIO(4, 8); +static struct gpio gpio_rf_amp_en = GPIO(4, 9); +static struct gpio gpio_ant_bias_en_n = GPIO(1, 12); #endif /* CPLD JTAG interface GPIO pins, FPGA config pins in Praline */ -static struct gpio_t gpio_cpld_tck = GPIO(3, 0); +static struct gpio gpio_cpld_tck = GPIO(3, 0); #ifdef PRALINE -static struct gpio_t gpio_fpga_cfg_creset = GPIO(2, 11); -static struct gpio_t gpio_fpga_cfg_cdone = GPIO(5, 14); -static struct gpio_t gpio_fpga_cfg_spi_cs = GPIO(2, 10); +static struct gpio gpio_fpga_cfg_creset = GPIO(2, 11); +static struct gpio gpio_fpga_cfg_cdone = GPIO(5, 14); +static struct gpio gpio_fpga_cfg_spi_cs = GPIO(2, 10); #else -static struct gpio_t gpio_cpld_tdo = GPIO(5, 18); +static struct gpio gpio_cpld_tdo = GPIO(5, 18); #if (defined HACKRF_ONE || defined RAD1O) -static struct gpio_t gpio_cpld_tms = GPIO(3, 4); -static struct gpio_t gpio_cpld_tdi = GPIO(3, 1); +static struct gpio gpio_cpld_tms = GPIO(3, 4); +static struct gpio gpio_cpld_tdi = GPIO(3, 1); #else -static struct gpio_t gpio_cpld_tms = GPIO(3, 1); -static struct gpio_t gpio_cpld_tdi = GPIO(3, 4); +static struct gpio gpio_cpld_tms = GPIO(3, 1); +static struct gpio gpio_cpld_tdi = GPIO(3, 4); #endif #endif #if (defined HACKRF_ONE || defined PRALINE) -static struct gpio_t gpio_cpld_pp_tms = GPIO(1, 1); -static struct gpio_t gpio_cpld_pp_tdo = GPIO(1, 8); +static struct gpio gpio_cpld_pp_tms = GPIO(1, 1); +static struct gpio gpio_cpld_pp_tdo = GPIO(1, 8); #endif /* other CPLD interface GPIO pins */ #ifndef PRALINE -static struct gpio_t gpio_trigger_enable = GPIO(5, 12); +static struct gpio gpio_trigger_enable = GPIO(5, 12); #endif -static struct gpio_t gpio_q_invert = GPIO(0, 13); +static struct gpio gpio_q_invert = GPIO(0, 13); /* HackRF One r9 */ #ifdef HACKRF_ONE -static struct gpio_t gpio_h1r9_rx = GPIO(0, 7); -static struct gpio_t gpio_h1r9_1v8_enable = GPIO(2, 9); -static struct gpio_t gpio_h1r9_vaa_disable = GPIO(3, 6); -static struct gpio_t gpio_h1r9_trigger_enable = GPIO(5, 5); +static struct gpio gpio_h1r9_rx = GPIO(0, 7); +static struct gpio gpio_h1r9_1v8_enable = GPIO(2, 9); +static struct gpio gpio_h1r9_vaa_disable = GPIO(3, 6); +static struct gpio gpio_h1r9_trigger_enable = GPIO(5, 5); #endif #ifdef PRALINE -static struct gpio_t gpio_p2_ctrl0 = GPIO(7, 3); -static struct gpio_t gpio_p2_ctrl1 = GPIO(7, 4); -static struct gpio_t gpio_p1_ctrl0 = GPIO(0, 14); -static struct gpio_t gpio_p1_ctrl1 = GPIO(5, 16); -static struct gpio_t gpio_p1_ctrl2 = GPIO(3, 5); -static struct gpio_t gpio_clkin_ctrl = GPIO(0, 15); -static struct gpio_t gpio_aa_en = GPIO(1, 7); -static struct gpio_t gpio_trigger_in = GPIO(6, 26); -static struct gpio_t gpio_trigger_out = GPIO(5, 6); -static struct gpio_t gpio_pps_out = GPIO(5, 5); +static struct gpio gpio_p2_ctrl0 = GPIO(7, 3); +static struct gpio gpio_p2_ctrl1 = GPIO(7, 4); +static struct gpio gpio_p1_ctrl0 = GPIO(0, 14); +static struct gpio gpio_p1_ctrl1 = GPIO(5, 16); +static struct gpio gpio_p1_ctrl2 = GPIO(3, 5); +static struct gpio gpio_clkin_ctrl = GPIO(0, 15); +static struct gpio gpio_aa_en = GPIO(1, 7); +static struct gpio gpio_trigger_in = GPIO(6, 26); +static struct gpio gpio_trigger_out = GPIO(5, 6); +static struct gpio gpio_pps_out = GPIO(5, 5); #endif // clang-format on @@ -248,10 +248,10 @@ const ssp_config_t ssp_config_max283x = { .gpio_select = &gpio_max283x_select, }; -static struct gpio_t gpio_max2831_enable = GPIO(7, 1); -static struct gpio_t gpio_max2831_rx_enable = GPIO(7, 2); -static struct gpio_t gpio_max2831_rxhp = GPIO(6, 29); -static struct gpio_t gpio_max2831_ld = GPIO(4, 11); +static struct gpio gpio_max2831_enable = GPIO(7, 1); +static struct gpio gpio_max2831_rx_enable = GPIO(7, 2); +static struct gpio gpio_max2831_rxhp = GPIO(6, 29); +static struct gpio gpio_max2831_ld = GPIO(4, 11); max2831_driver_t max283x = { .bus = &spi_bus_ssp1, diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index 5d291804..3b8fca83 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -33,13 +33,13 @@ extern spi_bus_t spi_bus_ssp1; #ifdef PRALINE -static struct gpio_t gpio_max2837_enable = GPIO(6, 29); -static struct gpio_t gpio_max2837_rx_enable = GPIO(3, 3); -static struct gpio_t gpio_max2837_tx_enable = GPIO(3, 2); +static struct gpio gpio_max2837_enable = GPIO(6, 29); +static struct gpio gpio_max2837_rx_enable = GPIO(3, 3); +static struct gpio gpio_max2837_tx_enable = GPIO(3, 2); #else -static struct gpio_t gpio_max2837_enable = GPIO(2, 6); -static struct gpio_t gpio_max2837_rx_enable = GPIO(2, 5); -static struct gpio_t gpio_max2837_tx_enable = GPIO(2, 4); +static struct gpio gpio_max2837_enable = GPIO(2, 6); +static struct gpio gpio_max2837_rx_enable = GPIO(2, 5); +static struct gpio gpio_max2837_tx_enable = GPIO(2, 4); #endif max2837_driver_t max2837 = { diff --git a/firmware/common/mixer.c b/firmware/common/mixer.c index e29869c6..3e4c8083 100644 --- a/firmware/common/mixer.c +++ b/firmware/common/mixer.c @@ -28,25 +28,25 @@ /* RFFC5071 GPIO serial interface PinMux */ // clang-format off #if (defined JAWBREAKER || defined HACKRF_ONE) -static struct gpio_t gpio_rffc5072_select = GPIO(2, 13); -static struct gpio_t gpio_rffc5072_clock = GPIO(5, 6); -static struct gpio_t gpio_rffc5072_data = GPIO(3, 3); -static struct gpio_t gpio_rffc5072_reset = GPIO(2, 14); +static struct gpio gpio_rffc5072_select = GPIO(2, 13); +static struct gpio gpio_rffc5072_clock = GPIO(5, 6); +static struct gpio gpio_rffc5072_data = GPIO(3, 3); +static struct gpio gpio_rffc5072_reset = GPIO(2, 14); #endif #ifdef RAD1O -static struct gpio_t gpio_vco_ce = GPIO(2, 13); -static struct gpio_t gpio_vco_sclk = GPIO(5, 6); -static struct gpio_t gpio_vco_sdata = GPIO(3, 3); -static struct gpio_t gpio_vco_le = GPIO(2, 14); -static struct gpio_t gpio_vco_mux = GPIO(5, 25); -static struct gpio_t gpio_synt_rfout_en = GPIO(3, 5); +static struct gpio gpio_vco_ce = GPIO(2, 13); +static struct gpio gpio_vco_sclk = GPIO(5, 6); +static struct gpio gpio_vco_sdata = GPIO(3, 3); +static struct gpio gpio_vco_le = GPIO(2, 14); +static struct gpio gpio_vco_mux = GPIO(5, 25); +static struct gpio gpio_synt_rfout_en = GPIO(3, 5); #endif #ifdef PRALINE -static struct gpio_t gpio_rffc5072_select = GPIO(2, 13); -static struct gpio_t gpio_rffc5072_clock = GPIO(5, 18); -static struct gpio_t gpio_rffc5072_data = GPIO(4, 14); -static struct gpio_t gpio_rffc5072_reset = GPIO(2, 14); -static struct gpio_t gpio_rffc5072_ld = GPIO(6, 25); +static struct gpio gpio_rffc5072_select = GPIO(2, 13); +static struct gpio gpio_rffc5072_clock = GPIO(5, 18); +static struct gpio gpio_rffc5072_data = GPIO(4, 14); +static struct gpio gpio_rffc5072_reset = GPIO(2, 14); +static struct gpio gpio_rffc5072_ld = GPIO(6, 25); #endif // clang-format on diff --git a/firmware/common/operacake.c b/firmware/common/operacake.c index 297f5099..e7f71a5b 100644 --- a/firmware/common/operacake.c +++ b/firmware/common/operacake.c @@ -393,7 +393,7 @@ uint16_t gpio_test(uint8_t address) scu_pinmux(SCU_PINMUX_GPIO3_14, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_PINMUX_GPIO3_15, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - static struct gpio_t gpio_pins[] = { + static struct gpio gpio_pins[] = { GPIO(3, 8), // u1ctrl IO2 GPIO(3, 14), // u3ctrl0 IO3 GPIO(3, 15), // u3ctrl1 IO4 diff --git a/firmware/common/platform_detect.c b/firmware/common/platform_detect.c index 199878d8..bb44a61c 100644 --- a/firmware/common/platform_detect.c +++ b/firmware/common/platform_detect.c @@ -31,10 +31,10 @@ static board_id_t platform = BOARD_ID_UNDETECTED; static board_rev_t revision = BOARD_REV_UNDETECTED; -static struct gpio_t gpio2_9_on_P5_0 = GPIO(2, 9); -static struct gpio_t gpio3_6_on_P6_10 = GPIO(3, 6); -static struct gpio_t gpio3_4_on_P6_5 = GPIO(3, 4); -static struct gpio_t gpio2_6_on_P4_6 = GPIO(2, 6); +static struct gpio gpio2_9_on_P5_0 = GPIO(2, 9); +static struct gpio gpio3_6_on_P6_10 = GPIO(3, 6); +static struct gpio gpio3_4_on_P6_5 = GPIO(3, 4); +static struct gpio gpio2_6_on_P4_6 = GPIO(2, 6); #define P5_0_PUP (1 << 0) #define P5_0_PDN (1 << 1) @@ -61,9 +61,9 @@ static struct gpio_t gpio2_6_on_P4_6 = GPIO(2, 6); * hardware detection failure, but three LEDs are flashed if CPLD/FPGA configuration * fails. */ -static struct gpio_t gpio_led1 = GPIO(2, 1); -static struct gpio_t gpio_led2 = GPIO(2, 2); -static struct gpio_t gpio_led3 = GPIO(2, 8); +static struct gpio gpio_led1 = GPIO(2, 1); +static struct gpio gpio_led2 = GPIO(2, 2); +static struct gpio gpio_led3 = GPIO(2, 8); /* * Starting with r6, HackRF One has pin straps on ADC pins that indicate diff --git a/firmware/common/portapack.c b/firmware/common/portapack.c index c2775bb8..cad8f8cc 100644 --- a/firmware/common/portapack.c +++ b/firmware/common/portapack.c @@ -35,15 +35,15 @@ static void portapack_sleep_milliseconds(const uint32_t milliseconds) } // clang-format off -static struct gpio_t gpio_io_stbx = GPIO(5, 0); /* P2_0 */ -static struct gpio_t gpio_addr = GPIO(5, 1); /* P2_1 */ +static struct gpio gpio_io_stbx = GPIO(5, 0); /* P2_0 */ +static struct gpio gpio_addr = GPIO(5, 1); /* P2_1 */ __attribute__((unused)) -static struct gpio_t gpio_lcd_te = GPIO(5, 3); /* P2_3 */ +static struct gpio gpio_lcd_te = GPIO(5, 3); /* P2_3 */ __attribute__((unused)) -static struct gpio_t gpio_unused = GPIO(5, 7); /* P2_8 */ -static struct gpio_t gpio_lcd_rdx = GPIO(5, 4); /* P2_4 */ -static struct gpio_t gpio_lcd_wrx = GPIO(1, 10); /* P2_9 */ -static struct gpio_t gpio_dir = GPIO(1, 13); /* P2_13 */ +static struct gpio gpio_unused = GPIO(5, 7); /* P2_8 */ +static struct gpio gpio_lcd_rdx = GPIO(5, 4); /* P2_4 */ +static struct gpio gpio_lcd_wrx = GPIO(1, 10); /* P2_9 */ +static struct gpio gpio_dir = GPIO(1, 13); /* P2_13 */ // clang-format on diff --git a/firmware/common/rad1o/display.c b/firmware/common/rad1o/display.c index 86abead0..a48202e0 100644 --- a/firmware/common/rad1o/display.c +++ b/firmware/common/rad1o/display.c @@ -17,9 +17,9 @@ static void delayms(const uint32_t milliseconds) delay(milliseconds * 40800); } -static struct gpio_t gpio_lcd_cs = GPIO(4, 12); /* P9_0 */ -static struct gpio_t gpio_lcd_bl_en = GPIO(0, 8); /* P1_1 */ -static struct gpio_t gpio_lcd_reset = GPIO(5, 17); /* P9_4 */ +static struct gpio gpio_lcd_cs = GPIO(4, 12); /* P9_0 */ +static struct gpio gpio_lcd_bl_en = GPIO(0, 8); /* P1_1 */ +static struct gpio gpio_lcd_reset = GPIO(5, 17); /* P9_4 */ /**************************************************************************/ /* Utility routines to manage nokia display */ diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 87f0bb94..13b96cc9 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -99,7 +99,7 @@ * In HackRF One r9 this control signal has been moved to the microcontroller. */ -static struct gpio_t gpio_h1r9_no_ant_pwr = GPIO(2, 4); +static struct gpio gpio_h1r9_no_ant_pwr = GPIO(2, 4); static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) { diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index d9686ea1..d9d9ef37 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -30,9 +30,9 @@ /* HackRF One r9 clock control */ // clang-format off -static struct gpio_t gpio_h1r9_clkin_en = GPIO(5, 15); -static struct gpio_t gpio_h1r9_clkout_en = GPIO(0, 9); -static struct gpio_t gpio_h1r9_mcu_clk_en = GPIO(0, 8); +static struct gpio gpio_h1r9_clkin_en = GPIO(5, 15); +static struct gpio gpio_h1r9_clkout_en = GPIO(0, 9); +static struct gpio gpio_h1r9_mcu_clk_en = GPIO(0, 8); // clang-format on #include diff --git a/firmware/hackrf_usb/usb_api_board_info.c b/firmware/hackrf_usb/usb_api_board_info.c index aeff83b8..f9f75623 100644 --- a/firmware/hackrf_usb/usb_api_board_info.c +++ b/firmware/hackrf_usb/usb_api_board_info.c @@ -35,9 +35,9 @@ #ifdef HACKRF_ONE #include "gpio_lpc.h" -static struct gpio_t gpio_h1r9_clkout_en = GPIO(0, 9); -static struct gpio_t gpio_h1r9_mcu_clk_en = GPIO(0, 8); -static struct gpio_t gpio_h1r9_rx = GPIO(0, 7); +static struct gpio gpio_h1r9_clkout_en = GPIO(0, 9); +static struct gpio gpio_h1r9_mcu_clk_en = GPIO(0, 8); +static struct gpio gpio_h1r9_rx = GPIO(0, 7); #endif usb_request_status_t usb_vendor_request_read_board_id( From 30229730b45a02bddacfc2ea1cc925eebaa2fbbd Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sat, 28 Feb 2026 19:17:16 -0500 Subject: [PATCH 036/238] Fix baseband bandwidth configuration --- firmware/common/max2831.c | 8 ++-- firmware/common/max2831.h | 1 + firmware/common/radio.c | 89 +++++++++++++++------------------------ 3 files changed, 39 insertions(+), 59 deletions(-) diff --git a/firmware/common/max2831.c b/firmware/common/max2831.c index 6f641f54..efae9eb6 100644 --- a/firmware/common/max2831.c +++ b/firmware/common/max2831.c @@ -150,7 +150,7 @@ void max2831_set_mode(max2831_driver_t* const drv, const max2831_mode_t new_mode } drv->set_mode(drv, new_mode); - max2831_set_lpf_bandwidth(drv, drv->desired_lpf_bw); + max2831_set_lpf_bandwidth(drv, new_mode, drv->desired_lpf_bw); } max2831_mode_t max2831_mode(max2831_driver_t* const drv) @@ -304,13 +304,13 @@ static const max2831_ft_fine_t max2831_tx_ft_fine[] = { //clang-format on -uint32_t max2831_set_lpf_bandwidth(max2831_driver_t* const drv, const uint32_t bandwidth_hz) { +uint32_t max2831_set_lpf_bandwidth(max2831_driver_t* const drv, const max2831_mode_t mode, const uint32_t bandwidth_hz) { const max2831_ft_t* coarse; const max2831_ft_fine_t* fine; drv->desired_lpf_bw = bandwidth_hz; - if (drv->mode == MAX2831_MODE_RX) { + if (mode == MAX2831_MODE_RX) { coarse = max2831_rx_ft; fine = max2831_rx_ft_fine; } else { @@ -343,7 +343,7 @@ uint32_t max2831_set_lpf_bandwidth(max2831_driver_t* const drv, const uint32_t b /* Program found settings. */ set_MAX2831_LPF_COARSE(drv, coarse->ft); - if (drv->mode == MAX2831_MODE_RX) { + if (mode == MAX2831_MODE_RX) { set_MAX2831_RX_LPF_FINE_ADJ(drv, f->ft_fine); } else { set_MAX2831_TX_LPF_FINE_ADJ(drv, f->ft_fine); diff --git a/firmware/common/max2831.h b/firmware/common/max2831.h index 033b590e..c60b6a7e 100644 --- a/firmware/common/max2831.h +++ b/firmware/common/max2831.h @@ -93,6 +93,7 @@ extern void max2831_stop(max2831_driver_t* const drv); extern void max2831_set_frequency(max2831_driver_t* const drv, uint32_t freq); uint32_t max2831_set_lpf_bandwidth( max2831_driver_t* const drv, + const max2831_mode_t mode, const uint32_t bandwidth_hz); bool max2831_set_lna_gain(max2831_driver_t* const drv, const uint32_t gain_db); bool max2831_set_vga_gain(max2831_driver_t* const drv, const uint32_t gain_db); diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 482da9fb..90d3f030 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -394,7 +394,7 @@ static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) return true; } -static uint32_t auto_bandwidth(radio_t* const radio, uint64_t opmode) +static uint32_t auto_bandwidth(radio_t* const radio) { uint64_t rotation = radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION]; @@ -413,70 +413,49 @@ static uint32_t auto_bandwidth(radio_t* const radio, uint64_t opmode) const uint32_t bb_bandwidth = (sample_rate_hz * 3) / 4; const uint32_t lpf_bandwidth = bb_bandwidth + offset_hz * 2; - switch (opmode) { - case TRANSCEIVER_MODE_TX: - case TRANSCEIVER_MODE_SS: - radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_TX] = bb_bandwidth; - break; - default: - radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_RX] = bb_bandwidth; - } + radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_TX] = bb_bandwidth; + radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_RX] = bb_bandwidth; + return lpf_bandwidth; } static bool radio_update_bandwidth(radio_t* const radio, uint64_t* bank) { bool new_bw = false; - uint64_t opmode = bank[RADIO_OPMODE]; - if (opmode == RADIO_UNSET) { - opmode = radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]; - } #ifdef PRALINE /* Praline legacy mode always sets baseband bandwidth automatically. */ (void) bank; - uint32_t lpf_bandwidth = auto_bandwidth(radio, opmode); + uint32_t lpf_bandwidth = auto_bandwidth(radio); - switch (opmode) { - case TRANSCEIVER_MODE_TX: - case TRANSCEIVER_MODE_SS: - if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != - lpf_bandwidth) { - max2831_set_lpf_bandwidth(&max283x, lpf_bandwidth); - radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = - lpf_bandwidth; - new_bw = true; - } - break; - default: - if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] != - lpf_bandwidth) { - max2831_set_lpf_bandwidth(&max283x, lpf_bandwidth); - radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] = - lpf_bandwidth; - new_bw = true; - } - bool narrow_lpf_enable = false; - bool applied_narrow_lpf_enable = - radio->config[RADIO_BANK_APPLIED][RADIO_RX_NARROW_LPF]; - if (lpf_bandwidth <= 1750000) { - narrow_lpf_enable = true; - } - if (applied_narrow_lpf_enable != narrow_lpf_enable) { - narrowband_filter_set(narrow_lpf_enable); - radio->config[RADIO_BANK_APPLIED][RADIO_RX_NARROW_LPF] = - narrow_lpf_enable; - new_bw = true; - } - /* Always set HPF bandwidth to 30 kHz for now. */ - const max2831_rx_hpf_freq_t hpf_bandwidth = MAX2831_RX_HPF_30_KHZ; - if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] != - hpf_bandwidth) { - max2831_set_rx_hpf_frequency(&max283x, hpf_bandwidth); - radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] = - hpf_bandwidth; - new_bw = true; - } + if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != lpf_bandwidth) { + max2831_set_lpf_bandwidth(&max283x, MAX2831_MODE_TX, lpf_bandwidth); + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = lpf_bandwidth; + new_bw = true; + } + if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] != lpf_bandwidth) { + max2831_set_lpf_bandwidth(&max283x, MAX2831_MODE_RX, lpf_bandwidth); + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] = lpf_bandwidth; + new_bw = true; + } + bool narrow_lpf_enable = false; + bool applied_narrow_lpf_enable = + radio->config[RADIO_BANK_APPLIED][RADIO_RX_NARROW_LPF]; + if (lpf_bandwidth <= 1750000) { + narrow_lpf_enable = true; + } + if (applied_narrow_lpf_enable != narrow_lpf_enable) { + narrowband_filter_set(narrow_lpf_enable); + radio->config[RADIO_BANK_APPLIED][RADIO_RX_NARROW_LPF] = + narrow_lpf_enable; + new_bw = true; + } + /* Always set HPF bandwidth to 30 kHz for now. */ + const max2831_rx_hpf_freq_t hpf_bandwidth = MAX2831_RX_HPF_30_KHZ; + if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] != hpf_bandwidth) { + max2831_set_rx_hpf_frequency(&max283x, hpf_bandwidth); + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] = hpf_bandwidth; + new_bw = true; } #else uint64_t lpf_bandwidth; @@ -494,7 +473,7 @@ static bool radio_update_bandwidth(radio_t* const radio, uint64_t* bank) lpf_bandwidth = radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF]; } if (lpf_bandwidth == RADIO_UNSET) { - lpf_bandwidth = auto_bandwidth(radio, opmode); + lpf_bandwidth = auto_bandwidth(radio); } if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != lpf_bandwidth) { From bb670f9af70a518164b2faa4633e8b7db6c84c68 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sun, 1 Mar 2026 09:59:19 -0500 Subject: [PATCH 037/238] Add 40.24 fixed-point type --- firmware/common/fixed_point.h | 34 +++++++++++++++++ firmware/common/radio.c | 46 ++++++++++++----------- firmware/hackrf_usb/usb_api_sweep.c | 5 ++- firmware/hackrf_usb/usb_api_transceiver.c | 11 ++++-- 4 files changed, 69 insertions(+), 27 deletions(-) create mode 100644 firmware/common/fixed_point.h diff --git a/firmware/common/fixed_point.h b/firmware/common/fixed_point.h new file mode 100644 index 00000000..9485aaea --- /dev/null +++ b/firmware/common/fixed_point.h @@ -0,0 +1,34 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __FIXED_POINT_H__ +#define __FIXED_POINT_H__ + +/* 40.24 fixed-point */ +typedef uint64_t fp_40_24_t; + +/* one million in 40.24 fixed-point */ +#define FP_ONE_MHZ ((1000ULL * 1000ULL) << 24) + +/* one in 40.24 fixed-point */ +#define FP_ONE_HZ (1 << 24) + +#endif /*__FIXED_POINT_H__*/ diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 90d3f030..3b823872 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -27,6 +27,7 @@ #include "fpga.h" #include "platform_detect.h" #include "radio.h" +#include "fixed_point.h" #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define MAX(x, y) ((x) > (y) ? (x) : (y)) @@ -121,10 +122,10 @@ static bool radio_update_direction(radio_t* const radio, uint64_t* bank) /* * Convert sample rate in units of 1/(2**24) Hz to fraction. */ -static inline uint64_t frac_sample_rate(const uint64_t rate) +static inline uint64_t frac_sample_rate(const fp_40_24_t rate) { uint64_t num = rate; - uint64_t denom = 1 << 24; + uint64_t denom = FP_ONE_HZ; while ((num & 1) == 0) { num >>= 1; denom >>= 1; @@ -148,9 +149,9 @@ static inline uint32_t denominator(const uint64_t frac) /* * Convert fractional sample rate to units of 1/(2**24) Hz. */ -static inline uint64_t round_sample_rate(const uint64_t frac) +static inline fp_40_24_t round_sample_rate(const uint64_t frac) { - uint64_t num = (uint64_t) numerator(frac) << 24; + uint64_t num = (uint64_t) numerator(frac) * FP_ONE_HZ; uint32_t denom = denominator(frac); if (denom == 0) { denom = 1; @@ -182,15 +183,16 @@ static inline uint8_t compute_resample_log( return n; } -#define MIN_MCU_RATE (200000ULL << 24) -#define MAX_MCU_RATE (21800000ULL << 24) -#define DEFAULT_MCU_RATE (10000000ULL << 24) +#define MIN_MCU_RATE (200000ULL * FP_ONE_HZ) +#define MAX_MCU_RATE (21800000ULL * FP_ONE_HZ) +#define DEFAULT_MCU_RATE (10000000ULL * FP_ONE_HZ) -static uint64_t applied_afe_rate = RADIO_UNSET; +static fp_40_24_t applied_afe_rate = RADIO_UNSET; static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) { - uint64_t rate, frac, previous_n; + fp_40_24_t rate; + uint64_t frac, previous_n; uint8_t n = 0; bool new_rate = false; @@ -240,7 +242,7 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) * Resampling is enabled only in RX mode to work around a * spectrum inversion bug with TX interpolation. */ - n = compute_resample_log(rate >> 24, requested_n); + n = compute_resample_log(rate / FP_ONE_HZ, requested_n); previous_n = radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX]; if (n != previous_n) { #ifdef PRALINE @@ -251,8 +253,8 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) } } - uint64_t afe_rate = rate << n; - uint64_t previous_afe_rate = RADIO_UNSET; + fp_40_24_t afe_rate = rate << n; + fp_40_24_t previous_afe_rate = RADIO_UNSET; if (previous_n != RADIO_UNSET) { previous_afe_rate = radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] << previous_n; @@ -269,9 +271,9 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) return new_rate; } -#define DEFAULT_RF (2450000000ULL << 24) +#define DEFAULT_RF (2450ULL * FP_ONE_MHZ) -static uint64_t applied_offset = RADIO_UNSET; +static fp_40_24_t applied_offset = RADIO_UNSET; #ifdef PRALINE static const tune_config_t* select_tune_config(uint64_t opmode) @@ -312,8 +314,8 @@ static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) radio->config[RADIO_BANK_APPLIED][RADIO_IMAGE_REJECT]); if (new_if || new_lo || new_img_reject) { set_freq_explicit( - requested_if >> 24, - requested_lo >> 24, + requested_if / FP_ONE_HZ, + requested_lo / FP_ONE_HZ, requested_img_reject); radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF] = requested_if; @@ -348,7 +350,7 @@ static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) bool new_rf = (radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF] != requested_rf); - uint64_t requested_rf_hz = requested_rf >> 24; + uint64_t requested_rf_hz = requested_rf / FP_ONE_HZ; #ifdef PRALINE if (applied_afe_rate == RADIO_UNSET) { return false; @@ -376,10 +378,10 @@ static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION] = tune_config->shift << 6; } - uint64_t offset = applied_afe_rate / 4; + fp_40_24_t offset = applied_afe_rate / 4; bool new_offset = (applied_offset != offset); if (new_rotation || new_offset || new_config || new_rf) { - tuning_set_frequency(tune_config, requested_rf_hz, offset >> 24); + tuning_set_frequency(tune_config, requested_rf_hz, offset / FP_ONE_HZ); applied_offset = offset; } #else @@ -398,16 +400,16 @@ static uint32_t auto_bandwidth(radio_t* const radio) { uint64_t rotation = radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION]; - uint32_t sample_rate_hz = DEFAULT_MCU_RATE >> 24; + uint32_t sample_rate_hz = DEFAULT_MCU_RATE / FP_ONE_HZ; if (radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] != RADIO_UNSET) { sample_rate_hz = - radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] >> 24; + radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] / FP_ONE_HZ; } uint32_t offset_hz = 0; if ((rotation != 0) && (rotation != RADIO_UNSET) && (applied_offset != RADIO_UNSET)) { - offset_hz = applied_offset >> 24; + offset_hz = applied_offset / FP_ONE_HZ; } const uint32_t bb_bandwidth = (sample_rate_hz * 3) / 4; diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index 84a813a1..a8e7934c 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -30,6 +30,7 @@ #include "tuning.h" #include "usb_endpoint.h" #include "streaming.h" +#include "fixed_point.h" #include @@ -98,7 +99,7 @@ usb_request_status_t usb_vendor_request_init_sweep( &radio, RADIO_BANK_ACTIVE, RADIO_FREQUENCY_RF, - (sweep_freq + offset) << 24); + (sweep_freq + offset) * FP_ONE_HZ); usb_transfer_schedule_ack(endpoint->in); nvic_enable_irq(NVIC_USB0_IRQ); radio_update(&radio); @@ -228,7 +229,7 @@ void sweep_mode(uint32_t seq) &radio, RADIO_BANK_ACTIVE, RADIO_FREQUENCY_RF, - (sweep_freq + offset) << 24); + (sweep_freq + offset) * FP_ONE_HZ); nvic_enable_irq(NVIC_USB0_IRQ); blocks_queued = 0; } diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 6a72a1f4..88e61329 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -40,6 +40,7 @@ #include "usb.h" #include "usb_queue.h" #include "platform_detect.h" +#include "fixed_point.h" #include #include @@ -108,7 +109,11 @@ usb_request_status_t usb_vendor_request_set_freq( } else if (stage == USB_TRANSFER_STAGE_DATA) { const uint64_t freq = set_freq_params.freq_mhz * 1000000ULL + set_freq_params.freq_hz; - radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_FREQUENCY_RF, freq << 24); + radio_reg_write( + &radio, + RADIO_BANK_ACTIVE, + RADIO_FREQUENCY_RF, + freq * FP_ONE_HZ); radio_reg_write( &radio, RADIO_BANK_ACTIVE, @@ -145,12 +150,12 @@ usb_request_status_t usb_vendor_request_set_freq_explicit( &radio, RADIO_BANK_ACTIVE, RADIO_FREQUENCY_IF, - explicit_params.if_freq_hz << 24); + explicit_params.if_freq_hz * FP_ONE_HZ); radio_reg_write( &radio, RADIO_BANK_ACTIVE, RADIO_FREQUENCY_LO, - explicit_params.lo_freq_hz << 24); + explicit_params.lo_freq_hz * FP_ONE_HZ); radio_reg_write( &radio, RADIO_BANK_ACTIVE, From 880bc57ed1d68772b395a6816803ceba391e5be4 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sat, 7 Mar 2026 23:51:35 +0000 Subject: [PATCH 038/238] Add nostring attribute to buffer used for UI frequency display. --- firmware/common/ui_portapack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/ui_portapack.c b/firmware/common/ui_portapack.c index 3e8d3013..c6bf3039 100644 --- a/firmware/common/ui_portapack.c +++ b/firmware/common/ui_portapack.c @@ -511,7 +511,7 @@ static void portapack_ui_deinit(void) static void portapack_ui_set_frequency(uint64_t frequency) { - static char last[10] = " "; + __attribute__((nonstring)) static char last[10] = " "; ui_point_t point = {240 - 20, 16}; From 67b5617373ecfb9e5d716b6ef2d6f311799b570c Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sun, 1 Mar 2026 10:02:51 -0500 Subject: [PATCH 039/238] Configure sample rate more precisely --- firmware/common/fpga_selftest.c | 6 +- firmware/common/hackrf_core.c | 274 +++++++--------------- firmware/common/hackrf_core.h | 4 +- firmware/common/radio.c | 109 +++------ firmware/hackrf_usb/usb_api_transceiver.c | 18 +- 5 files changed, 145 insertions(+), 266 deletions(-) diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index f3bb01c1..1df90daf 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -190,7 +190,7 @@ bool fpga_if_xcvr_selftest(void) max2831_set_frequency(&max283x, 2500000000); // Capture 1: 4 Msps, tone at 0.5 MHz, narrowband filter OFF - sample_rate_frac_set(4000000, 1); + sample_rate_set(4ULL * FP_ONE_MHZ, true); delay_us_at_mhz(1000, 204); if (rx_samples(num_samples, 2000000) == -1) { timeout = true; @@ -213,7 +213,7 @@ bool fpga_if_xcvr_selftest(void) // Capture 3: 20 Msps, tone at 5 MHz, narrowband filter OFF fpga_set_tx_nco_pstep(&fpga, 255); - sample_rate_frac_set(20000000, 1); + sample_rate_set(20ULL * FP_ONE_MHZ, true); narrowband_filter_set(0); delay_us_at_mhz(1000, 204); if (rx_samples(num_samples, 2000000) == -1) { @@ -236,7 +236,7 @@ bool fpga_if_xcvr_selftest(void) &selftest.xcvr_measurements[3]); // Restore default settings. - sample_rate_set(10000000); + sample_rate_set(10ULL * FP_ONE_MHZ, true); rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_OFF); narrowband_filter_set(0); fpga_init(&fpga); diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 5509b9b1..511e3b04 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -409,53 +409,26 @@ jtag_t jtag_cpld = { .gpio = &jtag_gpio_cpld, }; -/* GCD algo from wikipedia */ -/* http://en.wikipedia.org/wiki/Greatest_common_divisor */ -static uint32_t gcd(uint32_t u, uint32_t v) +/* + * Configure clock generator to produce sample clock in units of 1/(2**24) Hz. + * Can be called with program=false for a dry run that returns the resultant + * frequency without actually configuring the clock generator. + * + * The clock generator output frequency is: + * + * fs = 128 * vco / (512 + p1 + p2/p3)) + * + * where p1, p2, and p3 are register values. + * + * For more information see: + * https://www.pa3fwm.nl/technotes/tn42a-si5351-programming.html + */ +fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program) { - int s; - - if (!u || !v) { - return u | v; - } - - for (s = 0; !((u | v) & 1); s++) { - u >>= 1; - v >>= 1; - } - - while (!(u & 1)) { - u >>= 1; - } - - do { - while (!(v & 1)) { - v >>= 1; - } - - if (u > v) { - uint32_t t; - t = v; - v = u; - u = t; - } - - v = v - u; - } while (v); - - return u << s; -} - -bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom) -{ - const uint64_t VCO_FREQ = 800 * 1000 * 1000; /* 800 MHz */ - uint32_t MSx_P1, MSx_P2, MSx_P3; - uint32_t a, b, c; - uint32_t rem; - - /* Round to the nearest Hz for display. */ - uint32_t rate_hz = (rate_num + (rate_denom >> 1)) / rate_denom; - hackrf_ui()->set_sample_rate(rate_hz); + const fp_40_24_t vco = 800 * FP_ONE_MHZ; + uint64_t p1, p2, p3; + uint64_t n, d, q; + fp_40_24_t remainder, resultant_rate; /* * First double the sample rate so that we can produce a clock at twice @@ -463,36 +436,72 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom) * and it is divided by two in an output divider to produce the actual * AFE clock. */ - rate_num *= 2; + fp_40_24_t rate = sample_rate * 2; - /* Find best config */ - a = (VCO_FREQ * rate_denom) / rate_num; + p1 = ((128 * vco) / rate) - 512; + if (vco % rate) { + /* + * Compute numerator (p2) for denominator (p3) matching + * fixed-point type. + */ + n = (128 * vco) - (rate * (p1 + 512)); + d = rate / FP_ONE_HZ; + n += (d / 2); + p2 = n / d; + p3 = 1 << 24; - rem = (VCO_FREQ * rate_denom) - (a * rate_num); + /* Reduce fraction. p3 is 1<<24, so gcd(p2, p3) is a power of 2 */ + unsigned int shift = p2 ? __builtin_ctz(p2) : 24; + p2 >>= shift; + p3 >>= shift; - if (!rem) { - /* Integer mode */ - b = 0; - c = 1; - } else { - /* Fractional */ - uint32_t g = gcd(rem, rate_num); - rem /= g; - rate_num /= g; - - if (rate_num < (1 << 20)) { - /* Perfect match */ - b = rem; - c = rate_num; - } else { - /* Approximate */ - c = (1 << 20) - 1; - b = ((uint64_t) c * (uint64_t) rem) / rate_num; - - g = gcd(b, c); - b /= g; - c /= g; + /* Convert fraction to valid denominator. */ + const uint64_t p3_max = 0xfffff; + if (p3 > p3_max) { + p2 *= p3_max; + p2 += (p3 / 2); + p2 /= p3; + p3 = p3_max; } + + /* Roll over to next p1 to enable integer mode. */ + if (p2 >= p3) { + p1++; + p2 = 0; + } + } else { + p2 = 0; + } + + /* Maximum: (128 * 2048) - 512 */ + if (p1 > 0x3fe00) { + p1 = 0x3fe00; + p2 = 0; + } + + if (p2 == 0) { + /* Use unity denominator for integer mode. */ + p3 = 1; + n = (vco * 128); + d = (p1 + 512); + n += (d / 2); + resultant_rate = n / d; + } else { + const uint64_t vco_hz = vco / FP_ONE_HZ; + n = p3 * vco_hz * 128; + d = p3 * (p1 + 512) + p2; + const uint64_t rate_hz = n / d; + remainder = (n - (d * rate_hz)) * FP_ONE_HZ; + remainder += (d / 2); + q = remainder / d; + resultant_rate = (rate_hz * FP_ONE_HZ) + q; + } + + /* Return MCU sample rate, not AFE clock rate. */ + resultant_rate = (resultant_rate + 1) / 2; + + if (!program) { + return resultant_rate; } bool streaming = sgpio_cpld_stream_is_enabled(&sgpio_config); @@ -501,103 +510,13 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom) sgpio_cpld_stream_disable(&sgpio_config); } - /* Can we enable integer mode ? */ - if (a & 0x1 || b) { + /* Integer mode can be enabled if p1 is even and p2 is zero. */ + if (p1 & 0x1 || p2) { si5351c_set_int_mode(&clock_gen, 0, 0); } else { si5351c_set_int_mode(&clock_gen, 0, 1); } - /* Final MS values */ - MSx_P1 = 128 * a + (128 * b / c) - 512; - MSx_P2 = (128 * b) % c; - MSx_P3 = c; - -#ifndef PRALINE - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - /* - * On HackRF One r9 all sample clocks are externally derived - * from MS1/CLK1 operating at twice the sample rate. - */ - si5351c_configure_multisynth(&clock_gen, 1, MSx_P1, MSx_P2, MSx_P3, 0); - } else { - /* - * On other platforms the clock generator produces three - * different sample clocks, all derived from multisynth 0. - */ - /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ - si5351c_configure_multisynth(&clock_gen, 0, MSx_P1, MSx_P2, MSx_P3, 1); - - /* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ - si5351c_configure_multisynth(&clock_gen, 1, 0, 0, 0, 0); //p1 doesn't matter - - /* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */ - si5351c_configure_multisynth(&clock_gen, 2, 0, 0, 0, 0); //p1 doesn't matter - } -#else - /* MS0/CLK0 is the source for the MAX5864/FPGA (AFE_CLK). */ - si5351c_configure_multisynth(&clock_gen, 0, MSx_P1, MSx_P2, MSx_P3, 1); -#endif - - if (streaming) { - sgpio_cpld_stream_enable(&sgpio_config); - } - - return true; -} - -bool sample_rate_set(const uint32_t sample_rate_hz) -{ - uint32_t p1 = 4608; - uint32_t p2 = 0; - uint32_t p3 = 0; - - switch (sample_rate_hz) { - case 8000000: - p1 = SI_INTDIV(50); // 800MHz / 50 = 16 MHz (SGPIO), 8 MHz (codec) - break; - - case 9216000: - // 43.40277777777778: a = 43; b = 29; c = 72 - p1 = 5043; - p2 = 40; - p3 = 72; - break; - - case 10000000: - p1 = SI_INTDIV(40); // 800MHz / 40 = 20 MHz (SGPIO), 10 MHz (codec) - break; - - case 12288000: - // 32.552083333333336: a = 32; b = 159; c = 288 - p1 = 3654; - p2 = 192; - p3 = 288; - break; - - case 12500000: - p1 = SI_INTDIV(32); // 800MHz / 32 = 25 MHz (SGPIO), 12.5 MHz (codec) - break; - - case 16000000: - p1 = SI_INTDIV(25); // 800MHz / 25 = 32 MHz (SGPIO), 16 MHz (codec) - break; - - case 18432000: - // 21.70138888889: a = 21; b = 101; c = 144 - p1 = 2265; - p2 = 112; - p3 = 144; - break; - - case 20000000: - p1 = SI_INTDIV(20); // 800MHz / 20 = 40 MHz (SGPIO), 20 MHz (codec) - break; - - default: - return false; - } - #ifndef PRALINE if (detected_platform() == BOARD_ID_HACKRF1_R9) { /* @@ -614,32 +533,21 @@ bool sample_rate_set(const uint32_t sample_rate_hz) si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); /* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ - si5351c_configure_multisynth( - &clock_gen, - 1, - p1, - 0, - 1, - 0); //p1 doesn't matter + si5351c_configure_multisynth(&clock_gen, 1, 0, 0, 0, 0); //p1 doesn't matter /* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */ - si5351c_configure_multisynth( - &clock_gen, - 2, - p1, - 0, - 1, - 0); //p1 doesn't matter + si5351c_configure_multisynth(&clock_gen, 2, 0, 0, 0, 0); //p1 doesn't matter } #else /* MS0/CLK0 is the source for the MAX5864/FPGA (AFE_CLK). */ si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); - - /* MS0/CLK1 is the source for SCT_CLK (CODEC_X2_CLK). */ - si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 0); #endif - return true; + if (streaming) { + sgpio_cpld_stream_enable(&sgpio_config); + } + + return resultant_rate; } /* @@ -926,7 +834,7 @@ void clock_gen_init(void) /* MS7/CLK7 is unused. */ /* Set to 10 MHz, the common rate between Jawbreaker and HackRF One. */ - sample_rate_set(10000000); + sample_rate_set(10ULL * FP_ONE_MHZ, true); si5351c_set_clock_source(&clock_gen, PLL_SOURCE_XTAL); // soft reset diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 6bc8e909..d3a7b0d6 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -45,6 +45,7 @@ extern "C" { #include "cpld_jtag.h" #include "ice40_spi.h" #include "fpga.h" +#include "fixed_point.h" /* * SCU PinMux @@ -435,8 +436,7 @@ void enable_1v8_power(void); void disable_1v8_power(void); #endif -bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom); -bool sample_rate_set(const uint32_t sampling_rate_hz); +fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program); clock_source_t activate_best_clock_source(void); diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 3b823872..ef16102f 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -28,6 +28,7 @@ #include "platform_detect.h" #include "radio.h" #include "fixed_point.h" +#include "hackrf_ui.h" #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define MAX(x, y) ((x) > (y) ? (x) : (y)) @@ -119,46 +120,6 @@ static bool radio_update_direction(radio_t* const radio, uint64_t* bank) return true; } -/* - * Convert sample rate in units of 1/(2**24) Hz to fraction. - */ -static inline uint64_t frac_sample_rate(const fp_40_24_t rate) -{ - uint64_t num = rate; - uint64_t denom = FP_ONE_HZ; - while ((num & 1) == 0) { - num >>= 1; - denom >>= 1; - if (denom == 1) { - break; - } - } - return (denom << 32) | (num & 0xffffffff); -} - -static inline uint32_t numerator(const uint64_t frac) -{ - return frac & 0xffffffff; -} - -static inline uint32_t denominator(const uint64_t frac) -{ - return frac >> 32; -} - -/* - * Convert fractional sample rate to units of 1/(2**24) Hz. - */ -static inline fp_40_24_t round_sample_rate(const uint64_t frac) -{ - uint64_t num = (uint64_t) numerator(frac) * FP_ONE_HZ; - uint32_t denom = denominator(frac); - if (denom == 0) { - denom = 1; - } - return (num + (denom >> 1)) / denom; -} - #define MAX_AFE_RATE_HZ (40000000UL) static inline uint8_t compute_resample_log( @@ -191,50 +152,47 @@ static fp_40_24_t applied_afe_rate = RADIO_UNSET; static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) { - fp_40_24_t rate; - uint64_t frac, previous_n; + fp_40_24_t rate, afe_rate; + uint64_t previous_n; uint8_t n = 0; + bool new_afe_rate = false; bool new_rate = false; + bool new_n = false; - const uint64_t requested_frac = bank[RADIO_SAMPLE_RATE_FRAC]; const uint64_t requested_rate = bank[RADIO_SAMPLE_RATE]; const uint64_t requested_n = bank[RADIO_RESAMPLE_RX]; if (requested_rate != RADIO_UNSET) { rate = MIN(requested_rate, MAX_MCU_RATE); rate = MAX(rate, MIN_MCU_RATE); - frac = frac_sample_rate(rate); - } else if (requested_frac != RADIO_UNSET) { - frac = requested_frac; - if (round_sample_rate(frac) > MAX_MCU_RATE) { - frac = frac_sample_rate(MAX_MCU_RATE); - } - if (round_sample_rate(frac) < MIN_MCU_RATE) { - frac = frac_sample_rate(MIN_MCU_RATE); - } - rate = round_sample_rate(frac); } else { rate = radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE]; if (rate == RADIO_UNSET) { rate = DEFAULT_MCU_RATE; } - frac = RADIO_UNSET; } + const uint64_t previous_opmode = radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]; uint64_t opmode = bank[RADIO_OPMODE]; if (opmode == RADIO_UNSET) { - opmode = radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]; + opmode = previous_opmode; + } + switch (previous_opmode) { + case TRANSCEIVER_MODE_TX: + case TRANSCEIVER_MODE_SS: + previous_n = radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX]; + break; + default: + previous_n = radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX]; } switch (opmode) { case TRANSCEIVER_MODE_TX: case TRANSCEIVER_MODE_SS: - previous_n = radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX]; - if (n != previous_n) { + if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX]) { #ifdef PRALINE fpga_set_tx_interpolation_ratio(&fpga, n); #endif radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX] = n; - new_rate = true; } break; default: @@ -243,32 +201,33 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) * spectrum inversion bug with TX interpolation. */ n = compute_resample_log(rate / FP_ONE_HZ, requested_n); - previous_n = radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX]; - if (n != previous_n) { + if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX]) { #ifdef PRALINE fpga_set_rx_decimation_ratio(&fpga, n); #endif radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX] = n; - new_rate = true; } } + new_n = (n != previous_n); - fp_40_24_t afe_rate = rate << n; - fp_40_24_t previous_afe_rate = RADIO_UNSET; - if (previous_n != RADIO_UNSET) { - previous_afe_rate = radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] - << previous_n; - } - - if (afe_rate != previous_afe_rate) { - sample_rate_frac_set(numerator(frac) << n, denominator(frac)); + afe_rate = rate << n; + afe_rate = sample_rate_set(afe_rate, false); + new_afe_rate = (afe_rate != applied_afe_rate); + if (new_afe_rate) { + afe_rate = sample_rate_set(afe_rate, true); applied_afe_rate = afe_rate; - radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE_FRAC] = frac; + } + rate = afe_rate >> n; + new_rate = (rate != radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE]); + if (new_rate) { radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] = rate; - new_rate = true; + + /* Round to the nearest Hz for display. */ + const uint32_t rate_hz = (rate + (FP_ONE_HZ >> 1)) / FP_ONE_HZ; + hackrf_ui()->set_sample_rate(rate_hz); } - return new_rate; + return (new_afe_rate || new_rate || new_n); } #define DEFAULT_RF (2450ULL * FP_ONE_MHZ) @@ -691,8 +650,8 @@ bool radio_update(radio_t* const radio) bool dc = false; if ((dirty & - ((1 << RADIO_SAMPLE_RATE) | (1 << RADIO_SAMPLE_RATE_FRAC) | - (1 << RADIO_RESAMPLE_TX) | (1 << RADIO_RESAMPLE_RX))) || + ((1 << RADIO_SAMPLE_RATE) | (1 << RADIO_RESAMPLE_TX) | + (1 << RADIO_RESAMPLE_RX))) || ((detected_platform() == BOARD_ID_PRALINE) && (dirty & (1 << RADIO_OPMODE)))) { rate = radio_update_sample_rate(radio, &tmp_bank[0]); diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 88e61329..964ff22c 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -166,6 +166,18 @@ usb_request_status_t usb_vendor_request_set_freq_explicit( return USB_REQUEST_STATUS_OK; } +/* + * Convert fractional sample rate to units of 1/(2**24) Hz. + */ +static inline fp_40_24_t round_sample_rate(uint64_t num, uint32_t denom) +{ + num *= FP_ONE_HZ; + if (denom == 0) { + denom = 1; + } + return (num + (denom >> 1)) / denom; +} + usb_request_status_t usb_vendor_request_set_sample_rate_frac( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) @@ -179,9 +191,9 @@ usb_request_status_t usb_vendor_request_set_sample_rate_frac( NULL); } else if (stage == USB_TRANSFER_STAGE_DATA) { uint32_t numerator = set_sample_r_params.freq_hz; - uint64_t denominator = set_sample_r_params.divider; - uint64_t value = (denominator << 32) | numerator; - radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_SAMPLE_RATE_FRAC, value); + uint32_t denominator = set_sample_r_params.divider; + uint64_t value = round_sample_rate(numerator, denominator); + radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_SAMPLE_RATE, value); usb_transfer_schedule_ack(endpoint->in); } return USB_REQUEST_STATUS_OK; From 2e1fbd5960b4a90cd966638aa17f1657ed8418f1 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sat, 28 Feb 2026 19:21:30 -0500 Subject: [PATCH 040/238] Remove fractional sample rate radio register --- firmware/common/radio.h | 40 ++++++++++++---------------- host/hackrf-tools/src/hackrf_debug.c | 2 +- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/firmware/common/radio.h b/firmware/common/radio.h index 5922977f..59f9592a 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -106,88 +106,82 @@ typedef enum { * Sample rate (as seen by MCU/host) in 1/(2**24) Hz. */ RADIO_SAMPLE_RATE = 6, - /** - * Sample rate (as seen by MCU/host) in fractional format. The - * numerator is stored in the low 32 bits. The denominator is stored in - * the high 32 bits. - */ - RADIO_SAMPLE_RATE_FRAC = 7, /** * Base two logarithm of TX decimation ratio (0 means a ratio of 1). */ - RADIO_RESAMPLE_TX = 8, + RADIO_RESAMPLE_TX = 7, /** * Base two logarithm of RX decimation ratio (0 means a ratio of 1). */ - RADIO_RESAMPLE_RX = 9, + RADIO_RESAMPLE_RX = 8, /** * TX RF amplifier enable of type bool. */ - RADIO_GAIN_TX_RF = 10, + RADIO_GAIN_TX_RF = 9, /** * TX IF amplifier gain in dB. */ - RADIO_GAIN_TX_IF = 11, + RADIO_GAIN_TX_IF = 10, /** * RX RF amplifier enable of type bool. */ - RADIO_GAIN_RX_RF = 12, + RADIO_GAIN_RX_RF = 11, /** * RX IF amplifier gain in dB. */ - RADIO_GAIN_RX_IF = 13, + RADIO_GAIN_RX_IF = 12, /** * RX baseband amplifier gain in dB. */ - RADIO_GAIN_RX_BB = 14, + RADIO_GAIN_RX_BB = 13, /** * TX baseband bandwidth in Hz. This controls analog baseband filter * settings but is specified as the desired bandwidth centered in * digital baseband as seen by the MCU/host. */ - RADIO_BB_BANDWIDTH_TX = 15, + RADIO_BB_BANDWIDTH_TX = 14, /** * RX baseband bandwidth in Hz. This controls analog baseband filter * settings but is specified as the desired bandwidth centered in * digital baseband as seen by the MCU/host. */ - RADIO_BB_BANDWIDTH_RX = 16, + RADIO_BB_BANDWIDTH_RX = 15, /** * Quadrature transceiver TX baseband LPF bandwidth in Hz. If no * rotation is performed, this is set to match RADIO_BB_BANDWIDTH. * Currently unused. */ - RADIO_XCVR_TX_LPF = 17, + RADIO_XCVR_TX_LPF = 16, /** * Quadrature transceiver RX baseband LPF bandwidth in Hz. If no * rotation is performed, this is set to match RADIO_BB_BANDWIDTH. * Currently unused. */ - RADIO_XCVR_RX_LPF = 18, + RADIO_XCVR_RX_LPF = 17, /** * Quadrature transceiver RX baseband HPF bandwidth in Hz. Currently * unused. */ - RADIO_XCVR_RX_HPF = 19, + RADIO_XCVR_RX_HPF = 18, /** * Narrowband RX analog baseband LPF enable of type bool. Currently unused. */ - RADIO_RX_NARROW_LPF = 20, + RADIO_RX_NARROW_LPF = 19, /** * RF port bias tee enable of type bool. */ - RADIO_BIAS_TEE = 21, + RADIO_BIAS_TEE = 20, /** * Trigger input enable of type bool. */ - RADIO_TRIGGER = 22, + RADIO_TRIGGER = 21, /** * DC block enable of type bool. */ - RADIO_DC_BLOCK = 23, + RADIO_DC_BLOCK = 22, } radio_register_t; -#define RADIO_NUM_REGS (24) +#define RADIO_NUM_REGS (23) #define RADIO_UNSET (0xffffffffffffffff) /** diff --git a/host/hackrf-tools/src/hackrf_debug.c b/host/hackrf-tools/src/hackrf_debug.c index 5f8785b5..52ede9cb 100644 --- a/host/hackrf-tools/src/hackrf_debug.c +++ b/host/hackrf-tools/src/hackrf_debug.c @@ -501,7 +501,7 @@ int radio_read_register( return result; } -#define RADIO_NUM_REGS (24) +#define RADIO_NUM_REGS (23) int radio_read_registers(hackrf_device* device, const uint8_t bank) { From 25bd7dad1bf2196acb132e183f64aecc57a10142 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Sat, 28 Feb 2026 19:21:52 -0500 Subject: [PATCH 041/238] Use external callback to set radio sample rate --- firmware/common/hackrf_core.c | 4 +++- firmware/common/radio.c | 25 +++++++++++++++---------- firmware/common/radio.h | 12 ++++++++++++ 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 511e3b04..784eae55 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -351,7 +351,9 @@ fpga_driver_t fpga = { }; #endif -radio_t radio; +radio_t radio = { + .sample_rate_cb = sample_rate_set, +}; rf_path_t rf_path = { .switchctrl = 0, diff --git a/firmware/common/radio.c b/firmware/common/radio.c index ef16102f..bae631f7 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -210,21 +210,26 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) } new_n = (n != previous_n); - afe_rate = rate << n; - afe_rate = sample_rate_set(afe_rate, false); - new_afe_rate = (afe_rate != applied_afe_rate); - if (new_afe_rate) { - afe_rate = sample_rate_set(afe_rate, true); - applied_afe_rate = afe_rate; + if (radio->sample_rate_cb) { + afe_rate = rate << n; + afe_rate = radio->sample_rate_cb(afe_rate, false); + new_afe_rate = (afe_rate != applied_afe_rate); + if (new_afe_rate) { + afe_rate = radio->sample_rate_cb(afe_rate, true); + applied_afe_rate = afe_rate; + } + } else { + return false; } rate = afe_rate >> n; new_rate = (rate != radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE]); if (new_rate) { radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] = rate; - - /* Round to the nearest Hz for display. */ - const uint32_t rate_hz = (rate + (FP_ONE_HZ >> 1)) / FP_ONE_HZ; - hackrf_ui()->set_sample_rate(rate_hz); + if (rate != RADIO_UNSET) { + /* Round to the nearest Hz for display. */ + const uint32_t rate_hz = (rate + (FP_ONE_HZ >> 1)) / FP_ONE_HZ; + hackrf_ui()->set_sample_rate(rate_hz); + } } return (new_afe_rate || new_rate || new_n); diff --git a/firmware/common/radio.h b/firmware/common/radio.h index 59f9592a..13cd2626 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -27,6 +27,8 @@ #include #include +#include "fixed_point.h" + typedef enum { RADIO_OK = 1, RADIO_ERR_INVALID_PARAM = -2, @@ -205,10 +207,20 @@ typedef enum { #define RADIO_NUM_BANKS (5) +/** + * A callback function must be provided that configures clock generation to + * produce the requested sample clock frequency. The function must return the + * configured sample rate. A boolean program argument may be set to false to + * execute a dry run, returning the sample rate without configuring clock + * generation. + */ +typedef fp_40_24_t (*sample_rate_fn)(const fp_40_24_t sample_rate, const bool program); + typedef struct radio_t { radio_config_mode_t config_mode; uint64_t config[RADIO_NUM_BANKS][RADIO_NUM_REGS]; volatile uint32_t regs_dirty; + sample_rate_fn sample_rate_cb; } radio_t; void radio_init(radio_t* const radio); From bd87a5a1b4da09381c377901065fbd7ab386bbc5 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Tue, 3 Mar 2026 13:40:25 +0200 Subject: [PATCH 042/238] firmware: add MAX2831 support to max283x.c --- firmware/common/fpga_selftest.c | 6 +- firmware/common/hackrf_core.c | 19 +- firmware/common/hackrf_core.h | 9 +- firmware/common/max2831.h | 2 +- firmware/common/max283x.c | 251 +++++++++++++++++++++++-- firmware/common/max283x.h | 33 ++++ firmware/common/radio.c | 34 +--- firmware/common/rf_path.c | 22 +-- firmware/common/tuning.c | 22 +-- firmware/hackrf-common.cmake | 7 +- firmware/hackrf_usb/usb_api_register.c | 39 +--- 11 files changed, 299 insertions(+), 145 deletions(-) diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index 1df90daf..cd09b91f 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -185,9 +185,9 @@ bool fpga_if_xcvr_selftest(void) fpga_set_tx_nco_pstep(&fpga, 64); // NCO phase increment fpga_set_tx_nco_enable(&fpga, true); // TX enable rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_RX_CALIBRATION); - max2831_set_lna_gain(&max283x, 16); - max2831_set_vga_gain(&max283x, 36); - max2831_set_frequency(&max283x, 2500000000); + max283x_set_lna_gain(&max283x, 16); + max283x_set_vga_gain(&max283x, 36); + max283x_set_frequency(&max283x, 2500000000); // Capture 1: 4 Msps, tone at 0.5 MHz, narrowband filter OFF sample_rate_set(4ULL * FP_ONE_MHZ, true); diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 383e5540..d4ee8433 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -27,8 +27,6 @@ #include "sgpio.h" #include "si5351c.h" #include "spi_ssp.h" -#include "max2831.h" -#include "max2831_target.h" #include "max283x.h" #include "max5864.h" #include "max5864_target.h" @@ -247,21 +245,6 @@ const ssp_config_t ssp_config_max283x = { .clock_prescale_rate = 2, .gpio_select = &gpio_max283x_select, }; - -static struct gpio gpio_max2831_enable = GPIO(7, 1); -static struct gpio gpio_max2831_rx_enable = GPIO(7, 2); -static struct gpio gpio_max2831_rxhp = GPIO(6, 29); -static struct gpio gpio_max2831_ld = GPIO(4, 11); - -max2831_driver_t max283x = { - .bus = &spi_bus_ssp1, - .gpio_enable = &gpio_max2831_enable, - .gpio_rxtx = &gpio_max2831_rx_enable, - .gpio_rxhp = &gpio_max2831_rxhp, - .gpio_ld = &gpio_max2831_ld, - .target_init = max2831_target_init, - .set_mode = max2831_target_set_mode, -}; #else const ssp_config_t ssp_config_max283x = { /* FIXME speed up once everything is working reliably */ @@ -276,9 +259,9 @@ const ssp_config_t ssp_config_max283x = { .clock_prescale_rate = 2, .gpio_select = &gpio_max283x_select, }; +#endif max283x_driver_t max283x = {}; -#endif const ssp_config_t ssp_config_max5864 = { /* FIXME speed up once everything is working reliably */ diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index d3a7b0d6..eea31df7 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -34,7 +34,6 @@ extern "C" { #include "si5351c.h" #include "spi_ssp.h" -#include "max2831.h" #include "max283x.h" #include "max5864.h" #include "mixer.h" @@ -396,14 +395,11 @@ extern const ssp_config_t ssp_config_w25q80bv; extern const ssp_config_t ssp_config_max283x; extern const ssp_config_t ssp_config_max5864; -#ifndef PRALINE -extern max283x_driver_t max283x; -#else -extern max2831_driver_t max283x; +#ifdef PRALINE extern ice40_spi_driver_t ice40; extern fpga_driver_t fpga; - #endif +extern max283x_driver_t max283x; extern max5864_driver_t max5864; extern mixer_driver_t mixer; extern w25q80bv_driver_t spi_flash; @@ -419,7 +415,6 @@ void clock_gen_shutdown(void); void ssp1_set_mode_max283x(void); void ssp1_set_mode_max5864(void); #ifdef PRALINE -void ssp1_set_mode_max2831(void); void ssp1_set_mode_ice40(void); #endif diff --git a/firmware/common/max2831.h b/firmware/common/max2831.h index c60b6a7e..2fa06973 100644 --- a/firmware/common/max2831.h +++ b/firmware/common/max2831.h @@ -37,8 +37,8 @@ typedef enum { MAX2831_MODE_STANDBY, MAX2831_MODE_TX, MAX2831_MODE_RX, - MAX2831_MODE_TX_CALIBRATION, MAX2831_MODE_RX_CALIBRATION, + MAX2831_MODE_TX_CALIBRATION, } max2831_mode_t; typedef enum { diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index 3b8fca83..bcb71345 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -25,45 +25,60 @@ #include "gpio.h" #include "gpio_lpc.h" -#include "max2837.h" -#include "max2837_target.h" -#include "max2839.h" -#include "max2839_target.h" #include "spi_bus.h" extern spi_bus_t spi_bus_ssp1; #ifdef PRALINE -static struct gpio gpio_max2837_enable = GPIO(6, 29); -static struct gpio gpio_max2837_rx_enable = GPIO(3, 3); -static struct gpio gpio_max2837_tx_enable = GPIO(3, 2); +static struct gpio gpio_max283x_enable = GPIO(7, 1); +static struct gpio gpio_max283x_rx_enable = GPIO(7, 2); +static struct gpio gpio_max2831_rxhp = GPIO(6, 29); +static struct gpio gpio_max2831_ld = GPIO(4, 11); #else -static struct gpio gpio_max2837_enable = GPIO(2, 6); -static struct gpio gpio_max2837_rx_enable = GPIO(2, 5); -static struct gpio gpio_max2837_tx_enable = GPIO(2, 4); +static struct gpio gpio_max283x_enable = GPIO(2, 6); +static struct gpio gpio_max283x_rx_enable = GPIO(2, 5); +static struct gpio gpio_max283x_tx_enable = GPIO(2, 4); #endif +#ifdef PRALINE +max2831_driver_t max2831 = { + .bus = &spi_bus_ssp1, + .gpio_enable = &gpio_max283x_enable, + .gpio_rxtx = &gpio_max283x_rx_enable, + .gpio_rxhp = &gpio_max2831_rxhp, + .gpio_ld = &gpio_max2831_ld, + .target_init = max2831_target_init, + .set_mode = max2831_target_set_mode, +}; +#else max2837_driver_t max2837 = { .bus = &spi_bus_ssp1, - .gpio_enable = &gpio_max2837_enable, - .gpio_rx_enable = &gpio_max2837_rx_enable, - .gpio_tx_enable = &gpio_max2837_tx_enable, + .gpio_enable = &gpio_max283x_enable, + .gpio_rx_enable = &gpio_max283x_rx_enable, + .gpio_tx_enable = &gpio_max283x_tx_enable, .target_init = max2837_target_init, .set_mode = max2837_target_set_mode, }; max2839_driver_t max2839 = { .bus = &spi_bus_ssp1, - .gpio_enable = &gpio_max2837_enable, - .gpio_rxtx = &gpio_max2837_rx_enable, + .gpio_enable = &gpio_max283x_enable, + .gpio_rxtx = &gpio_max283x_rx_enable, .target_init = max2839_target_init, .set_mode = max2839_target_set_mode, }; +#endif /* Initialize chip. */ void max283x_setup(max283x_driver_t* const drv, max283x_variant_t type) { drv->type = type; switch (type) { +#ifdef PRALINE + case MAX2831_VARIANT: + memcpy(&drv->drv.max2831, &max2831, sizeof(max2831)); + max2831_setup(&drv->drv.max2831); + break; +#else case MAX2837_VARIANT: memcpy(&drv->drv.max2837, &max2837, sizeof(max2837)); max2837_setup(&drv->drv.max2837); @@ -73,14 +88,64 @@ void max283x_setup(max283x_driver_t* const drv, max283x_variant_t type) memcpy(&drv->drv.max2839, &max2839, sizeof(max2839)); max2839_setup(&drv->drv.max2839); break; +#endif } } +/* Returns the number of registers supported by the driver. */ +uint16_t max283x_num_regs(max283x_driver_t* const drv) +{ + switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + return MAX2831_NUM_REGS; + break; +#else + case MAX2837_VARIANT: + return MAX2837_NUM_REGS; + break; + + case MAX2839_VARIANT: + return MAX2839_NUM_REGS; + break; +#endif + } + + return 0; +} + +/* Returns the maximum data register value supported by the driver. */ +uint16_t max283x_data_regs_max_value(max283x_driver_t* const drv) +{ + switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + return MAX2831_DATA_REGS_MAX_VALUE; + break; +#else + case MAX2837_VARIANT: + return MAX2837_DATA_REGS_MAX_VALUE; + break; + + case MAX2839_VARIANT: + return MAX2839_DATA_REGS_MAX_VALUE; + break; +#endif + } + + return 0; +} + /* Read a register via SPI. Save a copy to memory and return * value. Mark clean. */ uint16_t max283x_reg_read(max283x_driver_t* const drv, uint8_t r) { switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + return max2831_reg_read(&drv->drv.max2831, r); + break; +#else case MAX2837_VARIANT: return max2837_reg_read(&drv->drv.max2837, r); break; @@ -88,6 +153,7 @@ uint16_t max283x_reg_read(max283x_driver_t* const drv, uint8_t r) case MAX2839_VARIANT: return max2839_reg_read(&drv->drv.max2839, r); break; +#endif } return 0; @@ -98,6 +164,11 @@ uint16_t max283x_reg_read(max283x_driver_t* const drv, uint8_t r) void max283x_reg_write(max283x_driver_t* const drv, uint8_t r, uint16_t v) { switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + max2831_reg_write(&drv->drv.max2831, r, v); + break; +#else case MAX2837_VARIANT: max2837_reg_write(&drv->drv.max2837, r, v); break; @@ -105,6 +176,7 @@ void max283x_reg_write(max283x_driver_t* const drv, uint8_t r, uint16_t v) case MAX2839_VARIANT: max2839_reg_write(&drv->drv.max2839, r, v); break; +#endif } } @@ -114,6 +186,11 @@ void max283x_reg_write(max283x_driver_t* const drv, uint8_t r, uint16_t v) void max283x_regs_commit(max283x_driver_t* const drv) { switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + max2831_regs_commit(&drv->drv.max2831); + break; +#else case MAX2837_VARIANT: max2837_regs_commit(&drv->drv.max2837); break; @@ -121,12 +198,18 @@ void max283x_regs_commit(max283x_driver_t* const drv) case MAX2839_VARIANT: max2839_regs_commit(&drv->drv.max2839); break; +#endif } } void max283x_set_mode(max283x_driver_t* const drv, const max283x_mode_t new_mode) { switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + max2831_set_mode(&drv->drv.max2831, (max2831_mode_t) new_mode); + break; +#else case MAX2837_VARIANT: max2837_set_mode(&drv->drv.max2837, (max2837_mode_t) new_mode); break; @@ -134,12 +217,18 @@ void max283x_set_mode(max283x_driver_t* const drv, const max283x_mode_t new_mode case MAX2839_VARIANT: max2839_set_mode(&drv->drv.max2839, (max2839_mode_t) new_mode); break; +#endif } } max283x_mode_t max283x_mode(max283x_driver_t* const drv) { switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + return (max283x_mode_t) max2831_mode(&drv->drv.max2831); + break; +#else case MAX2837_VARIANT: return (max283x_mode_t) max2837_mode(&drv->drv.max2837); break; @@ -147,18 +236,20 @@ max283x_mode_t max283x_mode(max283x_driver_t* const drv) case MAX2839_VARIANT: return (max283x_mode_t) max2839_mode(&drv->drv.max2839); break; +#endif } - return 0; } -//max283x_mode_t max283x_mode(max283x_driver_t* const drv); -//void max283x_set_mode(max283x_driver_t* const drv, const max283x_mode_t new_mode); - /* Turn on/off all chip functions. Does not control oscillator and CLKOUT */ void max283x_start(max283x_driver_t* const drv) { switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + max2831_start(&drv->drv.max2831); + break; +#else case MAX2837_VARIANT: max2837_start(&drv->drv.max2837); break; @@ -166,12 +257,18 @@ void max283x_start(max283x_driver_t* const drv) case MAX2839_VARIANT: max2839_start(&drv->drv.max2839); break; +#endif } } void max283x_stop(max283x_driver_t* const drv) { switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + max2831_stop(&drv->drv.max2831); + break; +#else case MAX2837_VARIANT: max2837_stop(&drv->drv.max2837); break; @@ -179,6 +276,7 @@ void max283x_stop(max283x_driver_t* const drv) case MAX2839_VARIANT: max2839_stop(&drv->drv.max2839); break; +#endif } } @@ -187,6 +285,11 @@ void max283x_stop(max283x_driver_t* const drv) void max283x_set_frequency(max283x_driver_t* const drv, uint32_t freq) { switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + max2831_set_frequency(&drv->drv.max2831, freq); + break; +#else case MAX2837_VARIANT: max2837_set_frequency(&drv->drv.max2837, freq); break; @@ -194,14 +297,28 @@ void max283x_set_frequency(max283x_driver_t* const drv, uint32_t freq) case MAX2839_VARIANT: max2839_set_frequency(&drv->drv.max2839, freq); break; +#endif } } uint32_t max283x_set_lpf_bandwidth( max283x_driver_t* const drv, + const max283x_mode_t mode, const uint32_t bandwidth_hz) { +#ifndef PRALINE + (void) mode; +#endif + switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + return max2831_set_lpf_bandwidth( + &drv->drv.max2831, + (max2831_mode_t) mode, + bandwidth_hz); + break; +#else case MAX2837_VARIANT: return max2837_set_lpf_bandwidth(&drv->drv.max2837, bandwidth_hz); break; @@ -209,6 +326,7 @@ uint32_t max283x_set_lpf_bandwidth( case MAX2839_VARIANT: return max2839_set_lpf_bandwidth(&drv->drv.max2839, bandwidth_hz); break; +#endif } return 0; @@ -217,6 +335,11 @@ uint32_t max283x_set_lpf_bandwidth( bool max283x_set_lna_gain(max283x_driver_t* const drv, const uint32_t gain_db) { switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + return max2831_set_lna_gain(&drv->drv.max2831, gain_db); + break; +#else case MAX2837_VARIANT: return max2837_set_lna_gain(&drv->drv.max2837, gain_db); break; @@ -224,6 +347,7 @@ bool max283x_set_lna_gain(max283x_driver_t* const drv, const uint32_t gain_db) case MAX2839_VARIANT: return max2839_set_lna_gain(&drv->drv.max2839, gain_db); break; +#endif } return false; @@ -232,6 +356,11 @@ bool max283x_set_lna_gain(max283x_driver_t* const drv, const uint32_t gain_db) bool max283x_set_vga_gain(max283x_driver_t* const drv, const uint32_t gain_db) { switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + return max2831_set_vga_gain(&drv->drv.max2831, gain_db); + break; +#else case MAX2837_VARIANT: return max2837_set_vga_gain(&drv->drv.max2837, gain_db); break; @@ -239,6 +368,7 @@ bool max283x_set_vga_gain(max283x_driver_t* const drv, const uint32_t gain_db) case MAX2839_VARIANT: return max2839_set_vga_gain(&drv->drv.max2839, gain_db); break; +#endif } return false; @@ -247,6 +377,11 @@ bool max283x_set_vga_gain(max283x_driver_t* const drv, const uint32_t gain_db) bool max283x_set_txvga_gain(max283x_driver_t* const drv, const uint32_t gain_db) { switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + return max2831_set_txvga_gain(&drv->drv.max2831, gain_db); + break; +#else case MAX2837_VARIANT: return max2837_set_txvga_gain(&drv->drv.max2837, gain_db); break; @@ -254,6 +389,7 @@ bool max283x_set_txvga_gain(max283x_driver_t* const drv, const uint32_t gain_db) case MAX2839_VARIANT: return max2839_set_txvga_gain(&drv->drv.max2839, gain_db); break; +#endif } return false; @@ -262,6 +398,11 @@ bool max283x_set_txvga_gain(max283x_driver_t* const drv, const uint32_t gain_db) void max283x_tx(max283x_driver_t* const drv) { switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + max2831_tx(&drv->drv.max2831); + break; +#else case MAX2837_VARIANT: max2837_tx(&drv->drv.max2837); break; @@ -269,12 +410,18 @@ void max283x_tx(max283x_driver_t* const drv) case MAX2839_VARIANT: max2839_tx(&drv->drv.max2839); break; +#endif } } void max283x_rx(max283x_driver_t* const drv) { switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + max2831_rx(&drv->drv.max2831); + break; +#else case MAX2837_VARIANT: max2837_rx(&drv->drv.max2837); break; @@ -282,5 +429,71 @@ void max283x_rx(max283x_driver_t* const drv) case MAX2839_VARIANT: max2839_rx(&drv->drv.max2839); break; +#endif + } +} + +void max283x_set_rx_hpf_frequency( + max283x_driver_t* const drv, + const max283x_rx_hpf_freq_t freq) +{ +#ifndef PRALINE + (void) freq; +#endif + + switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + max2831_set_rx_hpf_frequency( + &drv->drv.max2831, + (max2831_rx_hpf_freq_t) freq); + break; +#else + case MAX2837_VARIANT: + // unsupported + break; + + case MAX2839_VARIANT: + // unsupported + break; +#endif + } +} + +void max283x_tx_calibration(max283x_driver_t* const drv) +{ + switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + max2831_tx_calibration(&drv->drv.max2831); + break; +#else + case MAX2837_VARIANT: + // unsupported - use max283x_set_mode instead + break; + + case MAX2839_VARIANT: + // unsupported - use max283x_set_mode instead + break; +#endif + } +} + +void max283x_rx_calibration(max283x_driver_t* const drv) +{ + switch (drv->type) { +#ifdef PRALINE + case MAX2831_VARIANT: + max2831_rx_calibration(&drv->drv.max2831); + break; +#else + case MAX2837_VARIANT: + // unsupported - use max283x_set_mode instead + break; + + case MAX2839_VARIANT: + // unsupported - use max283x_set_mode instead + break; +#endif } } diff --git a/firmware/common/max283x.h b/firmware/common/max283x.h index 06ff6465..3da32d11 100644 --- a/firmware/common/max283x.h +++ b/firmware/common/max283x.h @@ -30,6 +30,8 @@ #include "gpio.h" #include "gpio_lpc.h" +#include "max2831.h" +#include "max2831_target.h" #include "max2837.h" #include "max2837_target.h" #include "max2839.h" @@ -47,22 +49,43 @@ typedef enum { } max283x_mode_t; typedef enum { + MAX283x_RX_HPF_100_HZ = 0, + MAX283x_RX_HPF_4_KHZ = 1, + MAX283x_RX_HPF_30_KHZ = 2, + MAX283x_RX_HPF_600_KHZ = 3, +} max283x_rx_hpf_freq_t; + +typedef enum { +#ifdef PRALINE + MAX2831_VARIANT, +#else MAX2837_VARIANT, MAX2839_VARIANT, +#endif } max283x_variant_t; typedef struct { max283x_variant_t type; union { +#ifdef PRALINE + max2831_driver_t max2831; +#else max2837_driver_t max2837; max2839_driver_t max2839; +#endif } drv; } max283x_driver_t; /* Initialize chip. */ void max283x_setup(max283x_driver_t* const drv, max283x_variant_t type); +/* Returns the number of registers supported by the driver. */ +uint16_t max283x_num_regs(max283x_driver_t* const drv); + +/* Returns the maximum data register value supported by the driver. */ +uint16_t max283x_data_regs_max_value(max283x_driver_t* const drv); + /* Read a register via SPI. Save a copy to memory and return * value. Mark clean. */ uint16_t max283x_reg_read(max283x_driver_t* const drv, uint8_t r); @@ -88,6 +111,7 @@ void max283x_stop(max283x_driver_t* const drv); void max283x_set_frequency(max283x_driver_t* const drv, uint32_t freq); uint32_t max283x_set_lpf_bandwidth( max283x_driver_t* const drv, + const max283x_mode_t mode, const uint32_t bandwidth_hz); bool max283x_set_lna_gain(max283x_driver_t* const drv, const uint32_t gain_db); @@ -98,4 +122,13 @@ bool max283x_set_txvga_gain(max283x_driver_t* const drv, const uint32_t gain_db) void max283x_tx(max283x_driver_t* const drv); void max283x_rx(max283x_driver_t* const drv); +/* Set MAX2831 receiver high-pass filter corner frequency in Hz */ +void max283x_set_rx_hpf_frequency( + max283x_driver_t* const drv, + const max283x_rx_hpf_freq_t freq); + +/* Perform MAX2831 TX and RX calibration. */ +void max283x_tx_calibration(max283x_driver_t* const drv); +void max283x_rx_calibration(max283x_driver_t* const drv); + #endif // __MAX283x_H diff --git a/firmware/common/radio.c b/firmware/common/radio.c index bae631f7..8e1f445d 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -395,12 +395,12 @@ static bool radio_update_bandwidth(radio_t* const radio, uint64_t* bank) uint32_t lpf_bandwidth = auto_bandwidth(radio); if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != lpf_bandwidth) { - max2831_set_lpf_bandwidth(&max283x, MAX2831_MODE_TX, lpf_bandwidth); + max283x_set_lpf_bandwidth(&max283x, MAX283x_MODE_TX, lpf_bandwidth); radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = lpf_bandwidth; new_bw = true; } if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] != lpf_bandwidth) { - max2831_set_lpf_bandwidth(&max283x, MAX2831_MODE_RX, lpf_bandwidth); + max283x_set_lpf_bandwidth(&max283x, MAX283x_MODE_RX, lpf_bandwidth); radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] = lpf_bandwidth; new_bw = true; } @@ -417,9 +417,9 @@ static bool radio_update_bandwidth(radio_t* const radio, uint64_t* bank) new_bw = true; } /* Always set HPF bandwidth to 30 kHz for now. */ - const max2831_rx_hpf_freq_t hpf_bandwidth = MAX2831_RX_HPF_30_KHZ; + const max283x_rx_hpf_freq_t hpf_bandwidth = MAX283x_RX_HPF_30_KHZ; if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] != hpf_bandwidth) { - max2831_set_rx_hpf_frequency(&max283x, hpf_bandwidth); + max283x_set_rx_hpf_frequency(&max283x, hpf_bandwidth); radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] = hpf_bandwidth; new_bw = true; } @@ -443,7 +443,7 @@ static bool radio_update_bandwidth(radio_t* const radio, uint64_t* bank) } if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != lpf_bandwidth) { - max283x_set_lpf_bandwidth(&max283x, lpf_bandwidth); + max283x_set_lpf_bandwidth(&max283x, MAX283x_MODE_TX, lpf_bandwidth); radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_RX] = lpf_bandwidth; radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_TX] = lpf_bandwidth; radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = lpf_bandwidth; @@ -508,19 +508,11 @@ static bool radio_update_gain(radio_t* const radio, uint64_t* bank) gain = bank[RADIO_GAIN_TX_IF]; if ((gain != RADIO_UNSET) && (gain != radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF])) { -#ifdef PRALINE - max2831_set_txvga_gain(&max283x, gain); -#else max283x_set_txvga_gain(&max283x, gain); -#endif radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] = gain; new_gain = true; } else if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] == RADIO_UNSET) { -#ifdef PRALINE - max2831_set_txvga_gain(&max283x, DEFAULT_GAIN_IF); -#else max283x_set_txvga_gain(&max283x, DEFAULT_GAIN_IF); -#endif radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] = DEFAULT_GAIN_IF; new_gain = true; } @@ -528,19 +520,11 @@ static bool radio_update_gain(radio_t* const radio, uint64_t* bank) gain = bank[RADIO_GAIN_RX_IF]; if ((gain != RADIO_UNSET) && (gain != radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF])) { -#ifdef PRALINE - max2831_set_lna_gain(&max283x, gain); -#else max283x_set_lna_gain(&max283x, gain); -#endif radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] = gain; new_gain = true; } else if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] == RADIO_UNSET) { -#ifdef PRALINE - max2831_set_lna_gain(&max283x, DEFAULT_GAIN_IF); -#else max283x_set_lna_gain(&max283x, DEFAULT_GAIN_IF); -#endif radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] = DEFAULT_GAIN_IF; new_gain = true; } @@ -548,19 +532,11 @@ static bool radio_update_gain(radio_t* const radio, uint64_t* bank) gain = bank[RADIO_GAIN_RX_BB]; if ((gain != RADIO_UNSET) && (gain != radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_BB])) { -#ifdef PRALINE - max2831_set_vga_gain(&max283x, gain); -#else max283x_set_vga_gain(&max283x, gain); -#endif radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_BB] = gain; new_gain = true; } else if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_BB] == RADIO_UNSET) { -#ifdef PRALINE - max2831_set_vga_gain(&max283x, DEFAULT_GAIN_BB); -#else max283x_set_vga_gain(&max283x, DEFAULT_GAIN_BB); -#endif radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_BB] = DEFAULT_GAIN_BB; new_gain = true; } diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 13b96cc9..1c605d1c 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -31,7 +31,6 @@ #include "gpio_lpc.h" #include "platform_detect.h" #include "mixer.h" -#include "max2831.h" #include "max283x.h" #include "max5864.h" #include "sgpio.h" @@ -443,16 +442,15 @@ void rf_path_init(rf_path_t* const rf_path) ssp1_set_mode_max283x(); #ifdef PRALINE - max2831_setup(&max283x); - max2831_start(&max283x); + max283x_setup(&max283x, MAX2831_VARIANT); #else if (detected_platform() == BOARD_ID_HACKRF1_R9) { max283x_setup(&max283x, MAX2839_VARIANT); } else { max283x_setup(&max283x, MAX2837_VARIANT); } - max283x_start(&max283x); #endif + max283x_start(&max283x); // On HackRF One, the mixer is now set up earlier in boot. #ifndef HACKRF_ONE @@ -481,11 +479,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d ssp1_set_mode_max5864(); max5864_tx(&max5864); ssp1_set_mode_max283x(); -#ifdef PRALINE - max2831_tx(&max283x); -#else max283x_tx(&max283x); -#endif sgpio_configure(&sgpio_config, SGPIO_DIRECTION_TX); break; @@ -503,11 +497,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d ssp1_set_mode_max5864(); max5864_rx(&max5864); ssp1_set_mode_max283x(); -#ifdef PRALINE - max2831_rx(&max283x); -#else max283x_rx(&max283x); -#endif sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); break; @@ -520,9 +510,9 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d max5864_xcvr(&max5864); ssp1_set_mode_max283x(); if (direction == RF_PATH_DIRECTION_TX_CALIBRATION) { - max2831_tx_calibration(&max283x); + max283x_tx_calibration(&max283x); } else { - max2831_rx_calibration(&max283x); + max283x_rx_calibration(&max283x); } sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); break; @@ -537,11 +527,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d ssp1_set_mode_max5864(); max5864_standby(&max5864); ssp1_set_mode_max283x(); -#ifdef PRALINE - max2831_set_mode(&max283x, MAX2831_MODE_STANDBY); -#else max283x_set_mode(&max283x, MAX283x_MODE_STANDBY); -#endif sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); break; } diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index e1a1d951..5e6ae7ff 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -25,9 +25,6 @@ #include "hackrf_ui.h" #include "hackrf_core.h" #include "mixer.h" -#include "max2831.h" -#include "max2837.h" -#include "max2839.h" #include "sgpio.h" #include "operacake.h" #include "platform_detect.h" @@ -168,35 +165,35 @@ bool tuning_set_frequency( rf = rf + offset; } - max2831_mode_t prior_max2831_mode = max2831_mode(&max283x); - max2831_set_mode(&max283x, MAX2831_MODE_STANDBY); + max283x_mode_t prior_max283x_mode = max283x_mode(&max283x); + max283x_set_mode(&max283x, MAX283x_MODE_STANDBY); if (cfg->if_mhz == 0) { rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS); - max2831_set_frequency(&max283x, rf); + max283x_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 + rf; real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_hz); - max2831_set_frequency(&max283x, real_mixer_freq_hz - rf); + max283x_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 - rf; real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_hz); - max2831_set_frequency(&max283x, real_mixer_freq_hz + rf); + max283x_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 = rf - FREQ_ONE_MHZ * cfg->if_mhz; real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_hz); - max2831_set_frequency(&max283x, rf - real_mixer_freq_hz); + max283x_set_frequency(&max283x, rf - real_mixer_freq_hz); sgpio_cpld_set_mixer_invert(&sgpio_config, 0); } - max2831_set_mode(&max283x, prior_max2831_mode); + max283x_set_mode(&max283x, prior_max283x_mode); hackrf_ui()->set_frequency(freq); operacake_set_range(freq_mhz); return true; @@ -223,11 +220,8 @@ bool set_freq_explicit( } rf_path_set_filter(&rf_path, path); -#ifdef PRALINE - max2831_set_frequency(&max283x, if_freq_hz); -#else max283x_set_frequency(&max283x, if_freq_hz); -#endif + if (lo_freq_hz > if_freq_hz) { sgpio_cpld_set_mixer_invert(&sgpio_config, 1); } else { diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index ee6d5f15..5c0195c3 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -213,6 +213,7 @@ macro(DeclareTargets) ${SRC_M4} ${PATH_HACKRF_FIRMWARE_COMMON}/fpga.c ${PATH_HACKRF_FIRMWARE_COMMON}/ice40_spi.c + ${PATH_HACKRF_FIRMWARE_COMMON}/max283x.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2831.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2831_target.c ) @@ -247,9 +248,9 @@ macro(DeclareTargets) set_target_properties(${PROJECT_NAME}_m0.elf PROPERTIES COMPILE_FLAGS "${CFLAGS_M0}") set_target_properties(${PROJECT_NAME}_m0.elf PROPERTIES LINK_FLAGS "${LDFLAGS_M0}") - DeclareTarget("${PROJECT_NAME}" "" "${CFLAGS_M4}" "${LDFLAGS_M4}") - DeclareTarget("${PROJECT_NAME}" "_ram" "${CFLAGS_M4_RAM} -DRAM_MODE" "${LDFLAGS_M4_RAM}") - DeclareTarget("${PROJECT_NAME}" "_dfu" "${CFLAGS_M4_RAM} -DDFU_MODE" "${LDFLAGS_M4_RAM}") + DeclareTarget("${PROJECT_NAME}" "" "${CFLAGS_M4}" "${LDFLAGS_M4}") + DeclareTarget("${PROJECT_NAME}" "_ram" "${CFLAGS_M4_RAM} -DRAM_MODE" "${LDFLAGS_M4_RAM}") + DeclareTarget("${PROJECT_NAME}" "_dfu" "${CFLAGS_M4_RAM} -DDFU_MODE" "${LDFLAGS_M4_RAM}") add_custom_target( ${PROJECT_NAME}.dfu ${DFU_ALL} diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index 48dd5e62..e863acd5 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -40,9 +40,10 @@ usb_request_status_t usb_vendor_request_write_max283x( const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { -#ifndef PRALINE - if (endpoint->setup.index < MAX2837_NUM_REGS) { - if (endpoint->setup.value < MAX2837_DATA_REGS_MAX_VALUE) { + uint16_t num_regs = max283x_num_regs(&max283x); + uint16_t data_regs_max_value = max283x_data_regs_max_value(&max283x); + if (endpoint->setup.index < num_regs) { + if (endpoint->setup.value < data_regs_max_value) { max283x_reg_write( &max283x, endpoint->setup.index, @@ -51,18 +52,6 @@ usb_request_status_t usb_vendor_request_write_max283x( return USB_REQUEST_STATUS_OK; } } -#else - if (endpoint->setup.index < MAX2831_NUM_REGS) { - if (endpoint->setup.value < MAX2831_DATA_REGS_MAX_VALUE) { - max2831_reg_write( - &max283x, - endpoint->setup.index, - endpoint->setup.value); - usb_transfer_schedule_ack(endpoint->in); - return USB_REQUEST_STATUS_OK; - } - } -#endif return USB_REQUEST_STATUS_STALL; } else { return USB_REQUEST_STATUS_OK; @@ -74,8 +63,8 @@ usb_request_status_t usb_vendor_request_read_max283x( const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { -#ifndef PRALINE - if (endpoint->setup.index < MAX2837_NUM_REGS) { + uint16_t num_regs = max283x_num_regs(&max283x); + if (endpoint->setup.index < num_regs) { const uint16_t value = max283x_reg_read(&max283x, endpoint->setup.index); endpoint->buffer[0] = value & 0xff; @@ -89,22 +78,6 @@ usb_request_status_t usb_vendor_request_read_max283x( usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } -#else - if (endpoint->setup.index < MAX2831_NUM_REGS) { - const uint16_t value = - max2831_reg_read(&max283x, endpoint->setup.index); - endpoint->buffer[0] = value & 0xff; - endpoint->buffer[1] = value >> 8; - usb_transfer_schedule_block( - endpoint->in, - &endpoint->buffer, - 2, - NULL, - NULL); - usb_transfer_schedule_ack(endpoint->out); - return USB_REQUEST_STATUS_OK; - } -#endif return USB_REQUEST_STATUS_STALL; } else { return USB_REQUEST_STATUS_OK; From 431becb1904de80e963c96d0ceb38c2a78140355 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 16 Mar 2026 15:29:15 +0000 Subject: [PATCH 043/238] Support customization of FPGA image loading mechanism. --- firmware/common/fpga.h | 15 +++++++++- firmware/common/fpga_image.c | 43 +++++++++++---------------- firmware/common/ice40_spi.c | 7 +++-- firmware/common/ice40_spi.h | 3 +- firmware/hackrf_usb/hackrf_usb.c | 31 ++++++++++++++++++- firmware/hackrf_usb/usb_api_praline.c | 15 +++++++--- 6 files changed, 78 insertions(+), 36 deletions(-) diff --git a/firmware/common/fpga.h b/firmware/common/fpga.h index b7bb90bb..383444c5 100644 --- a/firmware/common/fpga.h +++ b/firmware/common/fpga.h @@ -44,6 +44,19 @@ struct fpga_driver_t { uint8_t regs_dirty; }; +struct fpga_loader_t { + /* Start address added as an offset to all read() calls. */ + uint32_t start_addr; + /* Any one-off setup needed before calling read(). May be NULL. */ + void (*setup)(void); + /* Read data from the specified address. */ + void (*read)(uint32_t addr, uint32_t len, uint8_t* const data); + /* Buffer to use for compressed data (4096 bytes). */ + uint8_t* in_buffer; + /* Buffer to use for decompressed data (4096 bytes). */ + uint8_t* out_buffer; +}; + /* Initialize the loaded bitstream's registers to their default values. */ extern void fpga_init(fpga_driver_t* const drv); @@ -75,7 +88,7 @@ void fpga_set_prbs_enable(fpga_driver_t* const drv, const bool enable); void fpga_set_tx_nco_enable(fpga_driver_t* const drv, const bool enable); void fpga_set_tx_nco_pstep(fpga_driver_t* const drv, const uint8_t phase_increment); -bool fpga_image_load(unsigned int index); +bool fpga_image_load(struct fpga_loader_t* loader, unsigned int index); bool fpga_spi_selftest(void); bool fpga_sgpio_selftest(void); bool fpga_if_xcvr_selftest(void); diff --git a/firmware/common/fpga_image.c b/firmware/common/fpga_image.c index a70906b8..8d0c1932 100644 --- a/firmware/common/fpga_image.c +++ b/firmware/common/fpga_image.c @@ -21,31 +21,28 @@ #include "hackrf_core.h" #include "lz4_blk.h" -#include "lz4_buf.h" #include "selftest.h" - -// FPGA bitstreams blob. -extern uint32_t _binary_fpga_bin_start; -extern uint32_t _binary_fpga_bin_end; -extern uint32_t _binary_fpga_bin_size; +#include "fpga.h" struct fpga_image_read_ctx { + struct fpga_loader_t* loader; uint32_t addr; size_t next_block_sz; uint8_t init_flag; }; -static size_t fpga_image_read_block_cb(void* _ctx, uint8_t* out_buffer) +static size_t fpga_image_read_block_cb(void* _ctx) { // Assume out_buffer is 4KB struct fpga_image_read_ctx* ctx = _ctx; + struct fpga_loader_t* loader = ctx->loader; size_t block_sz = ctx->next_block_sz; uint8_t block_sz_buf[2]; // first iteration: read first block size if (ctx->init_flag == 0) { - w25q80bv_read(&spi_flash, ctx->addr, 2, block_sz_buf); + loader->read(ctx->addr, 2, block_sz_buf); block_sz = block_sz_buf[0] | block_sz_buf[1] << 8; ctx->addr += 2; ctx->init_flag = 1; @@ -56,48 +53,42 @@ static size_t fpga_image_read_block_cb(void* _ctx, uint8_t* out_buffer) return 0; // Read compressed block (and the next block size) from flash. - w25q80bv_read(&spi_flash, ctx->addr, block_sz, lz4_in_buf); + loader->read(ctx->addr, block_sz, loader->in_buffer); ctx->addr += block_sz; - w25q80bv_read(&spi_flash, ctx->addr, 2, block_sz_buf); + loader->read(ctx->addr, 2, block_sz_buf); ctx->next_block_sz = block_sz_buf[0] | block_sz_buf[1] << 8; ctx->addr += 2; // Decompress block. - return lz4_blk_decompress(lz4_in_buf, out_buffer, block_sz); + return lz4_blk_decompress(loader->in_buffer, loader->out_buffer, block_sz); } -bool fpga_image_load(unsigned int index) +bool fpga_image_load(struct fpga_loader_t* loader, unsigned int index) { -#if defined(DFU_MODE) || defined(RAM_MODE) - selftest.fpga_image_load = SKIPPED; - selftest.report.pass = false; - return false; -#endif - // TODO: do SPI setup and read number of bitstreams once! - - // Prepare for SPI flash access. - spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv); - w25q80bv_setup(&spi_flash); + if (loader->setup != NULL) + loader->setup(); // Read number of bitstreams from flash. // Check the bitstream exists, and extract its offset. - uint32_t addr = (uint32_t) &_binary_fpga_bin_start; + uint32_t addr = loader->start_addr; uint32_t num_bitstreams, bitstream_offset; - w25q80bv_read(&spi_flash, addr, 4, (uint8_t*) &num_bitstreams); + loader->read(addr, 4, (uint8_t*) &num_bitstreams); if (index >= num_bitstreams) return false; - w25q80bv_read(&spi_flash, addr + 4 * (index + 1), 4, (uint8_t*) &bitstream_offset); + loader->read(addr + 4 * (index + 1), 4, (uint8_t*) &bitstream_offset); // A callback function is used by the FPGA programmer // to obtain consecutive gateware chunks. ice40_spi_target_init(&ice40); ssp1_set_mode_ice40(); struct fpga_image_read_ctx fpga_image_ctx = { - .addr = (uint32_t) &_binary_fpga_bin_start + bitstream_offset, + .loader = loader, + .addr = loader->start_addr + bitstream_offset, }; const bool success = ice40_spi_syscfg_program( &ice40, + loader->out_buffer, fpga_image_read_block_cb, &fpga_image_ctx); ssp1_set_mode_max283x(); diff --git a/firmware/common/ice40_spi.c b/firmware/common/ice40_spi.c index 344bb0e6..57abd73d 100644 --- a/firmware/common/ice40_spi.c +++ b/firmware/common/ice40_spi.c @@ -82,7 +82,8 @@ static uint32_t spi_ssp1_transfer_word(const uint32_t data) bool ice40_spi_syscfg_program( ice40_spi_driver_t* const drv, - size_t (*read_block_cb)(void* ctx, uint8_t* buffer), + uint8_t* buf, + size_t (*read_block_cb)(void* ctx), void* read_ctx) { // Drive CRESET_B = 0, SPI_SS = 0, SPI_SCK = 1. @@ -107,11 +108,11 @@ bool ice40_spi_syscfg_program( // first, on falling edge of SPI_SCK. gpio_clear(drv->gpio_select); for (;;) { - size_t read_sz = read_block_cb(read_ctx, lz4_out_buf); + size_t read_sz = read_block_cb(read_ctx); if (read_sz == 0) break; for (size_t j = 0; j < read_sz; j++) { - spi_ssp1_transfer_word(lz4_out_buf[j]); + spi_ssp1_transfer_word(buf[j]); } } diff --git a/firmware/common/ice40_spi.h b/firmware/common/ice40_spi.h index 93c5adc6..2a0cdac5 100644 --- a/firmware/common/ice40_spi.h +++ b/firmware/common/ice40_spi.h @@ -42,7 +42,8 @@ uint8_t ice40_spi_read(ice40_spi_driver_t* const drv, uint8_t r); void ice40_spi_write(ice40_spi_driver_t* const drv, uint8_t r, uint16_t v); bool ice40_spi_syscfg_program( ice40_spi_driver_t* const drv, - size_t (*read_block_cb)(void* ctx, uint8_t* buffer), + uint8_t* buf, + size_t (*read_block_cb)(void* ctx), void* read_ctx); #endif // __ICE40_SPI_H diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index d8934514..64457261 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -63,6 +63,7 @@ #include "fpga.h" #include "selftest.h" #include "delay.h" +#include "lz4_buf.h" extern uint32_t __m0_start__; extern uint32_t __m0_end__; @@ -256,6 +257,29 @@ static void m0_rom_to_ram(void) memcpy(dest, (uint32_t*) (base + src), len); } +#if defined(PRALINE) && !(defined(DFU_MODE) || defined(RAM_MODE)) +extern uint32_t _binary_fpga_bin_start; + +void fpga_loader_setup(void) +{ + spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv); + w25q80bv_setup(&spi_flash); +} + +void fpga_loader_read(uint32_t addr, uint32_t size, uint8_t* buf) +{ + w25q80bv_read(&spi_flash, addr, size, buf); +} + +struct fpga_loader_t fpga_loader = { + .start_addr = (uint32_t) &_binary_fpga_bin_start, + .setup = fpga_loader_setup, + .read = fpga_loader_read, + .in_buffer = lz4_in_buf, + .out_buffer = lz4_out_buf, +}; +#endif + int main(void) { // Copy M0 image from ROM before SPIFI is disabled @@ -315,7 +339,12 @@ int main(void) halt_and_flash(6000000); } #else - fpga_image_load(0); + #if defined(DFU_MODE) || defined(RAM_MODE) + selftest.fpga_image_load = SKIPPED; + selftest.report.pass = false; + #else + fpga_image_load(&fpga_loader, 0); + #endif delay_us_at_mhz(100, 204); fpga_spi_selftest(); fpga_sgpio_selftest(); diff --git a/firmware/hackrf_usb/usb_api_praline.c b/firmware/hackrf_usb/usb_api_praline.c index 9fcde4b1..c5b8fd30 100644 --- a/firmware/hackrf_usb/usb_api_praline.c +++ b/firmware/hackrf_usb/usb_api_praline.c @@ -24,6 +24,7 @@ #include "usb_api_praline.h" #include "usb_queue.h" #include +#include #include @@ -71,17 +72,23 @@ usb_request_status_t usb_vendor_request_set_narrowband_filter( return USB_REQUEST_STATUS_OK; } -bool fpga_image_load(unsigned int index); - usb_request_status_t usb_vendor_request_set_fpga_bitstream( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { +#if defined(DFU_MODE) || defined(RAM_MODE) + (void) endpoint; + (void) stage; + return USB_REQUEST_STATUS_STALL; +#else + extern struct fpga_loader_t fpga_loader; + if (stage == USB_TRANSFER_STAGE_SETUP) { - if (!fpga_image_load(endpoint->setup.value)) { + if (!fpga_image_load(&fpga_loader, endpoint->setup.value)) { return USB_REQUEST_STATUS_STALL; } usb_transfer_schedule_ack(endpoint->in); } return USB_REQUEST_STATUS_OK; -} \ No newline at end of file +#endif +} From a25ca541dfb348788ae3f6cae4a068df1c9d3865 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Tue, 3 Mar 2026 18:23:46 +0200 Subject: [PATCH 044/238] firmware: define platform gpio --- firmware/common/platform_gpio.c | 227 ++++++++++++++++++++ firmware/common/platform_gpio.h | 367 ++++++++++++++++++++++++++++++++ firmware/hackrf-common.cmake | 1 + 3 files changed, 595 insertions(+) create mode 100644 firmware/common/platform_gpio.c create mode 100644 firmware/common/platform_gpio.h diff --git a/firmware/common/platform_gpio.c b/firmware/common/platform_gpio.c new file mode 100644 index 00000000..d00851d5 --- /dev/null +++ b/firmware/common/platform_gpio.c @@ -0,0 +1,227 @@ +/* + * Copyright 2012-2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include +#include "platform_gpio.h" + +// clang-format off + +const platform_gpio_t* platform_gpio(void) +{ + static const platform_gpio_t* _platform_gpio = NULL; + if (_platform_gpio != NULL) { + return _platform_gpio; + } + + static platform_gpio_t gpio; + + /* LEDs */ + gpio.led[0] = &GPIO2_1; + gpio.led[1] = &GPIO2_2; + gpio.led[2] = &GPIO2_8; +#if defined(RAD1O) + gpio.led[3] = &GPIO5_26; +#elif defined(PRALINE) + gpio.led[3] = &GPIO4_6; +#endif + + /* Power Supply Control */ +#if defined(PRALINE) + gpio.gpio_1v2_enable = &GPIO4_7; + gpio.gpio_3v3aux_enable_n = &GPIO5_15; +#else + gpio.gpio_1v8_enable = &GPIO3_6; +#endif + + /* MAX283x GPIO (XCVR_CTL / CS_XCVR) PinMux */ +#if defined(PRALINE) + gpio.max283x_select = &GPIO6_28; + gpio.max283x_enable = &GPIO7_1; + gpio.max283x_rx_enable = &GPIO7_2; + gpio.max2831_rxhp = &GPIO6_29; + gpio.max2831_ld = &GPIO4_11; +#else + gpio.max283x_select = &GPIO0_15; + gpio.max283x_enable = &GPIO2_6; + gpio.max283x_rx_enable = &GPIO2_5; + gpio.max283x_tx_enable = &GPIO2_4; +#endif + + /* MAX5864 SPI chip select (AD_CS / CS_AD) GPIO PinMux */ +#if defined(PRALINE) + gpio.max5864_select = &GPIO6_30; +#else + gpio.max5864_select = &GPIO2_7; +#endif + + /* RF supply (VAA) control */ +#if defined(HACKRF_ONE) + gpio.vaa_disable = &GPIO2_9; +#elif defined(PRALINE) + gpio.vaa_disable = &GPIO4_1; +#elif defined(RAD1O) + gpio.vaa_enable = &GPIO2_9; +#endif + + /* W25Q80BV Flash */ + gpio.w25q80bv_hold = &GPIO1_14; + gpio.w25q80bv_wp = &GPIO1_15; + gpio.w25q80bv_select = &GPIO5_11; + + /* RF switch control */ +#if defined(HACKRF_ONE) + gpio.hp = &GPIO2_0; + gpio.lp = &GPIO2_10; + gpio.tx_mix_bp = &GPIO2_11; + gpio.no_mix_bypass = &GPIO1_0; + gpio.rx_mix_bp = &GPIO2_12; + gpio.tx_amp = &GPIO2_15; + gpio.tx = &GPIO5_15; + gpio.mix_bypass = &GPIO5_16; + gpio.rx = &GPIO5_5; + gpio.no_tx_amp_pwr = &GPIO3_5; + gpio.amp_bypass = &GPIO0_14; + gpio.rx_amp = &GPIO1_11; + gpio.no_rx_amp_pwr = &GPIO1_12; + // HackRF One rev 9 + gpio.h1r9_rx = &GPIO0_7; + gpio.h1r9_no_ant_pwr = &GPIO2_4; +#elif defined(RAD1O) + gpio.tx_rx_n = &GPIO1_11; + gpio.tx_rx = &GPIO0_14; + gpio.by_mix = &GPIO1_12; + gpio.by_mix_n = &GPIO2_10; + gpio.by_amp = &GPIO1_0; + gpio.by_amp_n = &GPIO5_5; + gpio.mixer_en = &GPIO5_16; + gpio.low_high_filt = &GPIO2_11; + gpio.low_high_filt_n = &GPIO2_12; + gpio.tx_amp = &GPIO2_15; + gpio.rx_lna = &GPIO5_15; +#elif defined(PRALINE) + gpio.tx_en = &GPIO3_4; + gpio.mix_en_n = &GPIO3_2; + gpio.mix_en_n_r1_0 = &GPIO5_6; + gpio.lpf_en = &GPIO4_8; + gpio.rf_amp_en = &GPIO4_9; + gpio.ant_bias_en_n = &GPIO1_12; +#endif + + /* CPLD JTAG interface GPIO pins_FPGA config pins in Praline */ + gpio.cpld_tck = &GPIO3_0; +#if defined(PRALINE) + gpio.fpga_cfg_creset = &GPIO2_11; + gpio.fpga_cfg_cdone = &GPIO5_14; + gpio.fpga_cfg_spi_cs = &GPIO2_10; +#elif defined(HACKRF_ONE) || defined(RAD1O) + gpio.cpld_tdo = &GPIO5_18; + gpio.cpld_tms = &GPIO3_4; + gpio.cpld_tdi = &GPIO3_1; +#else + gpio.cpld_tms = &GPIO3_1; + gpio.cpld_tdi = &GPIO3_4; +#endif +#if defined(HACKRF_ONE) || defined(PRALINE) + gpio.cpld_pp_tms = &GPIO1_1; + gpio.cpld_pp_tdo = &GPIO1_8; +#endif + + /* Other CPLD interface GPIO pins */ +#if !defined(PRALINE) + gpio.trigger_enable = &GPIO5_12; +#endif + gpio.q_invert = &GPIO0_13; + + /* RFFC5071 GPIO serial interface PinMux */ +#if defined(JAWBREAKER) || defined(HACKRF_ONE) + gpio.rffc5072_select = &GPIO2_13; + gpio.rffc5072_clock = &GPIO5_6; + gpio.rffc5072_data = &GPIO3_3; + gpio.rffc5072_reset = &GPIO2_14; +#elif defined(RAD1O) + gpio.vco_ce = &GPIO2_13; + gpio.vco_sclk = &GPIO5_6; + gpio.vco_sdata = &GPIO3_3; + gpio.vco_le = &GPIO2_14; + gpio.vco_mux = &GPIO5_25; + gpio.synt_rfout_en = &GPIO3_5; +#elif defined(PRALINE) + gpio.rffc5072_select = &GPIO2_13; + gpio.rffc5072_clock = &GPIO5_18; + gpio.rffc5072_data = &GPIO4_14; + gpio.rffc5072_reset = &GPIO2_14; + gpio.rffc5072_ld = &GPIO6_25; +#endif + + /* Praline */ +#if defined(PRALINE) + gpio.p2_ctrl0 = &GPIO7_3; + gpio.p2_ctrl1 = &GPIO7_4; + gpio.p1_ctrl0 = &GPIO0_14; + gpio.p1_ctrl1 = &GPIO5_16; + gpio.p1_ctrl2 = &GPIO3_5; + gpio.clkin_ctrl = &GPIO0_15; + gpio.aa_en = &GPIO1_7; + gpio.trigger_in = &GPIO6_26; + gpio.trigger_out = &GPIO5_6; + gpio.pps_out = &GPIO5_5; +#endif + + /* HackRF One r9 */ +#if defined(HACKRF_ONE) + /* HackRF One r9 clock control */ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + gpio.h1r9_clkin_en = &GPIO5_15; + gpio.h1r9_clkout_en = &GPIO0_9; + gpio.h1r9_mcu_clk_en = &GPIO0_8; + } + + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + gpio.h1r9_1v8_enable = &GPIO2_9; + gpio.h1r9_vaa_disable = &GPIO3_6; + gpio.h1r9_trigger_enable = &GPIO5_5; + } +#endif + + /* RAD1O */ +#if defined(RAD1O) + gpio.lcd_cs = &GPIO4_12; /* P9_0 */ + gpio.lcd_bl_en = &GPIO0_8; /* P1_1 */ + gpio.lcd_reset = &GPIO5_17; /* P9_4 */ +#endif + + /* Portapack */ +#if defined(HACKRF_ONE) || defined(PRALINE) + gpio.io_stbx = &GPIO5_0; /* P2_0 */ + gpio.addr = &GPIO5_1; /* P2_1 */ + gpio.lcd_te = &GPIO5_3; /* P2_3 */ + gpio.unused = &GPIO5_7; /* P2_8 */ + gpio.lcd_rdx = &GPIO5_4; /* P2_4 */ + gpio.lcd_wrx = &GPIO1_10; /* P2_9 */ + gpio.dir = &GPIO1_13; /* P2_13 */ +#endif + + _platform_gpio = &gpio; + + return _platform_gpio; +} + +// clang-format on diff --git a/firmware/common/platform_gpio.h b/firmware/common/platform_gpio.h new file mode 100644 index 00000000..600a7e68 --- /dev/null +++ b/firmware/common/platform_gpio.h @@ -0,0 +1,367 @@ +/* + * Copyright 2012-2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __PLATFORM_GPIO_H +#define __PLATFORM_GPIO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gpio_lpc.h" +#include "platform_detect.h" + +typedef struct { + /* LEDs */ + gpio_t led[4]; + + /* Power Supply Control */ + gpio_t gpio_1v8_enable; +#if defined(PRALINE) + gpio_t gpio_1v2_enable; + gpio_t gpio_3v3aux_enable_n; +#endif + + /* MAX283x GPIO (XCVR_CTL / CS_XCVR) PinMux */ + gpio_t max283x_select; + gpio_t max283x_enable; + gpio_t max283x_rx_enable; + gpio_t max283x_tx_enable; +#if defined(PRALINE) + gpio_t max2831_rxhp; + gpio_t max2831_ld; +#endif + + /* MAX5864 SPI chip select (AD_CS / CS_AD) GPIO PinMux */ + gpio_t max5864_select; + + /* RF supply (VAA) control */ + gpio_t vaa_disable; +#if defined(RAD1O) + gpio_t vaa_enable; +#endif + + /* W25Q80BV Flash */ + gpio_t w25q80bv_hold; + gpio_t w25q80bv_wp; + gpio_t w25q80bv_select; + + /* RF switch control */ +#if defined(HACKRF_ONE) + gpio_t hp; + gpio_t lp; + gpio_t tx_mix_bp; + gpio_t no_mix_bypass; + gpio_t rx_mix_bp; + gpio_t tx_amp; + gpio_t tx; + gpio_t mix_bypass; + gpio_t rx; + gpio_t no_tx_amp_pwr; + gpio_t amp_bypass; + gpio_t rx_amp; + gpio_t no_rx_amp_pwr; + gpio_t h1r9_no_ant_pwr; // HACKRF_ONE r9 + gpio_t h1r9_rx; // HACKRF_ONE r9 +#endif +#if defined(RAD1O) + gpio_t tx_rx_n; + gpio_t tx_rx; + gpio_t by_mix; + gpio_t by_mix_n; + gpio_t by_amp; + gpio_t by_amp_n; + gpio_t mixer_en; + gpio_t low_high_filt; + gpio_t low_high_filt_n; + gpio_t tx_amp; + gpio_t rx_lna; +#endif +#if defined(PRALINE) + gpio_t tx_en; + gpio_t mix_en_n; + gpio_t mix_en_n_r1_0; + gpio_t lpf_en; + gpio_t rf_amp_en; + gpio_t ant_bias_en_n; +#endif + + /* CPLD JTAG interface GPIO pins, FPGA config pins in Praline */ + gpio_t cpld_tck; + gpio_t cpld_tdo; + gpio_t cpld_tms; + gpio_t cpld_tdi; +#if defined(HACKRF_ONE) || defined(PRALINE) + gpio_t cpld_pp_tms; + gpio_t cpld_pp_tdo; +#endif +#if defined(PRALINE) + gpio_t fpga_cfg_creset; + gpio_t fpga_cfg_cdone; + gpio_t fpga_cfg_spi_cs; +#endif + + /* Other CPLD interface GPIO pins */ +#if !defined(PRALINE) + gpio_t trigger_enable; +#endif + gpio_t q_invert; + + /* RFFC5071 GPIO serial interface PinMux */ + gpio_t rffc5072_select; + gpio_t rffc5072_clock; + gpio_t rffc5072_data; + gpio_t rffc5072_reset; + gpio_t rffc5072_ld; // PRALINE + gpio_t vco_ce; // RAD1O + gpio_t vco_sclk; // RAD1O + gpio_t vco_sdata; // RAD1O + gpio_t vco_le; // RAD1O + gpio_t vco_mux; // RAD1O + gpio_t synt_rfout_en; // RAD1O + + /* Praline */ +#if defined(PRALINE) + gpio_t p2_ctrl0; + gpio_t p2_ctrl1; + gpio_t p1_ctrl0; + gpio_t p1_ctrl1; + gpio_t p1_ctrl2; + gpio_t clkin_ctrl; + gpio_t aa_en; + gpio_t trigger_in; + gpio_t trigger_out; + gpio_t pps_out; +#endif + + /* HackRF One r9 */ +#if defined(HACKRF_ONE) + /* HackRF One r9 clock control */ + gpio_t h1r9_clkin_en; + gpio_t h1r9_clkout_en; + gpio_t h1r9_mcu_clk_en; + + gpio_t h1r9_1v8_enable; + gpio_t h1r9_vaa_disable; + gpio_t h1r9_trigger_enable; +#endif + + /* RAD1O */ +#if defined(RAD1O) + gpio_t lcd_cs; + gpio_t lcd_bl_en; + gpio_t lcd_reset; +#endif + + /* Portapack */ +#if defined(HACKRF_ONE) || defined(PRALINE) + gpio_t io_stbx; + gpio_t addr; + __attribute__((unused)) gpio_t lcd_te; + __attribute__((unused)) gpio_t unused; + gpio_t lcd_rdx; + gpio_t lcd_wrx; + gpio_t dir; +#endif +} platform_gpio_t; + +// Detects and returns the global platform gpio instance of the active board id and revision. +const platform_gpio_t* platform_gpio(void); + +/* LPC43xx GPIO pre-declarations - we use these instead of the GPIO() + macro so that we can assign them at runtime. */ +static const struct gpio GPIO0_0 = GPIO(0, 0); +static const struct gpio GPIO0_1 = GPIO(0, 1); +static const struct gpio GPIO0_2 = GPIO(0, 2); +static const struct gpio GPIO0_3 = GPIO(0, 3); +static const struct gpio GPIO0_4 = GPIO(0, 4); +static const struct gpio GPIO0_5 = GPIO(0, 5); +static const struct gpio GPIO0_6 = GPIO(0, 6); +static const struct gpio GPIO0_7 = GPIO(0, 7); +static const struct gpio GPIO0_8 = GPIO(0, 8); +static const struct gpio GPIO0_9 = GPIO(0, 9); +static const struct gpio GPIO0_10 = GPIO(0, 10); +static const struct gpio GPIO0_11 = GPIO(0, 11); +static const struct gpio GPIO0_12 = GPIO(0, 12); +static const struct gpio GPIO0_13 = GPIO(0, 13); +static const struct gpio GPIO0_14 = GPIO(0, 14); +static const struct gpio GPIO0_15 = GPIO(0, 15); + +static const struct gpio GPIO1_0 = GPIO(1, 0); +static const struct gpio GPIO1_1 = GPIO(1, 1); +static const struct gpio GPIO1_2 = GPIO(1, 2); +static const struct gpio GPIO1_3 = GPIO(1, 3); +static const struct gpio GPIO1_4 = GPIO(1, 4); +static const struct gpio GPIO1_5 = GPIO(1, 5); +static const struct gpio GPIO1_6 = GPIO(1, 6); +static const struct gpio GPIO1_7 = GPIO(1, 7); +static const struct gpio GPIO1_8 = GPIO(1, 8); +static const struct gpio GPIO1_9 = GPIO(1, 9); +static const struct gpio GPIO1_10 = GPIO(1, 10); +static const struct gpio GPIO1_11 = GPIO(1, 11); +static const struct gpio GPIO1_12 = GPIO(1, 12); +static const struct gpio GPIO1_13 = GPIO(1, 13); +static const struct gpio GPIO1_14 = GPIO(1, 14); +static const struct gpio GPIO1_15 = GPIO(1, 15); + +static const struct gpio GPIO2_0 = GPIO(2, 0); +static const struct gpio GPIO2_1 = GPIO(2, 1); +static const struct gpio GPIO2_2 = GPIO(2, 2); +static const struct gpio GPIO2_3 = GPIO(2, 3); +static const struct gpio GPIO2_4 = GPIO(2, 4); +static const struct gpio GPIO2_5 = GPIO(2, 5); +static const struct gpio GPIO2_6 = GPIO(2, 6); +static const struct gpio GPIO2_7 = GPIO(2, 7); +static const struct gpio GPIO2_8 = GPIO(2, 8); +static const struct gpio GPIO2_9 = GPIO(2, 9); +static const struct gpio GPIO2_10 = GPIO(2, 10); +static const struct gpio GPIO2_11 = GPIO(2, 11); +static const struct gpio GPIO2_12 = GPIO(2, 12); +static const struct gpio GPIO2_13 = GPIO(2, 13); +static const struct gpio GPIO2_14 = GPIO(2, 14); +static const struct gpio GPIO2_15 = GPIO(2, 15); + +static const struct gpio GPIO3_0 = GPIO(3, 0); +static const struct gpio GPIO3_1 = GPIO(3, 1); +static const struct gpio GPIO3_2 = GPIO(3, 2); +static const struct gpio GPIO3_3 = GPIO(3, 3); +static const struct gpio GPIO3_4 = GPIO(3, 4); +static const struct gpio GPIO3_5 = GPIO(3, 5); +static const struct gpio GPIO3_6 = GPIO(3, 6); +static const struct gpio GPIO3_7 = GPIO(3, 7); +static const struct gpio GPIO3_8 = GPIO(3, 8); +static const struct gpio GPIO3_9 = GPIO(3, 9); +static const struct gpio GPIO3_10 = GPIO(3, 10); +static const struct gpio GPIO3_11 = GPIO(3, 11); +static const struct gpio GPIO3_12 = GPIO(3, 12); +static const struct gpio GPIO3_13 = GPIO(3, 13); +static const struct gpio GPIO3_14 = GPIO(3, 14); +static const struct gpio GPIO3_15 = GPIO(3, 15); + +static const struct gpio GPIO4_0 = GPIO(4, 0); +static const struct gpio GPIO4_1 = GPIO(4, 1); +static const struct gpio GPIO4_2 = GPIO(4, 2); +static const struct gpio GPIO4_3 = GPIO(4, 3); +static const struct gpio GPIO4_4 = GPIO(4, 4); +static const struct gpio GPIO4_5 = GPIO(4, 5); +static const struct gpio GPIO4_6 = GPIO(4, 6); +static const struct gpio GPIO4_7 = GPIO(4, 7); +static const struct gpio GPIO4_8 = GPIO(4, 8); +static const struct gpio GPIO4_9 = GPIO(4, 9); +static const struct gpio GPIO4_10 = GPIO(4, 10); +static const struct gpio GPIO4_11 = GPIO(4, 11); +static const struct gpio GPIO4_12 = GPIO(4, 12); +static const struct gpio GPIO4_13 = GPIO(4, 13); +static const struct gpio GPIO4_14 = GPIO(4, 14); +static const struct gpio GPIO4_15 = GPIO(4, 15); + +static const struct gpio GPIO5_0 = GPIO(5, 0); +static const struct gpio GPIO5_1 = GPIO(5, 1); +static const struct gpio GPIO5_2 = GPIO(5, 2); +static const struct gpio GPIO5_3 = GPIO(5, 3); +static const struct gpio GPIO5_4 = GPIO(5, 4); +static const struct gpio GPIO5_5 = GPIO(5, 5); +static const struct gpio GPIO5_6 = GPIO(5, 6); +static const struct gpio GPIO5_7 = GPIO(5, 7); +static const struct gpio GPIO5_8 = GPIO(5, 8); +static const struct gpio GPIO5_9 = GPIO(5, 9); +static const struct gpio GPIO5_10 = GPIO(5, 10); +static const struct gpio GPIO5_11 = GPIO(5, 11); +static const struct gpio GPIO5_12 = GPIO(5, 12); +static const struct gpio GPIO5_13 = GPIO(5, 13); +static const struct gpio GPIO5_14 = GPIO(5, 14); +static const struct gpio GPIO5_15 = GPIO(5, 15); +static const struct gpio GPIO5_16 = GPIO(5, 16); +static const struct gpio GPIO5_17 = GPIO(5, 17); +static const struct gpio GPIO5_18 = GPIO(5, 18); +static const struct gpio GPIO5_19 = GPIO(5, 19); +static const struct gpio GPIO5_20 = GPIO(5, 20); +static const struct gpio GPIO5_21 = GPIO(5, 21); +static const struct gpio GPIO5_22 = GPIO(5, 22); +static const struct gpio GPIO5_23 = GPIO(5, 23); +static const struct gpio GPIO5_24 = GPIO(5, 24); +static const struct gpio GPIO5_25 = GPIO(5, 25); +static const struct gpio GPIO5_26 = GPIO(5, 26); + +static const struct gpio GPIO6_0 = GPIO(6, 0); +static const struct gpio GPIO6_1 = GPIO(6, 1); +static const struct gpio GPIO6_2 = GPIO(6, 2); +static const struct gpio GPIO6_3 = GPIO(6, 3); +static const struct gpio GPIO6_4 = GPIO(6, 4); +static const struct gpio GPIO6_5 = GPIO(6, 5); +static const struct gpio GPIO6_6 = GPIO(6, 6); +static const struct gpio GPIO6_7 = GPIO(6, 7); +static const struct gpio GPIO6_8 = GPIO(6, 8); +static const struct gpio GPIO6_9 = GPIO(6, 9); +static const struct gpio GPIO6_10 = GPIO(6, 10); +static const struct gpio GPIO6_11 = GPIO(6, 11); +static const struct gpio GPIO6_12 = GPIO(6, 12); +static const struct gpio GPIO6_13 = GPIO(6, 13); +static const struct gpio GPIO6_14 = GPIO(6, 14); +static const struct gpio GPIO6_15 = GPIO(6, 15); +static const struct gpio GPIO6_16 = GPIO(6, 16); +static const struct gpio GPIO6_17 = GPIO(6, 17); +static const struct gpio GPIO6_18 = GPIO(6, 18); +static const struct gpio GPIO6_19 = GPIO(6, 19); +static const struct gpio GPIO6_20 = GPIO(6, 20); +static const struct gpio GPIO6_21 = GPIO(6, 21); +static const struct gpio GPIO6_22 = GPIO(6, 22); +static const struct gpio GPIO6_23 = GPIO(6, 23); +static const struct gpio GPIO6_24 = GPIO(6, 24); +static const struct gpio GPIO6_25 = GPIO(6, 25); +static const struct gpio GPIO6_26 = GPIO(6, 26); +static const struct gpio GPIO6_27 = GPIO(6, 27); +static const struct gpio GPIO6_28 = GPIO(6, 28); +static const struct gpio GPIO6_29 = GPIO(6, 29); +static const struct gpio GPIO6_30 = GPIO(6, 30); + +static const struct gpio GPIO7_0 = GPIO(7, 0); +static const struct gpio GPIO7_1 = GPIO(7, 1); +static const struct gpio GPIO7_2 = GPIO(7, 2); +static const struct gpio GPIO7_3 = GPIO(7, 3); +static const struct gpio GPIO7_4 = GPIO(7, 4); +static const struct gpio GPIO7_5 = GPIO(7, 5); +static const struct gpio GPIO7_6 = GPIO(7, 6); +static const struct gpio GPIO7_7 = GPIO(7, 7); +static const struct gpio GPIO7_8 = GPIO(7, 8); +static const struct gpio GPIO7_9 = GPIO(7, 9); +static const struct gpio GPIO7_10 = GPIO(7, 10); +static const struct gpio GPIO7_11 = GPIO(7, 11); +static const struct gpio GPIO7_12 = GPIO(7, 12); +static const struct gpio GPIO7_13 = GPIO(7, 13); +static const struct gpio GPIO7_14 = GPIO(7, 14); +static const struct gpio GPIO7_15 = GPIO(7, 15); +static const struct gpio GPIO7_16 = GPIO(7, 16); +static const struct gpio GPIO7_17 = GPIO(7, 17); +static const struct gpio GPIO7_18 = GPIO(7, 18); +static const struct gpio GPIO7_19 = GPIO(7, 19); +static const struct gpio GPIO7_20 = GPIO(7, 20); +static const struct gpio GPIO7_21 = GPIO(7, 21); +static const struct gpio GPIO7_22 = GPIO(7, 22); +static const struct gpio GPIO7_23 = GPIO(7, 23); +static const struct gpio GPIO7_24 = GPIO(7, 24); +static const struct gpio GPIO7_25 = GPIO(7, 25); + +#ifdef __cplusplus +} +#endif + +#endif /* __PLATFORM_GPIO_H */ diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 5c0195c3..fc9d128c 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -185,6 +185,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/gpio_lpc.c ${PATH_HACKRF_FIRMWARE_COMMON}/hackrf_ui.c ${PATH_HACKRF_FIRMWARE_COMMON}/platform_detect.c + ${PATH_HACKRF_FIRMWARE_COMMON}/platform_gpio.c ${PATH_HACKRF_FIRMWARE_COMMON}/firmware_info.c ${PATH_HACKRF_FIRMWARE_COMMON}/clkin.c ${PATH_HACKRF_FIRMWARE_COMMON}/gpdma.c From 5d8e23953b565a194c1f5f122690404dcf702797 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Sat, 7 Mar 2026 10:10:49 +0000 Subject: [PATCH 045/238] firmware: define platform scu --- firmware/common/platform_scu.c | 372 +++++++++++++++++++++++++++++++++ firmware/common/platform_scu.h | 309 +++++++++++++++++++++++++++ firmware/hackrf-common.cmake | 1 + 3 files changed, 682 insertions(+) create mode 100644 firmware/common/platform_scu.c create mode 100644 firmware/common/platform_scu.h diff --git a/firmware/common/platform_scu.c b/firmware/common/platform_scu.c new file mode 100644 index 00000000..9521b90c --- /dev/null +++ b/firmware/common/platform_scu.c @@ -0,0 +1,372 @@ +/* + * Copyright 2012-2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include +#include "platform_scu.h" + +// clang-format off + +const platform_scu_t* platform_scu(void) +{ + static const platform_scu_t* _platform_scu = NULL; + if (_platform_scu != NULL) { + return _platform_scu; + } + + static platform_scu_t scu; + + /* LED PinMux */ + scu.PINMUX_LED1 = SCU_PINMUX_LED1; /* GPIO2[1] on P4_1 */ + scu.PINMUX_LED2 = SCU_PINMUX_LED2; /* GPIO2[2] on P4_2 */ + scu.PINMUX_LED3 = SCU_PINMUX_LED3; /* GPIO2[8] on P6_12 */ +#if defined(PRALINE) + scu.PINMUX_LED4 = (P8_6); /* GPIO4[6] on P8_6 */ +#elif defined(RAD1O) + scu.PINMUX_LED4 = (PB_6); /* GPIO5[26] on PB_6 */ +#endif + + /* Power Supply PinMux */ + scu.PINMUX_EN1V8 = (P6_10); /* GPIO3[6] on P6_10 */ + scu.PINMUX_EN1V2 = (P8_7); /* GPIO4[7] on P8_7 */ +#if defined(PRALINE) + scu.PINMUX_EN3V3_AUX_N = (P6_7); /* GPIO5[15] on P6_7 */ + scu.PINMUX_EN3V3_OC_N = (P6_11); /* GPIO3[7] on P6_11 */ +#endif + + /* GPIO Input PinMux */ + scu.PINMUX_BOOT0 = (P1_1); /* GPIO0[8] on P1_1 */ + scu.PINMUX_BOOT1 = (P1_2); /* GPIO0[9] on P1_2 */ +#if !defined(HACKRF_ONE) + scu.PINMUX_BOOT2 = (P2_8); /* GPIO5[7] on P2_8 */ + scu.PINMUX_BOOT3 = (P2_9); /* GPIO1[10] on P2_9 */ +#endif + scu.PINMUX_PP_LCD_TE = (P2_3); /* GPIO5[3] on P2_3 */ + scu.PINMUX_PP_LCD_RDX = (P2_4); /* GPIO5[4] on P2_4 */ + scu.PINMUX_PP_UNUSED = (P2_8); /* GPIO5[7] on P2_8 */ + scu.PINMUX_PP_LCD_WRX = (P2_9); /* GPIO1[10] on P2_9 */ + scu.PINMUX_PP_DIR = (P2_13); /* GPIO1[13] on P2_13 */ + + /* USB peripheral */ +#if defined(JAWBREAKER) + scu.PINMUX_USB_LED0 = (P6_8); + scu.PINMUX_USB_LED1 = (P6_7); +#endif + + /* SSP1 Peripheral PinMux */ + scu.SSP1_CIPO = (P1_3); /* P1_3 */ + scu.SSP1_COPI = (P1_4); /* P1_4 */ + scu.SSP1_SCK = (P1_19); /* P1_19 */ + scu.SSP1_CS = (P1_20); /* P1_20 */ + + /* CPLD JTAG interface */ +#if defined(PRALINE) + scu.PINMUX_FPGA_CRESET = (P5_2); /* GPIO2[11] on P5_2 */ + scu.PINMUX_FPGA_CDONE = (P4_10); /* GPIO5[14] */ + scu.PINMUX_FPGA_SPI_CS = (P5_1); /* GPIO2[10] */ +#endif + scu.PINMUX_CPLD_TDO = (P9_5); /* GPIO5[18] */ + scu.PINMUX_CPLD_TCK = (P6_1); /* GPIO3[ 0] */ +#if defined(RAD1O) || defined(HACKRF_ONE) || defined(PRALINE) + scu.PINMUX_CPLD_TMS = (P6_5); /* GPIO3[ 4] */ + scu.PINMUX_CPLD_TDI = (P6_2); /* GPIO3[ 1] */ +#else + scu.PINMUX_CPLD_TMS = (P6_2); /* GPIO3[ 1] */ + scu.PINMUX_CPLD_TDI = (P6_5); /* GPIO3[ 4] */ +#endif + + /* CPLD SGPIO interface */ +#if defined(PRALINE) + scu.PINMUX_SGPIO0 = (P0_0); + scu.PINMUX_SGPIO1 = (P0_1); + scu.PINMUX_SGPIO2 = (P1_15); + scu.PINMUX_SGPIO3 = (P1_16); + scu.PINMUX_SGPIO4 = (P9_4); + scu.PINMUX_SGPIO5 = (P6_6); + scu.PINMUX_SGPIO6 = (P2_2); + scu.PINMUX_SGPIO7 = (P1_0); + scu.PINMUX_SGPIO8 = (P8_0); + scu.PINMUX_SGPIO9 = (P9_3); + scu.PINMUX_SGPIO10 = (P8_2); + scu.PINMUX_SGPIO11 = (P1_17); + scu.PINMUX_SGPIO12 = (P1_18); + scu.PINMUX_SGPIO14 = (P1_18); + scu.PINMUX_SGPIO15 = (P1_18); + + scu.PINMUX_SGPIO0_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION3); + scu.PINMUX_SGPIO1_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION3); + scu.PINMUX_SGPIO2_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu.PINMUX_SGPIO3_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu.PINMUX_SGPIO4_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO5_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu.PINMUX_SGPIO6_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.PINMUX_SGPIO7_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO8_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.PINMUX_SGPIO9_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO10_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.PINMUX_SGPIO11_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO12_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.PINMUX_SGPIO14_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.PINMUX_SGPIO15_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); +#else + scu.PINMUX_SGPIO0 = (P0_0); + scu.PINMUX_SGPIO1 = (P0_1); + scu.PINMUX_SGPIO2 = (P1_15); + scu.PINMUX_SGPIO3 = (P1_16); + scu.PINMUX_SGPIO4 = (P6_3); + scu.PINMUX_SGPIO5 = (P6_6); + scu.PINMUX_SGPIO6 = (P2_2); + scu.PINMUX_SGPIO7 = (P1_0); + scu.PINMUX_SGPIO8 = (P9_6); + scu.PINMUX_SGPIO9 = (P4_3); + scu.PINMUX_SGPIO10 = (P1_14); + scu.PINMUX_SGPIO11 = (P1_17); + scu.PINMUX_SGPIO12 = (P1_18); + scu.PINMUX_SGPIO14 = (P4_9); + scu.PINMUX_SGPIO15 = (P4_10); + + scu.PINMUX_SGPIO0_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION3); + scu.PINMUX_SGPIO1_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION3); + scu.PINMUX_SGPIO2_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu.PINMUX_SGPIO3_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu.PINMUX_SGPIO4_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu.PINMUX_SGPIO5_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu.PINMUX_SGPIO6_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.PINMUX_SGPIO7_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO8_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO9_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION7); + scu.PINMUX_SGPIO10_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO11_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO12_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.PINMUX_SGPIO14_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.PINMUX_SGPIO15_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); +#endif + scu.TRIGGER_EN = (P4_8); /* GPIO5[12] on P4_8 */ + + /* MAX283x GPIO (XCVR_CTL) PinMux */ +#if defined(PRALINE) + scu.XCVR_ENABLE = PE_1; /* GPIO7[1] on PE_1 */ + scu.XCVR_RXENABLE = PE_2; /* GPIO7[2] on PE_2 */ + scu.XCVR_CS = PD_14; /* GPIO6[28] on PD_14 */ + scu.XCVR_RXHP = PD_15; /* GPIO6[29] on PD_15 */ + scu.XCVR_LD = P9_6; /* GPIO4[11] on P9_6 */ + + scu.XCVR_ENABLE_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.XCVR_RXENABLE_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.XCVR_CS_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.XCVR_RXHP_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.XCVR_LD_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0 | + SCU_CONF_EPD_EN_PULLDOWN | SCU_CONF_EPUN_DIS_PULLUP); +#elif defined(JELLYBEAN) || defined(JAWBREAKER) || defined(HACKRF_ONE) + scu.XCVR_ENABLE = P4_6; /* GPIO2[6] on P4_6 */ + scu.XCVR_RXENABLE = P4_5; /* GPIO2[5] on P4_5 */ + scu.XCVR_TXENABLE = P4_4; /* GPIO2[4] on P4_4 */ + scu.XCVR_CS = P1_20; /* GPIO0[15] on P1_20 */ + + scu.XCVR_ENABLE_PINCFG = (SCU_GPIO_FAST); + scu.XCVR_RXENABLE_PINCFG = (SCU_GPIO_FAST); + scu.XCVR_TXENABLE_PINCFG = (SCU_GPIO_FAST); + scu.XCVR_CS_PINCFG = (SCU_GPIO_FAST); +#elif defined(RAD1O) + scu.XCVR_RXHP = P8_1; /* GPIO[] on P8_1 */ + scu.XCVR_B6 = P8_2; /* GPIO[] on P8_2 */ + scu.XCVR_B7 = P9_3; /* GPIO[] on P9_3 */ +#endif + + /* MAX5864 SPI chip select (AD_CS) GPIO PinMux */ +#if defined(PRALINE) + scu.AD_CS = (PD_16); /* GPIO6[30] on PD_16 */ + scu.AD_CS_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); +#else + scu.AD_CS = (P5_7); /* GPIO2[7] on P5_7 */ + scu.AD_CS_PINCFG = (SCU_GPIO_FAST); +#endif + + /* RFFC5071 GPIO serial interface PinMux */ +#if defined(PRALINE) + scu.MIXER_ENX = (P5_4); /* GPIO2[13] on P5_4 */ + scu.MIXER_SCLK = (P9_5); /* GPIO5[18] on P9_5 */ + scu.MIXER_SDATA = (P9_2); /* GPIO4[14] on P9_2 */ + scu.MIXER_RESETX = (P5_5); /* GPIO2[14] on P5_5 */ + scu.MIXER_LD = (PD_11); /* GPIO6[25] on PD_11 */ + + scu.MIXER_SCLK_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.MIXER_SDATA_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.MIXER_LD_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); +#elif defined(JAWBREAKER) || defined(HACKRF_ONE) + scu.MIXER_ENX = (P5_4); /* GPIO2[13] on P5_4 */ + scu.MIXER_SCLK = (P2_6); /* GPIO5[6] on P2_6 */ + scu.MIXER_SDATA = (P6_4); /* GPIO3[3] on P6_4 */ + scu.MIXER_RESETX = (P5_5); /* GPIO2[14] on P5_5 */ + + scu.MIXER_SCLK_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.MIXER_SDATA_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); +#elif defined(RAD1O) + scu.VCO_CE = (P5_4); /* GPIO2[13] on P5_4 */ + scu.VCO_SCLK = (P2_6); /* GPIO5[6] on P2_6 */ + scu.VCO_SDATA = (P6_4); /* GPIO3[3] on P6_4 */ + scu.VCO_LE = (P5_5); /* GPIO2[14] on P5_5 */ + scu.VCO_MUX = (PB_5); /* GPIO5[25] on PB_5 */ + scu.MIXER_EN = (P6_8); /* GPIO5[16] on P6_8 */ + scu.SYNT_RFOUT_EN = (P6_9); /* GPIO3[5] on P6_9 */ +#endif + + /* RF LDO control */ +#if defined(JAWBREAKER) + scu.RF_LDO_ENABLE = (P5_0); /* GPIO2[9] on P5_0 */ +#endif + + /* RF supply (VAA) control */ +#if defined(PRALINE) + scu.NO_VAA_ENABLE = P8_1; /* GPIO4[1] on P8_1 */ +#elif defined(HACKRF_ONE) + scu.NO_VAA_ENABLE = P5_0; /* GPIO2[9] on P5_0 */ +#elif defined(RAD1O) + scu.VAA_ENABLE = P5_0; /* GPIO2[9] on P5_0 */ +#endif + + /* SPI flash */ + scu.SSP0_CIPO = (P3_6); + scu.SSP0_COPI = (P3_7); + scu.SSP0_SCK = (P3_3); + scu.SSP0_CS = (P3_8); /* GPIO5[11] on P3_8 */ + scu.FLASH_HOLD = (P3_4); /* GPIO1[14] on P3_4 */ + scu.FLASH_WP = (P3_5); /* GPIO1[15] on P3_5 */ + + /* RF switch control */ +#if defined(PRALINE) + scu.TX_EN = P6_5; /* GPIO3[4] on P6_5 */ + scu.MIX_EN_N = P6_3; /* GPIO3[2] on P6_3 */ + scu.MIX_EN_N_R1_0 = P2_6; /* GPIO5[6] on P2_6 */ + scu.LPF_EN = PA_1; /* GPIO4[8] on PA_1 */ + scu.RF_AMP_EN = PA_2; /* GPIO4[9] on PA_2 */ + scu.ANT_BIAS_EN_N = P2_12; /* GPIO1[12] on P2_12 */ + scu.ANT_BIAS_OC_N = P2_11; /* GPIO1[11] on P2_11 */ +#elif defined(HACKRF_ONE) + scu.HP = P4_0; /* GPIO2[0] on P4_0 */ + scu.LP = P5_1; /* GPIO2[10] on P5_1 */ + scu.TX_MIX_BP = P5_2; /* GPIO2[11] on P5_2 */ + scu.NO_MIX_BYPASS = P1_7; /* GPIO1[0] on P1_7 */ + scu.RX_MIX_BP = P5_3; /* GPIO2[12] on P5_3 */ + scu.TX_AMP = P5_6; /* GPIO2[15] on P5_6 */ + scu.TX = P6_7; /* GPIO5[15] on P6_7 */ + scu.MIX_BYPASS = P6_8; /* GPIO5[16] on P6_8 */ + scu.RX = P2_5; /* GPIO5[5] on P2_5 */ + scu.NO_TX_AMP_PWR = P6_9; /* GPIO3[5] on P6_9 */ + scu.AMP_BYPASS = P2_10; /* GPIO0[14] on P2_10 */ + scu.RX_AMP = P2_11; /* GPIO1[11] on P2_11 */ + scu.NO_RX_AMP_PWR = P2_12; /* GPIO1[12] on P2_12 */ +#elif defined(RAD1O) + scu.BY_AMP = P1_7; /* GPIO1[0] on P1_7 */ + scu.BY_AMP_N = P2_5; /* GPIO5[5] on P2_5 */ + scu.TX_RX = P2_10; /* GPIO0[14] on P2_10 */ + scu.TX_RX_N = P2_11; /* GPIO1[11] on P2_11 */ + scu.BY_MIX = P2_12; /* GPIO1[12] on P2_12 */ + scu.BY_MIX_N = P5_1; /* GPIO2[10] on P5_1 */ + scu.LOW_HIGH_FILT = P5_2; /* GPIO2[11] on P5_2 */ + scu.LOW_HIGH_FILT_N = P5_3; /* GPIO2[12] on P5_3 */ + scu.TX_AMP = P5_6; /* GPIO2[15] on P5_6 */ + scu.RX_LNA = P6_7; /* GPIO5[15] on P6_7 */ +#endif + + /* Praline */ +#if defined(PRALINE) + scu.P2_CTRL0 = (PE_3); /* GPIO7[3] on PE_3 */ + scu.P2_CTRL1 = (PE_4); /* GPIO7[4] on PE_4 */ + scu.P1_CTRL0 = (P2_10); /* GPIO0[14] on P2_10 */ + scu.P1_CTRL1 = (P6_8); /* GPIO5[16] on P6_8 */ + scu.P1_CTRL2 = (P6_9); /* GPIO3[5] on P6_9 */ + scu.CLKIN_CTRL = (P1_20); /* GPIO0[15] on P1_20 */ + scu.AA_EN = (P1_14); /* GPIO1[7] on P1_14 */ + scu.TRIGGER_IN = (PD_12); /* GPIO6[26] on PD_12 */ + scu.TRIGGER_OUT = (P2_6); /* GPIO5[6] on P2_6 */ + scu.PPS_OUT = (P2_5); /* GPIO5[5] on P2_5 */ + + scu.P2_CTRL0_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.P2_CTRL1_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.P1_CTRL0_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.P1_CTRL1_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.P1_CTRL2_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.CLKIN_CTRL_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.AA_EN_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.TRIGGER_IN_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.TRIGGER_OUT_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.PPS_OUT_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); +#endif + + /* HackRF One r9 */ +#if defined(HACKRF_ONE) + scu.H1R9_CLKIN_EN = P6_7; /* GPIO5[15] on P6_7 */ + scu.H1R9_CLKOUT_EN = P1_2; /* GPIO0[9] on P1_2 = has boot pull-down; */ + scu.H1R9_MCU_CLK_EN = P1_1; /* GPIO0[8] on P1_1 = has boot pull-up; */ + scu.H1R9_RX = P2_7; /* GPIO0[7] on P4_4 = has boot pull-up; */ + scu.H1R9_NO_ANT_PWR = P4_4; /* GPIO2[4] on P4_4 */ + scu.H1R9_EN1V8 = P5_0; /* GPIO2[9] on P5_0 */ + scu.H1R9_NO_VAA_EN = P6_10; /* GPIO3[6] on P6_10 */ + scu.H1R9_TRIGGER_EN = P2_5; /* GPIO5[5] on P2_5 */ +#endif + + /* Miscellaneous */ + scu.PINMUX_PP_D0 = (P7_0); /* GPIO3[8] */ + scu.PINMUX_PP_D1 = (P7_1); /* GPIO3[9] */ + scu.PINMUX_PP_D2 = (P7_2); /* GPIO3[10] */ + scu.PINMUX_PP_D3 = (P7_3); /* GPIO3[11] */ + scu.PINMUX_PP_D4 = (P7_4); /* GPIO3[12] */ + scu.PINMUX_PP_D5 = (P7_5); /* GPIO3[13] */ + scu.PINMUX_PP_D6 = (P7_6); /* GPIO3[14] */ + scu.PINMUX_PP_D7 = (P7_7); /* GPIO3[15] */ + + /* TODO add other Pins */ + + scu.PINMUX_GPIO3_8 = (P7_0); /* GPIO3[8] */ + scu.PINMUX_GPIO3_9 = (P7_1); /* GPIO3[9] */ + scu.PINMUX_GPIO3_10 = (P7_2); /* GPIO3[10] */ + scu.PINMUX_GPIO3_11 = (P7_3); /* GPIO3[11] */ + scu.PINMUX_GPIO3_12 = (P7_4); /* GPIO3[12] */ + scu.PINMUX_GPIO3_13 = (P7_5); /* GPIO3[13] */ + scu.PINMUX_GPIO3_14 = (P7_6); /* GPIO3[14] */ + scu.PINMUX_GPIO3_15 = (P7_7); /* GPIO3[15] */ + + scu.PINMUX_PP_TDO = (P1_5); /* GPIO1[8] */ + scu.PINMUX_SD_POW = (P1_5); /* GPIO1[8] */ + scu.PINMUX_SD_CMD = (P1_6); /* GPIO1[9] */ + scu.PINMUX_PP_TMS = (P1_8); /* GPIO1[1] */ + scu.PINMUX_SD_VOLT0 = (P1_8); /* GPIO1[1] */ + scu.PINMUX_SD_DAT0 = (P1_9); /* GPIO1[2] */ + scu.PINMUX_SD_DAT1 = (P1_10); /* GPIO1[3] */ + scu.PINMUX_SD_DAT2 = (P1_11); /* GPIO1[4] */ + scu.PINMUX_SD_DAT3 = (P1_12); /* GPIO1[5] */ + scu.PINMUX_SD_CD = (P1_13); /* GPIO1[6] */ + + scu.PINMUX_PP_IO_STBX = (P2_0); /* GPIO5[0] */ + scu.PINMUX_PP_ADDR = (P2_1); /* GPIO5[1] */ + scu.PINMUX_U0_TXD = (P2_0); /* GPIO5[0] */ + scu.PINMUX_U0_RXD = (P2_1); /* GPIO5[1] */ + + scu.PINMUX_ISP = (P2_7); /* GPIO0[7] */ + + scu.PINMUX_GP_CLKIN = (P4_7); + + _platform_scu = &scu; + + return _platform_scu; +} + +// clang-format on diff --git a/firmware/common/platform_scu.h b/firmware/common/platform_scu.h new file mode 100644 index 00000000..fd4bae49 --- /dev/null +++ b/firmware/common/platform_scu.h @@ -0,0 +1,309 @@ +/* + * Copyright 2012-2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __PLATFORM_SCU_H +#define __PLATFORM_SCU_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "platform_detect.h" + +/* + * SCU PinMux + */ + +typedef struct { + /* LED PinMux */ + scu_grp_pin_t PINMUX_LED1; + scu_grp_pin_t PINMUX_LED2; + scu_grp_pin_t PINMUX_LED3; +#if defined(RAD1O) || defined(PRALINE) + scu_grp_pin_t PINMUX_LED4; +#endif + + /* Power Supply PinMux */ + scu_grp_pin_t PINMUX_EN1V8; + scu_grp_pin_t PINMUX_EN1V2; +#if defined(PRALINE) + scu_grp_pin_t PINMUX_EN3V3_AUX_N; + scu_grp_pin_t PINMUX_EN3V3_OC_N; +#endif + + /* GPIO Input PinMux */ + scu_grp_pin_t PINMUX_BOOT0; + scu_grp_pin_t PINMUX_BOOT1; +#if !defined(HACKRF_ONE) + scu_grp_pin_t PINMUX_BOOT2; + scu_grp_pin_t PINMUX_BOOT3; +#endif + scu_grp_pin_t PINMUX_PP_LCD_TE; + scu_grp_pin_t PINMUX_PP_LCD_RDX; + scu_grp_pin_t PINMUX_PP_UNUSED; + scu_grp_pin_t PINMUX_PP_LCD_WRX; + scu_grp_pin_t PINMUX_PP_DIR; + + /* USB peripheral */ +#if defined(JAWBREAKER) + scu_grp_pin_t PINMUX_USB_LED0; + scu_grp_pin_t PINMUX_USB_LED1; +#endif + + /* SSP1 Peripheral PinMux */ + scu_grp_pin_t SSP1_CIPO; + scu_grp_pin_t SSP1_COPI; + scu_grp_pin_t SSP1_SCK; + scu_grp_pin_t SSP1_CS; + + /* CPLD JTAG interface */ +#if defined(PRALINE) + scu_grp_pin_t PINMUX_FPGA_CRESET; + scu_grp_pin_t PINMUX_FPGA_CDONE; + scu_grp_pin_t PINMUX_FPGA_SPI_CS; +#endif + scu_grp_pin_t PINMUX_CPLD_TDO; + scu_grp_pin_t PINMUX_CPLD_TCK; + scu_grp_pin_t PINMUX_CPLD_TMS; + scu_grp_pin_t PINMUX_CPLD_TDI; + + /* CPLD SGPIO interface */ + scu_grp_pin_t PINMUX_SGPIO0; + scu_grp_pin_t PINMUX_SGPIO1; + scu_grp_pin_t PINMUX_SGPIO2; + scu_grp_pin_t PINMUX_SGPIO3; + scu_grp_pin_t PINMUX_SGPIO4; + scu_grp_pin_t PINMUX_SGPIO5; + scu_grp_pin_t PINMUX_SGPIO6; + scu_grp_pin_t PINMUX_SGPIO7; + scu_grp_pin_t PINMUX_SGPIO8; + scu_grp_pin_t PINMUX_SGPIO9; + scu_grp_pin_t PINMUX_SGPIO10; + scu_grp_pin_t PINMUX_SGPIO11; + scu_grp_pin_t PINMUX_SGPIO12; + scu_grp_pin_t PINMUX_SGPIO14; + scu_grp_pin_t PINMUX_SGPIO15; + scu_grp_pin_t PINMUX_SGPIO0_PINCFG; + scu_grp_pin_t PINMUX_SGPIO1_PINCFG; + scu_grp_pin_t PINMUX_SGPIO2_PINCFG; + scu_grp_pin_t PINMUX_SGPIO3_PINCFG; + scu_grp_pin_t PINMUX_SGPIO4_PINCFG; + scu_grp_pin_t PINMUX_SGPIO5_PINCFG; + scu_grp_pin_t PINMUX_SGPIO6_PINCFG; + scu_grp_pin_t PINMUX_SGPIO7_PINCFG; + scu_grp_pin_t PINMUX_SGPIO8_PINCFG; + scu_grp_pin_t PINMUX_SGPIO9_PINCFG; + scu_grp_pin_t PINMUX_SGPIO10_PINCFG; + scu_grp_pin_t PINMUX_SGPIO11_PINCFG; + scu_grp_pin_t PINMUX_SGPIO12_PINCFG; + scu_grp_pin_t PINMUX_SGPIO14_PINCFG; + scu_grp_pin_t PINMUX_SGPIO15_PINCFG; + scu_grp_pin_t TRIGGER_EN; + + /* MAX283x GPIO (XCVR_CTL) PinMux */ + scu_grp_pin_t XCVR_RXHP; // RAD1O, PRALINE + scu_grp_pin_t XCVR_B6; // RAD1O + scu_grp_pin_t XCVR_B7; // RAD1O + scu_grp_pin_t XCVR_ENABLE; // PRALINE, HACKRF_ONE + scu_grp_pin_t XCVR_RXENABLE; // PRALINE, HACKRF_ONE + scu_grp_pin_t XCVR_CS; // PRALINE, HACKRF_ONE + scu_grp_pin_t XCVR_LD; // PRALINE + uint32_t XCVR_ENABLE_PINCFG; // PRALINE, HACKRF_ONE + uint32_t XCVR_RXENABLE_PINCFG; // PRALINE, HACKRF_ONE + uint32_t XCVR_CS_PINCFG; // PRALINE, HACKRF_ONE + uint32_t XCVR_RXHP_PINCFG; // PRALINE + uint32_t XCVR_LD_PINCFG; // PRALINE + scu_grp_pin_t XCVR_TXENABLE; // HACKRF_ONE + uint32_t XCVR_TXENABLE_PINCFG; // HACKRF_ONE + + /* MAX5864 SPI chip select (AD_CS) GPIO PinMux */ + scu_grp_pin_t AD_CS; + scu_grp_pin_t AD_CS_PINCFG; + + /* RFFC5071 GPIO serial interface PinMux */ + scu_grp_pin_t MIXER_ENX; + scu_grp_pin_t MIXER_SCLK; + scu_grp_pin_t MIXER_SDATA; + scu_grp_pin_t MIXER_RESETX; + uint32_t MIXER_SCLK_PINCFG; + uint32_t MIXER_SDATA_PINCFG; +#if defined(PRALINE) + scu_grp_pin_t MIXER_LD; + uint32_t MIXER_LD_PINCFG; +#elif defined(RAD1O) + scu_grp_pin_t VCO_CE; + scu_grp_pin_t VCO_SCLK; + scu_grp_pin_t VCO_SDATA; + scu_grp_pin_t VCO_LE; + scu_grp_pin_t VCO_MUX; + scu_grp_pin_t MIXER_EN; + scu_grp_pin_t SYNT_RFOUT_EN; +#endif + + /* RF LDO control */ +#if defined(JAWBREAKER) + scu_grp_pin_t RF_LDO_ENABLE; +#endif + + /* RF supply (VAA) control */ +#if defined(PRALINE) || defined(HACKRF_ONE) + scu_grp_pin_t NO_VAA_ENABLE; +#elif defined(RAD1O) + scu_grp_pin_t VAA_ENABLE; +#endif + + /* SPI flash */ + scu_grp_pin_t SSP0_CIPO; + scu_grp_pin_t SSP0_COPI; + scu_grp_pin_t SSP0_SCK; + scu_grp_pin_t SSP0_CS; + scu_grp_pin_t FLASH_HOLD; + scu_grp_pin_t FLASH_WP; + + /* RF switch control */ +#if defined(PRALINE) + scu_grp_pin_t TX_EN; + scu_grp_pin_t MIX_EN_N; + scu_grp_pin_t MIX_EN_N_R1_0; + scu_grp_pin_t LPF_EN; + scu_grp_pin_t RF_AMP_EN; + scu_grp_pin_t ANT_BIAS_EN_N; + scu_grp_pin_t ANT_BIAS_OC_N; +#elif defined(HACKRF_ONE) + scu_grp_pin_t HP; + scu_grp_pin_t LP; + scu_grp_pin_t TX_MIX_BP; + scu_grp_pin_t NO_MIX_BYPASS; + scu_grp_pin_t RX_MIX_BP; + scu_grp_pin_t TX_AMP; + scu_grp_pin_t TX; + scu_grp_pin_t MIX_BYPASS; + scu_grp_pin_t RX; + scu_grp_pin_t NO_TX_AMP_PWR; + scu_grp_pin_t AMP_BYPASS; + scu_grp_pin_t RX_AMP; + scu_grp_pin_t NO_RX_AMP_PWR; +#elif defined(RAD1O) + scu_grp_pin_t BY_AMP; + scu_grp_pin_t BY_AMP_N; + scu_grp_pin_t TX_RX; + scu_grp_pin_t TX_RX_N; + scu_grp_pin_t BY_MIX; + scu_grp_pin_t BY_MIX_N; + scu_grp_pin_t LOW_HIGH_FILT; + scu_grp_pin_t LOW_HIGH_FILT_N; + scu_grp_pin_t TX_AMP; + scu_grp_pin_t RX_LNA; +#endif + + /* Praline */ +#if defined(PRALINE) + scu_grp_pin_t P2_CTRL0; + scu_grp_pin_t P2_CTRL1; + scu_grp_pin_t P1_CTRL0; + scu_grp_pin_t P1_CTRL1; + scu_grp_pin_t P1_CTRL2; + scu_grp_pin_t CLKIN_CTRL; + scu_grp_pin_t AA_EN; + scu_grp_pin_t TRIGGER_IN; + scu_grp_pin_t TRIGGER_OUT; + scu_grp_pin_t PPS_OUT; + + scu_grp_pin_t P2_CTRL0_PINCFG; + scu_grp_pin_t P2_CTRL1_PINCFG; + scu_grp_pin_t P1_CTRL0_PINCFG; + scu_grp_pin_t P1_CTRL1_PINCFG; + scu_grp_pin_t P1_CTRL2_PINCFG; + scu_grp_pin_t CLKIN_CTRL_PINCFG; + scu_grp_pin_t AA_EN_PINCFG; + scu_grp_pin_t TRIGGER_IN_PINCFG; + scu_grp_pin_t TRIGGER_OUT_PINCFG; + scu_grp_pin_t PPS_OUT_PINCFG; +#endif + + /* HackRF One r9 */ +#if defined(HACKRF_ONE) + scu_grp_pin_t H1R9_CLKIN_EN; + scu_grp_pin_t H1R9_CLKOUT_EN; + scu_grp_pin_t H1R9_MCU_CLK_EN; + scu_grp_pin_t H1R9_RX; + scu_grp_pin_t H1R9_NO_ANT_PWR; + scu_grp_pin_t H1R9_EN1V8; + scu_grp_pin_t H1R9_NO_VAA_EN; + scu_grp_pin_t H1R9_TRIGGER_EN; +#endif + + /* Miscellaneous */ + scu_grp_pin_t PINMUX_PP_D0; + scu_grp_pin_t PINMUX_PP_D1; + scu_grp_pin_t PINMUX_PP_D2; + scu_grp_pin_t PINMUX_PP_D3; + scu_grp_pin_t PINMUX_PP_D4; + scu_grp_pin_t PINMUX_PP_D5; + scu_grp_pin_t PINMUX_PP_D6; + scu_grp_pin_t PINMUX_PP_D7; + + /* TODO add other Pins */ + + scu_grp_pin_t PINMUX_GPIO3_8; + scu_grp_pin_t PINMUX_GPIO3_9; + scu_grp_pin_t PINMUX_GPIO3_10; + scu_grp_pin_t PINMUX_GPIO3_11; + scu_grp_pin_t PINMUX_GPIO3_12; + scu_grp_pin_t PINMUX_GPIO3_13; + scu_grp_pin_t PINMUX_GPIO3_14; + scu_grp_pin_t PINMUX_GPIO3_15; + + scu_grp_pin_t PINMUX_PP_TDO; + scu_grp_pin_t PINMUX_SD_POW; + scu_grp_pin_t PINMUX_SD_CMD; + scu_grp_pin_t PINMUX_PP_TMS; + scu_grp_pin_t PINMUX_SD_VOLT0; + scu_grp_pin_t PINMUX_SD_DAT0; + scu_grp_pin_t PINMUX_SD_DAT1; + scu_grp_pin_t PINMUX_SD_DAT2; + scu_grp_pin_t PINMUX_SD_DAT3; + scu_grp_pin_t PINMUX_SD_CD; + + scu_grp_pin_t PINMUX_PP_IO_STBX; + scu_grp_pin_t PINMUX_PP_ADDR; + scu_grp_pin_t PINMUX_U0_TXD; + scu_grp_pin_t PINMUX_U0_RXD; + + scu_grp_pin_t PINMUX_ISP; + + scu_grp_pin_t PINMUX_GP_CLKIN; +} platform_scu_t; + +// Detects and returns the global platform scu instance of the active board id and revision. +const platform_scu_t* platform_scu(void); + +// Platform detection needs these for error indication. +#define SCU_PINMUX_LED1 (P4_1) /* GPIO2[1] on P4_1 */ +#define SCU_PINMUX_LED2 (P4_2) /* GPIO2[2] on P4_2 */ +#define SCU_PINMUX_LED3 (P6_12) /* GPIO2[8] on P6_12 */ + +#ifdef __cplusplus +} +#endif + +#endif /* __PLATFORM_SCU_H */ diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index fc9d128c..1c6b7d6d 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -186,6 +186,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/hackrf_ui.c ${PATH_HACKRF_FIRMWARE_COMMON}/platform_detect.c ${PATH_HACKRF_FIRMWARE_COMMON}/platform_gpio.c + ${PATH_HACKRF_FIRMWARE_COMMON}/platform_scu.c ${PATH_HACKRF_FIRMWARE_COMMON}/firmware_info.c ${PATH_HACKRF_FIRMWARE_COMMON}/clkin.c ${PATH_HACKRF_FIRMWARE_COMMON}/gpdma.c From ce5cd7b0526028bfee5210a8402090ebbe0fd281 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Sat, 7 Mar 2026 10:44:34 +0000 Subject: [PATCH 046/238] firmware: replace static gpio & scu definitions --- firmware/common/hackrf_core.c | 581 +++++++++-------------- firmware/common/hackrf_core.h | 347 +------------- firmware/common/ice40_spi.c | 16 +- firmware/common/max2831_target.c | 21 +- firmware/common/max2837_target.c | 21 +- firmware/common/max2839_target.c | 19 +- firmware/common/max283x.c | 39 +- firmware/common/max2871.c | 16 +- firmware/common/max5864_target.c | 13 +- firmware/common/mixer.c | 100 ++-- firmware/common/mixer.h | 4 +- firmware/common/operacake.c | 14 +- firmware/common/platform_gpio.h | 4 + firmware/common/portapack.c | 62 +-- firmware/common/rf_path.c | 92 ++-- firmware/common/rf_path.h | 2 + firmware/common/rffc5071.c | 5 +- firmware/common/rffc5071_spi.c | 12 +- firmware/common/sgpio.c | 40 +- firmware/common/si5351c.c | 55 ++- firmware/common/w25q80bv_target.c | 17 +- firmware/hackrf_usb/usb_api_board_info.c | 11 +- 22 files changed, 497 insertions(+), 994 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index d4ee8433..365d7926 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -24,24 +24,17 @@ #include "hackrf_core.h" #include "hackrf_ui.h" #include "delay.h" -#include "sgpio.h" -#include "si5351c.h" -#include "spi_ssp.h" #include "max283x.h" -#include "max5864.h" #include "max5864_target.h" -#include "w25q80bv.h" #include "w25q80bv_target.h" -#include "i2c_bus.h" #include "i2c_lpc.h" -#include "cpld_jtag.h" #include "ice40_spi.h" #include "platform_detect.h" +#include "platform_gpio.h" +#include "platform_scu.h" #include "clkin.h" #include #include -#include -#include #if (defined HACKRF_ONE || defined PRALINE) #include "portapack.h" @@ -49,152 +42,6 @@ #include "gpio_lpc.h" -/* GPIO Output PinMux */ -static struct gpio gpio_led[] = { - GPIO(2, 1), - GPIO(2, 2), - GPIO(2, 8), -#ifdef RAD1O - GPIO(5, 26), -#endif -#ifdef PRALINE - GPIO(4, 6), -#endif -}; - -// clang-format off -#ifndef PRALINE -static struct gpio gpio_1v8_enable = GPIO(3, 6); -#else -static struct gpio gpio_1v2_enable = GPIO(4, 7); -static struct gpio gpio_3v3aux_enable_n = GPIO(5, 15); -#endif - -/* MAX283x GPIO (XCVR_CTL / CS_XCVR) PinMux */ -#ifdef PRALINE -static struct gpio gpio_max283x_select = GPIO(6, 28); -#else -static struct gpio gpio_max283x_select = GPIO(0, 15); -#endif - -/* MAX5864 SPI chip select (AD_CS / CS_AD) GPIO PinMux */ -#ifdef PRALINE -static struct gpio gpio_max5864_select = GPIO(6, 30); -#else -static struct gpio gpio_max5864_select = GPIO(2, 7); -#endif - -/* RFFC5071 GPIO serial interface PinMux */ -// #ifdef RAD1O -// static struct gpio gpio_rffc5072_select = GPIO(2, 13); -// static struct gpio gpio_rffc5072_clock = GPIO(5, 6); -// static struct gpio gpio_rffc5072_data = GPIO(3, 3); -// static struct gpio gpio_rffc5072_reset = GPIO(2, 14); -// #endif - -/* RF supply (VAA) control */ -#ifdef HACKRF_ONE -static struct gpio gpio_vaa_disable = GPIO(2, 9); -#endif -#ifdef PRALINE -static struct gpio gpio_vaa_disable = GPIO(4, 1); -#endif -#ifdef RAD1O -static struct gpio gpio_vaa_enable = GPIO(2, 9); -#endif - -static struct gpio gpio_w25q80bv_hold = GPIO(1, 14); -static struct gpio gpio_w25q80bv_wp = GPIO(1, 15); -static struct gpio gpio_w25q80bv_select = GPIO(5, 11); - -/* RF switch control */ -#ifdef HACKRF_ONE -static struct gpio gpio_hp = GPIO(2, 0); -static struct gpio gpio_lp = GPIO(2, 10); -static struct gpio gpio_tx_mix_bp = GPIO(2, 11); -static struct gpio gpio_no_mix_bypass = GPIO(1, 0); -static struct gpio gpio_rx_mix_bp = GPIO(2, 12); -static struct gpio gpio_tx_amp = GPIO(2, 15); -static struct gpio gpio_tx = GPIO(5, 15); -static struct gpio gpio_mix_bypass = GPIO(5, 16); -static struct gpio gpio_rx = GPIO(5, 5); -static struct gpio gpio_no_tx_amp_pwr = GPIO(3, 5); -static struct gpio gpio_amp_bypass = GPIO(0, 14); -static struct gpio gpio_rx_amp = GPIO(1, 11); -static struct gpio gpio_no_rx_amp_pwr = GPIO(1, 12); -#endif -#ifdef RAD1O -static struct gpio gpio_tx_rx_n = GPIO(1, 11); -static struct gpio gpio_tx_rx = GPIO(0, 14); -static struct gpio gpio_by_mix = GPIO(1, 12); -static struct gpio gpio_by_mix_n = GPIO(2, 10); -static struct gpio gpio_by_amp = GPIO(1, 0); -static struct gpio gpio_by_amp_n = GPIO(5, 5); -static struct gpio gpio_mixer_en = GPIO(5, 16); -static struct gpio gpio_low_high_filt = GPIO(2, 11); -static struct gpio gpio_low_high_filt_n = GPIO(2, 12); -static struct gpio gpio_tx_amp = GPIO(2, 15); -static struct gpio gpio_rx_lna = GPIO(5, 15); -#endif -#ifdef PRALINE -static struct gpio gpio_tx_en = GPIO(3, 4); -static struct gpio gpio_mix_en_n = GPIO(3, 2); -static struct gpio gpio_mix_en_n_r1_0 = GPIO(5, 6); -static struct gpio gpio_lpf_en = GPIO(4, 8); -static struct gpio gpio_rf_amp_en = GPIO(4, 9); -static struct gpio gpio_ant_bias_en_n = GPIO(1, 12); -#endif - -/* CPLD JTAG interface GPIO pins, FPGA config pins in Praline */ -static struct gpio gpio_cpld_tck = GPIO(3, 0); -#ifdef PRALINE -static struct gpio gpio_fpga_cfg_creset = GPIO(2, 11); -static struct gpio gpio_fpga_cfg_cdone = GPIO(5, 14); -static struct gpio gpio_fpga_cfg_spi_cs = GPIO(2, 10); -#else -static struct gpio gpio_cpld_tdo = GPIO(5, 18); -#if (defined HACKRF_ONE || defined RAD1O) -static struct gpio gpio_cpld_tms = GPIO(3, 4); -static struct gpio gpio_cpld_tdi = GPIO(3, 1); -#else -static struct gpio gpio_cpld_tms = GPIO(3, 1); -static struct gpio gpio_cpld_tdi = GPIO(3, 4); -#endif -#endif - -#if (defined HACKRF_ONE || defined PRALINE) -static struct gpio gpio_cpld_pp_tms = GPIO(1, 1); -static struct gpio gpio_cpld_pp_tdo = GPIO(1, 8); -#endif - -/* other CPLD interface GPIO pins */ -#ifndef PRALINE -static struct gpio gpio_trigger_enable = GPIO(5, 12); -#endif -static struct gpio gpio_q_invert = GPIO(0, 13); - -/* HackRF One r9 */ -#ifdef HACKRF_ONE -static struct gpio gpio_h1r9_rx = GPIO(0, 7); -static struct gpio gpio_h1r9_1v8_enable = GPIO(2, 9); -static struct gpio gpio_h1r9_vaa_disable = GPIO(3, 6); -static struct gpio gpio_h1r9_trigger_enable = GPIO(5, 5); -#endif - -#ifdef PRALINE -static struct gpio gpio_p2_ctrl0 = GPIO(7, 3); -static struct gpio gpio_p2_ctrl1 = GPIO(7, 4); -static struct gpio gpio_p1_ctrl0 = GPIO(0, 14); -static struct gpio gpio_p1_ctrl1 = GPIO(5, 16); -static struct gpio gpio_p1_ctrl2 = GPIO(3, 5); -static struct gpio gpio_clkin_ctrl = GPIO(0, 15); -static struct gpio gpio_aa_en = GPIO(1, 7); -static struct gpio gpio_trigger_in = GPIO(6, 26); -static struct gpio gpio_trigger_out = GPIO(5, 6); -static struct gpio gpio_pps_out = GPIO(5, 5); -#endif -// clang-format on - i2c_bus_t i2c0 = { .obj = (void*) I2C0_BASE, .start = i2c_lpc_start, @@ -222,6 +69,33 @@ si5351c_driver_t clock_gen = { .i2c_address = 0x60, }; +static ssp_config_t ssp_config_max283x = { + /* FIXME speed up once everything is working reliably */ + /* + // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + const uint8_t serial_clock_rate = 32; + const uint8_t clock_prescale_rate = 128; + */ + // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + .serial_clock_rate = 21, + .clock_prescale_rate = 2, +}; + +max283x_driver_t max283x = {}; + +static ssp_config_t ssp_config_max5864 = { + /* FIXME speed up once everything is working reliably */ + /* + // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + const uint8_t serial_clock_rate = 32; + const uint8_t clock_prescale_rate = 128; + */ + // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + .data_bits = SSP_DATA_8BITS, + .serial_clock_rate = 21, + .clock_prescale_rate = 2, +}; + spi_bus_t spi_bus_ssp1 = { .obj = (void*) SSP1_BASE, .config = &ssp_config_max5864, @@ -231,62 +105,15 @@ spi_bus_t spi_bus_ssp1 = { .transfer_gather = spi_ssp_transfer_gather, }; -#ifdef PRALINE -const ssp_config_t ssp_config_max283x = { - /* FIXME speed up once everything is working reliably */ - /* - // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - const uint8_t serial_clock_rate = 32; - const uint8_t clock_prescale_rate = 128; - */ - // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - .data_bits = SSP_DATA_9BITS, // send 2 words - .serial_clock_rate = 21, - .clock_prescale_rate = 2, - .gpio_select = &gpio_max283x_select, -}; -#else -const ssp_config_t ssp_config_max283x = { - /* FIXME speed up once everything is working reliably */ - /* - // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - const uint8_t serial_clock_rate = 32; - const uint8_t clock_prescale_rate = 128; - */ - // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - .data_bits = SSP_DATA_16BITS, - .serial_clock_rate = 21, - .clock_prescale_rate = 2, - .gpio_select = &gpio_max283x_select, -}; -#endif - -max283x_driver_t max283x = {}; - -const ssp_config_t ssp_config_max5864 = { - /* FIXME speed up once everything is working reliably */ - /* - // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - const uint8_t serial_clock_rate = 32; - const uint8_t clock_prescale_rate = 128; - */ - // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - .data_bits = SSP_DATA_8BITS, - .serial_clock_rate = 21, - .clock_prescale_rate = 2, - .gpio_select = &gpio_max5864_select, -}; - max5864_driver_t max5864 = { .bus = &spi_bus_ssp1, .target_init = max5864_target_init, }; -const ssp_config_t ssp_config_w25q80bv = { +ssp_config_t ssp_config_w25q80bv = { .data_bits = SSP_DATA_8BITS, .serial_clock_rate = 2, .clock_prescale_rate = 2, - .gpio_select = &gpio_w25q80bv_select, }; spi_bus_t spi_bus_ssp0 = { @@ -300,33 +127,23 @@ spi_bus_t spi_bus_ssp0 = { w25q80bv_driver_t spi_flash = { .bus = &spi_bus_ssp0, - .gpio_hold = &gpio_w25q80bv_hold, - .gpio_wp = &gpio_w25q80bv_wp, .target_init = w25q80bv_target_init, }; sgpio_config_t sgpio_config = { - .gpio_q_invert = &gpio_q_invert, -#ifndef PRALINE - .gpio_trigger_enable = &gpio_trigger_enable, -#endif .slice_mode_multislice = true, }; #ifdef PRALINE -const ssp_config_t ssp_config_ice40_fpga = { +ssp_config_t ssp_config_ice40_fpga = { .data_bits = SSP_DATA_8BITS, .spi_mode = SSP_CPOL_1_CPHA_1, .serial_clock_rate = 21, .clock_prescale_rate = 2, - .gpio_select = &gpio_fpga_cfg_spi_cs, }; ice40_spi_driver_t ice40 = { .bus = &spi_bus_ssp1, - .gpio_select = &gpio_fpga_cfg_spi_cs, - .gpio_creset = &gpio_fpga_cfg_creset, - .gpio_cdone = &gpio_fpga_cfg_cdone, }; fpga_driver_t fpga = { @@ -340,55 +157,9 @@ radio_t radio = { rf_path_t rf_path = { .switchctrl = 0, -#ifdef HACKRF_ONE - .gpio_hp = &gpio_hp, - .gpio_lp = &gpio_lp, - .gpio_tx_mix_bp = &gpio_tx_mix_bp, - .gpio_no_mix_bypass = &gpio_no_mix_bypass, - .gpio_rx_mix_bp = &gpio_rx_mix_bp, - .gpio_tx_amp = &gpio_tx_amp, - .gpio_tx = &gpio_tx, - .gpio_mix_bypass = &gpio_mix_bypass, - .gpio_rx = &gpio_rx, - .gpio_no_tx_amp_pwr = &gpio_no_tx_amp_pwr, - .gpio_amp_bypass = &gpio_amp_bypass, - .gpio_rx_amp = &gpio_rx_amp, - .gpio_no_rx_amp_pwr = &gpio_no_rx_amp_pwr, -#endif -#ifdef RAD1O - .gpio_tx_rx_n = &gpio_tx_rx_n, - .gpio_tx_rx = &gpio_tx_rx, - .gpio_by_mix = &gpio_by_mix, - .gpio_by_mix_n = &gpio_by_mix_n, - .gpio_by_amp = &gpio_by_amp, - .gpio_by_amp_n = &gpio_by_amp_n, - .gpio_mixer_en = &gpio_mixer_en, - .gpio_low_high_filt = &gpio_low_high_filt, - .gpio_low_high_filt_n = &gpio_low_high_filt_n, - .gpio_tx_amp = &gpio_tx_amp, - .gpio_rx_lna = &gpio_rx_lna, -#endif -#ifdef PRALINE - .gpio_tx_en = &gpio_tx_en, - .gpio_mix_en_n = &gpio_mix_en_n, - .gpio_lpf_en = &gpio_lpf_en, - .gpio_rf_amp_en = &gpio_rf_amp_en, - .gpio_ant_bias_en_n = &gpio_ant_bias_en_n, -#endif }; -jtag_gpio_t jtag_gpio_cpld = { - .gpio_tck = &gpio_cpld_tck, -#ifndef PRALINE - .gpio_tms = &gpio_cpld_tms, - .gpio_tdi = &gpio_cpld_tdi, - .gpio_tdo = &gpio_cpld_tdo, -#endif -#if (defined HACKRF_ONE || defined PRALINE) - .gpio_pp_tms = &gpio_cpld_pp_tms, - .gpio_pp_tdo = &gpio_cpld_pp_tdo, -#endif -}; +jtag_gpio_t jtag_gpio_cpld = {}; jtag_t jtag_cpld = { .gpio = &jtag_gpio_cpld, @@ -892,6 +663,9 @@ void ssp1_set_mode_ice40(void) void pin_shutdown(void) { + const platform_gpio_t* gpio = platform_gpio(); + const platform_scu_t* scu = platform_scu(); + /* Configure all GPIO as Input (safe state) */ gpio_init(); @@ -910,50 +684,50 @@ void pin_shutdown(void) * LPC43xx pull-up and pull-down resistors are approximately 53K. */ #if (defined HACKRF_ONE || defined PRALINE) - scu_pinmux(SCU_PINMUX_PP_TMS, SCU_GPIO_PUP | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_PINMUX_PP_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_PP_TMS, SCU_GPIO_PUP | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_PP_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); #endif - scu_pinmux(SCU_PINMUX_CPLD_TCK, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_CPLD_TCK, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); #ifndef PRALINE - scu_pinmux(SCU_PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_PINMUX_CPLD_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); + scu_pinmux(scu->PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_CPLD_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); #endif /* Configure SCU Pin Mux as GPIO */ - scu_pinmux(SCU_PINMUX_LED1, SCU_GPIO_NOPULL); - scu_pinmux(SCU_PINMUX_LED2, SCU_GPIO_NOPULL); - scu_pinmux(SCU_PINMUX_LED3, SCU_GPIO_NOPULL); + scu_pinmux(scu->PINMUX_LED1, SCU_GPIO_NOPULL); + scu_pinmux(scu->PINMUX_LED2, SCU_GPIO_NOPULL); + scu_pinmux(scu->PINMUX_LED3, SCU_GPIO_NOPULL); #ifdef RAD1O - scu_pinmux(SCU_PINMUX_LED4, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION4); + scu_pinmux(scu->PINMUX_LED4, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION4); #endif #ifdef PRALINE - scu_pinmux(SCU_PINMUX_LED4, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_LED4, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); #endif /* Configure USB indicators */ #ifdef JAWBREAKER - scu_pinmux(SCU_PINMUX_USB_LED0, SCU_CONF_FUNCTION3); - scu_pinmux(SCU_PINMUX_USB_LED1, SCU_CONF_FUNCTION3); + scu_pinmux(scu->PINMUX_USB_LED0, SCU_CONF_FUNCTION3); + scu_pinmux(scu->PINMUX_USB_LED1, SCU_CONF_FUNCTION3); #endif #ifdef PRALINE disable_1v2_power(); disable_3v3aux_power(); - gpio_output(&gpio_1v2_enable); - gpio_output(&gpio_3v3aux_enable_n); - scu_pinmux(SCU_PINMUX_EN1V2, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_PINMUX_EN3V3_AUX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + gpio_output(gpio->gpio_1v2_enable); + gpio_output(gpio->gpio_3v3aux_enable_n); + scu_pinmux(scu->PINMUX_EN1V2, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_EN3V3_AUX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); #else disable_1v8_power(); if (detected_platform() == BOARD_ID_HACKRF1_R9) { #ifdef HACKRF_ONE - gpio_output(&gpio_h1r9_1v8_enable); - scu_pinmux(SCU_H1R9_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + gpio_output(gpio->h1r9_1v8_enable); + scu_pinmux(scu->H1R9_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); #endif } else { - gpio_output(&gpio_1v8_enable); - scu_pinmux(SCU_PINMUX_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + gpio_output(gpio->gpio_1v8_enable); + scu_pinmux(scu->PINMUX_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); } #endif @@ -964,10 +738,10 @@ void pin_shutdown(void) /* Configure RF power supply (VAA) switch control signal as output */ if (detected_platform() == BOARD_ID_HACKRF1_R9) { #ifdef HACKRF_ONE - gpio_output(&gpio_h1r9_vaa_disable); + gpio_output(gpio->h1r9_vaa_disable); #endif } else { - gpio_output(&gpio_vaa_disable); + gpio_output(gpio->vaa_disable); } #endif @@ -976,51 +750,51 @@ void pin_shutdown(void) disable_rf_power(); /* Configure RF power supply (VAA) switch control signal as output */ - gpio_output(&gpio_vaa_enable); + gpio_output(gpio->vaa_enable); /* Disable unused clock outputs. They generate noise. */ scu_pinmux(CLK0, SCU_CLK_IN | SCU_CONF_FUNCTION7); scu_pinmux(CLK2, SCU_CLK_IN | SCU_CONF_FUNCTION7); - scu_pinmux(SCU_PINMUX_GPIO3_10, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_PINMUX_GPIO3_11, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_GPIO3_10, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_GPIO3_11, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); #endif #ifdef PRALINE - scu_pinmux(SCU_P2_CTRL0, SCU_P2_CTRL0_PINCFG); - scu_pinmux(SCU_P2_CTRL1, SCU_P2_CTRL1_PINCFG); - scu_pinmux(SCU_P1_CTRL0, SCU_P1_CTRL0_PINCFG); - scu_pinmux(SCU_P1_CTRL1, SCU_P1_CTRL1_PINCFG); - scu_pinmux(SCU_P1_CTRL2, SCU_P1_CTRL2_PINCFG); - scu_pinmux(SCU_CLKIN_CTRL, SCU_CLKIN_CTRL_PINCFG); - scu_pinmux(SCU_AA_EN, SCU_AA_EN_PINCFG); - scu_pinmux(SCU_TRIGGER_IN, SCU_TRIGGER_IN_PINCFG); - scu_pinmux(SCU_TRIGGER_OUT, SCU_TRIGGER_OUT_PINCFG); - scu_pinmux(SCU_PPS_OUT, SCU_PPS_OUT_PINCFG); - scu_pinmux(SCU_PINMUX_FPGA_CRESET, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_PINMUX_FPGA_CDONE, SCU_GPIO_PUP | SCU_CONF_FUNCTION4); - scu_pinmux(SCU_PINMUX_FPGA_SPI_CS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(scu->P2_CTRL0, scu->P2_CTRL0_PINCFG); + scu_pinmux(scu->P2_CTRL1, scu->P2_CTRL1_PINCFG); + scu_pinmux(scu->P1_CTRL0, scu->P1_CTRL0_PINCFG); + scu_pinmux(scu->P1_CTRL1, scu->P1_CTRL1_PINCFG); + scu_pinmux(scu->P1_CTRL2, scu->P1_CTRL2_PINCFG); + scu_pinmux(scu->CLKIN_CTRL, scu->CLKIN_CTRL_PINCFG); + scu_pinmux(scu->AA_EN, scu->AA_EN_PINCFG); + scu_pinmux(scu->TRIGGER_IN, scu->TRIGGER_IN_PINCFG); + scu_pinmux(scu->TRIGGER_OUT, scu->TRIGGER_OUT_PINCFG); + scu_pinmux(scu->PPS_OUT, scu->PPS_OUT_PINCFG); + scu_pinmux(scu->PINMUX_FPGA_CRESET, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_FPGA_CDONE, SCU_GPIO_PUP | SCU_CONF_FUNCTION4); + scu_pinmux(scu->PINMUX_FPGA_SPI_CS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); p2_ctrl_set(P2_SIGNAL_CLK3); p1_ctrl_set(P1_SIGNAL_CLKIN); narrowband_filter_set(0); clkin_ctrl_set(CLKIN_SIGNAL_P22); - gpio_output(&gpio_p2_ctrl0); - gpio_output(&gpio_p2_ctrl1); - gpio_output(&gpio_p1_ctrl0); - gpio_output(&gpio_p1_ctrl1); - gpio_output(&gpio_p1_ctrl2); - gpio_output(&gpio_clkin_ctrl); - gpio_output(&gpio_pps_out); - gpio_output(&gpio_aa_en); - gpio_input(&gpio_trigger_in); - gpio_input(&gpio_trigger_out); - gpio_clear(&gpio_fpga_cfg_spi_cs); - gpio_output(&gpio_fpga_cfg_spi_cs); - gpio_clear(&gpio_fpga_cfg_creset); - gpio_output(&gpio_fpga_cfg_creset); - gpio_input(&gpio_fpga_cfg_cdone); + gpio_output(gpio->p2_ctrl0); + gpio_output(gpio->p2_ctrl1); + gpio_output(gpio->p1_ctrl0); + gpio_output(gpio->p1_ctrl1); + gpio_output(gpio->p1_ctrl2); + gpio_output(gpio->clkin_ctrl); + gpio_output(gpio->pps_out); + gpio_output(gpio->aa_en); + gpio_input(gpio->trigger_in); + gpio_input(gpio->trigger_out); + gpio_clear(gpio->fpga_cfg_spi_cs); + gpio_output(gpio->fpga_cfg_spi_cs); + gpio_clear(gpio->fpga_cfg_creset); + gpio_output(gpio->fpga_cfg_creset); + gpio_input(gpio->fpga_cfg_cdone); #endif /* enable input on SCL and SDA pins */ @@ -1030,6 +804,9 @@ void pin_shutdown(void) /* Run after pin_shutdown() and prior to enabling power supplies. */ void pin_setup(void) { + const platform_gpio_t* gpio = platform_gpio(); + const platform_scu_t* scu = platform_scu(); + led_off(0); led_off(1); led_off(2); @@ -1037,35 +814,116 @@ void pin_setup(void) led_off(3); #endif - gpio_output(&gpio_led[0]); - gpio_output(&gpio_led[1]); - gpio_output(&gpio_led[2]); + gpio_output(gpio->led[0]); + gpio_output(gpio->led[1]); + gpio_output(gpio->led[2]); #if (defined RAD1O || defined PRALINE) - gpio_output(&gpio_led[3]); + gpio_output(gpio->led[3]); +#endif + + /* Configure drivers and driver pins */ + ssp_config_max283x.gpio_select = gpio->max283x_select; +#if defined(PRALINE) + ssp_config_max283x.data_bits = SSP_DATA_9BITS; // send 2 words +#else + ssp_config_max283x.data_bits = SSP_DATA_16BITS; +#endif + + ssp_config_max5864.gpio_select = gpio->max5864_select; + + ssp_config_w25q80bv.gpio_select = gpio->w25q80bv_select; + spi_flash.gpio_hold = gpio->w25q80bv_hold; + spi_flash.gpio_wp = gpio->w25q80bv_wp; + + sgpio_config.gpio_q_invert = gpio->q_invert; +#if !defined(PRALINE) + sgpio_config.gpio_trigger_enable = gpio->trigger_enable; +#endif + +#if defined(PRALINE) + ssp_config_ice40_fpga.gpio_select = gpio->fpga_cfg_spi_cs; + ice40.gpio_select = gpio->fpga_cfg_spi_cs; + ice40.gpio_creset = gpio->fpga_cfg_creset; + ice40.gpio_cdone = gpio->fpga_cfg_cdone; +#endif + + jtag_gpio_cpld.gpio_tck = gpio->cpld_tck; +#if !defined(PRALINE) + jtag_gpio_cpld.gpio_tms = gpio->cpld_tms; + jtag_gpio_cpld.gpio_tdi = gpio->cpld_tdi; + jtag_gpio_cpld.gpio_tdo = gpio->cpld_tdo; +#endif +#if defined(HACKRF_ONE) || defined(PRALINE) + jtag_gpio_cpld.gpio_pp_tms = gpio->cpld_pp_tms; + jtag_gpio_cpld.gpio_pp_tdo = gpio->cpld_pp_tdo; #endif ssp1_set_mode_max283x(); mixer_bus_setup(&mixer); -#ifdef HACKRF_ONE +#if defined(HACKRF_ONE) if (detected_platform() == BOARD_ID_HACKRF1_R9) { - rf_path.gpio_rx = &gpio_h1r9_rx; - sgpio_config.gpio_trigger_enable = &gpio_h1r9_trigger_enable; + rf_path.gpio_rx = gpio->h1r9_rx; + sgpio_config.gpio_trigger_enable = gpio->h1r9_trigger_enable; } #endif -#ifdef PRALINE + /* Configure RF path */ +#if defined(HACKRF_ONE) + rf_path = (rf_path_t){ + .switchctrl = 0, + .gpio_hp = gpio->hp, + .gpio_lp = gpio->lp, + .gpio_tx_mix_bp = gpio->tx_mix_bp, + .gpio_no_mix_bypass = gpio->no_mix_bypass, + .gpio_rx_mix_bp = gpio->rx_mix_bp, + .gpio_tx_amp = gpio->tx_amp, + .gpio_tx = gpio->tx, + .gpio_mix_bypass = gpio->mix_bypass, + .gpio_rx = gpio->rx, + .gpio_no_tx_amp_pwr = gpio->no_tx_amp_pwr, + .gpio_amp_bypass = gpio->amp_bypass, + .gpio_rx_amp = gpio->rx_amp, + .gpio_no_rx_amp_pwr = gpio->no_rx_amp_pwr, + }; + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + rf_path.gpio_rx = gpio->h1r9_rx; + rf_path.gpio_h1r9_no_ant_pwr = gpio->h1r9_no_ant_pwr; + } +#elif defined(RAD1O) + rf_path = (rf_path_t){ + .switchctrl = 0, + .gpio_tx_rx_n = gpio->tx_rx_n, + .gpio_tx_rx = gpio->tx_rx, + .gpio_by_mix = gpio->by_mix, + .gpio_by_mix_n = gpio->by_mix_n, + .gpio_by_amp = gpio->by_amp, + .gpio_by_amp_n = gpio->by_amp_n, + .gpio_mixer_en = gpio->mixer_en, + .gpio_low_high_filt = gpio->low_high_filt, + .gpio_low_high_filt_n = gpio->low_high_filt_n, + .gpio_tx_amp = gpio->tx_amp, + .gpio_rx_lna = gpio->rx_lna, + }; +#elif defined(PRALINE) + rf_path = (rf_path_t){ + .switchctrl = 0, + .gpio_tx_en = gpio->tx_en, + .gpio_mix_en_n = gpio->mix_en_n, + .gpio_lpf_en = gpio->lpf_en, + .gpio_rf_amp_en = gpio->rf_amp_en, + .gpio_ant_bias_en_n = gpio->ant_bias_en_n, + }; board_rev_t rev = detected_revision(); if ((rev == BOARD_REV_PRALINE_R1_0) || (rev == BOARD_REV_GSG_PRALINE_R1_0)) { - rf_path.gpio_mix_en_n = &gpio_mix_en_n_r1_0; + rf_path.gpio_mix_en_n = gpio->mix_en_n_r1_0; } #endif - rf_path_pin_setup(&rf_path); /* Configure external clock in */ - scu_pinmux(SCU_PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1); + scu_pinmux(scu->PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1); sgpio_configure_pin_functions(&sgpio_config); } @@ -1073,32 +931,32 @@ void pin_setup(void) #ifdef PRALINE void enable_1v2_power(void) { - gpio_set(&gpio_1v2_enable); + gpio_set(platform_gpio()->gpio_1v2_enable); } void disable_1v2_power(void) { - gpio_clear(&gpio_1v2_enable); + gpio_clear(platform_gpio()->gpio_1v2_enable); } void enable_3v3aux_power(void) { - gpio_clear(&gpio_3v3aux_enable_n); + gpio_clear(platform_gpio()->gpio_3v3aux_enable_n); } void disable_3v3aux_power(void) { - gpio_set(&gpio_3v3aux_enable_n); + gpio_set(platform_gpio()->gpio_3v3aux_enable_n); } #else void enable_1v8_power(void) { if (detected_platform() == BOARD_ID_HACKRF1_R9) { #ifdef HACKRF_ONE - gpio_set(&gpio_h1r9_1v8_enable); + gpio_set(platform_gpio()->h1r9_1v8_enable); #endif } else { - gpio_set(&gpio_1v8_enable); + gpio_set(platform_gpio()->gpio_1v8_enable); } } @@ -1106,10 +964,10 @@ void disable_1v8_power(void) { if (detected_platform() == BOARD_ID_HACKRF1_R9) { #ifdef HACKRF_ONE - gpio_clear(&gpio_h1r9_1v8_enable); + gpio_clear(platform_gpio()->h1r9_1v8_enable); #endif } else { - gpio_clear(&gpio_1v8_enable); + gpio_clear(platform_gpio()->gpio_1v8_enable); } } #endif @@ -1117,16 +975,17 @@ void disable_1v8_power(void) #ifdef HACKRF_ONE void enable_rf_power(void) { + const platform_gpio_t* gpio = platform_gpio(); uint32_t i; /* many short pulses to avoid one big voltage glitch */ for (i = 0; i < 1000; i++) { if (detected_platform() == BOARD_ID_HACKRF1_R9) { - gpio_set(&gpio_h1r9_vaa_disable); - gpio_clear(&gpio_h1r9_vaa_disable); + gpio_set(gpio->h1r9_vaa_disable); + gpio_clear(gpio->h1r9_vaa_disable); } else { - gpio_set(&gpio_vaa_disable); - gpio_clear(&gpio_vaa_disable); + gpio_set(gpio->vaa_disable); + gpio_clear(gpio->vaa_disable); } } } @@ -1134,9 +993,9 @@ void enable_rf_power(void) void disable_rf_power(void) { if (detected_platform() == BOARD_ID_HACKRF1_R9) { - gpio_set(&gpio_h1r9_vaa_disable); + gpio_set(platform_gpio()->h1r9_vaa_disable); } else { - gpio_set(&gpio_vaa_disable); + gpio_set(platform_gpio()->vaa_disable); } } #endif @@ -1144,7 +1003,7 @@ void disable_rf_power(void) #ifdef PRALINE void enable_rf_power(void) { - gpio_clear(&gpio_vaa_disable); + gpio_clear(platform_gpio()->vaa_disable); /* Let the voltage stabilize */ delay(1000000); @@ -1152,14 +1011,14 @@ void enable_rf_power(void) void disable_rf_power(void) { - gpio_set(&gpio_vaa_disable); + gpio_set(platform_gpio()->vaa_disable); } #endif #ifdef RAD1O void enable_rf_power(void) { - gpio_set(&gpio_vaa_enable); + gpio_set(platform_gpio()->vaa_enable); /* Let the voltage stabilize */ delay(1000000); @@ -1167,35 +1026,35 @@ void enable_rf_power(void) void disable_rf_power(void) { - gpio_clear(&gpio_vaa_enable); + gpio_clear(platform_gpio()->vaa_enable); } #endif #ifdef PRALINE void led_on(const led_t led) { - gpio_clear(&gpio_led[led]); + gpio_clear(platform_gpio()->led[led]); } void led_off(const led_t led) { - gpio_set(&gpio_led[led]); + gpio_set(platform_gpio()->led[led]); } #else void led_on(const led_t led) { - gpio_set(&gpio_led[led]); + gpio_set(platform_gpio()->led[led]); } void led_off(const led_t led) { - gpio_clear(&gpio_led[led]); + gpio_clear(platform_gpio()->led[led]); } #endif void led_toggle(const led_t led) { - gpio_toggle(&gpio_led[led]); + gpio_toggle(platform_gpio()->led[led]); } void set_leds(const uint8_t state) @@ -1206,9 +1065,9 @@ void set_leds(const uint8_t state) #endif for (int i = 0; i < num_leds; i++) { #ifdef PRALINE - gpio_write(&gpio_led[i], ((state >> i) & 1) == 0); + gpio_write(platform_gpio()->led[i], ((state >> i) & 1) == 0); #else - gpio_write(&gpio_led[i], ((state >> i) & 1) == 1); + gpio_write(platform_gpio()->led[i], ((state >> i) & 1) == 1); #endif } } @@ -1240,29 +1099,33 @@ void halt_and_flash(const uint32_t duration) #ifdef PRALINE void p1_ctrl_set(const p1_ctrl_signal_t signal) { - gpio_write(&gpio_p1_ctrl0, signal & 1); - gpio_write(&gpio_p1_ctrl1, (signal >> 1) & 1); - gpio_write(&gpio_p1_ctrl2, (signal >> 2) & 1); + const platform_gpio_t* gpio = platform_gpio(); + + gpio_write(gpio->p1_ctrl0, signal & 1); + gpio_write(gpio->p1_ctrl1, (signal >> 1) & 1); + gpio_write(gpio->p1_ctrl2, (signal >> 2) & 1); } void p2_ctrl_set(const p2_ctrl_signal_t signal) { - gpio_write(&gpio_p2_ctrl0, signal & 1); - gpio_write(&gpio_p2_ctrl1, (signal >> 1) & 1); + const platform_gpio_t* gpio = platform_gpio(); + + gpio_write(gpio->p2_ctrl0, signal & 1); + gpio_write(gpio->p2_ctrl1, (signal >> 1) & 1); } void clkin_ctrl_set(const clkin_signal_t signal) { - gpio_write(&gpio_clkin_ctrl, signal & 1); + gpio_write(platform_gpio()->clkin_ctrl, signal & 1); } void pps_out_set(const uint8_t value) { - gpio_write(&gpio_pps_out, value & 1); + gpio_write(platform_gpio()->pps_out, value & 1); } void narrowband_filter_set(const uint8_t value) { - gpio_write(&gpio_aa_en, value & 1); + gpio_write(platform_gpio()->aa_en, value & 1); } #endif diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index eea31df7..c9ca7dce 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -46,354 +46,11 @@ extern "C" { #include "fpga.h" #include "fixed_point.h" -/* - * SCU PinMux - */ - -/* GPIO Output PinMux */ -#define SCU_PINMUX_LED1 (P4_1) /* GPIO2[1] on P4_1 */ -#define SCU_PINMUX_LED2 (P4_2) /* GPIO2[2] on P4_2 */ -#define SCU_PINMUX_LED3 (P6_12) /* GPIO2[8] on P6_12 */ -#ifdef RAD1O - #define SCU_PINMUX_LED4 (PB_6) /* GPIO5[26] on PB_6 */ -#endif -#ifdef PRALINE - #define SCU_PINMUX_LED4 (P8_6) /* GPIO4[6] on P8_6 */ -#endif - -#define SCU_PINMUX_EN1V8 (P6_10) /* GPIO3[6] on P6_10 */ -#define SCU_PINMUX_EN1V2 (P8_7) /* GPIO4[7] on P8_7 */ -#ifdef PRALINE - #define SCU_PINMUX_EN3V3_AUX_N (P6_7) /* GPIO5[15] on P6_7 */ - #define SCU_PINMUX_EN3V3_OC_N (P6_11) /* GPIO3[7] on P6_11 */ -#endif - -/* GPIO Input PinMux */ -#define SCU_PINMUX_BOOT0 (P1_1) /* GPIO0[8] on P1_1 */ -#define SCU_PINMUX_BOOT1 (P1_2) /* GPIO0[9] on P1_2 */ -#ifndef HACKRF_ONE - #define SCU_PINMUX_BOOT2 (P2_8) /* GPIO5[7] on P2_8 */ - #define SCU_PINMUX_BOOT3 (P2_9) /* GPIO1[10] on P2_9 */ -#endif -#define SCU_PINMUX_PP_LCD_TE (P2_3) /* GPIO5[3] on P2_3 */ -#define SCU_PINMUX_PP_LCD_RDX (P2_4) /* GPIO5[4] on P2_4 */ -#define SCU_PINMUX_PP_UNUSED (P2_8) /* GPIO5[7] on P2_8 */ -#define SCU_PINMUX_PP_LCD_WRX (P2_9) /* GPIO1[10] on P2_9 */ -#define SCU_PINMUX_PP_DIR (P2_13) /* GPIO1[13] on P2_13 */ - -/* USB peripheral */ -#ifdef JAWBREAKER - #define SCU_PINMUX_USB_LED0 (P6_8) - #define SCU_PINMUX_USB_LED1 (P6_7) -#endif - -/* SSP1 Peripheral PinMux */ -#define SCU_SSP1_CIPO (P1_3) /* P1_3 */ -#define SCU_SSP1_COPI (P1_4) /* P1_4 */ -#define SCU_SSP1_SCK (P1_19) /* P1_19 */ -#define SCU_SSP1_CS (P1_20) /* P1_20 */ - -/* CPLD JTAG interface */ -#ifdef PRALINE - #define SCU_PINMUX_FPGA_CRESET (P5_2) /* GPIO2[11] on P5_2 */ - #define SCU_PINMUX_FPGA_CDONE (P4_10) /* GPIO5[14] */ - #define SCU_PINMUX_FPGA_SPI_CS (P5_1) /* GPIO2[10] */ -#endif -#define SCU_PINMUX_CPLD_TDO (P9_5) /* GPIO5[18] */ -#define SCU_PINMUX_CPLD_TCK (P6_1) /* GPIO3[ 0] */ -#if (defined HACKRF_ONE || defined RAD1O || defined PRALINE) - #define SCU_PINMUX_CPLD_TMS (P6_5) /* GPIO3[ 4] */ - #define SCU_PINMUX_CPLD_TDI (P6_2) /* GPIO3[ 1] */ -#else - #define SCU_PINMUX_CPLD_TMS (P6_2) /* GPIO3[ 1] */ - #define SCU_PINMUX_CPLD_TDI (P6_5) /* GPIO3[ 4] */ -#endif - -/* CPLD SGPIO interface */ -#ifdef PRALINE - #define SCU_PINMUX_SGPIO0 (P0_0) - #define SCU_PINMUX_SGPIO1 (P0_1) - #define SCU_PINMUX_SGPIO2 (P1_15) - #define SCU_PINMUX_SGPIO3 (P1_16) - #define SCU_PINMUX_SGPIO4 (P9_4) - #define SCU_PINMUX_SGPIO5 (P6_6) - #define SCU_PINMUX_SGPIO6 (P2_2) - #define SCU_PINMUX_SGPIO7 (P1_0) - #define SCU_PINMUX_SGPIO8 (P8_0) - #define SCU_PINMUX_SGPIO9 (P9_3) - #define SCU_PINMUX_SGPIO10 (P8_2) - #define SCU_PINMUX_SGPIO11 (P1_17) - #define SCU_PINMUX_SGPIO12 (P1_18) - #define SCU_PINMUX_SGPIO14 (P1_18) - #define SCU_PINMUX_SGPIO15 (P1_18) - - #define SCU_PINMUX_SGPIO0_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION3) - #define SCU_PINMUX_SGPIO1_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION3) - #define SCU_PINMUX_SGPIO2_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION2) - #define SCU_PINMUX_SGPIO3_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION2) - #define SCU_PINMUX_SGPIO4_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION6) - #define SCU_PINMUX_SGPIO5_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION2) - #define SCU_PINMUX_SGPIO6_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION0) - #define SCU_PINMUX_SGPIO7_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION6) - #define SCU_PINMUX_SGPIO8_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - #define SCU_PINMUX_SGPIO9_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION6) - #define SCU_PINMUX_SGPIO10_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - #define SCU_PINMUX_SGPIO11_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION6) - #define SCU_PINMUX_SGPIO12_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION0) - #define SCU_PINMUX_SGPIO14_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION0) - #define SCU_PINMUX_SGPIO15_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION0) - -#else - #define SCU_PINMUX_SGPIO0 (P0_0) - #define SCU_PINMUX_SGPIO1 (P0_1) - #define SCU_PINMUX_SGPIO2 (P1_15) - #define SCU_PINMUX_SGPIO3 (P1_16) - #define SCU_PINMUX_SGPIO4 (P6_3) - #define SCU_PINMUX_SGPIO5 (P6_6) - #define SCU_PINMUX_SGPIO6 (P2_2) - #define SCU_PINMUX_SGPIO7 (P1_0) - #if (defined JAWBREAKER || defined HACKRF_ONE || defined RAD1O) - #define SCU_PINMUX_SGPIO8 (P9_6) - #endif - #define SCU_PINMUX_SGPIO9 (P4_3) - #define SCU_PINMUX_SGPIO10 (P1_14) - #define SCU_PINMUX_SGPIO11 (P1_17) - #define SCU_PINMUX_SGPIO12 (P1_18) - #define SCU_PINMUX_SGPIO14 (P4_9) - #define SCU_PINMUX_SGPIO15 (P4_10) - - #define SCU_PINMUX_SGPIO0_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION3) - #define SCU_PINMUX_SGPIO1_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION3) - #define SCU_PINMUX_SGPIO2_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION2) - #define SCU_PINMUX_SGPIO3_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION2) - #define SCU_PINMUX_SGPIO4_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION2) - #define SCU_PINMUX_SGPIO5_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION2) - #define SCU_PINMUX_SGPIO6_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION0) - #define SCU_PINMUX_SGPIO7_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION6) - #define SCU_PINMUX_SGPIO8_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION6) - #define SCU_PINMUX_SGPIO9_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION7) - #define SCU_PINMUX_SGPIO10_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION6) - #define SCU_PINMUX_SGPIO11_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION6) - #define SCU_PINMUX_SGPIO12_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION0) - #define SCU_PINMUX_SGPIO14_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - #define SCU_PINMUX_SGPIO15_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - -#endif -#define SCU_TRIGGER_EN (P4_8) /* GPIO5[12] on P4_8 */ - -/* MAX2837 GPIO (XCVR_CTL) PinMux */ -#ifdef RAD1O - #define SCU_XCVR_RXHP (P8_1) /* GPIO[] on P8_1 */ - #define SCU_XCVR_B6 (P8_2) /* GPIO[] on P8_2 */ - #define SCU_XCVR_B7 (P9_3) /* GPIO[] on P8_3 */ -#endif - -#ifdef PRALINE - #define SCU_XCVR_ENABLE (PE_1) /* GPIO7[1] on PE_1 */ - #define SCU_XCVR_RXENABLE (PE_2) /* GPIO7[2] on PE_2 */ - #define SCU_XCVR_CS (PD_14) /* GPIO6[28] on PD_14 */ - #define SCU_XCVR_RXHP (PD_15) /* GPIO6[29] on PD_15 */ - #define SCU_XCVR_LD (P9_6) /* GPIO4[11] on P9_6 */ - - #define SCU_XCVR_ENABLE_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - #define SCU_XCVR_RXENABLE_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - #define SCU_XCVR_CS_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - #define SCU_XCVR_RXHP_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - #define SCU_XCVR_LD_PINCFG \ - (SCU_GPIO_FAST | SCU_CONF_FUNCTION0 | SCU_CONF_EPD_EN_PULLDOWN | \ - SCU_CONF_EPUN_DIS_PULLUP) -#else - #define SCU_XCVR_ENABLE (P4_6) /* GPIO2[6] on P4_6 */ - #define SCU_XCVR_RXENABLE (P4_5) /* GPIO2[5] on P4_5 */ - #define SCU_XCVR_TXENABLE (P4_4) /* GPIO2[4] on P4_4 */ - #define SCU_XCVR_CS (P1_20) /* GPIO0[15] on P1_20 */ - - #define SCU_XCVR_ENABLE_PINCFG (SCU_GPIO_FAST) - #define SCU_XCVR_RXENABLE_PINCFG (SCU_GPIO_FAST) - #define SCU_XCVR_TXENABLE_PINCFG (SCU_GPIO_FAST) - #define SCU_XCVR_CS_PINCFG (SCU_GPIO_FAST) -#endif - -/* MAX5864 SPI chip select (AD_CS) GPIO PinMux */ -#ifdef PRALINE - #define SCU_AD_CS (PD_16) /* GPIO6[30] on PD_16 */ - #define SCU_AD_CS_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) -#else - #define SCU_AD_CS (P5_7) /* GPIO2[7] on P5_7 */ - #define SCU_AD_CS_PINCFG (SCU_GPIO_FAST) -#endif - -/* RFFC5071 GPIO serial interface PinMux */ -#if (defined JAWBREAKER || defined HACKRF_ONE) - #define SCU_MIXER_ENX (P5_4) /* GPIO2[13] on P5_4 */ - #define SCU_MIXER_SCLK (P2_6) /* GPIO5[6] on P2_6 */ - #define SCU_MIXER_SDATA (P6_4) /* GPIO3[3] on P6_4 */ - #define SCU_MIXER_RESETX (P5_5) /* GPIO2[14] on P5_5 */ - - #define SCU_MIXER_SCLK_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - #define SCU_MIXER_SDATA_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION0) -#endif -#ifdef PRALINE - #define SCU_MIXER_ENX (P5_4) /* GPIO2[13] on P5_4 */ - #define SCU_MIXER_SCLK (P9_5) /* GPIO5[18] on P9_5 */ - #define SCU_MIXER_SDATA (P9_2) /* GPIO4[14] on P9_2 */ - #define SCU_MIXER_RESETX (P5_5) /* GPIO2[14] on P5_5 */ - #define SCU_MIXER_LD (PD_11) /* GPIO6[25] on PD_11 */ - - #define SCU_MIXER_SCLK_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - #define SCU_MIXER_SDATA_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION0) - #define SCU_MIXER_LD_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) -#endif -#ifdef RAD1O - #define SCU_VCO_CE (P5_4) /* GPIO2[13] on P5_4 */ - #define SCU_VCO_SCLK (P2_6) /* GPIO5[6] on P2_6 */ - #define SCU_VCO_SDATA (P6_4) /* GPIO3[3] on P6_4 */ - #define SCU_VCO_LE (P5_5) /* GPIO2[14] on P5_5 */ - #define SCU_VCO_MUX (PB_5) /* GPIO5[25] on PB_5 */ - #define SCU_MIXER_EN (P6_8) /* GPIO5[16] on P6_8 */ - #define SCU_SYNT_RFOUT_EN (P6_9) /* GPIO3[5] on P6_9 */ -#endif - -/* RF LDO control */ -#ifdef JAWBREAKER - #define SCU_RF_LDO_ENABLE (P5_0) /* GPIO2[9] on P5_0 */ -#endif - -/* RF supply (VAA) control */ -#ifdef HACKRF_ONE - #define SCU_NO_VAA_ENABLE (P5_0) /* GPIO2[9] on P5_0 */ -#endif -#ifdef PRALINE - #define SCU_NO_VAA_ENABLE (P8_1) /* GPIO4[1] on P8_1 */ -#endif -#ifdef RAD1O - #define SCU_VAA_ENABLE (P5_0) /* GPIO2[9] on P5_0 */ -#endif - -/* SPI flash */ -#define SCU_SSP0_CIPO (P3_6) -#define SCU_SSP0_COPI (P3_7) -#define SCU_SSP0_SCK (P3_3) -#define SCU_SSP0_CS (P3_8) /* GPIO5[11] on P3_8 */ -#define SCU_FLASH_HOLD (P3_4) /* GPIO1[14] on P3_4 */ -#define SCU_FLASH_WP (P3_5) /* GPIO1[15] on P3_5 */ - -/* RF switch control */ -#ifdef HACKRF_ONE - #define SCU_HP (P4_0) /* GPIO2[0] on P4_0 */ - #define SCU_LP (P5_1) /* GPIO2[10] on P5_1 */ - #define SCU_TX_MIX_BP (P5_2) /* GPIO2[11] on P5_2 */ - #define SCU_NO_MIX_BYPASS (P1_7) /* GPIO1[0] on P1_7 */ - #define SCU_RX_MIX_BP (P5_3) /* GPIO2[12] on P5_3 */ - #define SCU_TX_AMP (P5_6) /* GPIO2[15] on P5_6 */ - #define SCU_TX (P6_7) /* GPIO5[15] on P6_7 */ - #define SCU_MIX_BYPASS (P6_8) /* GPIO5[16] on P6_8 */ - #define SCU_RX (P2_5) /* GPIO5[5] on P2_5 */ - #define SCU_NO_TX_AMP_PWR (P6_9) /* GPIO3[5] on P6_9 */ - #define SCU_AMP_BYPASS (P2_10) /* GPIO0[14] on P2_10 */ - #define SCU_RX_AMP (P2_11) /* GPIO1[11] on P2_11 */ - #define SCU_NO_RX_AMP_PWR (P2_12) /* GPIO1[12] on P2_12 */ -#endif -#ifdef RAD1O - #define SCU_BY_AMP (P1_7) /* GPIO1[0] on P1_7 */ - #define SCU_BY_AMP_N (P2_5) /* GPIO5[5] on P2_5 */ - #define SCU_TX_RX (P2_10) /* GPIO0[14] on P2_10 */ - #define SCU_TX_RX_N (P2_11) /* GPIO1[11] on P2_11 */ - #define SCU_BY_MIX (P2_12) /* GPIO1[12] on P2_12 */ - #define SCU_BY_MIX_N (P5_1) /* GPIO2[10] on P5_1 */ - #define SCU_LOW_HIGH_FILT (P5_2) /* GPIO2[11] on P5_2 */ - #define SCU_LOW_HIGH_FILT_N (P5_3) /* GPIO2[12] on P5_3 */ - #define SCU_TX_AMP (P5_6) /* GPIO2[15] on P5_6 */ - #define SCU_RX_LNA (P6_7) /* GPIO5[15] on P6_7 */ -#endif -#ifdef PRALINE - #define SCU_TX_EN (P6_5) /* GPIO3[4] on P6_5 */ - #define SCU_MIX_EN_N (P6_3) /* GPIO3[2] on P6_3 */ - #define SCU_MIX_EN_N_R1_0 (P2_6) /* GPIO5[6] on P2_6 */ - #define SCU_LPF_EN (PA_1) /* GPIO4[8] on PA_1 */ - #define SCU_RF_AMP_EN (PA_2) /* GPIO4[9] on PA_2 */ - #define SCU_ANT_BIAS_EN_N (P2_12) /* GPIO1[12] on P2_12 */ - #define SCU_ANT_BIAS_OC_N (P2_11) /* GPIO1[11] on P2_11 */ -#endif - -#ifdef PRALINE - #define SCU_P2_CTRL0 (PE_3) /* GPIO7[3] on PE_3 */ - #define SCU_P2_CTRL1 (PE_4) /* GPIO7[4] on PE_4 */ - #define SCU_P1_CTRL0 (P2_10) /* GPIO0[14] on P2_10 */ - #define SCU_P1_CTRL1 (P6_8) /* GPIO5[16] on P6_8 */ - #define SCU_P1_CTRL2 (P6_9) /* GPIO3[5] on P6_9 */ - #define SCU_CLKIN_CTRL (P1_20) /* GPIO0[15] on P1_20 */ - #define SCU_AA_EN (P1_14) /* GPIO1[7] on P1_14 */ - #define SCU_TRIGGER_IN (PD_12) /* GPIO6[26] on PD_12 */ - #define SCU_TRIGGER_OUT (P2_6) /* GPIO5[6] on P2_6 */ - #define SCU_PPS_OUT (P2_5) /* GPIO5[5] on P2_5 */ - - #define SCU_P2_CTRL0_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - #define SCU_P2_CTRL1_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - #define SCU_P1_CTRL0_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION0) - #define SCU_P1_CTRL1_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - #define SCU_P1_CTRL2_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION0) - #define SCU_CLKIN_CTRL_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION0) - #define SCU_AA_EN_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION0) - #define SCU_TRIGGER_IN_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - #define SCU_TRIGGER_OUT_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - #define SCU_PPS_OUT_PINCFG (SCU_GPIO_FAST | SCU_CONF_FUNCTION4) - -#endif - -#define SCU_PINMUX_PP_D0 (P7_0) /* GPIO3[8] */ -#define SCU_PINMUX_PP_D1 (P7_1) /* GPIO3[9] */ -#define SCU_PINMUX_PP_D2 (P7_2) /* GPIO3[10] */ -#define SCU_PINMUX_PP_D3 (P7_3) /* GPIO3[11] */ -#define SCU_PINMUX_PP_D4 (P7_4) /* GPIO3[12] */ -#define SCU_PINMUX_PP_D5 (P7_5) /* GPIO3[13] */ -#define SCU_PINMUX_PP_D6 (P7_6) /* GPIO3[14] */ -#define SCU_PINMUX_PP_D7 (P7_7) /* GPIO3[15] */ -/* TODO add other Pins */ -#define SCU_PINMUX_GPIO3_8 (P7_0) /* GPIO3[8] */ -#define SCU_PINMUX_GPIO3_9 (P7_1) /* GPIO3[9] */ -#define SCU_PINMUX_GPIO3_10 (P7_2) /* GPIO3[10] */ -#define SCU_PINMUX_GPIO3_11 (P7_3) /* GPIO3[11] */ -#define SCU_PINMUX_GPIO3_12 (P7_4) /* GPIO3[12] */ -#define SCU_PINMUX_GPIO3_13 (P7_5) /* GPIO3[13] */ -#define SCU_PINMUX_GPIO3_14 (P7_6) /* GPIO3[14] */ -#define SCU_PINMUX_GPIO3_15 (P7_7) /* GPIO3[15] */ - -#define SCU_PINMUX_PP_TDO (P1_5) /* GPIO1[8] */ -#define SCU_PINMUX_SD_POW (P1_5) /* GPIO1[8] */ -#define SCU_PINMUX_SD_CMD (P1_6) /* GPIO1[9] */ -#define SCU_PINMUX_PP_TMS (P1_8) /* GPIO1[1] */ -#define SCU_PINMUX_SD_VOLT0 (P1_8) /* GPIO1[1] */ -#define SCU_PINMUX_SD_DAT0 (P1_9) /* GPIO1[2] */ -#define SCU_PINMUX_SD_DAT1 (P1_10) /* GPIO1[3] */ -#define SCU_PINMUX_SD_DAT2 (P1_11) /* GPIO1[4] */ -#define SCU_PINMUX_SD_DAT3 (P1_12) /* GPIO1[5] */ -#define SCU_PINMUX_SD_CD (P1_13) /* GPIO1[6] */ - -#define SCU_PINMUX_PP_IO_STBX (P2_0) /* GPIO5[0] */ -#define SCU_PINMUX_PP_ADDR (P2_1) /* GPIO5[1] */ -#define SCU_PINMUX_U0_TXD (P2_0) /* GPIO5[0] */ -#define SCU_PINMUX_U0_RXD (P2_1) /* GPIO5[1] */ - -#define SCU_PINMUX_ISP (P2_7) /* GPIO0[7] */ - -#define SCU_PINMUX_GP_CLKIN (P4_7) - -/* HackRF One r9 */ -#define SCU_H1R9_CLKIN_EN (P6_7) /* GPIO5[15] on P6_7 */ -#define SCU_H1R9_CLKOUT_EN (P1_2) /* GPIO0[9] on P1_2 (has boot pull-down) */ -#define SCU_H1R9_MCU_CLK_EN (P1_1) /* GPIO0[8] on P1_1 (has boot pull-up) */ -#define SCU_H1R9_RX (P2_7) /* GPIO0[7] on P4_4 (has boot pull-up) */ -#define SCU_H1R9_NO_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_TRIGGER_EN (P2_5) /* GPIO5[5] on P2_5 */ +#include "platform_scu.h" /* TODO: Hide these configurations */ extern si5351c_driver_t clock_gen; -extern const ssp_config_t ssp_config_w25q80bv; -extern const ssp_config_t ssp_config_max283x; -extern const ssp_config_t ssp_config_max5864; +extern ssp_config_t ssp_config_w25q80bv; #ifdef PRALINE extern ice40_spi_driver_t ice40; diff --git a/firmware/common/ice40_spi.c b/firmware/common/ice40_spi.c index 57abd73d..69491df0 100644 --- a/firmware/common/ice40_spi.c +++ b/firmware/common/ice40_spi.c @@ -21,20 +21,22 @@ #include "ice40_spi.h" -#include #include "hackrf_core.h" #include "lz4_buf.h" #include "delay.h" +#include "platform_scu.h" void ice40_spi_target_init(ice40_spi_driver_t* const drv) { + const platform_scu_t* scu = platform_scu(); + /* Configure SSP1 Peripheral and relevant FPGA pins. */ - scu_pinmux(SCU_SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); - scu_pinmux(SCU_PINMUX_FPGA_CRESET, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_PINMUX_FPGA_CDONE, SCU_GPIO_PUP | SCU_CONF_FUNCTION4); - scu_pinmux(SCU_PINMUX_FPGA_SPI_CS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(scu->SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(scu->SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(scu->SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); + scu_pinmux(scu->PINMUX_FPGA_CRESET, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_FPGA_CDONE, SCU_GPIO_PUP | SCU_CONF_FUNCTION4); + scu_pinmux(scu->PINMUX_FPGA_SPI_CS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); /* Configure GPIOs as inputs or outputs as needed. */ gpio_clear(drv->gpio_creset); diff --git a/firmware/common/max2831_target.c b/firmware/common/max2831_target.c index 757ebae0..47a07eaa 100644 --- a/firmware/common/max2831_target.c +++ b/firmware/common/max2831_target.c @@ -21,16 +21,17 @@ #include "max2831_target.h" -#include -#include "hackrf_core.h" +#include "platform_scu.h" void max2831_target_init(max2831_driver_t* const drv) { - /* Configure SSP1 Peripheral (to be moved later in SSP driver) */ - scu_pinmux(SCU_SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); + const platform_scu_t* scu = platform_scu(); - scu_pinmux(SCU_XCVR_CS, SCU_XCVR_CS_PINCFG); + /* Configure SSP1 Peripheral (to be moved later in SSP driver) */ + scu_pinmux(scu->SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(scu->SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); + + scu_pinmux(scu->XCVR_CS, scu->XCVR_CS_PINCFG); /* * Configure XCVR_CTL GPIO pins. @@ -39,10 +40,10 @@ void max2831_target_init(max2831_driver_t* const drv) * MAX2837 which had a separate TXENABLE. On MAX2831 a single RXTX pin * switches between RX (high) and TX (low) modes. */ - scu_pinmux(SCU_XCVR_ENABLE, SCU_XCVR_ENABLE_PINCFG); - scu_pinmux(SCU_XCVR_RXENABLE, SCU_XCVR_RXENABLE_PINCFG); - scu_pinmux(SCU_XCVR_RXHP, SCU_XCVR_RXHP_PINCFG); - scu_pinmux(SCU_XCVR_LD, SCU_XCVR_LD_PINCFG); + scu_pinmux(scu->XCVR_ENABLE, scu->XCVR_ENABLE_PINCFG); + scu_pinmux(scu->XCVR_RXENABLE, scu->XCVR_RXENABLE_PINCFG); + scu_pinmux(scu->XCVR_RXHP, scu->XCVR_RXHP_PINCFG); + scu_pinmux(scu->XCVR_LD, scu->XCVR_LD_PINCFG); /* Set GPIO pins as outputs. */ gpio_output(drv->gpio_enable); diff --git a/firmware/common/max2837_target.c b/firmware/common/max2837_target.c index dc8f69c1..91e48d71 100644 --- a/firmware/common/max2837_target.c +++ b/firmware/common/max2837_target.c @@ -23,22 +23,23 @@ #include "max2837_target.h" -#include -#include "hackrf_core.h" +#include "platform_scu.h" void max2837_target_init(max2837_driver_t* const drv) { - /* Configure SSP1 Peripheral (to be moved later in SSP driver) */ - scu_pinmux(SCU_SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); + const platform_scu_t* scu = platform_scu(); - scu_pinmux(SCU_XCVR_CS, SCU_XCVR_CS_PINCFG); + /* Configure SSP1 Peripheral (to be moved later in SSP driver) */ + scu_pinmux(scu->SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(scu->SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(scu->SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); + + scu_pinmux(scu->XCVR_CS, scu->XCVR_CS_PINCFG); /* Configure XCVR_CTL GPIO pins. */ - scu_pinmux(SCU_XCVR_ENABLE, SCU_XCVR_ENABLE_PINCFG); - scu_pinmux(SCU_XCVR_RXENABLE, SCU_XCVR_RXENABLE_PINCFG); - scu_pinmux(SCU_XCVR_TXENABLE, SCU_XCVR_TXENABLE_PINCFG); + scu_pinmux(scu->XCVR_ENABLE, scu->XCVR_ENABLE_PINCFG); + scu_pinmux(scu->XCVR_RXENABLE, scu->XCVR_RXENABLE_PINCFG); + scu_pinmux(scu->XCVR_TXENABLE, scu->XCVR_TXENABLE_PINCFG); /* Set GPIO pins as outputs. */ gpio_output(drv->gpio_enable); diff --git a/firmware/common/max2839_target.c b/firmware/common/max2839_target.c index 356313e9..63c2f6ec 100644 --- a/firmware/common/max2839_target.c +++ b/firmware/common/max2839_target.c @@ -23,17 +23,18 @@ #include "max2839_target.h" -#include -#include "hackrf_core.h" +#include "platform_scu.h" void max2839_target_init(max2839_driver_t* const drv) { - /* Configure SSP1 Peripheral (to be moved later in SSP driver) */ - scu_pinmux(SCU_SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); + const platform_scu_t* scu = platform_scu(); - scu_pinmux(SCU_XCVR_CS, SCU_GPIO_FAST); + /* Configure SSP1 Peripheral (to be moved later in SSP driver) */ + scu_pinmux(scu->SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(scu->SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(scu->SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); + + scu_pinmux(scu->XCVR_CS, SCU_GPIO_FAST); /* * Configure XCVR_CTL GPIO pins. @@ -42,8 +43,8 @@ void max2839_target_init(max2839_driver_t* const drv) * MAX2837 which had a separate TXENABLE. On MAX2839 a single RXTX pin * switches between RX (high) and TX (low) modes. */ - scu_pinmux(SCU_XCVR_ENABLE, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_RXENABLE, SCU_GPIO_FAST); + scu_pinmux(scu->XCVR_ENABLE, SCU_GPIO_FAST); + scu_pinmux(scu->XCVR_RXENABLE, SCU_GPIO_FAST); /* Set GPIO pins as outputs. */ gpio_output(drv->gpio_enable); diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index bcb71345..7dd2c3fd 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -23,46 +23,26 @@ #include "max283x.h" -#include "gpio.h" -#include "gpio_lpc.h" +#include "platform_gpio.h" #include "spi_bus.h" extern spi_bus_t spi_bus_ssp1; -#ifdef PRALINE -static struct gpio gpio_max283x_enable = GPIO(7, 1); -static struct gpio gpio_max283x_rx_enable = GPIO(7, 2); -static struct gpio gpio_max2831_rxhp = GPIO(6, 29); -static struct gpio gpio_max2831_ld = GPIO(4, 11); -#else -static struct gpio gpio_max283x_enable = GPIO(2, 6); -static struct gpio gpio_max283x_rx_enable = GPIO(2, 5); -static struct gpio gpio_max283x_tx_enable = GPIO(2, 4); -#endif #ifdef PRALINE max2831_driver_t max2831 = { .bus = &spi_bus_ssp1, - .gpio_enable = &gpio_max283x_enable, - .gpio_rxtx = &gpio_max283x_rx_enable, - .gpio_rxhp = &gpio_max2831_rxhp, - .gpio_ld = &gpio_max2831_ld, .target_init = max2831_target_init, .set_mode = max2831_target_set_mode, }; #else max2837_driver_t max2837 = { .bus = &spi_bus_ssp1, - .gpio_enable = &gpio_max283x_enable, - .gpio_rx_enable = &gpio_max283x_rx_enable, - .gpio_tx_enable = &gpio_max283x_tx_enable, .target_init = max2837_target_init, .set_mode = max2837_target_set_mode, }; max2839_driver_t max2839 = { .bus = &spi_bus_ssp1, - .gpio_enable = &gpio_max283x_enable, - .gpio_rxtx = &gpio_max283x_rx_enable, .target_init = max2839_target_init, .set_mode = max2839_target_set_mode, }; @@ -72,6 +52,23 @@ max2839_driver_t max2839 = { void max283x_setup(max283x_driver_t* const drv, max283x_variant_t type) { drv->type = type; + + const platform_gpio_t* gpio = platform_gpio(); + + /* MAX283x GPIO PinMux */ +#if defined(PRALINE) + max2831.gpio_enable = gpio->max283x_enable; + max2831.gpio_rxtx = gpio->max283x_rx_enable; + max2831.gpio_rxhp = gpio->max2831_rxhp; + max2831.gpio_ld = gpio->max2831_ld; +#else + max2837.gpio_enable = gpio->max283x_enable; + max2837.gpio_rx_enable = gpio->max283x_rx_enable; + max2837.gpio_tx_enable = gpio->max283x_tx_enable; + max2839.gpio_enable = gpio->max283x_enable; + max2839.gpio_rxtx = gpio->max283x_rx_enable; +#endif + switch (type) { #ifdef PRALINE case MAX2831_VARIANT: diff --git a/firmware/common/max2871.c b/firmware/common/max2871.c index 598599cc..9179c93e 100644 --- a/firmware/common/max2871.c +++ b/firmware/common/max2871.c @@ -43,14 +43,16 @@ static void delay_ms(int ms); void max2871_setup(max2871_driver_t* const drv) { + const platform_scu_t* scu = platform_scu(); + /* Configure GPIO pins. */ - scu_pinmux(SCU_VCO_CE, SCU_GPIO_FAST); - scu_pinmux(SCU_VCO_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - /* Only used for the debug pin config: scu_pinmux(SCU_VCO_SCLK, SCU_GPIO_FAST); */ - scu_pinmux(SCU_VCO_SDATA, SCU_GPIO_FAST); - scu_pinmux(SCU_VCO_LE, SCU_GPIO_FAST); - scu_pinmux(SCU_VCO_MUX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu_pinmux(SCU_SYNT_RFOUT_EN, SCU_GPIO_FAST); + scu_pinmux(scu->VCO_CE, SCU_GPIO_FAST); + scu_pinmux(scu->VCO_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + /* Only used for the debug pin config: scu_pinmux(scu->VCO_SCLK, SCU_GPIO_FAST); */ + scu_pinmux(scu->VCO_SDATA, SCU_GPIO_FAST); + scu_pinmux(scu->VCO_LE, SCU_GPIO_FAST); + scu_pinmux(scu->VCO_MUX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu_pinmux(scu->SYNT_RFOUT_EN, SCU_GPIO_FAST); /* Set GPIO pins as outputs. */ gpio_output(drv->gpio_vco_ce); diff --git a/firmware/common/max5864_target.c b/firmware/common/max5864_target.c index ed433415..208ee9c3 100644 --- a/firmware/common/max5864_target.c +++ b/firmware/common/max5864_target.c @@ -22,21 +22,22 @@ #include "max5864_target.h" -#include -#include "hackrf_core.h" +#include "platform_scu.h" void max5864_target_init(max5864_driver_t* const drv) { (void) drv; + const platform_scu_t* scu = platform_scu(); + /* Configure SSP1 Peripheral (to be moved later in SSP driver) */ - scu_pinmux(SCU_SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); + scu_pinmux(scu->SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(scu->SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(scu->SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); /* * Configure CS_AD pin to keep the MAX5864 SPI disabled while we use the * SPI bus for the MAX2837. FIXME: this should probably be somewhere else. */ - scu_pinmux(SCU_AD_CS, SCU_AD_CS_PINCFG); + scu_pinmux(scu->AD_CS, scu->AD_CS_PINCFG); } diff --git a/firmware/common/mixer.c b/firmware/common/mixer.c index 3e4c8083..c615c7f1 100644 --- a/firmware/common/mixer.c +++ b/firmware/common/mixer.c @@ -23,39 +23,10 @@ #include "rffc5071.h" #include "rffc5071_spi.h" #include "max2871.h" -#include "gpio_lpc.h" +#include "platform_gpio.h" -/* RFFC5071 GPIO serial interface PinMux */ -// clang-format off -#if (defined JAWBREAKER || defined HACKRF_ONE) -static struct gpio gpio_rffc5072_select = GPIO(2, 13); -static struct gpio gpio_rffc5072_clock = GPIO(5, 6); -static struct gpio gpio_rffc5072_data = GPIO(3, 3); -static struct gpio gpio_rffc5072_reset = GPIO(2, 14); -#endif -#ifdef RAD1O -static struct gpio gpio_vco_ce = GPIO(2, 13); -static struct gpio gpio_vco_sclk = GPIO(5, 6); -static struct gpio gpio_vco_sdata = GPIO(3, 3); -static struct gpio gpio_vco_le = GPIO(2, 14); -static struct gpio gpio_vco_mux = GPIO(5, 25); -static struct gpio gpio_synt_rfout_en = GPIO(3, 5); -#endif -#ifdef PRALINE -static struct gpio gpio_rffc5072_select = GPIO(2, 13); -static struct gpio gpio_rffc5072_clock = GPIO(5, 18); -static struct gpio gpio_rffc5072_data = GPIO(4, 14); -static struct gpio gpio_rffc5072_reset = GPIO(2, 14); -static struct gpio gpio_rffc5072_ld = GPIO(6, 25); -#endif -// clang-format on - -#if (defined JAWBREAKER || defined HACKRF_ONE || defined PRALINE) -const rffc5071_spi_config_t rffc5071_spi_config = { - .gpio_select = &gpio_rffc5072_select, - .gpio_clock = &gpio_rffc5072_clock, - .gpio_data = &gpio_rffc5072_data, -}; +#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) +static rffc5071_spi_config_t rffc5071_spi_config; spi_bus_t spi_bus_rffc5071 = { .config = &rffc5071_spi_config, @@ -67,80 +38,79 @@ spi_bus_t spi_bus_rffc5071 = { mixer_driver_t mixer = { .bus = &spi_bus_rffc5071, - .gpio_reset = &gpio_rffc5072_reset, - #ifdef PRALINE - .gpio_ld = &gpio_rffc5072_ld, - #endif -}; -#endif -#ifdef RAD1O -mixer_driver_t mixer = { - .gpio_vco_ce = &gpio_vco_ce, - .gpio_vco_sclk = &gpio_vco_sclk, - .gpio_vco_sdata = &gpio_vco_sdata, - .gpio_vco_le = &gpio_vco_le, - .gpio_synt_rfout_en = &gpio_synt_rfout_en, - .gpio_vco_mux = &gpio_vco_mux, }; +#elif defined(RAD1O) +mixer_driver_t mixer = {}; #endif void mixer_bus_setup(mixer_driver_t* const mixer) { -#if (defined JAWBREAKER || defined HACKRF_ONE || defined PRALINE) (void) mixer; + +#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) + const platform_gpio_t* gpio = platform_gpio(); + rffc5071_spi_config = (rffc5071_spi_config_t){ + .gpio_select = gpio->rffc5072_select, + .gpio_clock = gpio->rffc5072_clock, + .gpio_data = gpio->rffc5072_data, + }; spi_bus_start(&spi_bus_rffc5071, &rffc5071_spi_config); #endif -#ifdef RAD1O - (void) mixer; -#endif } void mixer_setup(mixer_driver_t* const mixer) { -#if (defined JAWBREAKER || defined HACKRF_ONE || defined PRALINE) + const platform_gpio_t* gpio = platform_gpio(); + +#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) + mixer->gpio_reset = gpio->rffc5072_reset; + #if defined(PRALINE) + mixer->gpio_ld = gpio->rffc5072_ld; + #endif rffc5071_setup(mixer); -#endif -#ifdef RAD1O +#elif defined(RAD1O) + mixer->gpio_vco_ce = gpio->vco_ce; + mixer->gpio_vco_sclk = gpio->vco_sclk; + mixer->gpio_vco_sdata = gpio->vco_sdata; + mixer->gpio_vco_le = gpio->vco_le; + mixer->gpio_synt_rfout_en = gpio->synt_rfout_en; + mixer->gpio_vco_mux = gpio->vco_mux; max2871_setup(mixer); #endif } uint64_t mixer_set_frequency(mixer_driver_t* const mixer, uint64_t hz) { -#if (defined JAWBREAKER || defined HACKRF_ONE || defined PRALINE) +#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) return rffc5071_set_frequency(mixer, hz); -#endif -#ifdef RAD1O +#elif defined(RAD1O) return max2871_set_frequency(mixer, hz / 1000000); #endif } void mixer_enable(mixer_driver_t* const mixer) { -#if (defined JAWBREAKER || defined HACKRF_ONE || defined PRALINE) +#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) rffc5071_enable(mixer); -#endif -#ifdef RAD1O +#elif defined(RAD1O) max2871_enable(mixer); #endif } void mixer_disable(mixer_driver_t* const mixer) { -#if (defined JAWBREAKER || defined HACKRF_ONE || defined PRALINE) +#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) rffc5071_disable(mixer); -#endif -#ifdef RAD1O +#elif defined(RAD1O) max2871_disable(mixer); #endif } void mixer_set_gpo(mixer_driver_t* const mixer, uint8_t gpo) { -#if (defined JAWBREAKER || defined HACKRF_ONE || defined PRALINE) +#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) rffc5071_set_gpo(mixer, gpo); -#endif -#ifdef RAD1O +#elif defined(RAD1O) (void) mixer; (void) gpo; #endif diff --git a/firmware/common/mixer.h b/firmware/common/mixer.h index 06ca88f5..840ebba2 100644 --- a/firmware/common/mixer.h +++ b/firmware/common/mixer.h @@ -26,9 +26,7 @@ #if (defined JAWBREAKER || defined HACKRF_ONE || defined PRALINE) #include "rffc5071.h" typedef rffc5071_driver_t mixer_driver_t; -#endif - -#ifdef RAD1O +#elif defined(RAD1O) #include "max2871.h" typedef max2871_driver_t mixer_driver_t; #endif diff --git a/firmware/common/operacake.c b/firmware/common/operacake.c index e7f71a5b..bc00ff35 100644 --- a/firmware/common/operacake.c +++ b/firmware/common/operacake.c @@ -26,7 +26,7 @@ #include "gpio.h" #include "gpio_lpc.h" #include "i2c_bus.h" -#include +#include "platform_scu.h" /* * I2C Mode @@ -387,11 +387,13 @@ uint16_t gpio_test(uint8_t address) return 0xFFFF; } - scu_pinmux(SCU_PINMUX_GPIO3_8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_PINMUX_GPIO3_12, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_PINMUX_GPIO3_13, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_PINMUX_GPIO3_14, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_PINMUX_GPIO3_15, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + const platform_scu_t* scu = platform_scu(); + + scu_pinmux(scu->PINMUX_GPIO3_8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_GPIO3_12, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_GPIO3_13, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_GPIO3_14, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_GPIO3_15, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); static struct gpio gpio_pins[] = { GPIO(3, 8), // u1ctrl IO2 diff --git a/firmware/common/platform_gpio.h b/firmware/common/platform_gpio.h index 600a7e68..35354b9a 100644 --- a/firmware/common/platform_gpio.h +++ b/firmware/common/platform_gpio.h @@ -31,7 +31,11 @@ extern "C" { typedef struct { /* LEDs */ +#if defined(PRALINE) || defined(RAD1O) gpio_t led[4]; +#else + gpio_t led[3]; +#endif /* Power Supply Control */ gpio_t gpio_1v8_enable; diff --git a/firmware/common/portapack.c b/firmware/common/portapack.c index cad8f8cc..6220ed35 100644 --- a/firmware/common/portapack.c +++ b/firmware/common/portapack.c @@ -23,30 +23,16 @@ #include "portapack.h" #include "hackrf_core.h" -#include "gpio_lpc.h" +#include "platform_gpio.h" +#include "platform_scu.h" #include "delay.h" -#include - static void portapack_sleep_milliseconds(const uint32_t milliseconds) { /* NOTE: Naively assumes 204 MHz instruction cycle clock and five instructions per count */ delay(milliseconds * 40800); } -// clang-format off -static struct gpio gpio_io_stbx = GPIO(5, 0); /* P2_0 */ -static struct gpio gpio_addr = GPIO(5, 1); /* P2_1 */ -__attribute__((unused)) -static struct gpio gpio_lcd_te = GPIO(5, 3); /* P2_3 */ -__attribute__((unused)) -static struct gpio gpio_unused = GPIO(5, 7); /* P2_8 */ -static struct gpio gpio_lcd_rdx = GPIO(5, 4); /* P2_4 */ -static struct gpio gpio_lcd_wrx = GPIO(1, 10); /* P2_9 */ -static struct gpio gpio_dir = GPIO(1, 13); /* P2_13 */ - -// clang-format on - typedef struct portapack_if_t { gpio_t gpio_dir; gpio_t gpio_lcd_rdx; @@ -58,11 +44,6 @@ typedef struct portapack_if_t { } portapack_if_t; static portapack_if_t portapack_if = { - .gpio_dir = &gpio_dir, - .gpio_lcd_rdx = &gpio_lcd_rdx, - .gpio_lcd_wrx = &gpio_lcd_wrx, - .gpio_io_stbx = &gpio_io_stbx, - .gpio_addr = &gpio_addr, .gpio_port_data = GPIO_LPC_PORT(3), .io_reg = 0x03, }; @@ -191,6 +172,15 @@ static void portapack_io_write(const bool address, const uint_fast16_t value) static void portapack_if_init(void) { + const platform_gpio_t* gpio = platform_gpio(); + const platform_scu_t* scu = platform_scu(); + + portapack_if.gpio_dir = gpio->dir; + portapack_if.gpio_lcd_rdx = gpio->lcd_rdx; + portapack_if.gpio_lcd_wrx = gpio->lcd_wrx; + portapack_if.gpio_io_stbx = gpio->io_stbx; + portapack_if.gpio_addr = gpio->addr; + portapack_data_mask_set(); portapack_data_write_high(0); @@ -208,22 +198,22 @@ static void portapack_if_init(void) /* gpio_input(portapack_if.gpio_rot_a); */ /* gpio_input(portapack_if.gpio_rot_b); */ - scu_pinmux(SCU_PINMUX_PP_D0, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); - scu_pinmux(SCU_PINMUX_PP_D1, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); - scu_pinmux(SCU_PINMUX_PP_D2, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); - scu_pinmux(SCU_PINMUX_PP_D3, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); - scu_pinmux(SCU_PINMUX_PP_D4, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); - scu_pinmux(SCU_PINMUX_PP_D5, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); - scu_pinmux(SCU_PINMUX_PP_D6, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); - scu_pinmux(SCU_PINMUX_PP_D7, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); + scu_pinmux(scu->PINMUX_PP_D0, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); + scu_pinmux(scu->PINMUX_PP_D1, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); + scu_pinmux(scu->PINMUX_PP_D2, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); + scu_pinmux(scu->PINMUX_PP_D3, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); + scu_pinmux(scu->PINMUX_PP_D4, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); + scu_pinmux(scu->PINMUX_PP_D5, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); + scu_pinmux(scu->PINMUX_PP_D6, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); + scu_pinmux(scu->PINMUX_PP_D7, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); - scu_pinmux(SCU_PINMUX_PP_DIR, SCU_CONF_FUNCTION0 | SCU_GPIO_NOPULL); - scu_pinmux(SCU_PINMUX_PP_LCD_RDX, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); - scu_pinmux(SCU_PINMUX_PP_LCD_WRX, SCU_CONF_FUNCTION0 | SCU_GPIO_NOPULL); - scu_pinmux(SCU_PINMUX_PP_IO_STBX, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); - scu_pinmux(SCU_PINMUX_PP_ADDR, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); - /* scu_pinmux(SCU_PINMUX_PP_LCD_TE, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); */ - /* scu_pinmux(SCU_PINMUX_PP_UNUSED, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); */ + scu_pinmux(scu->PINMUX_PP_DIR, SCU_CONF_FUNCTION0 | SCU_GPIO_NOPULL); + scu_pinmux(scu->PINMUX_PP_LCD_RDX, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); + scu_pinmux(scu->PINMUX_PP_LCD_WRX, SCU_CONF_FUNCTION0 | SCU_GPIO_NOPULL); + scu_pinmux(scu->PINMUX_PP_IO_STBX, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); + scu_pinmux(scu->PINMUX_PP_ADDR, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); + /* scu_pinmux(scu->PINMUX_PP_LCD_TE, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); */ + /* scu_pinmux(scu->PINMUX_PP_UNUSED, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); */ } static void portapack_lcd_reset_state(const bool active) diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 1c605d1c..9fee21e7 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -23,13 +23,12 @@ #include "rf_path.h" -#include - #include #include "hackrf_ui.h" #include "gpio_lpc.h" #include "platform_detect.h" +#include "platform_scu.h" #include "mixer.h" #include "max283x.h" #include "max5864.h" @@ -94,11 +93,6 @@ #define SWITCHCTRL_ANT_PWR (1 << 6) /* turn on antenna port power */ #ifdef HACKRF_ONE -/* - * In HackRF One r9 this control signal has been moved to the microcontroller. - */ - -static struct gpio gpio_h1r9_no_ant_pwr = GPIO(2, 4); static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) { @@ -173,9 +167,9 @@ static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) if (detected_platform() == BOARD_ID_HACKRF1_R9) { if (ctrl & SWITCHCTRL_ANT_PWR) { - gpio_clear(&gpio_h1r9_no_ant_pwr); + gpio_clear(rf_path->gpio_h1r9_no_ant_pwr); } else { - gpio_set(&gpio_h1r9_no_ant_pwr); + gpio_set(rf_path->gpio_h1r9_no_ant_pwr); } } else { if (ctrl & SWITCHCTRL_ANT_PWR) { @@ -315,32 +309,36 @@ static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) void rf_path_pin_setup(rf_path_t* const rf_path) { +#if !defined(JELLYBEAN) && !defined(JAWBREAKER) + const platform_scu_t* scu = platform_scu(); +#endif + #ifdef HACKRF_ONE /* Configure RF switch control signals */ // clang-format off - scu_pinmux(SCU_HP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_LP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_TX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_NO_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_RX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu_pinmux(SCU_NO_TX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_AMP_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_RX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->HP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->LP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->TX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->NO_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->RX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu_pinmux(scu->NO_TX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->AMP_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->RX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); // clang-format on if (detected_platform() == BOARD_ID_HACKRF1_R9) { - scu_pinmux(SCU_H1R9_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_H1R9_NO_ANT_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - gpio_clear(&gpio_h1r9_no_ant_pwr); - gpio_output(&gpio_h1r9_no_ant_pwr); - scu_pinmux(SCU_H1R9_NO_VAA_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->H1R9_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->H1R9_NO_ANT_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + gpio_clear(rf_path->gpio_h1r9_no_ant_pwr); + gpio_output(rf_path->gpio_h1r9_no_ant_pwr); + scu_pinmux(scu->H1R9_NO_VAA_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); } else { - scu_pinmux(SCU_TX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu_pinmux(SCU_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu_pinmux(scu->TX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu_pinmux(scu->RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); gpio_output(rf_path->gpio_tx); - scu_pinmux(SCU_NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); } /* @@ -365,21 +363,21 @@ void rf_path_pin_setup(rf_path_t* const rf_path) #elif RAD1O /* Configure RF switch control signals */ // clang-format off - scu_pinmux(SCU_BY_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_BY_AMP_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu_pinmux(SCU_TX_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_TX_RX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_BY_MIX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_BY_MIX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_LOW_HIGH_FILT, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_LOW_HIGH_FILT_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_RX_LNA, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu_pinmux(SCU_MIXER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu_pinmux(scu->BY_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->BY_AMP_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu_pinmux(scu->TX_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->TX_RX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->BY_MIX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->BY_MIX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->LOW_HIGH_FILT, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->LOW_HIGH_FILT_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->RX_LNA, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu_pinmux(scu->MIXER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); // clang-format on /* Configure RF power supply (VAA) switch */ - scu_pinmux(SCU_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); /* * Safe (initial) switch settings turn off both amplifiers and antenna port @@ -401,21 +399,21 @@ void rf_path_pin_setup(rf_path_t* const rf_path) gpio_output(rf_path->gpio_rx_lna); #elif PRALINE /* Configure RF switch control signals */ - scu_pinmux(SCU_TX_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->TX_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); board_rev_t rev = detected_revision(); if ((rev == BOARD_REV_PRALINE_R1_0) || (rev == BOARD_REV_GSG_PRALINE_R1_0)) { - scu_pinmux(SCU_MIX_EN_N_R1_0, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu_pinmux(scu->MIX_EN_N_R1_0, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); } else { - scu_pinmux(SCU_MIX_EN_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->MIX_EN_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); } - scu_pinmux(SCU_LPF_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_RF_AMP_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->LPF_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->RF_AMP_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); /* Configure antenna port power control signal */ - scu_pinmux(SCU_ANT_BIAS_EN_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->ANT_BIAS_EN_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); /* Configure RF power supply (VAA) switch */ - scu_pinmux(SCU_NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); /* * Safe (initial) switch settings turn off both amplifiers and antenna port diff --git a/firmware/common/rf_path.h b/firmware/common/rf_path.h index 0ebc75f2..e7c47130 100644 --- a/firmware/common/rf_path.h +++ b/firmware/common/rf_path.h @@ -60,6 +60,8 @@ typedef struct rf_path_t { gpio_t gpio_amp_bypass; gpio_t gpio_rx_amp; gpio_t gpio_no_rx_amp_pwr; + // In HackRF One r9 this control signal has been moved to the microcontroller. + gpio_t gpio_h1r9_no_ant_pwr; #endif #ifdef RAD1O gpio_t gpio_tx_rx_n; diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 73ab70cd..f8339bce 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -37,9 +37,9 @@ #include "rffc5071_regs.def" // private register def macros #include "selftest.h" -#include #include "hackrf_core.h" #include "delay.h" +#include "platform_scu.h" static bool enabled = false; @@ -104,7 +104,8 @@ void rffc5071_setup(rffc5071_driver_t* const drv) #ifdef PRALINE /* Configure mixer PLL lock detect pin */ - scu_pinmux(SCU_MIXER_LD, SCU_MIXER_LD_PINCFG); + const platform_scu_t* scu = platform_scu(); + scu_pinmux(scu->MIXER_LD, scu->MIXER_LD_PINCFG); gpio_input(drv->gpio_ld); #endif diff --git a/firmware/common/rffc5071_spi.c b/firmware/common/rffc5071_spi.c index 3254ebdb..943bb0c8 100644 --- a/firmware/common/rffc5071_spi.c +++ b/firmware/common/rffc5071_spi.c @@ -20,8 +20,8 @@ * Boston, MA 02110-1301, USA. */ -#include #include "hackrf_core.h" +#include "platform_scu.h" #include "rffc5071_spi.h" @@ -65,8 +65,9 @@ static void rffc5071_spi_bus_init(spi_bus_t* const bus) { const rffc5071_spi_config_t* const config = bus->config; - scu_pinmux(SCU_MIXER_SCLK, SCU_MIXER_SCLK_PINCFG); - scu_pinmux(SCU_MIXER_SDATA, SCU_MIXER_SDATA_PINCFG); + const platform_scu_t* scu = platform_scu(); + scu_pinmux(scu->MIXER_SCLK, scu->MIXER_SCLK_PINCFG); + scu_pinmux(scu->MIXER_SDATA, scu->MIXER_SDATA_PINCFG); gpio_output(config->gpio_clock); rffc5071_spi_direction_out(bus); @@ -80,8 +81,9 @@ static void rffc5071_spi_target_init(spi_bus_t* const bus) const rffc5071_spi_config_t* const config = bus->config; /* Configure GPIO pins. */ - scu_pinmux(SCU_MIXER_ENX, SCU_GPIO_FAST); - scu_pinmux(SCU_MIXER_RESETX, SCU_GPIO_FAST); + const platform_scu_t* scu = platform_scu(); + scu_pinmux(scu->MIXER_ENX, SCU_GPIO_FAST); + scu_pinmux(scu->MIXER_RESETX, SCU_GPIO_FAST); /* Set GPIO pins as outputs. */ gpio_output(config->gpio_select); diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index 50b98d77..6f095217 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -22,11 +22,11 @@ * Boston, MA 02110-1301, USA. */ -#include #include #include "hackrf_core.h" #include "platform_detect.h" +#include "platform_scu.h" #include "sgpio.h" @@ -34,29 +34,33 @@ static void update_q_invert(sgpio_config_t* const config); void sgpio_configure_pin_functions(sgpio_config_t* const config) { - scu_pinmux(SCU_PINMUX_SGPIO0, SCU_PINMUX_SGPIO0_PINCFG); - scu_pinmux(SCU_PINMUX_SGPIO1, SCU_PINMUX_SGPIO1_PINCFG); - scu_pinmux(SCU_PINMUX_SGPIO2, SCU_PINMUX_SGPIO2_PINCFG); - scu_pinmux(SCU_PINMUX_SGPIO3, SCU_PINMUX_SGPIO3_PINCFG); - scu_pinmux(SCU_PINMUX_SGPIO4, SCU_PINMUX_SGPIO4_PINCFG); - scu_pinmux(SCU_PINMUX_SGPIO5, SCU_PINMUX_SGPIO5_PINCFG); - scu_pinmux(SCU_PINMUX_SGPIO6, SCU_PINMUX_SGPIO6_PINCFG); - scu_pinmux(SCU_PINMUX_SGPIO7, SCU_PINMUX_SGPIO7_PINCFG); - scu_pinmux(SCU_PINMUX_SGPIO8, SCU_PINMUX_SGPIO8_PINCFG); - scu_pinmux(SCU_PINMUX_SGPIO9, SCU_PINMUX_SGPIO9_PINCFG); - scu_pinmux(SCU_PINMUX_SGPIO10, SCU_PINMUX_SGPIO10_PINCFG); - scu_pinmux(SCU_PINMUX_SGPIO11, SCU_PINMUX_SGPIO11_PINCFG); - scu_pinmux(SCU_PINMUX_SGPIO12, SCU_PINMUX_SGPIO12_PINCFG); /* GPIO0[13] */ - scu_pinmux(SCU_PINMUX_SGPIO14, SCU_PINMUX_SGPIO14_PINCFG); /* GPIO5[13] */ - scu_pinmux(SCU_PINMUX_SGPIO15, SCU_PINMUX_SGPIO15_PINCFG); /* GPIO5[14] */ + const platform_scu_t* scu = platform_scu(); + + scu_pinmux(scu->PINMUX_SGPIO0, scu->PINMUX_SGPIO0_PINCFG); + scu_pinmux(scu->PINMUX_SGPIO1, scu->PINMUX_SGPIO1_PINCFG); + scu_pinmux(scu->PINMUX_SGPIO2, scu->PINMUX_SGPIO2_PINCFG); + scu_pinmux(scu->PINMUX_SGPIO3, scu->PINMUX_SGPIO3_PINCFG); + scu_pinmux(scu->PINMUX_SGPIO4, scu->PINMUX_SGPIO4_PINCFG); + scu_pinmux(scu->PINMUX_SGPIO5, scu->PINMUX_SGPIO5_PINCFG); + scu_pinmux(scu->PINMUX_SGPIO6, scu->PINMUX_SGPIO6_PINCFG); + scu_pinmux(scu->PINMUX_SGPIO7, scu->PINMUX_SGPIO7_PINCFG); + scu_pinmux(scu->PINMUX_SGPIO8, scu->PINMUX_SGPIO8_PINCFG); + scu_pinmux(scu->PINMUX_SGPIO9, scu->PINMUX_SGPIO9_PINCFG); + scu_pinmux(scu->PINMUX_SGPIO10, scu->PINMUX_SGPIO10_PINCFG); + scu_pinmux(scu->PINMUX_SGPIO11, scu->PINMUX_SGPIO11_PINCFG); + scu_pinmux(scu->PINMUX_SGPIO12, scu->PINMUX_SGPIO12_PINCFG); /* GPIO0[13] */ + scu_pinmux(scu->PINMUX_SGPIO14, scu->PINMUX_SGPIO14_PINCFG); /* GPIO5[13] */ + scu_pinmux(scu->PINMUX_SGPIO15, scu->PINMUX_SGPIO15_PINCFG); /* GPIO5[14] */ if (detected_platform() == BOARD_ID_HACKRF1_R9) { +#if defined(HACKRF_ONE) scu_pinmux( - SCU_H1R9_TRIGGER_EN, + scu->H1R9_TRIGGER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[5] */ +#endif } else { scu_pinmux( - SCU_TRIGGER_EN, + scu->TRIGGER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[12] */ } diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index d9d9ef37..41dbd6c4 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -23,17 +23,10 @@ #include "si5351c.h" #include "clkin.h" #include "platform_detect.h" -#include "gpio_lpc.h" +#include "platform_gpio.h" +#include "platform_scu.h" #include "hackrf_core.h" #include "selftest.h" -#include - -/* HackRF One r9 clock control */ -// clang-format off -static struct gpio gpio_h1r9_clkin_en = GPIO(5, 15); -static struct gpio gpio_h1r9_clkout_en = GPIO(0, 9); -static struct gpio gpio_h1r9_mcu_clk_en = GPIO(0, 8); -// clang-format on #include @@ -204,20 +197,24 @@ void si5351c_configure_clock_control( if (source == PLL_SOURCE_CLKIN) { /* PLLB on CLKIN */ pll = SI5351C_CLK_PLL_SRC_B; + #if defined(HACKRF_ONE) if (detected_platform() == BOARD_ID_HACKRF1_R9) { /* * HackRF One r9 always uses PLL A on the XTAL input * but externally switches that input to CLKIN. */ pll = SI5351C_CLK_PLL_SRC_A; - gpio_set(&gpio_h1r9_clkin_en); + gpio_set(platform_gpio()->h1r9_clkin_en); } + #endif } else { /* PLLA on XTAL */ pll = SI5351C_CLK_PLL_SRC_A; + #if defined(HACKRF_ONE) if (detected_platform() == BOARD_ID_HACKRF1_R9) { - gpio_clear(&gpio_h1r9_clkin_en); + gpio_clear(platform_gpio()->h1r9_clkin_en); } + #endif } #endif if (clkout_enabled) { @@ -313,11 +310,16 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) uint8_t data[] = {SI5351C_REG_OUTPUT_EN, value}; si5351c_write(drv, data, sizeof(data)); - if ((clkout_enabled) && (detected_platform() == BOARD_ID_HACKRF1_R9)) { - gpio_set(&gpio_h1r9_clkout_en); - } else { - gpio_clear(&gpio_h1r9_clkout_en); +#if defined(HACKRF_ONE) + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + const platform_gpio_t* gpio = platform_gpio(); + if (clkout_enabled) { + gpio_set(gpio->h1r9_clkout_en); + } else { + gpio_clear(gpio->h1r9_clkout_en); + } } +#endif } void si5351c_set_int_mode( @@ -409,21 +411,26 @@ void si5351c_init(si5351c_driver_t* const drv) selftest.report.pass = false; } +#if defined(HACKRF_ONE) if (detected_platform() == BOARD_ID_HACKRF1_R9) { + const platform_gpio_t* gpio = platform_gpio(); + const platform_scu_t* scu = platform_scu(); + /* CLKIN_EN */ - scu_pinmux(SCU_H1R9_CLKIN_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - gpio_clear(&gpio_h1r9_clkin_en); - gpio_output(&gpio_h1r9_clkin_en); + scu_pinmux(scu->H1R9_CLKIN_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + gpio_clear(gpio->h1r9_clkin_en); + gpio_output(gpio->h1r9_clkin_en); /* CLKOUT_EN */ - scu_pinmux(SCU_H1R9_CLKOUT_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - gpio_clear(&gpio_h1r9_clkout_en); - gpio_output(&gpio_h1r9_clkout_en); + scu_pinmux(scu->H1R9_CLKOUT_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + gpio_clear(gpio->h1r9_clkout_en); + gpio_output(gpio->h1r9_clkout_en); /* MCU_CLK_EN */ - scu_pinmux(SCU_H1R9_MCU_CLK_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - gpio_clear(&gpio_h1r9_mcu_clk_en); - gpio_output(&gpio_h1r9_mcu_clk_en); + scu_pinmux(scu->H1R9_MCU_CLK_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + gpio_clear(gpio->h1r9_mcu_clk_en); + gpio_output(gpio->h1r9_mcu_clk_en); } +#endif (void) drv; } diff --git a/firmware/common/w25q80bv_target.c b/firmware/common/w25q80bv_target.c index a83f5d98..b4a50a7b 100644 --- a/firmware/common/w25q80bv_target.c +++ b/firmware/common/w25q80bv_target.c @@ -22,8 +22,7 @@ #include "w25q80bv_target.h" -#include -#include "hackrf_core.h" +#include "platform_scu.h" /* TODO: Why is CS being controlled manually when SSP0 could do it * automatically? @@ -35,6 +34,8 @@ void w25q80bv_target_init(w25q80bv_driver_t* const drv) /* Init SPIFI GPIO to Normal GPIO */ + const platform_scu_t* scu = platform_scu(); + // P3_3 SPIFI_SCK => SSP0_SCK scu_pinmux(P3_3, (SCU_SSP_IO | SCU_CONF_FUNCTION2)); // P3_4 SPIFI SPIFI_SIO3 IO3 => GPIO1[14] @@ -49,14 +50,14 @@ void w25q80bv_target_init(w25q80bv_driver_t* const drv) scu_pinmux(P3_8, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); /* configure SSP pins */ - scu_pinmux(SCU_SSP0_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP0_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP0_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION2)); + scu_pinmux(scu->SSP0_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(scu->SSP0_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(scu->SSP0_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION2)); /* configure GPIO pins */ - scu_pinmux(SCU_FLASH_HOLD, SCU_GPIO_FAST); - scu_pinmux(SCU_FLASH_WP, SCU_GPIO_FAST); - scu_pinmux(SCU_SSP0_CS, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); + scu_pinmux(scu->FLASH_HOLD, SCU_GPIO_FAST); + scu_pinmux(scu->FLASH_WP, SCU_GPIO_FAST); + scu_pinmux(scu->SSP0_CS, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); /* drive CS, HOLD, and WP pins high */ gpio_set(drv->gpio_hold); diff --git a/firmware/hackrf_usb/usb_api_board_info.c b/firmware/hackrf_usb/usb_api_board_info.c index f9f75623..ffa135f2 100644 --- a/firmware/hackrf_usb/usb_api_board_info.c +++ b/firmware/hackrf_usb/usb_api_board_info.c @@ -23,6 +23,7 @@ #include "usb_api_board_info.h" #include "platform_detect.h" +#include "platform_gpio.h" #include "firmware_info.h" #include @@ -35,9 +36,6 @@ #ifdef HACKRF_ONE #include "gpio_lpc.h" -static struct gpio gpio_h1r9_clkout_en = GPIO(0, 9); -static struct gpio gpio_h1r9_mcu_clk_en = GPIO(0, 8); -static struct gpio gpio_h1r9_rx = GPIO(0, 7); #endif usb_request_status_t usb_vendor_request_read_board_id( @@ -138,9 +136,10 @@ usb_request_status_t usb_vendor_request_reset( * correctly after the reset. */ if (detected_platform() == BOARD_ID_HACKRF1_R9) { - gpio_input(&gpio_h1r9_mcu_clk_en); - gpio_input(&gpio_h1r9_clkout_en); - gpio_input(&gpio_h1r9_rx); + const platform_gpio_t* gpio = platform_gpio(); + gpio_input(gpio->h1r9_mcu_clk_en); + gpio_input(gpio->h1r9_clkout_en); + gpio_input(gpio->h1r9_rx); } #endif wwdt_reset(100000); From 0c5b8938688cf5664dfb1b8a890eabef6a303d65 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Mon, 23 Mar 2026 10:48:31 +0200 Subject: [PATCH 047/238] firmware: exclude signals not used by praline --- firmware/common/hackrf_core.c | 2 +- firmware/common/platform_gpio.c | 14 +++++--------- firmware/common/platform_gpio.h | 2 ++ firmware/common/platform_scu.c | 7 +++---- firmware/common/platform_scu.h | 5 +++-- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 365d7926..726d1869 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -848,7 +848,7 @@ void pin_setup(void) #endif jtag_gpio_cpld.gpio_tck = gpio->cpld_tck; -#if !defined(PRALINE) +#if defined(HACKRF_ONE) || defined(RAD1O) jtag_gpio_cpld.gpio_tms = gpio->cpld_tms; jtag_gpio_cpld.gpio_tdi = gpio->cpld_tdi; jtag_gpio_cpld.gpio_tdo = gpio->cpld_tdo; diff --git a/firmware/common/platform_gpio.c b/firmware/common/platform_gpio.c index d00851d5..3ba0dff6 100644 --- a/firmware/common/platform_gpio.c +++ b/firmware/common/platform_gpio.c @@ -74,11 +74,11 @@ const platform_gpio_t* platform_gpio(void) /* RF supply (VAA) control */ #if defined(HACKRF_ONE) - gpio.vaa_disable = &GPIO2_9; + gpio.vaa_disable = &GPIO2_9; #elif defined(PRALINE) - gpio.vaa_disable = &GPIO4_1; + gpio.vaa_disable = &GPIO4_1; #elif defined(RAD1O) - gpio.vaa_enable = &GPIO2_9; + gpio.vaa_enable = &GPIO2_9; #endif /* W25Q80BV Flash */ @@ -131,13 +131,11 @@ const platform_gpio_t* platform_gpio(void) gpio.fpga_cfg_creset = &GPIO2_11; gpio.fpga_cfg_cdone = &GPIO5_14; gpio.fpga_cfg_spi_cs = &GPIO2_10; -#elif defined(HACKRF_ONE) || defined(RAD1O) +#endif +#if defined(HACKRF_ONE) || defined(RAD1O) gpio.cpld_tdo = &GPIO5_18; gpio.cpld_tms = &GPIO3_4; gpio.cpld_tdi = &GPIO3_1; -#else - gpio.cpld_tms = &GPIO3_1; - gpio.cpld_tdi = &GPIO3_4; #endif #if defined(HACKRF_ONE) || defined(PRALINE) gpio.cpld_pp_tms = &GPIO1_1; @@ -192,9 +190,7 @@ const platform_gpio_t* platform_gpio(void) gpio.h1r9_clkin_en = &GPIO5_15; gpio.h1r9_clkout_en = &GPIO0_9; gpio.h1r9_mcu_clk_en = &GPIO0_8; - } - if (detected_platform() == BOARD_ID_HACKRF1_R9) { gpio.h1r9_1v8_enable = &GPIO2_9; gpio.h1r9_vaa_disable = &GPIO3_6; gpio.h1r9_trigger_enable = &GPIO5_5; diff --git a/firmware/common/platform_gpio.h b/firmware/common/platform_gpio.h index 35354b9a..a6669cbd 100644 --- a/firmware/common/platform_gpio.h +++ b/firmware/common/platform_gpio.h @@ -110,9 +110,11 @@ typedef struct { /* CPLD JTAG interface GPIO pins, FPGA config pins in Praline */ gpio_t cpld_tck; +#if defined(HACKRF_ONE) || defined(RAD1O) gpio_t cpld_tdo; gpio_t cpld_tms; gpio_t cpld_tdi; +#endif #if defined(HACKRF_ONE) || defined(PRALINE) gpio_t cpld_pp_tms; gpio_t cpld_pp_tdo; diff --git a/firmware/common/platform_scu.c b/firmware/common/platform_scu.c index 9521b90c..af7f44dd 100644 --- a/firmware/common/platform_scu.c +++ b/firmware/common/platform_scu.c @@ -77,16 +77,15 @@ const platform_scu_t* platform_scu(void) scu.SSP1_CS = (P1_20); /* P1_20 */ /* CPLD JTAG interface */ + scu.PINMUX_CPLD_TCK = (P6_1); /* GPIO3[ 0] */ #if defined(PRALINE) scu.PINMUX_FPGA_CRESET = (P5_2); /* GPIO2[11] on P5_2 */ scu.PINMUX_FPGA_CDONE = (P4_10); /* GPIO5[14] */ scu.PINMUX_FPGA_SPI_CS = (P5_1); /* GPIO2[10] */ -#endif - scu.PINMUX_CPLD_TDO = (P9_5); /* GPIO5[18] */ - scu.PINMUX_CPLD_TCK = (P6_1); /* GPIO3[ 0] */ -#if defined(RAD1O) || defined(HACKRF_ONE) || defined(PRALINE) +#elif defined(RAD1O) || defined(HACKRF_ONE) scu.PINMUX_CPLD_TMS = (P6_5); /* GPIO3[ 4] */ scu.PINMUX_CPLD_TDI = (P6_2); /* GPIO3[ 1] */ + scu.PINMUX_CPLD_TDO = (P9_5); /* GPIO5[18] */ #else scu.PINMUX_CPLD_TMS = (P6_2); /* GPIO3[ 1] */ scu.PINMUX_CPLD_TDI = (P6_5); /* GPIO3[ 4] */ diff --git a/firmware/common/platform_scu.h b/firmware/common/platform_scu.h index fd4bae49..7db50071 100644 --- a/firmware/common/platform_scu.h +++ b/firmware/common/platform_scu.h @@ -80,11 +80,12 @@ typedef struct { scu_grp_pin_t PINMUX_FPGA_CRESET; scu_grp_pin_t PINMUX_FPGA_CDONE; scu_grp_pin_t PINMUX_FPGA_SPI_CS; -#endif +#else scu_grp_pin_t PINMUX_CPLD_TDO; - scu_grp_pin_t PINMUX_CPLD_TCK; scu_grp_pin_t PINMUX_CPLD_TMS; scu_grp_pin_t PINMUX_CPLD_TDI; +#endif + scu_grp_pin_t PINMUX_CPLD_TCK; /* CPLD SGPIO interface */ scu_grp_pin_t PINMUX_SGPIO0; From 2b8b61879a6466a4302538010929c2a57f1907ea Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Mon, 23 Mar 2026 12:28:42 +0200 Subject: [PATCH 048/238] firmware: use consistent indentation across gpio/scu assignments --- firmware/common/platform_gpio.c | 74 +++++++++++------------ firmware/common/platform_scu.c | 100 ++++++++++++++++---------------- 2 files changed, 88 insertions(+), 86 deletions(-) diff --git a/firmware/common/platform_gpio.c b/firmware/common/platform_gpio.c index 3ba0dff6..66211d5f 100644 --- a/firmware/common/platform_gpio.c +++ b/firmware/common/platform_gpio.c @@ -67,24 +67,24 @@ const platform_gpio_t* platform_gpio(void) /* MAX5864 SPI chip select (AD_CS / CS_AD) GPIO PinMux */ #if defined(PRALINE) - gpio.max5864_select = &GPIO6_30; + gpio.max5864_select = &GPIO6_30; #else - gpio.max5864_select = &GPIO2_7; + gpio.max5864_select = &GPIO2_7; #endif /* RF supply (VAA) control */ #if defined(HACKRF_ONE) - gpio.vaa_disable = &GPIO2_9; + gpio.vaa_disable = &GPIO2_9; #elif defined(PRALINE) - gpio.vaa_disable = &GPIO4_1; + gpio.vaa_disable = &GPIO4_1; #elif defined(RAD1O) - gpio.vaa_enable = &GPIO2_9; + gpio.vaa_enable = &GPIO2_9; #endif /* W25Q80BV Flash */ - gpio.w25q80bv_hold = &GPIO1_14; - gpio.w25q80bv_wp = &GPIO1_15; - gpio.w25q80bv_select = &GPIO5_11; + gpio.w25q80bv_hold = &GPIO1_14; + gpio.w25q80bv_wp = &GPIO1_15; + gpio.w25q80bv_select = &GPIO5_11; /* RF switch control */ #if defined(HACKRF_ONE) @@ -126,20 +126,20 @@ const platform_gpio_t* platform_gpio(void) #endif /* CPLD JTAG interface GPIO pins_FPGA config pins in Praline */ - gpio.cpld_tck = &GPIO3_0; + gpio.cpld_tck = &GPIO3_0; #if defined(PRALINE) - gpio.fpga_cfg_creset = &GPIO2_11; - gpio.fpga_cfg_cdone = &GPIO5_14; - gpio.fpga_cfg_spi_cs = &GPIO2_10; + gpio.fpga_cfg_creset = &GPIO2_11; + gpio.fpga_cfg_cdone = &GPIO5_14; + gpio.fpga_cfg_spi_cs = &GPIO2_10; #endif #if defined(HACKRF_ONE) || defined(RAD1O) - gpio.cpld_tdo = &GPIO5_18; - gpio.cpld_tms = &GPIO3_4; - gpio.cpld_tdi = &GPIO3_1; + gpio.cpld_tdo = &GPIO5_18; + gpio.cpld_tms = &GPIO3_4; + gpio.cpld_tdi = &GPIO3_1; #endif #if defined(HACKRF_ONE) || defined(PRALINE) - gpio.cpld_pp_tms = &GPIO1_1; - gpio.cpld_pp_tdo = &GPIO1_8; + gpio.cpld_pp_tms = &GPIO1_1; + gpio.cpld_pp_tdo = &GPIO1_8; #endif /* Other CPLD interface GPIO pins */ @@ -155,12 +155,12 @@ const platform_gpio_t* platform_gpio(void) gpio.rffc5072_data = &GPIO3_3; gpio.rffc5072_reset = &GPIO2_14; #elif defined(RAD1O) - gpio.vco_ce = &GPIO2_13; - gpio.vco_sclk = &GPIO5_6; - gpio.vco_sdata = &GPIO3_3; - gpio.vco_le = &GPIO2_14; - gpio.vco_mux = &GPIO5_25; - gpio.synt_rfout_en = &GPIO3_5; + gpio.vco_ce = &GPIO2_13; + gpio.vco_sclk = &GPIO5_6; + gpio.vco_sdata = &GPIO3_3; + gpio.vco_le = &GPIO2_14; + gpio.vco_mux = &GPIO5_25; + gpio.synt_rfout_en = &GPIO3_5; #elif defined(PRALINE) gpio.rffc5072_select = &GPIO2_13; gpio.rffc5072_clock = &GPIO5_18; @@ -171,28 +171,30 @@ const platform_gpio_t* platform_gpio(void) /* Praline */ #if defined(PRALINE) - gpio.p2_ctrl0 = &GPIO7_3; - gpio.p2_ctrl1 = &GPIO7_4; - gpio.p1_ctrl0 = &GPIO0_14; - gpio.p1_ctrl1 = &GPIO5_16; - gpio.p1_ctrl2 = &GPIO3_5; - gpio.clkin_ctrl = &GPIO0_15; - gpio.aa_en = &GPIO1_7; - gpio.trigger_in = &GPIO6_26; - gpio.trigger_out = &GPIO5_6; - gpio.pps_out = &GPIO5_5; + gpio.p2_ctrl0 = &GPIO7_3; + gpio.p2_ctrl1 = &GPIO7_4; + gpio.p1_ctrl0 = &GPIO0_14; + gpio.p1_ctrl1 = &GPIO5_16; + gpio.p1_ctrl2 = &GPIO3_5; + gpio.clkin_ctrl = &GPIO0_15; + gpio.aa_en = &GPIO1_7; + gpio.trigger_in = &GPIO6_26; + gpio.trigger_out = &GPIO5_6; + gpio.pps_out = &GPIO5_5; #endif /* HackRF One r9 */ #if defined(HACKRF_ONE) - /* HackRF One r9 clock control */ if (detected_platform() == BOARD_ID_HACKRF1_R9) { + /* HackRF One r9 clock control */ gpio.h1r9_clkin_en = &GPIO5_15; gpio.h1r9_clkout_en = &GPIO0_9; gpio.h1r9_mcu_clk_en = &GPIO0_8; - gpio.h1r9_1v8_enable = &GPIO2_9; - gpio.h1r9_vaa_disable = &GPIO3_6; + /* HackRF One r9 power control */ + gpio.h1r9_1v8_enable = &GPIO2_9; + gpio.h1r9_vaa_disable = &GPIO3_6; + gpio.h1r9_trigger_enable = &GPIO5_5; } #endif diff --git a/firmware/common/platform_scu.c b/firmware/common/platform_scu.c index af7f44dd..2da5ff7a 100644 --- a/firmware/common/platform_scu.c +++ b/firmware/common/platform_scu.c @@ -34,13 +34,13 @@ const platform_scu_t* platform_scu(void) static platform_scu_t scu; /* LED PinMux */ - scu.PINMUX_LED1 = SCU_PINMUX_LED1; /* GPIO2[1] on P4_1 */ - scu.PINMUX_LED2 = SCU_PINMUX_LED2; /* GPIO2[2] on P4_2 */ - scu.PINMUX_LED3 = SCU_PINMUX_LED3; /* GPIO2[8] on P6_12 */ + scu.PINMUX_LED1 = SCU_PINMUX_LED1; /* GPIO2[1] on P4_1 */ + scu.PINMUX_LED2 = SCU_PINMUX_LED2; /* GPIO2[2] on P4_2 */ + scu.PINMUX_LED3 = SCU_PINMUX_LED3; /* GPIO2[8] on P6_12 */ #if defined(PRALINE) - scu.PINMUX_LED4 = (P8_6); /* GPIO4[6] on P8_6 */ + scu.PINMUX_LED4 = (P8_6); /* GPIO4[6] on P8_6 */ #elif defined(RAD1O) - scu.PINMUX_LED4 = (PB_6); /* GPIO5[26] on PB_6 */ + scu.PINMUX_LED4 = (PB_6); /* GPIO5[26] on PB_6 */ #endif /* Power Supply PinMux */ @@ -200,20 +200,20 @@ const platform_scu_t* platform_scu(void) /* RFFC5071 GPIO serial interface PinMux */ #if defined(PRALINE) - scu.MIXER_ENX = (P5_4); /* GPIO2[13] on P5_4 */ - scu.MIXER_SCLK = (P9_5); /* GPIO5[18] on P9_5 */ - scu.MIXER_SDATA = (P9_2); /* GPIO4[14] on P9_2 */ - scu.MIXER_RESETX = (P5_5); /* GPIO2[14] on P5_5 */ - scu.MIXER_LD = (PD_11); /* GPIO6[25] on PD_11 */ + scu.MIXER_ENX = (P5_4); /* GPIO2[13] on P5_4 */ + scu.MIXER_SCLK = (P9_5); /* GPIO5[18] on P9_5 */ + scu.MIXER_SDATA = (P9_2); /* GPIO4[14] on P9_2 */ + scu.MIXER_RESETX = (P5_5); /* GPIO2[14] on P5_5 */ + scu.MIXER_LD = (PD_11); /* GPIO6[25] on PD_11 */ scu.MIXER_SCLK_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.MIXER_SDATA_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu.MIXER_LD_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); #elif defined(JAWBREAKER) || defined(HACKRF_ONE) - scu.MIXER_ENX = (P5_4); /* GPIO2[13] on P5_4 */ - scu.MIXER_SCLK = (P2_6); /* GPIO5[6] on P2_6 */ - scu.MIXER_SDATA = (P6_4); /* GPIO3[3] on P6_4 */ - scu.MIXER_RESETX = (P5_5); /* GPIO2[14] on P5_5 */ + scu.MIXER_ENX = (P5_4); /* GPIO2[13] on P5_4 */ + scu.MIXER_SCLK = (P2_6); /* GPIO5[6] on P2_6 */ + scu.MIXER_SDATA = (P6_4); /* GPIO3[3] on P6_4 */ + scu.MIXER_RESETX = (P5_5); /* GPIO2[14] on P5_5 */ scu.MIXER_SCLK_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.MIXER_SDATA_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); @@ -312,56 +312,56 @@ const platform_scu_t* platform_scu(void) /* HackRF One r9 */ #if defined(HACKRF_ONE) - scu.H1R9_CLKIN_EN = P6_7; /* GPIO5[15] on P6_7 */ - scu.H1R9_CLKOUT_EN = P1_2; /* GPIO0[9] on P1_2 = has boot pull-down; */ - scu.H1R9_MCU_CLK_EN = P1_1; /* GPIO0[8] on P1_1 = has boot pull-up; */ - scu.H1R9_RX = P2_7; /* GPIO0[7] on P4_4 = has boot pull-up; */ - scu.H1R9_NO_ANT_PWR = P4_4; /* GPIO2[4] on P4_4 */ - scu.H1R9_EN1V8 = P5_0; /* GPIO2[9] on P5_0 */ - scu.H1R9_NO_VAA_EN = P6_10; /* GPIO3[6] on P6_10 */ - scu.H1R9_TRIGGER_EN = P2_5; /* GPIO5[5] on P2_5 */ + scu.H1R9_CLKIN_EN = P6_7; /* GPIO5[15] on P6_7 */ + scu.H1R9_CLKOUT_EN = P1_2; /* GPIO0[9] on P1_2 = has boot pull-down; */ + scu.H1R9_MCU_CLK_EN = P1_1; /* GPIO0[8] on P1_1 = has boot pull-up; */ + scu.H1R9_RX = P2_7; /* GPIO0[7] on P4_4 = has boot pull-up; */ + scu.H1R9_NO_ANT_PWR = P4_4; /* GPIO2[4] on P4_4 */ + scu.H1R9_EN1V8 = P5_0; /* GPIO2[9] on P5_0 */ + scu.H1R9_NO_VAA_EN = P6_10; /* GPIO3[6] on P6_10 */ + scu.H1R9_TRIGGER_EN = P2_5; /* GPIO5[5] on P2_5 */ #endif /* Miscellaneous */ - scu.PINMUX_PP_D0 = (P7_0); /* GPIO3[8] */ - scu.PINMUX_PP_D1 = (P7_1); /* GPIO3[9] */ - scu.PINMUX_PP_D2 = (P7_2); /* GPIO3[10] */ - scu.PINMUX_PP_D3 = (P7_3); /* GPIO3[11] */ - scu.PINMUX_PP_D4 = (P7_4); /* GPIO3[12] */ - scu.PINMUX_PP_D5 = (P7_5); /* GPIO3[13] */ - scu.PINMUX_PP_D6 = (P7_6); /* GPIO3[14] */ - scu.PINMUX_PP_D7 = (P7_7); /* GPIO3[15] */ + scu.PINMUX_PP_D0 = (P7_0); /* GPIO3[8] */ + scu.PINMUX_PP_D1 = (P7_1); /* GPIO3[9] */ + scu.PINMUX_PP_D2 = (P7_2); /* GPIO3[10] */ + scu.PINMUX_PP_D3 = (P7_3); /* GPIO3[11] */ + scu.PINMUX_PP_D4 = (P7_4); /* GPIO3[12] */ + scu.PINMUX_PP_D5 = (P7_5); /* GPIO3[13] */ + scu.PINMUX_PP_D6 = (P7_6); /* GPIO3[14] */ + scu.PINMUX_PP_D7 = (P7_7); /* GPIO3[15] */ /* TODO add other Pins */ - scu.PINMUX_GPIO3_8 = (P7_0); /* GPIO3[8] */ - scu.PINMUX_GPIO3_9 = (P7_1); /* GPIO3[9] */ - scu.PINMUX_GPIO3_10 = (P7_2); /* GPIO3[10] */ - scu.PINMUX_GPIO3_11 = (P7_3); /* GPIO3[11] */ - scu.PINMUX_GPIO3_12 = (P7_4); /* GPIO3[12] */ - scu.PINMUX_GPIO3_13 = (P7_5); /* GPIO3[13] */ - scu.PINMUX_GPIO3_14 = (P7_6); /* GPIO3[14] */ - scu.PINMUX_GPIO3_15 = (P7_7); /* GPIO3[15] */ + scu.PINMUX_GPIO3_8 = (P7_0); /* GPIO3[8] */ + scu.PINMUX_GPIO3_9 = (P7_1); /* GPIO3[9] */ + scu.PINMUX_GPIO3_10 = (P7_2); /* GPIO3[10] */ + scu.PINMUX_GPIO3_11 = (P7_3); /* GPIO3[11] */ + scu.PINMUX_GPIO3_12 = (P7_4); /* GPIO3[12] */ + scu.PINMUX_GPIO3_13 = (P7_5); /* GPIO3[13] */ + scu.PINMUX_GPIO3_14 = (P7_6); /* GPIO3[14] */ + scu.PINMUX_GPIO3_15 = (P7_7); /* GPIO3[15] */ - scu.PINMUX_PP_TDO = (P1_5); /* GPIO1[8] */ - scu.PINMUX_SD_POW = (P1_5); /* GPIO1[8] */ - scu.PINMUX_SD_CMD = (P1_6); /* GPIO1[9] */ - scu.PINMUX_PP_TMS = (P1_8); /* GPIO1[1] */ - scu.PINMUX_SD_VOLT0 = (P1_8); /* GPIO1[1] */ - scu.PINMUX_SD_DAT0 = (P1_9); /* GPIO1[2] */ - scu.PINMUX_SD_DAT1 = (P1_10); /* GPIO1[3] */ - scu.PINMUX_SD_DAT2 = (P1_11); /* GPIO1[4] */ - scu.PINMUX_SD_DAT3 = (P1_12); /* GPIO1[5] */ - scu.PINMUX_SD_CD = (P1_13); /* GPIO1[6] */ + scu.PINMUX_PP_TDO = (P1_5); /* GPIO1[8] */ + scu.PINMUX_SD_POW = (P1_5); /* GPIO1[8] */ + scu.PINMUX_SD_CMD = (P1_6); /* GPIO1[9] */ + scu.PINMUX_PP_TMS = (P1_8); /* GPIO1[1] */ + scu.PINMUX_SD_VOLT0 = (P1_8); /* GPIO1[1] */ + scu.PINMUX_SD_DAT0 = (P1_9); /* GPIO1[2] */ + scu.PINMUX_SD_DAT1 = (P1_10); /* GPIO1[3] */ + scu.PINMUX_SD_DAT2 = (P1_11); /* GPIO1[4] */ + scu.PINMUX_SD_DAT3 = (P1_12); /* GPIO1[5] */ + scu.PINMUX_SD_CD = (P1_13); /* GPIO1[6] */ scu.PINMUX_PP_IO_STBX = (P2_0); /* GPIO5[0] */ scu.PINMUX_PP_ADDR = (P2_1); /* GPIO5[1] */ scu.PINMUX_U0_TXD = (P2_0); /* GPIO5[0] */ scu.PINMUX_U0_RXD = (P2_1); /* GPIO5[1] */ - scu.PINMUX_ISP = (P2_7); /* GPIO0[7] */ + scu.PINMUX_ISP = (P2_7); /* GPIO0[7] */ - scu.PINMUX_GP_CLKIN = (P4_7); + scu.PINMUX_GP_CLKIN = (P4_7); _platform_scu = &scu; From 00f47250f2bcb48d37672dca4636afa2b7a8acb3 Mon Sep 17 00:00:00 2001 From: Mike Walters Date: Sat, 14 Mar 2026 16:26:03 +0000 Subject: [PATCH 049/238] Skip detection of conflicting Opera Cake board if a DA7219 is detected --- firmware/common/da7219.c | 44 ++++++++++++++++++++++++++++++++ firmware/common/da7219.h | 32 +++++++++++++++++++++++ firmware/common/operacake.c | 13 ++++++++++ firmware/common/operacake.h | 1 + firmware/hackrf-common.cmake | 1 + firmware/hackrf_usb/hackrf_usb.c | 4 +++ 6 files changed, 95 insertions(+) create mode 100644 firmware/common/da7219.c create mode 100644 firmware/common/da7219.h diff --git a/firmware/common/da7219.c b/firmware/common/da7219.c new file mode 100644 index 00000000..dd175863 --- /dev/null +++ b/firmware/common/da7219.c @@ -0,0 +1,44 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "da7219.h" +#include "hackrf_core.h" +#include "i2c_bus.h" + +#define DA7219_REG_CHIP_ID1 0x81 +#define DA7219_REG_CHIP_ID2 0x82 + +i2c_bus_t* const da7219_bus = &i2c0; + +uint8_t da7219_read_reg(i2c_bus_t* const bus, uint8_t reg) +{ + const uint8_t data_tx[] = {reg}; + uint8_t data_rx[] = {0x00}; + i2c_bus_transfer(bus, DA7219_ADDRESS, data_tx, 1, data_rx, 1); + return data_rx[0]; +} + +bool da7219_detect(void) +{ + uint8_t chip_id1 = da7219_read_reg(da7219_bus, DA7219_REG_CHIP_ID1); + uint8_t chip_id2 = da7219_read_reg(da7219_bus, DA7219_REG_CHIP_ID2); + return (chip_id1 == 0x23) && (chip_id2 == 0x93); +} diff --git a/firmware/common/da7219.h b/firmware/common/da7219.h new file mode 100644 index 00000000..1c255159 --- /dev/null +++ b/firmware/common/da7219.h @@ -0,0 +1,32 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __DA7219_H +#define __DA7219_H + +#include +#include + +#define DA7219_ADDRESS 0x1A + +bool da7219_detect(void); + +#endif /* __DA7219_H */ diff --git a/firmware/common/operacake.c b/firmware/common/operacake.c index bc00ff35..7c2e85da 100644 --- a/firmware/common/operacake.c +++ b/firmware/common/operacake.c @@ -77,6 +77,7 @@ #define INVALID_RANGE 0xFF; static uint8_t current_range = INVALID_RANGE; +static uint8_t skip_address = OPERACAKE_ADDRESS_INVALID; i2c_bus_t* const oc_bus = &i2c0; @@ -122,6 +123,9 @@ uint8_t operacake_init(bool allow_gpio) { /* Find connected operacakes */ for (int addr = 0; addr < 8; addr++) { + if (addr + OPERACAKE_ADDRESS_DEFAULT == skip_address) { + continue; + } operacake_write_reg( oc_bus, addr, @@ -146,6 +150,15 @@ uint8_t operacake_init(bool allow_gpio) return 0; } +void operacake_skip_i2c_address(uint8_t address) +{ + skip_address = address; + uint8_t board_addr = address - OPERACAKE_ADDRESS_DEFAULT; + if (board_addr < 8) { + operacake_boards[board_addr].present = false; + } +} + bool operacake_is_board_present(uint8_t address) { if (address >= OPERACAKE_MAX_BOARDS) { diff --git a/firmware/common/operacake.h b/firmware/common/operacake.h index 8183cf2a..ec8bae25 100644 --- a/firmware/common/operacake.h +++ b/firmware/common/operacake.h @@ -43,6 +43,7 @@ extern "C" { #define MAX_OPERACAKE_RANGES 8 uint8_t operacake_init(bool allow_gpio); +void operacake_skip_i2c_address(uint8_t address); bool operacake_is_board_present(uint8_t address); void operacake_get_boards(uint8_t* addresses); bool operacake_set_mode(uint8_t address, uint8_t mode); diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 1c6b7d6d..26a24d6e 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -194,6 +194,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/selftest.c ${PATH_HACKRF_FIRMWARE_COMMON}/m0_state.c ${PATH_HACKRF_FIRMWARE_COMMON}/adc.c + ${PATH_HACKRF_FIRMWARE_COMMON}/da7219.c ) if(BOARD STREQUAL "RAD1O") diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 64457261..749e188d 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -64,6 +64,7 @@ #include "selftest.h" #include "delay.h" #include "lz4_buf.h" +#include "da7219.h" extern uint32_t __m0_start__; extern uint32_t __m0_end__; @@ -388,6 +389,9 @@ int main(void) fpga_if_xcvr_selftest(); #endif + if (da7219_detect()) { + operacake_skip_i2c_address(DA7219_ADDRESS); + } bool operacake_allow_gpio; if (hackrf_ui()->operacake_gpio_compatible()) { operacake_allow_gpio = true; From 49912be0561636cb3ffc880e9dc9dd932ae6fd95 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 19 Mar 2026 14:49:58 -0400 Subject: [PATCH 050/238] Ensure clean firmware build directory in CI --- ci-scripts/build_h1_firmware.sh | 3 ++- ci-scripts/build_hpro_firmware.sh | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ci-scripts/build_h1_firmware.sh b/ci-scripts/build_h1_firmware.sh index a50785a8..762d64de 100755 --- a/ci-scripts/build_h1_firmware.sh +++ b/ci-scripts/build_h1_firmware.sh @@ -3,6 +3,7 @@ set -e git submodule init git submodule update cd firmware/hackrf_usb -cmake -B build +rm -rf build +cmake -DBOARD=HACKRF_ONE -B build cmake --build build cd ../.. diff --git a/ci-scripts/build_hpro_firmware.sh b/ci-scripts/build_hpro_firmware.sh index 8340d0ac..830d4bf7 100755 --- a/ci-scripts/build_hpro_firmware.sh +++ b/ci-scripts/build_hpro_firmware.sh @@ -3,6 +3,7 @@ set -e git submodule init git submodule update cd firmware/hackrf_usb +rm -rf build cmake -DBOARD=PRALINE -B build cmake --build build cd ../.. From 35f1f2fab262f849fd765290477fd86068c4a59f Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 24 Mar 2026 12:24:25 -0400 Subject: [PATCH 051/238] Fix typo --- ci-scripts/hackrf_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/hackrf_test.py b/ci-scripts/hackrf_test.py index 42d0393d..fc1027cd 100644 --- a/ci-scripts/hackrf_test.py +++ b/ci-scripts/hackrf_test.py @@ -1351,7 +1351,7 @@ def main(): eut.clkout_connected = True tester.clkout_connected = True - if count > 0 and not args.fw_update: + if count > 0 and not args.fwupdate: eut.activate_leds(False) eut.test_serial() From 9c255d78fd8e581ea274a08e33d87bbd4f6d558f Mon Sep 17 00:00:00 2001 From: mndza Date: Thu, 19 Mar 2026 11:47:17 +0100 Subject: [PATCH 052/238] Fix output clock glitches on PLL reset --- firmware/common/si5351c.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 41dbd6c4..d3108180 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -27,6 +27,7 @@ #include "platform_scu.h" #include "hackrf_core.h" #include "selftest.h" +#include "delay.h" #include @@ -141,9 +142,12 @@ void si5351c_configure_pll_multisynth(si5351c_driver_t* const drv) void si5351c_reset_pll(si5351c_driver_t* const drv) { + si5351c_disable_all_outputs(drv); /* reset PLLA and PLLB */ uint8_t data[] = {177, 0xA0}; si5351c_write(drv, data, sizeof(data)); + delay_us_at_mhz(2000, 204); + si5351c_enable_clock_outputs(drv); } void si5351c_configure_multisynth( From 8d6ee8438c4ec3d0cf50661cecabebe8b4e8a001 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 24 Mar 2026 11:53:54 -0400 Subject: [PATCH 053/238] Always use PLL A On most platforms, we previously set PLL A to use XTAL input and PLL B to use CLKIN, switching from one PLL to the other to change clock source. Now we use PLL A at all times, switching the PLL input to change clock source. This avoids output clock phase inconsistencies that can happen when switching output multisynths from one PLL to another. It also makes it possible in the future to use one PLL for sample rate and the other PLL for reference clocks. --- ci-scripts/hackrf_pro_test.py | 15 ++++-- ci-scripts/hackrf_test.py | 15 ++++-- firmware/common/hackrf_core.c | 3 +- firmware/common/si5351c.c | 87 +++++++++++++++-------------------- firmware/common/si5351c.h | 12 +++-- 5 files changed, 66 insertions(+), 66 deletions(-) diff --git a/ci-scripts/hackrf_pro_test.py b/ci-scripts/hackrf_pro_test.py index bbe7e85f..1e9ac9f4 100644 --- a/ci-scripts/hackrf_pro_test.py +++ b/ci-scripts/hackrf_pro_test.py @@ -719,8 +719,7 @@ class HackRF: log(receive.stdout + receive.stderr) fail(220 + self.unit_number) - # confirm that PLL locked to new source - expected_value = "0x01" if (enable and self.partner.revision != "r9") else "0x51" + # confirm that PLL A locked to new source timeout = time.time() + 1 while time.time() < timeout: debug = subprocess.run([self.partner.bin_dir + "/hackrf_debug", "-d", @@ -730,9 +729,17 @@ class HackRF: if debug.returncode != 0: log(debug.stderr) fail(230 + self.unit_number) - if expected_value in debug.stdout: + output = str(debug.stdout).split() + try: + val = int(output[3], 0) + except: + log(debug.stderr) + log(traceback.format_exc()) + fail(230 + self.unit_number) + # Check LOL_A + if not (val >> 5) & 1: break - if expected_value not in debug.stdout: + if (val >> 5) & 1: fail(232 + self.unit_number) time.sleep(0.1) else: diff --git a/ci-scripts/hackrf_test.py b/ci-scripts/hackrf_test.py index fc1027cd..13948ad3 100644 --- a/ci-scripts/hackrf_test.py +++ b/ci-scripts/hackrf_test.py @@ -595,8 +595,7 @@ class HackRF: log(receive.stdout + receive.stderr) fail(220 + self.unit_number) - # confirm that PLL locked to new source - expected_value = "0x01" if (enable and self.partner.revision != "r9") else "0x51" + # confirm that PLL A locked to new source timeout = time.time() + 1 while time.time() < timeout: debug = subprocess.run([self.partner.bin_dir + "hackrf_debug", "-d", @@ -606,9 +605,17 @@ class HackRF: if debug.returncode != 0: log(debug.stderr) fail(230 + self.unit_number) - if expected_value in debug.stdout: + output = str(debug.stdout).split() + try: + val = int(output[3], 0) + except: + log(debug.stderr) + log(traceback.format_exc()) + fail(230 + self.unit_number) + # Check LOL_A + if not (val >> 5) & 1: break - if expected_value not in debug.stdout: + if (val >> 5) & 1: fail(232 + self.unit_number) time.sleep(0.1) else: diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 726d1869..737f3ba3 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -528,8 +528,6 @@ void clock_gen_init(void) si5351c_power_down_all_clocks(&clock_gen); si5351c_set_crystal_configuration(&clock_gen); si5351c_enable_xo_and_ms_fanout(&clock_gen); - si5351c_configure_pll_sources(&clock_gen); - si5351c_configure_pll_multisynth(&clock_gen); /* * Clocks on HackRF One r9: @@ -592,6 +590,7 @@ void clock_gen_init(void) /* Set to 10 MHz, the common rate between Jawbreaker and HackRF One. */ sample_rate_set(10ULL * FP_ONE_MHZ, true); + si5351c_configure_clock_control(&clock_gen); si5351c_set_clock_source(&clock_gen, PLL_SOURCE_XTAL); // soft reset si5351c_reset_pll(&clock_gen); diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index d3108180..76ad7aa0 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -117,26 +117,35 @@ void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv) /* * Register 15: PLL Input Source * CLKIN_DIV=0 (Divide by 1) - * PLLA_SRC=0 (XTAL) - * PLLB_SRC=1 (CLKIN) + * Set both PLLA_SRC and PLLB_SRC */ -void si5351c_configure_pll_sources(si5351c_driver_t* const drv) +void si5351c_configure_pll_sources( + si5351c_driver_t* const drv, + const enum pll_sources source) { - uint8_t data[] = {15, 0x08}; + uint8_t data[] = {15, 0x00}; + if (source == PLL_SOURCE_CLKIN) { + data[1] = 0x0c; + } si5351c_write(drv, data, sizeof(data)); } /* MultiSynth NA (PLLA) and NB (PLLB) */ -void si5351c_configure_pll_multisynth(si5351c_driver_t* const drv) +void si5351c_configure_pll_multisynth( + si5351c_driver_t* const drv, + const enum pll_sources source) { - /*PLLA: 25MHz XTAL * (0x0e00+512)/128 = 800mhz -> int mode */ + /* XTAL: 25 MHz * (0x0e00 + 512) / 128 = 800 MHz, integer mode */ uint8_t data[] = {26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00}; + if (source == PLL_SOURCE_CLKIN) { + /* CLKIN: 10 MHz * (0x2600 + 512) / 128 = 800 MHz, integer mode */ + data[4] = 0x26; + } si5351c_write(drv, data, sizeof(data)); - /*PLLB: 10MHz CLKIN * (0x2600+512)/128 = 800mhz */ + /* Apply same configuration to PLL B. */ data[0] = 34; - data[4] = 0x26; si5351c_write(drv, data, sizeof(data)); } @@ -184,43 +193,11 @@ void si5351c_configure_multisynth( si5351c_write(drv, data, sizeof(data)); } -void si5351c_configure_clock_control( - si5351c_driver_t* const drv, - const enum pll_sources source) +void si5351c_configure_clock_control(si5351c_driver_t* const drv) { - uint8_t pll; + const uint8_t pll = SI5351C_CLK_PLL_SRC_A; uint8_t clkout_ctrl; -#ifdef RAD1O - (void) source; - /* PLLA on XTAL */ - pll = SI5351C_CLK_PLL_SRC_A; -#endif - -#if (defined JAWBREAKER || defined HACKRF_ONE || defined PRALINE) - if (source == PLL_SOURCE_CLKIN) { - /* PLLB on CLKIN */ - pll = SI5351C_CLK_PLL_SRC_B; - #if defined(HACKRF_ONE) - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - /* - * HackRF One r9 always uses PLL A on the XTAL input - * but externally switches that input to CLKIN. - */ - pll = SI5351C_CLK_PLL_SRC_A; - gpio_set(platform_gpio()->h1r9_clkin_en); - } - #endif - } else { - /* PLLA on XTAL */ - pll = SI5351C_CLK_PLL_SRC_A; - #if defined(HACKRF_ONE) - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - gpio_clear(platform_gpio()->h1r9_clkin_en); - } - #endif - } -#endif if (clkout_enabled) { clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | @@ -352,18 +329,26 @@ void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_source if (source == active_clock_source) { return; } - si5351c_configure_clock_control(drv, source); - active_clock_source = source; + si5351c_disable_all_outputs(drv); if (detected_platform() == BOARD_ID_HACKRF1_R9) { - /* 25MHz XTAL * (0x0e00+512)/128 = 800mhz -> int mode */ - uint8_t pll_data[] = {26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00}; +#if defined(HACKRF_ONE) + /* + * HackRF One r9 always uses PLL A on the XTAL input + * but externally switches that input to CLKIN. + */ + si5351c_configure_pll_sources(drv, PLL_SOURCE_XTAL); if (source == PLL_SOURCE_CLKIN) { - /* 10MHz CLKIN * (0x2600+512)/128 = 800mhz */ - pll_data[4] = 0x26; + gpio_set(platform_gpio()->h1r9_clkin_en); + } else { + gpio_clear(platform_gpio()->h1r9_clkin_en); } - si5351c_write(drv, pll_data, sizeof(pll_data)); - si5351c_reset_pll(drv); +#endif + } else { + si5351c_configure_pll_sources(drv, source); } + si5351c_configure_pll_multisynth(drv, source); + active_clock_source = source; + si5351c_reset_pll(drv); } bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv) @@ -389,7 +374,7 @@ void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable) /* Configure clock to 10MHz */ si5351c_configure_multisynth(drv, clkout, 80 * 128 - 512, 0, 1, 0); - si5351c_configure_clock_control(drv, active_clock_source); + si5351c_configure_clock_control(drv); si5351c_enable_clock_outputs(drv); } diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index 4c91bfba..ad47e8d4 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -75,8 +75,12 @@ void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv); void si5351c_power_down_all_clocks(si5351c_driver_t* const drv); void si5351c_set_crystal_configuration(si5351c_driver_t* const drv); void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv); -void si5351c_configure_pll_sources(si5351c_driver_t* const drv); -void si5351c_configure_pll_multisynth(si5351c_driver_t* const drv); +void si5351c_configure_pll_sources( + si5351c_driver_t* const drv, + const enum pll_sources source); +void si5351c_configure_pll_multisynth( + si5351c_driver_t* const drv, + const enum pll_sources source); void si5351c_reset_pll(si5351c_driver_t* const drv); void si5351c_configure_multisynth( si5351c_driver_t* const drv, @@ -85,9 +89,7 @@ void si5351c_configure_multisynth( const uint32_t p2, const uint32_t p3, const uint_fast8_t r_div); -void si5351c_configure_clock_control( - si5351c_driver_t* const drv, - const enum pll_sources source); +void si5351c_configure_clock_control(si5351c_driver_t* const drv); void si5351c_enable_clock_outputs(si5351c_driver_t* const drv); void si5351c_set_int_mode( si5351c_driver_t* const drv, From 5e0ecb9eac69978adb33d73bb4b50aeb3da9d46a Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 10 Mar 2026 18:04:46 -0400 Subject: [PATCH 054/238] Add phase offset to FPGA_CLK/SCT_CLK In order to support higher DAC sample rates on Praline with interpolation, it is necessary to adjust the phase of FPGA_CLK with respect to AFE_CLK. --- firmware/common/hackrf_core.c | 27 ++++++++++++++++++-- firmware/common/si5351c.c | 46 ++++++++++++++++++++++++++++++++--- firmware/common/si5351c.h | 4 +++ 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 737f3ba3..4793efd9 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -266,6 +266,7 @@ fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program) sgpio_cpld_stream_disable(&sgpio_config); } +#ifndef PRALINE /* Integer mode can be enabled if p1 is even and p2 is zero. */ if (p1 & 0x1 || p2) { si5351c_set_int_mode(&clock_gen, 0, 0); @@ -273,7 +274,6 @@ fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program) si5351c_set_int_mode(&clock_gen, 0, 1); } -#ifndef PRALINE if (detected_platform() == BOARD_ID_HACKRF1_R9) { /* * On HackRF One r9 all sample clocks are externally derived @@ -295,8 +295,31 @@ fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program) si5351c_configure_multisynth(&clock_gen, 2, 0, 0, 0, 0); //p1 doesn't matter } #else - /* MS0/CLK0 is the source for the MAX5864/FPGA (AFE_CLK). */ + /* MS0/CLK0 is the source for the MAX5864 (AFE_CLK). */ si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); + + /* MS1/CLK1 is the source for the FPGA (FPGA_CLK and SCT_CLK). */ + si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 1); + + /* Delay FPGA_CLK relative to AFE_CLK. */ + uint8_t phase_offset = 0; + if (p1 < 2100) { + phase_offset = (p1 >> 4) - 6; + } + si5351c_set_phase(&clock_gen, 1, phase_offset); + + if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { + /* + * On older boards FPGA_CLK is on CLK2 while SCT_CLK is on + * CLK1. We configure both so that behavior is consistent with + * newer boards that use CLK1 for both FPGA_CLK and SCT_CLK. + */ + si5351c_configure_multisynth(&clock_gen, 2, p1, p2, p3, 1); + si5351c_set_phase(&clock_gen, 2, phase_offset); + } + + /* Reset PLL to synchronize output clock phase. */ + si5351c_reset_pll(&clock_gen); #endif if (streaming) { diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 76ad7aa0..399d01fc 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -244,13 +244,27 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv) data[6] = SI5351C_CLK_POWERDOWN; } #ifdef PRALINE + /* CLK0: AFE_CLK */ data[1] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA); - data[3] = clkout_ctrl; + /* CLK1: SCT_CLK and FPGA_CLK */ + data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) | + SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | + SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA); + /* CLK4: XCVR_CLK */ data[5] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA) | SI5351C_CLK_INV; + if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { + /* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */ + data[3] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) | + SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | + SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA); + } else { + /* CLK2: MCU_CLK */ + data[3] = SI5351C_CLK_POWERDOWN; + } #endif si5351c_write(drv, data, sizeof(data)); } @@ -262,7 +276,7 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv) void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) { /* Enable CLK outputs 0, 1, 2, 4, 5 only. */ - /* Praline: enable 0, 4, 5 only. */ + /* Praline: enable 0, 1, 4, 5 only. */ /* 7: Clock to CPU is deactivated as it is not used and creates noise */ /* 3: External clock output is deactivated by default */ @@ -272,8 +286,14 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) SI5351C_CLK_DISABLE(6) | SI5351C_CLK_DISABLE(7); #else uint8_t value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | - SI5351C_CLK_DISABLE(2) | SI5351C_CLK_ENABLE(4) | SI5351C_CLK_ENABLE(5) | - SI5351C_CLK_DISABLE(6) | SI5351C_CLK_DISABLE(7); + SI5351C_CLK_ENABLE(4) | SI5351C_CLK_ENABLE(5) | SI5351C_CLK_DISABLE(6) | + SI5351C_CLK_DISABLE(7); + if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { + /* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */ + value |= SI5351C_CLK_ENABLE(2); + } else { + value |= SI5351C_CLK_DISABLE(2); + } #endif uint8_t clkout = 3; @@ -423,3 +443,21 @@ void si5351c_init(si5351c_driver_t* const drv) #endif (void) drv; } + +/* + * Set initial phase offset of output multisynth. AN619 associates this setting + * with outputs, but it seems to really be a multisynth setting. + * + * After changing this setting, you must call si5351c_reset_pll() to + * synchronize outputs with the new phase offset. + */ +void si5351c_set_phase( + si5351c_driver_t* const drv, + const uint8_t ms_number, + const uint8_t offset) +{ + const uint8_t address = 165 + ms_number; + if (ms_number < 8) { + si5351c_write_single(drv, address, offset & 0x7f); + } +} diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index ad47e8d4..001991dc 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -106,6 +106,10 @@ void si5351c_write( const size_t data_count); void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable); void si5351c_init(si5351c_driver_t* const drv); +void si5351c_set_phase( + si5351c_driver_t* const drv, + const uint8_t ms_number, + const uint8_t offset); #ifdef __cplusplus } From b4c4dd7506d47005e80130441982dd186aaccee4 Mon Sep 17 00:00:00 2001 From: mndza Date: Mon, 16 Feb 2026 10:34:29 +0100 Subject: [PATCH 055/238] gateware: change extended precision samples to little-endian --- firmware/fpga/build/praline_fpga.bin | Bin 199896 -> 200090 bytes firmware/fpga/top/ext_precision_rx.py | 8 ++++---- firmware/fpga/top/ext_precision_tx.py | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/firmware/fpga/build/praline_fpga.bin b/firmware/fpga/build/praline_fpga.bin index 460d2552f34bc7159462b0b0c610d8fc722fe1ee..8b962d2e2a94a86684cb45957aea7436976b1f8e 100644 GIT binary patch delta 126255 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�ZDK0m{|Ip@S78v|3wkS*`K^raeX-k@zJ1YV>>h^tz zaJFwtAwxb_Kih)`HfKDep5=O!inVgM*9{2`J5m*ne!!y*RM1RMdTp}%Ql0i`{N|i) zvS#+8<^r7llbVHzLL(|jdx|sg@{@kDVSj%_tG9)l4J{3YvVkDp(<-Czq5x3Ri+O>r zt9er4y8s^C|FC&nkus~dQAy`JdHtxzOEjG}7v5i{j3_mQA)?Q8joAoA=W6?Hh3;Ne zirsUSKht7-V;rn^!$@@PK(QMJ9B)s9G=f?cErDd@sUma=)ZX8U=8}z-;UJ}RT}4d3 z1Ld8MgRW~Mmvw?cD@4ppmji%%rwj5sT5T`MtF6jT`-tghOc10_QX7KD4;_QOc9&Iy z_KZpPtX)Edk*TEIuDwTcyr2*Sw#=U`w}V5FG(}$?;LnFg>RZ!DHDHUQ)74dMfPM}W zS+ZzkjfZ{QCTN$hb&K6(gPBohAIjyLs zdHu8bTh7S6S{j55B6_q-rTej?s;I?p`zr=dJW7}$yhp1QXA-n0*SyNbNAihT2Z_() z^#)#);Grb5ORu>fu) zt<}wnbYgI9dysr)6YBR;Tv7Gmg}&OBozZ*|ktr&9z|&4N`9(z~8zO8jQw-tp`=TnM z4(7V9PQpnHcIIP0yIs{F6(NM0CagHLZe*+)D`Bfj7{p z0s-ggpN^KVa`7?_od$owuvj{}iiEkGz{ZQwIJ(u3Qkm43^)4{fPWx~^y-@%!0p+PF zggfk6^!6Z|fNJ70;b5UlaLUzaP8%oW4Q%K?-YT*2S&hfD?GA*A_{(mT3M+WMc$}Q?;X)cRFFSZ3~DzpF_#>kp(#03uZOFaVC12x+S-5;b#Av9TE)+~|ns-nhy$iSn* z5c2^>SyqS^dF!#nxY#lhKvc$9muSl8`ujxNagS5Ec&4xrRU8C|m5OM(x0NeWZb_K1|a_GDj$fKb36~zS zE%Dsm!SA4O%vjenO+;6$loTBb{%Nom1_YFW$s<}ux=!Q@>ZJ`}#vCEp#gw1nHdTda zlBQ@j=9D;ty4i~?5_?gKp%k4-Y6z`Bm#PWW+rodS&e03BBF}sPZb2KzDkT&FEyJE( zwTou_%sVK$mWqoekX-l%p%{7|Y+=IE>__2)QZ;%9f58y}S?Mu!R`Yr~3v2*ygSrWC z<86MKylbgWbh+~>Waflmn-+{bO6N6fM)pKIpReUoNefSo9h(ZYh2Y=RAvZIN9bvQ1 z5V<3}aJY=$Kw70v=dj=$%;9SdutbsjKIbdYD!O|!0O#9c$eK6g^M&ZDCRLC&5dWE) znWSvDK0ZhaAeyw0ju}lMHEu5L11xjjx+Y8Wm_Ls>rnfPCaJ)uN+{zqBHX;oZp=;ox z^L#$Yf&qmaWtSUS=0}jL@xh?Y+ie6kin>dVUVg|mn#`W%YSoe{pN9;$hF z#{wSc`h&J;E20;=C&f*3ohuhtimhdrV3 z^Z<5^Pf5P_SgXD^N{=~ArENCWKq(d_7Sj4|icxBFXd=xs(%2PJh!j5w45TC$V%ijO z=NX$bc%)@0F?iA1&2oL(XcU0Yctl%6IWNIQXF2q;rwzRi-ob0pB(qgdk7z<%>(Kqn z)2sF9JoR*x**g817gaPwp(c`cXz@}gSS>foWQr`s+m*0W`L*!%$OaIx zPi=Lv8$RD+~YWITdY98;HZC$_F(7#sV1Ne7M5Y!&}M zs*N?$>uA-t!82VPy}na{8ic@hS}Bco*qtIFswvd}P^&(|!=_Hq;m<|WF70vSw8(cF zdoi@%Ev%>~VGN&5Se|8iI4UcL$Iuyuw#6uk`{q?k7X+zTjS;e{@`#-8odh2RlF^85pX@Njb|X!aLF-gTIP?hJE#gy|&kp6-vNixRm&p?wf`{L!XL8DBLm@ zP;e$H!J;f^UFO-08aj)l0uQ%}-mE?h^PHiN@!9rYxBXX1L+TU}uU%pKg^ z>6yb}g!ObW3oH&(@3P#yApj>+R2_sTT}r)p%2R7qTZJAi@upejq1ndd0np&sDRB`E zK?2Fk&(Uk2bhKN^=tF_(8%+8|^s*M3z`W+h_T3I9^e)o(`ieR~q8cvWG#$M2vt}Jg zsF!=`S~hxranmr|2n&Q;>;3P1_N0?@#91EnJfBPAdMZ|Y-jmCkWm@$_N9HjnMbs}j zM~rC*cYn%4%KA`b>1DXbM2Y-$Hm%&y~EDgkOiVYnoC*zM`V-+Io_Z(j)t>a$UxmIowFoCfTI({mp9p8yV! z&bQgEF5m?})xhFu4l$9VT@hC~zIVQrw|E8S7hHg5AQT5`N-gVn?}&$szi27OB_l60Mjq~fL>(HhNn#8cD{1N`pNi}?_}SEBnm zO#_Rt={EYNpsV?1L=flZ`RYkh#qC3mK1@dObMRf|29v0fMvM@CP~eWsOU)=C`%|15;@+wE@L2=Q%sLRgP(8`W9*~51-rp zjHcg|5OtQ@*osX%fsdYKg2PEt8}q@C%e~bP?YPHZ2ihYts!=-S?~w$K*e|&zse_s; zpa`H38h^*41@Q^>?pqqJg3FqhKaD;2-gnyy^<5tB0vZBL=T@@a`3J}<{5pCxNWSiM z8d%tKM8?>+)6F&Y%z5Y*fKNEs{Um<9)S;cNSOy*=0)6p)A>3ZLRRq^Rm%_r{!1;!D z#4lFB_@L&Y)Wcwk@R~SWKH`0n+aRX0dCXe8W*EITxCeWYbM%JL{4RWp;eF>c;|rfi zxy>^e$x`LZ~z z9J19-_7o_sIy^aLkRmf}{;|vP{xj>t7|evZH}@V5(}nV!PZYWsBg7~|Dn2*vc=M#) z8dPp8e|TLVHYpdNr3Zr(p%;jDm(&Oip*PV?^R1lQi(zlcD!QoL^H~xs7E%f98qIs> zDL8TYzWVoQl&@R60x3h17ckkZR_)!u>>l2W288Jtp1JC>S2`)m(*7LQ&p-Q{?QmFh>PZ9t>z5(UQ-(QQtb^um**xyQ&Ex=U2)0_ht_!js@=KoWB0 zjTl_ow5;C)Byw$SFjRoh*2B6>r=r*e%+dM!fe2d=L1C|aa4=0sDrsaFZDdvRcM~cE z)BUiCZ~%a!Uq`0|!uP#!wp|}z)edJH?Uo_(U~iRMI2&XLj-z9ocVuUM0{$HvyS`#k zKIJ_uH2gZ!6L@Wr)j*cK4w^^k)U%kh$o080);bmNJcw}g14#u`F>^#4S|PuX z?I(ARs58yDmtoRTdvDlbP8>LSwM>m7I-cuY;Q;rT2N>H+2HrEH5}>XmlMKWY9pRka zlTw!UCb82T!*Un*qq$AF+TF%xQEEOzEgF=>jXY{2vZ4?~o;q?2pGf{4=M@8`0MM#*HZsaX|SH?x>jkh#3| zTBL~vcdr$Cu{H@UA^7@7X(}F6sA;Uob%ix=5F6KW{!{T>AE4w~fi}+V?-!%w5l)GgPfuqG+>F?CPq+=GTMct<$yfrQc$GrF% zC7Fy(6-{^WHE}zN@6W$sYby_L>*-vuea+O>dWZqMk6?P^?n_y-)kW#kBBu1QITOcYd64mf;9otx6E^0M z*tjRJIn?$F2f1~jsK+*F;V+FMvyUOGw!deWp;gSX6HY%8_d(@A@|PUXp?A^cSPa5x zFkE1PeGAYcTf5eOO0$in2tC9#n^x;F-Ms0=RPZmFXs39Nv;<#yfF6AVt6=5k!9A4l zQ*eom27?5wG^Jj1cn+m^dt+vxSUiwEC&bv8a7d>+km`4rh&t*9i+a*p$gZ|tYtHJ` zhbzEaxKQ*)$Hn1w6Hj#rC+@L7;^VG)r@cvtXazwm{>&A20I`L#-(s8hsh6>OL3w+C ze}xL^IjsSNT7$RHlMWvXePsGh&kZ;qfnarL=blWixl~7)CKKjXp3bZ{sQAk z{32CYSm%dRY13uiT2GT1e z;@`WY6HXN@C2fT+LAJlXKo4{;H#n@}dA{^x#yEylzz@1Te*t>G1-8%1wc4sHALXCP z)hzf%$(7qsX9`3q=~|H2pj zEer9}C4i6;)K=K91$iazb~4FUIn}Q*c7jE20lIZF3;fNcn$6m53Wf90P%MoE#LCsW zEvBP=gnqZ+MR~=bnb+o%J%9yv?xKtT4&nNZ!1_BovwHx42$*~|hC;qQ?bN@f`zCKM zS?X!nSzA4e**5)Gk0h-31A}I0@Kfq%mcS`V>8nTOTuZvm8O6-}QJ*s8zBuUU_nIt_Hyp9PctY+)BHpoaaG zYVR8W!7S>RPxS_vHspK7ioxYW{9BKQjx_`Q8RQT7>c8{xNjXTlTA3{#TXmygqQEPf zDOl5bxp$6zNV#PE$VxGyE$g90iHWDmVaXBSp;q%i4j$`@O>Nb$%@v`a^)Caa=u27m zk`1Y7Zo}X-J=b}yWuX`SiGm(ht1Y^~A$WXjbUuCO`xknoKxiE3p%)z8J(u1-0oM6S z2wo|k`}&`}5s)5LC9|sk#CpxV&0OPA34jVnthPSqgM`IMTr;~Jlhdq49^M-*AuM_b zfynE8vswkA^bd|ZaQYtv%V`81&( z<8blD*3@Tt@0ml{)I5d25qSg-oljt}3_Fg`S z`X5pQ`8dE2Rz7+_0L+%?$|y=;i}uqM_s^PmHiv0{^ac9A#2BtB(J>u}AO7%FIZXhM zJO>^J0p#vZ0Vv?uK2AAAn;|~9m~4DHZmYs|>qVdaSHfCkAiFlc30FCN>-hQzE*`TF zh3F=LZ1{HhZ|P)-S@?s$2me^gxWp@Aw!y#2&eX;K%^OPy?_+Zy~i zZCr24$u#m;Nc$uP;tDJY@2l`;jC^}aD2;O`YmIur(U1vc6!JThurVo0%Udqq3(82; zK7`FIA$pgJ;;ft`~ToUeWkp^8LDu8+rrD zu8dwxgS@}6isbz~*VuDd;84s}wIyLWb zy)Z@_zq1c3i-xshG;zNDcQ?ZD3cbuKpw(irNl8$@@PpbIYjSe)?0xz>^oW8FoU?E1 zc2R-2pY^#sUpE+-tIl}n3|YcMiF)%zfp*}-ssLVyrX3M62}Ndcln z*a--TZBQ;CDohYDDqcfTgKhRCAi+jZMC=oaU_paoyIk?m6z&Z&BK9_j2rB-Z&_u=S z|2;h4=Y1|P?VNpfS>;{tTFV=ES@71u10HbKC2n%a=!>X@SFK0UB6)*vh_6072&xC&nV{N4Jyc8Z_9oVkahN#pZuF?7jYA-brB#Wi$v>xpv0G^ulu)3nRnp+s6T#}D`|5=CI<7hhG zW&i!-5-Q!sBRs4)td0)2Wbi>YPO(KFIw<;NS)+NB!DBZZ2IoN92H5T7Jg zVZ!c?a08sI-Be*H&SqNR>dCj_t9L)ikirTIU|()O^6pvQ@C|?VLWIC~bMrryK?1!G zmxm!upfRcZ8qXCTk9RJN?!wH>-aNq-2h=AxPwR6i7Od}0?_{7F<7il&%H3b08d;QW z`Inxx;%09lOWn+B4y@iY7owIdyALdsys6IHELgIY3u)Z6Z@F@I>8}7`EZ(nHUZ)HW z_^R-bnMwWu&oTQ_B@?ARSg^0)1?8v;n9{IWvZ5KvXl?Z#Hk?0Hwp1R@TRFV^rCoUH3bt3`7q%R@9-xfGI4|)%nC&Lm%b*7 zWsq{rmG#GaC}m(pA-0)n5%}1m6$_6L)b1$%I|;moT*F@G_-1IEkKDSy-8e~wiID8?!=F)XHWiH%yi?Op+ggqJRbH?cMN@l zVS5lHCfKUjcvvs&KHT5;nu($FB~(Nv6pvC!bl?_1b?n;FdlH-!$$Qg9p)z+W3KMib zu_tJMyPE)xLF0m}O7>hvd>#esfE;9WsC=Cg|JSf&FAC_V|HK#Ga`E*9MB-F=4$G-W zQG~Ssms}&CYxQ((hVM0x1v0n50PFz-a~H1c+SKXgBm(BW0TiQ-VD{=grzmZ*b~TNs(x++(X=fD7(eZ%x^{1vVoWW=jjf@%Byo+-I zQ?Rg;52KRI+SlkqNhS1%!?9L~K;&Z*V1;ePY$#tcX-~%$GLNPvvSml#-kJy2;-&C; zvyfpG6u+NY6HxWs^9dZIma?R~eHk3LQskG{(p4x00hNWa)%=dBI4&%9(=WYgzy<9F zzX6VVg37LDc0Sz??y6D+IW#AeXJS5O1019j>zEF33~<*oy+_1Y-e(4X6tNI2?4i0i z9^p7rB&n*&u-Cg)GcYm)SidJ$iW+=zc8Y0@RRT7{hT$g|>M8jKiw%x;*}o#w z!}ZO0rh7~UV3#24Nw%}*3aVJ2I6a0HbvcNOTu1$z2SFU?^nX5@!d@|R^C*b&#FfdCbU)OeNWX>@ zg1J-J3?q;nP>%%4NM!vC%onqcbSrJ1Z!W?`)M_MXv3R_3w^E_E4nIs*W;0cgKQqEh z5_{l#OA8Z0sVJOwv-c-=ut@&~nB0|0(ZS~HkUYt{}W4PG`IY@o(W<5s>3Pk_cRb?srq}=XzECND@U#;o8kD5fSVs=$3mzE` zD0h>3Kn02hFvS8l5xQ&+?~E_P85!3wnzEe?7Jl_HS+Aa=oo*49rCWY!CI>nFdyv}I zsM+4G=V@so-bf2z|Apu@jfcHy@m`9R5odMiLue<_ENbYw-qOOBNmuQ`&Bl#Zz|7SP%D5aBJ!$8XD z+}*PpX*K`uuV?pd~Q?C!}rnj)R+?~0)B3*>_NWNw7`Gxbd}ixO-JM8`WHMT_bRppXfA>(4zJN3-9=Ds z7Zoq1&Zr9rtJL%4xdL_K^6Z{&PG(SSzg$iMuGNu7-D0 z-Az1F!a(KN&X1{9f0r3y3HIo_f5iwP;{25`YzS)o}&lbCwQ{qU+0z- z7{$^X*4?DHCwbK(qtI4|8in!3CGgn3a&Y_tuO^A;<$=3SBSeH6j1_G9a`eyI$g7A= zoWQDk#2d$ZE0!Kiw0OdB#x@}WiRduOQjV>1zK-eEzqc#ZW5)a%P_<{dRBafmS<-q_ zi8{ogiW{~5CPJbcd{x}9s1ST-;IMr_h_M-SfW~jWNS07}^v7@E=VpZw5EI0gwGP)T zb2791+w?134@yo`*b?tvhDCRP1<5ocI;Iuc4XA(d=H%XMnqAwm{EOoNC6qcX#Tzrb zOq&r-94#=PLbVF;dH1xKb(xvoW0&BO)sC8UM-{G{Lfk`p^uBM$2!sTN&EKlyrKQ$s zN3}zrJTe@4m5=Kx5D=Xh7iF>w^|Uo10b(|4zXgEX@ffU3?oZ+yE(xy;)c(Jk0bp)> zn(@u zT_%ko`_LFfhMBBEx#?&Yf12kw2#12m0hh`RO^|6%hD-=IYWp76;(5;kZVIXP zS%~5)ulm9la{XJQD8%Zt*|`*j&m}AqiIE96B=8}Yem}SwznOqOz<=rAfIW`_TYt_& z!5~h#c_9qpn3BbosmcpV7Ao8on=GJqhALd>g%wl_O#kIe+g}S~sz33=yvsV~P-iar z;sG_MIpzzgGtmAoRF>ML+Ij2^Zk4Ib9)kpdKP*Uz_@X7$DM)UDy<~uOfcm?#?@cF2 zQ=->B5&8y3Hm|I)r#ucIT}73ur*gS%Dt{|Mfm*Tc$}!l28AEuLT#I$DL(yk%JzZ3N z>tzSO30U5B1|2ljzJX=Cs#4fXX>Z&;u}~w;gkI%h1p7!UI}##J&tFmsNJ;dUO=KcD~#6NN4AzY;O>Kr+!5{!BwmR)6S3H#I4m9SV&QlHalG9Q_i*2^i<{$kJ<>pVqZ+TxEBQ* zU@N76e!bbI!FmejRGm#+KB3G8|IP*E5(cb8e%di-Q;FhCpdw%7CDslY6U0rN?kZ;U zubxqtxBDe5Op-0p zPGn2~?bbGXVn~ohg>VSMlowk(-_IRVHe;!HiY3XV9-P%>+dv2G^(x&QCFCQVh&pZ^8)kHx;GZeN0@a?h9^E5KNRFuCEvGyDf? zu6so-BEiPAbf6)up59d649Qu0%Yd5>_;FQ5p0Qp`z?UdjJ zID19C!{8KTcBQ$ULiC}%o*ux-Fft4J)9CWSUw()B(@Y*=75XCpeQAzb7l@9l`izfk zhTVB31=m$_q31tRTTS-menfS-=2UG#{5NterNXIy@8BN@<=d)~;6{{L5T8nfC z*ZRlBH3z{1MSX+S!S>p{L~A-jfM!#`Kl`22h>NGA@Mx0kO$MDn_@Qh&fDF8|3$>nm)z|~O zI*5PFs~J@|ADhULpQp-74$#NE_fus zwFUr!*K5_LF$-i}myHDe%}fL>gDX&K#Ws%grhmWn;zk%kS+SWPw4*wAMRiFz^iie~ zKBXd_Y6i4IrRqOA;w(qhphU6U_j_zjk;Tko?~AWc3ib?_myOm7C$w(j4VU|q5rPZh zL78tiCfkbzC&KMm0qj)RwVwm%d9L*x7??TH>(aQGTREo!#v*Rm9(ytToM!otDD@ig zB@&%6sL3}MdQ2@tbwKdF#_D!XBA?coxA_1|4WX~U$kF$f)k-*)%i-XW!B(0!{^D~d zyNC~W{t40>uTy6319Hwv=>&wwHw@zD^T!6D%qn}Y1j0rE)M(aeABLi_a+kyYnM=yu z{xr=24o#5(;tK2>6jG_0uN@D%5k1QWf`jw#Qc&V?B#J)shT|6(-z*|7G+{>$f&s~Y zxc5Az(`ZB7P)$%xFAFJoCam$8C;l;PpyYm+lz?zz1k>J(jz(**{4@3o#kL-(kNIGod$eTDksg{B?V*iC}h1erpkKYtj zse@o;k%xvmL>>CzX@ho|!MqWy;lR_aSR7YRRZt;`BHphq@jAEdJ@0zLPqo(00cU3r zKf#sQO#}mE_WD_vVV}75(G=(ynZnG4OjR%QI5xt&Z-yPooN}+v%mv?Y6!Uu_e3TzN zQOUOXSEm#Fv41TRrn+E61m`)W#2aA?MhmnASO-r$56Wl%8At=pF+gY;8Apf>zXjx@ z0a=>adx?PklgG}6`)5smWyy2JuqS6I9}%r+9}2~5;@Bqko9Z6#V88dZUGM~`Zsg#< z(toK|)n96v@?X&X{eLG?J&oNPN$~I$E?|HH~TnB^4Rk~F9pi)&$NV;g}-#~_Ppbe0`~!Qh_IEjdOd17o-YH+$xTzi#AeJzFK9 zBNwt1Hr4gMA(-AzeWT9GQ06vj>Mj;Lr9hVa58Hiy8;CE0^{+JxxGETR zc)Q$l?4E6h)O?tocma%6&{13v{0LO(0RDF-Wd9E|?GeP+qzNkAQsx4D(yOMz;(-eS zKZ01RyRYbge53~X9XYVUakn{iCOVs7jfB&J-_iU>F&x2lmwPjjI{k<`?l$p$a2o(K zU;TSY*^|1hFrL`r($)1b@KMP|oExER37^9a40A(y%F;bQ>*n1iWHU<7V6A|_oA0r|^*msLUL$CwpLB2UXb{h$|c84022 zDx!hk_UeuKN5aSp#^~*x5SQrYHH<#8yEI}e62*v*;1DwCy$$Rk(8lnp#O$)@xDloq zcr{{)gFm5~n4r+D7rJQi4#u8jORra3Yw&@*-QZU?yH$G`tvY2$ET0k$!CG9}j^7RV z?_YwzznKlyUVr37D((W45n%8x#*^rxl~`QNoVA+Oj~Cs*=Cf%*IlS z+|F|;jJs#j&>2TYz_98^g{?I(?^TDIn{Z3U^Cr=nW9Kb1XgaD_JNT8(?zCs}<-e`o z1N@te?>k&DkCe**)T8JHN{@*Igh&zC6G6%fjHGae2@qG!az}HL)k?^PxO-e9lz-h_ z--4NhC_412wTjh5qf+sDct#EX^GR?fgrR`PjX0JG$#DL}RA=e%%yzMIKh5r}c; zD^{4%6-D%0sZ|_gQPnACC%RG=*=m!59~TZ@*T}EM&5(={q96c{G4tCA;(;!qya0M= zj-LBzMAFCp^S_7lnw985z#Zb>mWp#>R^Z=U^$F7G-{|P@D zQxeD~CIuoA?1_9761un#_9=jt*Le`?nAWRD=`tK3ief2)ZGaf}*u^ zadP+LGN-tWaFZAqCk-)?M7Fq9LT`7{QeF+80zxM-+nvw`jKiylCiMcy-=JNnQ>&_+ zul&YFIuAHFt;m4VKrk%3ra>um1%Ed`G%6b>+U$+U9zK|rpZNkp=^p!K%3e^240-rM z8cURD@WUxAdw@tV_J{5NI*vW^5i68-75lMM8M#kNY|JA^!8FZOM3Qs!3M9*C0tgch zl2c(6w{22$^?P|}TU>!ckBTqR2+7lH(Pmi!tR;UBc2Cm)Fr&|6t->oPm1bprgb2)@0QCs~r=@fC=t~YM9*k?WDog&kp7d-6cka6J5^fp7zgK7jYjaz$P3#e@urz!^m0b?i41gHO zrn8H7V)}S1_eIcoL{UbA1kp%uqs)#^X^>McPSQhD*jG$lk+XVF9Mh<$@z8354@t(9 z@Y~4HxE3Io1*^-h1>{00%e8jB9WJH@qkoe+91tdwqQ+4J*ui)BcP{YwZ`La!YvSj4 zVQi<-Uz@-yBVhyXbO@!zu8Q;E_4oNOXhD}`gDdXAX-^Bh45RN1z|D_NEe z`!83XR+KW^A)mAgL=S# zP}*t82;eWJNV*GnwovhDy4f4}A63|9AR8R9HWsYyOFiUc>YySl^dOT@;L0dHkL^_z zKly5XR?|KzK*>w5#*FbL&O;aDo@=A05Q4J}9FEum*F4a&r41?Ch2!6V#Aau@Mw)Zak(v%l`F zgJ=N#it?3u8UZoAnfyahRW(38n`&W`Qh|3c<;x)D*dQagK!irU^U5&oadwL&CRyqa zc!&CRlnt=(Y!A(YC;__AUP`=)luIZ-+`%yQtWprG1?jH}1hDpuCv$GYyLuYNJU=+~u;0Q8}xaTexnOYs6-mm8_?-!0m*PejYu8#axzgl5H?8 zH%*;w&81?wscF1H%LJb|z zAB;y>OT@IJ5MMYpb>aIWH7`+5zKvamsE_y(M$2GW(QOn4A;h8&B9SCf-C4?g3~qTW z6D9%dJ`co|{6;w#Hp&Ea>lT?H-Ly2u{Llcbp^($q3r?)3{}?vRw4OxG--8naj8JqS z@U_5J{|`_D4vqRG<;d??p7@am!TN}rtmwa#m_)1CHq1Emy9FaN3(pZTJ&i2yN${^0 zS|nO>H9DV#by?=2zat4A{#^@M#3BO#ng`pTqjvwTiyT zq}@p~fkuG5S7IZdNO^@0>JQhofYrGUOjv3`$c)&R$g7udhYz1kJgna2!EUom&60F@q7uCXKTTkUZ8>dl^jJ~jhj<8(JRbh#l zNtJWejt1p&dyeGh2daMx>)Wa7OnXrYAzU70k5e$5O_jSNi29W{)^-)< zlox%G$FyR#(~gs|kg${~_AQ&O1j^95ly@iyG2dg5@E=c^S19}z&DUEkO0?|Y;|Y(9 zw!OTR`hYn(!Nyd^|KK^|HyAX?0q!C4^?DWI!?9F1w_jVJLE*D_nHMRo=p1^Hz?x0e zs>kN>YqT;oW}>WDqJ9rY(Ny}tnGI$MC?|s;{h0bX*^4B6gms22032{)vRDa-vmTAI zcZLOU%%x5*Gy?C^sca)ZClAiC5|Sg?@?PDzb!OsUB2x$Hkl;pDB}23|u^ZdYA!Vo_ zeK(wbFvJ!>lfmmB&XTu0T<>LGtntt>l_ zUC*jZh|e-GgH-gR-tZ89S#>-h(}Aim9sTx{m551Qkv z<_#%>s=ESGW@NL z`zM~&He0=%>_l|cyZl@frYKaidj6Z8^5pNT(IJ5g7JY`LVqIB@D8zALstN1Loh&6= z)Ki_{W6crNv&{6`mi;@2I1p-8GKXI0`|s>bnYJ=4rfiQfSdBTro+G5ab3*)wE}e;8 zzg4Gch~O0T#IDKTb;C@F6#I>B`BT{7hZAL2dCyk-AGrOX)*KbnSbxur|4`@+>K~$J ze<}~gL{*x~P>5phe>yLu!6VrAX9!8K99yy7HqlXm;-lY0G!jb#`=>YLKfvKa;Sx={ z+5G7eLcVJPsb819spY6H*ZAbZ)pPlxuxG4$%NMR*n%>Ogk!o7t{at2 z{1PTwg+NDJEuI48NOEg?lR~fQ_DH8%p^q~*sIn^LG76zUasmw%q6Etx)=i{$lpUjB z;4;4bEgg9ykYbB)F8XF5#!<%ueBpW+#)#5r^HZGDTrGhQSr@{GO}2+Wuf>d{H&?wV z;{-c2=QME}yAYzrW>os6qP1jL#%^%`L;MR$>~<_@4~P$?msU`Ii&3x4GTCu#YJ5RW zbdc7djjR$X&X0?j!J7{|`11m@(5cCw582At2@1I<8*7n8<1H=- z^28FTB+2|+n(&h5stK$Fbv=eWLa6b9DADfPIXz&%eW(Qf54S19OhEpKEaWDjQ?k_U zh13^DWe%QOrJo;%4L*`AtA=)z8Mt=sn}D^lz`H`mT_TXi=%F86)M)7v_+r>_gu{O} z7}^ZOg|~01k5X0kiQP96(3nXyiZM`N@vt9=*>o2xl%viAQ6Oa^U3dsv^5Hg2qIR{Q=5nGvPI@;}Zlv0L@?m%ikN!#tR7oEb%OM~{@u#RdzDS~|Pu8rx z$05gz%7SE^S-M6Y?w0K-Fc^vZ`6qAW*!5)gV^=`>NH&^H$at-m>@C!}<@xEDIRA0Y zo7YR3eKlsaeYewJ!D&z=-aoOCr{Qxq5m6K+wIMa-kVj?gYBqasL665N55bSD=p5EL z`8=V9qekWANT>(>35hutMqa=DOisWUP!A@8kH)_WNd+*FG)z1#uN2s}Mb>V&wgmFb z{?{8qeaWs{Mml8sf6@Fl_OG&UFv0dqn)^&qPt2k5(tl7x{pXFm8!v&zZ)u*1fo@&U zjUL=NxkWs2#~l-K0F3aZpDm>SVg2H9R9*@`=QZ4_O3+9EpM7uQ zVVjhm6b;cu4<6bEqRaQjKx&DE!V&D}NDbZB>QF@bze2x*VACe`V6%%qmu)D6;E*i~ z5AH$N0}_+Jm{@~tJMPK^@*#3a%GSzI)?pY&<4< zeyBz=cW)AOgk@!RaCR&5yaXl4W{Z!2iB+|oP=h1H4=PsPyO=ne297^(CiZXb%$SwO zInTS-IjHER#73|vq-b%us9@24tz-yZu265PzdFyd;jworqEIC{AJw$~k?AH36#us| zf`#7kd`*5FkUZL9;U40_rt_hfSZX7OtMXF^(5`A(A)RnSWi>Zoc-@Fb|31W zn%c?~Nj~Dxse9?XWuIM&>RCEBD#wzqnv7Kgwqn@rHsu$gEfLN-q!#*;56`@WJ z_>VSGpLNvOLbiB*1z$_{baOrhTTIp&HN!^b)EZp1B%h)VO1m?8mhpl@H@1)pfZ3L8d9+4lAmGYC^_I@k*57OfMX=FRmjlFbu4UhBNlPIRpX#rcb za?geT!Gmg8(+-#D`z33A3I{3PDrdp2nLr)#6KY21h49$N8+~fVv6@B;gRM5p^V#mKM!;Gs@S|DkW(LcWMsKoasN3No)9Dx{4}O#1C9b#{`3I zF^Z_ozdM$1%BX+9&%hbvNznJ(T~E)+r(SgbTY8itft>}EcZ2$S4n>XdILWpM>`%Q+ zqk?B&d`g5cq^ry4MDP(rwt$CZmr?q9R#+xKG+<+|j={x7jH;VCGf|G~m&~E4E^2WH zMaS5Omo&dX0{)M!$U0c##rbe@vUDG$l)vn<`BIe`o#)m&Xgd`$SMm?jd041$0s5f% zy;GocjLLDJjpIi%D2lFVRPYkYefZJ3PtKFJ5x&~OfmZx~nCy4WL8-x{MC-yYC(sNO zh0yFyJbfni4?q$-_PA6XEdh33`QERGh z4JYw8s+eR@x~JhZs+4(1<_j?UL>WAd$|=oEQi-XgOq~Aco+YB5o7M#FrXFE13_>}2 zk@x(U^d`Q*#sUZgDNIl7*?IJuvDZu!YeUox>*e2FVs^L;5yX0(nxjv9EWVSboCX99 z--un#qmUkJ4uj}mlX;=JVAUL3MK0J|r6?6o+2LzS6l=!$Y>u>ZOFmk{eV$oJunAxG zIozu4sIy8HFPQm3<9nwwY16o>czsMt8rFnbQwj1r???sUQp?$-bl>dRpO{B?B+0+! z=Rk2lO>uL2fg}hLZ3cGtVDMt;(OSqf_)4$EQF2;mKks>KosEu_(zSAP`?pbV!A}|V zf_82`OM-=@O44iD48ZmJcn@}>_*z}HJ4QvHN~-y6e=0|xOMQlaY;gpq+m&=<8q$-D z9PMg69`$hxDrwFN*i+#aGXD<%ZEwh)9q9u2{CzhNWSjMbM5y5KRaZ(o-|Q6UODcH! zv4A34ZsT{~&0zvH!HEfP?r<+*`q@36wB|+sNt-TS^LiAU9`&$nwncLyO!OI%q*ruw z!eg+}_utX|jn~q$5nMC!A$vYl_U(*ITlx;-8Cpun%KDrh9s-dN=*)lP;!?Dq#B#(P z%*46Kq>;IUe{M6z(jCabQsHN%)*}(&{CWUtWZivKa_~QcNW5Ih;KN8dJE@knc*74D znNL91pqB4y8jJj><{BC(eDU)gOR9%B&{WN2Arp1+TGUJr-~Z>AdK9Sq64*?P^t*kD zKQhuONm}b$Mu(Od^jJOBXV{%k-0Wp^0T+3 z(<$|I*aL1}i`&!b|NX%KRE}O{u7(!AXoJ8Bhe&hL_aiE*t3K}bjPHx=7nKHOo=-=dZ8Vo4SYJH z{7u!h=Vt8R-~dNWA0{e9L&?;a-rsZi;qf#gfYSFW&D*pr%q+V0i)Kk;QQhkP68x;= z9xD&){=f53DJ|86Q=fT7e2i2`-rh<1ezmmVnORhl`+mT0>Rna{!p66E>I&B8*o&0! zuxoN-gIePWn0m&`NIQYxxH92@1-sF|^bcM?3o0S|hNWuSywd@b8+J6&P9>Ek<|7s>%eyL&p8Gqn^B1 zjV>cIOD~9TC)lsCmc1Ei=+8KI;2p2dy8-3LD#uQSgo3qB*ZO+l^5ca?$#M_P1AJPbmkQyROK-YkvW%PMaTJ@4 zg81(jv{aT_w_(6N+HWCivQCbtaaS4>qCI%@eMAVPgQq6>TXYJWQaM(->9?<{NP5R{ zKoGzF0&I3Tyqh-HuOk|UaoL%KEEv0oa}w!yr~BsLO(dk1#v+gHvvR9~QJhvT3P@F73CQ4&VA@YSo$U|4G?2%1A%?@AC`nSxu_fwc^q$FK!Jx zMpI1x*D(grBTJkjYq1Hgwt{e8@RN)ccAomm0@lN=c{rrD0k3OY~H4S zH)7fL-!T3Q5M4)z*iO3HzYk@I zQywY%Z8%wvjaTsKS}*#-cP&r2t$wD`f{;`|`SQO6VLoBtc&WB|9xvO)veQjSNVTyQ zJtWW=FKFWG3fUBb32qn$DB+Q;EY_cnz;>%UKm?g|UiU2gA z(x?3?@%PDnQ5?+!%}oY><$UFU6C>6CHT8x{$y#(Zb<9j)v(kg%2?O3^b&}LBIE@}C zYYW@`oP*b;EStT%u^ZM6a6NkjzbuR|0mZgW^#^Jd6 zAUyf-tBW8j|2~}j7eq-F+vW)Je;=<#eB#H2xZ)Y?FVfBjB;S^#`&_`sfwf?Wg`^)}l*Ui`oNXR5zQ^ zK87toUEp(8-EzGH{W@ezpD3Ptxja9sH}%D~Q-1R^6C68^8C`k0iHHSmFL7a&vv5p< zOSJt=(BHlvs&T`kHz6#^TgS8sh>qt0G#9`Mwe(NbSU3M5C@+Rf+Z@0Z0-YrN6R3_V zgW@~daL&QG+X%NVe;w#H#o1K$(^qZ{Ok=iM&jYtu9~f~1Lpv8Iw8pL5&($)*6)@TN zTw06U9-D0D(dMBF#?Sg>rWT`pxne--ll||4?aD@ePfN@J0G$s{sDOm;kH*h^Mq>SU z5Q9J<-To`ndo0J(jeS)``I{Uc#PDV2bRM!;e8xR$7ItHTtv6>Oe~V5d z2Ch^cWK1Ok%iP!rh>w5z9(HPW z_uaFJ#K`lhzq5$WH!@&P(r+3^L2eDsL_mQE=WDKz(D(U@jQQI@@lxkR?B1vTdF2*I zYD*5KEU(&bzYn8;KSKnVkk~%hIof7Tnai6}TI7XMu=bJqzEVBPx9cDffBj)Q?DNy_ zK2Q@6f9-~sAF^|75cMdpK`~KMqx~yI@Hqv@*-C>RfbDYhw*-_cOqN*9%X(x@Iwh!s zS-lX>eON-2U*?C6vXSe-+GFfii+~56Ex$FylC!zf$_k+@%uR zqhBJ`!LeS<3hg*oj>DsWeg$r{rsaQ_jC_mrrFkY-rZme1pRzD=9Y5gXyK-$i#s;Y8 zNCyiQNnm2ix9S~@mgNoEo~75PUL>^Yp$0_|Xy5O6K#X*R@Vb09B|K}};ae%Rcq8x4 zCL`yc^)4N+CF^&Z$d183DCV(ObkvQe>O7AseXPI2gumY_|m1Anmoa zav1u5n<(f9Evk%~rTe$)d>mN-&~5Zb@I{#rE%WkVC*AGK_WxvteNVB78tLB{RqEaZ zFgecq!sOqC+61xZrGb9m^ArtZ!_s}vd##t|6KX@D;H%L&q$_1YEYI9nTjupy0Z{rf zcO;Z{oTz?NVyvQG(tb~&H}6%&3XcL%j}QSRU{r94e3OFvC06kkqtd%9^K-?z;U`)t z=@8z_f(`W)>&N7Jsvq04oQC=E69xwA?{(_9O!6UsB$p3`*J_SFB+jK`tXb35BJA_sYSD><{Q}D5xMRy{%THsS6&29%= zvoDJb9gK3*c37$|>Fq$cVXHO(uA(;I98U$+YSx>9cC!ub9i(0isF`%`ggx?G6Dk!G2aL13S|3JN@NWI0FYvXYD-H-56k!F9xY{$OK zd{2>*NoJc_r0e6cp_!<^q+U#5N2yE0PH*$Vn5RlxTC;dZd|RAU3pSbaG2=I}hH5mE z;bLFLm4KoV70-YX7AxfZ2)hCsdTQQ0Pa;Aj&z#V#R{wisK%i3KK%2zAgc*~9Fd!Jh z7NiIjU|IT5rGQ@p1Ow26?P>ARNN8SXF#T?p+md4t5H0TBf_lR^;K(v+l9tj^OX@TV z5{P;+FSV$+Cj?jcLOPankMb1$4X2v5<7p;ILy|37iiB(tk{Y4+-!Hfn{pbv|fgw9i z|DfX#XbcyCxROy6IKbn>qyo$T&^8<#lkGr!z^gdoA+pn`!5O64R7CPJ%GF;XwmC+H zLKG71quX@6U+bE;B~GN2N-WyzI`UT$qSIvK&Y1}e|EOZON>fBIWbA3&6q_OsFaTgb z=J&}mx&WpzcowG=i;1In5_k*()_Wi7a3)Yz{uKI75)eVl3$YEQ6>IBFMHV)(gJhiM z60r1uOv+3G>MQ^XS!M?DzgS7%MG;JpM*EwfY2ZIl)WQfrG_P#7)gLL8!2J=GX47ct z2xkjnpm`53rcvB!qA&1$kA@O4z1V?F>_0eDC`3xO@D63!^|3;jC$yeqVvrU4TO4l*InSTwt*rCQFbsu0xR<(hP0kbCQwFRZ`?Zuj(%Q1G`XU{&nJ72jKz@N|k;> z-4g=FRVe5?O%(fa5n#j-OgCfpsAR#T%qqA!#u~VTtBdhGmwmvaMjduCE8wrb_2j%8 z!WQk0bhjg0gzEHPc#|3oe=9QpvZsk`J4}=@89U$068d=x{U5V4_}i)s+Xe6A6!O7< z`XVlcIj_@kGT)i|okaMc-zzALkP2|=YV{_SoY-8y{k6*GtB7Xh#^qSnp6~-I=R){D zRI>Tia9h;umK#|Dy4*&l&hQCPLUoZ9skR_@v%=Fz7)gL+@s-nuV`q~149yK$rZoFQUW1^TB@OpU**EfMI>99AnSjfLqZz{u9E|DM_*16{4 zdn!=K{oy2hY1+l#LrkWse-0J-S6t32112A@&Qt{IoFyiaHXS9@4L)8F_7EV>Tbb3l zh?a(TBw)hJL{@()EITrqR@)82jzE|htU<3a3*@!>!@bCI$k-H1z{=x;xLSmu4$?W& zz*xcjZ7rnj_0=?B4#b*6DfJ?%?oI7J>_#I5MFWALeF zcfVk`tMwTL!l$4F5*kM@l0aaTqWTsM^SC3A9`yrQ>7oYV9E771qqJzCsjBZL>2e4IH0H&QXFLi zhhUFXHBlW+VF?UhEcv(`!G(?dBa@8^hPS`C1kdkp-vP;dso8C8X^2uxfwa0`W{d?; zU(N8T(q{1QLcA#qkwz)u2fb82&~U#JHsTdkZ*9 z;#l9xr2_N31l(u#3CRdr?-ChN?|ZTnW=2AhFtEq27zOlO)NbyrY~e2kF zQdkX-HWuDkjuU8Iyc8(Xfj6cr>=RW=i~z$FBM`#RV?~0NDQR!ivT0=(tP07;>{V+t zrgsp`V6$n9k!{}PwYSu?Y1?{CI1m^0bmtRxVbd%Rzs(brUwGNmI^}cr0wv=(az6rD zVGHIu)7O%)x?@T3&snCw>1~YAtg@c=e3*UmlDsbfS>0N;wTyNf5H9}+zjwA)Q6dG> zFQbv+Jj?`$Iu#i*bSaW6yh^c}oxj)kP8C?4^K=L3+{FhU%23;zh%V%qa0iarvow+| zF6Zn0{Bxz4@dSU)6h81D;eMaZdV8~A_pGU!;0N_i`R&Uf;)tV2J#0j0hxf?>v5{xt z@LkU0W68e3SNQMTpVTbzFYg7|P#5RuaL3sj`MUs{z!nH(vNkWhekR`IafPX@6e66I5P4>M9RlKG*yHtgItX~wh&09k700lUW%Xl{%_|BhATt$7F zvQtSknDu3Nma31Qz`n?<3Vo#1fnm})2|WCmQEXc`WI!?6Uu)l}g;muxK9*u>$iqnM z)(eQ(NQB0yDg1$Cd;*oESVP3S=0^g-shHUK3_ejmn!R^|mV%xKXi7S=tt+QSIw0hB z-4G>Bm8h7nhCW6Cx5&T;kFYKAdTdN|DI)q74 zNUmfuTwt`3my5GhbWaXXhBzDFq?4ldRoH#TvEW_I_Wt{lQ`WMW#K|=s%hCuXqZBI2 zN%w-)T-Do~Z33P?!st*&h2v-$*w`!Ip!4sz{d`-p1PJ*?AtKg?+Y%&XG8FZ!v zTv0=De#n?1HW4&T6VhcCCIl%F8rZs)n5YQvaAHu@l;}ZpoV+V`)>!MHU1zqzxc?kY zaWP@J_!u!h3>;=K9t?paQbTwqRHqQQI^h>Q7~#h1S#yX)#(i+tGWVC^p?LP@ZMd@){`A)X z^s2mc9_Bu0D$Y-ue4A(DB0Up1P$S^epy#xjfSuNDj;1KacXb*wVEnd@3xXO((%7eD z%?D+nXLRyWqLC;Ug$u{2WF$U6Yg;Ty35<5==$UxLng6Bu1fqlJeKrUahJn}cG2qY~ z_d(OC|EiKR@uniIuVHela3-@~+R|4DEBrC6A3^mTj759*J$)%M@b>ef;!;GFu5ml0 zD#Or)c{B=dg{Mx&*se=7f9F6_C<`VIz5H1u4JMsPOxn zo<@C1attkd>6;)a(D1bS>~rRN4F7J2RO{nzoblL1{yolmY=O zq%D;4klq%=f~YC-sEC?E#jc_TM7N7*Zpu>;3=b7oR)UD)yC}N&TBke|6xX7tsJI(^ zf$L+#Q(RI1-}vVzAkAdv&b{ZJd(L;hb52~%_$;*80G(kyv3d)lgJ(EQ69EIsm4Xe` zcpEJ(fd3R4epdY&xqKRAVez?6`09ShETxOYTZ$j}UTP-^fiZdCWfklM5+x;;1as33 zN1bC-fM!6&%My#t@b106tFh6-kpDG--t2`UXf6(kV3J%cFWkqW-JjHYR5dpfb(Lf2 zqR$_IFnMt>A-sJjU5;&bJcAgO#Rs$|;o418d}S%#m+XD0OYT9$@7)scP`YbIFNVEl zp%FAjb^{DV*&CkPP74tx+i4LSw@XDaV?mgT*y5-UcEAZXp8dng=eC)nCJhMN zsro=8p6J-6I5}?BW-E4pxg&+tS2bT%cl}DmZG`EfHi99~9^$?T@B@Ly#_0h1#LcfK z@%OeUtyBBBb8kgd;0}&(9mRW6CHN5t(rstLg30_}6+Tu>#Zf}FsI)LDoB<48>A6yl zXAPn`ou7r17d=%I6t=OZ-mZ;w6Avo(aG1yIU8cR4nydySS+r>b-%KIDErrH%^+}6z zYe3YzofQNVN-)$|tKpag1nCOLdr7)igCTUE5yTDi;RS9}ApiO1KRA3Ove}XiGjP;t z7ilI+HrjNNvQw6zFQKW3*%TGo5sp$)6kHy;l+9fZU2rhXjw%32gIs@vLd#*@S0NP| zYxp2FR}~qdVxzyto%sW{=ikOjjVg-29#TG|+#T=@~}O;a5vdxkZvJ zKMM-^IjDwumq9^zzy?|1#9qcnXJS^aq8IQSMpQ=OS~CAclbl{J{s$?qClZ=V)tYBkDJJ)iYZ3wrflM{FHqmLNB5)Ti%cfF zUX&Z?ucE1vr5@)dHPP~B_E)cDSHTfOF+uW+*SX&a@cz8#tLhO)Q)C0ZH7H5vs~5RX zG1e`Ri)v9lga1IZyM~uP8M_4WXB?gRhGmIO#w`9?Ob`l5s+VX@7%AC<5yrqB5Wfh! zt^@n2h}bx-W=Uj7mg47mYPjBbyANHr>>V6_$k~CoIALip`Ayi=-Q0$^ja^-DV{fCd z^v_CxT&PtQvvfB3G(X1RnR<15TyR#*%W5OHQdOg69pz&>P(pCCa(9&AYZSQ~x3Pfh z8kGO$b$5TfUE{1@T2wQ(TJdRL6M7OWr!*d*LgN{3@?pGsK)nQ>=Q`9M*xPhOlvsTl zjG(1TlO!gU{`3G}?u1c`$U4LGL7o#mpx!XN-ZX)U@^^RW`70B@qa;{HT+Y!i+ch<6yr6?~#c3Tdh){rNU-PBC9Gx)%06xeq zRPpeLhUMsPrTN1d#Vk=hkN<-MLAZl7|2dIc&v1Sp-70? z^b}2ULj!iKAa=-II^+yt4BvX9m`~4;y*cr^ulQDY7drViXH&S$K+J^WLG~&R+RP`h3wZXoA#4R zq3jK!;aF6F>}53YEmuYhsb%h0FydYWZE8SE1~T(3%Fn|8EDA;e&D%KS|NmEcmZLq6 zGXwt|1Z)<6Mev&|v0*eOB0SpOGFEP%Lg6}I9up+*HpTIL@I zrWh4D_N$(PGH~PkcUZiA$!Mi$*|2C#T65q72mwLFm@LtKBj(Z4)`P6Dhs7bXrxl5H4Ux>kqJsp;RLjPspk0;(_-dCM!xS@gwPGpubT(WkPm7{l zsnBeM3d^pOj*|h)8j)WAI;ertGGhJNSnQ_Ed6cl!0oQcn!|#)l_om@eT*Yt+24+Q?+Ci*{1vv;YkV%=+a@-7yYiA2;rE<{^(++c<6N0R z8GWqd9dj8siHjJSQJnRC{>kWV^|;ccR7)kv2o`S7dbDOi9|*OcXd8V_>-BmO`i8Qc zBoCN){8c*cWj1lyQA)iaL;Kge+TbwayI$9R|7-6k)DL`nX)Tk&8bi2AVUi2kMT_xCHOmM+2 z(PGQBvJNy5Hb3|aTifGHNrI+xd5IR?N?^{@WbOF@(LJ6J4BH6tH(3ct3cj*dWLO4L zb&}Pe&j|dl`W|oWl3-37VJ%faVOcD|&J5F-`iBm=_j7)$5-Kj*&go~R8b>GwifjF# z`%H5D;^Jb&)RBm}5~uG$C1SPwx(ZlMp_OvFewpS{%3F1vfUBG9D1X+}>!PZhi zb(WY|Z+RRdchjLr66E><`zHosys{MC9A0<@R$uZI_kpB2Wh@oi#gz(#LrJhNHR~Q9IFuN|^Y3T%#*G52*s*mPvd=JB9THTBQ2B7fmRB@j;_y2UBrqUWn4kRLCMruWlWJh~po>QOeYpCD25Vdpz~ zb->b&xbPBI9~(s&ABXbs@#|PH;=Yz2_eBF;v)%;ES11p8tbAAh42BZv1@EKKrH#0n zqHyzpW?738QPNO})`8y_Qc#P;e^t>b+OHtyQGOhfQ60%2YI$d!>y2F#Wv{-5dM8?v z*+R>}ctsX-mDj5dC!aY@4cej+6=`bpd=*I}q&KQ4)tlim&~?2I4Jp|YETik_vU&lB*Kmb6ja!3kIj$&rJ|56%(cUJErCS+`T=;{J2GJ(YkD z8#P|%E?nj2{h6(~ea0#U=To8g72Ra7fL=SP=WVXB78WHTx1vxAA4@o8pD?gVSDZMh zPQLFGfT2jqlWTa@mPK~9yYF!u6>$^&Tqsur{yE9Uni*|Tz=73$N<~?kve(h$N9uwaccp?FCTHIU}|(wwW*T&jv8+^9na5aT_1aW-g{WEdfoL(nQ;G=opdR!&_8nYgOCaj z3b{#Ahwn}oUF2b2W>&)5Pd#E|C#ZyiY5q~5t76-Q+g-@kGwpkzQXnjAdmSnTUG^w1 z97GAv|HB3$g~bfa#>#GMuReTTmWi4AGOJRh~zw1p>ec&7XLxADXzUV zGg7!KL6Zk_Gx8a4%EvBW((RcW`X+%eJ$N1SBN5-Hlm-jVCl+wwpou0@R)_FgUCG{` z#7)BxID01my*9dE^jK4!P40Fo+(e7`s%U$<1Oe>^$y5YMP*_s&6|L1PtD3t(RpntK z4(ZtLETW72SFfA7wr1XZ6ZheTkJy5ZL-7NA_H3X>yh*Siy z*gB$|i%0Q2B~+OuxA&pbh5-HM67;5pXOo#Fa6UtnWf7z{sXs~tthn(|+yh&BUyDs7 zB}yDFBWX_XoQjnHLL>A zc77K{@QNtbMDRu>9*N1>)jf?Y-Sa!mRd!M(9;T4E_(Rys=s$fsVX?OfqM10>swT(| z2>nb96yY4i#-fCVl?Z6DXvY@UAQhL+1ON^&TRU(=dwQt@=; z9Xv$-ieKQt0J4M+$FZP;2rK2fv2x5}YmHMt$I6t)yBzM3#vDJR2XgQs=!E3I={dA| zVD*lRZ0HrREGz@m8_V@=9gA$4D*r%+@b7ZtM~DWM9n8aOQDPa~LYVZ~9I!G28s$A* z#AYcaa$yu^N|5L!o(Lr~$XShS4Iw=73#vn-{(3~kLbG0f0)&i~tx(@F$CI-JjJ!JP z1O&=bX0ZHb%b818_9|RVu1%CGOj9-rtqvpC9(KT%7?Wq1Y#`W)K30hpnoAeDKXs<0 z5+xj3luhpviH_ui7bNb3&TvS#Pjjr%$T&Q<<(|xs4J(QP0y;qZ5!V{^pIXvTY3O%DZjjmOC6_y!2_&kRqS028UQY4fMPSLfYZ*q(Bos5Xj zIQVK%n@uSc#&|A_kKqI8pYfO#rSK(>=e)1PkDD~MU32I_?L<<0XVzPig9Nl^BevK6 zJjvKXrQAemwJ@V0btq8(J?5!_=088A_9jGX)#z@@BQkfgFjc5MDOmyh-JlugMsHxp z)j8;mjja}ToIBi(p}YqyJBN>aAG7tUi7%%qPWn@$X15(x(goCr{5T3=zh1R@`A}8J z0FSJpSi&|bdr|5=Zrx>NoML*@l)`p11x*ZMgLR6PtJeH8=P4Pqi*gs?F^k?IMPf+q zwOG1bvdlI3|1xeJ+Ws)Su%8amlbDzwzn)j31CZ1I*fx~#^s|W7AaU^vpGI#H@5?7~ z%HCW2h04aONiW-p%6uy-;XPN4 zjIBk16>20xz7L{TqN&U{fN}{TurtGgBgA&4Juz9!(N+zQeZ9ovnRmPCaetj7nZ;&_E!b>3QE^uG;T%? zQ04d`4PTSl<8Ec?r)!?Yh$g~k2`k_3o5P>iwCX5CbZf8W9t6JOH;yeLj#(%Z$Z7~P z-C(M`+OB{e5xITYqU@KyOIxtdIv6tS!yzUSDpXGA9)wa?4i1brVZGtnxwOxz2Y`5A zY$#bR(-GCo(H}qeMJM!MelAUfnmHuMra&iyQB5vuq6WTPxE$w;{=$QaVsypCXxCU9pfGa(hFkz05s!h=qO!ILkw-C( zkyK_EVgo`E6Elvx@Sb|unEM5e&%Gff36>TeEB@StS3?{u6{th4Zy8Fk805~ar&VNJ zZT-eBEg||wZ#9?_CDhO_V|*LDGUQ&B3IvT$QMrWviDX{UV>Cv@p>M4z=rKD?pr0?J z$K7YLjMqQF5Wyyi9KfH-Fj8zIg-@8xWn#b zz=~ODcAM!WSdmG_u<PhQc$e9tE+(q=%#~Tk) z{gYQm=b*`M4DaP{xG}5D`xW@lW?-}gHgxrcp!q&i^OaEs zyPitIA-V<+C+}1$^t-2Vf4>~^CpRjk(E-SXbt>isisbhSZ#DFDZqLYU=Ozlu`B}>i zi7`08c(FE-C{2jJT_&M{P#4E{5VZo8PBxw%#tH~r1iX#vvTgiX6m&_QBBf*k?ZmRS z(x4Q6Jop&?C^1KAR`-FrlLw24x_ei zy##(al}goki0TX|TM7<#jKAR#Uv~#jpB|)c!s`(P12}0g`X$W z))7rm2GBL#)Jpb?@Tr*m2g|*PvBA2WL?!CujL!z@aWT&gGpB@Oq2B_=A_eoSZIts5 zhQlHk_(vZ<%KY|*o2T{;U&V6z{e9#iR@HEFhMRgP7jo_1{BR6AQNe6y*Ytl~oxw&I zA%%^(yV>Z=zJ6Q$)SK}^3Cvw@Jh+&RVC(^^+nSqMs(N#=J#tZdF&K$XR>mw& z)23GKGO{RpIxEOIrSJ=>DW1AUP-Kc)z@BH<45;sP@<0oFm=`0-t$;t2`nz)o@P*yz z#7p(4E7Aks_fOI3TbLk4QG%n})5Z(l%6sSMr~|87q%xWcbEi^W=zMI5^DgJE(NZmB z`St>KTbkI(V#&y-RRXnU=!(e|{VBIaVP^jQ2pkmfxtxjcPfr6# z^E3X(}f1&nTeh>954{E5k-An1>)RI+*w%d=r{k|Lo8M$gEEhL*3`TvS{mT>)e0Z$|N#?#KA+za}Knz~7Jp6aN;%Ardg6pWCTaHtwm{auD5MYHr;-R{y2X1|y1Dy{Qw?6GflA@N0LOY(f zds{Iw#T;85Jn3wjGVt=0%N{`IhwY0{vqsYO0-2Zud99ZFyHOsxl)lF4Mci>~<%2c0 zxDy!$2yn(}_!d2CB6#Gcra5oP*`RC{6yHYg8J1{h0NJ5@rZ*mj5C@G+e+xtH*T?U1^Ozv z5RopgW@}c|2AuOx$&VbQ-`IJ(QXnla1U`ewtok11$Fp#7s1_n6vk+R4Yv2{1-Ah&5 z;&K5cqZ$N%MAQjo^hP5S9kHom`#G9fJ%5OR)keSj`^QS>XyLNKKQ`YjB!cNgeQ2P> zGu*VIs6tQ~>KHUAaoAfP%Cr1*xp!ZPOE>Q>yFIv5a$5bbUL-)I`<>SUJ-P2rW`ni* z>MactCGCh;0UUdV)!1;U$@M7z;L;D))ku>zWIlnUR`Wx{f7s+9l~!Dt53B>qSAvW) zf%)^Fq`XKz%|u{Tk=jK5e%$y_bqS5`I<+JRbt`EH0z zifX?9FF+22LIw3ys@zTqhdwDi}fd;4XG#Q3eOJ{DD_;#BYT=S&5|{tEsR#)BD9nThGE zrT}!kAIRI>1mM({2adf#GgI*rdZT2m!~~G>FXx3hf0*w=Xq*#E;q~4+(XP@O%4^T# zovaj)R5wNOhW9ADF-dnwf)PdiJE!BL9N;Q2r)s{w6UEN&rQi@f?DBndfvZkw z10znaw5Z_?@c25^2C#ytzgl3#t2JOZa}&6YVYVizq3#f+aE^=1DNpL^#a=r}y|qny z&gLLm5<}))50>cUcrV{?-%V!pG&#lQdl^TG>1Z1kF46S4`f-o9>8ZB_HWN!ZOB)#} z&|4TJiL>byRQsiD$WaGKYZ|r0VE>KcHt?8wO$BVTiY1@Jl4*WZkGxA}M*{h@54k2- zn7K9$l;;l$3mpTHBJe#~@)ee+O<);)+PO4olIEl-1*A*)hhr54qeobSMIjss#W^_m z!g$Nh{%Y9~k%BBBOS>PRQL2UcYw_B9wK5oX{6a_(``%SLI$-G2SQA(8Tq-}NfkpBb zEsw5H>+hH3c^x!@c1#oqRClt%=rlA9=~8ZjXr4gVVl5TU=4M5gKFj2{*dgO3J)-68 z7Dk=|#P$*Q>QRD#%6)Wtp<>c5<(c>Y1O7+763?D4Ta>xK>jKN_ZpHQyy(LGRw(S^$fa4*%S$Uy4 z>^WsJu3Q7UI^UPeS_G3+IUjpQUs1f9+K3PO45u)|^RNHewm{*-k>e5wl%vh8X)fSu zpD7uDOz9joMzYLIb&{q?Jw>3R6fUe~Vf7A_ySru6B?l5rO4Xm4*`f4%80H`HN-ag$8zXdNwdK@Fs)*d;M7)*~@NXcFN)c7|==l zklKJ{t%351Qf_A9j~Y_T(%j5YPn>F*z2nq~v!h)%na=s7-p(Bdwyjie-V;)q+t}y|#LBR$km_Am29B$DaT~#VZ~t z8s8%TR#Esr*k1IbrtNf1@l3JkqJ!YG5Sl!r^m$>F7^En%fmsFsdWgV=7d$;qwHj)` z`?!U%q_%e4mXAvmwR)Gb@e)LA4LYgr z#SAP1_qpyzIG1@RiSOEN0AV0F2_VV=n>-LIVRuYVUoyX9ra|AoVX zWk;Am=IeUpMd75G=O-@I@30%y`Aq}AfGb1Sfw6HjOFn!IE~srSQP2WTz2Lihcy)NE zeUt7z?4?G%2!U#>lYh6De$MMAYBWl)pg6%7|2;{noRVc*4Duo17T4!xf3hbVR={-; z^j|``czn~1Y)(+~k=Xr{=a-zL5GsmzhNTarnea?$18tk=BeX7`Y=ygado488aa&wY zR7$gN1RDAguPnPH_8zSn@Qpz7&(7D)yIgbef6BW*w}XHDX{?g^WC@>6S7onIHEOh? zOfJ>eEJ}=n|C?e%%(s+z;}&Af`R%QqBp(Ok^!0BZNB||-m76Pt^mqe3sq4#Q8A*T| zESHV&qLoUNxeLYDIi~k9s#!lH`KAsi@w=X)8I@6o5>7Ndt6e$OQ1fo}P4-A+#IM>{bulwcAD5chg9nHu-dkfO6`uu(= zxU$GdB;7X0!gw?hAq1ckte{|&66CY8DX1FLNZm}w!Cp$7$QKxi09u84@E*hULHA42_^pR>a{RA=eycO@`I3+n8dF;c>fpS+rnebTm?p(tpX4;sPOwwunQ^mMj| zL(!1jN%kS9dUSUOaT_LrcMl~~>_1dcTSCGqvGqN>kEsYsVvhA<3ja`bSVzcB9HU3_ zymOGD0USogd!bcmP93Cw7Q#5;OCxt*%EojkHvNshN=ULI7*fHi6sd_KLQ%+M`CT{e z#Dv^yJx|?b;hniTc>TotRt?#|BL zI-g5%7Zj`a-Eof5td8UYjEQiLiZZ-{w8-`zh;Ql;Rjay_goU}YO^IB+pA+x0Ox8Y@ z#_PQC+CzAC$0C}YfIv>5NAq#3eDMP-TPCljx!CyNK#ttS5;*&?hJk%384mv!KUTuK z5dZCLSXa&#qgK$(MSIt`&81J~4FDqKPHg^#f zh4x88{f#t*!kg;s6oy9F?mNM9e_!rr2w}&ZxO7ZFn;`S;TczQ%7xHUW?*2v9RHdQM z*iN`L7{c>eH$W{adD-pkKhLVaQ8PFNww*wm}U!Hs!wv)Vyh#z@gmiO z$ztL5ans_IGStC{1-K)fi$Rp3KG;3N`>qzEsfXt0hv#0x3aH#wv+B>G>owRZR>Rh% z{J5s&WiJ3)isXfMOg=Lcdud03%bFWOcx{ra@|k64hjGtj7foeWqNAHBfcOGk2Uz6E zm1#;BAPWyGU-Ut|bq_o41_cNkLV`VJBZuj*hILivk8UjohJTsnZDFarrP(WRDpYsV zK2>Bjg1D$wwzoqmSZQk|Pxg?^b{R2>O=r(emuX=AkMAHD$J$kBO;)?$YgQK6ce^XY zT&rQimtmT-IVXDuj^}vt$nQYNC~MKvn|T+Q4N&dojuTH0lxV;(Ux#8kNj;FLw)3al zfW-6FA+bWB0D0N}Ywxzms|`Y{^=E#OsHyp}j6OqmPlPyte0bYqFwB3~f*dftWdc+4 zH4NerWjUNNbXCrq-ho$d0PxD=NB(R64@;j*QJ}xx-5MMb+ICVloI{~e-Di&>zkR)m z6YF%}o38<8bQ56 zPWzC!Vrv0%?r8&VvUJ(TdMJclX*nI|kLIyS`&6gZdMbC<(6KmUygw)pX~X)@&tFeP zqZF28J8e@8xq2BoX$0qw%2C7DGqm4$VPY5rABTNYK=bu_wYf^Xs;()Pn2Sf^R>M`? zzjp>l&yLEhw(DK?extPOg=hWT9 z)7Ri#dYNjy?Nag;y3@EQ?2+x3vbwO~?+}q-xGTtyE5FyoTXDoFnM;{tUJ&R8Z62Rz z6t4<|V~td!QEaNJUd1O2nYc11=v2Bp!5}Td8vNhUoFY`1lg?cL?p(n$phNqlQEptq z%38_irZ06q1tp9Sw(csWyyzbF3#>$VCv5dHD(~j4&+-@20mi}q-gUF78XJ}Jm}?2m zRJXWbnfE}($9T5%a;UOICW{_$r!HemLg?H6($&Wku01LWTxpp@0_-B{I|-9l^cq`4d|! zAp*#TC2=JSW}_s*h4&{?MPA;Jbys}^-*ruMTH&GKTxyq|P4I2`VQV^TF+oZ)I##gC zI4DYIsj@nP(kbYYGp%USVS&ICv|xC&%uI8YO;^9r=#aOY^~r9Inb7W!FBPu8v9MjD zZs%XRV)b}?B zl{M-Vzn!LT#k(gP**cF=TFWikkE#jKmw2ls*+76A*NPQ-N|KRL6M5b{+mB_P&^8}K z7+39ZvGueZcG?VVd-wM=6tu{CWsTS}AS$@}0?4U&qvJkHLE&nX zh>>bW&pL*bj(R2g_m^#eH;p*`k+xa53VXTvRY7K?k-XA;!qad)0*<5k+OZ*qU9O(Y z!JfJrH5C!8mDmS0@dsdpLQB+jqW2&UWPNdVb8duWJzey6ww3FCmGUy*=;pQkIx6}#zX6R!0D8P<{%;btJ|m-a^9iyf!`CDEfUHi zi=u>IIHO6J+_nsw>%FUu0dR z>?M6bZB!8ShbD0^LH&rxutWnAD{0anxe!3?7p!QL?u>Y>5B<|!N)h?ye*-XYHH1gk5f=SxtGR`35_qpIBtNSQ~K;X zFi!Yyul!@dOf2F%zJpGsfR=`(Sfsu%v(8(#nax7Tj*%P&kj+&*lER)%p%U~8x~(Ju znt<2?j7-Iw^Di1RDV+4bmN(c~w!##W4Sex%8Rv)4ypnS)?3#ZPKGIO=D9q~L2vYSF zW%n;EC^0F1&mO0qQii|YU22i*xBpFrE@Ct1unfAw#&ikcnL8Fd?QgKtYX<3SaOE|B zmZVX`Yj-4;6Z16vID0Q$=*6so2w^JnJm>Z1+j?4 zg@|DtgJlDz*(mf&pm*CJ#jt*UdEEUL_3E_;T<=rR<3wOg59XFo*RXyu{s7R$MjA&C z_UM?WSc><0Qd<;J`q;f2z+ucj^IF9&V&7hT2;N6vZ%|Mqj;)R_V3KCn@r!6H&Df#L z?TL-yX|8yW56wY~SrrO6@;3Ma%I}9evHNo0J0URgy8lXvzt3I6d4zZ8rjT}m;5~{N zhr@(mZj@PPB;_Ag)jeuo0>+8z6(rck#LsZWo6n3;QdvKL8sl*Ua#x=Eh>~ZqVz#wR z3dDKxjap@!kd8`Xxnj6I2Uy7sya3`?ubN!I1G~8WLI$ql4jrQ(q^2H}BrSj*FlbRR z|3xU?+60I=&3pFVRjS zfSQgV?zMC|oW%~Kxe?eq$mHmWoF`D~F$En6V>sI>b_=6DG!{<{4}H!FlRv@gomi1kwC)iw}ppXcz!s#2GTUq#{e;Y02>+Y$8sS{+@J1mofI&g1E$k_fKfw&rTnz~$J1B@be z5hUb)b?n7J*Pq_P+ZV38PjQGxuew$SFot>E8FdqKR2x{oSsk$65F{MJxa&38n2CS>TQ8& zx<-!L4e$NZ+B6R9MJ!E|Fwyh1F2UIg>emL{gFBzpww>S7ZbGA=Qi$lJ>SBjZdOX*_ zp+@Q-&2_MAmC7-@1P1kP7V00ulBrXUJE#d7)SaRsWQO;P2#WUd-4pmD4uTd}X^SE( zuQF6K>aoi`P#S&FJZhI@;LF{gLP1E-qnzBKPtb?iF}~+(Cj6Y}$w1Zy%Kr+4OvJZg z@-yg_zA2S1T%^Hm55q6`isXBMYy?+E{);L@-d}%V0wwApLUX+w=8PE_$*}ktTBS8$Rec58;DOhB^Fw;p7YtHL{|9I0d#C^a diff --git a/firmware/fpga/top/ext_precision_rx.py b/firmware/fpga/top/ext_precision_rx.py index 3950458e..a3188c21 100644 --- a/firmware/fpga/top/ext_precision_rx.py +++ b/firmware/fpga/top/ext_precision_rx.py @@ -31,16 +31,16 @@ class Top(Elaboratable): m.submodules.mcu_intf = mcu_intf = SGPIOInterface( sample_width=24, rx_assignments=[ - lambda w: Cat(w[8:12], w[11].replicate(4)), lambda w: w[0:8], - lambda w: Cat(w[20:24], w[23].replicate(4)), + lambda w: Cat(w[8:12], w[11].replicate(4)), lambda w: w[12:20], + lambda w: Cat(w[20:24], w[23].replicate(4)), ], tx_assignments=[ - lambda w, v: w[8:12].eq(v), lambda w, v: w[0:8].eq(v), - lambda w, v: w[20:24].eq(v), + lambda w, v: w[8:12].eq(v), lambda w, v: w[12:20].eq(v), + lambda w, v: w[20:24].eq(v), ], domain="sync" ) diff --git a/firmware/fpga/top/ext_precision_tx.py b/firmware/fpga/top/ext_precision_tx.py index 6b55acc4..07765994 100644 --- a/firmware/fpga/top/ext_precision_tx.py +++ b/firmware/fpga/top/ext_precision_tx.py @@ -29,16 +29,16 @@ class Top(Elaboratable): m.submodules.mcu_intf = mcu_intf = SGPIOInterface( sample_width=24, rx_assignments=[ - lambda w: Cat(w[8:12], w[11].replicate(4)), lambda w: w[0:8], - lambda w: Cat(w[20:24], w[23].replicate(4)), + lambda w: Cat(w[8:12], w[11].replicate(4)), lambda w: w[12:20], + lambda w: Cat(w[20:24], w[23].replicate(4)), ], tx_assignments=[ - lambda w, v: w[8:12].eq(v), lambda w, v: w[0:8].eq(v), - lambda w, v: w[20:24].eq(v), + lambda w, v: w[8:12].eq(v), lambda w, v: w[12:20].eq(v), + lambda w, v: w[20:24].eq(v), ], domain="sync" ) From 42cfa481f9c0e69bfe776c9f0be39c971a13135c Mon Sep 17 00:00:00 2001 From: mndza Date: Fri, 6 Mar 2026 08:39:00 +0100 Subject: [PATCH 056/238] gateware: create a special DAC clock domain --- firmware/fpga/board.py | 33 ++++++++++++++--------- firmware/fpga/build/praline_fpga.bin | Bin 200090 -> 201040 bytes firmware/fpga/interface/max586x.py | 32 +++++++++++------------ firmware/fpga/top/ext_precision_rx.py | 18 +++++++------ firmware/fpga/top/ext_precision_tx.py | 18 +++++++------ firmware/fpga/top/half_precision.py | 14 +++++----- firmware/fpga/top/standard.py | 36 ++++++++++++++------------ 7 files changed, 83 insertions(+), 68 deletions(-) diff --git a/firmware/fpga/board.py b/firmware/fpga/board.py index d5c22361..632d673a 100644 --- a/firmware/fpga/board.py +++ b/firmware/fpga/board.py @@ -5,7 +5,7 @@ # Copyright (c) 2024 Great Scott Gadgets # SPDX-License-Identifier: BSD-3-Clause -from amaranth import Elaboratable, Signal, Instance, Module, ClockDomain +from amaranth import Elaboratable, Signal, Const, Instance, Module, ClockDomain from amaranth.build import Resource, Pins, Clock, Attrs from amaranth.vendor import LatticeICE40Platform from amaranth_boards.resources import SPIResource @@ -21,8 +21,8 @@ class PralinePlatform(LatticeICE40Platform): hfosc_div = 0 # Do not divide resources = [ - Resource("fpga_clk", 0, Pins("39", dir="i"), - Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")), + Resource("fpga_clk", 0, Pins("47", dir="i"), + Attrs(IO_STANDARD="SB_LVCMOS")), # ADC/DAC interfaces. Resource("afe_clk", 0, Pins("35", dir="i"), @@ -65,14 +65,18 @@ class PralinePlatform(LatticeICE40Platform): class ClockDomainGenerator(Elaboratable): @staticmethod - def lut_delay(m, signal, *, depth): + def lut_delay(m, signal, *, depth, invert=False): + # Each LUT introduces a minimum propagation delay of 9ns (best case). signal_out = signal for i in range(depth): signal_in = signal_out - signal_out = Signal() + signal_out = Signal(attrs={"keep": True}) # avoid LUT optimization m.submodules += Instance("SB_LUT4", - p_LUT_INIT=0xAAAA, # Buffer configuration + p_LUT_INIT=Const(0b01 if invert else 0b10, 16), i_I0=signal_in, + i_I1=Const(0), + i_I2=Const(0), + i_I3=Const(0), o_O=signal_out, ) return signal_out @@ -81,12 +85,17 @@ class ClockDomainGenerator(Elaboratable): m = Module() # Define clock domains. - m.domains.gck1 = cd_gck1 = ClockDomain(name="gck1", reset_less=True) # analog front-end clock. + m.domains.adclk = cd_adclk = ClockDomain(name="adclk", reset_less=True) + m.domains.daclk = cd_daclk = ClockDomain(name="daclk", reset_less=True) - # We need to delay `gck1` clock by at least 8ns, not possible with the PLL alone. - # Each LUT introduces a minimum propagation delay of 9ns (best case). - delayed_gck1 = self.lut_delay(m, platform.request("afe_clk").i, depth=2) - m.d.comb += cd_gck1.clk.eq(delayed_gck1) - platform.add_clock_constraint(delayed_gck1, 40e6) + adclk_ref = platform.request("afe_clk").i + fpgaclk_ref = platform.request("fpga_clk").i + + delayed_adclk = self.lut_delay(m, adclk_ref, depth=2) # delay `afe_clk` clock by at least 8ns + m.d.comb += cd_adclk.clk.eq(delayed_adclk) + platform.add_clock_constraint(delayed_adclk, 40e6) + + m.d.comb += cd_daclk.clk.eq(fpgaclk_ref) + platform.add_clock_constraint(cd_daclk.clk, 40e6) return m diff --git a/firmware/fpga/build/praline_fpga.bin b/firmware/fpga/build/praline_fpga.bin index 8b962d2e2a94a86684cb45957aea7436976b1f8e..4eae1f90e10e56cf515bc07f091245cf2b80d5ed 100644 GIT binary patch literal 201040 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%0A?rF=SPvfOYYqwMlhD)83u@ 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 z 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

FCh1E&wqw^Z=)9s)J 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 literal 200090 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%0DSD@8G}D>e(!UaTnAMu$neu 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%0D@Si>>6(Gu~v};9YLW_wh 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 # SPDX-License-Identifier: BSD-3-Clause -from amaranth import Module, Signal, C, Cat +from amaranth import Module, Signal, C, Cat, Mux from amaranth.lib import io, stream, wiring from amaranth.lib.wiring import Out, In @@ -15,9 +15,10 @@ class MAX586xInterface(wiring.Component): dac_stream: In(stream.Signature(IQSample(8), always_ready=True)) q_invert: In(1) - def __init__(self, bb_domain): + def __init__(self, adc_domain, dac_domain): super().__init__() - self._bb_domain = bb_domain + self._adc_domain = adc_domain + self._dac_domain = dac_domain def elaborate(self, platform): m = Module() @@ -25,30 +26,27 @@ class MAX586xInterface(wiring.Component): dac_stream = self.dac_stream # Generate masks for inverting the Q component based on the q_invert signal. - q_invert = Signal() + q_invert_rx = Signal() + q_invert_tx = Signal() rx_q_mask = Signal(8) tx_q_mask = Signal(10) - m.d[self._bb_domain] += q_invert.eq(self.q_invert) - with m.If(q_invert): - m.d.comb += [ - rx_q_mask.eq(0x80), - tx_q_mask.eq(0x1FF), - ] - with m.Else(): - m.d.comb += [ - rx_q_mask.eq(0x7F), - tx_q_mask.eq(0x200), - ] + m.d[self._adc_domain] += q_invert_rx.eq(self.q_invert) + m.d[self._dac_domain] += q_invert_tx.eq(self.q_invert) + + m.d.comb += [ + rx_q_mask.eq(Mux(q_invert_rx, 0x80, 0x7F)), + tx_q_mask.eq(Mux(q_invert_tx, 0x1FF, 0x200)), + ] # Capture the ADC signals using a DDR input buffer. - m.submodules.adc_in = adc_in = io.DDRBuffer("i", platform.request("da", dir="-"), i_domain=self._bb_domain) + m.submodules.adc_in = adc_in = io.DDRBuffer("i", platform.request("da", dir="-"), i_domain=self._adc_domain) m.d.comb += [ adc_stream.p.i .eq(adc_in.i[0] ^ 0x80), # I: non-inverted between MAX2837 and MAX5864. adc_stream.p.q .eq(adc_in.i[1] ^ rx_q_mask), # Q: inverted between MAX2837 and MAX5864. ] # Output to the DAC using a DDR output buffer. - m.submodules.dac_out = dac_out = io.DDRBuffer("o", platform.request("dd", dir="-"), o_domain=self._bb_domain) + m.submodules.dac_out = dac_out = io.DDRBuffer("o", platform.request("dd", dir="-"), o_domain=self._dac_domain) with m.If(dac_stream.valid): m.d.comb += [ dac_out.o[0] .eq(Cat(C(0, 2), dac_stream.p.i) ^ 0x200), diff --git a/firmware/fpga/top/ext_precision_rx.py b/firmware/fpga/top/ext_precision_rx.py index a3188c21..ec01684a 100644 --- a/firmware/fpga/top/ext_precision_rx.py +++ b/firmware/fpga/top/ext_precision_rx.py @@ -25,9 +25,11 @@ class Top(Elaboratable): m = Module() m.submodules.clkgen = ClockDomainGenerator() + adc_clk = "adclk" + dac_clk = "daclk" # Submodules. - m.submodules.adcdac_intf = adcdac_intf = MAX586xInterface(bb_domain="gck1") + m.submodules.adcdac_intf = adcdac_intf = MAX586xInterface(adc_domain=adc_clk, dac_domain=dac_clk) m.submodules.mcu_intf = mcu_intf = SGPIOInterface( sample_width=24, rx_assignments=[ @@ -56,19 +58,19 @@ class Top(Elaboratable): rx_chain = { # DC block and quarter shift. - "dc_block": DCBlock(width=8, num_channels=2, domain="gck1"), - "quarter_shift": DomainRenamer("gck1")(QuarterShift()), + "dc_block": DCBlock(width=8, num_channels=2, domain=adc_clk), + "quarter_shift": DomainRenamer(adc_clk)(QuarterShift()), # CIC mandatory first stage with compensator. - "cic": CICDecimator(2, 4, (4,8,16,32), width_in=8, width_out=12, num_channels=2, always_ready=True, domain="gck1"), - "cic_comp": DomainRenamer("gck1")(FIRFilter([-0.125, 0, 0.75, 0, -0.125], shape=fixed.SQ(11), shape_out=fixed.SQ(11), always_ready=True, num_channels=2)), + "cic": CICDecimator(2, 4, (4,8,16,32), width_in=8, width_out=12, num_channels=2, always_ready=True, domain=adc_clk), + "cic_comp": DomainRenamer(adc_clk)(FIRFilter([-0.125, 0, 0.75, 0, -0.125], shape=fixed.SQ(11), shape_out=fixed.SQ(11), always_ready=True, num_channels=2)), # Final half-band decimator stages. - "hbfir1": HalfBandDecimatorMAC16(taps_hb1, data_shape=fixed.SQ(11), overclock_rate=4, always_ready=True, domain="gck1"), - "hbfir2": HalfBandDecimatorMAC16(taps_hb2, data_shape=fixed.SQ(11), overclock_rate=8, always_ready=True, domain="gck1"), + "hbfir1": HalfBandDecimatorMAC16(taps_hb1, data_shape=fixed.SQ(11), overclock_rate=4, always_ready=True, domain=adc_clk), + "hbfir2": HalfBandDecimatorMAC16(taps_hb2, data_shape=fixed.SQ(11), overclock_rate=8, always_ready=True, domain=adc_clk), # Clock domain conversion. - "clkconv": ClockConverter(IQSample(12), 8, "gck1", "sync", always_ready=True), + "clkconv": ClockConverter(IQSample(12), 8, adc_clk, "sync", always_ready=True), } for k,v in rx_chain.items(): m.submodules[f"rx_{k}"] = v diff --git a/firmware/fpga/top/ext_precision_tx.py b/firmware/fpga/top/ext_precision_tx.py index 07765994..e1e95755 100644 --- a/firmware/fpga/top/ext_precision_tx.py +++ b/firmware/fpga/top/ext_precision_tx.py @@ -23,9 +23,11 @@ class Top(Elaboratable): m = Module() m.submodules.clkgen = ClockDomainGenerator() + adc_clk = "adclk" + dac_clk = "daclk" # Submodules. - m.submodules.adcdac_intf = adcdac_intf = MAX586xInterface(bb_domain="gck1") + m.submodules.adcdac_intf = adcdac_intf = MAX586xInterface(adc_domain=adc_clk, dac_domain=dac_clk) m.submodules.mcu_intf = mcu_intf = SGPIOInterface( sample_width=24, rx_assignments=[ @@ -55,20 +57,20 @@ class Top(Elaboratable): tx_chain = { # Clock domain conversion. - "clkconv": ClockConverter(IQSample(12), 8, "sync", "gck1", always_ready=False), + "clkconv": ClockConverter(IQSample(12), 8, "sync", dac_clk, always_ready=False), # Half-band interpolation stages (+ skid buffers for timing closure). "hbfir1": HalfBandInterpolatorMAC16(taps_hb1, data_shape=fixed.SQ(11), - overclock_rate=8, num_channels=2, always_ready=False, domain="gck1"), - "skid1": DomainRenamer("gck1")(StreamSkidBuffer(IQSample(12), always_ready=False)), + overclock_rate=8, num_channels=2, always_ready=False, domain=dac_clk), + "skid1": DomainRenamer(dac_clk)(StreamSkidBuffer(IQSample(12), always_ready=False)), "hbfir2": HalfBandInterpolatorMAC16(taps_hb2, data_shape=fixed.SQ(11), - overclock_rate=4, num_channels=2, always_ready=False, domain="gck1"), - "skid2": DomainRenamer("gck1")(StreamSkidBuffer(IQSample(12), always_ready=False)), + overclock_rate=4, num_channels=2, always_ready=False, domain=dac_clk), + "skid2": DomainRenamer(dac_clk)(StreamSkidBuffer(IQSample(12), always_ready=False)), # CIC interpolation stage. - "cic_comp": DomainRenamer("gck1")(FIRFilter([-0.125, 0, 0.75, 0, -0.125], shape=fixed.SQ(11), shape_out=fixed.SQ(11), always_ready=False, num_channels=2)), + "cic_comp": DomainRenamer(dac_clk)(FIRFilter([-0.125, 0, 0.75, 0, -0.125], shape=fixed.SQ(11), shape_out=fixed.SQ(11), always_ready=False, num_channels=2)), "cic_interpolator": CICInterpolator(2, 4, (4, 8, 16, 32), 12, 8, num_channels=2, - always_ready=False, domain="gck1"), + always_ready=False, domain=dac_clk), } for k,v in tx_chain.items(): m.submodules[f"tx_{k}"] = v diff --git a/firmware/fpga/top/half_precision.py b/firmware/fpga/top/half_precision.py index 974f68ee..64a23df6 100644 --- a/firmware/fpga/top/half_precision.py +++ b/firmware/fpga/top/half_precision.py @@ -54,17 +54,19 @@ class Top(Elaboratable): m = Module() m.submodules.clkgen = ClockDomainGenerator() + adc_clk = "adclk" + dac_clk = "daclk" # Submodules. - m.submodules.adcdac_intf = adcdac_intf = MAX586xInterface(bb_domain="gck1") + m.submodules.adcdac_intf = adcdac_intf = MAX586xInterface(adc_domain=adc_clk, dac_domain=dac_clk) m.submodules.mcu_intf = mcu_intf = SGPIOInterface(sample_width=8, domain="sync") m.d.comb += adcdac_intf.q_invert.eq(platform.request("q_invert").i) rx_chain = { - "dc_block": DCBlock(width=8, num_channels=2, domain="gck1"), - "half_prec": DomainRenamer("gck1")(IQHalfPrecisionConverter()), - "clkconv": ClockConverter(IQSample(4), 16, "gck1", "sync"), + "dc_block": DCBlock(width=8, num_channels=2, domain=adc_clk), + "half_prec": DomainRenamer(adc_clk)(IQHalfPrecisionConverter()), + "clkconv": ClockConverter(IQSample(4), 16, adc_clk, "sync"), } for k,v in rx_chain.items(): m.submodules[f"rx_{k}"] = v @@ -78,8 +80,8 @@ class Top(Elaboratable): tx_chain = { - "clkconv": ClockConverter(IQSample(4), 16, "sync", "gck1", always_ready=False), - "half_prec": DomainRenamer("gck1")(IQHalfPrecisionConverterInv()), + "clkconv": ClockConverter(IQSample(4), 16, "sync", dac_clk, always_ready=False), + "half_prec": DomainRenamer(dac_clk)(IQHalfPrecisionConverterInv()), } for k,v in tx_chain.items(): m.submodules[f"tx_{k}"] = v diff --git a/firmware/fpga/top/standard.py b/firmware/fpga/top/standard.py index 7f85925b..87db3607 100644 --- a/firmware/fpga/top/standard.py +++ b/firmware/fpga/top/standard.py @@ -26,9 +26,11 @@ class Top(Elaboratable): m = Module() m.submodules.clkgen = ClockDomainGenerator() + adc_clk = "adclk" + dac_clk = "daclk" # Submodules. - m.submodules.adcdac_intf = adcdac_intf = MAX586xInterface(bb_domain="gck1") + m.submodules.adcdac_intf = adcdac_intf = MAX586xInterface(adc_domain=adc_clk, dac_domain=dac_clk) m.submodules.mcu_intf = mcu_intf = SGPIOInterface(sample_width=16, domain="sync") m.d.comb += adcdac_intf.q_invert.eq(platform.request("q_invert").i) @@ -52,13 +54,13 @@ class Top(Elaboratable): common_rx_filter_opts = dict( data_shape=fixed.SQ(7), always_ready=True, - domain="gck1", + domain=adc_clk, ) rx_chain = { # DC block and quarter shift. - "dc_block": DCBlock(width=8, num_channels=2, domain="gck1"), - "quarter_shift": DomainRenamer("gck1")(QuarterShift()), + "dc_block": DCBlock(width=8, num_channels=2, domain=adc_clk), + "quarter_shift": DomainRenamer(adc_clk)(QuarterShift()), # Half-band decimation stages. "hbfir5": HalfBandDecimator(taps5, **common_rx_filter_opts), @@ -68,7 +70,7 @@ class Top(Elaboratable): "hbfir1": HalfBandDecimator(taps, **common_rx_filter_opts), # Clock domain conversion. - "clkconv": ClockConverter(IQSample(8), 8, "gck1", "sync"), + "clkconv": ClockConverter(IQSample(8), 8, adc_clk, "sync"), } for k,v in rx_chain.items(): m.submodules[f"rx_{k}"] = v @@ -82,20 +84,20 @@ class Top(Elaboratable): tx_chain = { # Clock domain conversion. - "clkconv": ClockConverter(IQSample(8), 8, "sync", "gck1", always_ready=False), + "clkconv": ClockConverter(IQSample(8), 8, "sync", dac_clk, always_ready=False), # Half-band interpolation stages (+ skid buffers for timing closure). "hbfir1": HalfBandInterpolator(taps, data_shape=fixed.SQ(7), - num_channels=2, always_ready=False, domain="gck1"), - "skid2": DomainRenamer("gck1")(StreamSkidBuffer(IQSample(8), always_ready=False)), + num_channels=2, always_ready=False, domain=dac_clk), + "skid2": DomainRenamer(dac_clk)(StreamSkidBuffer(IQSample(8), always_ready=False)), "hbfir2": HalfBandInterpolator(taps2, data_shape=fixed.SQ(7), - num_channels=2, always_ready=False, domain="gck1"), - "skid3": DomainRenamer("gck1")(StreamSkidBuffer(IQSample(8), always_ready=False)), + num_channels=2, always_ready=False, domain=dac_clk), + "skid3": DomainRenamer(dac_clk)(StreamSkidBuffer(IQSample(8), always_ready=False)), # CIC interpolation stage. "cic_interpolator": CICInterpolator(1, 3, (1, 2, 4, 8), 8, 8, num_channels=2, - always_ready=False, domain="gck1"), - "skid4": DomainRenamer("gck1")(StreamSkidBuffer(IQSample(8), always_ready=False)), + always_ready=False, domain=dac_clk), + "skid4": DomainRenamer(dac_clk)(StreamSkidBuffer(IQSample(8), always_ready=False)), } for k,v in tx_chain.items(): m.submodules[f"tx_{k}"] = v @@ -106,7 +108,7 @@ class Top(Elaboratable): connect(m, last, block.input) last = block.output # DAC can also be driven with an internal NCO. - m.submodules.nco = nco = DomainRenamer("gck1")(NCO(phase_width=16, output_width=8)) + m.submodules.nco = nco = DomainRenamer(dac_clk)(NCO(phase_width=16, output_width=8)) with m.If(nco.en): m.d.comb += [ adcdac_intf.dac_stream.p.eq(nco.output), @@ -153,11 +155,11 @@ class Top(Elaboratable): ] # TX NCO control. - tx_pstep_gck1 = Signal(8) - m.submodules.nco_phase_cdc = cdc.FFSynchronizer(tx_pstep, tx_pstep_gck1, o_domain="gck1") - m.d.gck1 += [ + tx_pstep_dacclk = Signal(8) + m.submodules.nco_phase_cdc = cdc.FFSynchronizer(tx_pstep, tx_pstep_dacclk, o_domain=dac_clk) + m.d[dac_clk] += [ nco.en .eq(tx_ctrl[0]), - nco.phase .eq(nco.phase + (tx_pstep_gck1 << 6)), + nco.phase .eq(nco.phase + (tx_pstep_dacclk << 6)), ] return m From a153a42b40ae8a466db4da74590f6d3ec1def5d3 Mon Sep 17 00:00:00 2001 From: mndza Date: Fri, 13 Mar 2026 13:50:04 +0100 Subject: [PATCH 057/238] gateware: rearrange registers --- firmware/common/fpga.c | 6 ++---- firmware/common/fpga.h | 4 ++-- firmware/common/fpga_regs.def | 19 ++++++++++--------- firmware/common/fpga_selftest.c | 2 +- firmware/fpga/build/praline_fpga.bin | Bin 201040 -> 201137 bytes firmware/fpga/top/ext_precision_rx.py | 17 ++++++++++++----- firmware/fpga/top/ext_precision_tx.py | 21 +++++++++++++++------ firmware/fpga/top/standard.py | 11 ++++++----- 8 files changed, 48 insertions(+), 32 deletions(-) diff --git a/firmware/common/fpga.c b/firmware/common/fpga.c index 069d1a09..34ebd791 100644 --- a/firmware/common/fpga.c +++ b/firmware/common/fpga.c @@ -30,8 +30,7 @@ void fpga_init(fpga_driver_t* const drv) { // Standard bitstream default register values. 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_RX_PSTEP(drv, 0); set_FPGA_STANDARD_CTRL_PRBS(drv, false); set_FPGA_STANDARD_CTRL_TRIGGER_EN(drv, false); set_FPGA_STANDARD_TX_CTRL(drv, 0); @@ -105,8 +104,7 @@ void fpga_set_rx_quarter_shift_mode( fpga_driver_t* const drv, const fpga_quarter_shift_mode_t mode) { - set_FPGA_STANDARD_CTRL_QUARTER_SHIFT_EN(drv, (mode >> 0) & 0b1); - set_FPGA_STANDARD_CTRL_QUARTER_SHIFT_UP(drv, (mode >> 1) & 0b1); + set_FPGA_STANDARD_RX_PSTEP(drv, (mode & 0b11) << 6); fpga_regs_commit(drv); } diff --git a/firmware/common/fpga.h b/firmware/common/fpga.h index 383444c5..2b1fbe14 100644 --- a/firmware/common/fpga.h +++ b/firmware/common/fpga.h @@ -25,8 +25,8 @@ #include #include "ice40_spi.h" -/* Up to 6 registers, each containing up to 8 bits of data */ -#define FPGA_NUM_REGS 6 +/* Up to 7 registers, each containing up to 8 bits of data */ +#define FPGA_NUM_REGS 7 #define FPGA_DATA_REGS_MAX_VALUE 255 typedef enum { diff --git a/firmware/common/fpga_regs.def b/firmware/common/fpga_regs.def index c575c493..5964657b 100644 --- a/firmware/common/fpga_regs.def +++ b/firmware/common/fpga_regs.def @@ -53,22 +53,23 @@ const uint8_t n = r; /* REG 01 (1): CTRL */ __MREG__(FPGA_STANDARD_CTRL, 1, 0, 8) __MREG__(FPGA_STANDARD_CTRL_DC_BLOCK, 1, 0, 1) -__MREG__(FPGA_STANDARD_CTRL_QUARTER_SHIFT_EN, 1, 1, 1) -__MREG__(FPGA_STANDARD_CTRL_QUARTER_SHIFT_UP, 1, 2, 1) __MREG__(FPGA_STANDARD_CTRL_PRBS, 1, 6, 1) __MREG__(FPGA_STANDARD_CTRL_TRIGGER_EN, 1, 7, 1) /* REG 02 (2): RX_DECIM */ __MREG__(FPGA_STANDARD_RX_DECIM, 2, 0, 3) -/* REG 03 (3): TX_CTRL */ -__MREG__(FPGA_STANDARD_TX_CTRL, 3, 0, 1) -__MREG__(FPGA_STANDARD_TX_CTRL_NCO_EN, 3, 0, 1) +/* REG 03 (3): RX_PSTEP */ +__MREG__(FPGA_STANDARD_RX_PSTEP, 3, 0, 8) -/* REG 04 (4): TX_INTRP */ -__MREG__(FPGA_STANDARD_TX_INTRP, 4, 0, 3) +/* REG 04 (4): TX_CTRL */ +__MREG__(FPGA_STANDARD_TX_CTRL, 4, 0, 1) +__MREG__(FPGA_STANDARD_TX_CTRL_NCO_EN, 4, 0, 1) -/* REG 05 (5): TX_PSTEP */ -__MREG__(FPGA_STANDARD_TX_PSTEP, 5, 0, 8) +/* REG 05 (5): TX_INTRP */ +__MREG__(FPGA_STANDARD_TX_INTRP, 5, 0, 3) + +/* REG 06 (6): TX_PSTEP */ +__MREG__(FPGA_STANDARD_TX_PSTEP, 6, 0, 8) #endif // __FPGA_REGS_DEF diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index cd09b91f..2b5ec1b3 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -60,7 +60,7 @@ bool fpga_spi_selftest(void) } // Test writing a register and reading it back. - uint8_t reg = 5; + uint8_t reg = 6; uint8_t write_value = 0xA5; ssp1_set_mode_ice40(); ice40_spi_write(&ice40, reg, write_value); diff --git a/firmware/fpga/build/praline_fpga.bin b/firmware/fpga/build/praline_fpga.bin index 4eae1f90e10e56cf515bc07f091245cf2b80d5ed..764987b2981c7d23a1b75c76f41c5921e3c9dd0b 100644 GIT binary patch literal 201137 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 z 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 yEZw<#k5jc;-#~D9eEiqn?W*JuovME?Q!q2{0f literal 201040 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%0A?rF=SPvfOYYqwMlhD)83u@ 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 z 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

FCh1E&wqw^Z=)9s)J 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 diff --git a/firmware/fpga/top/ext_precision_rx.py b/firmware/fpga/top/ext_precision_rx.py index ec01684a..562e6f1f 100644 --- a/firmware/fpga/top/ext_precision_rx.py +++ b/firmware/fpga/top/ext_precision_rx.py @@ -4,7 +4,7 @@ # Copyright (c) 2025 Great Scott Gadgets # SPDX-License-Identifier: BSD-3-Clause -from amaranth import Elaboratable, Module, Cat, DomainRenamer +from amaranth import Elaboratable, Module, Cat, DomainRenamer, Signal from amaranth.lib.wiring import connect from amaranth_future import fixed @@ -87,9 +87,11 @@ class Top(Elaboratable): m.submodules.spi_regs = spi_regs = SPIRegisterInterface(spi_port) # Add control registers. - ctrl = spi_regs.add_register(0x01, init=0) - rx_decim = spi_regs.add_register(0x02, init=0, size=3) - #tx_intrp = spi_regs.add_register(0x04, init=0, size=3) + ctrl = spi_regs.add_register(0x01, init=0) + rx_decim = Signal(3, init=2) + rx_decim_new = Signal(3) + rx_decim_stb = Signal() + spi_regs.add_sfr(0x02, read=rx_decim, write_signal=rx_decim_new, write_strobe=rx_decim_stb) m.d.comb += [ # Trigger enable. @@ -101,8 +103,13 @@ class Top(Elaboratable): rx_chain["quarter_shift"].up .eq(ctrl[2]), # RX decimation rate. - rx_chain["cic"].factor .eq(rx_decim+2), + rx_chain["cic"].factor .eq(rx_decim), ] + with m.If(rx_decim_stb): + with m.If(rx_decim_new < 2): + m.d.sync += rx_decim.eq(2) + with m.Else(): + m.d.sync += rx_decim.eq(rx_decim_new) return m diff --git a/firmware/fpga/top/ext_precision_tx.py b/firmware/fpga/top/ext_precision_tx.py index e1e95755..08a3adf0 100644 --- a/firmware/fpga/top/ext_precision_tx.py +++ b/firmware/fpga/top/ext_precision_tx.py @@ -4,7 +4,8 @@ # Copyright (c) 2025 Great Scott Gadgets # SPDX-License-Identifier: BSD-3-Clause -from amaranth import Elaboratable, Module, Cat, DomainRenamer +from amaranth import Elaboratable, Module, Cat, DomainRenamer, Signal +from amaranth.lib import cdc from amaranth.lib.wiring import connect from amaranth_future import fixed @@ -88,16 +89,24 @@ class Top(Elaboratable): m.submodules.spi_regs = spi_regs = SPIRegisterInterface(spi_port) # Add control registers. - ctrl = spi_regs.add_register(0x01, init=0) - tx_intrp = spi_regs.add_register(0x02, init=0, size=3) + ctrl = spi_regs.add_register(0x01, init=0) + tx_intrp = Signal(3, init=2) + tx_intrp_new = Signal(3) + tx_intrp_stb = Signal() + spi_regs.add_sfr(0x05, read=tx_intrp, write_signal=tx_intrp_new, write_strobe=tx_intrp_stb) m.d.comb += [ # Trigger enable. mcu_intf.trigger_en .eq(ctrl[7]), - - # TX interpolation rate. - tx_chain["cic_interpolator"].factor .eq(tx_intrp + 2), ] + # TX interpolation rate. + m.submodules.rx_decim_cdc = cdc.FFSynchronizer(tx_intrp, tx_chain["cic_interpolator"].factor, o_domain=dac_clk) + + with m.If(tx_intrp_stb): + with m.If(tx_intrp_new < 2): + m.d.sync += tx_intrp.eq(2) + with m.Else(): + m.d.sync += tx_intrp.eq(tx_intrp_new) return m diff --git a/firmware/fpga/top/standard.py b/firmware/fpga/top/standard.py index 87db3607..3c68df8a 100644 --- a/firmware/fpga/top/standard.py +++ b/firmware/fpga/top/standard.py @@ -125,9 +125,10 @@ class Top(Elaboratable): # Add control registers. ctrl = spi_regs.add_register(0x01, init=0) rx_decim = spi_regs.add_register(0x02, init=0, size=3) - tx_ctrl = spi_regs.add_register(0x03, init=0, size=1) - tx_intrp = spi_regs.add_register(0x04, init=0, size=3) - tx_pstep = spi_regs.add_register(0x05, init=0) + rx_pstep = spi_regs.add_register(0x03, init=0) + tx_ctrl = spi_regs.add_register(0x04, init=0, size=1) + tx_intrp = spi_regs.add_register(0x05, init=0, size=3) + tx_pstep = spi_regs.add_register(0x06, init=0) m.d.sync += [ # Trigger enable. @@ -138,8 +139,8 @@ class Top(Elaboratable): # RX settings. rx_chain["dc_block"].enable .eq(ctrl[0]), - rx_chain["quarter_shift"].enable .eq(ctrl[1]), - rx_chain["quarter_shift"].up .eq(ctrl[2]), + rx_chain["quarter_shift"].enable .eq(rx_pstep[-2]), + rx_chain["quarter_shift"].up .eq(rx_pstep[-1]), # RX decimation rate. rx_chain["hbfir5"].enable .eq(rx_decim > 4), From 5038dbea8dd4de12994a66be9be83b4293b23370 Mon Sep 17 00:00:00 2001 From: mndza Date: Tue, 10 Mar 2026 09:42:49 +0100 Subject: [PATCH 058/238] gateware: fix missed resets when changing rate in CIC interpolator --- firmware/fpga/build/praline_fpga.bin | Bin 201137 -> 200930 bytes firmware/fpga/top/standard.py | 12 ++++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/firmware/fpga/build/praline_fpga.bin b/firmware/fpga/build/praline_fpga.bin index 764987b2981c7d23a1b75c76f41c5921e3c9dd0b..14b6bfc284947c0e284d997a8ec9ae666f36c8c7 100644 GIT binary patch delta 59352 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 delta 59579 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

L3pqfpk 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 2), rx_chain["hbfir2"].enable .eq(rx_decim > 1), rx_chain["hbfir1"].enable .eq(rx_decim > 0), + ] - # TX interpolation rate. - tx_chain["cic_interpolator"].factor .eq(Mux(tx_intrp > 2, tx_intrp - 2, 0)), - tx_chain["hbfir1"].enable .eq(tx_intrp > 0), - tx_chain["hbfir2"].enable .eq(tx_intrp > 1), + # TX interpolation rate. + tx_intrp_dacclk = Signal.like(tx_intrp) + m.submodules.tx_intrp_cdc = cdc.FFSynchronizer(tx_intrp, tx_intrp_dacclk, o_domain=dac_clk) + m.d.comb += [ + tx_chain["cic_interpolator"].factor .eq(Mux(tx_intrp_dacclk > 2, tx_intrp_dacclk - 2, 0)), + tx_chain["hbfir1"].enable .eq(tx_intrp_dacclk > 0), + tx_chain["hbfir2"].enable .eq(tx_intrp_dacclk > 1), ] # TX NCO control. From dc4f946b0ba2ee07535a3b4d5d2b3ce994da4f19 Mon Sep 17 00:00:00 2001 From: mndza Date: Fri, 13 Mar 2026 15:18:06 +0100 Subject: [PATCH 059/238] gateware: reduce ADC clock time delay, force BEL of LUT chain --- firmware/fpga/board.py | 8 ++++++-- firmware/fpga/build/praline_fpga.bin | Bin 200930 -> 201089 bytes firmware/fpga/dsp/mcm.py | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/firmware/fpga/board.py b/firmware/fpga/board.py index 632d673a..a52045cd 100644 --- a/firmware/fpga/board.py +++ b/firmware/fpga/board.py @@ -65,12 +65,15 @@ class PralinePlatform(LatticeICE40Platform): class ClockDomainGenerator(Elaboratable): @staticmethod - def lut_delay(m, signal, *, depth, invert=False): + def lut_delay(m, signal, *, depth, invert=False, bel=None): # Each LUT introduces a minimum propagation delay of 9ns (best case). signal_out = signal for i in range(depth): signal_in = signal_out signal_out = Signal(attrs={"keep": True}) # avoid LUT optimization + other_opts = {} + if bel is not None: + other_opts["a_BEL"] = f"{bel}/lc{i}" m.submodules += Instance("SB_LUT4", p_LUT_INIT=Const(0b01 if invert else 0b10, 16), i_I0=signal_in, @@ -78,6 +81,7 @@ class ClockDomainGenerator(Elaboratable): i_I2=Const(0), i_I3=Const(0), o_O=signal_out, + **other_opts, ) return signal_out @@ -91,7 +95,7 @@ class ClockDomainGenerator(Elaboratable): adclk_ref = platform.request("afe_clk").i fpgaclk_ref = platform.request("fpga_clk").i - delayed_adclk = self.lut_delay(m, adclk_ref, depth=2) # delay `afe_clk` clock by at least 8ns + delayed_adclk = self.lut_delay(m, adclk_ref, depth=1, bel="X12/Y30") # delay `afe_clk` clock by at least 8ns m.d.comb += cd_adclk.clk.eq(delayed_adclk) platform.add_clock_constraint(delayed_adclk, 40e6) diff --git a/firmware/fpga/build/praline_fpga.bin b/firmware/fpga/build/praline_fpga.bin index 14b6bfc284947c0e284d997a8ec9ae666f36c8c7..addeb7a744816abe13ed0a71924639a66113384b 100644 GIT binary patch literal 201089 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�A^J;yOBVQ=;n}s0!uB1X=5`Cx;|YjfChNLff(ALtgu<(wpkzs zF=OEkEP-j6SXYI|iMTU@iE?-LVjohb3Yv{K;h{8N`75jJ1eP?;5u16^wE#5 zGqy!rM^iN8J}a}6VRYQUy=p;AB65PWd$Q&np2V_A$ep6+S$^>~bSz5lZAA?0L_U*8 zxYFDZeAq!6Ogq6W$>1~mN_ZHxFwp>j8)E<3@dSOv@-d(gsHKs6Umrvj3goD0i5h@D zIy|n=ApeN@)+sd9%-{k$EabM~X#4_GI2mCW!(e8cZdNppkU4qHOEIBysqhc>9M9&1 ztq&G0>&6(p)P&W;K>(Vz$by6+xu~pP$-X272Ob1@0JQMiurg{EkM_1NQ&tPe=-vdX zBl<#xA>nyDsVw#t7VPLk24X>VJKFBD3P>EeiXr|C4|(rEXTTGNKXM0&#*TVM-?1pV zF*SbXCnpEP@G&V|LN|ayl~}n7Y~f2VHhw>00Oc(t;M`5QZx8A<6`9R@`2e8q7K~+>gxZ}eIu0y&X^QQ*I$BP=W}2w z*W(Z9w=CpqWFZ90JWip;t2IoOUB;j(D`?7aLML04 zEO`0w*Ha}y_-?@9fGz8p#dOscoITG{CZvMUyw4jaPX4>zn_B|80n*hxsDUZQRft0= zdk<|2bUN?_P*~dt^yn|l_!<$Oeh1h%JQg@a4?E%|AY;(L5(O%Hz6T$owdCRT#lVh! zp-^)fv-rhY6hVkzznZG2>4}?Q&x6!raIodoKas!K1OtR}X2Z*HCiPykbE$f)$@WpH zcGCzWghm35wJ`iE8T{6!NwgCD^BjrA(~n~$zMu6Y0FH={5rCRoJH&vcU@2 zvycXw4?rHea{Hx}WofG23uimyD*PGHpE@~rdaE)6XbsO7*Wjvx``!Ag8;b}^rEVZ^ z;AWgY_mo~1g}=PVlMkX;FZlsCip>J|pXPL$Y~ipj>fq(NJV@H(Y)LzgiXJ$T3;G25 z+y`}(Lzg@BXN{C6-^rnr@L=L|BON4vW?|1cvhqK5yC`6z1_3dp0s$Ywdy;uujdCr3 z9*fQ$9t|V?0Ri|F5W+x{0gOM(KqNHT2QV-=l&^tTjs12gvs*hK@&m8ed{;Zha2PcN z#z0#RuC+Fqyuk&L@qy8SM=9xnkwOBp zneeWT5|q=8qhkM`7y$bW#?EC0hSk*_HO*~299zPy_9|~&0QIF@^WS9E|42Dkkr6kB zZzBFjR@Enyf%rs~m|LEL_CM<@Fwc4EAgMN8tDXi2f0Sl_?5L$0K;J@{Wg4z16c^`& zR2rv7r%ek=;p}x`&ogsC|8nJS&R~ZW1@z8hu3D>NF#(c>;6 zKp39w2*i?o8hiW8=pxsfFq?J6b}oO>UrXm*1D_=cF#^fqb1B3?UI{ zZFbNo+tjM$>+P=Y9Q7A+w+1T4;>t45?=~92#5%eHWPg!=#-Gw3=ZiF5BTf&BH#@OiKj-{;|P zDZJ)V7%4>*>wuRhPoB85|N%DaxK_BAtXAL+3c4+W zG%?GtJxLqCQI?SkrVHR};cB+@eLBOW(N*vV!c0X5=U8B7^R)Gxu*x%`jSx&2VDXi} zunN7f(hq@>b`qRuF3XjR_s6v1jWJ98@Kts!TFn+NES^!}T#*{bpSIOynw_L5xt6zo3yC_W-u_wh{ z2oH`P`i>qf#Sfi|hnA7a2N(SZb29509a+1s9WKL>E!4ytd!q|}t_sXgkg`Uo+w z#2$!8aqQS>KSR`nqOR`xfjFp#<&Q~;jc;%+65zXQ7qSf0e89nxaUB{-@zH3?qr2Wt zt&5KaIxF2E#Z|Y`W?w!qnqy4Wa5y97YKLC6T2a2?D5#18H9rC4JnaG0b;CBNI4SA{ z*+R)o8?w69GLC%%QK^Vom5AH>dy-!ImeoutN3=z6;It|bI{5GPg-sW0j)C}KoROvY zh*=N@xXwh~2$bJsH^E^B#_Q#xq}9vM_%aGEJZc4RGD$&u6-5+I>f*LJXgFVZK6A(O zB+JOWI*0%)+i@J))vxPFj^bLj3Ty;Wo_f|}V#)Oydtd`zb0|6)jeAb0;Qly{AK|l<3t?)t)wr1UjEJfEQaui;?Bhu}`Y%CI{-va1O9WBrK3I%xdif zY8TTuhB6te99u%K8k5_>1IZnU6@nPpl2VX=pPtYA(h)!G1Ipeip#!?2uTtX}sj0Od z+OOM(Qg`%w*^`U|yKV1_EbWuN$TH0u)VP#%*n>x(#Y}>^*eFEwKAHHo2C-xI? z9K2mdH@RPp^<~u#{6@N~1Fyc!)q4f9%&=&@*P)tKVFqpR2C8^|)~c0*(ui)DHf=8k z9_Y$_GCW)l;rujN*>BZ0FRq4ja)DsIZIpWSqck~%I@g0QQxoizIat>>Xwl|;8~aDGou%j%ZS8}PUh`MitLF2xQ2D1&tQv{Dz26`Iizjq;m5u-{ z6us9d%V6SmV*t!%&n|x28i$hv_$Hcmi)(F~5QFK@_yu&QU0VmoL0`eK*@!5nv$fiH zK6V_VQ%u2ST1;G(>NEi0P6h!`(v6R~PO0VFkvn$r13K&g<$cnleZxXX4Pk4oa2}O5 zHq2%_l_T(V-4Zge-ve(qRR%CY%X?DvP|Y)IO|G4e@{!pJL_b>27) zAZ5B17jlye566}Jhurf?P85?l>mGpBpcd$K?+Y&8s5U=yRIghXT(;I z7y=b@8rXa<{xYw}T|K(}p-+MD zvMbAE7qmpTzm%G$z~6N1)34?dnhSi2!_$qSjRq26Se2N$e^{8q=8z zxrT9%Dmz6oA5n@l4GBJA!+7rljE4CYUjvoZNqK|Fnm5M{){bv{jo=2ADq0jc$_9Wm z#Qv+L^u^b`Yhig0#{X+XYV-=NysMzq$ZGH(3&6L-;VS{Mf||(Ib2<5FJT)0qOvZD4 z1-MqEM>82v2~Am)U-2yzg;`Vkp=Nje78Y|#O~ao3@=k9=mTuu7CO?j9()tcaioX;I zJu|vhALyE>I8a|m>qM9oRMj=Y4N^#AL}1s8xq6N!V;HL!W!TOV+6GXfb9RQ)Q$CfD z*qY*2eI6gk9BlkCUkh>6bNk=+ondeRbv%VVvy_@fN>R`pNI`+)o&=NSqT5Ybc;FTT zH=+}gu2kv>hA&$v>Tiz$?y;L$Dq)7KleDlHEQ7B6Rc+{%x{H6;OThX1{8BswqqsLS z-a;_Tl*F<5Uzv;68H2mfYKTgGydL`CC5ECKywaAw6^n8Qj+E~N(ibxaD!+d?g~A3; zq`nSOXWU$?jdU?3Ag;LH;XQ8yx+8=DF}6Cu25rl)?$4Yk1^kR&yU*}v{8c*1WPrBuP5*rz=agzoSxj`*6o!4ov#T8<4YSH%!`{wy^(g%oLwI zfm5*h!r%=$?;Fob)Eu)89`ysbGPlwv8&o+I*RlJeegIl}z3AGyr15wN9s)tBMyWVHsWkQUsB*XUuAw0rcTx;9pIkd8ja z%P90;Q)o3Q{=z~UxCK4H0j$t%L7MKtrQ72JZ+m^{YUW-HGij!$#ry1EJ)~U(-H+&F zO?h1mcej_>M6O_gAq&mLzF3feMy&6=4T6IoLp~>heF>l5&a0jfKM{7oy29z;B)zcA zzXa*DHgC)-JVKBY&w%meN(A8kVpI@$uyFl{?fBoIc7-V}Ad^udXb!14rG(nI0jZ^E z<8U<)ABAEYKUznyPUP&C|Ci&7ik<8az!RP~oHWI7XdeH2+(liKwVh_v+~g1?XG2Hy z_Ts{&>dX4Mef}cScO4!SIEug?l+aV_2P*gbp-#utz(sqv!o9u#`*$3NcIfcEBhkL7 zJ8VBr>>A1+^9@~n7Uj#(M3xRRSoKtpsdTYWaRF~+O{Xt~7$g4!omWt-SrI(*7A8Oc zZ6Ag2*J%u)D=t8NyjI7p7u6F81StcA1FN1s8H~b)N zJarrSBzZ4?UcAXq8M-3xZ!0ww1>UW4AcHkifcS^v*U)NhTo&VajZi`bo^)^waxisD z*K8WUau}F1G}HC!>pL+2EA$I+>&8*I&nAj;5X7phi2-Y}C%Pnw7R?ehAaFPkbueYm zK9Dh?!cF}#R_$@b)l~JHM^G#k8S}Q6WE3=rhtahQq&29_E01aL58b0sWpno2lOE(FQt_R zJ@?_ZeliU5+}u2S8kB(Cg<_JX;o4Xalt3|dT;MXa!dZlKnmZY5_Q+$O&p>E*Kkb{K zJpi=syhd>he$zcL@PcuS@8sXS3qp@swc(Cgf0xgR%tarbfAAh zu{9N)JKZ%)*~D*I_c=hWVT~Q&;N9>Qwgu- zLy$x!ppz`Zy~0(4qww`<5}*l|3hByu_1e^DAkjJ zTksn(mRlyzr%fz_-EO?`x3e>d4S~c0zwe^F7A=yHKN%1v~4#s0TxL0}_T8w?bt?2Xz_;s0o_S0er+>(W2*a zrp3f=O-+8+v49IT7ShJqJWSq8{v4~6VIE20pj7t)1gx{wbhpq4%NN{0ILlUVpmHjT zIDH^P-pzx?zpS4!0y~Q^-}z53!;q#s{ZoJ+qw_oxb=2XYo7)X1V8+V@yh~wf`LS`- zu=(l~Zc%=GSzKamg8$$1RUWFKs-fZZNuGSVaAS;k=FaX{K^Z>n5bnWj^G~FB!eQ8b z-oYKf&<-Qwwb2z>kURcuT%{MP90+BV(N%~dY>^34dQj$~45WbWen;Kp74!97{EAF5 zO=y3bh8Kz07%#RpUxkd-Ff&jLLFVk@wWA~mP%)*SyRwiW6Y>)}(c~Q-(!f+-dGOAwMHayY@HVIZhM)>{6y_i{YI;8Xf1|ouDhV6COdG=^TS$de!=s#fcs9*vPXMj z`*&e;^w+>xAfQ1P6hmrpg*u$_5ZkRI!#$!_BsYVy>Z{V zR%6rEe;lQvfvp=<_%3Q`rX>5f(`rOxaE8>^ln*48-r~Kot;R;7jcJ-ms3$1?#=CRq zTTUydf^#2bQwT!6Hy{P=dbFksmH<%n=#N{boBA*FYnS*#qMvsJga$(DC6wEk!l9Jq ztQA?+PFk|@=1R?kIi&+*(Q>uv4sAw%G69K=8o zPf@f$qk4XW28TDYa&-Z&Ief=&@3@G!u`FBg^ZEc(%d02ahz0hmB8H6jCtex3w=Dy^ z6#tHPp*IyV@?hy_-b5TBlMa03Q6nELHaYLl(}vV@(ONf?sxF=J8Z+a^Kw~E6T+Yh+ zt4o=P&>y{4_B>Xg4KPt|FX5+%O&T8wuZa5H5yL}Ep2_AS{Usk9JExnj+e!`2Pewu2 zQ@&DD{EoCTKfjsg^?UH=dw+tZVD@nCT*UJO72NLo2Q&*w{%XUpOK+;YhGh2_y1dH?R3) zz0z}2=t(e+E5vlF7b~^&mjbBv$L7*U+W24JC3Uwi+plqtgLs?~JZ?Idx2F|ief&-f z56nAsW)I^4$|7BmJRJ~uZ&#YWcLI=8q0~#>)8W}o4#x2J zub&{v>y;2_b-E^zfX=XJ=3Q`t|3Pan2Xl{Wclo>z=&0B!&0zt?1~Pei&Z78vfh@Z= zxe+yn2VrqYuYcDuFXnT`Nw{+(k_SyI{0!^GkDA8Iu1hM~O<1v{$BH-V_QD5%&x*zG ze#x@t{Oi}l?aw_{j9O|5;eqql@P`lFA%@C=*+fT_kBkPY8Z4c@xs&HmI;3qk z^3b54X894|UeS%_&bXe6?=t$@l}O)f!xWmQ7UuiHX7xbwKciWd^$Zpe8Jb7u^Sm8s zLpqfz(oh0nGidmC&@jiGLWR{Pd3I>p2o`N4Y|BOFL}D5I(&dU^htS|vQbYp`nIFKl z1Gqw=lE&mX_@F4_QTXYAAmz)MG%Dp@i+%Z5gf*d(d^oBh=QG%3C}N!reUYp5%n+1o5uKEET^_kA~#$g9?j;B|~vP%qv_ zm+15QwlAfzyYHdMpXe3K`%RtZ&?RA(zEGdU5L&%XrDolCv?^AFrS$Gdj{~CTeeT3A zvK4bccPjEq+-b#b`5Pa~5DNL=i(JJ=BB3}zi$r1n@}0e?kOndYvhEat_3!A%g4@Yp zxSRZ6Y=o)BK4xGODTGe@7<-Y~eTnDLz#C$(GlVLvp`B#o^Azd!H)#d>PA0J!=2UtM zmd}DGX^gDb7KvI^IE6WS5^Ck-y^Eloo!FB08Z_&58z_LspA^2MY|!T2%rjIh@$%q3 zaFd=PnWc$pqaLd7O&_O#zJ}|u(U$bniS-n+ysR{+?xta+wiEKO)zks1YM5eFw*!2K zgAh+KiiD}cM171}GZMp2A_Xu2Ekk_zCE7rt=V)tcxk-VRjF2@%qh?K{sLfm0eJvZ%u${aoqDU#Zez>4HUS;667(o**Y0(;4n9D)9 zh7MLnS{Hc3MsE%K=;_p}!{on^6#(s+B5JJq`e*r0E3ZJ2ATRx4OMe;=Z_xstpgyPB z!kR5qOPS@CBDI!lk@oQSY(>xat6{gIM$5;X-^$R_F{CG{SKvu_3(|Z~zfnRHaWR#Z zcJo6lZY7DS9CnR9u79tT^`LJ`_&h{^+o@J8;j2AHt8o<6O_!S!qj*N*P>5UPN`%kj zu}V_ac98hu)<3Z-;l`6wmf@>d5uiw~MX73)-#W_Mo5n(A;3(zs0{x&DxNfi7Hq02S zJc33Hnf~D*x-rUR_5>lHPaY4EzFOhpF@=DVkji_%AB~Nnn=&rjEADJvN%@}1TEY{6 z+VAtv&PEC?97y@eCI&k!q*$a`4r1*FDr>xrh048r+`OM%94uZtEAF<(JIHv(XlM|l za{D2o)(M`GxzG5#Q>08|cBbtO>6G3U~2#+EUf1aE>Zc?xG5V+BXUEmOgvWICvmL(cl77x^9SJX0J z;)%q5g*KaqlQ*zu(wqP=z5ZWHV_Hl!`z_EjdN}y;_yGQ_0RG;LMAXX$i>%S`C13hhuZ=-0zja6<3bTiLvmQku6owZuZl+y6Ssv2E6-bZu zY9pNAxfRboO^CGTV~Eko^lP6ClX+KVxMQ$k(m{)7dS8PI(I$AUoP+va6To>t_r{WB zz4#dyeVH|YF6NLr6wN}?a+bI5F{+1Nkp7N`Yq#q86L5s}YELKz{dXfx&XI^$XsG^TA@!iD&-FMp$m^ zY5VLGdI#BuBm=3&xWFgnsBtTb>GE@2+PyrUh!+5)H4r{1dM>0g%=pf`(^!6XJRx&y zWQv0Nakwg!^YsS_2YkC|+t}P7?k?j_{AY6pB^sq$)@<|+qC_t`ueVbNCtW1h`8=Oi z3dG93;?EIw>(5_#CMV_^KM;Td1%%Q+pFqw8|3o-B0@Fb2BT6|WsImmLAoN|{js?_! z0aP4d_>RjE223)8y3<4zhZP=BVLLe}-GCCwOG2-Gj~m_vp!81+a$QkoE>pE ziu5$TU)M@rM1Tu7DZn?F={TRGC|K%jJ(gK zGWbR$Rg_@=B|s%sk`>|QVsks}^dI4XIdF`|1i{|^iXKi~PG$AR3(TJP{)kD;?vl|C z_zpCe%Ds{ZYFZ;m#@~pcD51% z3llk^W^EKDzq z`Q=Csp%`<66z{UWFl}@>i{YpnUHN^qy=b=_PvOWf#0Yk>W5)91dmNDSjBVIk9%q^6 zoFC`!CIJ4Mzsg9X9Jrhdx>(|QG&&t4VQkJ)5ItkUBTA4k)OTM45-?saSqiY@Fq+(d z(2}HF$Es(M{s;%pD$?#5z(rU75%yy5>b_Ck66Geze}b;CFpp_g!z{|B+`^%NC9yL1)*0n5+02su!;sy>dW5xoTUUBH+gM;V_&50}F@()IV3f5jc3a~S9_g3>>_W$U56X>X_>|K1HbH}Pwl3Pg;0tC1f z0t5uT8Nh%6PKCi>qZWf0ajGD#L9s0cH6r4vBn&D-F{r4t79xs>8kAOSryBx_8tG`G z(zZhZ+Mr@vVNj%P`G42n|Gl-|dh6M1(IiyedxkylZ|}{oRYaVVydQcaWnwuqNm8Gd zO^<`|7G8ikMLl>8khiIkHTXT)mVx8D)vQ-+BKW}`=t?Z56sp3=TyVK0e=mwo!B;zh z#zB6y(ttlf!fdz-01XGm#3p0Y*OyR? z{5Hs8AVuX{*FKGqN7G`R!AuLM_tUenG)T_%kyloz#1xR zH01RxYyzao?q+3-QhQ06!TNYCgTovLgB3Y|8fhuxHX`6&3@W>ms&S3k-{JihzYlRiexzV2_6%DsVmEoSOzemBrMQp^R>8c)S()*ioj{m(?Y((x)w!5qM@o4u zT4>+j$bY0!MI55liuYCQ^CQ`Me-o%36@f%seOY(-uU&6z$q`5Uy^TBn8XWEX`qS5o zL9A}Q!Y1l$l3v!NqO>=>CX~;t!pjI4GNqVYX470(AQU*@+dp4TPToHITRpFCkQ)Ap z|5q(x@-OLhc%>La;U907Ej()CoZ==6Xe1 z#%E?Cz5~F45jCPGdobk>kQwe z1aegV2lW&OXmp$@1w;QfK8iYfqU{ex#{ zl>lAkKGqN0)^P#zV(d$8uJX1QF;=hA###Jp`!#jVg2js$p?q-7f&QwU zNMkD4e{p|#e5)2TyXoEcB5hpGsnZ{pvl_IS%(W>-BLM(LW&g8ZPiWB2bT4{G=AphZ zUVtzg64?--Hnd9`DqOOS5}{P5JvaAxGAeu##j?7fzC@(+&&;Z2a*Y zr1%FI9~A+%Lq!KK_>Q&H7mfW&JD&6FZRj}Q@PlU<-VUzADapXs;25D+EC5ExYGp9M zviHL7Wh|(C8i)a93{i2DZc&{+Pv-Sl#Mko=S;ns|$s7WI_j%qebe3}=0n>%BfXN7b zY72#}-+}|hnwI5WhcL1yU4#--9;hTM2=}S8&!4lLU+4dJGfQwZ+`?Lv^-40Y|B`$0 zrHYfk1h8of@&3v?f5~7t@htVEE-MBatD191U+5*@@@ktAnV?gpD=N&I3pqbpdu z%arr^^;o6Jlw1h}&i+8MGDM(iB3q-b(Y!iF%6}Kn1>N{_%XdMwsPv4q0SL`N&=CxO zOC@mDv7H%MYNAR>;AIGLV&5GFPtCHhj-E;QQblbxUpj?4$+VZScUBO8>(4)!H&9pk z?V}q7$cB*S0PrzJ0_y{3O7QzGlJ@Ul&tm)=6oS`Z7%B*Mtx8|Pga=-T21{T}A$ReJ zA)NaC^gWh=zPVMP4>ks^-4JYA0FeO8!pT_5*uW)?-DvL9JE0>f`2b9~j=YqLlKm90 zLPhV^*GxyzE+v=X8Bu!c_1-y@tXmA7fq?N%rFc(KTPX=*zdKEmVS&AIRE6`^l0ue( zhQs=X2`(lun{t;T|IeLifKp?femaENIgSs+3~d32rBp6dsCFx zVHH)Wg#2yPgc6FyYUm)@#IP($5i|yFIYR6QM8(I5S20Hl%fsbX?B5E92%TFhPL_;J zV8Mc9$W+j0SaSIr>x}H8iey14Hcc*k=?n!L;Chj2gXR&Po;;9zZKzI)ZX zRU9TAkG2hR3Gkd4+!i2xQY?*S#h>kvxJQrZ(SC(lW*GOFjVI#_IHNt>GlxU`5;iu} zXK>3woYYAGS&!49tIUHgB12>dk6i}Ru+9)dTWF1)J&C2m5j2)1t3NiGLVLU*`e1FK z9pN-cCkD{-VL5}H==1JuPj2;js!gK*VMhVlLm|A9Q%6i()i$W+C{a@m6!o2f>Vc zZ{%CBq!6r&cHZlwq91_W#9p0Y>UEYIVv6%m9)bBP z&ron~DaAi@+0^VwRasP)U0IWlhz^1_T!4;ao@Qy2&5SqjL{8K!YMbq96O@?@+Nq-e z6}F7BLZ7H;nvYaSeO4~6SKEe&!L*U)i_Gzny@9OC{@PUYNcpVAWgz(qiy|Ang0!-* z;(V{r7d$^up>^_b14uW-#s>bq6F|STD!O5(<6gqq>q25RFiUzV;|r^ePPjoa-KKXK z6h7E!bzxW_K7c?-0ksw&Ne;`$X(wx~W@pJkRCe@k4El)*!zJ;qa$N!obOM)=1=Qbh znD4lE5r;rloX9v1$0hKd8XSl7{$9ywijsY7#9qjC)-nO{zc-Jx%Me0cGTy3Nu@V}G z2mpojDA4G-High{rQPVrv#TT+&u_`$1~Nchdb%j(S!P7{a(eh7x26*TQa6F3*=hzC zb-u!0Qf!refW@QQ!)Jd?tHF>K>R8zBBC=9xs(`mJ1L76!%66)bzb*!WGS#b`wHhX1 zCo;8^x-}l=Q?7a!LD+$iO0s*01>iO9*J-=bzcC$95Liy2-xG!kQa#ALaWt5^DuhJg9x^1Gdt!18~ zuyk=RSF=uk2-=}cfPG3s)*v8v^GO{@F9o7`CNdS0qQy(lnMSuPh-d!NH3EWU(I~SM zQPkTj`La>QbPE~?8S5^h+MnHOxCzX)z6QtDEBOG4jJ5a%h!PNi{5NY$BUkzC#Tp77 zrY%E8P)#&VfC&U;P$+%EZce229tNzk2EGI;e+sul&EM+urXDnhYW1YkSdEIcF4ePu zGIXtrSO#cDg=-$aLvc!#qem13K5a68P?Qa@>P@R^k+RXZ9h3-2;n(WVMiA3r%7v1u z_ZE~w-+XvaEM=sEH2EHUs%fOE?9wgdc+~@1w8(9wTEyH`vp1rO9sK16&-4gXSw!~r z%pyQZ3fU7N5ESIl!!OAnP~UYau_qagCHlyx9OY$Oby=z|6&47Iy|E>xm6`9YjjF{} zf7qqBpPq~j`0E^;p8UHO7V>^Bzz-HeAN&=iX7E(6VvNQc_Q3T+J-rme0s~jbMqb=+ z5zIjVnB{!3D-$D?gH|h;ff1La;xy`&ero6owlP9SUcvUjFt;c($ET>Dv=;cHoO<=_ zm_trz5OhHjBg@nf>=r`tW|Djo5eF505_)HKTX;39X*wAx{s&TcwwwWIQ7_25yPBX| zS1QY)fOpa3)I_~roWzP1S89_TDh0`-S#+E!5Az_#TC=6f1oLB2yj5v^Zz@QKxL$`x zvG`SutrmK)o#aZVKL)`m<^qT^zmQ4KZNG-I6hi7cB3bKc*!>^n^jF%5VXr-XwkgF+w$VsN(r17&X6C~klgd7_eZh)xe#s2~t6}cLf zSA#PY5j>6L*=LQ&EOz-@i2A8bMTSI=Y6xq_A@w0^sO@h&s9eG5W7DZw&QBQ`10n;> z@WBr@A9@jyDHpX>3Gu!Eu=dzEDskK&vteG`-@25F0%Ab9%9ow`)eAK8G-1i>~)$LUJJEhhoh>hW*+86M)RNK&?nLjMRzU zmDSQCh2K+E>;`gT&2oh~U9xm8dr^TZ+-_F4)gO_>22E(a#mIBN#2{OE&m_QhUWuSV zb_7V+UX*7~qp_`zNpmBQ(ws|4p35sn3A;BR&#ek7%PHT>lwVCCp+VgOZ}GH zPT(&t7({(Po}si&&a2dUPY30IdkC5hLf7o_Zq1{W>NXpzCX5x6Ou*72ux+vu9~1&< z>|}QLR(w!JSei1uERaYk5pM+}fOhc!V!d4i&GGSwz{k3c#S@Xe#siXEokV|y`5CB% zX9C?>K@KeDT$=aUBa&?L#py#kL4>c>d*)b45Ee77{%x7W3y9-6m}UNc0kTx@vNV1e z;fB1N4y^&23Y>aKT!CL^U2P-6BuvB>6HzM0H-4F2&YNJY?tjG7j>D@#fM-5>Zk+?!?g}+Oui8j=5)hU^&uL)os{0CGboH z*YRi3!_>t(Amn8ba7G*lR)J;MQ9P;Kmm?B%DzpUI_=~M(d^(%CScbJEjlYK~)N^rG zAoUMBA-ID}pk81SEyY{~#2+m5EJpA>iy|y7do3p{De5iLs?jW>~9jDSu}DIK<7o5+py=y25Pg)bZvX&$)2x0WR22WBICR zod-!i#u(=bG`oY1&xOsLS~~{Tjjg3wHhp=T(eqUP>cO^q$)+L5!W2^SIa==ECt3Qz zk7#t>8F0wUEZobQl=eL&VB_A!!rcA~g`?1cbKwood7sSxvbazoQk&O4LVtm;MHqJ= zvXc+OVbDuRabcRx@9)Au;G|FtV7ieI-)#s|3ItNp>`;o5#%h~Vv1KIc=r}q!pl8s! z1K1RXz_GNU;2cbr!pX=nEb)0IVf1YD!+$b%BLiqQqyoX&3`fG^@=2OrbTkf4Phlf> z2VXiGcW;TT%nokF%2`*5*8)MBI1LkdHqXvTLy*_ni6$iZ=u24i!lvJq#uJ~LeQbQJ zj^0&XM8wdWQB^ER+w{9v61G)9-al}0x(*vhQ@O2KFHv6S8sho9#VwV@77fB#(r%2G z+{#|A*iljq`qd{| zsPC*oh2QE~N45%66rBSUi|wZh_y$-(R1^4hG=mm|daBwICLXr` zmIJFj_wPf;y2O3`*?J;6d->8TNW^SzFDQS5*|r?V_;{~@R9S{X6Zw)sFdHC7k&cYu zqSD}^Z|=s47S1Z5gKLT=OVb{hEE2CBm?1M} zC+SKh%%`DKEIF%wB_-`KQxCQeW?X%-O* za_k1}Pw1n5T)$PvN^4(wVP#AtsSzmY8HL)S_8;B> zPX|F8;V9g9<-aNdwZmJQa$rTvBBg#5cHiMX#8N-R6pNz?bjBZK=^4{(&B3Tsx*rvz zqaVc(5MgEs*@QTbIvEiZbzT6L0jX#^Vufxo;tJ+U&evo_&se|p-B2xU{zdMf3FNoBV2JL{(WqHlIuE!vgd1SWuv_6EAt^nF z#8)>Tb_cUyZV{D@-d(zYg2j0n2K-*gqI1DpP1pP2{W(j>ZPqFT)jVbBsI9C5{FKsf zu;cmHJbn!|annw-jkt{-7YHrNgj8JuTNxMHh>Z9Z0V$0XUcczJk-mOW)!iRAzB5$|I^uL`mzqM3AQz<+kt|9ofI|N73w z|MQhg|MydmuL|^S*rwaLTi1Z~H%AHS_=VBISR-=+;Q7T{A6^VP(qLcAE>%F2f(8}E zf)tcG^{w1MW%ag-2bsfJ2(8HbTHn#YpgW41v33`~7Zb^H8vrmIx|s%+4MO3~=Z3^qgm9=Fz20AExi9nc&PSKxZ(vx?W@BO=jTEVTfSeBHPG_a+8_Wz)-ytz#edSFkT@iWe`4F0O6hFM~sx|8HfMb78 z!9N)!4sHpt7uCyQ;9JJcJPMx{(Q#IG#UgPPA;nd1mB8eA&>N6P#vc?!R_IBZcwjcgZea`=Spv0tdz0Q$hGw$*2lYK7iv`A+R8p}`LQj`T{Zq}mJLhy_#XjkQ=nv-7qRGvt(j ztBzu+8Q4X1^Wr(=F49^`6fh4=;Gqg$cpTags2);XQb#>#E3jdo;?>;kn4>zauQ`Wd zm+8$qyx1ov(#!#uv%!rIqHFM<#`I=)JiaZ1>y!19?&wR4CnL&Im3^gdle&Ht>k3qYX}*( z8q_>F39!8K<+b@VI_*T_hQUab&N(k~IZsNQ8P^jDRb>|9Y137frWn@r%)F9H^#c9p z;}dAKLs_?JHf#Ecc#97M@58OiKq|CxG_^S-k{__*Yt_XtrE6H3uu9e_{i`Lv>Q+`(H7R}AW33q!Y+p;s5=tPSoRBrkSW}XdAYPR-T1Qd7IiJl- zRUyJl#%Q4VZo6DSt(6W_FKVPQX!_aZ52q}wJn1KFw8ko==*}B=6HE*>qUB{htnrVP z4}X3gAZr@gcdT7%OPnO`aMD zl?%0d$MW(%$HQ$1+nO2Q$f2Do4Zll}aMT_@{B)Gmwwecgq>{RYS zu%h5KE$^fmY4X5m34s`ip26KS?dcsQ{wCj!T3gWD@)*nTyT5X=y3(u;99%Rt&{3bJ zo}H))8fw^$MSGaIVq>b?Js3SfbeS?j-0Qr~%V3ZcDl&*$SN;05=V_&6GHT-g(MEC5tVabr6O#~q@z0w^EEY?T5IeX>uLn^ zKWj})h*kQyd!9;aDA1Ghvm#^u8l@otEFx76JBiYWvGGZi02SC{RLd#=^1G1DFU;oa zK)+plSfMfLuhi7Dv0y!vPW1`|C|XM+5`XWrwu%a~m(O^PhUI83x^N&cRmk($ROPxy zuaNLYTWNS}gZqrHm^Bq=Hqki4GdJz~=EF|`QSM2yhds&}bj(ox*X!Wpcx6##sNmNDnbwEHO8>9cuc zJse~`PWIA^yFZ7q$Ffnj!IV3*_3-4h9evqeG98{y zWjutQeu<~{1X^k*LA1Fn)5~Vaz4a7*>eCQ(2$S5nj#BLUP;(VenmzNdE~42DSXV%T z@5W;iL>L#!C%g{Mwj62f5T>9KTg5qG$i@1ayFE8ClEf0{FexBeb6+dHWCTkN>Y!p7 z2ODf)6-~!>ArWcz!+|-mx&ZB%dG+f!n_%nh_kaq=vT+bsePG;l(eZ9y{jT5%hZcn0 zghPTev7xz2foD5o5*8OKeYfH;I~hb;hiD1hVwa2D6RtwpJ*Mvv2u2}NM-F2MHzEb% zb4hhWMZA;Qh!SwZ!HFRqKhj6(7jT!s8o6N?`H{(q)zXe3$m#627GXvD%4TOTE%_|q!dPIlXRtE>^+$hxy;S1y zB|oPNA&;V^Ac+8^1l^26M4yDbZQqsn!oq%hKR?=p$v6yJ`7f=8g2k{J+0j<797lHT z1c;3UC{-}+iW6`SIfD3B3Lpn{uwkwjW|UfPYdeBfbiMP-w3`uC!UP=WpKrN0@`8!K z8%mpZtdqoC_+5m~cULk|=9;FO@%yyblQEM9PFRmc+-IrXYNA9XxzwYGmdx4-mZ)j^ z+)KrlM*TDqAJG@qK~d3qL;17AXU^G&MtbZFSFS;0evQO{_?%QbPxbx&m{h|PhTfM- zFh`PgKXpI)9JNNZ$`}qqf9G)Kl=9+KTM!KyK08wwc?rmSD7k)|-k}q@{c}@f4fKCn zAaQPk&fX1TWQ=SZ?8&#a?ckkZ((b)HWr23)ijs3!vPUtVii97%s}9RCns4G=IYsLy zVwK}40A8mnQt=4LHbz#71#DmAb10Ag7I|hUqJ?1g)%zd8o;9;_^h%zW`@B*ja6!@4 zXSdMq2Z-Ikpa|L!dj)D#pre2n(eA#%;QR|}mB=^?vZ>qQE7~L+bWm0W5tr2|;b@VnCf+26|!1etrQ%F?+KbR+`F`lS+0@74C2p{^xpMI_;^2#(MM z)-sPVu$*5l7#&HVIc2IU0?8u!E2!HRe$r>51^gv5*u2(sDc+1HY&Wu%Xp<>v?E8f- zuP7n)M!gj}6?iLFQ~5<}8*)d8a4pfDC@g#)DV8hT$29o7h@&cMVGcPxE%6b>8gSZ@ zcVo0kkD%|CSmq+ME0GbS}J=mPkf@*-|Z5-pl&*!!R*rbJnpKj=G+}{`0sm6 z5!00ZRlZ5cUS31&9xiI0Tp1tCocZOlH$Gg_Mow1Mf*f@U-{4BLi#VaFlTAZ~VUeTy zL2iO=L8v;5S%{aES(bGbq+gNaW1Vzv{SiTKhEyN1J6IIMZW)^5PqA#Zq2hKPYzM|l z{6Pu#gUL3N@?zr%>Dr*%ljr%0HOp5{F@=nuTI{KG(&u^pNQ>nph=iF75@f9X&A={C zb)muZO`yubpM6$OQ&yo;h+WKRrlS4?xQ8ZLW{{vF{hWhXO0>?r)5A-pbG~5TXzLgL z>{=FL_xLi((2_^fJ;Oo zU1lbRtxDs3B>hNM@m*AGLFwhOYfZa^jRH}@hdk-qWoNB+Qj=s@;OcIO1SSCd^0Pa4BiC8^fC3N?R z9o!5i_53I#2ZV2Z9IKcB+Z&vkr`?2TY-@2T+pqtE&#LUZgfAn^UOsj`v+qP~co+i%BdM^Sp?6jsE4QhX7Q*-wI$fkaQF;f80m$r@R=2Ur14IY>Ktj`t z+K@u?f~AaZF-++iK%;ihI;hu(;^lzLXUrF6hjla%6V+}c%ICCtQmW_uCr zB8cBcsQA)%F)9&r$$pG-Ot#PaS^9})fvK}uS!cVwUkO^h(EN9WivW4{l%=YfGny_+ zSoUCR>hIkt7qQ8fl#$)Ku72e^h&~dQjbPXfJ8g+xe@3g%EjU)*4|4hL&@(JmWmdR( za_%?Ji1%nsB%ylt!EalFN*?>bXo20(n1%x~M-Qe~X)&{Rl=9RPzfIygp0e9Ztw;IVU@gi+l|B z(2II(k=+gp>}JlsqUh%?48?o+H)E2^+DwJ<6SO3lG?;c0U8=$GY_8i7q{g%c1 z^RjvhH4xGb#se!H#39*fOpiIP{_!Z55+h&CCSS<-+ZUFq`t+c+Knt1UO`GvM(HOw! zx(rD>-J@EAn9>3rFq=AsRlSJXZ7%4atYIXKhk(12WvD0CKUv0y!b*uF2PAbijVW6d zzz*1kz_@Oc$lC0ObsJ-Q~DqOakG??tsnVtT~5R>9x>9o%X zYFDFf5F;r>p~+^G*VtD-rg+{Z?2=AE_pEkDaRW#AIs^=AR=8BMniAK@8(;^r*aS$k z?^)0a`s{=547PtrHaUYPQ2}w+EL){fM7L^2qe5y0BD!>YLgZuvjw)HWG}4PE?}2S= zydTK7`WVTb5L5^>T$20H^`Sj5x~TLfcl3b3UPj z*W19{)BxDX2-dL9#UWJr(-2>8$bTEw5g~LTkqtt8B3|g}0;xbWLQrDj;UJ^gn`wgo zfu4jw{L5|+)A$U2BA8AD0#c*WWG2HW%n}=ri8LOVg|7!8I8LGv36hwknxM|n5`ptx zG(}oA!>HxSCiU(pzmK}It>t($+Y34(I!Z}0V}?wqFsEc8TIx~>@yp@$2sMooZhU0; z3M?3(Eg`b6rsAT;QrgHwyTh@hkx<t-T%V>@ck@sd8vMm)=CD>V8elt4U{xUiJn6n(FN=-@#5knv_0`{olbj8Pt}OA1GDw{r%h|hAw^T-*-e7DEQY{3vY6ejZ37a_xlKm^5S!Mba?hB8^ux}Bn0 zri*R%K^B6)F|e3Mr8!h~ei{LqL}v>)tCG}<*#K#6 z!%5yo#e~rl!#lmz4paELyMT`4Mp1`jTZo~pLtenX?mz*p{{EI<1vDyI0Q&*B=%N2s zZsdmr;v)}%z05T7y0|fdgVI8(2p@{K}$TL~7vPyKX>X73Cgt1BR4#8C5}dsv#fw;l&uth()U$VqvE z|B=bM_XohF&&#Z!Jh4u*GbmjfQsujhIydGS+BPSQ4=UvD*5?vTr7D!CUR*&b09VVBHd1vi&5BX1HndGZIedw+lmUd|lowsU z1=yQ6GrQ%_Y;x;ABh$nVRk0M*U4eTfr`%kA)HN?;$9*Ohzd^_(hSfyOGQuK8pk?ZFH^b_Q0D0 zYKW&#k+YkZ=LxqHlcoy}KZt9hi4xZQ0L{udq7*-z9#5OZmmnD?PY(hTgg#dF*<4gX zrvX(Fh;t-jVGxornBqmC60}$a1rF5uOAOILMxgxS11pvK=SHmu+@aQMJj6dxl{%wX zfYmXVVXPpZ`w36y;Kg?T^`2jpqSz5d8KRX#z@v@E<#X!B!=`stzILRG6d%)W4H9t7WQfFQv-l@ZG0q09s3H#a3=VvO!`Yr2KOobF5x zq~JB9m{X)E&#|%wj3zeYRy&co9i2;~Un|qK)M@oNiw+XPk5KR)+;`@_XE$^+)%Rcx zTtoIN!&|lTYJ!EUzouqjX5_AL!ZzwEaAzrfb~?aLYQZhAFLOe|{!L&pvhUm|+0)t7 z=1%gfJv1j%8ri|?d!weDM{iT(zt7m1EK7YG+bIE8cMEZ~jh!+I71sCokK@Rd^uYn* zO(xwCl4@^WS)K3)DBKhNVb&;o#(97=`U42Ch7yYv;>$tx#+63$?JNp$J9}Y{&BqT|xR7IK- z-P<29GX=1Hst3oSI1(QnS^?Kx33etF(cZMO#!^%BUd74ts?pooNB+cXfs{%$pS-+; zS=opmQIWKyUl9-lqO>3Kd?uw*G-NCBlrJZ4iv}%hP*#>bJ@z-fi`kP8W06~xn#Z3D zamm*AqSl;qPG5_&EMn>Qk9o=%uBtMthDaUN6*jQ? z6@TblKt2Zn^`Y86^^a;=@FjJ$5GSAh*H>>2u$k5Poj=d3@gN&Ud9smqCT+wI-6yc` zLA3DYUBV{*-VusaF%mB;0>Jb@rO)k;R_C~@4W(I!Q1ul~G#F}J+X&S1k(JPs{Wd^Z zt3?e(R^+sw{hbMcwB3z92y%pJ9lg}8)@?CkGk1D5Z|LVgu4$i7v%r{zP~jpcp1n{= zs(~UyWGxAL5NtdT7TuU#w!!vI^i56U5_z_g$-1xqBuOcov=jti_WYP2KUBdUkoiI_ zjuVclk48s9iVO}2MaqfalQnXzna?VXGDWt%rRn|rHi?Th8!2#8u);!=1EPUS4f}OE zm6}in0A03>_~6ms0(b}5s?=1fV&_vq<+Z-BUqwgp*1-Yw-)n8j~x+Arn#!>6We8g546$9WIhU0EV>U( z>74YRcBA`A`2Nth6pmjz**CLoag4?-^?EbpM)?+X^xotCl)1KZxh+M+MN@@t|IO9d zJz1_)UGn}@?xXz8*_ojmBu;9?zC#R}ghremrz)`lh?<&;+s!k_Fa^MMA?Tsu1Q9%r z81s|SLMo9>6?B0qLC;-Wc_x_)Pl6I+$W|TZXi)(|=>ujjIu8VaEExn}6?&@$(5i&^ zbo2$VUV2=@kep7+6%-5&qvCjS3IY-ovkl6B+0CW;&QpY!_w>r>cF9A>VbH@xbZnC3 zDP}kE5RQex4tbLb#+1Z$0nO>_|A+v^7>HkaZXtrNjapSULnB1TvW?_$KIUk!%L zp>ycCRz=d!FZ}8KPVXAabrp-RwrScAPtPG<=gk^l4eIzQhNtumQfu`c=@;-|O4mqq zVEO7{d<*`8RxG0os?d*r5k~}69M16u_C)VhQ7*HYaayL4*QFw*gZz39oy;n=Y5RYc zQ%X&%hxbG1$faG;ES(0`eF@w`o{dDXASNM!p0qinO|qZ~J3l85!OpDv`i;As<`?5t zC9XXS?gdunZ)`#Am2yXUUaE3lsYs@j7v4NLhC%yf;Ij5n5{Lj)DvQzb%^`}rtqd*1 zR2HFuE!J6fD!(W4co0soKBD;&qRFO9@^>qE$K_{b01f-D{0$HC!xDlQ;VN!-e+E1B z=>e`vP=Gp-4Ul3QohZzLmyEmrnufK`h4Gla zZY+07BS*%;^EQkPMAy~8T_tniy`XRQ9BayvQ9L~s&&7%Pmf-_XJ*Re9Z1wuvwnr&Y zG#DTfhJuikQ6p92W1rk@JLJ5U63_FsHYjBXr6fkpuJtEDYJ?>SWJmZDhtE(<~ z+M-RF3qk_!>b7+@LiP6joF=hU>1UfkT#0XBgDP=|A_4{lgH0KNypka@8blx5o`-NZ zRoMu=l9e8A{EN8eUw;Qkq0h}Te#0O*fRX_+ZZIg>U5kROa!qy(FL!dN)=N9vuETi7 z(yO0?4@dHmR4rb}_iZN7!F^?>;KW~eB>kWQ!a_QU^uW`Kt%!QXt^$_RPQ~gKwh56< zVEq%YZ8IUUu;-=-Q5_-tkMD}^X>@X>YaRgcs-?a62=Wq(`w>7-HoAy}h{{jX>q&W% zO{=11fZ$MZG<`jDhJNgPsZc(~*^jFpeCZot=u9RujYC3gKK2CSo;xu0c9Wc%z=0Ko z|FZ{n6idy;5A0BQpCDzBs$9j(D@bD5vlroD1fGQPCXzrr59US@W6#YLG(o^n&ppL_*!eLuMcmakjUhr_;LoUJ zU#Vp>O>BZxA57T07w%< zi6>i#o+STveARjX856II@WR#;Ne$>P`g|AJ2HXy^si?G1e*|fwtrB(zYj;=R0+b`4 zu5g}^OzJDrej43~ux}~gVqAl9#8aE6@hyf-j&K{aa=Wl9taqL7tB|Gk&NLpFBJsQT zMXU-BXSO;KIoP7=S+RE8#tTrCD-jrgCbN6rmw$%~;yFibEloKGatEuY5Li&lwhx?x zaTmvSal#B;j+ByR-NM72>2JAcmmRKO6CEp@eizeE{s0cT4{MB~N}zM&$b>EEhW$vJ zlJ*y+OM@3vFu_ItFNDCPqctiAMdBo*Ra&agjG>(*ZSC8NPtdk{7JNU5oMeT=1Xiqp zu+K||fM5yGu!bXK(Sa$HpT6D*$LD;g#RINl+p_Lv<)G>n;yJ{CY{7wn0U0~;078{X z$tN9$({g8QEQvcZ=ZyawUsJtx8nN|RFTb&r(_!d2FCu}rnK+s%D9Q*?EvE9?=Yqaq zAHbNLjcNxS^@!{AgZ&(pB5r{{ihs!IeuLUx;$8;jxP4U(GJ7|u`Lf)cya9J+tI(^823aKE}0ASWy^4?MmWo>0L;! zd5Y4*JcRicG|1C=tbw2ieV-xlvhfnaISRk-SuK*Hz}6vgp)w7EEkD^B0?;VLCLST= zFt#@XCv+JytdFsXOC4@doeRRXhoEacpWE!hMe)`20-`q^g1ulvR0lE$fYz7%$gKS5 zXb+ni`gaM&+a#7DrK<%SZ}5^;dn;0Skwh?%d^1=48(9>Sx`(98tOi6;nr`#eOO;ZJ zb3dQ=givj3Mab0c9*64Gl0CN+=rNfgX|bz(b^u({WpKeEWkk^-2vW;8s$nw@iNC&= zx^i`RDX_@-q>K$^*$Zk-qt&KAVb%p1&B1&B>qlh z$Ft-Wl2WJ|8?FFt=A7@aBfjI5anw=@=v5Lo9*Lh?!IbGxdZlNTObEX^!UJtMvtC&j z3KA`_SI{|{mKD!}nD@fKGNZ<}l{?@UAjDN%JE8@Vo}@Ktl;fws>(dSz{m|owDpO_@ zm3ER!A)$QT6_`EheMb1vSN;p4Q5jmyvhjXvjMu#JwAv=9=c_KVb>!Q_mTMKIjK9dN z)O7T`Zl?gsq!Bw&^C0oA(@yQgs{sZwvR44T#z~(r@*s?i!R!G-dbR%0hnl@iBG=tb zcj`ubbP*wlo-$`jgs#Qi?@e1}Vk%$j+***iMGK?tbksPRt2mt?hS2w&q*y(a`9vu$ zTm+sV9I8DFsViG~89Qxvk+=}~L??y4maYTm>NzHMmD{+7GYcU|-tdXq8t=4W zL&sR+k9x(mO~_e0xy#mGm>p}J_<$gKg#&x&u;0YR20NE~J^d_pm%h5)!b6NvmFyAK zl3yV8#MSGJsaEdrlK^Ik$saGSywR5mZH`$qk*4nsyp$co;b^QC?F&>PaBPR!QZH^> z2s`N+Jvz)lYxnL!3`dqg7koYf84wm5TSnkS_Tzzf#MbKRZ z^+ziP2iDo(O#>MKj9V80vx1H&CH_tIKHkR^BkxGfK|`tQ+wo;*ON0Ama~WTRcm zCfqjZErB6xjsFUMhO%gUv1Py|3=O8kT7gKiMI=uBtXxzQK>HlGjBo{gsGJU@NN-_`Aw<)9(u zK|gFPK{Gm6*yvOH!2t`|ovaJe2tn7(`r1b139~Kpr4v1=hZoJbLH#%d2HSGshLtvS zMeq4u)f@G>U_0(*g1&GwoW=qNm`UWrh?wc9bAX|FcnGCFw=K!ua@C zs$f`yMWQ4`WhG@vCex^yv(W-qV#GxJ@)}Uiv+Ha=4qMczdCwOjmqEE}ih@ zyqiQ$BL|Jy$dsev(7n{TX|T$6lCwRvC66^Lh_Bkv+XWQ2VI7(o`hs{R(0m(}8}8o* zGpd$dnIkVEn%S11Qb?>42&pEX*r;-8Jod^PaGjedGoVRQPt>MfltXhWB*F%p=I^Ie z#2wHl&ZTc<9TN9!G4I(@>y@|J?RJc3G9^bprOxUPTJxxH4);P=>UR(pZ2VA%ov_7Pp`fb%0B`8dDQ@C%-@2V|{KcJRnMS1@;>&lscv$hF3#;Hmg zIKGQm&6rhD;Py*P+M=vEVnOt0Mm4+)28G2t zD_n5N;nt(X{bKslOaS{0VHM#qDm{OT4fh^%Tg14v4{8h6{K~ z*YIJ3Z3GIpvT0l0t4ga`9>@p?+=hy_>-lP9gQNm*Ny%$`7(5Wz;xW`tf?p{cUds)VK#lb!6(2Zb-?3aFW1#*(P^cOZkYlDqR^*UB!Y9m-o z8PI?)Pf~|%y`MhgmHsQeR8tfpU#Pa%k@;j$E_;5pjXIJcJ)?kY%7^fIUch^@7`$F6 zU=m8yCjbWUI$a%g!J14=<5OFoMFz1@?aGzUI{1R1ZLZfQ=kkffo)moV!vxWx403N) z92u4{C$~8^*xI_|6J+e>^!%D}MhQ3)*e&}t`nWQ+Zcvo6@1St`Bv}1Oz`Eed*WB}z z6J8d_le7nL3bv@CuTj$2ZgNSRwyKZ?y!r!4R=9A=9lI%4@EPw}Z1}@3&bpU*hS!hG z4!9Snv=uCUfMA%*z#POECuaZ2LR~eMrWFaoBnFrP#mv zA)OzZMzLWChB)^7%sJ+&&uct`VxIBZAL07EF8SSbiX$(Q!pYSIGB(!GMzSZ_hun{7 z{8X8@XqB8omZ+BC+3vXlF2`1b^vq89#2adYCL0*-kt0(hP0FRhUYXd_-gW zbf?}m7bz8wj@>^U@g~iedCLK@s7U+PB7HP`nrq+fP3Z|w&h#VEZ`TI5oyP~lmfBKi zMznbYQZx~{`DWIhB12LM4!mgi>9OoM!#-yOj{9K}@2yC0q4+?!$fI-O{4nx+e&0Y^FaeqT8nVNB z85bS!jwYym}ELw+k&YtR$a zEqx0=?&D<&98r$4n75N5to!z#z{EpJ-9s=wpFc@x%+~a|3v0sd1}Y{^js)=t`~TzV zP2i)bvbOPa@2#q?-m9|_AcX29kOl&FNPq|tsw0~YYO@I4SqA)HaY7s=4nP8&gyecj&F6iit&89Ho_bnZ1Vp|7Y>{ivBkD6So6lZ)FPvB|D zBQ`4#tx6?oUVg-jM{x_9&6FTZ7!i^$JU5x=m!T^*F0%&-hP(tQU3gQtH>E5U(!ymi zHOH0-_FF1MFMD)RQ6&y1Sp~f7+fZ?G&FoRP2~nt})9BP=nYUh5gC3xkxx~Ez1u0D5 z$*qI9{v0<6DvGS8(>fbODo#Czl6%#ZaWnGqP+}hQoNl)p$2_2_i?3uPQV9II^ zA&nJEA49>T!U9`05Q(5q@bGU>>Qq!UorTzU6fy_9;_8|oYOMv7?)L<&V(a?en|tZi z%h%cqm81`1fHpdh;yoAR9OS9c@MR3lpM&m@C}C`I0ca*d*`j~O(efaqEahQPUG!4$j+Gbl6JOk`P1+6bA;tm&T6T__M5mvpNWm7CadrBMl(IFs!*0KySSg~$v ztw^JKMi4u)dYhSHmif0R&$wvO*F6QlM%|e9Xhr0(MnxhoGfnyPav6vMZlDYpk{1sX z*_XxCsKO7z@iCeV=`hm2nP}{yL65JMjp~G2vScFYDwDp29M<;rGRfe;)AFoI2OV}9 zSD-r``iExD$KjXs^E1a`HEpX=o$L;3D~wBEsQ;IIK89{Z&&e)GM6hW#wAt?&b*BbU zKbaDpUFVMuiz>S7NA)1Ig5M7g6(>Jz0Xbt9%1*b;eUpS{=CzNI6oE6nE!?k%H?#qj z_O;%8E3O#6nZhW3T(=qZcGuvrU4ZvJ%3~&IwO+yG4N6W4wcLB-OGJrzk$_>PFj6}E z;xCK_DK!xxk%YLHK+k3v%2y=04;SnazOdwfb%%!i5zU*vq;I`U;~RCkFO6pQhf`5c zwf1+p%->6)d&Ml1ueBXwpi|Kq7Q+lFI4-eCg1Wdv{NH+>!j(K@iDGn(h;wivl)IiK z8U?a?8@V|R_-FiPb$r~^8f#3a1whh@XP^n#IFXPbG4)m-qGJbm$QrMQy>!?er4w`@ zkP{;IEoc~%x+N^?+%_WdG);E1lo)hny~D0opud){(?so}N#)l2|K{P?A+Qruu7K>Y zZi>}PYPJ%gZMP|z$AkR3x!Q_i>b9l9WgPx%0Qucf#NP{ELXIuk1lCp=V`!$~hjg(i zIMfR?ssuGf^}Y#QqQl33DR0!>ocjsWf@10;7ze;|+OjVQvJ+grjltKT&lE^cas0oY z(}*eIFZ@xMbW~G_B9Kp(U>W?3i9|^tiLb&ZH3A8jGY$TX8>ZC)u*JtP{ts9nyJ(_m zQE^{9OK-d$IR2SXhr|$cDys@#MGJl6>IT43KMs$HZf*mp6~|NYrySQObR}hD6qC-e z^rD{WW8*eb?m_7(X}gP8?Xjq+$jky`TEz|M@&W9F=$)@vX@uB7-7>P05~z$JuYe@E zcHB;zfIb6nLj%)2sCp(V?(cuphbjQzwxqMsypon5nr*}68`$5NP9%F!Xr75$(jVm* zO!TA_lkssmBGf0afzE609*tGdU1&H{Tm?t+9?0`&(Dy{HWwadM3p%4qBzkh#UYe)_ zb;vGMjYFeTOKlW>1(_d27?!Ec2Q+~jI{A8m%RrWsk;&312TRO?gC)INyN%0vBsHVs z7E{yI7^4jP-LD=I1sbT*V?s-qhCy{($TXpi#a6;rVDJwWWcyIcq-yvKOm2r2U@ln+ z0*x${QAGn4*=Xz?j^L3IBClc91~p&JtNHKbQ^=Cre?`0xP^2L5wh0b&Ks)fDl_x2v zDbUl2LCC)8Nt^1{;FIKs8LYcF%0kvtNKqNbq6km*gs)HJj#=^yJKZgv?iW>T;&7!I zL~Gy=Him;R`#&fdBT+t*U@(RUGvLx(2p19T!U)#WVw{KiYP6xU1W!OI;;ZPnh0?KF zA{#)fY4$kGW};v7tOR)u@P=ZtYbPQoyp@IM0>|>_DZk~dX~I#3wk{#L0o`L-5He-g zoSKYAWCZukYnOf)TEk#0Ymq^PE<Sw(u4%}e!oMY zFKHlw-Dabmj(1UPNSVM`njOrFQaKcp+d_hj`YA<2laNd^Y9xpaD9@Lb^6`*vv+*R# z_4OL2Kh2;Gkcx>r8J&PMly&WgjniGR6rdt2y^0SuB+7mWA#*HN4LbsSf&Ion4Kjew z#46Avn0$5m}3iVdWcQSvH|l`)DxMFk+a4iYk@1KnwU3A3Np0gYR!6JUsC zEc(OY*?g11fn*BATPNzZAvi(-n!9ZoVH47ek((f3`@hA+u7YosiES_Z4Wa6JVYb9p5yAKbZ3tceX693a9z2~AogD@ zuo6OkUMG`S3WX{L<0nW4DCc7vRVzZf{4Li$EOXwO5U|pX{ zf#=8@mjxB7I&{iCijnxIn4Jc6TW!On1R1=2{)Q{hgZ>(k06LI}dFS_qv~#Sp2vT4% zBoV+_pkYzmqZl6UC^Fg}ghByhft5j?b!ckDHMsn+ba8fy<)z70VOiJm{TlpuN9iu| zWmhswpydGK#1*%RNlTwvd2#t!GF5bO9%U(10`N7S=hZD`VQToE0fw@J+~BiaN=Ph! zpZWoelk0MtxaPwpZ^W;s)u_*|f^QcAon5F=8}*h8o>kxD!ZQ7>I;iOhzHAYVf>&Z4 z=FjTt1t?z%{HenDhcMD(l-lb~LX`p{c2v<|Lz7b|ejkDxr(SW&tCge+HBSX?bIAPO zIwrz_lb>jLRfRP2Po@rn0OdMmiuDhb86L};P8hH`Xj<5)h*$pZgW)EEtXfSdhz?e{}45bdPFM3krvZiiUGLk)zO(030T zgwX(XRA^yUo+sYoE(|W#-zAM5Qt;9}(n~unjq~G_U-B9=dko#oiW4zc(_n|9BF)9k zPVW)E#)9@bLrw&Iiuvq&&!aydzsT7@K3E^T;;bt_ozjZ2%#0{njatRC#H=g+aacqtP?H89 ziP-q@talM{TZxh!M0XkPzH>;)BKED~h`@tLCVur1chFm~tl4MWBYPITc61kKM?6ta zNph$LLG}IUG4%P&HB*G_{w(%79kf4onN9Q|vThHuiMgNK4w^Ts;iUh0%2%FHuZ?pD zp;R>BD6(5!Ne>NJ&{$)q^s~&N6v?#;V`8Q1DSdSfA_y#1Tndrff;4 z!R1`f6c7ywA1?B;GC{J5wC#C1Py1;s(Sp8?VqBOJUkmQ^RWLCBCCW`Eob-tXag4}( zlusTh`QbyDepGIFxBuv~X+YyxylWj4=39jm}OQ%{Z-jaY@MPZsW@ji@e-$w=8+I^T|5U#@zx&byl;lV@XM_&YJ zaUp)~0ZDqd*xa8GbJWpuxF3}#)mL~ZdzFS{tpe>U!RKgQQ8y3xPAAlAc(xrr^DVZN zOhYfC$kx#h5Q2=$=MaxU0jXd42eA#Ah=25|;a$Ig+tryxCq$fqnBUFM?i3;KecoaI z3Ru#Cn$=mWnG6%1dSBPeBdU3?bz^w|2hTeQ;%Ijv;fxMMNMFmF*DqE?Ba(@Wc_Ey;6btHc0>B668 zP>cBEp`G4E7AY`r#3*jnztURlrfNXb5M6XZMbqUFBdUW+ev5$tb=WQdVM~`5fTvl9 z!dVNZs1En1tkoTdv4W~mA*R!!!>|!ig3d@G#)P6_vA-`Gqr^$vgo1Gx858Q;!Ziu) zwTo!DtiXj~0z=U^z>r>5GsSUVzyeoQumNOR={M-VQ0*4Jji5O6v1_<(kU3G}ON@$O zb*nJ~W;$INgqrD3`Otrc`6v7xVB#>f^d_W-L)yYr$*~K0I$#9Vj|J7io;Bb4f)-k8 z23n==c^KZkVd;J%~G;aRUj%y17>5d5CTW zZ4?2ha!%{Ja7R@P*2rRHREkO9}P6BL~yunNwI& z5?{W}<}qs6PsQ5RY*umH9u|cok^_o$JY>l}xAr*9nwQ(8TLpbC{!GX?d*XN7z!4X8 zPD6)pyvbBDeB`h&b{&xUG}bAkzg3OsB`{y)8^o~8@{cTRnw4~pr;aTq?8&@Oq{L44 zxN%KitT4vToXG=30)2+h4nuP>r$s{zM661TJ;kChqEAHk|60b2A}Hn8Qx31e>&fdR zw3X{Kof@d@spM~YZ)av&2w6|jz|2M$A0vy+_9yvB7;)ObStTMc2T>Dis}x_k(~)KV z!1o8>iInDBH*nVhZg$Xg+GW!v8@!~av*uGVStemdXYi1>k~TCf-(v$E$(xF4WB*%D zVds)B>~_I5!c9%SVl4W8jfD@d?htX7r3@0_TzlzazRrPxDZ#$^HHgq1@hw{A;M?pU1s_dIKpj#mJqZg4y&3=90{NLHbE9peN9^4nR?-^(phg6$ zEKE>@ht!H!;!=thgtzAL)fJFindh?`89T#kuc|rpjX1}6L*eNR{DPD;Eds=ipeIu; zbvk^cf$;YaN09fLF}=#Zy3~Pp97`t}ux48p%oG?#6N>iXX2Zc% zm^HKr6W~Zvw2y*6r8!@_oJ3XhXRcSm2~E)|O*~1yK9t55kmN3nwo$pOev6`pwF%|? zlC5-M3Efk4`@aVGC{L~<9^(UDJ=U&gq3ha+FXB{M>ODR?(*Hhl%u3}~mf^90GV*_G8*#fr+1n@dMBE{DYDaHFYS{LAz;| z6W=4x9gHnj(;n0vd3>faf4zDd9kw$aGNWs98@{1#f2gfD8KA`s%A!IhU zj{$o%7RYG2iotRjH&x^qEN{alT!iV~8Yc&)s>H?btPx3mOhXJkNze<0z+FDgVP0J8b@)&3frsd}Nl;wGBA>UH6@RO*Kut!zd$* zVKAb6hc$xsZ>s2!#Iv+RL9RAC!Q#bYyHRvMne6M6idFoj+3^pyW7H!BAbZ)+Z#%)9 z?4>JLMCtJDoUU+-F=*_2mY`*{+G6_Y&mt)x@u@}zx`+1I2)>khn_xYt@AQ)qvcB2B zOnI2`jY@>=d0AoYB4IFW2)|Mo%D;F~T|$^TmLccS9O@9^lnoUfq`lfJt287 z$4FN`*=ga4Wj6iwn1p!mzHMQQ&m;TW1aF6Mf-`8+7c%qeWvfL?_PZoh$4L54HP*tl zny#76+3V<8*`=ZbB%Wpo`-mu7p|JF8x5pvlce-oPK26=(@dKI5-cyCuW9TpOEh6OJ zON*j-VW8*$`cb0=waeuDkuMd2Y!`;!){u%~-*o}I_ol?uq8p|aIGJFu-^75)CJb(|o&?w1v;0kY=NxXN&)yohVFN#qGA1*q4cwTfAhd&$-MktdEI33<-ydS7m2 z%BcFadq%dZc^?5Bu8scWiPja#ItrD(t1c?U@IW|4)7X{X!KWu66r;a{)Kyl?5>8&_ z#q+Qr#NK%5PzEpG*H>BKxadkiQHFYLAp^V#__U&4um2ya?fkaj1{O9@E0I&$K)-`z z(gi?)Ms?qhK#H7BS@E`zmuxEmD*C&Dk4xc;qPqqhx0q^}&~S+H)TWoda~IEN<9+A+ z$czHc#Uh!r*zEJ~WtZw-u`k#JFQx3AQ z&rV@1>Dlbu;k=kYo*a_n_w_1J<)F_WA){7F+vQ9S&HSS*^m{wG*wg z6AL_p*HCbULSZfTM^eAuNXCx{qj=x2A9I`RCX*)25cBgK-4~>RtNCUC+@9`1IOZeV zQ(9$34hNO`fT{QWUP*YGU=Al8r}5bEr~3b%4Xi(rM4}tQ-Fd;A6jZVeygzg7O8Dnb z^NI^aO?uQXQ9^@6@{Jkh+3L!4Fy(!woDdT=ZdF*gWre7Wj?2f^gy-q5m_FtzpG< znTLPJqPQEd(cmQ9%3YlnK4lTfT;{htr%*|$m+RZql zm9h>@nPTE$42;{@+3_2iJ>CLe*-wZ( z8K6>WIbR;sGde@zJ+&(+zc0Gx3hgF=i(OWtw6f~pgOI)TqAbcEV6avEPwFIxBeuU~ z!!c15=`t_}(T6U~B9nu|MWfDl40%aA<2lT+Z_K>d`y)}Zo`z(tdM{JQ3S?j$QLEo0^C?mg!10-9T>0?j z)c!1*WjpSoAzgXPkGv><5A#f9beyzyp4X+4diQ*KFGLo7Ui6EiRBlyilB=s5^qvvs z*EV!%$sx%dP-Hj{;Tj{F(IJP2z7s19q%bYIvl|>!W}`3iY6YHH{d1x>-#kg^+fnE8+{(Bbbm)eWI6^%G(^Jd(n zO}HMuY2uLRZoaNm-ytU@6)b+MS$}b#MIeRI@SAEz7o&#&P&XMlKAs*jrvX5)^}wde z0G&OisW5 zSM~5antO|_P)sH~{Gz{M@Ibnc1t-@~K6hUqgh^qQU+PID8T>p*;EoU1Gv5H+*O-HQg6G0#{syBz(1is!p{ zfl(_eZTSbqs6Qu0hCn#0tRC0~GtIO>0@52$l>|7Ivd0Y2E85@@Z#O%p@E_yNWo7I(jzw2&dyQY+SJ zBN0KOfALyb7Xy+O7hDcp;faDkGDP0ujjwe+sK1Fjn8%1d8*}{wBWDW!AJww-cJoIj z9w+085L@(sLS$MpEYjZng#D)h?KQOF{$~zKqAP#gdYC^Xny?DW&2Rk;Hfzn52vu!v zxrS|kUv3a3SpAzyLtTtK52APe(l7A<Deju~$|{00J$lv)65Q*4o!ijo z1yz08&Fhq;jdOrocKC8bVV()9(xP82jgBo>@Rz$Cr&!;cSWK4ApKOH@Qo)p<14h-% z?9=!vMC35XId?Y8;$r)zdR!#Ot*ub3%?>kHOsZt)I8Ub`6vYl;1;gWOsTZJSH~p`~ zqYPgFqeyaBca)7xe|k~_Cc}caC3Gc)heN)4G|4ov>W(PVNZQuM%P7oHiR&Dh(=Hqi zPS`!ur1Ad}mnv{Lww(b{Bx{^g(<_bkO`!_f^Tl?b7^@4L|FYBX#~UOU548!kLIgk*BZq!t9Dd{Ml)&acBitD=GS zib6!+u4VBCzP8OOA=F490m)&!GjC((hMbd&H*fQ?4ee-SFf3N}|VTecZut> z$XX6i(HaD9=FWGhIZ}6C%a~i3UC;Vx;Aah=z}dQfFa03qX}7*&fx2@KeT9gN!16el ze?#$-(GN=EX$1*ImWxj|E-U6uU;%>OrkCi4pxM7&2d?(-#Db)3Uk6r1^*6&EGuOth zI|a&y+0C)NmlRlj};mZa#G1wUCt z^0DQc$&)v4uzrBIVU8|7fo}07;kln9Gsi8YM1RyKi0PiQJ|%?7aj=N6h3%$6`u76} z(1G_q3Gc605HOrjc6S7_x4)V$m(dtx(RI90{oH}`z16W!&Udb`0`!RyrPPCXCRBu# zvdI}Vkfeqtex(j=Q3 zdMz<05yYRkggmR!=RKJ`UG;2Fofd-=T@ehniYXH7tyU|Wh8GA>TOMpR!oedKuCC~4 zR0qp0nMU-`jv-NV>C+h0u3xY5PNz&RCdRN5X2y zSZ6PowLHvsLCh#v=WDNkVt)6Y1g;`peWev3%ze{p{NiAg!_O4eAbuKE^X%|PSjYvO zq>c?JwQOYtlJ?A`>O-g=y(fLWQm&V9%!_Wm23x~#*mWz!HPx2E%0Q??XcU?A!ml$S z{H8?`7f&$@)`Nqr@$C0wh7JD=d2&$5p#uy0w}(w@s`_@y;(@oE*k6yEB;CLp+L0yH zs7k9?Hpl2HrAljM0O+V+Pz-ZE254DqHS`_!`E0SZ^fQ>xSivk96)_TCJ0Oigv;GD> zW3lt5q!^yH1&I_JVPg%fi(&N8&IpT~5)9@vd~L%ArJfp`{Sr(^M>$h`2}DN+(8x&? z4zk0xUkh(9-Ytp}aOud}>g2Kj5o{i>pJPlyD^Yy#tvFI-J$wWiVq|wsLD?{76>2-i z5KF?k#ZB`YVZ|ZGm%9dSYpKW49w9_Np7bltXe=XBf?O(G3)8R3H9k6*U&LV)qGXYK z!6lee*F&EHZIb@Zd<*P5nNUtZ3sBr_njS?cc@8a{S|rhZTLq>`=kLUa*3uvGuN)se zW7BX_guHRIq`0>D>lrtS`!P=p4)OY^~d-K=2Hb;xd1D<8rdWfj<2 z^v`O+s_NZuyoXvR-FEXni-wN>V30kO25I?tU&EZC;kzM!qk4`zLA{kogh5zDk&wSO zg!cUga%@4-c4n-!dlq3z-r>jA(r7jG;Y=}+k8L3Qc6?N5b*d4ao~%Z-)g<^6iXpK) zF?C?Jx&CcF6JbmEoY$b9a#KBn!5M6kVpy&PUs_S?;`d){Vr&VD5tT$7F+HQo#Vs0X zv^1)i*?m2{JH8(219N$fYl;5thJ62R@g=nK={Jw;zLova*diSVg4-C6mt|jOj=}M9 zNxXw%!h^m~-R!ht9+k=}7?aNL)H7Wg{()2IlAfX;D7rIz^nRMP^j|woa^LNk`Ls%W zztdrf9`MKpoNvOh0!_DrdT|SaDyv`30^jWYpDnU3w$Sf9qqWp$ zfRa&_ zX(SuSw-lVdXrbBBrd6*}Gp{-?aI%Ok+htl%S;-iAfiLNwft*(mP#7wV{FKx{w3fIM zCoE{`uHRvFWN!)omB_S3+#$Ot2S>sKr*btV0zH| zBjL}0CEvr8u@7DW4rFw;i!UkwxDk+nJ%G-Eb}$6aBtQgYR2cYSku)>?p{2Qm8XyN~ zVEV)pyP%qAWbNlUhIq%B7HAf@-{=hKxIUp2yh$4ZBy;GO?HCOoEIGaqm9P|zr1Yor z`LHW6sW>{Ukv*IbX{GwIaouqLWTv?eA6+S-(1RRz^fV#Y0W=SpCcrix4%8H>8BQUb z+ovcAcTWLGavWm#DeQmCqb9!5^OaW4{P(?s3g>vOlgNokh@lG}$$t$ZQU2C&s25{^-BxxL~=)l`) zGe)vAinanPZPqakh~Av7!*#QhLB7HdBW`IWq8|MCwmW@i&?<8AO*3w%UHfy5=rcTe z{d&}iA288H4yPY(a{X2cNi0Tps(rr(LJ7QDgSZ;!_J2Yq)^TwfTkOLb z8+p{fXk~XAT;-YM+|YCOF)A~CBWQ{>!7r#$S3- zVI6eHAvzaScOt|^^K9r9a&OhJl1hPStg$R8%uL4+z9F>|*oWvVs|W!zq$OhQ#!&TN zmz+PvkUO>*=oc=FfpM&Q6Yb#&O`ULG{`zaN~W}ys3!N6dk&n2RItM@FN&pr+~i6bwRC?V#y60wz@iODK4 zGON06_&r_Ut6|ZEnnAe{A+ynR%6*fcXUq4Zp!8 zB-1{*??GJbjrBIiQYG+kX-`d~I+NK>PmM4Gb>H%l?ZQ#^oIN1MlmAg~6D)Npm3jwjKOO#uF2w-4kc2Zqc(0M(?uio zG2Vm_VaUkmr@aob7;*TOIF(1CYQ*ztUK&x?mnJZu<^-Oa#aEG;(SK0USw==Y0P4ux zbNHqRqK}RXlO`3XDZ{lb@Xdry$mYD7tVJ^``t+fTe@()g589QHs1tGP+I~Gv67C)i zY^AEPw0Vy`lGK2w#$Ch5yAiA;M3eB&@l2yyMkl)?RujKOUGYBYmyXPVyeck7`7PEG zX-L_^zq?m);tLdD*F zisdckO~0rKAP}&On2Lm_Q~V$0@cOdnZ)pgq2BhBQ>SE(j3o{ugW~y#B)|6|#j$}Z7 zpec_UXJck;sz0G%g>ig_Hhynm<@P4PY7YXt4fx8%3Y%z!2|Kq!jq`?vgSJV%#MuRy zF8&hLYE{0Mm3KK=*5G}%!Xz!ae=}w#!e3~_G8R!RlLK~cg|23EP;-=ZSfm1)qaa}` zCals;7ZqS%D21DUUPV{OfQTUYLk#&u(RVMigtad;sEc>x1&IY)115hp$zce zisl4hvA~tcX)Med5cNQvcF5+>% z3ex@?Z~^WuC6TXdvgj`VECRReOY<(*!U70SqaW*P)eilQnbFv0nhaV?M;J z6rjDVJRU`^TA+r~Ve3V-rN^tIM|m8y!yWrhz&bjs=gjxN&uHH(nw|dg7 z2koGh;*46w#dijj@@r;%hc*scy?LTwrl=^edaI%OUM%nM5_gf+$G5?7IG0*5lb7=? zFGP_wWnOkTHyMo)-kOM;?o~|5(BTNj>=9prx7b9hAY)Y5>{sVwUqAPSXKz6Zx@f%GB7XVeH#utszxTdLKPUd63nOk`t2l! zD{**SjbJjO&}uJJ2otrCn)?n&v3aXs0kiOAYaa{i)7R3?h%(oMj9EXbt`huS5AWc! zdANT&=Ad?Zb}P!pES`5g=qoLbFacZw?-3l|Mp#c=K*3f;0W4fJ!5~0d^neOTQgZlj zhwY|FDg}|Gl-1Ne13z1u3sX&(S@H_X_;3u7!5XBJ06|cY=!M~M?o#lSQ%1P9p7 z2o7BL|ATmn!l?Wo%RBf`=So^`V^BDRZ1Mn-PPDifw;hEj6;24?o`(w?toJhF7F6mE z$)-}y6U8GaIn$uHc6WcuzPT6xYfpUB7=Z_lD(p6zflvUVEWM~E;1oH*H_OXy zq_AG^qGF)nVSGJ`^rG0Rd4R^=7Q8pT?t2aE;wqi-CMdF7ZhaW0ubjz^WD0veWXan4 zFolazT*f9lK@yrSjF^gF*06ZUYkb7_K3Qhne}1Z@&Fk-OCXdd?A=ZdMr5We&_GTv9 z%^l1nb1V{}e6s}BM^ut{6PQg_Vj(gOt2(Zt(7h-4XvH)UbQ>quH!d zxC$}4mI)+n6u%;PFP1?SExs!JRX^M}YuUd)v)NN!H`#xV^`| zmK*5`#MXraN~KGb>(R?BkhbceH~gu z=;g~V*=a5VM;QIgVtz2kgDB7YhBzx;fE3OgbM3!ci3fu>5*(E(7DDk+r;48cF|4@u zR?Beu6S8+GKIv{C$%#uQuIC1857!lLt%&8tVgTMM0lL1sNMN_xm`0Ik<%v z@Dm_HVQ<*ipe)jpHVwzmnYQ8(TU7^q2#xghOp)mP(gBAR;s-AXYBPwUNtpg6SN&w+ zo=!=E&E5dC zm!x-Jvh|Nqj`gYx zqQDHppCjFABdU2;DbP`g6)fMzCH-qiEiB(87f}260!RF9ZoqUWy zG$O8h&-!#zaatl8^aAX`Za&#A!IZEc3T(3e##MBdV((DMnkg>u5OS^zCz45sOC2)c zRRJjM>?l_8>(Qx!X#tQ%>dnZio>R6C-$`sxP+JyG@+<~qw}%51{m+U&HmcWuXOl>+ z;e-^%nS#DoOsafKTkh)etCjPt(+0&F5e=)3E|rgJF&EIrU$myiaY-szhHwk!&&1e! z6&-KF00Z2or;W=Q6qxz_jE5*>oI#hm?GB6f6cT;Uiq@S8Z#&2kN~aq8=}VBStZ-W& z=zd(FRgz*kuJ3lf;R(<;k2|?UH7Ziy5L04(fG(WaDKf%6BM1V21ovzYntCNR+k z=k}&3!S#aGrcCY7+fBSN+g-DPJQ}fYksQQDgcZk8>O)%MvUVI-{XLen*c_BXgjQ2| z5fng<#JvbZ`ZCmrw1|O`iwF1*aO6h6PRj+Nv51J)({TQ`d4SXU)(d!Zi@sXh0?pve zsz&}gAk%~+tmk{$PwrJU2j>xMH930TKL4Gx4>FbC9quivPQ$uJw*soW)JyQ9AL z@>a%vpjEE6wYEt?e?1&}BT(a$;5p6p>V_l$Lz39xEyHNhnopLIL8Z&MIKcBSoE2ut zVZTg7mc>0NmhDU>fs9p`Sg8f+m=y0XB29RNSl+!L0ym~1P zzn@Plq3WoczljVgQY9~UGJC?g1JxoV?xLnID2wzP%PS_q{u|;$Fsn$WFoA?WU_DV# z!wQYE1WeyFh>BRqD<4iXZ0ZQ9LrMHTg}w zXkH@`hG>5xRKMC-$Kg;}7exR`sb{$naoEtz%q$e#a!XReMgAO~n*Tt(baN1OiJ#^( zM&s8JNp_(Mg=6ZMb|Z1*yfR7IdCzi_^OZOr#{09|av)XWdolpD`UgM_hr^GRXyF@;v8P@M`*%G+Xnf;&SXHlwYe{ATkI9QE0CFp{j>nD2FrA+ktdDa0 zaK`8m|AVSO5+sWexO&X8p&l%D{-dt)R?5q+gLQN98>l=GoW_cpCu#gL)oL>B?pM(7 zHOav2qbt&ttbTJ2v5wg;zC&3j4u4H#Hs=N_q1IadPJ3rMgSaf#5$Vm{bdci>38cKm z)aRIOXtdsh5h#9zS&86oL^~^7+Yc(yLaU;T#c`twd8JD`%!jg=wHIy&ThGc)+cBN} zMX8Rqc7DfH)fHbMQSR{ptLo@%RJ&mrCyNf7vW@INp8X?!mbmNvt!7x7CD;punRp4D zl*zoNsbb9pEe<%Z)1zvk4LiMw=F0kW$P<|-+K%0X-LaLW&)5b(wtxIBF$LY5S4u~_x4Rc~BPwa_ceXoA(Gtds|M zp>jg2623}77&@M&GMt~y-nBgLZ*=N5=HdTD-C0ed0l`txv8AoIs)J-4M#D`i%or^3LR^-1Tjt}pLYwla&u z^Z1L#9%rN5?PzPIa#<}XRc0iQ=+>8CSa1u?RBEW`B{C7*fQlwOhTceM^rqMWyaZ`~ zBD0M5FfgY4f83o+`Q*ptBymLGcpafo><%U>L~k>a@3LC!>tS}vP`IgD5Hw|w4tF$c z>JNHDXsflnfwrWcO8NBedcq90Y%_gO@nvuLCg6pN%@_ZwE9@*)K0<>u=5J?+b44V;#r1;<+vuii6i=Im9Kmo(E3KwkD<}PiLXQS zlfFed3r0uoG?75$-`&Hpj0RHi=mN?GO;+NZEuuu6bSQZIZiUN!jy5P)7}N`2-CP0= z@rINI91&>E2B>Ozb_zXdaC;%X z38KSlBe)m6Qk4NPiH{#oVfk@Ur4e}(T_x7$ zlxy3M)H^^k=tt!s=vfE_o?pQVkPm_Y`wbEbbm@+0D+HGKfCO}+fvU(2{ui^5p2Aw> z5cDE_1C#kSZOFmI{*7H7M?*9?Oo3k*Th8+2hja#khQ;7AbZ$wd5xMEP?&O2+Y(n?id%IjLpxIz}QiSD2&am<5M*HYN>x+vtoi%=B;zpJb( zuA4#E-4qlzboTb$gz6R2Bv#+m!B{a~8%|Ne6}_5CCKFV5HS&tDVXc$6MZK}GV<~W# zgEU*qs7fUZ5wC75g6QmJM7xWS)tx8eop@<>AEAM-{iz6nRe8=Pg~n2lL!9?gH|WMN zVd7_JZHi?H$8XZT$o}vsEeSF;S4pvN1l!bQpv5vs_dX1|`5PBMp`$I#LUU}`hA(4d z5tdOK$rT%U72wT~Z1Z|n4W9oI+JW#W_5-QqeXBoUo<1LUUflTpZ%lD?L@Oxn$nzZX)=d8oAyl^?uJq6)xa zzh77QZ+Oagh&u2}tRRuFWFO4??M{zd=;+8`wZV>4MK1+sq5lS`nIH+0 zq|D3qRpU=%euiF2Ng@+sU-t(E65WYqh6U+1hyGZOW_%<~V`L#lpJ_}sfG}QV5~8%B z;*^$FG%0C0CeHzbYo;>wX|*JcEz)|5@uh%8={>B$b8DK0YPOxBzBiMnx;;KmQ6p@9#Y5&TlvSr#M0(HN5RE*2>ON&N zE1yppkaPMvO2LM)_EmwZ?W{X63D`et%VxrA&=I~t&Fycnu_Ub<$!IyplKPU54P5Cf zEdhzN0^_f7{r>V;gN0YP-No;soDYgYXO6jjN9zhtjGkyNNwRn_Oa6ipER=km{p_2X z7qd)Ckgm$o)$jL!2i%@lfSuIMEczl4YNvB*Ct)%#H~wBMVdq9%{so1V=tQ0Rae|$E z1qkJH$oFR}yPm@mfr!TUo3cul_n4KPd_D zESV+E7U^;Qe=NNTd{kA^K3wPArEf1uZYQ0PKuAs&AS}WS2^utzlLP@3p%K)G2+bl! z#-&+CK@m@f)sRD1wfT9TtaiP`~HS|9gM);t#s} zF6UI$se0H47kt5Vzi=;}a2NHi2)sbg+|D#C%|;tarhk;o)T1)@WS5x{Jg z#4OPf#$;^}AFlRUnsfQcDGwNDLSl(W9As^a&v|)}6K%4JSoYrT3eZ6x_z@jUVdY~d zWR%*x(450_P)K6<7wcVz0Y;UDGg20PZ-$YG6W#2$DOnUZ7ZL8A8t*G-?sY7wLd?TJ z>*A+5BCoiH)+Z8m4ptE&oOl3ruB}A>V7C4-bahQZ{$m`Ev8*1JuOxMy-x=`?U8}nX zPZGt1u>xO(4^B&sf%^;A{;CfyWVOI=lf(M<@O`fdo4?3pld1xbB4ZAy*`bu~P+E{a zOG5gP3P2mYvvmG$s?Q=Rb8OgAt>ITa2fhkx!PY4<#wcn+x67rnUlz|k$u`IV0V?8+ z#0sCS52nrKiV6lih8|FCe;09w#hbhnln-JRO>#P77#968qoscnr0KbG%HV7@=gt{rn~# z0WR4IEI}YNjVel_3>uEv{#E*)jPAIsGo3ZoAmjsBqMxz`pg5DVULVw~6!kycE*RQD zHMy#iO=&6=dhx(xIsh_RjUCua1JclHXrv(eo}2+wQiJqUd}CX7{~*sfpt!{)w86>= z5$t#CvwU^Qk`5|?1mte|Yb*Yqq5eq{+i`*kQl|nL ztpK8^!@BG2@J!MLX+wS@_E7+mtL0J1EE9M?r7{#5;Le06NpynR1rl6WRsX6}+WkQ!sg3nL((5>|jt0GW8Q$)=} zh)Xo@;H7Y3_!I^`PDAFLAV{|Ca2+N+BSe$5-yV;cJH=d`dTiMA^-?s3u)88ESp7Vn z7whQx!sy$9GHphgK9)d`g@429ehur3J@(@PlX+;M<-gM{{;zP;e=@CQm~z@7%)naC0@U9e%AOC;LN{?xP| zL+gjo1RT{`=o<9j1^peZEO3aFU7Ws=GA6#5-S-EHJ80W~%7ID#bYe+;S77?jVA9@2 zi0DgFXu(T53D|=%(6kYox_(1v5#qq6ba@o9D&NpDX*wR{;QlE79MGffgk?ix_u`UV zs-LJk){enhwhvG=mis|eM~VE6uy@xnml>Bl$JdY;noh7Y)H!DXPzAVLb{m$0eeJT{?`$DQ}mSBl#Up{@fcdHyYTVGL3w+Nc@sjhO7YDyT8>k<)v`JBL7w zoFu0ZWxb+El+f4?+%(XOWI~y^;hZG|Jtp&MZ^}^=3Fk9@p-1qnY|~dgvT3f~^U8 zKp}qba)Sykx-Xz2;3*X&z`k7TZ(y4%BKrMUTkYw+7D3JkM<^oh_%TrYPt;au(qcJT zx1+yLdog-eYMD{GU~n<9ELcS`)^Dj?XLg*K7`YH9L;8ymr!UWOuZjp z4lCt*sXu}t9h+Sev48?UrQHK35UPvKUa#0Fcx^b2#U(6P|C8RN*{5}@&uBGTtZl{Kq~qKezA=Tk)cO+@Kz-DCG_0cuv{42jtmCJ ztfVD(tCus)4Sk_~#5Q3od|djXx}BK|edHpaU8vK;#!6+Q8c84=YvQACV3ypYH4!)Tg6CdIA(qZr!01Y9AH4)u!ejO9`A)=np!JjUBCk58R~Tq%)HB5IHSBN*Rnj zuezKn>Q-K5;8*SBv+yOML&4C|608%7h&>z-4@d#|_S-z3n0QtJODQ(S!CY5pC_6Q7>(8KyidS3=__!fav9)~%a0RP#+)y@C+3cde~LmMyheV{jkq!mMl=Uu+hN$7oWS1kZ5- z^X=1rrrSqB=_oXr&w!#|%s%E(IL7dd4ZC<9nU5IAzxU6^a?uZZxYC3b5whJ+r}Tv8 zLTOD5WqZ(zOmD>ikGnahig5H;X+xfZCK5evHoUW-5KuN$5n`&XYeD!HyHjvU%3-f= zp9)Ji(mPl?03k>IX@VOsD03r>32MNKFUbs0%_4bovGc8;*Ao%hbX^SzF1C zNIo5B!y@VKv`0U~k-CI+q2hh9CWV*mkp`*WF-y@Ihv)I$n)WB19^!KpJQ|jvD~+>; zYUrl|AY@@V(S3ssc0`qRL!hCUfefM3RjlXY? z?b+-hR)w4a|3}YTV*};t3z4D*yP$)^iVwxt%3ym5Q|c-^9!8{SJpM+=9-ekOr(YuDJHD|9b(Bc7f)&x@2gsg7K$JG+3%?{1z4k#s~1PnTA#5jG7dD2I&?ePF;~aNkb7oJ6(X(FZ?vJ=%SOBi=vM zfo_JGFZopmqqNGpz#JnH-DKRhd1|OHSXld~)&w~k39HIIlIn>&#A1JX*Y^vc>(rd#EFR5{tTwjSd~~2l7qpdNy`WkK^6g8l9fe_vRK<8Is}MfL(2<|CBTvX^ zxi}QX1uf7g6FFSsPNC1U>De0775Mi<(QvglDqvD*H;4@X`@w5-^ouY@o94Q%P8^}ZMWa}$=Nv~kK8&(PX8;Vz?DAuLP6K>EQy3ZY(UBXY8UFBJQPYP=b)5 z(Sy_QPBy2GDcot<3;n&{*~TG0RCxsj>~79_^O$=;5?hQ`Wz$Jq2eeol3@HJT^;aWF zK&r2Qw{+<;N79$DW%@MI^z%e?{f}P&a{hrdRkW4J!&q_F(iAi|`;UT?HmYXKwT0<`EmB zD)a+zc%8O&dl0*?WhOd@-I2)9!^u3v`zx$*IB+H69GW#pPX%z8aXn7}q+3-&dI}Lb z7EBHJ`uGgwr4>6)iO?YZVaGRc0@lOD;vHl*P0>X3u#eaJd2@_60df)9`foOp%If!l zGDdq4>&b8mK_}Y*D7~EMhb6^NTY;R@6RpqaWyfM!m@9?BuL zz?X#Cp**xdOUbu%(~e=u4Yi5Y-1TI3KK-8ut-!w}%^9O`j@nXVW$9pVovx+HnsdWg zcPnT4p&R)l`&}qAExYpEZj#y%w8?{xe+YUus~3!fqG%fHl!K$N8x8mo<@~y+1X4yz zX$H@hw)jNF9 ziUV^C0W2>XB6VE6;p1hG3!?Lr-$rlmFD z$4w`INSCa5<2&;i-%|t&1d9vR92>DU$tRQcq?wO1I5`;HR}3r3Y0swDeqX5O!OVX> z&w)2NNih5Eck)d?qiRH?>#2I_x_9pU;7WgCZFh^U6--fm4lD}z zfdDQy_gTeAui3!=6#k88Hm~HRpTS&Wz%uQI;etY&H za70@ed2I5Qj=uD;gDVI)R69)nU$l)$p+SPMo+S}V?eF43nuF&ihWA+s~&Y@5U8)l*jM;y7{49P zKo+^kaT~f>wnY7xY14Gu{?Jkp+=cz~yOy7Wt4378Hjs$fXhvyPO<<#4#bLX$rm-H) zgWkqibxTddCid^y9?JMu=B?$``zL?xLKo zqEc`VOu2-lt+9cHh0(v5dG?Kzy6a5|UQ+Ns^P`TwbJ46Oi3#-yoW<6^1EVb=)jh$$ z>%2TG`i{j{2I)XhT(Rk8%u4!MsXih5svmu;7`T)jq)6LG4M2iE4*6^o)kcJ|MptVQ zb~`zDJ)z!Y>%W^=l%z7U2E|(R@)Rq!ZmaUJ8~7hVS9{fMhq+#a6wS#f*x!NR11V1{ z`bS)VXw-D-d_8q}G006qM z6)H4sehUJ$0bdP0LB=yC(q03jQGXNl*Ft{}X@3YlD>XTb!wlER4@|JpxW_18(=X|V zOY{3L!&mEcyA`fO&zvX$(T&V&XQyy<`R_c6BgNRCyR?3+sLpl>Awm{x-`;qVRIjtg zM@S9PyhSP-AgriU4lKpIj)3n@f7B7vW@fM(gQ#4_4r|~K*U!`4?ib$o1hj5pS0!j# z;8(boB=Fe8sE=zC=>*08|6RLNdgcF6MOI)YmP6$BuUcyAMVQXcF&7I<1zBi06A`^m zzx1t(ni!E}SXWt2k3b3Qyj==iNd>G0Qg6@^Epu-NezRz>ERTu`5(CpK>1X)9#R?aD z_d%3}6Jb)8XRAMZsCwe%FMcDo=whWAe* z1v#Bnn<~}?XqCjlYKn5WGQir~Pz?6ZuVNC>x{aCyTUDZ#gkJERJ`NI$LVr^(H?lI> zd^aj}LKJP>g~;#+@LXFI{eI`-epu1i-+(e%E{;%&&Zcf~<(h%4WC!W5Y1~|~ACW8J zyXmZE0-eAzu#-0wVpV(_{)Nz&7J;HNj_R4h?;H>>-e>%2_8iuz4uL%m=!>b{#)fFP zdiRUkd-KL^6V|jAfkAl(b4ZgHQo~L!oYI_%y|j?+RxHJ$h!A{gKD0GH952fd<4`mC zPNtCoEr$8T2{r~Gn2TS<>OHKV{z}4iub_zjH%@O*W3FV86u)LoDu-8o%d3$E`iU9< z>tow6sCp|O`&?u8ohjWN&yc53`; z)@E=;2_++2`NIGi;F@{o78{8!0TFnJLURd*Jf|8j&qh*YWS)-Q%PYQ}HReW@JsXWR z5m==lDe&u`b7|ZXi4uUMSWoN*Mt^3FRvooskm3Brln^xUV>+x@8ZUsu9lPxOL_XKs8AE3qr)yaHw=m&)9cpn$xn}I0cW8^3cE(b_X+Arv1e;b>+h{b$@5|9cjS`7Dk zXo;-=xZK4n%w5@3wJCzW1MC+7I+(IK5I)N>inw(&u%FatQ*bNSHX6>!s@O2ra^Nt^ z1zz@WFs|xzsMmDsd9xCefJ~H(_S7+x!tU72oP|e*X4Bw;iBX+ZgGAFqGp^MNqDkHi zVXoX^dfgm*hT_Ahc7V}=K5#J~4Kk(b!|c8Frh`rV6*77o+*y{EhRV`F9}pjU>qS(8CN!{}>ek zELGiQlxa(6Q;%#qsuwf`G$3#Qm03(iaijaxHkz&L`6l`)HGodvJ(0Yf73dZ(%eABh zZcWK(PUG0H?(i&t@;-&*KyWt1D%kprhVkl}L(S6B9rwT1dcBgX#X4WgbF1=AEuZ27 zp3`iacdg;zVaD<`n$!)FXjuLtg`=1W51%#)A2TX{PebWtC8%Sa6fXF}Tw{Y+!=h;> zAD~DosD*PrLHqaB=r<=>G2ysh<&P^Jl9qGuJ|>fZcY4t(37hH(S-)1JDw%B2yP&)m zhw`{NIyC4W9&zA32a4;I2t2eG3@J4oCQSl+&L%`Ns}6CGD?P?%K4I3zz}hynW~$vU zJIcWz#s$zl<{OA=)%#Df8x_`IF6L3@w-WR9xD;3rE2MngirRF?*%dN@KPC%UsBZHhkY$rp0|7 zdbJF@JryWj*zct@%;GHm6Ow&YDYfWbhW0Mta3I-*4F>;R`&t>IaS6sn=)X)5i2vBy zvn>+4Y&U;?vw7B_B(VgNPL^Ye2hp@9^q5|G8I9l0WtF;=QJYuO%>U$X6X6x9MweW) zu+2%~QPrjTP%jo|0H$3^3sQ5L z79F?gDsZgX+Pc~|dG((h>t9BmLeOcv87kHj!KaP9%?GaT7m_8-%w17C5d#a(X?F^M!qo9 zQJvr;Fj)~QI>!Y1kq9E@ME=j9ReF@!r2Y1+?xIf1r807e?UI*JJXI#E=lYWvYvsU^ z>52|{F@ROnC5$v8NCtYX^U+vhznFyPpqfepIo#JfCOJKE&k`zJZr)5QOBfPwx%+MN z3!cJZXw&pry?3fsbf$6znecA*7}M?*&33apk+A`rbdn8}J``Is4c0so;IuQJPF zFT^@XPe8pQNJC(UXuEa^KGg(rf_W4laTMe_9W^^qye0L+ml`fOu5j2!oqsGZg|m}# zq`*b35Rz&D8c{%QCrVRG3c&@HYAEc`sP%AV$+*MBRSTb*S(rxs83aN7KMN$ULPh`7 z1TX<#9N)m+I+>Axg6r^Yh1t&Fq8_#Ll{nV6g!fO(GMxXD?;`s0U@kzj;0hLUB3?Q(-w=G&v(Vi;3*=NQ^#er zqzQr!SOBAh)(d54lnCp8ti+ZC2yq=e`h$upBsDF{CO{qB#YCR|)E1kn$X>r5W%dfS zG$GZUqm@x6G9{o}Pfdgb3qd+b?!#( zHbvXXN^akgVan(pHbMPK$!D3Uqn2P6sR(KH~;q4sf{iBHz30R5zJZYoMAS z;_Nvd&?LF-FztX40g?;R`bsJ`tYf`d@}okUY$C3; zT16@1vJJ1M`xPtxoMB%oLgJH*5a_wM6T4{t86*p4ExF!x0;comJZvO_eTQ^q^>|n2+!aO-nO8T}5apI!RrX@=&VN%y%`FWdfG~wH!uWqHrB} z97Am=+pQtNVW*`svE&GZ=B))cKAax6H z3UMXJWQ2G>>BC$2`@xC#Ppi^87+tvQbyyf^*s?!qkEZG*R*tK$zN3n^g5SO7rAekD zm^0>-uz}18G520CUC2*mC1D6sA@Fnv-uh(-UhgLtiVv8T3^Z*8g0qA;%KY!=d7$dH z3oA|O97@Ejif)`MChMU|S&X*n8Ox~!VT-8VAhK-d$Oh~bLgmj7Sv?5QafZul=tr~eF%O4z&6RDaH(r{9)Y&}9FJ@D~bDkJ2V(vsrCiq^bGpuRaDrGl)fQt9#6c(?6gO`oEvqZCnm z@+5_Nk+N7BC8EM(JEr8*hHaP>PjtY-hn(AKC|gwdx<-wZr~jnAYV~QymRy?pGXVsT z6#hY@$<%YPRma5MUH}=Uz4J5bs2TILN2H>m?XE z>xtqdbKP<1T9Uz+yEz{*+D~~)K(cdHE>77?y3yaU-jpqr=a)3fBU)`t*(>Qg z%{GeOVW_Ua8P@^O+5ZY-h}2wKUz}J+;0rD-K#g@-*xkm;e8Z<`Q*jme2nZlY(}Z!M z(s;)xSW+x=hKfakoD-Z4(zj@XN!vs*;`G2!D(hGOJ9Nyti){HYD&_{$!m#tv14R ztY_t9)5O%IZ1iZc8(}xLtC%*ZF;*_Ru?}14iaMx{Ly@!YwoYq{94tD6ePDr+P~zcMbgUMpPQ=kAuTXzM@7il@;n7v znc(hcKFUM9QX@P3QA*h<{yt+p11r&Jf<&_;&yeOB>ug zTuCet;w+`ad>?9mnrNm7JNq|0eZ3Y0(+?Q}zymRwxVJb(iTwqsShl`c5-<@nHm`>F zNXVhck=#NzX(3RVRg`DV05<>c(9Vijbrkk=HHrQjIu4buUvFg1O+=7@y)mCGbB=t_#kB_6`Rij8xOxk57%;wK~{9YNzKut-7CpwcjchjMN;(vf5gbQ%PrJ4${QXlfqsNVwh^`t1Vc|6 z;TXD2s9#Ow?YT0G0QPoUT&lMZNb1D2AzZ>w0#(_-a4qd#mM@=#-^qYtRUTQfi>{N#B>i!_9`d0VpA52PhOl=R`(y>;v~Sok7q{+07Zc#8(Cxd!V?Yab1mg_86ZfDa#Iv(6SY;_=< z`YWx$uID{75xM#$Ob*_)q!bLQ{hLbjs3`s_I@fgP86)EH4w)QVaIzS)c=vaCSW}?u zbTS>v1ly`ErI+@9c|S#-)&6C~v~^ZTVLp_puzGuz7Ku#eF?}T53s+#y;uf8xHb{#( z40iG?stqb=Y@uD%Hv@YbW-%$Q-gv+42=sY{jYnk(%WKW1WH;p233iIQ20O!5zJDq( z9riz(f=t1=Qutpbv6~XP0N+gF9Xr>v2#*H5M5Ccc_ zh3+wETftL=1F;Agod92p+monA_nbP~*Zfr17DD_I67i1lG$%rEM`Y!8a$Hgw&*!v2 zH;;moD@ns^)M6MQJ>TJ#wAwPTvSSr(xMzJ3tKuBo+r1D5ewyn&oO~YH( z6r+ni+af8~^r#ND!v>;AsV;P$02GyDpxk#o6)qJ0+|oJ4Jda>d`x%a=y7P^fVD)Q(v{AU z6hlL@KN3Fw+LZ7sNH;THKp|%_4`~RONz{9{hqJY^OQUNU1X+{OtitCxzxpF;z4jR zv*QT-$Fdy}iv5d*mu(rP)-Xp~7kHSBh6v%&!l;K7Ox}Rq&!%WpFQIQ3OScU}Hb$ox z?cxM*yw`v)0S7G=tEx?k=1Kr!F76)NqmERePuWLL&2IyfHZH0PsZk@JmOthtciZ?jf8!Rqx#Vz5=PT0C$SuBf3~cgMDKOTmk)|0TaUcv}>FtK+d>4 z2P5B=;$;v*5GV=|n@pk5=kP1q5CZb~+Iby-7)}B*a0nn_JpOo22-FO_aJ-J^nJ*7f ztot4umF5fZZxLOvV#Ja}G3Hk3OGh5o{u6?$nbwJ3(|uh%bHIV43G2-%$e%z$WC~Ho z*Ltd^7Fx!&)3;eKu}JVKqk~*zgLa$)^FmKzMp0)V*{=$+yFUvNwTpM(sgOSy2G9+} z(k@{*+}I)z>TYgQplDu!d_>DHl0X$pSu&5uMI19129DffNU@Cj`a|v3Z7NiX=Dr7l z4_*G^{7*6wk8t%mSTyAR&SXtH$y(Mf=~=kE2dbJ~D4%WJs%1j1AcnF+ly)t~&PhRK zd)BxFU{BbEgtuL}wI`KZ+Ub8-t0LDD&xP$x9)alJ?OmNEkOWrvN7@GAinexjV_1js?9G*z!1 zow^@MA|qnt`hDb1+Nn=6C&GfrPO9>kqi^IJswu$|>TSsyv5mh{2#=su4Bg52)37=PC zFTaWsrnTI^ryXd(*S)0*%2p#27+IFa4y)pQan0qp=>a@GD_cbv4O9)J?r}6avPBnX z6wHe(Uyt?HqckzFHjD1x$|Vxr==q;8$2+inU*Eo%BGump=~m6Ix*p6u zw_ORYe^#Kr3@~)xXLM!HTb9_k?3~b8z&wPpoWl16x-;ZK4XHE*L(az^ET9l%9;{leM_0kiiZHUuO`L2$4$YG|_#*b~L_c zs!-aaKXu0-JPgtD=Zq(z?#rA;W&F4HP2#NO6j=-~y?th{f zji5wqL>7uWa{lda+7=~qydSKZ@tE&LtUYL}cPT2g!Huzdg0{7n?5r$p?$V+^Qz;Wy zXFaP)$T%&#^v^tQ6hp~!{qONyk9&;W%$io!pj zpiOIME!{Eeqm2P$g^&Md1YNI6=hAOr{M#TmG##ArWl(8DZ>(I zjvgFNMZ;%MH}^S~tKOuMiDfZ;FB~pANTcnp0!|DNumSg+FDBm;X?Sb(oRK`@F>CPe z^}Rkz<$;n>f)7IQvyA5LX%(36t#E^(LZB05M_5vS$LOTaz+AS&-f3-RtUm%_8&Wc_NTk5A;AN~4HT2ed`5AztWf z=RB$vmZX@klqUAR_Jcw^>IE_|R~w`IFP7bywjt|1SYOD^Z<$&&>079KO*&`u?yOxK zaFg1jY1MXOS%92|ne%MAaGCPW*KtnV9>vL`a&mM%Yp)iE??biII}$$IzQ>RbyK--( z27b@8`T#B$=yq8oR0iLb>H_^*#wvuR*fvw6s-M5nOHeQo_?%tkxq5Yzc#%RA+FmrP zo+q$YdLJ}YAz7jgZPY@`upE>h{V$D%0W|jUyhttU7*+oVl>(9%or{#lQ;dds$5Cm# z)X2+iU*KcCeZxVoV;}j(2wMS%%PVn($v3mGx`7pz{LCkNUb6zhbd0PfeI{V=CH&ej z_`B&2UxD?h57iHB36;(ZVsaQ?oVs&e4qY@rQwff8wLvoD&Y_$*%eD1CX%*5vtl9i! zc0tH`OK(^qd>v*ax2un)L7)7s>|I(QZ7?ev|Bcms(k!)2Ejusz2{l%`wDm?7-uNC= zd@UcEcfNRs*`U~_ORX&5n^wDVx58p!@E6(FP}#s4{k8rb=ysLU#Wb-Cf?U(b*0XSB zm@0(+3hN(+zcL`9&XGR=&Y3muXEg8OkMim|YVJnGT{qJhM9vt)(hV&XR&RgWQ-FoJ z^6yj(N_fND*=%)C*nxMbNAT#PPzfjs11#*CFQS%cNiHqqpXG?RU!hAwA7&+w2k*8| zxxjd~PtkgWj35HeBf5SLLGAz8e@K-$kW+z5@UbrTe37c;xhpFCsD?Ikz);JzXKMrD z!ry6B=s5{%ptS8fG%&m{Q#W!o`4IiS#I?7G*PDr`P64Q)yw8_wR5E-AW-BXR&lOeN z_K&A{qwMmIi>~B3w*5`W=5N!0?sA{yFRi*t*ZIR#)|ejTFLPoAgnk{V_nC;tZlMc) zcC+7iC{*?tq_CXdvuFfL_Q7w2}3GOR&m9+k#PDO_nvhvfPC%f^r6vo?d?7f7Hh29rR+HqH6DX~4Tbatj_r}eZ zBA4#Org#r>6=}2a4pz%(azt9qp|XT(BHlq^gj8V~hqycrhg8+KvUZy;9|ZYD=9z_I zM_}W^aWoQUS%_B+D#}52_pdZ8Q;ZH6FsLNrG_X%wx);#mIwJ7*{$~vb391XxDxe#Z z!S4cltc|2##2=Z6+u&jlN2@>`i5tvX7}tM=4#@QH@pGoZXL~ zkhnoZ1<$WtiyZT#ju~UfHLIjhw=-$%A4_@h}|0aGXx@3=Wq-bRqH##I8BL+^g>I zDkr1BpF|D^ceA-4#9|Ls$EiL!^z4pt~yAD9o3}l1vA&E0r8ITG1LU* zD0!0&1C|O9T!P|c9Hw8PAQ5}SJR)kzJMAJimjR#hr3|kyJsWNMcxA>6P%W^Cd&oGd zl?i<})hau_n9(6BOJ$d7;rj2X6gEWT=i&PeprKtE3T#*fItSpz0dko4p)GqaRJX*2 zdQ|T&{5l@)7^2P6hLM^sF6@SW=1@he7b<#3Ozf_oVYknWV%?0)4`e9#Y`dF~Lj>s3 zE<6ggcmeaXH&YvE5Ofzyi49ub;*c)>m>#A%{v%c|dd|3O4K_8f)>5BqcSClW+YLYH z={!AIUh;R)Q4P%V`sClv+P5nH?I=k&{56sptAY0?_=sdd!kR7`3Q z`&|6|0Ce5n2vG%hF4&Pm17vOj+^WRajKHnl{KTASqM6t*6GJ>woJM?x1Ex$!keu># zn-BPB2a#M{Rx#XVy0~RUH(HFR3e|xQH2n~zK-yYQXG`$(Q5h?_i5lP0)3|W%$f>;1 z(8J%ZFwXfaHCac|;8R73biNdHG11l3dy2x>0L>)%rXg{dl$_mbwabU;JyV~VsC`Y= zqd=1_sP9OxF;>mlRRvS=;L03n=BYXpt)F5*57$23ekqCbb<@n@a#17w9r%&SrqVf0 zXT#PjgbCEOq%KBRtSdVAypg-9)fkM}VY|;?YIJFXEluIDTCV*Jd%or*8JRyqmB}2G z1Y4ULXl5Tx%lcehM*iv4%Sd&jgs@`EIQ3Q8wC5T4Ul+v$wu5(jfOfX&m`orTjwqEK z4{*UsYp0WODZDzI2~Hw~sUCvVn`XJ<-=S_ZkL>#~=;hPF=|50zm&d7U6*}^D`DQxV zwZ#?yV|9mLSp4!p8>om-2dX=!1Go7{5<1yL0#HwJ8x$JG6pYG7W>W?fE7eHNWJJ#& zHNqjZjdSZP%(Majeq`3CEZM+v-endTk`@*y!_o{YzVYIogpyN?I#}r{Gq;Ro3L;wUs`blNwQvvfz$Do6xk-_skXF@-8lZ=h*>T zMHx~GwwDoBvR4OUy|JNL30IJQ?@Uk>;d<@Jd8$`13m0JMJ@ZVgT{q%QI5APz`$wud zapC6*4G1J_4$XU`b3FNOH40)aKqHYZ@hSM1CpHy!pw$S}HD=n;d{$mqd!1>gj~kPn z?V8sQE6+~-z;fkuYCB9)S>5LHmyx>HBasUjbp#p~D*Gz*w>5Nj%0m5cC#bMECM-H( zeq;g|74A+;U&O>R)oRr4ccB`=ot+2xiIwZHu#Fw3NSs*KO6Xt2>N5Y($Krs>h6>m_ zOSK9+b0vqz!2T4-=l>4o7QY_I&1}dLO$b^F-D=cDRui$j&|PU1(lGUDP`@I;`cVXJ z9U}Y@X3GKoGLzqA`Lly-3cKQ~&Q5yfF+jKL`7CU=loUP6a?AR%Tmy9i*J<%O;J_<7 z0HmL0-Fi1EL8T9+y|vpg4>NGu0JCUWx6I1?)h`t0=(4w%hwTvekD(hS#i%Y;poJ4} zvrd227he%*LnnCb7DiUm0$fFb!JRWg>|37_P>St2D{$Vpb#qOdy_eN)N6Gs?!HA}2 zH6upAJv07s*Y6+&cyY+sBS5lK{b1Utpv1L`=?u~)s0PGP6Z`@Xb+9uHYvzMTK~ojn zMdCIs(s99Mq{X_?nI3^53D*Vzdek#d;(<3#xTY2VNygY#r1pu;z&FK|R0)L9+3pJo z*s+XWcP;%Nq?#ll3L_Vm$Rk{Yi%se@Kp54!$mnwx8W{@>Pu_R?YZsz>hpbwI4pp=p zkMx7GmlN&5^V3<5WliB*Fbys6W@2cf3`cX3nuUHw)f4w6)=R!|nTzMOdS7-FYD>bD z*Ldz~iZo|uj>1|-gNO>zyC;Y=`4yC}cgL)65V)oie>=M_1yl0|+ksp7h9^T3cj~Ah zS$;u`kZTIvwylOW`S6u`oDZB!EOQ)4!8H6TMh?iaUNeg>B(B_y!b{%+3sIPW%gGja za!{_A0HpTeNg7uP;i2Ct-$)VsraL6e1d%w%oc>3oVv1WX$pW~PSMd^D`apTPG#+oNL8An0WG^mv{mBg zA(sKvpvPCcchPakz;-Qb6mVu3yShuLZFw$s_!cg%WOEX5cOW@%sItg7v7FQ3^hxjs z`Nl~xL>kBpti-7rX!(-<&D%^rs?1CnMp{&@!Xb@tHeESg3gzACM zUf2=cMUt}W%Uy=fhm@2$J@9$IUUZtnIYYK5FZ5fSl}Xy5y?}(m zIzARl$qbWSn4#J#t<$Qb@!B{;?o(d3{Owp2_ zlS&(X2y%7T@81T2Kyq=pL{v3vJ=xHRsWlXyvL6oxgH%>>h!QS6RD?4Q)aV}!80vk* zKZf((gy;Efo^_b)TUG;gAzxrv8<*-ezNN6trQ-^!o;cQ@&Sd+g2f_l_rSg9mU5g|? z)WMr^M=}dUScu zCpqE**E-Fb(zcR7sTrjk5uc>b(Q`1c;}Sb2uvO>je$Ztx%e;)lmc{wzn%~aZu;5h& zq9PbR>dozuB|NhH9b!d36hJRgAUmNE0JK=r?sr8zK7q}~BQs;sw@(^223?5l^r{c3 zPntI#!TqKD4A0^t9`Qi87XWb6`8xsYB5Q&{rVjQ1h=dC4OCZ@|dcHS(_UbO!39a{S z)$Ozh2jvC8Ftqm7$hehiXG{yyDq>5p&WxUjDC42I5KE8#AbiU-#5Az-A^zu81#xIQ z8VcC+v}9SDG-P%QgSbVPon${IsPI)T8Sb4;IKFB30+<}?pT7ku0&2O#?V0Jz?NQ9? zG~R{bVcmbqw3B@Jp59H%VR*K$V5t*#6mw-GK*+QjuV(#&rBjd~YEJl#PG2En%X_m4 z;`!YumDnyRSnEp|{Qx598A{81DnE~#MJUmB4VucJBMug`s&KZ?hUr0=7b$mK_hU0x zFVpz~T_IQ31lN?IwF2t7_OUJKX(f4r%2#Bze8Fe&X%MT>H^oTJKTue53rHE``+x}o zU*?{dG_^jX;p4V!q3voTwET(@YT_U!79f$7?n~mvzwXTzOOe^RWeU1k&H~lu^B-Ep1W&0w(4414F@nU^S9_H z@)8S7yc+{j+7F!D;)Ca#Y>h&b^s4!344e`Wk~aR|l84KTSHBxMD~%fLuV)}8hHVy9 z{(ygcLH1)PLNha_A1=uKMAqwq@KKwIqlYR17dd){o!&txDpO8|&^l@N*J$ta+{-^% zg)VJ->t&~1$26H3k#_2+f3PKXKX)gSMH`P(R3A8QeAPXK#7%~ND01;kLYF#Lpg5JS zb!sgae$IW+(7&xrJcf=9Gmc&QS7y5}m~knQ%;=ZsZ-|L4uY%LKHs^XauxIN`7jPsB zdpEeA6{RR%xu+4;$;h;4(Uykn|1}i({k{F-M?Lx!7Sx%i4KEwtKl~?uhIx6hVPt>y z>XF`f6Yip2&$!TSg{g{wO6-9YD3-dHlCQK(uj5v*Gd5crKj5niy_qj7Q;EwY>Qk$W8Fv4TV_S z5wE;ERf?aG#>KXfwyPI?vvb|sz;NaXfvmpnKf-B^PyCE3F|fge-ZVu6pwj6-7-bfw z(Cqocv4^9q;q0Tx-_W)vhgL-l=g$echtERU*?xCrs)xpB`q&9GWBskxth$l3+a??Z zC|DD^ZB`1lV&l1s>2wgCaqb_l^p=kf4vtaqmwTdL;T+reMw;w>mL!nddQp>G%wjcx zj89o2eH8D~Z}Xc|@yKGz21TML*5Lv}WGZj>bp{X0bL|kMLkpULNi}@@UGcUD>3p}I zO)2N`kcS^sW2ysx5g`c(89eMo6zV1v83dS;+reNPpoc#g#~gIrKg!PPEnSb?i*oz_ ze7S9_?HY-*$CP%v&xOXaIXzy0Jag+kf7*e9LZDe?)q)tx6a0s}ixAwgN1wr&(Nud8 z{eN{`du&tJ8UN0G*f+M5T!R5qOt?uMNH>}}agYKF^(PPdX)>zX!f zOBkZZJTn-@0mQNjfkOqf+Yq79t*aQirlN&mNGMjDRluAQln7{XQfPT?+3$i@shZ|L z66^Y&d(J)QJKy{JouM3H?2wB)SO05{3BF{%>R>in8LpbDFgL=zSqLXDoiQh9uc4X8Zz^*CMmy@1pRAaB)?lBF;Xn`K)Q1_5`0WJR|V`&tFjlVZ@_>{qK4G6Uz z00VvvrztlpgHK4hzt%pS7iI;$EP*}w`XCuU1cI-MwDZZZj5l)uRHd6P(ao{EM*iJj zToQ(;PJJ~Aw6N^sKR3Z)m7^O|sJ#awOQ(cTK45I8G<)KQzip{N@wGjEro|gDXpfrN zPd9RkVH1(`?_j!0A?MxJ*4I2_-#2vt!0P&XRSk(|_3}!?-`ic&OvCO;W**r2vR`va5JaBw2)$E&58w6fFd=hEsn5Szfz0b+DQ^Jzo5pYY`%n38#mdmwgSKT@L;8*J%^VzIx$ zUMh8&6ymT$a0_*6Lpjtifti>MTnR%}gj~W0j1z{JCyvWRr%meQlz*zyBnyWF)gqw% zX0rwVu1_iiKtof(bTFdR;iq;J*aE?aHGDj{7Yq|0sVwWy_lV32YsD zYUk(p>%6rX4tuCcjWtBdXGmn#{2FB(25a`O$3%!FVC|OEk8Wo`eCL805OmNk@Y-Qc z-a{C1Hn$tEiNzfGjAOK{Hqo}0>joj)lxD;CVGwdRV*2SYL<311Xuc@Ti{s@uh(azV z_#3hXhE%82pl!21hDS+HKXk7I|J^Mw^~3C;!hsHAw*c8`AU8=;)1Xf4vGNum=6o1s z33MJ4He6`{Mlq5ql!U7U&eAhs9S@PG%|6Cq2>H5!2vfL(z71(dUBNBqD{(c|ql?j~ z$ginF>w!YrJL5b!vBFkNhuTu+kl$FsjA8*ANsadTpdnm+fn_jH#n*TSA*pb?Y~ZKS}PZ$3MXru;Z*mw4<8j%`2W6)g(;Eht6ea2*Mi@+vWVLr`-@x&1YD(ZrKkJ!*@2||L|qUPex4e-6BMjb5@Nd0=H z5)ZZSIf~U|cbKUmuL(1!14nADkAt8j#9eR7l-C2IGSDKs62&&yY!r zvKi=CaRYRQz?E5a-%JrY;I5ur!LnnjSuHV9YJc02umJ{AR0O<|GhZkaZ1Nif;2})y zBI>F+MqqVSy9BLC$bl;IyvOGE@sR9#Uy83ll_M~Y_8?lB^=zdkOSgLd9~hH;U$Mzm z_PJm&UY`tDRN3r*Z^J_R!eN^Xmnl0N@{-C8D$L-gRS<*1gDg{|;()@8ZXSo`FHa*` z5UW-%<522*e@Rz$N<*$qG48M1?yJOVV2Tr1pIGTY39-C=`9G4&9A?!*c`UHqij1`| zPpA#(75eWsD%l+8jTJqZe05{LG)Ve2UB@bqpF#2z$_yZXOj)_==YPZ04*o1e`y4|p z5e@0vi$) zIyJ^ybS%;;vu}2kfo>+Dv>5(s~@1HFhD`&3>^9;l0j{27PXblt}cIuiyhLVnS z{)dluK)c&Qg$i{l>^K$5Gp_(Qq}rG509M62J1=54hy*M|B^Z`wk&;FV1U7|p7Au@M z<|W1GO+QXFfhH?DvS}J&v=rk&!qm8D0I~E;${n*9`7&NabgH!v2RuJ#mZuSPAbyDj z*g1sIc^tPLLGJZ&daro7L(zX zzLeaegQm}2{TdE@K*1xG8FKYj>MG5LY~kq6KXU?$qYRjWJyj)qM2Tl(wVLy6L#71E zTHISn`>H^u@{T$dTD- zaKm|_m1Egm$%9hwf&6VNcN^eIfs7T#w{j!19uSC{+KvDy&~#SbQgq=-l{(j$(1P25y{yqybvRey(1zx47IPhgYhA%knuWVSsEm*wxT+2F z6om$qk|QV_7`rZlrMf5d$GPuhCwAN(t%^dJNRKIH z#(IQL0(|ubjrhwX+;{9RHqb66gLjNrpS@vB5K;O4Tqf&6<*rpEzHy6n^{dS|uL#~^ zn&)ziY<|#Y+JD>3eb8jy*H0bZ?3V7|z00Lqt#2YYJTmgjZ+6x2|2mSt?r3D>rw`f` TJm~6I|I<;VD0u-&FVTMh5&N5j diff --git a/firmware/fpga/dsp/mcm.py b/firmware/fpga/dsp/mcm.py index ce9bd978..820dfe4b 100644 --- a/firmware/fpga/dsp/mcm.py +++ b/firmware/fpga/dsp/mcm.py @@ -24,7 +24,7 @@ class ShiftAddMCM(wiring.Component): "output": Out(stream.Signature( data.ArrayLayout( data.StructLayout({ - f"{i}": signed(width + bits_for(term)) for i, term in enumerate(terms) + f"{i}": signed(width + bits_for(abs(term))) for i, term in enumerate(terms) }), num_channels), always_ready=always_ready)), }) @@ -71,7 +71,7 @@ class ShiftAddMCM(wiring.Component): result += shifted_n # A single register can feed multiple outputs. - result_q = Signal(signed(self.width+bits_for(term-1)), name=f"mul_{term}_{c}") + result_q = Signal(signed(self.width+bits_for(abs(term))), name=f"mul_{term}_{c}") with m.If(self.input.ready & self.input.valid): m.d.sync += result_q.eq(result) From ea4b55b4a8974c6f1dc1f9b4fb2ec0bc47e4ce8a Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Wed, 4 Mar 2026 12:33:36 -0500 Subject: [PATCH 060/238] Enable TX interpolation --- firmware/common/radio.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 8e1f445d..2ea21d63 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -188,6 +188,7 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) switch (opmode) { case TRANSCEIVER_MODE_TX: case TRANSCEIVER_MODE_SS: + n = compute_resample_log(rate / FP_ONE_HZ, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX]) { #ifdef PRALINE fpga_set_tx_interpolation_ratio(&fpga, n); @@ -196,10 +197,6 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) } break; default: - /* - * Resampling is enabled only in RX mode to work around a - * spectrum inversion bug with TX interpolation. - */ n = compute_resample_log(rate / FP_ONE_HZ, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX]) { #ifdef PRALINE From b49f1df9562f4872ea3bfa6e1e63fb9b5b49c00e Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Tue, 17 Mar 2026 13:30:18 +0200 Subject: [PATCH 061/238] Remove unused includes and avoid transitive dependencies. --- firmware/common/adc.c | 5 +- firmware/common/clkin.c | 9 ++- firmware/common/cpld_jtag.c | 13 ++-- firmware/common/cpld_xc2c.c | 6 +- firmware/common/cpld_xc2c.h | 2 +- firmware/common/crc.h | 2 +- firmware/common/da7219.c | 2 + firmware/common/da7219.h | 1 - firmware/common/fault_handler.c | 4 +- firmware/common/firmware_info.c | 5 -- firmware/common/fixed_point.h | 2 + firmware/common/fpga.c | 6 +- firmware/common/fpga.h | 4 +- firmware/common/fpga_image.c | 7 +- firmware/common/fpga_selftest.c | 19 +++-- firmware/common/gpdma.c | 2 +- firmware/common/gpio_lpc.c | 3 + firmware/common/gpio_lpc.h | 2 - firmware/common/hackrf_core.c | 28 +++++--- firmware/common/hackrf_core.h | 24 +++---- firmware/common/hackrf_ui.c | 13 ++-- firmware/common/hackrf_ui.h | 5 +- firmware/common/i2c_bus.h | 4 +- firmware/common/i2c_lpc.h | 4 +- firmware/common/ice40_spi.c | 6 +- firmware/common/ice40_spi.h | 4 +- firmware/common/m0_state.c | 2 +- firmware/common/max2831.h | 2 +- firmware/common/max2831_target.c | 3 + firmware/common/max2837.h | 2 +- firmware/common/max2837_target.c | 3 + firmware/common/max2839.h | 2 +- firmware/common/max2839_target.c | 3 + firmware/common/max283x.c | 11 +++ firmware/common/max283x.h | 18 ++--- firmware/common/max2871.c | 10 +-- firmware/common/max2871.h | 4 +- firmware/common/max5864.c | 4 +- firmware/common/max5864.h | 2 +- firmware/common/max5864_target.c | 2 + firmware/common/mixer.c | 11 ++- firmware/common/mixer.h | 2 +- firmware/common/operacake.c | 9 ++- firmware/common/operacake.h | 2 +- firmware/common/operacake_sctimer.c | 12 ++-- firmware/common/platform_detect.c | 12 ++-- firmware/common/platform_gpio.c | 7 +- firmware/common/platform_gpio.h | 2 +- firmware/common/platform_scu.c | 5 +- firmware/common/platform_scu.h | 3 +- firmware/common/portapack.c | 7 +- firmware/common/portapack.h | 4 +- firmware/common/rad1o/decoder.c | 5 +- firmware/common/rad1o/display.c | 13 ++-- firmware/common/rad1o/display.h | 5 +- firmware/common/rad1o/print.c | 2 +- firmware/common/rad1o/render.h | 2 + firmware/common/rad1o/smallfonts.c | 6 ++ firmware/common/rad1o/smallfonts.h | 5 -- firmware/common/rad1o/ubuntu18.c | 4 ++ firmware/common/rad1o/ubuntu18.h | 1 - firmware/common/radio.c | 19 +++-- firmware/common/radio.h | 2 +- firmware/common/rf_path.c | 16 +++-- firmware/common/rf_path.h | 4 +- firmware/common/rffc5071.c | 13 ++-- firmware/common/rffc5071.h | 3 +- firmware/common/rffc5071_spi.c | 10 ++- firmware/common/rffc5071_spi.h | 3 +- firmware/common/rom_iap.c | 3 +- firmware/common/rom_iap.h | 2 +- firmware/common/sgpio.c | 9 ++- firmware/common/sgpio.h | 4 +- firmware/common/si5351c.c | 25 ++++--- firmware/common/si5351c.h | 3 +- firmware/common/spi_bus.h | 2 +- firmware/common/spi_ssp.c | 3 + firmware/common/spi_ssp.h | 5 +- firmware/common/streaming.c | 3 +- firmware/common/tuning.c | 12 +++- firmware/common/tuning.h | 10 +-- firmware/common/ui_portapack.c | 6 ++ firmware/common/ui_rad1o.c | 10 ++- firmware/common/usb.c | 15 ++-- firmware/common/usb.h | 3 + firmware/common/usb_queue.c | 4 +- firmware/common/usb_queue.h | 2 + firmware/common/usb_request.c | 5 +- firmware/common/usb_standard_request.c | 8 +-- firmware/common/usb_standard_request.h | 5 +- firmware/common/usb_type.h | 1 - firmware/common/w25q80bv.c | 6 +- firmware/common/w25q80bv.h | 9 +-- firmware/common/w25q80bv_target.c | 3 + firmware/common/xapp058/ports.c | 5 +- firmware/hackrf_usb/hackrf_usb.c | 85 ++++++++++++++--------- firmware/hackrf_usb/usb_api_adc.c | 12 +++- firmware/hackrf_usb/usb_api_adc.h | 2 +- firmware/hackrf_usb/usb_api_board_info.c | 21 +++--- firmware/hackrf_usb/usb_api_board_info.h | 2 +- firmware/hackrf_usb/usb_api_cpld.c | 17 ++--- firmware/hackrf_usb/usb_api_cpld.h | 4 +- firmware/hackrf_usb/usb_api_m0_state.c | 6 +- firmware/hackrf_usb/usb_api_m0_state.h | 2 +- firmware/hackrf_usb/usb_api_operacake.c | 7 +- firmware/hackrf_usb/usb_api_operacake.h | 2 +- firmware/hackrf_usb/usb_api_praline.c | 11 +-- firmware/hackrf_usb/usb_api_praline.h | 2 +- firmware/hackrf_usb/usb_api_register.c | 19 +++-- firmware/hackrf_usb/usb_api_register.h | 2 +- firmware/hackrf_usb/usb_api_selftest.c | 20 ++++-- firmware/hackrf_usb/usb_api_selftest.h | 2 +- firmware/hackrf_usb/usb_api_spiflash.c | 8 ++- firmware/hackrf_usb/usb_api_spiflash.h | 2 +- firmware/hackrf_usb/usb_api_sweep.c | 22 +++--- firmware/hackrf_usb/usb_api_sweep.h | 5 +- firmware/hackrf_usb/usb_api_transceiver.c | 35 ++++------ firmware/hackrf_usb/usb_api_transceiver.h | 4 +- firmware/hackrf_usb/usb_api_ui.c | 6 +- firmware/hackrf_usb/usb_api_ui.h | 2 +- firmware/hackrf_usb/usb_bulk_buffer.h | 1 - firmware/hackrf_usb/usb_descriptor.c | 5 +- firmware/hackrf_usb/usb_endpoint.c | 2 + firmware/hackrf_usb/usb_endpoint.h | 2 +- 124 files changed, 568 insertions(+), 344 deletions(-) diff --git a/firmware/common/adc.c b/firmware/common/adc.c index 5d1ddaca..9355567f 100644 --- a/firmware/common/adc.c +++ b/firmware/common/adc.c @@ -19,10 +19,13 @@ * Boston, MA 02110-1301, USA. */ -#include "adc.h" +#include + #include #include +#include "adc.h" + uint16_t adc_read(uint8_t pin) { bool alt_pin = (pin & 0x80); diff --git a/firmware/common/clkin.c b/firmware/common/clkin.c index 5ab8123a..9f63681c 100644 --- a/firmware/common/clkin.c +++ b/firmware/common/clkin.c @@ -19,12 +19,17 @@ * Boston, MA 02110-1301, USA. */ -#include "gpdma.h" +#include "clkin.h" + +#include + #include #include #include +#include #include -#include + +#include "gpdma.h" #define CLOCK_CYCLES_1_MS (204000) #define MEASUREMENT_WINDOW_MS (50) diff --git a/firmware/common/cpld_jtag.c b/firmware/common/cpld_jtag.c index 1641499b..4ef9ce5d 100644 --- a/firmware/common/cpld_jtag.c +++ b/firmware/common/cpld_jtag.c @@ -19,11 +19,14 @@ * Boston, MA 02110-1301, USA. */ +#if !defined(PRALINE) + #include +#endif + #include "cpld_jtag.h" -#include "hackrf_core.h" -#include "xapp058/micro.h" -#include -#include +#if !defined(PRALINE) + #include "xapp058/micro.h" +#endif #ifndef PRALINE static refill_buffer_cb refill_buffer; @@ -111,4 +114,4 @@ unsigned char cpld_jtag_get_next_byte(void) xsvf_pos++; return byte; } -#endif \ No newline at end of file +#endif diff --git a/firmware/common/cpld_xc2c.c b/firmware/common/cpld_xc2c.c index 58a5a6b6..ec5ffeb1 100644 --- a/firmware/common/cpld_xc2c.c +++ b/firmware/common/cpld_xc2c.c @@ -22,11 +22,11 @@ #include "cpld_xc2c.h" -#include "crc.h" - -#include #include +#include "crc.h" +#include "gpio.h" + // clang-format off typedef enum { CPLD_XC2C_IR_INTEST = 0b00000010, diff --git a/firmware/common/cpld_xc2c.h b/firmware/common/cpld_xc2c.h index 2e33967b..26ac8fa4 100644 --- a/firmware/common/cpld_xc2c.h +++ b/firmware/common/cpld_xc2c.h @@ -23,8 +23,8 @@ #ifndef __CPLD_XC2C_H__ #define __CPLD_XC2C_H__ -#include #include +#include #include "cpld_jtag.h" diff --git a/firmware/common/crc.h b/firmware/common/crc.h index 787b29a6..f8acf5fc 100644 --- a/firmware/common/crc.h +++ b/firmware/common/crc.h @@ -23,8 +23,8 @@ #ifndef __CRC_H__ #define __CRC_H__ -#include #include +#include typedef struct { uint32_t remainder; diff --git a/firmware/common/da7219.c b/firmware/common/da7219.c index dd175863..376e04a5 100644 --- a/firmware/common/da7219.c +++ b/firmware/common/da7219.c @@ -19,6 +19,8 @@ * Boston, MA 02110-1301, USA. */ +#include + #include "da7219.h" #include "hackrf_core.h" #include "i2c_bus.h" diff --git a/firmware/common/da7219.h b/firmware/common/da7219.h index 1c255159..f0289240 100644 --- a/firmware/common/da7219.h +++ b/firmware/common/da7219.h @@ -22,7 +22,6 @@ #ifndef __DA7219_H #define __DA7219_H -#include #include #define DA7219_ADDRESS 0x1A diff --git a/firmware/common/fault_handler.c b/firmware/common/fault_handler.c index 63c868d8..9d20c71e 100644 --- a/firmware/common/fault_handler.c +++ b/firmware/common/fault_handler.c @@ -21,10 +21,10 @@ * Boston, MA 02110-1301, USA. */ -#include - #include "fault_handler.h" +#include + typedef struct { uint32_t r0; uint32_t r1; diff --git a/firmware/common/firmware_info.c b/firmware/common/firmware_info.c index 2b3d25ff..1ac02074 100644 --- a/firmware/common/firmware_info.c +++ b/firmware/common/firmware_info.c @@ -21,11 +21,6 @@ #include "firmware_info.h" #include "platform_detect.h" -#include "gpio_lpc.h" -#include "hackrf_core.h" - -#include -#include #ifdef JAWBREAKER #define SUPPORTED_PLATFORM PLATFORM_JAWBREAKER diff --git a/firmware/common/fixed_point.h b/firmware/common/fixed_point.h index 9485aaea..500d2e54 100644 --- a/firmware/common/fixed_point.h +++ b/firmware/common/fixed_point.h @@ -22,6 +22,8 @@ #ifndef __FIXED_POINT_H__ #define __FIXED_POINT_H__ +#include + /* 40.24 fixed-point */ typedef uint64_t fp_40_24_t; diff --git a/firmware/common/fpga.c b/firmware/common/fpga.c index 34ebd791..9c4d55f2 100644 --- a/firmware/common/fpga.c +++ b/firmware/common/fpga.c @@ -19,11 +19,13 @@ * Boston, MA 02110-1301, USA. */ +#include "fpga.h" + #include + +#include "fpga_regs.def" #include "hackrf_core.h" #include "ice40_spi.h" -#include "fpga.h" -#include "fpga_regs.def" /* Set up all registers according to the loaded bitstream's defaults. */ void fpga_init(fpga_driver_t* const drv) diff --git a/firmware/common/fpga.h b/firmware/common/fpga.h index 2b1fbe14..bf78cf08 100644 --- a/firmware/common/fpga.h +++ b/firmware/common/fpga.h @@ -23,6 +23,8 @@ #define __FPGA_H #include +#include + #include "ice40_spi.h" /* Up to 7 registers, each containing up to 8 bits of data */ @@ -35,7 +37,7 @@ typedef enum { FPGA_QUARTER_SHIFT_MODE_DOWN = 0b01, } fpga_quarter_shift_mode_t; -struct fpga_driver_t; +struct fpga_driver_t; // IWYU pragma: keep - fixed in #1704 typedef struct fpga_driver_t fpga_driver_t; struct fpga_driver_t { diff --git a/firmware/common/fpga_image.c b/firmware/common/fpga_image.c index 8d0c1932..dc88556b 100644 --- a/firmware/common/fpga_image.c +++ b/firmware/common/fpga_image.c @@ -19,10 +19,15 @@ * Boston, MA 02110-1301, USA. */ +#include +#include +#include + +#include "fpga.h" #include "hackrf_core.h" +#include "ice40_spi.h" #include "lz4_blk.h" #include "selftest.h" -#include "fpga.h" struct fpga_image_read_ctx { struct fpga_loader_t* loader; diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index 2b5ec1b3..cc1d8d9c 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -19,12 +19,21 @@ * Boston, MA 02110-1301, USA. */ -#include "hackrf_core.h" -#include "m0_state.h" -#include "streaming.h" -#include "selftest.h" -#include "fpga.h" +#include +#include +#include + #include "delay.h" +#include "fixed_point.h" +#include "fpga.h" +#include "hackrf_core.h" +#include "ice40_spi.h" +#include "m0_state.h" +#include "max283x.h" +#include "rf_path.h" +#include "selftest.h" +#include "sgpio.h" +#include "streaming.h" // USB buffer used during selftests. #define USB_BULK_BUFFER_SIZE 0x8000 diff --git a/firmware/common/gpdma.c b/firmware/common/gpdma.c index 42ba78b4..3dc61452 100644 --- a/firmware/common/gpdma.c +++ b/firmware/common/gpdma.c @@ -20,7 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#include +#include "gpdma.h" #include diff --git a/firmware/common/gpio_lpc.c b/firmware/common/gpio_lpc.c index 6e639d8d..16a436cc 100644 --- a/firmware/common/gpio_lpc.c +++ b/firmware/common/gpio_lpc.c @@ -22,8 +22,11 @@ #include "gpio_lpc.h" +#include #include +#include "gpio.h" + void gpio_init(void) { for (size_t i = 0; i < 8; i++) { diff --git a/firmware/common/gpio_lpc.h b/firmware/common/gpio_lpc.h index f47e490a..f018e43c 100644 --- a/firmware/common/gpio_lpc.h +++ b/firmware/common/gpio_lpc.h @@ -25,8 +25,6 @@ #include -#include "gpio.h" - /* NOTE: libopencm3 constants and functions not used here due to naming * conflicts. I'd recommend changes to libopencm3 design to separate * register #defines and API declarations into separate header files. diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 4793efd9..8db0e855 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -21,26 +21,32 @@ * Boston, MA 02110-1301, USA. */ +#include +#include +#include +#include +#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) + #include +#endif + +#include "delay.h" +#include "gpio.h" #include "hackrf_core.h" #include "hackrf_ui.h" -#include "delay.h" +#include "i2c_lpc.h" #include "max283x.h" #include "max5864_target.h" -#include "w25q80bv_target.h" -#include "i2c_lpc.h" -#include "ice40_spi.h" #include "platform_detect.h" #include "platform_gpio.h" #include "platform_scu.h" -#include "clkin.h" -#include -#include - -#if (defined HACKRF_ONE || defined PRALINE) +#include "spi_bus.h" +#include "w25q80bv_target.h" +#if defined(HACKRF_ONE) || defined(PRALINE) #include "portapack.h" #endif - -#include "gpio_lpc.h" +#if defined(PRALINE) + #include "ice40_spi.h" +#endif i2c_bus_t i2c0 = { .obj = (void*) I2C0_BASE, diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index c9ca7dce..74a171a1 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -28,25 +28,25 @@ extern "C" { #endif -#include #include +#include -#include "si5351c.h" -#include "spi_ssp.h" - +#include "cpld_jtag.h" +#include "fixed_point.h" +#include "i2c_bus.h" #include "max283x.h" #include "max5864.h" #include "mixer.h" -#include "w25q80bv.h" -#include "sgpio.h" #include "radio.h" #include "rf_path.h" -#include "cpld_jtag.h" -#include "ice40_spi.h" -#include "fpga.h" -#include "fixed_point.h" - -#include "platform_scu.h" +#include "sgpio.h" +#include "si5351c.h" +#include "spi_ssp.h" +#include "w25q80bv.h" +#if defined(PRALINE) + #include "fpga.h" + #include "ice40_spi.h" +#endif /* TODO: Hide these configurations */ extern si5351c_driver_t clock_gen; diff --git a/firmware/common/hackrf_ui.c b/firmware/common/hackrf_ui.c index ac7f1c18..dbf1cc24 100644 --- a/firmware/common/hackrf_ui.c +++ b/firmware/common/hackrf_ui.c @@ -20,13 +20,16 @@ * Boston, MA 02110-1301, USA. */ -#include "hackrf_ui.h" - -#include "ui_portapack.h" -#include "ui_rad1o.h" - #include +#include "hackrf_ui.h" +#if defined(PRALINE) || defined(HACKRF_ONE) + #include "ui_portapack.h" +#endif +#if defined(RAD1O) + #include "ui_rad1o.h" +#endif + #define UNUSED(x) (void) (x) /* Stub functions for null UI function table */ diff --git a/firmware/common/hackrf_ui.h b/firmware/common/hackrf_ui.h index cc9a6fa6..24d2fa8e 100644 --- a/firmware/common/hackrf_ui.h +++ b/firmware/common/hackrf_ui.h @@ -23,9 +23,12 @@ #ifndef HACKRF_UI_H #define HACKRF_UI_H -#include +#include #include +#include "radio.h" +#include "rf_path.h" + typedef void (*hackrf_ui_init_fn)(void); typedef void (*hackrf_ui_deinit_fn)(void); typedef void (*hackrf_ui_set_frequency_fn)(uint64_t frequency); diff --git a/firmware/common/i2c_bus.h b/firmware/common/i2c_bus.h index 7eb745c7..95431437 100644 --- a/firmware/common/i2c_bus.h +++ b/firmware/common/i2c_bus.h @@ -23,10 +23,10 @@ #ifndef __I2C_BUS_H__ #define __I2C_BUS_H__ -#include #include +#include -struct i2c_bus_t; +struct i2c_bus_t; // IWYU pragma: keep - fixed in #1704 typedef struct i2c_bus_t i2c_bus_t; struct i2c_bus_t { diff --git a/firmware/common/i2c_lpc.h b/firmware/common/i2c_lpc.h index db57282f..c4f3e8c3 100644 --- a/firmware/common/i2c_lpc.h +++ b/firmware/common/i2c_lpc.h @@ -23,9 +23,9 @@ #ifndef __I2C_LPC_H__ #define __I2C_LPC_H__ -#include -#include #include +#include +#include #include "i2c_bus.h" diff --git a/firmware/common/ice40_spi.c b/firmware/common/ice40_spi.c index 69491df0..c8364b8a 100644 --- a/firmware/common/ice40_spi.c +++ b/firmware/common/ice40_spi.c @@ -21,8 +21,10 @@ #include "ice40_spi.h" -#include "hackrf_core.h" -#include "lz4_buf.h" +#include +#include +#include + #include "delay.h" #include "platform_scu.h" diff --git a/firmware/common/ice40_spi.h b/firmware/common/ice40_spi.h index 2a0cdac5..92ce6280 100644 --- a/firmware/common/ice40_spi.h +++ b/firmware/common/ice40_spi.h @@ -22,12 +22,14 @@ #ifndef __ICE40_SPI_H #define __ICE40_SPI_H +#include #include #include + #include "gpio.h" #include "spi_bus.h" -struct ice40_spi_driver_t; +struct ice40_spi_driver_t; // IWYU pragma: keep - fixed in #1704 typedef struct ice40_spi_driver_t ice40_spi_driver_t; struct ice40_spi_driver_t { diff --git a/firmware/common/m0_state.c b/firmware/common/m0_state.c index 83af28d0..cfb74295 100644 --- a/firmware/common/m0_state.c +++ b/firmware/common/m0_state.c @@ -20,8 +20,8 @@ */ #include "m0_state.h" + #include -#include void m0_set_mode(enum m0_mode mode) { diff --git a/firmware/common/max2831.h b/firmware/common/max2831.h index 2fa06973..9298247a 100644 --- a/firmware/common/max2831.h +++ b/firmware/common/max2831.h @@ -48,7 +48,7 @@ typedef enum { MAX2831_RX_HPF_600_KHZ = 3, } max2831_rx_hpf_freq_t; -struct max2831_driver_t; +struct max2831_driver_t; // IWYU pragma: keep - fixed in #1704 typedef struct max2831_driver_t max2831_driver_t; struct max2831_driver_t { diff --git a/firmware/common/max2831_target.c b/firmware/common/max2831_target.c index 47a07eaa..21c8a16d 100644 --- a/firmware/common/max2831_target.c +++ b/firmware/common/max2831_target.c @@ -21,6 +21,9 @@ #include "max2831_target.h" +#include + +#include "gpio.h" #include "platform_scu.h" void max2831_target_init(max2831_driver_t* const drv) diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index 5f0b0024..0c7a65c8 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -41,7 +41,7 @@ typedef enum { MAX2837_MODE_RX } max2837_mode_t; -struct max2837_driver_t; +struct max2837_driver_t; // IWYU pragma: keep - fixed in #1704 typedef struct max2837_driver_t max2837_driver_t; struct max2837_driver_t { diff --git a/firmware/common/max2837_target.c b/firmware/common/max2837_target.c index 91e48d71..6446a48c 100644 --- a/firmware/common/max2837_target.c +++ b/firmware/common/max2837_target.c @@ -23,6 +23,9 @@ #include "max2837_target.h" +#include + +#include "gpio.h" #include "platform_scu.h" void max2837_target_init(max2837_driver_t* const drv) diff --git a/firmware/common/max2839.h b/firmware/common/max2839.h index fbffa5b1..ac238fe2 100644 --- a/firmware/common/max2839.h +++ b/firmware/common/max2839.h @@ -44,7 +44,7 @@ typedef enum { MAX2839_MODE_CLKOUT, } max2839_mode_t; -struct max2839_driver_t; +struct max2839_driver_t; // IWYU pragma: keep - fixed in #1704 typedef struct max2839_driver_t max2839_driver_t; struct max2839_driver_t { diff --git a/firmware/common/max2839_target.c b/firmware/common/max2839_target.c index 63c2f6ec..3932bb7a 100644 --- a/firmware/common/max2839_target.c +++ b/firmware/common/max2839_target.c @@ -23,6 +23,9 @@ #include "max2839_target.h" +#include + +#include "gpio.h" #include "platform_scu.h" void max2839_target_init(max2839_driver_t* const drv) diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index 7dd2c3fd..7c5de380 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -21,10 +21,21 @@ * Boston, MA 02110-1301, USA. */ +#include + #include "max283x.h" #include "platform_gpio.h" #include "spi_bus.h" +#if defined(PRALINE) + #include "max2831.h" + #include "max2831_target.h" +#else + #include "max2837.h" + #include "max2837_target.h" + #include "max2839.h" + #include "max2839_target.h" +#endif extern spi_bus_t spi_bus_ssp1; diff --git a/firmware/common/max283x.h b/firmware/common/max283x.h index 3da32d11..e67bf8de 100644 --- a/firmware/common/max283x.h +++ b/firmware/common/max283x.h @@ -24,19 +24,15 @@ #ifndef __MAX283x_H #define __MAX283x_H -#include #include -#include +#include -#include "gpio.h" -#include "gpio_lpc.h" -#include "max2831.h" -#include "max2831_target.h" -#include "max2837.h" -#include "max2837_target.h" -#include "max2839.h" -#include "max2839_target.h" -#include "spi_bus.h" +#if defined(PRALINE) + #include "max2831.h" +#else + #include "max2837.h" + #include "max2839.h" +#endif typedef enum { MAX283x_MODE_SHUTDOWN, diff --git a/firmware/common/max2871.c b/firmware/common/max2871.c index 9179c93e..2d9b0c29 100644 --- a/firmware/common/max2871.c +++ b/firmware/common/max2871.c @@ -20,22 +20,22 @@ */ #include "max2871.h" + +#include +#include + #include "max2871_regs.h" #include "selftest.h" +#include "platform_scu.h" #if (defined DEBUG) #include #define LOG printf #else #define LOG(x, ...) - #include #include - #include "hackrf_core.h" #endif -#include -#include - static uint32_t max2871_spi_read(max2871_driver_t* const drv); static void max2871_spi_write(max2871_driver_t* const drv, uint8_t r, uint32_t v); static void max2871_write_registers(max2871_driver_t* const drv); diff --git a/firmware/common/max2871.h b/firmware/common/max2871.h index a11172bc..3cc9bb3a 100644 --- a/firmware/common/max2871.h +++ b/firmware/common/max2871.h @@ -22,10 +22,10 @@ #ifndef MAX2871_H #define MAX2871_H -#include "gpio.h" - #include +#include "gpio.h" + typedef struct { gpio_t gpio_vco_ce; gpio_t gpio_vco_sclk; diff --git a/firmware/common/max5864.c b/firmware/common/max5864.c index 78a84661..b91a1cd1 100644 --- a/firmware/common/max5864.c +++ b/firmware/common/max5864.c @@ -20,10 +20,10 @@ * Boston, MA 02110-1301, USA. */ -#include - #include "max5864.h" +#include + static void max5864_write(max5864_driver_t* const drv, uint8_t value) { spi_bus_transfer(drv->bus, &value, 1); diff --git a/firmware/common/max5864.h b/firmware/common/max5864.h index a0602e50..0ce2c6e1 100644 --- a/firmware/common/max5864.h +++ b/firmware/common/max5864.h @@ -25,7 +25,7 @@ #include "spi_bus.h" -struct max5864_driver_t; +struct max5864_driver_t; // IWYU pragma: keep - fixed in #1704 typedef struct max5864_driver_t max5864_driver_t; struct max5864_driver_t { diff --git a/firmware/common/max5864_target.c b/firmware/common/max5864_target.c index 208ee9c3..1fc64934 100644 --- a/firmware/common/max5864_target.c +++ b/firmware/common/max5864_target.c @@ -22,6 +22,8 @@ #include "max5864_target.h" +#include + #include "platform_scu.h" void max5864_target_init(max5864_driver_t* const drv) diff --git a/firmware/common/mixer.c b/firmware/common/mixer.c index c615c7f1..cc598701 100644 --- a/firmware/common/mixer.c +++ b/firmware/common/mixer.c @@ -20,10 +20,15 @@ */ #include "mixer.h" -#include "rffc5071.h" -#include "rffc5071_spi.h" -#include "max2871.h" + #include "platform_gpio.h" +#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) + #include "rffc5071.h" + #include "rffc5071_spi.h" + #include "spi_bus.h" +#elif defined(RAD1O) + #include "max2871.h" +#endif #if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) static rffc5071_spi_config_t rffc5071_spi_config; diff --git a/firmware/common/mixer.h b/firmware/common/mixer.h index 840ebba2..bfd638bb 100644 --- a/firmware/common/mixer.h +++ b/firmware/common/mixer.h @@ -23,7 +23,7 @@ #ifndef __MIXER_H #define __MIXER_H -#if (defined JAWBREAKER || defined HACKRF_ONE || defined PRALINE) +#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) #include "rffc5071.h" typedef rffc5071_driver_t mixer_driver_t; #elif defined(RAD1O) diff --git a/firmware/common/operacake.c b/firmware/common/operacake.c index 7c2e85da..61d78512 100644 --- a/firmware/common/operacake.c +++ b/firmware/common/operacake.c @@ -21,11 +21,16 @@ */ #include "operacake.h" -#include "operacake_sctimer.h" -#include "hackrf_core.h" + +#include + +#include + #include "gpio.h" #include "gpio_lpc.h" +#include "hackrf_core.h" #include "i2c_bus.h" +#include "operacake_sctimer.h" #include "platform_scu.h" /* diff --git a/firmware/common/operacake.h b/firmware/common/operacake.h index ec8bae25..39da6ef0 100644 --- a/firmware/common/operacake.h +++ b/firmware/common/operacake.h @@ -27,8 +27,8 @@ extern "C" { #endif -#include #include +#include #define OPERACAKE_PA1 0 #define OPERACAKE_PA2 1 diff --git a/firmware/common/operacake_sctimer.c b/firmware/common/operacake_sctimer.c index 8658c0e6..9ae37567 100644 --- a/firmware/common/operacake_sctimer.c +++ b/firmware/common/operacake_sctimer.c @@ -22,14 +22,16 @@ #include "operacake_sctimer.h" -#include - -#include +#include #include #include -#include -#include "sct.h" +#if !defined(PRALINE) + #include + #include +#endif + #include "delay.h" +#include "sct.h" #define U1CTRL_SET SCT_OUT14_SET #define U1CTRL_CLR SCT_OUT14_CLR diff --git a/firmware/common/platform_detect.c b/firmware/common/platform_detect.c index bb44a61c..b3903035 100644 --- a/firmware/common/platform_detect.c +++ b/firmware/common/platform_detect.c @@ -19,14 +19,16 @@ * Boston, MA 02110-1301, USA. */ -#include "platform_detect.h" +#include + +#include "adc.h" +#include "delay.h" #include "firmware_info.h" +#include "gpio.h" #include "gpio_lpc.h" #include "hackrf_core.h" -#include "delay.h" -#include "adc.h" - -#include +#include "platform_detect.h" +#include "platform_scu.h" static board_id_t platform = BOARD_ID_UNDETECTED; static board_rev_t revision = BOARD_REV_UNDETECTED; diff --git a/firmware/common/platform_gpio.c b/firmware/common/platform_gpio.c index 66211d5f..df07fc2a 100644 --- a/firmware/common/platform_gpio.c +++ b/firmware/common/platform_gpio.c @@ -19,9 +19,14 @@ * Boston, MA 02110-1301, USA. */ -#include #include "platform_gpio.h" +#include + +#if defined(HACKRF_ONE) + #include "platform_detect.h" +#endif + // clang-format off const platform_gpio_t* platform_gpio(void) diff --git a/firmware/common/platform_gpio.h b/firmware/common/platform_gpio.h index a6669cbd..e327e4ba 100644 --- a/firmware/common/platform_gpio.h +++ b/firmware/common/platform_gpio.h @@ -26,8 +26,8 @@ extern "C" { #endif +#include "gpio.h" #include "gpio_lpc.h" -#include "platform_detect.h" typedef struct { /* LEDs */ diff --git a/firmware/common/platform_scu.c b/firmware/common/platform_scu.c index 2da5ff7a..f29ac543 100644 --- a/firmware/common/platform_scu.c +++ b/firmware/common/platform_scu.c @@ -19,9 +19,12 @@ * Boston, MA 02110-1301, USA. */ -#include #include "platform_scu.h" +#include + +#include + // clang-format off const platform_scu_t* platform_scu(void) diff --git a/firmware/common/platform_scu.h b/firmware/common/platform_scu.h index 7db50071..793eefa5 100644 --- a/firmware/common/platform_scu.h +++ b/firmware/common/platform_scu.h @@ -26,8 +26,9 @@ extern "C" { #endif +#include + #include -#include "platform_detect.h" /* * SCU PinMux diff --git a/firmware/common/portapack.c b/firmware/common/portapack.c index 6220ed35..fefa2f11 100644 --- a/firmware/common/portapack.c +++ b/firmware/common/portapack.c @@ -22,10 +22,15 @@ #include "portapack.h" +#include + +#include "cpld_jtag.h" +#include "delay.h" +#include "gpio.h" +#include "gpio_lpc.h" #include "hackrf_core.h" #include "platform_gpio.h" #include "platform_scu.h" -#include "delay.h" static void portapack_sleep_milliseconds(const uint32_t milliseconds) { diff --git a/firmware/common/portapack.h b/firmware/common/portapack.h index b24e75f1..d4dda66e 100644 --- a/firmware/common/portapack.h +++ b/firmware/common/portapack.h @@ -23,9 +23,9 @@ #ifndef __PORTAPACK_H__ #define __PORTAPACK_H__ -#include -#include #include +#include +#include #define ARRAY_SIZEOF(x) (sizeof(x) / sizeof(x[0])) diff --git a/firmware/common/rad1o/decoder.c b/firmware/common/rad1o/decoder.c index b5450194..53d3636c 100644 --- a/firmware/common/rad1o/decoder.c +++ b/firmware/common/rad1o/decoder.c @@ -1,8 +1,7 @@ -#include "fonts.h" -#include "render.h" - #include +#include "render.h" + // Local function: Get next nibble. static int ctr = 0; // offset for next nibble static int hilo = 0; // 0= high nibble next, 1=low nibble next diff --git a/firmware/common/rad1o/display.c b/firmware/common/rad1o/display.c index a48202e0..91813aab 100644 --- a/firmware/common/rad1o/display.c +++ b/firmware/common/rad1o/display.c @@ -1,16 +1,15 @@ #include "display.h" -#include "gpio_lpc.h" -#include "hackrf_core.h" -#include "delay.h" - -#include -#include - #include #include #include +#include + +#include "gpio.h" +#include "gpio_lpc.h" +#include "delay.h" + static void delayms(const uint32_t milliseconds) { /* NOTE: Naively assumes 204 MHz instruction cycle clock and five instructions per count */ diff --git a/firmware/common/rad1o/display.h b/firmware/common/rad1o/display.h index 7a9e077f..63711dfc 100644 --- a/firmware/common/rad1o/display.h +++ b/firmware/common/rad1o/display.h @@ -1,10 +1,11 @@ #ifndef __RAD1O_DISPLAY_H__ #define __RAD1O_DISPLAY_H__ -#include - #include +#include +#include + #define RESX 130 #define RESY 130 diff --git a/firmware/common/rad1o/print.c b/firmware/common/rad1o/print.c index 4b9958cd..d279f4e7 100644 --- a/firmware/common/rad1o/print.c +++ b/firmware/common/rad1o/print.c @@ -1,6 +1,6 @@ #include "print.h" + #include "display.h" -#include "fonts.h" #include "render.h" #include "smallfonts.h" diff --git a/firmware/common/rad1o/render.h b/firmware/common/rad1o/render.h index dcfdd6c8..1c623381 100644 --- a/firmware/common/rad1o/render.h +++ b/firmware/common/rad1o/render.h @@ -1,6 +1,8 @@ #ifndef __RENDER_H_ #define __RENDER_H_ +#include + #include "fonts.h" void rad1o_setTextColor(uint8_t bg, uint8_t fg); diff --git a/firmware/common/rad1o/smallfonts.c b/firmware/common/rad1o/smallfonts.c index 14413a75..7bae79ee 100644 --- a/firmware/common/rad1o/smallfonts.c +++ b/firmware/common/rad1o/smallfonts.c @@ -37,8 +37,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ + #include "smallfonts.h" +#include +#include + +#include "fonts.h" + /* System 7x8 */ const uint8_t au8Font7x8[] = { 0, 0, 0, 0, 0, 0, 0, //' ' diff --git a/firmware/common/rad1o/smallfonts.h b/firmware/common/rad1o/smallfonts.h index d195c28b..af69bf27 100644 --- a/firmware/common/rad1o/smallfonts.h +++ b/firmware/common/rad1o/smallfonts.h @@ -38,11 +38,6 @@ #ifndef __RAD1O_SMALLFONTS_H__ #define __RAD1O_SMALLFONTS_H__ -#include "fonts.h" - -#include -#include - /* Partially based on original code for the KS0108 by Stephane Rey */ /* Current version by Kevin Townsend */ diff --git a/firmware/common/rad1o/ubuntu18.c b/firmware/common/rad1o/ubuntu18.c index d47ef49d..524667ff 100644 --- a/firmware/common/rad1o/ubuntu18.c +++ b/firmware/common/rad1o/ubuntu18.c @@ -1,5 +1,9 @@ #include "ubuntu18.h" +#include + +#include "fonts.h" + /* Font data for Ubuntu Regular 18pt */ /* Copyright 2010 Canonical Ltd. Licensed under the Ubuntu Font Licence 1.0 diff --git a/firmware/common/rad1o/ubuntu18.h b/firmware/common/rad1o/ubuntu18.h index fe9a9923..38b58e76 100644 --- a/firmware/common/rad1o/ubuntu18.h +++ b/firmware/common/rad1o/ubuntu18.h @@ -1,6 +1,5 @@ #ifndef __RAD1O_UBUNTU18_H__ #define __RAD1O_UBUNTU18_H__ -#include "fonts.h" extern const struct FONT_DEF Font_Ubuntu18pt; diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 2ea21d63..c714d5e7 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -19,16 +19,23 @@ * Boston, MA 02110-1301, USA. */ -#include +#include +#include +#include + +#include "fixed_point.h" #include "hackrf_core.h" -#include "tuning.h" -#include "rf_path.h" -#include "fpga.h" +#include "hackrf_ui.h" +#include "max283x.h" #include "platform_detect.h" #include "radio.h" -#include "fixed_point.h" -#include "hackrf_ui.h" +#include "rf_path.h" +#include "tuning.h" +#if defined(PRALINE) + #include "fpga.h" + #include "tune_config.h" +#endif #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define MAX(x, y) ((x) > (y) ? (x) : (y)) diff --git a/firmware/common/radio.h b/firmware/common/radio.h index 13cd2626..7b526a9d 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -24,8 +24,8 @@ #ifndef __RF_CONFIG_H__ #define __RF_CONFIG_H__ -#include #include +#include #include "fixed_point.h" diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 9fee21e7..c78ec831 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -23,18 +23,22 @@ #include "rf_path.h" -#include +#if defined(HACKRF_ONE) || defined(RAD1O) || defined(PRALINE) + #include +#endif +#include "hackrf_core.h" #include "hackrf_ui.h" -#include "gpio_lpc.h" -#include "platform_detect.h" -#include "platform_scu.h" -#include "mixer.h" #include "max283x.h" #include "max5864.h" +#include "mixer.h" +#include "platform_detect.h" #include "sgpio.h" +#if defined(HACKRF_ONE) || defined(RAD1O) || defined(PRALINE) + #include "platform_scu.h" +#endif -#if (defined JAWBREAKER || defined HACKRF_ONE || defined RAD1O || defined PRALINE) +#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(RAD1O) || defined(PRALINE) /* * RF switches on Jawbreaker are controlled by General Purpose Outputs (GPO) on * the RFFC5072. diff --git a/firmware/common/rf_path.h b/firmware/common/rf_path.h index e7c47130..2d098d86 100644 --- a/firmware/common/rf_path.h +++ b/firmware/common/rf_path.h @@ -26,7 +26,9 @@ #include -#include "gpio.h" +#if defined(HACKRF_ONE) || defined(RAD1O) || defined(PRALINE) + #include "gpio.h" +#endif typedef enum { RF_PATH_DIRECTION_OFF, diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index f8339bce..177537f5 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -33,13 +33,18 @@ #include #include + +#if defined(PRALINE) + #include +#endif + +#include "delay.h" #include "rffc5071.h" #include "rffc5071_regs.def" // private register def macros #include "selftest.h" - -#include "hackrf_core.h" -#include "delay.h" -#include "platform_scu.h" +#if defined(PRALINE) + #include "platform_scu.h" +#endif static bool enabled = false; diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index f191b98d..506f1a09 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -23,10 +23,11 @@ #ifndef __RFFC5071_H #define __RFFC5071_H +#include #include -#include "spi_bus.h" #include "gpio.h" +#include "spi_bus.h" /* 31 registers, each containing 16 bits of data. */ #define RFFC5071_NUM_REGS 31 diff --git a/firmware/common/rffc5071_spi.c b/firmware/common/rffc5071_spi.c index 943bb0c8..6fd2c936 100644 --- a/firmware/common/rffc5071_spi.c +++ b/firmware/common/rffc5071_spi.c @@ -20,11 +20,15 @@ * Boston, MA 02110-1301, USA. */ -#include "hackrf_core.h" -#include "platform_scu.h" - #include "rffc5071_spi.h" +#include +#include + +#include + +#include "platform_scu.h" + static void rffc5071_spi_target_select(spi_bus_t* const bus) { const rffc5071_spi_config_t* const config = bus->config; diff --git a/firmware/common/rffc5071_spi.h b/firmware/common/rffc5071_spi.h index fddf67d8..7df2d8bf 100644 --- a/firmware/common/rffc5071_spi.h +++ b/firmware/common/rffc5071_spi.h @@ -23,9 +23,10 @@ #ifndef __RFFC5071_SPI_H #define __RFFC5071_SPI_H -#include "spi_bus.h" +#include #include "gpio.h" +#include "spi_bus.h" typedef struct rffc5071_spi_config_t { gpio_t gpio_select; diff --git a/firmware/common/rom_iap.c b/firmware/common/rom_iap.c index c926359a..a8f185ad 100644 --- a/firmware/common/rom_iap.c +++ b/firmware/common/rom_iap.c @@ -20,10 +20,11 @@ * Boston, MA 02110-1301, USA. */ -#include "hackrf_core.h" #include +#include "hackrf_core.h" #include "rom_iap.h" +#include "spi_bus.h" #include "w25q80bv.h" #define ROM_IAP_ADDR (0x10400100) diff --git a/firmware/common/rom_iap.h b/firmware/common/rom_iap.h index 171f2678..50cfcf93 100644 --- a/firmware/common/rom_iap.h +++ b/firmware/common/rom_iap.h @@ -23,8 +23,8 @@ #ifndef __ROM_IAP__ #define __ROM_IAP__ -#include #include +#include typedef enum { /* TODO define other commands */ diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index 6f095217..f364d7b0 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -22,13 +22,18 @@ * Boston, MA 02110-1301, USA. */ +#include + +#include +#include #include -#include "hackrf_core.h" #include "platform_detect.h" #include "platform_scu.h" - #include "sgpio.h" +#if !defined(PRALINE) + #include "hackrf_core.h" +#endif static void update_q_invert(sgpio_config_t* const config); diff --git a/firmware/common/sgpio.h b/firmware/common/sgpio.h index 0d8e9f0f..08d7d222 100644 --- a/firmware/common/sgpio.h +++ b/firmware/common/sgpio.h @@ -23,10 +23,8 @@ #ifndef __SGPIO_H__ #define __SGPIO_H__ -#include #include - -#include +#include #include "gpio.h" diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 399d01fc..8b6e52fd 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -20,16 +20,23 @@ * Boston, MA 02110-1301, USA. */ -#include "si5351c.h" -#include "clkin.h" -#include "platform_detect.h" -#include "platform_gpio.h" -#include "platform_scu.h" -#include "hackrf_core.h" -#include "selftest.h" -#include "delay.h" - #include +#include + +#if defined(HACKRF_ONE) + #include +#endif + +#include "clkin.h" +#include "delay.h" +#include "platform_detect.h" +#include "selftest.h" +#include "si5351c.h" +#if defined(HACKRF_ONE) + #include "gpio.h" + #include "platform_gpio.h" + #include "platform_scu.h" +#endif static enum pll_sources active_clock_source = PLL_SOURCE_UNINITIALIZED; /* External clock output default is deactivated as it creates noise */ diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index 001991dc..d151a74d 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -27,8 +27,9 @@ extern "C" { #endif -#include #include +#include +#include #include "i2c_bus.h" diff --git a/firmware/common/spi_bus.h b/firmware/common/spi_bus.h index d24e2bbf..cd885644 100644 --- a/firmware/common/spi_bus.h +++ b/firmware/common/spi_bus.h @@ -30,7 +30,7 @@ typedef struct { const size_t count; } spi_transfer_t; -struct spi_bus_t; +struct spi_bus_t; // IWYU pragma: keep - fixed in #1704 typedef struct spi_bus_t spi_bus_t; struct spi_bus_t { diff --git a/firmware/common/spi_ssp.c b/firmware/common/spi_ssp.c index 4e25aa4a..7c288d51 100644 --- a/firmware/common/spi_ssp.c +++ b/firmware/common/spi_ssp.c @@ -22,6 +22,9 @@ #include "spi_ssp.h" +#include + +#include #include #include diff --git a/firmware/common/spi_ssp.h b/firmware/common/spi_ssp.h index 769277dd..2325f49f 100644 --- a/firmware/common/spi_ssp.h +++ b/firmware/common/spi_ssp.h @@ -26,11 +26,10 @@ #include #include -#include "spi_bus.h" +#include #include "gpio.h" - -#include +#include "spi_bus.h" typedef struct ssp_config_t { ssp_datasize_t data_bits; diff --git a/firmware/common/streaming.c b/firmware/common/streaming.c index d984fe25..1c2440fb 100644 --- a/firmware/common/streaming.c +++ b/firmware/common/streaming.c @@ -23,9 +23,10 @@ #include -#include #include +#include "sgpio.h" + void baseband_streaming_enable(sgpio_config_t* const sgpio_config) { SGPIO_SET_EN_1 = (1 << SGPIO_SLICE_A); diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 5e6ae7ff..47724e36 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -22,12 +22,18 @@ */ #include "tuning.h" -#include "hackrf_ui.h" + #include "hackrf_core.h" +#include "hackrf_ui.h" +#include "max283x.h" #include "mixer.h" #include "sgpio.h" -#include "operacake.h" -#include "platform_detect.h" +#if defined(PRALINE) || defined(HACKRF_ONE) + #include "operacake.h" +#endif +#ifdef PRALINE + #include "fpga.h" +#endif #ifndef PRALINE diff --git a/firmware/common/tuning.h b/firmware/common/tuning.h index 863fe6a0..b76dbcc3 100644 --- a/firmware/common/tuning.h +++ b/firmware/common/tuning.h @@ -24,11 +24,13 @@ #ifndef __TUNING_H__ #define __TUNING_H__ -#include "rf_path.h" -#include "tune_config.h" - -#include #include +#include + +#include "rf_path.h" +#if defined(PRALINE) + #include "tune_config.h" +#endif #define FREQ_ONE_MHZ (1000ULL * 1000) diff --git a/firmware/common/ui_portapack.c b/firmware/common/ui_portapack.c index c6bf3039..8a44db04 100644 --- a/firmware/common/ui_portapack.c +++ b/firmware/common/ui_portapack.c @@ -22,7 +22,13 @@ #include "ui_portapack.h" +#include +#include +#include + #include "portapack.h" +#include "radio.h" +#include "rf_path.h" /* Pixel data within a font or bitmap byte is "reversed": LSB is left-most pixel. */ diff --git a/firmware/common/ui_rad1o.c b/firmware/common/ui_rad1o.c index 8312c12b..977c5205 100644 --- a/firmware/common/ui_rad1o.c +++ b/firmware/common/ui_rad1o.c @@ -22,6 +22,14 @@ #include "ui_rad1o.h" +#include +#include +#include + +#include "hackrf_core.h" +#include "radio.h" +#include "rf_path.h" + #include "rad1o/display.h" #include "rad1o/draw.h" #include "rad1o/print.h" @@ -29,8 +37,6 @@ #include "rad1o/smallfonts.h" #include "rad1o/ubuntu18.h" -#include - static uint64_t freq = 0; static uint32_t sample_rate = 0; static uint32_t filter_bw = 0; diff --git a/firmware/common/usb.c b/firmware/common/usb.c index 85795ec9..64cd6c08 100644 --- a/firmware/common/usb.c +++ b/firmware/common/usb.c @@ -20,19 +20,20 @@ * Boston, MA 02110-1301, USA. */ -#include #include +#include -#include "usb.h" -#include "usb_type.h" -#include "usb_queue.h" -#include "usb_standard_request.h" - +#include #include -#include +#include #include #include +#include "usb.h" +#include "usb_queue.h" +#include "usb_standard_request.h" +#include "usb_type.h" + usb_device_t* usb_device_usb0 = 0; usb_queue_head_t usb_qh[12] ATTR_ALIGNED(2048); diff --git a/firmware/common/usb.h b/firmware/common/usb.h index 3d089816..ee2ff9b6 100644 --- a/firmware/common/usb.h +++ b/firmware/common/usb.h @@ -23,6 +23,9 @@ #ifndef __USB_H__ #define __USB_H__ +#include +#include + // TODO: Refactor to support high performance operations without having to // expose usb_transfer_descriptor_t. Or usb_endpoint_prime(). Or, or, or... #include diff --git a/firmware/common/usb_queue.c b/firmware/common/usb_queue.c index a4cab94a..3d5a4c34 100644 --- a/firmware/common/usb_queue.c +++ b/firmware/common/usb_queue.c @@ -21,12 +21,12 @@ * Boston, MA 02110-1301, USA. */ -#include #include #include -#include +#include #include +#include #include "locking.h" #include "usb.h" diff --git a/firmware/common/usb_queue.h b/firmware/common/usb_queue.h index 793db5e0..8793558f 100644 --- a/firmware/common/usb_queue.h +++ b/firmware/common/usb_queue.h @@ -24,6 +24,8 @@ #ifndef __USB_QUEUE_H__ #define __USB_QUEUE_H__ +#include + #include #include "usb_type.h" diff --git a/firmware/common/usb_request.c b/firmware/common/usb_request.c index 9aa2f595..e05cfa01 100644 --- a/firmware/common/usb_request.c +++ b/firmware/common/usb_request.c @@ -20,12 +20,13 @@ * Boston, MA 02110-1301, USA. */ -#include "usb.h" #include "usb_request.h" -#include "usb_queue.h" #include +#include "usb.h" +#include "usb_queue.h" + static void usb_request(usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { usb_request_status_t status = USB_REQUEST_STATUS_STALL; diff --git a/firmware/common/usb_standard_request.c b/firmware/common/usb_standard_request.c index 9671f5bf..152802c8 100644 --- a/firmware/common/usb_standard_request.c +++ b/firmware/common/usb_standard_request.c @@ -20,14 +20,14 @@ * Boston, MA 02110-1301, USA. */ -#include -#include - #include "usb_standard_request.h" +#include +#include + #include "usb.h" -#include "usb_type.h" #include "usb_queue.h" +#include "usb_type.h" const uint8_t* usb_endpoint_descriptor(const usb_endpoint_t* const endpoint) { diff --git a/firmware/common/usb_standard_request.h b/firmware/common/usb_standard_request.h index f27d4292..e9ea9f69 100644 --- a/firmware/common/usb_standard_request.h +++ b/firmware/common/usb_standard_request.h @@ -23,8 +23,11 @@ #ifndef __USB_STANDARD_REQUEST_H__ #define __USB_STANDARD_REQUEST_H__ -#include "usb_type.h" +#include +#include + #include "usb_request.h" +#include "usb_type.h" void usb_set_configuration_changed_cb(void (*callback)(usb_device_t* const)); diff --git a/firmware/common/usb_type.h b/firmware/common/usb_type.h index fcff336c..b268c6bb 100644 --- a/firmware/common/usb_type.h +++ b/firmware/common/usb_type.h @@ -24,7 +24,6 @@ #define __USB_TYPE_H__ #include -#include // TODO: Move this to some common compiler-tricks location. #define ATTR_PACKED __attribute__((packed)) diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index 08480138..9e7e1acd 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -27,11 +27,11 @@ * programming the flash. */ -#include -#include - #include "w25q80bv.h" +#include +#include + #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #define W25Q80BV_READ_DATA 0x03 diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index 55fefaad..f737afe6 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -24,14 +24,15 @@ #ifndef __W25Q80BV_H__ #define __W25Q80BV_H__ -#include #include +#include + +#include "gpio.h" +#include "spi_bus.h" #define W25Q80BV_DEVICE_ID_RES 0x13 /* Expected device_id for W25Q80BV */ #define W25Q16DV_DEVICE_ID_RES 0x14 /* Expected device_id for W25Q16DV */ #define W25Q32JV_DEVICE_ID_RES 0x15 /* Expected device_id for W25Q32JV */ -#include "spi_bus.h" -#include "gpio.h" typedef union { uint64_t id_64b; @@ -39,7 +40,7 @@ typedef union { uint8_t id_8b[8]; /* 8*8bits 64bits Unique ID */ } w25q80bv_unique_id_t; -struct w25q80bv_driver_t; +struct w25q80bv_driver_t; // IWYU pragma: keep - fixed in #1704 typedef struct w25q80bv_driver_t w25q80bv_driver_t; struct w25q80bv_driver_t { diff --git a/firmware/common/w25q80bv_target.c b/firmware/common/w25q80bv_target.c index b4a50a7b..40fd4fbb 100644 --- a/firmware/common/w25q80bv_target.c +++ b/firmware/common/w25q80bv_target.c @@ -22,6 +22,9 @@ #include "w25q80bv_target.h" +#include + +#include "gpio.h" #include "platform_scu.h" /* TODO: Why is CS being controlled manually when SSP0 could do it diff --git a/firmware/common/xapp058/ports.c b/firmware/common/xapp058/ports.c index 336c83cf..16b4b03d 100644 --- a/firmware/common/xapp058/ports.c +++ b/firmware/common/xapp058/ports.c @@ -9,11 +9,12 @@ /* Updated comments to clarify instructions.*/ /* Add print in setPort for xapp058_example.exe.*/ /*******************************************************/ + #include "ports.h" -#include "hackrf_core.h" -#include "cpld_jtag.h" +#include +#include "cpld_jtag.h" #include "gpio.h" void delay_jtag(uint32_t duration) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 749e188d..6170ce6d 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -21,50 +21,69 @@ * Boston, MA 02110-1301, USA. */ -#include +#include +#include #include #include #include -#include -#include - -#include - -#include "tuning.h" - -#include "usb.h" -#include "usb_standard_request.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include "usb_descriptor.h" +#include +#include +#include +#include +#include +#include +#if defined(HACKRF_ONE) + #include +#endif +#if defined(PRALINE) || defined(HACKRF_ONE) + #include +#endif +#if defined(PRALINE) || defined(HACKRF_ONE) || defined(JAWBREAKER) + #include +#endif +#if defined(PRALINE) + #include + #if !(defined(DFU_MODE) || defined(RAM_MODE)) + #include + #include + #include + #endif +#else + #include + #include +#endif -#include "usb_device.h" -#include "usb_endpoint.h" -#include "usb_api_board_info.h" -#include "usb_api_cpld.h" -#include "usb_api_register.h" -#include "usb_api_spiflash.h" -#include "usb_api_operacake.h" -#include "usb_api_praline.h" -#include "usb_api_selftest.h" #include "usb_api_adc.h" -#include "operacake.h" +#include "usb_api_board_info.h" +#include "usb_api_m0_state.h" +#include "usb_api_operacake.h" +#include "usb_api_register.h" +#include "usb_api_selftest.h" +#include "usb_api_spiflash.h" #include "usb_api_sweep.h" #include "usb_api_transceiver.h" #include "usb_api_ui.h" -#include "usb_bulk_buffer.h" -#include "usb_api_m0_state.h" -#include "cpld_xc2c.h" -#include "portapack.h" -#include "hackrf_ui.h" -#include "platform_detect.h" -#include "clkin.h" -#include "fpga.h" -#include "selftest.h" -#include "delay.h" -#include "lz4_buf.h" -#include "da7219.h" +#include "usb_descriptor.h" +#include "usb_device.h" +#include "usb_endpoint.h" +#if defined(PRALINE) + #include "usb_api_praline.h" +#else + #include "usb_api_cpld.h" +#endif extern uint32_t __m0_start__; extern uint32_t __m0_end__; diff --git a/firmware/hackrf_usb/usb_api_adc.c b/firmware/hackrf_usb/usb_api_adc.c index ee1bc98e..30d33d30 100644 --- a/firmware/hackrf_usb/usb_api_adc.c +++ b/firmware/hackrf_usb/usb_api_adc.c @@ -19,11 +19,17 @@ * Boston, MA 02110-1301, USA. */ -#include -#include -#include "adc.h" #include "usb_api_adc.h" +#include +#include + +#include +#include +#include + +#include "adc.h" + usb_request_status_t usb_vendor_request_adc_read( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) diff --git a/firmware/hackrf_usb/usb_api_adc.h b/firmware/hackrf_usb/usb_api_adc.h index 8f4d2568..e321267e 100644 --- a/firmware/hackrf_usb/usb_api_adc.h +++ b/firmware/hackrf_usb/usb_api_adc.h @@ -22,8 +22,8 @@ #ifndef __USB_API_ADC_H__ #define __USB_API_ADC_H__ -#include #include +#include usb_request_status_t usb_vendor_request_adc_read( usb_endpoint_t* const endpoint, diff --git a/firmware/hackrf_usb/usb_api_board_info.c b/firmware/hackrf_usb/usb_api_board_info.c index ffa135f2..a1ad3bce 100644 --- a/firmware/hackrf_usb/usb_api_board_info.c +++ b/firmware/hackrf_usb/usb_api_board_info.c @@ -22,20 +22,21 @@ */ #include "usb_api_board_info.h" -#include "platform_detect.h" -#include "platform_gpio.h" -#include "firmware_info.h" -#include -#include -#include -#include - -#include #include +#include + +#include +#include +#include +#include +#include +#include +#include #ifdef HACKRF_ONE - #include "gpio_lpc.h" + #include + #include #endif usb_request_status_t usb_vendor_request_read_board_id( diff --git a/firmware/hackrf_usb/usb_api_board_info.h b/firmware/hackrf_usb/usb_api_board_info.h index 663d25d8..77e4066d 100644 --- a/firmware/hackrf_usb/usb_api_board_info.h +++ b/firmware/hackrf_usb/usb_api_board_info.h @@ -26,8 +26,8 @@ #include -#include #include +#include typedef struct { uint32_t part_id[2]; diff --git a/firmware/hackrf_usb/usb_api_cpld.c b/firmware/hackrf_usb/usb_api_cpld.c index 19748a24..7d8200c3 100644 --- a/firmware/hackrf_usb/usb_api_cpld.c +++ b/firmware/hackrf_usb/usb_api_cpld.c @@ -23,18 +23,19 @@ #include "usb_api_cpld.h" -#include -#include -#include -#include - -#include "usb_endpoint.h" - -#include #include #include #include +#include +#include +#include +#include +#include +#include + +#include "usb_endpoint.h" + uint8_t cpld_xsvf_buffer[512]; volatile bool cpld_wait = false; diff --git a/firmware/hackrf_usb/usb_api_cpld.h b/firmware/hackrf_usb/usb_api_cpld.h index dfbdcfe6..f508ea5f 100644 --- a/firmware/hackrf_usb/usb_api_cpld.h +++ b/firmware/hackrf_usb/usb_api_cpld.h @@ -24,10 +24,8 @@ #ifndef __USB_API_CPLD_H__ #define __USB_API_CPLD_H__ -#include - -#include #include +#include void cpld_update(void); diff --git a/firmware/hackrf_usb/usb_api_m0_state.c b/firmware/hackrf_usb/usb_api_m0_state.c index 678d8dee..f8679b83 100644 --- a/firmware/hackrf_usb/usb_api_m0_state.c +++ b/firmware/hackrf_usb/usb_api_m0_state.c @@ -21,10 +21,12 @@ #include "usb_api_m0_state.h" -#include #include -#include + +#include #include +#include +#include usb_request_status_t usb_vendor_request_get_m0_state( usb_endpoint_t* const endpoint, diff --git a/firmware/hackrf_usb/usb_api_m0_state.h b/firmware/hackrf_usb/usb_api_m0_state.h index 32f40fcf..4e7ba2a4 100644 --- a/firmware/hackrf_usb/usb_api_m0_state.h +++ b/firmware/hackrf_usb/usb_api_m0_state.h @@ -23,7 +23,7 @@ #define __M0_STATE_USB_H__ #include -#include "m0_state.h" +#include usb_request_status_t usb_vendor_request_get_m0_state( usb_endpoint_t* const endpoint, diff --git a/firmware/hackrf_usb/usb_api_operacake.c b/firmware/hackrf_usb/usb_api_operacake.c index 81644ce1..a9766086 100644 --- a/firmware/hackrf_usb/usb_api_operacake.c +++ b/firmware/hackrf_usb/usb_api_operacake.c @@ -21,12 +21,17 @@ */ #include "usb_api_operacake.h" -#include "usb_queue.h" +#include #include +#include + #include #include #include +#include +#include +#include usb_request_status_t usb_vendor_request_operacake_get_boards( usb_endpoint_t* const endpoint, diff --git a/firmware/hackrf_usb/usb_api_operacake.h b/firmware/hackrf_usb/usb_api_operacake.h index cc511bda..6e772ec1 100644 --- a/firmware/hackrf_usb/usb_api_operacake.h +++ b/firmware/hackrf_usb/usb_api_operacake.h @@ -23,8 +23,8 @@ #ifndef __USB_API_OPERACAKE_H__ #define __USB_API_OPERACAKE_H__ -#include #include +#include usb_request_status_t usb_vendor_request_operacake_get_boards( usb_endpoint_t* const endpoint, diff --git a/firmware/hackrf_usb/usb_api_praline.c b/firmware/hackrf_usb/usb_api_praline.c index c5b8fd30..6a44da60 100644 --- a/firmware/hackrf_usb/usb_api_praline.c +++ b/firmware/hackrf_usb/usb_api_praline.c @@ -22,11 +22,14 @@ */ #include "usb_api_praline.h" -#include "usb_queue.h" -#include -#include -#include +#include +#include +#include +#include +#if !(defined(DFU_MODE) || defined(RAM_MODE)) + #include +#endif usb_request_status_t usb_vendor_request_p1_ctrl( usb_endpoint_t* const endpoint, diff --git a/firmware/hackrf_usb/usb_api_praline.h b/firmware/hackrf_usb/usb_api_praline.h index 2fb2bd48..df96c921 100644 --- a/firmware/hackrf_usb/usb_api_praline.h +++ b/firmware/hackrf_usb/usb_api_praline.h @@ -22,8 +22,8 @@ #ifndef __USB_API_PRALINE_H__ #define __USB_API_PRALINE_H__ -#include #include +#include usb_request_status_t usb_vendor_request_p2_ctrl( usb_endpoint_t* const endpoint, diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index e863acd5..01d9fa8f 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -23,17 +23,24 @@ */ #include "usb_api_register.h" -#include -#include -#include -#include -#include -#include +#include #include #include #include +#include +#include +#include +#include +#include +#include +#if defined(PRALINE) || defined(HACKRF_ONE) || defined(JAWBREAKER) + #include +#endif +#if defined(PRALINE) + #include +#endif usb_request_status_t usb_vendor_request_write_max283x( usb_endpoint_t* const endpoint, diff --git a/firmware/hackrf_usb/usb_api_register.h b/firmware/hackrf_usb/usb_api_register.h index 07714b39..c94710cb 100644 --- a/firmware/hackrf_usb/usb_api_register.h +++ b/firmware/hackrf_usb/usb_api_register.h @@ -24,8 +24,8 @@ #ifndef __USB_API_REGISTER_H__ #define __USB_API_REGISTER_H__ -#include #include +#include usb_request_status_t usb_vendor_request_write_max283x( usb_endpoint_t* const endpoint, diff --git a/firmware/hackrf_usb/usb_api_selftest.c b/firmware/hackrf_usb/usb_api_selftest.c index 16a1cff4..4fe2e628 100644 --- a/firmware/hackrf_usb/usb_api_selftest.c +++ b/firmware/hackrf_usb/usb_api_selftest.c @@ -19,14 +19,24 @@ * Boston, MA 02110-1301, USA. */ -#include #include -#include -#include +#include +#if defined(PRALINE) || defined(HACKRF_ONE) || defined(JAWBREAKER) + #include +#endif + #include +#include + +#include +#include +#include +#include +#if !defined(PRALINE) + #include +#endif + #include "usb_api_selftest.h" -#include "selftest.h" -#include "platform_detect.h" static char* itoa(int val, int base) { diff --git a/firmware/hackrf_usb/usb_api_selftest.h b/firmware/hackrf_usb/usb_api_selftest.h index 453d0362..69478653 100644 --- a/firmware/hackrf_usb/usb_api_selftest.h +++ b/firmware/hackrf_usb/usb_api_selftest.h @@ -22,8 +22,8 @@ #ifndef __USB_API_SELFTEST_H #define __USB_API_SELFTEST_H -#include #include +#include usb_request_status_t usb_vendor_request_read_selftest( usb_endpoint_t* const endpoint, diff --git a/firmware/hackrf_usb/usb_api_spiflash.c b/firmware/hackrf_usb/usb_api_spiflash.c index 5133fa0c..d422836e 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.c +++ b/firmware/hackrf_usb/usb_api_spiflash.c @@ -23,12 +23,14 @@ #include "usb_api_spiflash.h" -#include "usb_queue.h" - #include +#include #include - +#include +#include +#include +#include #include /* Buffer size == spi_flash.page_len */ diff --git a/firmware/hackrf_usb/usb_api_spiflash.h b/firmware/hackrf_usb/usb_api_spiflash.h index cd46b4aa..726734a2 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.h +++ b/firmware/hackrf_usb/usb_api_spiflash.h @@ -24,8 +24,8 @@ #ifndef __USB_API_SPIFLASH_H__ #define __USB_API_SPIFLASH_H__ -#include #include +#include usb_request_status_t usb_vendor_request_erase_spiflash( usb_endpoint_t* const endpoint, diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index a8e7934c..0c5dbfff 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -20,19 +20,25 @@ * Boston, MA 02110-1301, USA. */ -#include "usb_api_sweep.h" -#include "usb_queue.h" +#include #include + +#include +#include + +#include #include +#include +#include +#include +#include +#include +#include + +#include "usb_api_sweep.h" #include "usb_api_transceiver.h" #include "usb_bulk_buffer.h" -#include "usb_api_m0_state.h" -#include "tuning.h" #include "usb_endpoint.h" -#include "streaming.h" -#include "fixed_point.h" - -#include #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define MAX(x, y) ((x) > (y) ? (x) : (y)) diff --git a/firmware/hackrf_usb/usb_api_sweep.h b/firmware/hackrf_usb/usb_api_sweep.h index afae5f72..95cfe848 100644 --- a/firmware/hackrf_usb/usb_api_sweep.h +++ b/firmware/hackrf_usb/usb_api_sweep.h @@ -23,9 +23,10 @@ #ifndef __USB_API_SWEEP_H__ #define __USB_API_SWEEP_H__ -#include -#include +#include + #include +#include enum sweep_style { LINEAR = 0, diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 964ff22c..ab3d6af4 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -23,30 +23,23 @@ #include "usb_api_transceiver.h" -#include "hackrf_ui.h" -#include "operacake_sctimer.h" - -#include -#include "usb_bulk_buffer.h" -#include "usb_api_m0_state.h" - -#include "usb_api_cpld.h" // Remove when CPLD update is handled elsewhere - -#include "max2837.h" -#include "max2839.h" -#include "rf_path.h" -#include "tuning.h" -#include "streaming.h" -#include "usb.h" -#include "usb_queue.h" -#include "platform_detect.h" -#include "fixed_point.h" - +#include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "usb_bulk_buffer.h" #include "usb_endpoint.h" -#include "usb_api_sweep.h" #define USB_TRANSFER_SIZE 0x4000 diff --git a/firmware/hackrf_usb/usb_api_transceiver.h b/firmware/hackrf_usb/usb_api_transceiver.h index e06d6c16..e28e6bbb 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.h +++ b/firmware/hackrf_usb/usb_api_transceiver.h @@ -24,7 +24,9 @@ #ifndef __USB_API_TRANSCEIVER_H__ #define __USB_API_TRANSCEIVER_H__ -#include +#include + +#include #include #include diff --git a/firmware/hackrf_usb/usb_api_ui.c b/firmware/hackrf_usb/usb_api_ui.c index 5fe1becb..918a6e23 100644 --- a/firmware/hackrf_usb/usb_api_ui.c +++ b/firmware/hackrf_usb/usb_api_ui.c @@ -22,12 +22,10 @@ #include "usb_api_ui.h" -#include #include #include - -#include -#include +#include +#include usb_request_status_t usb_vendor_request_set_ui_enable( usb_endpoint_t* const endpoint, diff --git a/firmware/hackrf_usb/usb_api_ui.h b/firmware/hackrf_usb/usb_api_ui.h index f7f6996b..62eecfa7 100644 --- a/firmware/hackrf_usb/usb_api_ui.h +++ b/firmware/hackrf_usb/usb_api_ui.h @@ -23,8 +23,8 @@ #ifndef __USB_API_UI_H__ #define __USB_API_UI_H__ -#include #include +#include usb_request_status_t usb_vendor_request_set_ui_enable( usb_endpoint_t* const endpoint, diff --git a/firmware/hackrf_usb/usb_bulk_buffer.h b/firmware/hackrf_usb/usb_bulk_buffer.h index 3e284143..f3021bf5 100644 --- a/firmware/hackrf_usb/usb_bulk_buffer.h +++ b/firmware/hackrf_usb/usb_bulk_buffer.h @@ -24,7 +24,6 @@ #ifndef __USB_BULK_BUFFER_H__ #define __USB_BULK_BUFFER_H__ -#include #include #define USB_BULK_BUFFER_SIZE 0x8000 diff --git a/firmware/hackrf_usb/usb_descriptor.c b/firmware/hackrf_usb/usb_descriptor.c index 679a9589..7c98f0ca 100644 --- a/firmware/hackrf_usb/usb_descriptor.c +++ b/firmware/hackrf_usb/usb_descriptor.c @@ -20,10 +20,11 @@ * Boston, MA 02110-1301, USA. */ +#include "usb_descriptor.h" + #include -#include "usb_type.h" -#include "usb_descriptor.h" +#include #define USB_VENDOR_ID (0x1D50) diff --git a/firmware/hackrf_usb/usb_endpoint.c b/firmware/hackrf_usb/usb_endpoint.c index 02832708..a8a35f0d 100644 --- a/firmware/hackrf_usb/usb_endpoint.c +++ b/firmware/hackrf_usb/usb_endpoint.c @@ -23,7 +23,9 @@ #include "usb_endpoint.h" +#include #include +#include #include "usb_device.h" diff --git a/firmware/hackrf_usb/usb_endpoint.h b/firmware/hackrf_usb/usb_endpoint.h index 7a594cd5..acb86ab5 100644 --- a/firmware/hackrf_usb/usb_endpoint.h +++ b/firmware/hackrf_usb/usb_endpoint.h @@ -24,8 +24,8 @@ #ifndef __USB_ENDPOINT_H__ #define __USB_ENDPOINT_H__ -#include #include +#include extern usb_endpoint_t usb_endpoint_control_out; extern USB_DECLARE_QUEUE(usb_endpoint_control_out); From 99cdefb761a8ee76677687ba2a40bb5647e307a0 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Fri, 27 Mar 2026 18:07:35 -0400 Subject: [PATCH 062/238] Clean up vestiges of Jellybean --- firmware/common/platform_scu.c | 2 +- firmware/common/rf_path.c | 100 ++++++++++++++++----------------- 2 files changed, 50 insertions(+), 52 deletions(-) diff --git a/firmware/common/platform_scu.c b/firmware/common/platform_scu.c index f29ac543..df611bd2 100644 --- a/firmware/common/platform_scu.c +++ b/firmware/common/platform_scu.c @@ -176,7 +176,7 @@ const platform_scu_t* platform_scu(void) scu.XCVR_RXHP_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.XCVR_LD_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0 | SCU_CONF_EPD_EN_PULLDOWN | SCU_CONF_EPUN_DIS_PULLUP); -#elif defined(JELLYBEAN) || defined(JAWBREAKER) || defined(HACKRF_ONE) +#elif defined(JAWBREAKER) || defined(HACKRF_ONE) scu.XCVR_ENABLE = P4_6; /* GPIO2[6] on P4_6 */ scu.XCVR_RXENABLE = P4_5; /* GPIO2[5] on P4_5 */ scu.XCVR_TXENABLE = P4_4; /* GPIO2[4] on P4_4 */ diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index c78ec831..30c8c718 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Jared Boone * Copyright 2013 Benjamin Vernoux * @@ -38,57 +38,55 @@ #include "platform_scu.h" #endif -#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(RAD1O) || defined(PRALINE) - /* - * RF switches on Jawbreaker are controlled by General Purpose Outputs (GPO) on - * the RFFC5072. - * - * On HackRF One, the same signals are controlled by GPIO on the LPC. - * SWITCHCTRL_NO_TX_AMP_PWR and SWITCHCTRL_NO_RX_AMP_PWR are not normally used - * on HackRF One as the amplifier power is instead controlled only by - * SWITCHCTRL_AMP_BYPASS. - * - * The rad1o also uses GPIO pins to control the different switches. The amplifiers - * are also connected to the LPC. - * - * On Praline, a subset of control signals is managed by GPIO pins on the LPC, while - * the remaining signals are generated through combinatorial logic in hardware. - */ - #define SWITCHCTRL_NO_TX_AMP_PWR (1 << 0) /* GPO1 turn off TX amp power */ - #define SWITCHCTRL_AMP_BYPASS (1 << 1) /* GPO2 bypass amp section */ - #define SWITCHCTRL_TX (1 << 2) /* GPO3 1 for TX mode, 0 for RX mode */ - #define SWITCHCTRL_MIX_BYPASS (1 << 3) /* GPO4 bypass RFFC5072 mixer section */ - #define SWITCHCTRL_HP (1 << 4) /* GPO5 1 for high-pass, 0 for low-pass */ - #define SWITCHCTRL_NO_RX_AMP_PWR (1 << 5) /* GPO6 turn off RX amp power */ - - /* - GPO6 GPO5 GPO4 GPO3 GPO2 GPO1 - !RXAMP HP MIXBP TX AMPBP !TXAMP Mix mode Amp mode - 1 X 1 1 1 1 TX bypass Bypass - 1 X 1 1 0 0 TX bypass TX amplified - 1 1 0 1 1 1 TX high Bypass - 1 1 0 1 0 0 TX high TX amplified - 1 0 0 1 1 1 TX low Bypass - 1 0 0 1 0 0 TX low TX amplified - 1 X 1 0 1 1 RX bypass Bypass - 0 X 1 0 0 1 RX bypass RX amplified - 1 1 0 0 1 1 RX high Bypass - 0 1 0 0 0 1 RX high RX amplified - 1 0 0 0 1 1 RX low Bypass - 0 0 0 0 0 1 RX low RX amplified - */ - - /* - * Safe (initial) switch settings turn off both amplifiers and enable both amp - * bypass and mixer bypass. - */ - #define SWITCHCTRL_SAFE \ - (SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_TX | \ - SWITCHCTRL_MIX_BYPASS | SWITCHCTRL_HP | SWITCHCTRL_NO_RX_AMP_PWR) -#endif +/* + * RF switches on Jawbreaker are controlled by General Purpose Outputs (GPO) on + * the RFFC5072. + * + * On HackRF One, the same signals are controlled by GPIO on the LPC. + * SWITCHCTRL_NO_TX_AMP_PWR and SWITCHCTRL_NO_RX_AMP_PWR are not normally used + * on HackRF One as the amplifier power is instead controlled only by + * SWITCHCTRL_AMP_BYPASS. + * + * The rad1o also uses GPIO pins to control the different switches. The amplifiers + * are also connected to the LPC. + * + * On Praline, a subset of control signals is managed by GPIO pins on the LPC, while + * the remaining signals are generated through combinatorial logic in hardware. + */ +#define SWITCHCTRL_NO_TX_AMP_PWR (1 << 0) /* GPO1 turn off TX amp power */ +#define SWITCHCTRL_AMP_BYPASS (1 << 1) /* GPO2 bypass amp section */ +#define SWITCHCTRL_TX (1 << 2) /* GPO3 1 for TX mode, 0 for RX mode */ +#define SWITCHCTRL_MIX_BYPASS (1 << 3) /* GPO4 bypass RFFC5072 mixer section */ +#define SWITCHCTRL_HP (1 << 4) /* GPO5 1 for high-pass, 0 for low-pass */ +#define SWITCHCTRL_NO_RX_AMP_PWR (1 << 5) /* GPO6 turn off RX amp power */ /* - * Antenna port power on HackRF One (prior to r9) is controlled by GPO1 on the + * GPO6 GPO5 GPO4 GPO3 GPO2 GPO1 + * !RXAMP HP MIXBP TX AMPBP !TXAMP Mix mode Amp mode + * 1 X 1 1 1 1 TX bypass Bypass + * 1 X 1 1 0 0 TX bypass TX amplified + * 1 1 0 1 1 1 TX high Bypass + * 1 1 0 1 0 0 TX high TX amplified + * 1 0 0 1 1 1 TX low Bypass + * 1 0 0 1 0 0 TX low TX amplified + * 1 X 1 0 1 1 RX bypass Bypass + * 0 X 1 0 0 1 RX bypass RX amplified + * 1 1 0 0 1 1 RX high Bypass + * 0 1 0 0 0 1 RX high RX amplified + * 1 0 0 0 1 1 RX low Bypass + * 0 0 0 0 0 1 RX low RX amplified + */ + +/* + * Safe (initial) switch settings turn off both amplifiers and enable both amp + * bypass and mixer bypass. + */ +#define SWITCHCTRL_SAFE \ + (SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_TX | \ + SWITCHCTRL_MIX_BYPASS | SWITCHCTRL_HP | SWITCHCTRL_NO_RX_AMP_PWR) + +/* + * Antenna port power on HackRF One (except r9) is controlled by GPO1 on the * RFFC5072. This is the only thing we use RFFC5072 GPO for on HackRF One. * The value of SWITCHCTRL_NO_ANT_PWR does not correspond to the GPO1 bit in * the gpo register. @@ -313,7 +311,7 @@ static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) void rf_path_pin_setup(rf_path_t* const rf_path) { -#if !defined(JELLYBEAN) && !defined(JAWBREAKER) +#if !defined(JAWBREAKER) const platform_scu_t* scu = platform_scu(); #endif From e9b69b144c1f41dd8c4c1bc36f5ef26e153fdc04 Mon Sep 17 00:00:00 2001 From: mndza Date: Tue, 31 Mar 2026 12:49:15 +0200 Subject: [PATCH 063/238] gateware: add pstep register in RX extended precision --- firmware/fpga/build/praline_fpga.bin | Bin 201089 -> 200305 bytes firmware/fpga/top/ext_precision_rx.py | 5 +++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/firmware/fpga/build/praline_fpga.bin b/firmware/fpga/build/praline_fpga.bin index addeb7a744816abe13ed0a71924639a66113384b..90115bedb48a0a491a4476e667ab4ce0322b2ea1 100644 GIT binary patch delta 64790 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
  • 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 Rj8%be%3gi9AAjYC{|Bs;jEn#P delta 65580 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 w9p9TFVekZ+J@jel$NaVAvkN!c%Yeeg* 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%0DX?DcN4M_+GBP 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ð@t?B&DBE9 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 diff --git a/firmware/fpga/top/ext_precision_rx.py b/firmware/fpga/top/ext_precision_rx.py index 6f744c72..3284278a 100644 --- a/firmware/fpga/top/ext_precision_rx.py +++ b/firmware/fpga/top/ext_precision_rx.py @@ -88,9 +88,10 @@ class Top(Elaboratable): # Add control registers. ctrl = spi_regs.add_register(0x01, init=0) - rx_decim = Signal(3, init=2) + rx_decim = Signal(3, init=4) rx_decim_new = Signal(3) rx_decim_stb = Signal() + rx_decim_cic = Signal.like(rx_chain["cic"].factor) spi_regs.add_sfr(0x02, read=rx_decim, write_signal=rx_decim_new, write_strobe=rx_decim_stb) rx_pstep = spi_regs.add_register(0x03, init=0) @@ -104,13 +105,15 @@ class Top(Elaboratable): rx_chain["quarter_shift"].up .eq(rx_pstep[-1]), # RX decimation rate. - rx_chain["cic"].factor .eq(rx_decim), + rx_chain["cic"].factor .eq(rx_decim_cic), ] with m.If(rx_decim_stb): - with m.If(rx_decim_new < 2): - m.d.sync += rx_decim.eq(2) + with m.If(rx_decim_new < 4): + m.d.sync += rx_decim.eq(4) + m.d.sync += rx_decim_cic.eq(2) with m.Else(): m.d.sync += rx_decim.eq(rx_decim_new) + m.d.sync += rx_decim_cic.eq(rx_decim_new-2) return m diff --git a/firmware/fpga/top/ext_precision_tx.py b/firmware/fpga/top/ext_precision_tx.py index 08a3adf0..949a8ce5 100644 --- a/firmware/fpga/top/ext_precision_tx.py +++ b/firmware/fpga/top/ext_precision_tx.py @@ -90,9 +90,10 @@ class Top(Elaboratable): # Add control registers. ctrl = spi_regs.add_register(0x01, init=0) - tx_intrp = Signal(3, init=2) + tx_intrp = Signal(3, init=4) tx_intrp_new = Signal(3) tx_intrp_stb = Signal() + tx_intrp_cic = Signal.like(tx_chain["cic_interpolator"].factor) spi_regs.add_sfr(0x05, read=tx_intrp, write_signal=tx_intrp_new, write_strobe=tx_intrp_stb) m.d.comb += [ @@ -100,13 +101,15 @@ class Top(Elaboratable): mcu_intf.trigger_en .eq(ctrl[7]), ] # TX interpolation rate. - m.submodules.rx_decim_cdc = cdc.FFSynchronizer(tx_intrp, tx_chain["cic_interpolator"].factor, o_domain=dac_clk) + m.submodules.rx_decim_cdc = cdc.FFSynchronizer(tx_intrp_cic, tx_chain["cic_interpolator"].factor, o_domain=dac_clk) with m.If(tx_intrp_stb): - with m.If(tx_intrp_new < 2): - m.d.sync += tx_intrp.eq(2) + with m.If(tx_intrp_new < 4): + m.d.sync += tx_intrp.eq(4) + m.d.sync += tx_intrp_cic.eq(2) with m.Else(): m.d.sync += tx_intrp.eq(tx_intrp_new) + m.d.sync += tx_intrp_cic.eq(tx_intrp_new-2) return m From 68f9ee8b7996b57439b4c49edd19a01a207976d1 Mon Sep 17 00:00:00 2001 From: mndza Date: Wed, 21 Jan 2026 15:33:41 +0100 Subject: [PATCH 067/238] gateware: fix signal direction --- firmware/fpga/dsp/fir_mac16.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/fpga/dsp/fir_mac16.py b/firmware/fpga/dsp/fir_mac16.py index 84c59a89..81667f62 100644 --- a/firmware/fpga/dsp/fir_mac16.py +++ b/firmware/fpga/dsp/fir_mac16.py @@ -468,7 +468,7 @@ class iCE40Multiplier(wiring.Component): "a": In(signed(a_width)), "b": In(signed(b_width)), "valid_in": In(1), - "ready_in": In(1), + "ready_in": Out(1), "p": In(signed(p_width)), "p_load": In(1), "o": Out(signed(o_width)), From b2669ef2fd44e41bffcfdeea306f65b6c4a386a8 Mon Sep 17 00:00:00 2001 From: mndza Date: Fri, 27 Mar 2026 09:18:04 +0100 Subject: [PATCH 068/238] fix NCO phase symmetry --- firmware/fpga/dsp/nco.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/fpga/dsp/nco.py b/firmware/fpga/dsp/nco.py index e464399a..7419e011 100755 --- a/firmware/fpga/dsp/nco.py +++ b/firmware/fpga/dsp/nco.py @@ -54,7 +54,7 @@ class NCO(wiring.Component): addr_width = (self.output_width + 1) - 3 lut_depth = 1 << addr_width lut_scale = (1 << (self.output_width-1)) - 1 - lut_phases = [ i * pi / 4 / lut_depth for i in range(lut_depth) ] + lut_phases = [ (n * pi / 4 + .5) / lut_depth for n in range(lut_depth) ] lut_data = memory.MemoryData( shape=IQSample(self.output_width), depth=lut_depth, From 627c43b27913e0ac9911548fcd4b35c139aae511 Mon Sep 17 00:00:00 2001 From: mndza Date: Fri, 23 Jan 2026 15:44:15 +0100 Subject: [PATCH 069/238] gateware: add complex multiplier --- firmware/fpga/dsp/fir_mac16.py | 27 +++++++----- firmware/fpga/dsp/mixer.py | 80 ++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 firmware/fpga/dsp/mixer.py diff --git a/firmware/fpga/dsp/fir_mac16.py b/firmware/fpga/dsp/fir_mac16.py index 81667f62..57da9605 100644 --- a/firmware/fpga/dsp/fir_mac16.py +++ b/firmware/fpga/dsp/fir_mac16.py @@ -464,18 +464,23 @@ class SerialMAC16(wiring.Component): class iCE40Multiplier(wiring.Component): def __init__(self, a_width=16, b_width=16, p_width=32, o_width=32, always_ready=False): - super().__init__({ + signature = { "a": In(signed(a_width)), "b": In(signed(b_width)), "valid_in": In(1), "ready_in": Out(1), - "p": In(signed(p_width)), - "p_load": In(1), "o": Out(signed(o_width)), "valid_out": Out(1), "ready_out": In(1), - }) + } + if p_width > 0: + signature.update({ + "p": In(signed(p_width)), + "p_load": In(1), + }) + super().__init__(signature) self.always_ready = always_ready + self.p_width = p_width self.o_width = o_width def elaborate(self, platform): @@ -487,15 +492,17 @@ class iCE40Multiplier(wiring.Component): m.d.sync += pipe[i+1].eq(pipe[i]) return pipe - p_load_v = Signal() valid_v = Signal() m.d.comb += valid_v.eq(self.valid_in & self.ready_in) dsp_delay = 3 valid_pipe = pipe(valid_v, dsp_delay) - m.d.comb += p_load_v.eq(self.p_load & valid_v) - p_pipe = pipe(self.p, dsp_delay-1) - p_load_pipe = pipe(p_load_v, dsp_delay - 1) + + if self.p_width > 0: + p_load_v = Signal() + m.d.comb += p_load_v.eq(self.p_load & valid_v) + p_pipe = pipe(self.p, dsp_delay-1) + p_load_pipe = pipe(p_load_v, dsp_delay - 1) # skid buffer if not self.always_ready: @@ -529,10 +536,10 @@ class iCE40Multiplier(wiring.Component): # Inputs. mac.CLK .eq(ClockSignal("sync")), mac.CE .eq(1), - mac.C.as_signed().eq(Mux(p_load_pipe[2], p_pipe[2][16:], mac.O[16:])), + mac.C.as_signed().eq(Mux(p_load_pipe[2], p_pipe[2][16:], mac.O[16:]) if self.p_width > 0 else 0), mac.A.as_signed().eq(self.a), mac.B.as_signed().eq(self.b), - mac.D.as_signed().eq(Mux(p_load_pipe[2], p_pipe[2][:16], mac.O[:16])), + mac.D.as_signed().eq(Mux(p_load_pipe[2], p_pipe[2][:16], mac.O[:16]) if self.p_width > 0 else 0), mac.AHOLD .eq(~valid_pipe[0]), # 0: load mac.BHOLD .eq(~valid_pipe[0]), mac.CHOLD .eq(0), diff --git a/firmware/fpga/dsp/mixer.py b/firmware/fpga/dsp/mixer.py new file mode 100644 index 00000000..e5e599ae --- /dev/null +++ b/firmware/fpga/dsp/mixer.py @@ -0,0 +1,80 @@ +# +# This file is part of HackRF. +# +# Copyright (c) 2025 Great Scott Gadgets +# SPDX-License-Identifier: BSD-3-Clause + +from amaranth import Module +from amaranth.lib import wiring, stream +from amaranth.lib.wiring import In, Out + +from dsp.fir_mac16 import iCE40Multiplier +from dsp.round import convergent_round + +from util import IQSample + + +class ComplexMultiplier(wiring.Component): + + def __init__(self, a_shape, b_shape, c_shape, always_ready=False): + super().__init__({ + "a": In(stream.Signature(a_shape, always_ready=always_ready)), + "b": In(stream.Signature(b_shape, always_ready=always_ready)), + "c": Out(stream.Signature(c_shape, always_ready=always_ready)), + }) + self.always_ready = always_ready + + def elaborate(self, platform): + m = Module() + + A = self.a.p.i + B = self.a.p.q + C = self.b.p.i + D = self.b.p.q + + a_width = A.shape().width + b_width = B.shape().width + c_width = C.shape().width + d_width = D.shape().width + + o_shape = (A * C).shape() + o_width = o_shape.width + + m.submodules.dsp1 = dsp1 = iCE40Multiplier(a_width=a_width, b_width=c_width, p_width=0, o_width=o_width, always_ready=self.always_ready) + m.submodules.dsp2 = dsp2 = iCE40Multiplier(a_width=a_width, b_width=d_width, p_width=0, o_width=o_width, always_ready=self.always_ready) + m.submodules.dsp3 = dsp3 = iCE40Multiplier(a_width=b_width, b_width=d_width, p_width=0, o_width=o_width, always_ready=self.always_ready) + m.submodules.dsp4 = dsp4 = iCE40Multiplier(a_width=b_width, b_width=c_width, p_width=0, o_width=o_width, always_ready=self.always_ready) + + valid_in = self.a.valid & self.b.valid + m.d.comb += [ + dsp1.a.eq(A), + dsp1.b.eq(C), + dsp1.valid_in.eq(valid_in), + dsp2.a.eq(A), + dsp2.b.eq(D), + dsp2.valid_in.eq(valid_in), + dsp3.a.eq(B), + dsp3.b.eq(D), + dsp3.valid_in.eq(valid_in), + dsp4.a.eq(B), + dsp4.b.eq(C), + dsp4.valid_in.eq(valid_in), + ] + + ready_in = dsp1.ready_in + if not self.always_ready: + m.d.comb += self.a.ready.eq(ready_in) + m.d.comb += self.b.ready.eq(ready_in) + + with m.If(~self.c.valid | self.c.ready): + m.d.sync += self.c.valid.eq(dsp1.valid_out) + with m.If(dsp1.valid_out): + m.d.sync += self.c.p.i.eq(convergent_round(dsp1.o - dsp3.o, o_width - self.c.p.i.shape().width - 1)) + m.d.sync += self.c.p.q.eq(convergent_round(dsp2.o + dsp4.o, o_width - self.c.p.q.shape().width - 1)) + m.d.comb += dsp1.ready_out.eq(1) + m.d.comb += dsp2.ready_out.eq(1) + m.d.comb += dsp3.ready_out.eq(1) + m.d.comb += dsp4.ready_out.eq(1) + + return m + From 37ad28a03a78e633ebe4cb64246881b711e92bbd Mon Sep 17 00:00:00 2001 From: mndza Date: Fri, 23 Jan 2026 15:48:50 +0100 Subject: [PATCH 070/238] gateware: add configurable mixer to RX extended precision --- firmware/fpga/build/praline_fpga.bin | Bin 200273 -> 204769 bytes firmware/fpga/dsp/nco.py | 10 ++++-- firmware/fpga/top/ext_precision_rx.py | 44 ++++++++++++++++++-------- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/firmware/fpga/build/praline_fpga.bin b/firmware/fpga/build/praline_fpga.bin index b327ec0833617821f9e341fbd773c782fcebb524..a6b024858f10f08f84cbc6cffa578935c0ae469a 100644 GIT binary patch delta 129252 zcmX7Q3t&{$)%7~(K4&tS+?fm^ga~&+fB->mNPvJ5ZUQJO>hMr8rFMc;qqQYGs$i{i zCkcv*ItW!%)IsoVY7neeY`uV1^otTJR$HwdP(SeT)d}FEO7&mkj}ihibI)tbf{uXBy*pL$R3ns2IKSwHB~nb!?g=BSg94K*o|Vmv}-ZkOTdzoQRQ0O zCC4lEw+VzWIXqVsqvUBhWw?JPCK~@j%;*y(qft~M5Gf6rzzZ^!0~|p7m$Ou*I&7F+ zElPSYc8Q997or!#)mAYoFiQ@0cfky$pd~Tf+$F{jw`RkvC|@Vec5K*Zi%*3ofuhU4 z+}r?Y;b%GHB1|_tu|%or``}Fs-*=5r&utoaQkjBC<8vbV(Vb$vDgGqp%SXPP@8@&gm_a5RIdm=0^j$SJjL>VC68hC$4G45T& z+k2o^!>Yes{O&iaL&D|>Rd0aRzgR@PU9w$5gCj2&5w`*}hrgNUPK|~=L*(jY`5^lM zPeZ=Af1!DW7*S&G()+bxKqi!h@ZmaZ5DDA>cTY-%7^=*+RK%*a)AqsnRyw9x|A4H! zey;YFsIJMYGHId~m{qEbca;j|8qeaBNBM?S1inXDqSXcF-N*rh1L?Qsjy~< z!GR;v>gX1u?3y0vuM4j_n4l?nW~&$;yAZ-^(2$B%U#e8NJ(%M`%-SW#DxRZlsOGa| zZnEbMmy=b?T_uy23%em%i_wYRv8wA;8fuL)I)2qISz-P`v1m`HPZt;8uUQ-JlaAcy z#`wI=9dd(^qcLUBw+mWDdB+{bxHm7vM58h>8mVaLMF>Mi-N9E7J z6d(3hwKTCwsKv;BUd(z=-KKHAt~m3Nockh5?O$QyZASNtz!-Cy=t8$@Z&tsN zgG+Wv%oX~_n%E^HST`EDX-KYtEEC?l3stJY|m8 zI9963PKG|#j|JBTow<3~vBq4z4jsMeKN+<~9SL%?=Jy-_b?8hF!A148v9f$wlxUvJW(CtHV&m zqrg$*=BGmWAQ!a1-mgJI8I3O$kp!xxSK`6V=+MQ_p6@}laS!U0Wb7OzOvrS6h#j(PX*>;p@KwpD#V*G(lK zG!PBtX^M?kr0RX5#Y5a@Ur9D^Ex6mFcI^z<2fpLn`;>%ml@|XY&Eit#soawAK9uFJ zGW#CqTmSXDMs5?@bXCXK( z^mA-DTJH-dwdP3mf!DOFt!hA|_3IRUmy9}pS0?sC9i+pM@o@F^syQs+jC0f=mVfS} zCXkW0Yw4OI!a*Ylm9yMhcs*EQDz_-zjyN-%3|Z}(?YsY@BzzT~MKr1hyjmNohuOOulWKWj055W< z)Oz=QA0n`&=y)m^3B995*1jmq?LqnujgzsE#qzd4#Zb5UbhHb+D;9=NYfIQc*-;V7 zyFAz)*bFt8f14n?Aia??20t z;fhv~ExG^Nxp`Nrc(ql` zwr<>hU^JiJrYHy-J%}{?uW-h{{NTkR-kNg17PfExS~L`O5MG=POz45T*ZthDEC2wy zisWBat1*PpGhG_QZ#UaPGykU#D`R-)6NCM@9pJ>mTkhpmPmWLTlEO^bx zOI#bGiv#U+ajipS50oKgxf-gp^cvK~bAP%UwB>=KJWW6Z1t&#ALdiv+@ViPRe&%>n zP)8uS5XTJD8|_3?NSebOhRLFOVW-{31S0)9=Bx6%ev40v#YrSASbEWgsIc7fwEzN0 z%H;63bHXz*{fE?km?E!d4X+~fO;C@ia|%d+ZHxfP3h~!!;Q=qs@N|CA{}V=F-(=wn znA{+#N)O6*Jl!P!dkXidBQWEeDh#MLHe-eZ4aw6h$Mk|!}yXh|K0&V;;Q7$I8(*!z2xZ$yOax|y&L)M!`1oZ`^{Yl?2GcYHh8G$VED+c4S`cSml9^St<7%NF0WjN!qZ=cBazpqRby zjeqs0$R<~bh&3ISdkS_!Wa%y;?qbbaDASRi7|PoOf}=f{JScmhT0WA#=9=H5qd0wv$iA zTSYugOyN$adsXolx#g{VBr8smRrSnOim2D|2E07FAJk#F&73za|gjF#e zCk!hlQnVAe{WL%|!0%da;NuoSP7u+GgNQGm(<+6T&kFRNA!;&+;H%@mhsjJUm!$BU;lcI+dd*xRug7477>?MR=7% zJJ+SSm~m?^0kFteZ3*|wjlNd`^)#8qBWB0kW61iAhD@yO@3mk55=*+3CcxRIR5Ln> z$iA15@oPL9>GZw1v#@FLxR*eD+|>22`KpT zEU8XYM0-m6YodI`>v!ll_1D*WC?6-XNzvkw0c5T4QR!!0PI;Y?u9$l)_(#!P?~e6u z*FM^A;=+wh!b6Eds(iVkhSd$9EZx5k;&A8YmyuUHq-vtU4S-++gSM&8SuB&t=e9X` zo5=jWFRcWmkCYjA8;bfeqNd+vQbdTq9eItP!*slV2^_2rtl<>?*YK(oPTuIY(83p0 z?Q3hr++!gdH6hE5U=582dnIBUn;<*^ce8pCtbNl&uTh&6fPc!doN`d0UW;#cFA(!O zc-G!l6~9O+%b#*EHz~cP=nYCf`HaPl;Xd(OWhOoU>|aVHtR4%StD|HEierj?GkLsj2YIg)h7^Gc ztdiePCL&>}8Q!Nn&e=$VM ztM0t)vyQ8oN()@C+VV_+$4slFRa`3ixma<#Cc|pp(AI+96th-cRm}M7X0+}M1fEim z6EV+_wyM2qCK0j8zpPfVVK85e;7q-%Rgj3pEgX>1M62lS0D*l;Gd`UC;OSUivK!L2 zaME1i;#SyRfS=5hrMM#Ki|@-d07i0TGe56m+hb@SYVv3f!o50>F2Cajj?cLe;HUcS&328D+r^}El&cy;6rMBikYZ1LYedjVVpzMD zNStzGVt-k2jf<-TPW4G~v9L1JwQ}zkJ>smErG6NPPjl$+Y9%}m*8N4VnvvQ;`n+2w zhY%ba(wJiyLoYX?)`(!UyIFW2$$6>ao0wGvG^I_+4E3%J^`qBT&($7WBwi-lQp_cn z>{fBR_VZZT)N>+WDqH@tX%f0;_6O4m z=}hQD+N}#;C|tR=n@LjOo}Z;%lwGLw^0ew!r?@A2?Vp(|o4X`s1bLV0S~kLA)!NX5 zuT+s$?%y~a)y2UZulC5J)k+e4pP6RdI>tY3=fankx zZdkR8Hq)W537kM56hBckVN*AQUo#oF=2f4Yc2J%|nWuL&yNTyYo^4->y5TQB_;0PW zyIG@zQArBjo4iU$SGpTs$sWk+*8L3bCLWmU!#NOODuWeLdiqDzr1ZLOj1eq{2;lf*HWaDZ|^G@?zHG<(}rn(nEvqb#4 zS+5rjRMJe#d5Zjxzf|H3an)ifPnzgj!ahJEqI|$0qoaH%<}vHANUZY3`#`%y6Ny$K z10f2cMAA?#RbDb@D3V3=8NvS+bU1!BsJ{*H{Be_9N%B%%J&x!~G;bUVWf;RWnA>3H z{d_iH*XEXhqTs#}zSv45GYc|V3f!a-|e{SCdGTfhwu>GDaa!m#`USgvGECdV^6sgw`HHN z10IiBDL)1Lsf;iv6`cqia7IrM#oq- zbx9)=ifH$cL)q7{mjIK1NM9Rj6%E>)3tEXJ>T)f460VEda&egaelA{M5=2jM@Ds^o zHXjg$JoW6X%H*PptgW|RRh!*9pXlm%T~3Xd)TJd1c_OG05Hs+6`R@v@FHLC-rc6;_ zR(}vuATKm9Y3EC8xLpDX<7yF?XPhbz3gUtfFWkr!l8X}`3S3I#*qB#qiY!jac2%;N zPC4rt#-vJlsP_@arCy0AePXb;RhGso3zXMUmE`?`+22ePcU^cIqvBh#H`U(EBo+l5 ztf>*DnN@NiFgVPuapS5@RZ6D0(q_o4jNv^=1~53eOTJ|0i=S;5-0^O7URM}&wvrW+ z&;==z7%%fOkfXuqfx}Gsc!cDWe}vOys|yg-4q{N{E;*nPZiif-n!uMYYpkSGQ9o&H zzMh(_ig8cNSotr=V=Flmf=--gght^b;Bf>?9SK|ELMAm7%=*Dbyz)_=>DQ9xN10p- z@uY}|5-7a_C9q!nT+FZL(RimyW;J$=6<0AqDa(Y_IKo9pC3MY4@^Ph34XEGAnnM0G zAfjFOGag#mn4m}{wanE>s4ge=9xSqg$z=tZpo*$Ds;cC#cuM}e6rpbrmbXyYF;Wb7 z1D9e-FR3AXQly zR{d(de+}(Sh;M;|Nc=i2f0yXNsGq#qgV_jVlNX3Yv1dv1T3EsFWrIc3AXX_sN< zEAD##N+Cv30t~{rRX(bTkrUo-6_$BE23xbl>}0cNJ|t53x8{;ty>=M+Nb6i~BdU+q z@8{VL_V~p$T&o(E=B=h>dT~+O+=EVL)MQ02Lw-oW%Mvz3*UWuCA>d}FI93n_g$EvI zi79SJRa2k__KQwP46ba~q$aDf?j9vw{vn^9jpP=mG;$)mrX|nQGn5|P2tI+fsLo1(p`M7-CPl@34K)cmPVPThfT#6;mS154#2TlKYK9b~tqy0fOfMidM(=~gie zH200qbo8p@9iuefUV_BasWDz55Yj(;Mzo3zpTTb&^hCC`GW=PAS@oWk-<}{wU z9$vm%tuMFCBE{NznurgnaP+|p-@3r%{RCe-I2>h7QKg>{mVeQqJ&ckk{WbcMUMUfB zH^Cjq*E?UJEY_|K!sVuXK~ZjibNXuy_v*|822woVUt!F=z_oMxUEH?(C=>O96u|Vg zY><8{PXe%$L@)V+n5U!z{jyD+^h+h)i;R5=nh~Hj8e*{6;+G5D7pU6m-in?Kra0Wp zm(cs;L@lvg$*UAqDya_@L|PBmeoCG@Y?8VsHOG!$L2#i?2C+>PL?=7J;ZF6)-u0x2 z$`Y-aP@$#Nj4Itp1XNX9q1cD~RWq-bLDIPLD zAoABB?8tU)llk||1g^`ITTO0Vo%n9@^F03|?T=>W!cs>2nu=k2nRUb$C!{6c4`yQY z%sG50rTb?6axc9m7@M|BmNDE;{&M1`rP3(@>pyy?VQe2MQ9?<^W&O-fbzIO1LOv68 z?M&D_h=~uo)<3-%yYvitoX%^=9#b%-%1& zporBZF=xyOc*4%g;07w2s?_wQnu{+RvmQ<#Db2UwDrxUDXJ1Cgq90>-~yp z6Zm*u1pLmiaEh(|uY=8_s;|Q&QM1DKYM&=t_&N|NZq^c6IH&fV zfR%k4d(!(n)iU$MJhA_O@r|KGebb_K2ffREv)rQcF~d<`VqCRhh-HR4N&{J5au(UE zD^{=ZfnnkjoL{VrkhYvNM66iN<3FssuZXhNlp$k5Lzdq9kuc-ZX_(OWmZ;0_++s?% zpznSk!tG{Rf0Htzvi*N$%}(dM04mLRv&gE0JdffWnp@U)HQgfiOzmf!6xVU->zp2> zZL(3}rMv#8IGTK-c)nmbb5%pFG+U(AU)>%smSIQr(%L@eKWcx;gsc9h<7dG^`3b=l zUNlYQ3>6cNLyfr!&dC7!gNchhI?e+{nXu)$Oz%3HX9_DE3~#+C-9gU@sp68=7_1U( zlza7+Nj=LwzkPPd?r`^qWUHteYuzNOWcmt-2Lf@g+K?Mf&$H6BKUvJGc&CVFvMTn; ziBJ~3613}`bwM>)Bv}F4qz+P#7U5R0L%5U-V52IW# ztMX62ZovPMeAC}al=zC&|GzFKTxwjxb%#Aikji4z_vM(C;1-MqCB>}WOs!UmLwt(x zqI2^XGJLy!oaAmF4g3GoZ_%=l53NLA_aycA$+aak`iUa&SUU-h@}gORtqkg%h6>8X zc#|H@9Y?t&dEMEAS%p-(2gics$jmwD_RYjEhcWsMn2#IX8=LMy)jd=P-V&mN+eQCx zuJ_2?j!EV4ozFM$S)!0*4QF!!*+$%17#YHYl_b?i4IIgeoVoN zsjU#kW4H-^h9rwVqVJ`enMFoQ6QS#hJ`#5cF5B`xMJX3I(ZsNnIH5N&n%4mzRv!@k zIna_g_wdz7ohYReTp-?|GcbmcU^&mGrkOK1^O-LeDm(@jmSz_+Vw7mLY}UqK4I+#Un%d zdSZz4H*UPnDFMT%gL!iRL0! zc1qArS))bc9JVqzNE9t)xs3ed4Uw5Vc1{aVruY9AAfl8**(IxL+!x@eVt?Vx4Y`@U z0IBu#sT%J|d{eLr#(QX=aBf2QWc|z`MAqSn3s#cT(0jm=vws6#2`ei(@22Z&`_Q~t z98+X4F8)vcnVT;Y3q{awoFLeGqTDeNm)J8??02L{Q@RW4b{rjfD* zU!3oTJ6^5-9O_#VKTyC@%OTuCpAFotF4j+gSIkroV=GyzDOcZxzd5tbk&?&ElFABo zw3MuX%}04n5ALvSFjKb>?m>rO*#fe>Rg|gx_>*vhz90-_INHzK`FK?v znJotW^`xkBGdD0v1y&ER(BVy`FaXi9jR2u;-P;siwGy>+bGszjnv=Q~^Np`UzPpZ< zZFl<*a&Z6iik*MqulU-WMfysHHST4l91qn$Pc zNfuHne^AwoMykTX3E@fXZ`Y2g;=}C)HBtHVuvOBd!ZtS-+^f@{5ZCNnZR#C~soX8m zd;P5*a|dPaL$D`_s67sCHm&zG=T*&l-w(D^^IjhhSvETc6Q%7th~ zpB=V)uy7&*nc7wCc>q&!OR@LXevetS#m08cClX9?S z`nw#)3m<>ByA4@YsoyUn!qYADZtNW7tAlgoVa%2PC?hmb0ElQ?N}UMMeM0$YY%%svOyvopFjR+{gq0hCyo3H2ahYS=ueB&KqHGS>eZ@9VQtR7@vp%th~@{&*0S7BB3U|h^*0nti{ zw{-lQZ7<&SJTFx$bMK^e=e5a}+^yO>okw*VTfbFo1&>SHi%oRDwZ2lw&ue@h7_L!q zx%QP_Q*KeB@G_^rMACv&UQW>VZkrm676ey}q4J^Okx%r5a@hy(#jX+8&;%JU+-Mv7@FTJa(&=F<_ziro!^Be+195wMs_H{zDI~LPhBmK*aNaLq;7;R~= z^ZB`;O*W;lKsGeMZr9@Xb`h3O?vgXTd&}$N3f@u9)=pdJ8M2wxW$Q*WdzDCYmF1$F zrSER`>JSjNShva@HD{LGktHL&vqlV4AIma(qBka?exy+&aoL5^dm-E?`knU~r zxID#NYtdLM0+@1ZO6~}}{h3PZHW=KN2Cw#2o2?b@MM|JuJ5ll|K(%eHl`$%S-P1o6q6ZIrZxj5P!Np#>`vdkou_^ z=nvv)9bZW2@LKH;!L7lfdLqS^s+6DqEI4AE)1`cE+UD0|PSS*BXUJ!(%*D<6&a(#EB7`gV1LFO2b zyg6?6E?A1NN$#x-jbKbx?Q417e;GVjqRHQ7adAvN`ZqOsJmSC4v2B#vs{ z0fjJe-ltZVNX{oDxn2blqr=l0Gk3w^fM<$^j%Ib0xIFFs`8q2xFF17HpOBDigTeY; zvZKD$HW~9t_=D6O|C;-59c{E_Z-|`0I3`LPrr?~rc831K0n4P7`8hK0rY?X)Wb5_= zI|GjKTJ~##fu`P6yx`A#kl%y8)hv#9(A?DB z)9`VidYs%T<6fE+rAsM(f*V@dtKGc1H!^=LUX(z^f)4>@r*WBUNI}F0g zmX~by0ZFA^kjymyGtPHrcI-RYJcfFz^el|o3@P?8xu87-Qo)_~;qmLn_gQ>f@pJiB z;Z=EyP(i(|7}4;dA~ort*}PHhz<(X?2WN<+>wL0!Ybq03mY5nUvX z45wnxcW80!Mb-r5O&5tVF0!`r&*3ziiwC${6teH^L8@5`fB)ETv7qgG(rq?DITRx< zMcZQ;?z43bqF%RLkl*&i7I%q~B{8A=G{O&k){SFgxI9j0Yr1M2&yLm8nLm{yZ!EC7 zKp;way~x&?pKvviP8BNS#v!$!DNf$Ch#AevXpJQ*Uh!G~rDfA~NQJmRrZjFSs3+85 zRWjlMvxA)ooM_A9S2GY=c;Ygy0oB&iX!FL+f|(qrrt#0^CrN40TPT2or-oeYst~6{ za_WNYfn~uJtQm<>@EN{X6aoQSxRo_nINCgx8sxGu;tr7rkCI<(4Is_NE{}5}Z#k#J zu?yxC&Et_C91kX$qcC^HH#1%W8puqzdU0>AkEPGJ_dq8@aSGso-hL7txMGN?s0I@Qz=o`&N)mKpe^* z_)?AE&!9Z%p6T8~9y$rhZs$hYL{BhF$S(eR9jzty%YXJU(C@&A7=r)8r7G_G@*6Y@ zdjwfZBEhMQ+a-T$b+v4w{G3;qf2h=Kx%0}cFd7T`%S3snYK=qXb7K;T8xhS6ur}gK z4`%i28X}k7##B`(H!Fi|ZDL!xFuxXJz&J;|r*yca=a_b!hd#kK|0^bo9h>jeGF+F+ zOcdTZ(uvmNGPxnx$1^p*mX9VdY8@GzT^Vgtjt63PGy8vCSm|zJP8mw>v52)5(dXU= zDs*(>!BN_tLN<8uRt#nzk$fq>neHsOZ$9~>wAfaaWS~6*>pv0B{j&Z8Wmom}L|T}= zk96ZKJ@V{NU?1)rjZ*t3dM^VG(*+h7V7>;0_RbASNtUMA`A9N#Mg9I7G#b^-+Ri2S z6$l3VBbU$rsXRWo$Rh~}VwCoysPHcJ0-B*t-Ai~in9hX4t6cqgeGhO6Q9$)Qxz~Hr zm$Xz zi5b2MxV3#<+Czl`qhF~|o-t%^$t|sgp1>Hx|0}{_P4x@0ar_6&xy@iJTh$z^h7Iu! z<(kp7VWZ8X|DLQoS99i{mUvr?I$BRF{!gw=vBgXZ|5j>9Ab9-W*e0*?h!H!oA9jaT zckMubt)@<#>8&4J=)r7mxZF-tgBaBiV#B9EE4Nu4Sx_+;y@?#>YW5!WG+`|o zq(|L(rd7ULp`DynU%{vjF&dF!uPToYeeMc6jIFNz@>SEB;E3<^iJzx@_EOMGCO2ZG zGCyq}E8%<<#jXhj_I6Z^AC0d$G5^c%=!arheK~?aD)$zzC z)o!tw_Ld;p6(}T_&Ohuq6iv=5@PE0f2Y-)MP^ep5K5<6^9y_+13sss_tw_GVmq9(# zro3dH;nJf#G-_S`d4WW~_N_N!H00eflBj2j`q@6Nwj3|UxTOSx=9-dqt>o>Zodu13 z+Yb!VBkr&Cnc?S>i7mQ2#`I8x?8x@|94Od99M>{~Z?l-(+;rp5d*q~5s}ntFDNi|g ziiyaUy+384N;{ru|lvBB^Xi1Mtbrs-@CJ-!Gy)bg(FD#n9 z`n)ggLiUv#8%iAujNbb`F~~EEjtgSLjBlsY<=(t+3I0|ndS+qSAYAtO?n1@-_*uod zZp@BKIR9+7!k9F(WPX3pHFzis3|sr8SsP$JK!To)q3M}C`O46;Y|AAQt2FP~T1Kg1 z;?>dkMitL3S;QwBsu@d(!ZDp?>XjxQ3-)F`i{*+IkBZ_AuyTl-{kcl~ zo|iAFMRt)&-*SV0yT?7bA23sM@ z+Rw)Cy%QokN9f&A!bZ)jKjPoTuV1+dNJ1@-rJ>!t=!#{=V6~qjf$G?vdv3_`&(W%t z6Q0K-Q@ZVxWRALOOylStqyIw9-pu9&Q4 zTRf@`x))Y>^+8O5)vkmvmvma$MCHq}Meq!gOGd=HU!HaMaJ{8A53NRL+M5OX9iLHe zOgpO~^VWi9FD}~^th?nlZyW#lZECVcH~Zf+=j?&&qNH=v9&J_VX4ZLyco=LgYKCaY zFU7VkK2&5(qH`6x7S(CA2Euz$gdGieF|r#O!t};o4i!^69&dq_dl+&rs9(G0&?c@a zuNS1hSt8THC&B=KsW1nB9L&#MHOEaQ+`>P&SXAb5T1#19ftybMc@f`x`7kq9D1@H& z3V9FI*Z5YR7&9PRi*VTwDVMC`?DXPFPJu7k{EChYKAY8|@Z;GQAl>c>=wd0mdsviu z$a5`>J^u*2ITU<4_#T;hO3Pw6a!iI)&FkP(te9PX1B)4CtDLaZ!AhCoq2lNq_9~SK zRq+avV}@U8XRcL{p7#iM@)r=QyBd*%j>7i41U&{#E|pzbC6tBO9}3@OmoWk#xm76~ z;$04ScZ_FT7gDK8IxQByZfQPfMOC87}7pwQr)aN z@h$FkmlT?Gr9ixS>up%|0hKle^lA*+cPboHdKZ%QJ_lTnwnE(k9YuxwZMpIlxDGbj zrzU36z{2!~$7<4ukr`EaF;>*cHf*uzM|m}{(zhSXv07rvEQUSsihmC?k}d}uNqX_x zaC01o=mfT^yt9=aiZZS~Zj<}v1$oGNHreuR2NmBugDAB;ZVeQXFW&$;j*yPF>eM@V zX(w{1Llc|6;!b`jMoN#yGol7&0QnM1*Fo9@(+SSjCp2|U?-HZSpB?OBy@y{3@03K@ z9jX!T__J_Wn;a*$Zp{_$m(ko4--|-Aw@|oneKC_<|Cn;4wYzY!E#?;WF^rfcsV`2@ zKgdwLbUWOmq@@_)O=XMCRLP#UQF$&dO6?;ScpmnZhqjA4Yf5(*RbA7|c^~u^$rEtG z2pt5E9s!2l%8M{lXChFL0LTy{y%X47;NlH7&N(Z0d9TWNN#9_UHl7Dh zrG>7%7HA&V?UBhcg5eTb97$!upex-J}T#T`^dp|svO{uEbEcZjXQ5bC^ z;Sv`_K#mk?Ubii`Ida~O@UHK8IKlAh{kXa&z){`EIbyJTkzkjyXhB(uGV16hZmWn? z?~=SdgsJW(m2nnB@i$hoRkjG8_A?)qG>OtE&BDtez$3L=MH35CyH$~fLU)T9=;!WP zAR}MiZgstI0^*1=gxF`7SnHMfyjbF!Y)9s3D%)^=0a0Jj48BrR+h|sVh)rFS6}3Ek z*DJnYa$KdBZ9vq0PR+o@9#v5Xd*`qnlX5gLpWHewgj%`!<(j@5G%W3qUGUXtJwcQw2A&Rh34?}kG}gb1))*e z7{ed0jru&>u5Ea?mXz|K?j?>>(N z>Lv%k#nW(QgDARDAT zU@ffC>cbWZf>C|vis_U+#+8L}>>HP6NgVXYvGQ(CrEEaVZ2 z!O2o%o+<8pY|$j>V}GpYFrf>GYP-E&k(H*HipU6099O;I@zxfYF?s%FU={Mc@pjc> z%u!(5Xa(w|;Vym}kwB~pX2I+*nsfW10cZrd9nGbks(4kg)H`XCEx-8&WZx)soV|Fl@OSx@EG=HNpm@-bZrd%{jjLET_m#e_0$`597ODk`5vSier zzGKnvv0!LDYtz5trC9Hf{%T>_Q?&O@Hvecp5oai8?CpPp{Q)&IKH}w@`=+Q5D9vW^ z%9<`Qa;NjISz5h=?4So{B<217E?MdtEGwso>1m?YoIx#vzHJcaDABU9roP;;^m;L* z(J}E~QJqnLQ8>QRvA;pXsJ*@KXqiG|)lkxy#^pttBclE$Ii%^;LiOSD8mPV?oMf$w zZfl&IgO_CYk2Z^lVd$~Mzl!KoX@M%S;Sh5-t3#yLEMz`C8nMysXh_x*W)_ss!wBb3 z+AJ4|;M-8bn)txry#OXwws*I*UibrM-J%Y1uQjTLSrnMO-nV{Rlx$@d4vKTL${S%d zYnIxq)f?T`x!OP=;9X;vGgz)>x;R#n+&9xLb7Jdgh+hR#ll7%Usd-3bpLI?ZR<9J1 zqAze}^=Q8^(NfWDm3+48b8Q|Ox#f-qmIsV3ZStrV=ArX6cIxHIg$?g}=}li``!Ldn zniZ>PY)G_)M%d;64%x33?k*+@RT0;frHE+fU^0!17h)vx+0;1aGa2{$&k^Z6THO$; zUF)Ub*qqDaNV`VvsgUeQ@1)u=(>D*`ti23I%q*jGa~*=MJ~%&s9%)^29^xh57}Y#a z_PRBnaA&myb?ZHna={-0rQT>Ucz>&C?x1S3Neu4a5ww~vL~YGC$JqZNaM|ZRFy1>9 zRDY*TQGCv<&cJ-We+(14uM`-ft&abgQdR7sE8mn?m$ftLmGXMXHMqu}17Tl9 zbbr%Cp+9Vv?uUF8!SEnEr&<2vh{i4tS3R<-43YN-!OqBwd6(S(;V*_YcDGDj&_XGM zoW-rI2<0x~9TtAONNnp?%+i=NM!1=~mA%FH?52aUJC8|CTKw8Gg*z;mxJ(BN>*;0G zH?}$K_4oUJ!T412T+5;m zwpv5zM`a!R>(k?TTadYWO`)Hin3cr)+z)XP>}f1VE$O|NhKyUVH8Jqpxzyicvh(C` zu^~g#gj!>(!_Yovv$P8B4$X?!8hWkp-7a6yU#cmapz+81S9V}?!lV2;vT)osFNP)1 zd&DjfFZMW{KEE3EpPZSbB=rgLndNeq-3$UBlH)WMaV3o)J@zibhLqUKgw15~MY9T) z_75R-c1;S<_#y3%z!^CA=#C8hz?uqz>crT(oLzDG?7EZO-f022xa_Qba-y%!8mR$4-a+h0q5zFSE&&YU%wM1YC5}{mWJ9@Cgf|uTY z06r6!fcTA|N(4PiBJ_y!E#wNBSHd*H1nWnxX|w+sWEyQFfX_uxVVsdH*S%i00Ff*f)cFFsj}?TUZ=zw&MM;zZA_u89IEo6nC)tWE8}G==alX z6>}ITTrriS&v10MdWH6$EgW8SUyjMQUYm)*PEFyJd&hslA1bPp`V|6WMWk*hrWh{~ zXa1(KY@b7%^1O5*sMFpmBg2+}BWLFgy*6}|<5Zt@2OX9I4Ef|F^jCaLyJ_Y9@EBz1GJejnoJ-d%^aI~|bN;ABBsqb%Oe zu;s#iMyd1R4w3UJr{w#sUn?zk@%n2ItJW0+ss#JXYUz{fbJ%hprFGCmKWU@+pz0jR zKOj8Z0F4bEQoZ8 zh3qumk=XXk=UGS}FZiS=D|J-W6i-*>0l7gw>C+KE?Ebt>iLPiBsbVrrfm1Gvf%hwp zQOG<(+YR!gcPGJm3TqoMTSX~bP~1YJ-6Ha4@=v|0vU)2;g-M&$^H7>6A){5@B6o^= zl?N}rf@U$mP+B~?RSog__m+4AwOy2o86dM&kwy>P>nf4_mkPILH1bvbTv6fwCJQETfSv!Lc zZReIXW+XF08DQ;@HAC*LxtHuW%)S&7>o-biKoYy~2q!g%CUC&zd|xFmn3(SM*5nTY42! zSYxB4>4{m)wJy?Ufoa@{f|3%DbNn`M74WR#Tn$AHytjFV-Ao|7*)o|MrY^m6+IwqRs#o%6USBi|Pll zZ@*92x!qr2N(=gVjqgJ-Q3qT5+m@Z~5{#NLyC`kV*r!LrI^t!#kK7_&u@6iNq*(fY znh2hEX|Ce#I9rLxG_&6uQU7O{blk^2bJ8<~T(~rIof+|uKw+zZwca3_j$n=H&Sd2; zFzIurIwSS4`f-{=-SGQS+=JUbsIdkMF(DYA{L87DYpt_ie@9rMt6>*yDX@lHA;N03 ze|`$}OsskY&J_=p9JW0+*(wL^*GyjFml$a2Wamn;b$sO{Rk=Dakv!u)DP|NX7`g7! zrM$P|Xjc`9FVr(p`IAR?$|X#T!Zv$dqq&dpvi^7iiWZE9`Yn-ECRzK;23(-KJN?o* zl9xzl->4k5Q&nhdpmHGGU9y?pM^0sRD9V(-_cCfHjr5bei9H}A(T@;m?G*88FPBM- z!a}oRph@Sc6rBkiJ;94yNO*{0N9?~frEr`s8Z3+3)k&%91q85D~< zt~{J%H%aaYeaYLRC!5RIR+>^D#?!JrK;$%`q!OEDo~kN!zfG*vF2#DE*Lg6FrC~I< zY!+$S=56M0OcIM+bC$&F>aFu%`Nh;-9?}V}sQR8zJw|ZAEf6~Lh@$}@voq*`N zHQWAE%ga9-jC?@f`=qbHyQ$=3FBEhOLRNy(K7KUHQAM;UOApV2~{-_P*zaF-pk-Du=@GkaF2KYl;uKSWZEw)MiP@6?KBNn8j zWAQ@uSr5%TC@;hg<+8mmu=9V+kPaxtc5z>iu#}GjZ83MGCNg_8tFD04LyM!WZzxva znxe>UJvav|^8O{#5-f6AR`Ib-OU>oHD#0#}^xHzaP1X4GKjzyk=`x)eCH)?p+kZUY zw8HdW@Yh*mZaLZXGvm>#cs+xddWhO2E`74j1}bK&wrE;Up%}uuU$MIy|7+Hi{_;H) zztXrqJYjS=&EzXC?=eP5G8(r5SZ91?p%9yP`s5${2f^ROdkSIp>XO=B z1+vZ78p{P4p~;qQp0l03vv94Qyi|aZ->eF~I`aRKbS2bN|{tZnm{w@xp;sBzt$)|81L=T)@;&J;n z;OVf7crIP~TU%2t(H|gt{0-ZQ*>r0QlUZ(hJIG8?GwN;CxffegAEMWuzJ)rUW)|0N-3T`(tql9HdsiEB)w2Y{j-<_3pbc}cardJ_h7-wCq)w_=&=7W zV2Z-x8I;-8yPI`4*V7oCM&8S~?~k~%Oa(lfX_q86#%AdeEHC32vIlUZpHBF^wzt>lFC>fqu?dSC zp{9;`;+U3)5>Tqau2-8v0%B;%`7Q*9K!m`Qq?B2fm~AwXeBD6PK)@* zVj)bQC++gS{G5q)H{_ZRSy)ZYkO9HYY)!A=N;gUPk8FmoyOpNU$lsGbMd-sF-%MPV zr%D^Ke5w501_*QB%qMDkl7Xt*UDQi-jUfIM?UJpXQ4&^CTrrARpSd>TP0W1{UFE_* zZY6AcYUscn#{EHx3>R3L8-X!#WCbu095o?@ZWE@38kiMynFlXpWNM!9=pjO~$>=EJU5cv3=HAn`ewUgQ&$DrMTIVt4a9-mHN>AzMZeOh@k%mL2#7tnO6Q-k>EB zs`$mNZ1ncMd*7AhOgSsihoqpGmp(6}ZcT?>&qGd_Y|xFW`=kGSD9TwbPn_k6tCV71 zb6zfH<`$Vb6%#7EDr#k)P-#Z=?rs96eW(@Tim*uD4%rkN8~JF7^u4kRv^@K*Oq50G zfMJoedC7){0Nfb}`<_gHQ*5tbBcSiOf{Jyvh!maL9%f3dy~|6C zzUF#qfC@f6h{hY->~2w38}FZ|d6k~;TJK8w7E$&H^>Amkn)9A1xK~t9lI}I$WxB!N z6rSsALOgl;!Cu=QJl2cp@SWWn1KZVwQTA ztuFfLR^k@5h3<2YY?da$(bN7IJLIF@y~W<#R7Y1>7g(QA4?vG>i~YnC(ZdZ6w@lD( zBN}d-swtC*ZCSAn_|M-Sp_00&IYwa3?78eEmW7;;F72JOg)J)=e+gtngYT*|x&CF{ zde&cgzurB`2iyUlL_45ln5q4MY@!oC{xzfb{l}qtoATJkyZNtdw6`2jY#zNmf&Dw@ zx^6eBew0|~-6EHGaAs&H*PX^I{y8mBD!>U{qgUW^-OoM7+cGF~o`v)^ zUG2ydilo+?M1Na8)2H0phsO24{sD-`2|>uf#lnBS6VY5H|M$|{<#+v*j&hNdmU;Sr zy+5$$>Im)Qra90;dU%Al^SHD+n<4JVPHywR&4Bf@COZVi)Eqh9<|@8IP=b%+kNuu< zk}%=vt^#>7+E8YdGzr$+px<7ig1|KA+Bfm%^D~&7P0OFUR5&J^|K(<6*t|Ay~C1s8Q7y@@jFrO3=nw4qv7rG1p-{vp=`$>%SZ3-aF>W( z1X`E2iC8x_y#@&793ke7RAaPyCVECVU+ORISh`?t8 zK-Tr?O~fzLG+)^%M5~-|*>0aY1v?^IUVihf%jtV2T)`A@)`81>6zONpLi7dPk`o?t zz)~od-e=@emf0P8ImC)=^$ier{N>dfrHzOt%k7sN&c#_wgHdS8?-<6*SN5%)idBBz z0*_>5uC0tw3D}(9>|(eH(vv~OBJ_M3sNjc>OkCF6zKT_e;fXp42Tr@UfC}sN;j-8G z$vv16s{s8(@YzOeF0K4&km)_CRyU^Vc$GFwoj(I_8;_!+7LpWCF zt@U7k8`sXc-VtI~Gg3JH6(Y;FdeV@w+hNYcdF({&=q3n&x`lKd^DsiFRp^07tRQgL z%or8~1;(II+d%vcU>uzv+IF!ahd1HjY0i?48ROiF%TbJ?*@5Ny9jWPvA7t!onnrDP z-^=SD>89LTd5QZ=!TNC$U`IyC4VZyQlKTC((iHs1cF_|gJcN5>X!Q=V_o!=;ZGhrL z^biB|OZOZJ4{fvkA|QAz4XZNKyXZZusS2VHT?z#S{(Tp{D$o98y-5|c^$s*LJdbKQ zFUBVSR-&fTeHfWqHi&Dhr_(q#f5XFj__J^n9o)Ap4Ez@@0X7>ubd+P@iJ_LK0a{R;KI5#!W1y**I0v!df%@pUkpmeD)XkF8IEk)#iH z+_y7F3i5RiJ497bDgg6~ZoXxQK4mMTM=)2m@+V~Z75MC4;>kNv_C}o^tJ1<$VG6^g zT`m1(-o_l5>!o~iV8@3}Q@0;PTL{~mZHP4@Eck?%f3poEYhv+>jktw!V2cx1GgrB_G@DgO&=IcyWO1l$166YsuUX(fc>=HTj=#gI!=BN0S=wSirP>VZM4i7RiJ# z$7Tx(%8pNS{grkYnQz5T$|yh(2mxqiR@%%I(V$k3s2Yp7$8Q!Y1xd?O_-cJ%V;Lkq zk~fHDkH1a8QgkAZ*mK&VNFam_KAE2f;g3ZTpoJ}HjZS`0&}gX?H_AvmD9e3l3pY75 ziHPLN2~vr^Aa9VfDb8`T>%m`VK=$D>B5usA$ZZmpQIPC1mc_26*_xyuA$Eh4lcs41 zis%p)8;k&J)ceqo=`TkRSP&kHt)U!oxC8IPSVwDGxw_kT}v$@ z|1-v50tF4FkBcFx36xkzoMe7+25P1`nkyqkX}!2QOeetfOI(>L1}9m4$;hp6DCZ_v zNo8o8!~c@<=%EJW!+b8**?|vN<7FVw+F~yS&CCX(yLeO*#W;M-?zCP=0&|yRPEo)a zp+>l(NJ+rcm1SjY#2lKBg@b@g#m6M@d0@#jF+!)wYztHz-bJqwlSPa1Xy*2$)7=Ka zNiblt2&G*|TWxg!#)TJ$*pDp<+u9(WwRsn1SEcHL2fPJwc96$oT;^?>5=g3fR}UT}W60$(3{S02@nG`NBXYn9&iSIjshE z>DbE@@`3z7<^|C@FJ*PEC$pF~+dk6QT-!;*f-?u_$Yvs5R-zA7^tHx1GSF}HS7Ams zt%mqv^=>DR5oQy;7!kM%^i}vfRL538DGK{@U)FNuq(@#1R3Cu-eOfS*t;TuE@%|AF z2v}4g;W78(uVr3{zRe@WMTgX4LMZb`_i{K_{jPK(y)C}zgMP$ z+M=2~7lf*MuYcRI7~1$Sc%yKoMROLaCvB8bY?0>Kq+~pU#18D1&z~AWB_UtOU&NxG z##3sqG|yJBKa&}#1E>Ls^-X0T(%bYrx|{EJ0=Uvr>T?(LQCi5@az;;LZ^qYFaQw}& zg?m%64^7Lm&?#iMQy`H<5@)`_3)v4ch^^dP!65Xrnk}G(C=37DZ$VeN*YQ#?2|L}I zu+x1VZ;>MRx=S7v%6?{g;fZ_j=!*TQfU?fo2g%c)^aK0^>9MMwXyfI?0MJThXWTvF zo2hDllY_&_vM4U7AAqgE=Iko5i?zi|4athK-6S~OYo zMqHxMSIp(z#EV>al6#oz!nzi0u>7B*UPN)^>Id*L%}L-?769<7xK2z9r~p7Su)6Ig z3nTwLR%x;*ddc4*AaIr6S}vmV%+=^Bsk&yK3E)t}Z^=o+EfMSnO7z9P7~4jDjIV^~ z`b}$S;6v|IPtDjTP7+L!w8Lt^x|YTrK=|sUcn#bf9Y!01@5F1O-cSL*KHVrCIDrS7 z)(MM|WPdNmp*E)KoYq!8AWqfERc4(Or_I5_K=KWDSF3@7-i|6s7m&?k2#-!iAN2xn zmNth6G7gGb$9`E$m+*P|0rJ{(QXCd+Wcx&GIYT35_8a?T3f`zj3+vuCZ<2~ER-guj zw+t*GO7&YupJpuHqRiFBGi6rQE|f*gxn-G-$fH{@-)1^t-}({Ou5BHgzX7qn>`C?L zH6kt6L>*j}`L#S$Jphd|JwfdA8brUH6dQr1L{Lv6T*4MV_3OUdG~uQD;jI)kwcf87 zxviDglE1E=RS!_hAVKrvSXnw`E`zBPtdT4$gp{hOnJqlZekvs$rGv_1&}is6-s#Sc z9QNXQP|(BH^{hLrnt3F;AVt^Xf&4KmQY}JHHf=QzD<}%{@7*u8RhgJq5L1L6&Ym^+ zGeC#RV9JovzK-`!X&y?)bG%R&uXs$|M`aUq6j3EpyK^I&@n|?$2YBCAqA$;-W zE}#fPeD{QtMPcD*o5I~YR6U30wNUPUuRV?C3@of z-2tX3lGF)?^%R_vo|Kh2kVPr7DiU(fVdXmU8`w2$f6Jfi*&^agel|1KUC%Ah ziOqi$@i!x*8T|qFRO(*Gt%bi+RZgp$T(_+=0nwKsUzyQ0VtbjDK~ul@@{a-d>CbBS z`E1ACP&=?%&$1GwMHlm4vZ4zhT^IEG*!74PPIf%A2Mhs56$WQmn2m9R+_8NzVBT#GL;$vCQDk_lFdHK zR!o>OINBCj+qzPf8Q9Ynq^f=`1e5zJB!-c0Rti6V{xnrscuUj()@SVD^n0eyZaPgy z!P<%qaNsITohXR@s}B+;q;=5_xNybvHc&R?L*-$4d8&rG=1)T`IccS43n`UyYVg%^ zM+vEkmtc;CIqj&v*Yozk8~qD^d9d|l%rf0?^7>yE30?FTXv1-Q3B&A$?RUaoQrqkX z*$aV0KO+o3Kn1>kvUu3OwU&N_HjYW(MtI4fS5sF(_i58;o3yi$xZf;DV$l|B)#`;A z7LqCv^yHnSKfP!=Exd%ii$~0)El-~!)64tXQ*|G014<$O?=ya{(8zidEa#*a>ykXL z4{OFw1ut1=N^JFsW=!Mot#RQBOu35uCf|Gu68hC+|ENW-2-TrgrV#zgL}K>+d>of- zv!2Dg+8A4Nj|OGWXk((dQrPxX7Ou%Gn_-!c(tBwxI@u(DcnQGVH6!yBejuqpLdR?A;~J|#8?!ThEc3g#s%k%Lvd z1xlRyF!nVoD((mTwC!WsZ9+2uduO)wKUB|zU-%D*npRfV;Vc7;95B;F->F}VRIu4_ zN@4Q*-uEf6RGxrJ4OV>|wKKA0VGEKsa9^D2kv7>Q}7e)F|BF%uMMebYZei$wT|zhZPNOjGss`YksbP@+)6=g}-mo$Qs0O z>5}wKf{mi>&6bldj%tvP1`BzazoT2g3@zJ7h=G?Og|r>@y1uGL?D=ujVMDMzclR~X zdcv)C%qtOFd{=wor*`iG3yvVEBHkUP88;VM1!@E!hD^Tq>YOhf$R zQ!pt`rZ>2WuQ3FPa$bYlc|X-u(_Cu;s#>dN$eqy8_;XPrhGLq{J>8;k?L(? zW7$%?n{c;SAUDp8uwQWd~l#(sr!BqBuJay!u`8sHU-P=d()L&46 zdqh6Lb1DH`i4-y`M3WvWZALEkCLX7~(m8R^8Q^OV#0lhJ0j28ErgOG1Ey-*Xl<~9- zn*5nbNIITcw;(DM@qqFtcOR5*IwOdELmr z#lRNbJN!K~k7qwYx+*AxucMn3^YVY+@CFh8yov5q`~~RDsR;pmGWDw!-D<5pJn)Zu z2zgD$s_5O{!Ey5?txiula~p{KtdE3&O6d=5ZiVZW&GgoAny-*&$6MZY9)Rth6u&+@!0r~=DiHO5$IpZLt zWtQ~UKPi4x|IU5|2B=s^{a^FA47o`t1uZ@@Bf;(usV3zk$(@%pA3V9s$!dbf6Zdqr z$O<67S4kybKB}Kba?$e?R$d{>^<^(F%ve497jU#iYJ%#-q}>UH=27c%%zOfnZer|4q7E?+>omwYp(NSX0yKt6QwrC42!sFk!Aw;dZ*%qAv*=v^Y%@f!1 zq2KCWCC>Hp*P%`J08d9645g26&48`ZDf9mM=Ch(Js_y45<=F;k=u~DKL(wEdJCfVM zh&%rsfHc1CKA(NbwXlguKziU?&{d8Y<3r)In;kCr>lIJvKq=H4RuQz(i+~O;})5|2u!G^&nNDoQc*CoQG7l;W9tGW z%!bR4=u9KE^amR*K?8JbA!6tc)57g5=HXglF}*J}uXw`5Q24jW8h#zL5rWrVDzZVf zU2tc(6M6*sZ#s9MP%+}=EfVAu#86rSXtfRZ>*Xc@iWqG0 zlgGJw5U`(g_QBtKZG=3)TMe2@81>br>8o@iOVPC~x6P^0!HO1WOg&ql$-RFNhtYh8_PzZvJ)CEO*ueUjqh1uKbE0;(!uh7^| zuIg>zW-^)Pljx%RgVzTyz)EmweFBe2TpZo<+qguCWmK_}Y$IbF8rXR1fp=UK4BAI& zEOx-M7)?q=<5h%gq945QS5*x{i}&!ZM@2%{$6jb=UMFsW@RINZD`9mfaBP4Xm`+>D zr8Hnp%^wGH-l4z16lZQ5v;b-0{0Ntj{pF#NEa3}*%YJEo zx%DP3JByce<<)=JNmXRWVj@A6i!C6ln=n`yvR z^fVfh)i=55GFy7488e*gP7^bIiT?Iy1PW^O#0Q8S6smGi%lR5!7D@K!KS`7*-?%n;r8!VmBM~IqJcYIe%hOcY93vbJ1Cl27Ttdnq9 zo>}Xz71t7${=B!C#35jDNMgxt3!s9+V>c%RY@(Oz>>Z3fC7xHvo8&a=T^$1O{aqL7 ztz|U$zbUqfP4Qk&O{h(QY{x39(2a_x{w92nl;2q^Y|5ks>N}WM);8jL^nbmW?Kt4J zHb3`BF1%Dv)_*JrKKtwe-9Rx%w2Jm``RW4#3$`2TdqO<~JVNCg**2>U>nTy73);Ln zd7m0zI^%QX*fXixCX0kmemuuHxsO+JHM6o}%G7UpCZf& z(dE-Sa#{$q7>jn4 znwXEAuyvWu^*lLq$sxK~&dPiZRN1YL7q+^ye5h=MM{m1NLZ3A2Mk*b%v{Mqh9QeJM zrf92S;rts9%2eQ`iqRldU)m+1+)uhwS~&hcDFpR=$LR+_SN@j*klu@JhdL(V_!-*6 zf6RVdFfkJWCp^o@- z7SS?uQmAp9Ex??i@WRzGjwf1C9!Y`lFzKpL_h?<;8hr|xQ0SiHRHZ&Yv|**7`_eO6 z&raT(Blo8*=D7LT#c|L9-|@?gU&Q#6w@k#2qv4${w*LSB%*wgPFYqfsBUrV8OlDNk9f zt`ud5v_)fYh5zJ26p5@4UaE46(S*2fGKRfM*u0WZ*B=5^#TY$bp4d+t_(KVd$alVL zf2W6MQA8b1$y~?Tl-R#_)>X6kwg)06&@(%Cc$r7we-%p=s}=6LjDCy|wCb)K<%XwS z?nWu9Cx?dI9jMEHOgLW5wpM;+Vb{2SIBbtsg<(<~3=oFI+Q`_mmHD4jIDJQBDg1`{ zxFk853dl)ot!S55|7VA$(a^^G-iylpVhg6nahh87_H1k~MHiTa?G!ZiN3O28P@Jbw3Y)s@u#);!-2% zUc9?us2z>cC7yvMbQWu1=h{HvQ|TQ0T@TL4`9T8-tLJq}TL!dS)VtURwIZSAJ3K23 zFkeH)r!Km-GGp4>iVwxhd_{Sr8=DyWrn~cYG`mOhoyyO!QSpqe6)m{ny}gr>ygIn% z1v5leHnvm}4e*gABh%`B9hlqB3?n@TantBl8W9;)Go6(TC3lg$&DXRCV8@AV4i0xoA3I44MX$DRNHnt!E>afdi zO{DHUZ)fP@o&TtxvUsyAN6q$nW7NgMF3`zsAf?L%+9I#%FN(UvjnJKROcLj)ac~OA z+ka zkvP|yc9CnCA{A%kA^M$VKc6XFLs2LP{CBHbt~qR&ZXui8;AG?AQ1m3gBf67c$3M&* zx{=8yz9RcmGK~>1PgK|q(oo39 z3Rtt8q>Egf2P)h^S;;;Wa*kZ_9c2DOvw+-L1?Ufgu%tSjn(`=0Shz1K+tr)=4=Uu3 zU-$!?B6PG`IyRTkA#C18h91ou$IGBsCNqCk15T`XfK5n3%5LQiYu2Z-nRWF^HS#LxGhngBR%aNLVNHLUBr;$coo)E+G^^ zM^!Z#)euq@USk7P9QT!3&t#0I!-l8dYqzo9WFO&&i z*!MW;4Mk!50T!^f(5ULWIva&dMDEcRzt?{shKOvUmz0h!>lPAMgQ=6m3*fo)t<)z# zr-VI6JDXB?-;w6YvGGB4*BD_wss$&BnLdSkTDBloCv4vnN>SL;vohbVEqC0BV}24rSWIN^UxlzF5xl7z^O z5f0iouQ7^8n6kN<4@zhm3TE83O};2lrQH~Y1-c+6-H_dmHTjS7-IxOeRmf-L$123E z#%FnOxn~s$X|LrsHc|}WJ}w5!(4#>=+PRg=tB0Ab^cKeqzonbxy~38z%peT;$bId|vhEY2d$_h1>eXk=x;KRswbo^g(iB~>C~qB` z=xSu(dHsR75G)Ivr2QQcC>XPP4D!FVlC#1OE@2EjXDsS3E(Cq8)+s|S zc2TH2+%z7#?Sk}$1!u2g{pO~zqPaC33GNrg*Bj4$0U z<0K%IvuBH21yh$w%6AK<_q4BTLN$(ydZ!rgW^NJ+v`i8C7}|Z4oy?I%CRVRYQmlY% z50UiJdIcwXO3P+Su7_NAd5llM$71&+jt5MIK5;O! zu!|CgSdNQ3d>Gb*F;&&6Ke~&(r?ce6I#+S)jgQDuR}tIOk30KE)F?FGHIwm<4c1V1 ziO;B;Lqn#7qTAdNvZ!_dzBo-7FO*e*f5HL5_}xXJlXO9xh$V^V z$*e%Xo1(tbn`XSglAUfG3!B8+jA5UAgSNATuu}oxDs=M8RN}qa!mr*T!yNy&ADr0g z!J9B-Z2%-sum}Dujv4ql?4z(SU{|(BxmhKh)AB5MQ3{kmu+YZ-;%Z(dV2h`8RwSuf zdTV@zQoUH(p6B(l)ofOz4N(UO;-mZJ;8Nq4jG!uhugsP?8ISMv3S?adqP@7I-4BM3p?IS3v2U$^6#ik9?GwxH^H7r0dI@pQdYG7@O?+ zM}9L*Ukq=lp#S4gQ8&@zwpKM_%)Bbb>C0h{O)5ev#HW1-xn%S|Ap&4YDLh3p z9GqcbQz~@6dkb1fL}6sXkub4v2mVI->K?*I&P5(Bkxnp~I_V!Su*A?cL85T1|eKGLqqK-a>=QO2O12vtd>Ovw1Zu9>_7cT z={%DmwEq``#psdyV04kH=fV(FeK|$|r%3l;SS@N@m}X}Ga$^NlM*to|Iv|+X*`^uy zV1{%?{mmkTwDBUk`g&`%rBm*@6wa&UA}c#@qg*|%m^3KRnSuO=5`B3KV+Kjq?Ua&} z9Hh&47DC2IB*>#GP(v1S*?(a@bM31vAXZTiXcB*>mlb;rh_Qz6KTc_7cvCaNYRJC~ zV`hED@U0mFk>*JXAm2AjxRqtYOYEYf)ogc1{3{O)haRO1bi@*&9_7a+?B}n*3TJn4 zy$N!`sq1PBdjjThJC=jPPaI3aPoF>!JXpo5s)db8vg)(X87`VPkbaTqDAvdJZs%&pmS^?;aE%+I*vX93o+QTZ; zyJdIeS}`%2-}iR933otuL%F(^l7M|${nPIt8yytSMyVOM%0*ihI7_H}%s1mm>;S|| z0;dhHnrky%XEw$&k{z@+P=s#*V%Op$)!jy%tN3hMajx`9mPgi z(8BJ_L3}H)&%74dk7mR2lceW|ZuDEK)o*)qia0GU2187A^>b5X`u^xP?t%ZE1rj~Y z_Yh4{=}0G~03OP!=16EX?Qy+j2_?9o2u_=gPVwqgPZ;KrI?S0oxN_22;pPFOQ%)Nq zDOHgYfNP}3p7dgQ){bRqo_{8jusrK225}7C#1ehU|G+ZXb?NuwoAoqtDJE$_{CDr# zaPvN7Q_7Ixi%wI>NgPArOFVVXS%nf48wufoM3RE_auq)>9K9Z^$0kGu-eN_l|F<7L zl83q${vxA$MU;>0Xi*g4N!tPh&V)n)nea#Hh8=~^TEKKqGwclM5cxu9goTz_xTP~M z&WE6fyfBH~9}#uXtt|Btr@!;GlO|af3(yFnBPM%21uBtvlJaAxijgkztjBVSmFNqk z^@@h@%=I^*Lk*Q&#!^5^k7kZt*&sr{W+Iw^|FTJuJn~YplOG!&U z0{+#q=y`V-eb>SiuKw7cfN|d|WLvhF)R6RF0c~|G(w$PmaFdgz4^E#jm{8UigjRrJ z4s3{OmgcB(_R^dK7*GFs*`zYAQf|7=JoLFtxIa6oURd7Kw==5{6ST#5v=2sEc~GKa}9ZKRMy) zX{z<&BUE)Ch^wz~U?$TV{wE@fvlP;fo)NRZz}sCYKKRT;MyExq$5+7Pyd!azor7vo zDXGUT-;@ z(T^;S>+)21-$z;UI%-*Lo5bM#ji${IMp8-(>JW!aGw)mE!v|$CVsHRD?B$GpX0%m4 zVI+%5ef_}x2#Nje)JJTMm>wsSUO+lyQBqd9dm}_1`E>!PD<0?lW#I6L>#d$y+~H0 z(<&5_*||?NhnVANznqrRfp$!gI4qlWed^fbv{KYX?-J>XXgOT|N?-bJ6F2nQ8J;B2 zxOGz`Nx)z2(M)(py$*pNiLJ4qDwKmCNqTe3gUFQ38a&ZTK(Jt2OsY!YyuYFFpH^^- z1f%X=8F$e$aFj&wA_{xV2=0f)lEy*9keY;5`hB@zN2urrsavB0R9L=3v>ez^6CxFZ zc)hnBz2#;*@o#QmU*SApZd=eB77|#`(PlVrT~ffH^s%sv)J(CVEk$~(byhe#k+=y< zQA2riFIONFBM^YvrCJbjvN9I@G{Wz1IQJY7gb+M-2)F>kvF#U^oLvcb4!|2z1DrzCXx>jqS zn08qNP5?@7ztev?Kem#Dr`2XGdGS52o>mfl_d6z=1L_FgI`~v5*neGcnSuU)Mb}rP z^MZeuiIUV^Q_G?DD#B@t>9t?@_(t!qKx~)=GXveL!GxdX*#5$-lm<6RXrN97|9nNV zGZEYCSU*|bEw7BLfJJ@a{H@&1`~W9%Qtsd{pf{XL@5--kf}E9k-(n4!?A>E-CI_ijfg z@~*fr%HY)yEpK@h={q@pTcL&2=UC?^n%HaJIX4dQxhaMu+pT>MI^J=wWTt*jiZ*7R zVbm?@kibzPjpasz*cf2P;$oHJtB5jL_3d^qesMlz# zgzga?f?Z4cDA@O)L46E+Dl$7@Wt_&gm4|~V1rIMiSz)(PyMY~BAB{3uGGiImxk#*MMl zS{YSc^ARQPpy$IjfZ11VmIDW~z{No$q?Pty3Xi=YrO3i-3Pceqc*$CWRyjHq4WwZ6 zo@>dlO~RRAu+IYU(lL$lk>NwU1c9@fHI z0#Y-)g}Z2mKsV>bp=>nP!u=_*1ChVcHOG$Kn<}7$JDq^?qfuc5-7BReFScVnP<75U zkHG54J17NnwrD7TzpoTc4ldH7uZS!*EmiP(*e@;mY!nVa!(rLtZ;n9(Z)4~c`gh2q z1iDHS8;d#eUUYoJxL%eRWV1B^eWA}L>rZ_FWcKicO&PaO8PQXjugQF47RN zQs*+Ic@RXfYgikR;@IkNigdwD6Pe)kmN0zym+B!bY~f3%$UTZ{v_bGg*6t>ecH@n3 zldQ;+`3ulm$GFKN8za#Hte_{Je;n4(Bap{$Ke;()R-2ltnm3WW6GQB`3JSlVXXP(>JF#MEZ? zyYU18l_f!#G(UnImBZ21f@X25HG!zst;2IV)+=bBWy~5vKkKjQ%?cL(tWPr$q(}a@s#z;(vR^=P;9S83Br5Tc<7+>Y!jXN!_w7Py;=j*1T#N2c z%oY|l&Bxle$Uo9G9UJxlm>TOXa5Q-nOp(u%?+>qd5hCw`1I*CVU2@A@s%x+c`UB^l%ZuH}=+DD6l#6(u~G-5J% zwjYb$#e9T}oqtXrrn0Rs=i`JbTt>fK;x-ib71!fXsAb0&(QanaWy=pXx;I9LOEq(! z)Z2UN4h7SD`_J1c^6)UL$bLcUB>|>q$Due%jGB$eKD;jq0FN%29bF2VD&z~)kuaeg zSnbVljDf+BA-hPdDjShnio?+(j?&Q(!U0tnbUlQ;;1~DF)ZbcKEkU(I0|Iws~{*P-2afaXc;B$hViw zw;eBkxtqGN4xAP)t!5*WITkVle_4W~C8Vuzl^uINqMqpEB{u?8c@cz(l$W;G9m21$(|$4vGR#bDB!a4K!`bB zn|cppU1{QoRo?@p3hP9g@BV@oOE!x6esjxB2yQ&Nb{+hHJfcbV5K-&*EN{CYp0JWI zwz;`WN3cQnA*V6#)1B^DjzmZ@b?i*po-DROLFkNZ)X-_r&=&&(S=&)lZNn-UBwKe# zqw)6p#O$tPa0L+o#e_~TXAect@n zz&;V7s@nzROkp=2>-=Cf1%;7Srcgk!d|en*ebC;-=>f4sEDKC<8%H}om@Vt9=d241;eQ(GQh8AaFYpBU7T`n36oS8@6E;pO@I@I zBjM?lBb_ih43ZRXzR5L77-kCA9?73ML^LRbqqLVWQPs_)F~T|2%n7ZQTR8fKl`a;y z@8G4m6wRWT6UwTL@Sh|NWrW&o4YV4;3N&=1W_nN#>vuUg-s#rS#Wj!S9E;l@?4jUm zvX~aZM+=X3zS{;3catRS;b{19p#5qb znaW<3w6Yb<1jKFo+J($J?04n&C!8a~$BT+laIM>D38>e&hf1-D`D#}7T((+`sVF%( z+>a)Cf5DK+k~(-24q+hY>j+T%u(xouvX?SEQ#31Cj(m|SAZIh+P7EZ=w2I5pfgb#4 zeyo$+aSeQrU=ua-2d$NG)W27TMo8P~S(Dd|>SPmDODc~-wXfCbM|aUI>qobq!oClm z25uRq-rMLaoe5-EMpWjcm9^^unsHmC&f7~5_mkf#g3n_8lXY}#5JgmV zmQIM_^kupGsb4*dli1B8S!yl{YE)r}Nq)H69pu6;FFPIxJ>ttMY?b~-MNnPde`O>H zP^A|oXRufTMg$;qvO8YB9l#X_nZau1!ZaeV(TrVH`Tsc1Vu!lZS0KUFLZc4;?f;Y3 zW4-N?8$6QZXpu7lYRE$0G#hy+CU15|fU-|h1bb6Coqm)7>_B&pF@*!Ld#5x02$3@E zX((ql>NCJUvzA;MLZ!_uEBts1vjtZ44M-0LGU<>_1KKOPP)UMdqu%H;2+u1l1^5AU zR1g?f6`G`}-A(SMa}r>!Xzf|Nl_gRP<)&BJ?v+k_^pu9@y^V*O^-L`ZCiEH9OUk>IA}x5<-SsSq1FMN@ z;(1YuwlTdOp~0%P*mS#SAO#eptdY)f=~znc;R}#uDHtOUSa`QnWL0vpd5>7~9!qFg zM1*Bcy`I&7k6i$xIF2UV%rx3>5x&hG2+o%`;yS=i5Ko@cI_Mx(Czdk%Kppjo(;FR$ zTF%t&rS%r=;nx(LvQbcuN;ORZAO120^y!qWK9IsKzNbfN3oUFhOf0*E}>t#0CA2c-9gB#%|Xa`b68RFAT}!}Ia$G?O38hM5S5qB`JjGi@#Hw# zbm>*}7bL`F(9gNmW5Ov2hxe2ZH9X78YOx?$bOh)bg|JvkV$9o)7=*l!NBZ(qL`YFE z-&}&G&V}sPJd>1;+~Sb4dFwBqGOhgf3S}IQ)RU6TL=cP$8cTF!-+>!75UJ0sq+!T^ zGgPvBk#-2+GR+Nuz>h(Oza=Feg&~a~h99D1Ha&ZcZZx>n6PYp}^b`8cwa{ZNH<^j1 zfh+=!`HiMV>8h{pgA}~;_TjeaIA8~#(V>&`hBhMo-7qKF2>R>`d@ny|5)Z#(vu;Rr ztR7|_h(k`iZ%c&)^cD$J5~rgkohoL}wAwJRARZCVllGojpx~x0Po#;K@(9usaxH+E zA)v_e4_A;9)!}YJ<+tE+@faUGp#m4J&0B9p!A~z8@e`HV6hY?NNGGHE96Lfj_)=v6 z1OmlDZ%6vDau~XZ2!$Vzb_=ydHNb0GVlfBK!iE@zJOyN$g&a@#La(Gd$@v+&xzwyv zq3VUP4=lOD{s}P`b8YDFE3h7@?7#tgorL}hu-=_eQTSk==s$Zz^g-xKGahP2TNK|* zVlOKWOQ>Z%$*Pbx04tp4jhqo)XE`B;V_NW2b|J9kfF7z7N>9~~&2Y|Gmi;0C*I%i` z^8Tw28D)2iMZ#*BlSIIwp0I^aVM`do*N5xbj z(EpXZ?F|TN=uRR^1=B5aI@Q$9q7$uE7rL?!^C7tD!VEU{u(KH5z`Ar6Y|`uo15cG%E%8J-d|2QjP}}P~%C# zddY`_jI*fYE{5YRXq3sAhisLqN0E@gUc3mOB2spo2v&ABrN}%~_y=}p;kFDY14Kb@ z5KQ)pn95TSNAIcY`^59^E}|a6CcJ*H8_Kdh#w`cO;`!<~>b(XSFqo`e0JT(QP`pEX zUC7NiN=3pD1tmV;`>dPrzU6>hoH`!+U{I1n@PB|8Uvtg~%^by40SQ+*hQT zt~7g2v@pTfBZ(H4vqG^l#o32wBL$jQ^9jN^yBV`PA9#Sq@8t)0iFu6B%?o*!Xoe9V z6Fy)bR&6XtS)>x16We_dH^%lIwS`8H2?#l|1Ue~oCv$jWz-V(~+UYK#hw+DYI#Vnm z8D~0aY@&dsaAHCERH7S|62z^Ld-#dq!n&RmVZISq1FE4gna>G>6WBJ&?65^_l^%zW zc8!o#v{0DDJ95X(heP?>?C9eX5Ws3OSCC@;nXb=iCuCH*3*56YeawO{%rK!n-CN3g zPlK5J0s{ja?$liAk>r;WZS&k!#jQ5V$rQz^x~0|D7REnv3IA{j*&J-SQR5u*5xjqX z9NlkIZXo~65WDeGHz(97UNe6YEw~3~4>GA6`7`Fi*mU^N+h1=BAnOSMiXkF>B8(|~ z3cFmI9QwP+lMlOt@g=pm&F&PG3`#Jg*bNnh4Q5@ zOVCJ)%ybsF(A~o1ue$xxet8X0Hgx@wV~GJ2?Fk7UWgg}5QpZhrqb_!*dz%vhAZXQ! z-r!vu6ku=z!UAh~Yf9>L`;RRZ9+#6?!mQ?cKm!);bWzrT?c8s4iaoh`zaadLJ*#?g ztqGlRywiP^I^%6Az>{HN2!ImeFfFJwN#a;R_A<2;NRP9+EK>AGouYqCe=veS{81+< z7Wwyx;ACTrbJ$NvA8y|#c4Z%X49e9$f;OqaX&^bQ7crc4cU*a-QTo-DfMSD3Xt&`} z@S?Dtss`8oE&e##U9kNb>>mt1HRbg{PDBtPCuzOSTOiZ*G3 zA)zN#nRrS*1Py`L(C%K$g3a5K+QSlyD&q5u+-?hSShbdL4x@ zxFcp_5qoot$t|)f-Xu51*(Ej)vTcp09_Eq%W9d!6qbjoZ;Zt>&zTN30x06oNfsot| zfi#PFvj9N@R2J4jY>>@}&@6*tQ39eOqFqVYTnURTirR<>E{s9Y(E*(sKm{jA98pp6 zXR9dc=omJ2T>tO&`{sE@h2H8`)!E+jo^!|n*+!Z!E*zeNhqkuk4XIf-a$6#A^PhgIP8}4Q5Cg- zAknr|m#%%55Qx8Jzlcw>8^^X_19%1CBOkY!V7+L9=M3+M0wF3x3!))o6PQ0KsjP(< z-pJ;YIdDIpTHCAk0+g-Is-`Vu1FY3eu&VmmRoTBV^X@zNIo7^<8@~N&+o(_p0Ybfp z%c6TF!Hdt>Pg4!cA?U6tg9Q-1t=LX5IEuR;!XBC}aC{M4ClQhOk0az0c3E7ntib&| z5q$}QjrfI%c>x}knVr8Om8kM``mH#`@9&@)YApYAsk&)X3Ebssdn_JMYP)AAkx99r z?M8;>|C7fU``^NbB$MDW7d%C14+By7xo4I7DLQe4vF_xbFsp(m_MZm+<5!KXn_lb- zuLYvnf!78LI8E&GH#+__Zymk|Pi+ZOQoVgevdSGheG>DgUfVJpuxk3QM#R$X8@7>U zU0pgh8$G08=hOtGs*c?_)5-`g!%;ZBo6e<5pLy?iZsA8R`dYDu`<^SuP8ei3nE!%c zrBGCp|J@QYE7R0Z1(wK^p;Zo4Qh54K1q!gLd>KpL$}&IS&fD^ckFY1W>zhUvWn%k1he2p^Rg4G>ZRgD%@ z1(*&TSIZkIcC)gV_;YnJ1}9zST~Go=KqaTKy)|Sd;ZX#V%M~-{zsfZ5pBm6RQ`tct zAFY$o&knCabqY$sEpiU1wcnD@U#KG+QH{83@E+>N-RmD>J@_3tT3e8KY^_$RhLiy^hzzTeFqr{TCc5z6{pq8ulRn+2vQthEE zTq1xV9oJHE(pQASWFtZtsar$EF?Ifs#&k0wF>`pHAMb|ye3}9+3cJAg&Zdp{?R+PX zjHdQYP(s!C)uMQBmO!?~fZ}Y=%+Av1txwNQatE*WoZ4!DnpOwWWRjKKy>7`)F!UfQ zpg<^iy~-z$eo^3D1~94_%OCrjB>%H4;OoO1lQ`pEV~(aZvgB|qqu_ffptp522iMHH zH|Y7iqn2k4(LUrK^17;p6;S&5hQc|#hhW8jl*U{{3ye|U#oYX9tXC^mqhK z$AF+=5pNw^)M8e#;E^c!#~gm7?Tf}9Cp&!Fg!`IK(1jFBOQ3%QgmPQNj6p!QKwk6O zBA%mPurNcc)>>qeX+&lSv$6A?e9Xga&v~GMTYs^~ zGKcW}d0)T6aGJ9nZzPJketC4?x* zb~?;FBhty&q3pd{j$hgDdpPsral_g$?|HS8!_QXm$ku<8*c^^y27>8;841?4OB9eR zv?trUmta3k3;qHNm5Whk=osNPVrgHT8(>#Rxj5dmz;BPltfyG7YoUf zCuu#RVu*?)`2io-yzljx@d(;egJiUwQTz(pi?&T&Kk6h4v^a32u6R3vzyxhkT+#sR z4e!ujO;uwCH564-Z?`ZshB7>m>OGs# zT&)leOf)~hcyE5^r!L&xU3mC8-r!4u0rnM_O%@yW1~rM*%4=xJtRukTk35MBS?FWosf{j`bG8yuHI|I%H%i`fmhn#O&1IP@fKIIs18*Q^%}3GClkk zt@~pmai`4G0~U!zF_cy*lKKCC*BL0N9m8A; z`uojlg1{IyqADwL>ApW^Ho%j#NUf37`240&9$p1jR=5aLj?K_dnF$L|(BFy3@X)q| z8{q*74<}tuPmkdju#z6fAI|7TrGg@tXeRysl0^~Dq853Q5zIgQMS1?kT==8hm|}5= zV%9Hic?0&Hd*Rs8)|*fMKpWacG+~*juHQp5EF=AcryXz)ytC0HX>$du3XU=p)%4II zlHnYu)vusYug_G$3&a}A&g=ntza2k7+IV>J=-t#ACDr(dB`wl+6vaJK;LoQyvs)rSx!!#>MQV+i`MzMvq5g4htim1%ZE z6DA+p@gN!Rf)*#lIeZ}Hlby?Gu@-H>m#$s|duXXyB!u5&c?g|FnBDZTmq?<9B^f}d zT9PC;aVm*kLCqxT&r=|_!X;gRqDnDHKA9R~X z1;j)phur}`{96i>+DavwX)RT$JLUs)z;XZeUAOAwyuLI6fazET7YbCuP6m7&F4aCI z6P~x)mwxqIh^{;eNmS62pLTjqUM6frn35a^ckDsa5BWo=wUpomTb=5y6m+iT>O7UB zP>PHfnGh+bpz|f23xpG z!ydFSFV%&KUHp6t?$v7*VB9Jrnn;%*fi^cK1x{TAp4Y7Q=n*~|z}Kn$920-s?sg(t zG!G?Z8*-t`{m=DvtoL9?w*r;89AzRZU*{X!;vjte7dYQ_U!)N9FI-78>v#Oiwn@~n zJq{)KDjeZbtZ}cYA{#?cU)1sk(h#*CXTabsssee|67V5zXZaV+J=DjONZj}g1TB7OSn3oPX-IN zr}`;_KJ+|Afdoq1WnQ6jr9EvOVym@{CvNk1_d{X4Vu_W21B#@vF8WE}Jq<&-VLN=pU@~1zh*m%6Nq$-V)b# ztfHLyJDAxl_2|$Qj?Z1;>3@6d6Vasw+$_sg=NbM>$V?;Dj=8DH)<3C480LV`_bKp) z^~5Bo;MjWBY3hP>!~@rI0H92!@0v|Q!@CkbD~KH9ij~H-sQn?tWHDy>kHpFEPW5dq zCnp3$xTOV1Qlk8f3kO`v(eO~=!=loQu2{wo*Pzx8rdzC25hV{5g%UFL1<4Saw3&&; z`Rbo^q{h!rIw;HGZYW&zT#8r&9WELkX6G{L_v@Sm+%mVdu|~Kx*R+x-qziHN>)ffX z%Ou%i8-W|*8~=^QMR;t5QnCE+DkeJX0iRe7g><50%NBBwh?>SPbg@!i+gAfLF0$HI7>92KI;NqdTegBbOE20Tc5zF*l)pqy&nA; z`jHb{Dl>wXm^>Q~U8y&QpxfHBH)1MtVF)QN`ojol_rpm0zxAZy+{?=O0zj2-3D&WL z7wU2n=vEe^9)f5E&sv=(n#g<2O$ZG;&`wtjQr6)1U& zUeJoTgC4Lc??;LvN!L(>pZ3=))?3lbRhP(h1SZ7)aW}Ul*&2yYTw=!}bMSW;dL#(- zr&KMcg=xdjxRomB>Nnf;mYEjPAw_51fhl2Ha$M;%1wvIVk$^mA%-{m7%i}?#)W|B| z42O-kMr|cvNj4^t?xqwMvyyfP2#8%h0?NME7wDZ}syz{R;^+Ie{R{`=LXRYNw=?v$ zpXbCivAoQw9Oku_vb((Ez*AoWesA3M7!DCUiVRkfPr)>GCUV!(e;hihRQAR9iEUc# zT4K&JCeq)1R)5jgI2i~Vm-m{JQkwyq0lQI#?)CgR{ak-Y1p-$E--SF$2!@Ae@0z9Q z3$^VkkdOGAlqAP`MFp@EK--p$+bSe^IdvpF9EzDDLz(SAnb^jouPlC|2)e;C%Jv1xJqOQM!$1E7*3F}5@(sqnQm)5NaecJCjkdtEeXv% zzm7$xb1`{UJcb``!FdbFKqB%OyDHRp#wbZM*P@4D*^U;YD-st4r#mcm%xHKn#d$RkoxYR7JRi z>tO!rZhs~K_(0kHYA0oh7PmQVy6?%bWzzAvTnMGVxH4t3A5IxCb2INiY9}CtD89Gy z*zHLg4+(s3i*V}?G7?B?rdT#Hy3`GD8WCCaM13br`$*F>JaP>#ssqyjTtjDsIdD%cF(=+n>wZHtn4=LI$Cb&n^5mZH&x`(N3QqGT|A zQ|PCFpd!2j>g+;~UC68<6xkS2QA8%9+g*y#B1YX05*Vy>Q8Q3bR9;S|3&T?jayvG2 zPEg#gxe{W6)br_wVY>`W0W85TwRd!kqQmyg*>3oI#J#)7^?{=6MzHu#`wIQgD!L^> zL5N9<1)#8f^D4+!9+L10UvwsU0Pgf~g7`EoBD=tzR_lV2q%$+&0dQT8nh%bBXxJX7 z+Wv@jaFByhRG9I5i|;bB^cCs!lX60IGT}P^_=oU2a1mj-El@sydsQC$f$c-l+X9%i^UkN}1 zJ})0gozAzwH4A@=O3`DRFEj7hoCV$G1~PhQ?tO zf6Un+Rk+qW=Z45Z2;{QCiA_R`h+iTdem|J9q`(%?G7gQ3oqZQemL4C1Lst@8=H|$TkM8Ju!1K zUGSs0peME=)cF;TQu?Chup)%CPA-6QWmrn7z>j-WW|^{%#oWmNarVFcyw+SxRso8% z%$k8$%n{gzU@Lx)4sUWS2!lv(z~=3*z{Y4UyC@I#=o~ZbY*ipb6gq{!?|Urf;X7!x z4_XlSZFw&q<^s)&($h&v^B-kza|!u64r|Y> zvX+P4b^{^$n8w3sMGUE>=XPFOCUwDPAH&K zBAE6HINj&d9$gN9104Z6gF*Rc4H2RQZKta$g;eiSIs@GVj~h!>_9tTmu@+*9S%;kQ z$gp_s!THUNFXA_&z5w+D*#Gkxj6F5W$%NCB;%`Ny5p@fv%(t9q0w=8DoRl7%=4cmE zcDs&?M_aH7TJ>iU8EDBRYPGYJmagY$ zt^+!71ri(oTUL5|+)fF&{f z9#YfQ0KZa?f%)bEx(7UcA(-9VtwfpiQAZWtbQwR2wV)wQaktxFVY=@{S6ysx zceY^9=<??K8)qTM-gR z+SiQ?fGI9;smt;nX+k3aH=e+h4^(kjk1fFP*ePVKO75=)ns`+YM@> zA{o@T-=~H2rO;;fwC_}_E!Gz~%B}Q5`>FDJz#icws)$vz8Yuad&@zO+L5dDrk9IMu zi@0YWRfU~IqL{32={6oN+xRnLLe}6g|G#9CUQh_M(*vq(uwc25MTy6K|1E5CQ3P?O+qA;RuN$7Rnpk})G3BV@QLkKODDog`&WP^xw|5!mD1$0gvc%=0$%B}D4} zUpG+Lu;4M7Z$;PhQe@PItC`H<8LXQUL*8Ixeq|FgeX8#@e}6Yks)E!a@uT!eoHihn zXHOj@Nv`(2y-(XL(V@G2{YF)_4{8aQY1P2(kR{x~td(tpK69WZXeIQexwGkH{cmc| zsIS8ZhSKb6WbmkEsqvX@ws*mmb&!XiCA&vhtj5ObYtShbF-|= zFLbb)OR3N|NL778kb|IE55}bhzp-{ba#pu`ZIc>y>9&s@9qlu%QfBuWo9M!#hgVU( z{7t2!ss_Y_y~Z-zA60P!*kUSc9xCPowxpW=(2IA2pR&OyEb9a(YN&hn?MmKJ$FhLk zk3-WU;gXw%jb%v{fc_^2-RkXeu(G>vST<3^Bi_O`D?(oxu+=p8I$4i9R66>Y5l&|_ zl){s6G<)P#K2J5xWmTU$h=5Uodyrdh<|A`Lj(27&vN`(J?ONnrH-rkib*=_-+`a-{&i5b1kW5aoMOJ}7s4Gb^N#CP^)^{|rl=X(xK)c<$hyu;bHRgYt6*s* zT_!?W<#^a#Bc-%%qT)jzk;zbm@uSM~4U}rANcoo397g?ni<#2BD8~gs5DB%EffMMV zs$HE4ZtEL_2MYg44UKoliz>}VI-`t0ZFglNPB^KY(n>NZH%Z>xQ=y>JCsB5W_hl+9 zCMf9t(BKBQ0{?P=0%%pXl)g*z1Zi+O>MtTR6sl+fW!p%=)G%$B>-NBNJD`t&_QBh) zmT>JD}=ER&;fzkoGP>qbgh7#gr^J81C1}i)m;D z0msW_{U|Jx*Rk|hm}e;Wi04uNRS+tqG;{e|JpFp+3z#4BP^E{JfrWJq%&_{5qYGkz zm7N9TH!3^wltASoR-gowlrG74*enZLOQ3hcA3i>M098Ws<}70lWdA6hjsy609rv`L zY-Y+q3RiYK$E=3`q)|y~3WnR&{_V##arS|_(2M|Nhb8rAF2&7lX6x|rm;moFdl=ct zDLD0Ou9~vNG)iIge_tu@$82|J0}owcb{eZ_CGafN0j_-@KvxHzAK6mJ(o+~sbq$m8 z77Ymg63Wwuo>ie<(y{lEcTS~IVda4TDuI^cw91L&HV@VQiB%5W_b>c2W6)(oQDD$B zYUMLC-$%s_x98K)vqg9*6TN+k6nUJpsSw!&6@IcZi=KlM1oMfwM1XM7lO+!-gVmV6 zTPc}ak?^9t5RdWuiUel4Ucp7*EA^fU`m5?TfNU&$Yp;a=MRg0=!a(a^CZHZEdg_-)A|>ZrrNsl?@9Qe%CM`(C5uVMS&VcNq~Yp#c&MxO zlE+TB}`FUKlXA+o5eYKYNA3KAGfV+uKwS$hSH}kRKn?Ai8iMekG^`{~| zI8g~j-_Z$9C95~1PqW5_70PS);v;ZXeR{h#^o?&|n6!+#$Bb_0e_>U?ggsFX(li)8 zk2<&;tV}N%y1i(wI`kkze+<1RJ2alEi zPF0}phT<`3OjLkyzz~?!@eyAeA(OqmFp4U2Z%d5T1GDi;YmTP;U6(G`%7G&k*ZxQe zaUp4m8*Yhcz$;CIC5P$MFE0eh2IU`B-XpA%GhE21 zsU1UuhIlZIu0C_DfrDPAm}$a^Npm{}TI*JW5k3~#i#8)>XgD+P*g(+&+egVB%v{!$ zrrrNQ$jufok808tI)B*rSJfz+pjs%2>Hu0mXN0e7NsR+{AwLP7_Py_clV6)H)Ta0Y zep~IdJ87rlBvJoHa(P?*8+;t-qI?Cc>`Kk9`zYz70q5pVd4u1S_N4JAa%swQJVSg# zD?$7LkaCj0tah?8Gp#R9{j>iIwBUNb9m}Gc%kvYyAALzA%eIY#Jg`60zPnR$@SzzD ze^G~8mB;J-5+7LJ*30P%`|kkFxYAD-l%c23-HW$e|980lWOR;Zt%Iq`q5*(^P;Pz= zmGX^gb#w{V9&O+4_D&q1QPvS$Oi`5D+)@Y!40js1-zREUB`3ee!G>LVt{PzR15gi@*M#^gX%brOs zsJOw~k_~tRGLSL+3;hl@Q*~L3YPlR3> z;MdVe6P%;(*o%!nNDG^%zG=qIZS3;ZdvTLY;}Bis)Epy)dWlxNY?NKhj_gGnqOy+c zN;u6ZFeDfMM;ym#&{ds)cN9*y(}Fi+c%f|%UGy>uS^z>QBFhyWqC{oe?bQ+~;Z9>N zKuLgktGAGmK?Lcwz4H;`C+{W6k{-mEJKG+1L2{~R=QyV-hnVF*?Zr;}%O+G_WQdm< z%JVBZn1XxgOTl*jqzKrB{~j|*9ZKk@rdBB!AF7001SUo?lY69LFE=pH7#AagI|56aci#8&ZJ- zX^#d*fUfc5vx-1o;i`vI(fZ>1Q^S-ov#uq_!!zWo$`9a325~qD?6+VeD%(nu0Jj>F z0x+evCXNJi+Fep5^3I*R9`$#WcB!H})f8-h0T%Fl7TkvF_oam$y&z01NEwU_L8FQq zIv=nVi@*{wPq=Q}MGx+ZOS!cK4f__zu4~>XL#^fG=LvFyit|B>(v}v*gv6yqrrc-- z=-k(^kU^AW;R?j?{7qX`<=LE3B-e4k% zHGrha6B2O~) zHIT(>lM8FA+pRHywx5pVsJTlWOaoOH2%(n=JwY4bj5OHQ_=vx)E4{8ZZXkRauerdsh+;#kP}_9s{7Ot7b}vQ#(0$`GwmnGh;A;Rq^bm@%Dqr4cP-Tio}lt59!V zna`w7tK%rgt@q)oOc~2!R7kp{|0=FAcJM8YtYkxZq>e4ZX_4=e^zd596pU+?u_NTK zR?Ji#Ljg;w4%2AlhUC8$fkt^y)aUu}sJ8_xyt1mANcvA|X$7<*45hTZZ!6NpRhDni z;^&C2QqfnAzf?{Dq3p5a5=8%}AsvEP(N;g*io%`@7re?8%__amCO-3Cw|gWYk2&jW zrGDNE;dYwKup)({wvy<+HLq=}giuc=xLtV6^V*5%)y*W&76A5xH_qE|e_S!7uS z7;?U7&(GM!xaWI>-na}yVlE0ewt|AvKXI9OmX&A;_gj>r??cuaB%@XlEPJWwB;ztx zuTVzTKc$=5x=Q=OcisV@KT;W3^M+(d?LwcZRB89CpsRE$22G*e^%SE@83EI@{AW^- zD>3T2(xip;c07TYIL39-DSfhWPILK^iP^4MA3G??q;gbo1PppFs=A;Z!;OL{QOpAz z&BtVq#GoW;+~dwltGPn=79gdd7e>gCZ^rgAL$;R6fG*attG75 zAj|*7!!%BY-l2GTn2K8u)oYD>7QVVN4ezvnp-7SiZn}kCG4Td*uigL>Nit+%H%zUV z*7-W{G$Xz$;*ZmSR3>m6&;Z5AV=*;CS^`Zcs|TEJG2T=4G_|DxJqt~C3Qm{S$xy)! zC1I{jxFD_XI(%~29r3XSx+>5Lk0m6Et3s32OXQ(?qmb))WG2aKBydBDOwW%QO>D@; zR-enS+azZhmXY;QZo-o3Z82Oix%s`f8&M5$R)M!Yn;vhBK~Va%IR@tna;}2CKN^kw z?Lh+PQF!Z0gj=`J4eZysz~3+8v0?{Qexv7kqoJS6^ACPRW>?s~1L_4{@Wu;1&Y`z9 zBF6E~zvC1>T1?eh4@v+tETJ|~UkLRB(ZOIxJjiZKP_|@V{<$~6ucdIgZ9~hm z(9CRtf3zv>J=A}sc~=*Mzi61oR%Yk6*zxDU{@w#gB95yS9?^t^J=dBCw$^NYVyEqIKP^+t)M@^OB#3;;B)8nOY@XYxL9 zjmUge9P|&PegVv#i~6Q4Mb&DG{V73UGOWAMe>&7m<>P*E!5vw>wQ&h%Sf}gpM9(<+o`zgvaQ~L-Iva*k~)*n z7*~pFh#Hl*ZNcz&bw>qv-kjod8r?oWZje#ZE4HS$zqCT9y;}UQ2{=u+ub4=IqC)>U z6<@LQAvf8WkxO2eYSK)NkWu8}1SQ?!HEo?=C>4pGZ?bXGo0_C3JO10|2U$)EYKgf-Ez zbv2-r8F@u>QI&^=#YIMV@H0!8_2F=fjlFfL{UM5%wm))xDtn&o+?E<82ffVPI zBXj1a1`=zv7QQOhfW24%x~%n=8I?wPpR1p%*Nii)I7%;hEUz)kljWPE+jL^-XG$lp zS@M_4!%x{nR&!xyg z4gzarP#^me@sFjXT-zuq(eIkVq&Vfv%3bIwHmxmwo~7etx}TMjV2JPXjl6&ek5N=r z(ryfS>0Igykr-a-_v{N$XSDONF(4Dt+Z}L8;BEJ&GK(VRZkJ5TsPnjA;d|v5c=JXm zBDzo!bEZ&@4S;^$KTFAu&Y`}L+RCMWIwr%4c{_I(4<7#bx(B>q4GXN;$#0Y5(I z>?SBdCrVfYzA}>Dxx57hJKt`mlF$WNKs~$SjO_zU^segsce~fmm@7kI`4)W&u8z$0u&kZ<_A)oxX1*ypP%tsfv zx!18sJu(~(S~9t9pv}JRjKOuD4*oSt+}B{NZsw#))qajTlwUr+T>?KFDuhcW{fSH5 z6t>AOpAUFX!W_$w27GCA^I4o$`1X0l^phW*6%Px{ zFm6Z30c2ut9aDt3y!!MwOlt*ANni0yN=xlpAz0B@+AR1L>_08Rpt}>8@`OSbi1pgS$faVh#L4#XSliw;z zV2~9y4rW@&T5j1>a+S%j;-3+!q#|){F{FDhcsFk%*JFbBOwyu?q~KIMX}3>6`*dX) zeFwtPPGt7@d_#uV{~6gG%O@=-R@y}}u*(Ig7! ze`6W;4ZJ8)aVt~$P*vfe?D`hhU-9lh{i_Kb=&5Ol=PMaOuM&envRrns z*p#S;oiycI&2q~RuSmp>;*Vl1S4SzXQ*5=dN2xzbwfFP>p?&gG6>pN*ZPkAy-M5XK zfVOW?_|K>W$H(|rT2GcR*?x~b73Ui9O|I1Mpz7+8YV4Ss>M6;NOCVBB&2gUZE0pA&2)7vaQW=EE050?wWQa8sdf(|!^_5pd;aKdUi3;~twzN{h z_Sj=gJcl1)hzGL(ct52v&9$VNo6w9!hPnhDU$jT;ej2xNOBac)-h#F>JL3uh8}mlp z#BMC|3!*D3$j`LFdcf>pmr@M@E6N4#=n?1vm4=Q-O2wp{U!XnfwTX~Mq5lh&4a(UV zx-3L998z|CrAT-*4Ima|KF#%prHUVZt& z@9)qsF3QzQzMi9$u;QdBX2~fM5Pvp8vo(wgnnV|$i-&1*`gv}q9 zzC(*4WHIyi^F-5=F+g6nuTg$a=GO~7)3VhUq?Ko6x1`VuLBy<#BP{y0GDYR@aOpj2 zLjNv01jlMdc)+iZ`14BCr-5_`I0Q_#?dQYY*5-?qlExX)1xmKsgUvHY)ue; zD&H0%p7|&-NZ_r?Y{lg*_!oMjiV-UP_Ifs;evlntw<&*L99??7)0Wgmbv(&tb9D~nST2$ecFh0t~RI&%G zIM9Wa?$p&=sOasNkbiG5dfyf!5lymCE}XE6?KEI7&S@v@G@TJH*yAiz_?g05M7F*|N=rb5ejRqxKFss+{@p&p&~UP!1$ zne*3z_5L`O^js_J*@Kk;0D#pa_wTbk-FvS#N>QL*NZ~ZKlmwGO`LbRl5xK9k;DLhy z()K_xGGsSXNzU|+dlBzocfj>@gNmJPKLI&50n?sC|D*k)&*7wxR**%!93^Kae-zV4 zPhY)OdqTju$l3MEW8%nlY*_3xB|CiY_;W0eaAAntZ4@f@?5&#nEtvsmj77;04SLzj ztJuu^PvFml6egqIdCQl+q{#|?%M&Ofk(~t{zVYhLl&O(`UXmc|9PG~)b@g+U;N(kp z^1Ok{18V;_f4b)}t)$oRwhp%Xq5CRu7tHY0Tygs z&4;xh{$tCPOO#4F?R-yA%x+jUhC27qi`r|2F#(l*SEgK4XRD8aMbLxOZHrn>4Aqej^m_x~UhoU4hGpI!J0wCv30fcUmxzhz64D$1dAy3XR8UDo zh+$~LG?`j0)VTa_3szv*v%#fff7CZX6I;zquIros#O|A1UuvTI#;Z%jTEM^5*F)u? z7>(1@}h{M7#t?c-7)PS2P|jbab9ZofP0tErZ5w!m7M#**7z z)56fa=|Yhcf(1097Pch!rqi;^jkI5Todku4w=g$JPz=3sRVzGOPWnN7q1%Gg z9884*;=H%-vAIbYXfU?7HMnhO8i1pRTF9}8#Uh0(n%lSJyS&5dODP*m6rSmf1`Gu< zH%?l8BF@VYmhPdpj$m(Gn?d;~2uEKj33cE@^H|^xN)FZWX zjB*9gZIxHYw^LEsWxTN6S)-Wf#ax8&&&wY5K`s8XQDNyUY@(-N(HD$_~B5RatOVU1J<0Lp@^a$xa zG3{u7vvTEI9jvE%#xQm&@n0*X&C;hC9avwfzfIrGW_bwvjN4W+Hjo@k!6f2FOnpGS ze}xPsEcQiGOAra%k?DJLnS)r1iUddzPBRXMW?1O#DpiNF>ftPI902$Ngy|M20=uvp zJxE0L`Xv>YQUB%cy%u@#w#E8rrL-p;AH|H}yT&Y)Raz~(0p2OksMteK>;`ufyy7G1 zM6T}c2dPk?8s2S0&(VfUsspYc?mxPc83ujF3ps{;m#SrUy=I9md#D!JJq^VWIxdv)8AiniM1FfBYGv zb>Z0AF#$E1_(rviihmGX&RZNRBIQe27iZxss}HDFqeM)!8R2@FYFiWkF`P{r(qFpW zXeg$6{;5d?%K+mu^+D9Xl|Rl+w1`|6>@^ddM}*@L!V#;yDyvdk&Tcq}KAYsbV-(Yn zuf2xMv`HissjB<=?8cW2lrtUGI{?of>r;JHxb-J4$~!ZImV>pshU^GZa}l4%-#%kBLZgx{ z3@Br-cG7JZ2+>EzTo9k3oM&?dPVj7O@r~d zAY_F_YB4Iusx$%eldnq4#JC;+b3W_-nPFAG3t-=@bgt3 z{&*7dEeSP!XmOfE7&;O!O6CD~S6{`NCLsHG`y3e`en=MxRdb5L5#sMu^^Pv#Yc#cB z(`o`vRS&vvkRnaooQ=wdceMg<&$5%*9uzJG|AEAXcq!q=s->QQ>+q-aQYY2C{c8i* zsl`t0dIYdj(yaY_V_v5O=5Wl4U9Fd3Mj6Os)_>5oV8aTPKc=O%T9aQ96s4grwB#?N z4Sm0QpWo1DpZ4`DSMo1B8~k5~`6!`r^L|JXcfR ztxGMHAh-iy6x=4(1#&#)U`C^B?wn_VsDaJ8pN3kL`XlvHHnS`=&F}_eJ4U?%? z29%%);qd-I1tpX4XTT>p7D~6`GkAgZ1Nu|_%reX;+|0r(TsfR|8XsbK=~-5wzDj+2 zD6M|zIP%r*sJe8f_6RHBMWaJ{j0%b#XZhXaX(g9&mS;5aR0cbWUd{am4k=Ns zA)WWD!&rmAGZP823TSZ_)MD;+J0tw-9KsV|h0!96_4D6Vt>Ne%RZ1^7E_7ynVFL{g$ zEN{(jwkrvx=E6c-7h}9ZSFkRgS2~ehow=LgxFs|kX`y18k{Hlu9v~C`JVr;t#7q^%O@U)40DAyRF@Nd3Eu#V;CeSz_o(-Co=IE>oJI=|OL1ylnyyk()$K_u^$6mKFvE1A3T9@@0b z-w8W@^S^$&M5$h{q72O+GU8 zk8?Cmg$ge3{HJ}06|xpDWy)MnfZa#o1>LeK+-&Eu9uD-Yx}6nUbkWF2!uocrOR}I` zti@VzF=FBp7iLOB{l|W3~u@3iwi7OXO+s|{=f2i<;s{`^mRC^*hWLEAYtCr88 z=6KZiL%Ks%;yBwbaVkE8f8UghyS@5_y42YT6k}Z*u!A|ZN~KVcxCrWs@87Of9?cZXVIEM zn@E`lZ}EU3sn{dcQD7vvIz%51*yn2X2-nr-AsjH{cz@?E#&2gOmNse+{bu}~IAqgP z1;N9QFZOr(EQ)k11J;4ui&sVw@)nA|;8Y4ccRx}S$4DXf$YKh?rlNokPcO-jI<&f^Al^ug~65_>ljivi0 zjzlp$|C`6^vH2_ro*n!&TX|VK!WNVMj*qt7>c?iu`y2|$E-B7xWjsH+H4M*X9`Wky zeF>~^8V}@-jC4TDzQbe}T|X&o_$SxkJd+h(Hqb-nfod$tYE!eEYm znjm&p31qohy^6M|(>7Gb!+LgImX5mYpt7OiC{7d_d&S^CLv*XoKQ49f;@BTmV2n|5PSgwA|&|sqG6JO{yu z<1xjoe^Vc;!u@m^I2vMtosW~gp;AQzy%<+6)$NKEW^=)V+f~Q5XAo;t(MMqonoJGp z6+4VAm`~AcDJY1cqyVaJ^=2f};%eqI59mF%IW0=YiuY9!NS!UKXjI+?2Sy=Vy%7X` ztTn&6@->$Z5fpJga|JH{Hrygi*yVyh_{|etspBJrchKo+rog{%^N%Gu4AYH@5ByQ3 zet+&6Xja6taFbv@S`ZyOxRz#|3%p|^nNMd^Me0k`gKGUYvRc$waoXn&2;9|;-q9yC z<0&s+3t^yDVM@9)-6^|%q$__@w40E|--zfE|3^wvAW+U9d}3N}%09eT>?@lh&g>V z*a6d6Np?>G!eouv(LHV#0>vgs!S>xmryV5W$#)|KtbftrMUS}GS~=2h?Ro6IjmPs+ z6?%Z4egIQdkT)TR$7-7^A(RAV7lf-LQ4L683!roN#utvFFIAh$NcuLfhUL${{pWZL zsvTHE%rSMDH8IlwRkmeMQDzv9oIT{>}o1Ow_jj`Utv zf3k&LMBbId3&-U*%}8#>n9eYTyC6^q0B7#>oid9~KqzK9hs&Ybd^iTMpsZh~i)!-D zQ0#&CjC-0&RK;0^*{9I-JZlGHwJ6-sW`?>4k>cZJKhQ5cl3Qj7z$XJ{17AP;Ncwq~ z$R6agxkEXUp(u->Kk#v^7deseUmNjRiXAKatIH)z7%}V3C-Cf~&!^#2uefPC+9H1e zkf4&9kk*C{8z)r=d>kQYA3T{x34z9oSbqS$FRF#&Oni~;Xvgsn@0Nbv&0W|SE3k@0 z@YXSve`6+O&*C%d*f3&p8C0dgDv(YK)Z=|x;zT!YZ+r8JAX!)D;4RDMy9b{MjXyL0 zfPXYAhq8;>y6io!-Risd$ zc`}v6vYQX!!a>u>5meH}gF=VkFF-Oam|-(q3lWeO#ZKrWSb@qiD#qz;PjL#v95-k9C~5DZ1fgpx0l5 zET#o}=fj1C(Kh>j0be@VGrqTj7`7zmXoDz<_1@3RTjVnkq(*3twN$1AvCCk-h*!y+ zc!CEIqtCqIU0=dL_#agNf(arlh7~RivBr9pnKXPu>M6GK0^jyY&qRnt78O+#=Ev_*Ln9mT>pW)@x7gD-M@e`({Q=DRa8EM3-DLM7sB(4ctwX+2;YTvtHzFGaS{x)O8|M`59 zAcTr@-m?Mub*eR~%+6QOQ59-murOA=pQH>%Ym8{9vil$1PSXBQN}j-7RyZCUA{ZVG0o{SJMG+CGY!)NAUd zWvno@XseOY;qhu7e$geBt0xX(JIPZY5278l4*vpZj=>-aK(fXK2h1IbYm$gm5j!L% z9-D1m1mw%Equy+e@IbH*E&1G$s`pvLqG-L=lR!JAVpl0GVO%KxkECybkE*!-KQnV* zyV-2+ZbAql!rf$n@DOfDz=#ni0TC2+K}3v7H$X91tpR)lYu(ud5G=|fsAy4_SEUwf zFj}?6dP%Ti8%?yf)k^K+qiRd*2GH_r(f+@e|EHyeJoe6=InVF;o-=x)3?Qj)xaWX- zBk4_Y@G6J3mmegU_boxYbOWwUOEq6Cl--_cBm{yBh8RXeGvr@y#2r&kI7h+sZ?fxi-*o}u#cN|t8 z%F9+#4^}f&TY|Ad8Z4MyO=ZQCe@e@M6Qks%*beb&CP+?easzYDVwFhLZv$M`v&vFR z;q+~5MC;j^ac@`=bWOX=&BI1G{M2UszX82S8<$d;+X2zVYYynKJ&0XpT~Spqp^>xl zx|`6@zi3^nLo@k}Ydagjhbo&EI`IN)8i~y0l$nFaB5?~64_i8P6qr%e4 z%o9ORG#%f9Z7kaSn4*v};By>^eeOk=Gu-siPyf(UCnLYnegYlXZY{Z%_-t81 zdb@G^rx}K}M$ZpLH0Fv~@ml5?seH3S% z9{6WUE411;Z=*Jw8uMSe`R`Nhh244B&KP1&XplY8xVyYc3}SvAw1g)|cTOckS$+~< zwmd*h02vMD1Ybi3x7o6Q^l_ozLrI2?$`HaWwwz#FSRw4sbe?EBc=80|c{YQ+Lpg*T zr)@RK1K@I&tz_Df8Q9rdPJ<|k zYTGh|J?d|vzvi_GGy=&L-HXNCgJ|dN&APjN$xpu|XD)R0#bCxANRg|Ve_o7#rpfNq zOM5OXx{xwgdD6~s_Te|T;zhb$XK{c*y>T~r-4ijG$b!U>Z#1{s(H3jYV8c~xLFJu2 zIaCvD%k^>1JiFn~482Qxp#ZSGW4bVs`ouaKeMn84o5#|jw?lFk$BtHh?dR8wFtvsCwj_7D2yNG zuMs}WVcW>Jy2gMdJS18i`h`jTurrIWo_GnWUdSf49e448sE`#RY9uc4EBLT9OPrz~*ciaJBZ zo~S2;L3H!?eG>>{10g;iQwG>cz>%rYX~G*QynBQo?vpTkXE~cXMHx43}MC8WNaZVWgeNx z9Z!d_Ust{}nSgGv3n;R4Jj;wseK&*IQdCfToXG~e*V)X{2o*ds()44NFX5Z9jf-7u zy~`+v1Xk-JqRE6AoG#KYN#8hsMF9jSOeGBu(N_Y^m5boRleE>%Fp)F&yBdo)?^ALg z<*+9;Z~+EF>GZ1qGB%Co#Zr&L&W|QqfJ3xc>)%)wePT+aVKD7s)cP-MnLQCvXwJJ6 zzbrO?m-av-iC!8w&*haQ2VQiw|1t-O1Ao)nlCsO+w}dD!DNT3v=jO3I3Zs5<`+uHyIZY+++}_FUbppQ#8xgI1|x0be}ZK+-hIo5@NaV=S`fd3G-!5l>`Fs*5h4Skp9&;$_rY&{ zB9@p~jac`09t&4KDpIGIO24#C`N0iABPAi5xeeKEGX$fSIqkW3=>Q@g8Lmq{dV zd;!_&Dq^{zSV#&}dCGtjhF4x*ekE0IJs8lwOPXdepKwJ16+)*Jt@+)(=W)B?W$ym) zwOk>oMQsDfK9ew740FF0GWuMTq?K;{nkR>a=SY7vT_+P6qTMc^s2#99KZFl7b)0T{ z1!FxtB02txi5F42U_w5Hvy7Ka5tZJo=h0b#Q`e+szIP5hAoy9W+E=u+gaYYlbCKf( zJ=g?HFRJ#Mu~~_t^$&6SX!){G9jwU%h#DWzmv9N^Ti48T$Zeof;t!8urFW|P{hJ#j z)@xMy)boJMpT+CLgoL%7D%Cw&VmrtFuEAky>>h`hq#R?%_{6@+4#)^xv+W}JFFm2v ze^xjBcUt-exL#6h)lOP=7gjNL`z^S0n=yoYz@ zdVw3V0Zc`4nrIczhlQsc0JwdeVgJ>5H_EW*(DpWDLy6$eIVNLd1AH|ps<_eHdj?0g z_c#QIUDB{ViA2alP=k~|s7h7P7@b6LUrlZL9%NqJECD=|vC3A>J%PXo7-$DlMWCdB zG@hXjO6+ysqU@1Q-P6-;818@$2|81bF&K{1dpDD>@NKG$<;~6>61XtE7WPV$MSZY@ zez=YP^k+n@%KedUcm0#yR$g!t8&Ee^%lu@Sg3TE9asC-JS%T^)ab0~r6of&dHij^V zyrr9f(^zA|cZE)bpsQEwT_XS>!62ok=l0UqP3aq0ml-UmrG$flA${NwUo8g3;W{V|QWQv<=7G4}>-~r9lj}w7rXM`dClCB< z(GFDBwU~Gk#4*H?w*7&?MJ{<(ugClSF{2|=h`h;Ut9lH^naZ*#)Q;gAP$}u{V*p~b zq`A#VDx}9B4#i74+;C}q$eg}v*1(-qxxA;re_4JYSSccdPPhscHg-J_-b z2u%Dqcygx5j9rf4mpys+ONClw2xh0rA|(Ep5CqrwYs&E?akb6?ZbL?R>nGeDIeG4A zz0H8&Ai%3LGt_$gd2ILjhd|MezXUA zK8#Dw?{+cWViQ6h05zAhnE0I$aM7!?LpZG?hwv?_uF=ahD(MNKsxWk9kHNnO+XhBv zwqFwcZN%1w5@O+JwFrD-zLaf`&V{>jR=jyHgf(Mk-y-c3qIC&qBfNV;VnEQP7kdJElzz87vX3!YAmR~Ep#6+N^BTr ztVLJ-(z2%|NmM=}fhMDpPq@z70;NJ3uwi^(rC9kh*9iju*#Ei~+wCTG82Fm|3%dJF z{t!9n^r2W2VsF_r^0@n|KEo|ltP*L9PG%eujb`i}hpC#W`Ew!Z+9c7nkKjJQu+{$h zPE|0wZqHk=z2>Oh-Y(O1aYYM@dXo%vP{z`&zu_;LX( z5>N!_6=%fwxoJ0j`t%k z;aSqio^(C#G1w}i><8u`3T#{|6!qeL4mK3E6HDBm24_a!%TkfvM*?hCf%ryWSrk0U zY=&HL%i1y+qG$op71WsPb`yuh+Z<v~`v)KH(r-L)mA-7i!wHoi-=wz#c9;|&qYT=($kiskE zHAWK&*;{Jad6W)*Y@9GgL5`6NttGmeIHDs!5sr0~vPc&2G@2gVwbNQvdrC?u$!x9e znd7&i&k0#`l??-(OlV=um`O%(u~xjlohRcE9l}>)q5I~T&LI`n@id)Ad3GeR& zW=>SQ7a-Rv=-6B}_S>tIV4OWv{}K`ir*K{(V6L{$)dfR^duGsCc4iiUlsA6~y<_2m zZjwMWapxQ9LyRH(T21&*xRZ*RI-}}4VH#1+cBvTRUcspknlqKIc8&ffuTQT#J&6@yk#tD<+l7YMSFK! zO*Z`GE(@$2Ku`N_)9A{==TwzT;euWTT>)lx7_1c`)z&+X{H!o$7d2ueKaJuH^*ZmwuLyqwb?bK+^vE@=CC7Ty2Hqh|uUWA5`Vs9}=2Mx+uk&IF3 z@a`GBh6Yb*`mI?0_328loJ}SOMOS8mdk0{Eb(kzz+BE2s$_Oce0BZafM z;8wE*Z?>Gg7SV*vfu1O|pNbb|W^8(=k)SYnKH;6sIsgbgliPPPj-1PtEfI2nRH%PEP=Tv&#m? zLJ@ZQku0wMow&@ol!~$UZ4NoUVh`YAWfX~ksuLYaV((Q1ny}Wk4^kfd?Q%Fw3hPO~ z7KLaq3Che;h0qJi^c`9bNW=3>sc`j99xuo7aek6@*3!uO0!%349dHW?rl>AZPhS=9 z20G1pB?=*21^@f31mYjZ%>e%&5&@pW@o7lPPzo9h0CukSgCF)DOrMiw$eQDPgIO^g z0n-Si8H$3dV3WydL+v=HteSetf^7!=n*x5i6-{>x6KVm?pe$rBp=_MCdPHNw!R{!f z!H&U>FeE;1)!IN9A34UAyt7yBz|Ry=?a~?+ZM}oJh2;F4Rd!^r@O={wGtTqnNkZtu zKE{?wCZ(Pg(QJjWwhW(m7s1ekv1#y#x6iJvMzD+I43%TmV*f1(0xd%Un#lUl;MR|(ci~FM@&FsL;YOMiDKkig_CzG?^i=x**tZW1wGJ$8i zxrH<+1q;)n(g3y%kb95Nxrff$ET*l za5k>FKkE!5XX_JN$xeKU{=}6@s^lO?1OX7UM@8n~v8N?hF>NQ%|WQt_Z27~GJHL&K$ z>9!L&c%mKK4tso!wgnYe(%HxE=Rann)_tq7DdGBKi17l#O}FkTq;=SM8WQ5Q9%eVk zL5jv=nHQ%fjp$i-3OSp+Srju;)-0=*5E*Oo^pX=4{O>llk_Lnwhf zxMEcUt_DeW%!NfD?TcE))S8dio!&)NTX+21zd&$U3wnF5V~4R{P-lVcz=yf=p*Ts8 zv^tUwZA5H?>(d|>2z#IG{!M#|E#z~il4_#JfUXg0?)9aVggD_!5X5qAdWP7&MKCus zv4~a|XK|@W9zZ<3!4C~G*swd+oq>P_H;B4Yzv4B;A-)jfoxS_?Oc3ck6v5kDO!IP* zq`p=g9J&_Gw>SyWO9wqE!2c0fl9cgrGNCH~Lvd_yjwrVjV%VyK={*>>e1I7N7X1ED zY{)JMvJd@W^aD_x4@oNW>F0x%Vy&ovaVmh$JWV7wTOCTLMPmp7QHu?Q>~+rIdIlnI z;5p1nfa2JfrqLliMtAKd2ejki6uZdX&76atiRo$`AF+sgTAK_CQbHTug>F_1P!gxu zpkcf1eo{3PT1#<;oyI~!t?U4IMx4cazTfZ#fc)3>TTMA#{6?XhM|(*OIR=d5N8r5O zBJfcz(1RAC%9Knwg?QzOEN08mA_GDpbz*yt^cXaWGSlA2%hmBY%Qu>Q57h|ifm|o|;8tI*SLi-&2-_sA>5tv+@ z#1wF*nROG}P|h|`>6U_0m$>CZRcehzF>80Jc@h_aA}&N^UsBZrN5jmGemM?&6AwUv zW?sx^(otOTgY~sTS!$AHMJ2SWtr6Le0mvP>E&o__*?OA8aAp@X)WaLM7pzTAq?(;* zkkXMZl?Grlhu!SsSta@Jq!?5oh6xn9U4k33p%I7=5y&`n+ylC?`S*W)hQ3>mkCzk< zlpco=y};S6<`%}Kp;$WI+OAdF@nuwH&m0gf<&#lL!wgQyd*tMbwl(B1^+yAQGzPL% z4o8;Xyoxi#zfuC+vS%#{r06P|w~-w3ehm#xWJSHmdU!U+kLKmWV>y-~!jGSh6 ziDo=|9KkU7`Vf&cYh6lFbfxi6ELLjr1?DP)R@4Hu-6C>GTGQHEA}R~zh(59I^kA{& z0Kj1$(`;-&H1>%(6SPj15{!Kpm4^o@vEP%`S61l}H5tV-*F)&^BJ`w$tB@xd#(5xJ zKWPQMK zup_lD8#MvmrY7`7?<~`HY$HYAwI+L(oia+bII~+11>GqR=I*7@T>cGqKaqXWMR+86 z=nw*j8z0A+wS9!ikbqX!7%RPfM29roB@(s&sl^z^=nnF1N&8JG{_2Z%?*z9XXsU&{ z^I-Da90uNjfHf2(La7{aXf2B-UelPC;#F;-I|5=G&w%K!9h!BXo_G$K2Ks#21bLYr zd(}+tjlOU~Voo)K%7R*tK+upwID3$qOh&o?VILg&|z6NdXuj7S!IgtQWIjr#ktQJreIp1w#NKyO ztdu)v(M`MM|Fj{W-LJW3030zpY%=wx5x!WWTN;V=|O7Qkc~ zP7dEpE8Br7FZrer;X_#oN&G4`;~SI%s9QQcx}AclhaDRV`p*4IDy{MF_t=tWGMJK&yXNpFWIyFcbnM57 z5NQa+qTi<7B?50?Q6iMT9sH`1n-?LpR-qL827wHvGY}{$DTWBxcfr0+y&2mTrpC5j z2Z#nZsh_x84NP1A;ikuqq>e4fT#r~tXkL8lpOEuyL( z=jm9E06IGkL69&yt`!?bB@?6rf9g{He3qS|^sHTsj*F8~_K;JA)jijipX9p<)$PjP zu&PboQCv67-m!qeRrnDQ$4Otz^5vA8wFw!hV%RgyQ7q{vE@hnvFCzAN5lx zgBmGu$w(BON3+ZkKi7NzXO*EGtGvDwG4Wi)o!Iv-qN0Csh=TeqT|Rvs3`m=*9&1wsqb-Ki&LD#2N?V8VU#DTp+J=RH^M8J zJg%#=*jq_k3HGCY5kRHi|_kAmT;es9oS%a zNUk!p2hIP+Ed?OLSXQ<5+#a5LH#~A)kPr*8%0Sk9+#Cn8FQW z^${$`Er5I{vf!@8zvi*h<1L~EHAYg7tK|*By7%-GzkT_`SPdLy6pP4BpsukQl)6r1 z($4LmtL-W)j5|agd_*UBE2!k`7V~fhPVY)>&{Q_g3(WU~9m@oRCmEb(Ns`P`rQ7?E#@@k=0HGjcfdzxB zp~WTDWBc~9_<8QtzP(s2sqrIq)cc2@KST@BS#}uvce*S>^F6p_$G4~fODjSQYoF!IxAcVj(uje!j!`F!9MJ7^!7mY$ z@=7LK#QbzCYQkWiIexAON7JfD%aOAkWhVmFL{&II{+W-KhLRqmTX1I zMper)$SJ7N>Iix7G5SBV(!fnvQMin#a~yT{g6{YHl|=BTL|Y9-l)yq%;QeOeY76A zs1P1y=LBNC)FC3Rg;clO!^{Y$1l%K_=Xz395_q*ptLil2T}+Ys2dPpkDYAf=G~)f& ze#z15EO0|QkT9oY`4Gdct{(QR7VXIKNEryZPu%`_ZFcwBRGb?RTqN94YSEW4rC1Hl zK2c9Ns>cjuPFw4x06egM3ENuY!- zH*9YOIqyG&KsZIl6+brYkvpkU$!Qe3Ywn$X&SqOb*3dt3tWo6=20Vt7u}K1uk3y5h zP!ZwB0+U$~RuDVu=r(GOn$;h)edeS`J9@^O4!`o>0BaVQe89gPYe*Ns9|!pW6Zcxq z``r-rA0Xn-%&zi&+_q<{k(R z0&jpBkj4TEz}5beuGhuOg1t;vvBP{*Pji8-?PhlKeu`vY6Bk2Av%tC}CD47~-2Ook z7;bG4bONOp)V)+0ZWxQrdjd3rS=twU-NBQXLeq%AD_3+9X_o^#3kDnv7xFH=M~mpi zmN)~!pD?I+UAPYrKNMCFAIzb23}~g}WQ`Q4Zd}S%c2Ka7lU@**AB3>vLYO?Ke+|gi z>^y>bL2Ywty?yBv0)~E-ElJMxY5f~8eqj(ijHq8Rb|?oE--3uFr0CH{~~uYIR|M5 z-|ykPimkiZmI{4Ns@BU>*^q(YdIOCGf^S46%mxhaB6rx$^7#9_Jg7-Ll3cL0o&Z?@ zC>up*ZyAYIkI<5e&EN;UM@_fjq?KdNq`pTAOl%0p1PnjPq>5kyA;@;2rczB^b>HHU zL(Xn-HT50x6)|t5+QEjTiZv^0JvB_B>`4GTOYR6vDWh^El`(~_U{)8m#r}Fle0j;% zC0fn!>stE6&^c&2GI<{4R<#NFQ5t0-i-M|EpG6{{udwLnR#Z0fL$Ik~-U~AkZiT?s zWOr3mQsm4cKatJjhHyOoN))CYHoNu^Nw#iJe~V6t^9`I<#C|-8NqjOQ+r1kCU25bH zJYqQ*rTV|>R1k2>sr?^8QDF@R8(jeGND+JJsHZeN;Kva*W~}y&)+%e=(FOEg!946p zpml?or|H3bX%pE+V{li_0L78b!960qbtedg$^m{6G=2|*LJ&wOHndfrp#{=WDBA?{ zr0x?_?C@kH1Kd;Qa|5LNz?-ekH)obqUGN-$|r{d5k?ezb>-b-@B87&EJ@*W)b* zf>nN9#~ydon8eGmn5u-i?440V*OWHoi!N~W!n^~4E_rog< z!<{ZK%&$ODa{%Xyf1jO7Zpgh8N7z`MJW0SHleh)&(_pp~mZhWnaOjq7T{?{ktS z4VF^KbtagYGmUphVw^3O>z5qKpFe>}<6OYTbMtUBn8Ss?V)I;3RFR6vE!oyao??-v z2cDsAzc`2tFw_Qy1q}{mGLJ@c~dc_#Ye2G!HTX0yd0^ z4l9g7YsUMlpYD2PEwSHZx4QTjq9_L_)Hwh1qH3cbbd$$7c?kq#2uH9-^=EC7pA^}j zpgEA`xvF&&i2HHK77ZW1@H}rQ#pd*lpq2?p!$=@AYQ}_88zBjE&l2QrgA(ooaF6UG z3*hB!pV2TV$!M;KA;1qZhogXuuw-bPMp>~u_H-RrW4ABt%azmA@0V$Q^1?kNxGpL6 zUDhRf_Iny!DC)>hvTi>wqI`amOT3d#3`N8w!T)G_CYa5DSoR+e?_BbOxmSVN`ZBG? zOY@#>UH&8|Cq~!ud?Ca+ymEGJu8W2tKT?vC$dAw~v9URne+doSJTl^CkQuMQ9?8ia zRJin?IFng)$iV$lfb4Thb z!8-UQCsdR)QUSZL=$$(}Tb-akVA^j0;gy5PN)ZU<5rhL&s!$UF!sK-zz(MT7_a*(< zg`-mo=~)d^tCoW)XkNcp8rel(_12-fEMmEpQK{(oi;qkt5=6z$r_%^a~ zk~VpY?L?wPG)oeQcvrXii4x+zpJ8R9>2`gdvQ67%ck-8>(HKavdF)*!b}1gv+K7Z!~u`rfW7c)c*YSw-{d*~_ygR{PDJWO<&0e=>cD3nua9;hurelF zZm|I*od1tk+M$^_P%1StQ&5`>?YzET_84ju;2u=q3eKl4kwYk#fbS4jUWoA4(Jmt+ zNEpW8G^oR(JABXU5_m`4Cg(0{)Q-gYy);ieyvePMv93%|<<{V|s$)oWc4k>F4Dd3Y zrO%<~BJ(svoCn9TWSCTSbt;{|aihu}rM9@CkXo*NT5kleBKZ^S7#8EAwF43o^r)`~ zx()>04;x%Xh2WIuI*8psjZ4XrUu%s8BOksEw38p1ReAbY2dKA&c~|duNBMDw{%=i- z!KG)Y9i&Q<`v{$pVm@<3it2=I-^_NufrnY_g?$K?I8D~`*cP2iS&}4@@&>2(eyYj4 z^oFr(zn3QT{*0AY4GoQ6gA5%P$_}DzbFPBbP=SXBh_dL(rpaxDAr8n#P6hcTkMy~5 z$A|1}&{8hM=5%BUoo$yv{?`~w*4hZ12tBTV*mcKYJn5;I{&~6;F4agM@HD*5v8e50vF-QbS|Rl$US^4n@nBqY&nSPp6Tdd9Datv&9oup{aB@O-2$~ z$D2xyyH1Y*H7#w0yIBJNSN{xMyIdg*1+}L7L9%z=5qLWZ;VP>df;UMvbe$$K(Z5#_ z(H@;+MB)$mD%pZsmL|N>Y;=)*j3Eiji!K2<(JU^zcu6&d{{7sBI&wagPmC18kq z7(i-AYd}GjGuLM1C@moU2n*0mGkXm2I>Ii70x(Bz3F^zhpP#&ssHp(}3t5ZKp(Iw; zLro6ZL(qhnr1l(Jpnrk*8*bP}dG9u<;&1XW?jGYvHe^Y_SWqQo6Fk?cA}Tg&nZmHK0Z|48zBO?2u%cRt z2I31=>G{;->QR)ygkYM9f?J{tS;vaY8C^uB)mQt)?qYMRK7dq}R{n)DYfFTO`|=#U zVkXg|pkvE%)B^mou^t^Ep2s`RAl}K6JGN<)c6lMZGIn$ua~kNnK%3Rs`R9U9uxf6M% zUHy?Z&spQusuvBMW>zAO0|d6oJF=R)MI=v<-Mm2?g~la)7t5zx(ZaLz^_QLxu!WQ! zgAL;845lj%%tXpUJL#j+<8G>Q!vzH=0+}F7-VJ#i2eD1JqHrXs*yE}V)Z1Y&=l%>G zWBFeeug2k{_m;9SrLZZ=d;*#AMA3q@l}aF?66sNW4K;#y(ettHl&Vjur2xhhgKk(E zK)8+@N1@*k#Z@2!4Tc>U!%{gL&pGbdM7c}$yRkn6XuNq6b_CWU4J%pSfXHtaVi4@< z13->YjV%)QJ?u#|R97NUtUI5Iu^{OWG}oBG>AZ`f6>q>$)w@W|3+UQHTsPt8e28G7 zFSCgpyi2eS-0ts)cZyO_TRCIarr>-g6y^-Xa-*VYIv^fY} zVfxz}C^$|;<6lv6rj~aVDU`y1Z{2#=EB`@}N3mgkk%t4@O|!1)tv;+r4a?l#YnUB) zj#e%0>Db}fQ4EBig&8w2#3^<=6HK_7r(S;5SW>n4uLE}VfKGbA)^4Ea|9}%9q1w!r z_;|17dw2}zZS9lr5(0*lq}22*JZ#x;8X7*p4m%aAj{g^hX8Z?bsA7AFkuX|T)T%x) z#_cU*>Jt!ns8FG%5|PjI;xgROVpdpNnqxc>eBO8(NCT(S|e0lm|3G)N*7&a&CH zS)>9zMn{zGL|{k9g%LRyD2u8{ab9Q+v6pFiozkrkwWSaJx=lkog+Jg&WkUI(@IMeB zoEs_Pv*ZrX_nv6%aPT#Pj-W(}jVMIQ9=O+p--f|LGfU^1ZWw`QU-`=0e^A8sqiHD3E_pmN0IP#R7?0w`b6)dYK3*p zc=yQx+reCvYNU*Imw{B0H#H&DClV;KIMs`;z_SoRW1Qr=^VjX6=Tx$UG%DYK+uqRZ zgNV1cdy%R!O{>UpJU$|A?H=p_hohTt}fj zVh(u@EG5~h9sohfeK1vaVBc4ithhgq54nOI#{l=^S&GE}iz*R6>fy~ygu_m?seG`0 z3#_OlOelUTKD`jb_keEP&fv@PRMd`LmCo`H%SltT6AH!TJnFidxuG0s6%Dg%Pg7R< z$tiE-q>quVV2>zC$EMMPK=HN4dw%#v?FQD?i)adN^CY%K;@1V9F1k||4r`jUC`~ok zDvY79u`w_zGfU|EJf_o8np{fuZ)xoX`1-I}az9?nd6T1(o8<%gp8hnKIW|qi7P0%e zz{jHpTe!(``x~l(4S19yhbHpffUAjB&=<8?s4kxt)Ku;e^L;5h=4kY*Id6z$CZ;JA2OHeRD0B)iIR1Ib-+Jo2~#%aZ74JM^!G8koSX!1MvJojfUxRI zH{c4I4T4_7K#Je_jj6w|${-#Ho7n8d&mfsas*BKyH?Xf#+OU+YoEs)J-LrL@4bfj?@P}9LsQ_fb)JPw zgc`R)Kz|?{w-I356?i7n;2gGX+C2X*9eSF_9CZP+W$G_lTdrrUj1OqoCm4YeQ{XOqMwCk7JtQbIbhFrW}Qyd=OLtX!E} zqpyTG1<|ZH1{v?Pxw$=j=weWQFnF|bHYP1d8{7Xp_&?1ouDX8BjrkyXaFR6?vr6|f z_K}v|o_Wz#h$zq9`K?yt&Ft$jY|M0y%+i=w|MKoV{e+a6sr(b7@{Z06+HeNa~MH0g-4hH6hQsar?sOI&NCl`J~6Lwlk17bHnKw>qP!(-s)tT6 zdCY^g2O&|-51qJ`XuM9ZYbrEm7J>9-M^LWO9f?_|uC6Axq{LMf@%EIguuANyID!gN zo_WGA^p`*q9rQh7!r6HD|4=j1vXI)DR;4=QS}sF(V$BFh|5FS{`6a%F5vSod7^x7ej$G+fNL1>Hpr{Ks6CRmPT&ejiZre5tcP3= zk3vtWE|mf$!$vtMnqR~ol)$fv;X1rOYM7`rnt+2k3c&b$pN4En1NVbrh{{anmWE7AF<;XbnLOeJ@}IrL5y9d5+_`^<$R$Qo7vK=UHap4H5*F==w>^l0`RtojJQ z(^7WEiT5)tcxqI0gg2Jc?F@`lBRChcBJ_G&BhiuRF)iL_2ZcigC{cbezWRiHD| zY;4ekUk1|$J@^vU#p{_3a#G{Ve`vi8Gyiuk57zB>-H$B#p@FdPD;ffGp<(7@u?JuN z1fYEJis<@D`{%VO55Di&yIU6`;DueAbTO;H=kD?$Mud(Sk>|l_yF6GMK!72wir|7Z z==udF<#QPFmX_mZyhZR=_gv|bpLYV{(oW|bS}9(?r#nwch}Cln9w;xscu68x!1M-G zRbls&h)U!4{upI3o>Eqtor<6ZNI!z~XDxf`({`3cQP3|pUG@0Zixz?8zxp3NxW1D| zH^+n7xK9HZx`}u5XUx3?sN|EC?RGH<#+i`+Hk3mtW-VpIU;j=4K!w~L;@jU}ormq2 zS$gQ5uUSo>TlJ3sEe+&xtR!(mO6KEuKkLbf^#egys3;tOx=K4V3^orv-)v6pk;HGs z37yF-0O@)bRpAf*H$cILmDiWwrIqwP%N&{eEcCXh4%ocg3Q3wk+Hfkq2nbYvkbVye zPH)eSLkF4N6)3dP7dL>w&wO^9M%mu=z4=KjWwW(~rS=LVDuL#)HWUv{K6Uck(*|cN z3Pr1)wIS_vm_~HgA1m1X>u2%y;k({XNn{teS|ZjeZ#A6(QF5m7GIBOaS+8exnuzoGvYJQnx1*==;p@FMmBiTr<9So?ndkQhh0G^((D1CRecq?Wnt{ z55sohMBbGXO=o%_(&q?(K(6rm{$TBV<)WMMl_f(z&R@v}X@5=1anQ2XiF6potohj> z-q_xGfQ`Do8KhgLct>ChG&CparD7CL?Hy@$U}(jM(+6azZfvWzg=K6+=dc{qaKIcy zq?&B<1q2cV3vR=b&`OH|MOToM!J(X>ERY3{_9NCPxF6q2Ik@c^szGI2%>V6xJCh?1 zor`F}x1h6G+f0f&;8465fnR~zE5vz^*i z_f1D(jhv-7U=CXwmPouUyAZd@Nl3^kZo;OKgOxbVh`*3hoQEon?&9BhgvoJa%Nwex zVAYjJ=v{hS*M~j+aVy^Jl7>U?OrSv>DFhC!46nzeKMVH^;h%r-9C)=sX*A=1g9F%}Rk*gBG2{jm>-S6r z>nHGws6NpJ(ZheCk(mp~8Ho{f+EhvEJQnirvrbWXlBvo`zp9-yY`;JJb)*1WyI1A{HimOeaXxH9-}B5rY#V&Ac4UJxRKisBdjbs zlY9F}O{3ZdDk>w@ixWbDxA9w1GU7dqhBSCBzhl=ZgA;eKu z7eG16?QaDb_zO026?SJ(Y1>u2svf9K5?=e5ZC zc!y0z17oFQy~(uFz!3R&R@`IpNYyyszgrKFqFEIbkzmiTsvPYA1q9b^?-YrO^OJo}nt|kbg;2+P zZXwg;g%eF`W;4rxEWeNPh)9%l))6nH`DHdF828;!Tce+)T!HHY_n=k7=t!-DupbtO zvGJ2(C+`YI#9Mrx=2X<9C_V5gIiE>vZ(olfJ*F>%%>*MA!3IYvsp=bHPRw)~$!IKn zJ=J8L)*Gp15fFAKSScLE&S6VtQWL7cze0FY4m;zcY5bBg#D@59C+)o94H}R-5hDIIlQEZANOfHWCHC~lP!BFKfaO)EU)-2~|;EOQ0#rX-( zb82l=*yR#`Y^n~;e-L>G6u)|`(H@|z#Q}?HdqkO8ra}JGU7U z!&jC1 zLtpjOhE+V)3PNVIEX~dXuNAzRhsI=YYUh zQud8@9xCjZP+v)C{fg|pl$F+pwGvjzF>oeZbawVbMSZYu4DEdN)icn6o}T00D+a$r zs|@trV2$qOnDqpeiUyG?v?NJR6Ehl^Mc)ZKV`|PaO1H40ub&){S{*i3F0zx2jT%gF zM0{n^LuhoDV{08(Pcah;=)onEWZMf?!q~%3;ftix;E-CNGZjz=yfO0!j?Kh6HbECh z+HmzDntn4_8-V17^>XO<=lCo1^NAgYVW3BVsHD;8^Cci5e3oKxjb}fz)C8{Ooz+S_ zXGAJdx*_BMwt`~vYjaRcPh7ITvtc19UoMt{2VpcqU_uDeL^N;~@b|D*`~&l;@Wh0& zfL=hi#~^bDCYN1?nmL|S#AOlU=5g@srQo*nYEoGcnGo8Bw?aix67Teaz&{CFS50u| zYypf!HQ9dGXclhMr$6W$X%`T=U3(T}2P*h1h=oF;}T+y5+1u(Y>hzxT3lzZ2?iOlzya-L1)#@0=3Mk1;_@hoXUE z)pi++(kND^22RxH=*zY(pnSjn&VW>o-csw0q1*B4?8d`efxbLOSHam6=B`ZM zOwQGGnK`(J1MBk<8OnHXZi8R6}V8)9W zJ;|I}YXZ4;5qc|a872Nh3arb6oCJJ?u)9PmeZF&eWSnR%AAcvy$lemhHXMoo*D(_h4^JcN6bVaU@A z7OoskDpXE2Q{8j%tEZVW!;{p3&A_QkH30|%YYb_wji!--am?0Gq5KoEN*a4JC_rE; zMsnCAmd+t*N09gmyJ{WI*wR=Hpqfr{4q-$gr9l75fwRPu*lMAPKo1A7dbYdTPK zPL7@xXP9S0L8p=b1VUz0uYB+_vcbjt{g7i_5_Hl?7?`vSsMyI2G5-U?%0 za4D@EfEOsDL|7Zuig+`xS5v}9Au7vF!}qsBEdoZV@Ai=6qP=Z*4W5xqn5Qvn=RG~6 z0TN4t#tG=b<+A!s{aS`X!biW-VnzJp6puNDqxGQ!A0Q<_S^!?mKiSoIPc?cki#C*_ zS)4_$nM6}dtE(Xpi;Oe`lVJw!^n1Xr7IqoF_zR=TK}$=cjjGSHaElv+x828Db2J;V z23jXqiQM(YNR{El9_AUlPJ*bJXm;y=SS?SG(Z-1hd#*G!Qci;$iVL* zw^~$+ktY%%$gs`&cLC9?eL4X>WR}I2rC|NW^*O&Z9oG5>^I?>SNvonD=%udc=a@cK zKTRk%GRiYa^q^Qu~V*(d9U?6q39+kJVXwh)G zxZ1NI*DlMrFd$1FfZKJRp^qJ64fu?Kk0I*}7almRjX$C(+SY~#xv|}3g+iRGgFecy z5P)G;A|b@3PuoU;#Uf@F7V_GJzROJ6^ScSfavDEN)Bs<b7(Dgx9XradBP}m)hou_#L>=v(>ZKh_K8-pi7)(z1>xUL=-qB3e55H9jI|g za~h?gke$~-9dCug=dRz{!1p0M^qVLQ1nt-BwR`#E>xIRe;%lDA#uLhC&7P0j1;F`tyn zwp^{-gbME%SdXXmaS;h$@F`f)Fnq;;JTf4i!mKpX&LM_RVwvf2L`4Dp_4QjDaA$iF zHbO=(#~5cV#bA$gYdKWkcB+C`CqQM+x9ZCZN2d5mLd^rbDn}8s(oJWnd3x?*4FCTL znQ-W3c#^9xeV~>_oF50G_Ge<5tlydK2jtk22CT{u*(bFGwmtuU!FtqA-wEQ^=!Iay zu{EmhF(myHoO9O2^(>iCg4G=2LQfSYF#m~CPfXD|EozM@$lO<2RC~2xd4kwq6@hxt z$y#wIIzo3U`BUhfd9!>%9rxNJ@qUTd^*oNz0(R#ZbP3>!7R)Y(Rdg7Y6pYyeeUI7= z1@>5s(xvw>o{F<`B zzwlo;XH*9qn`k2h&#S<=&Ahj(%qAsX~ zTCE$(H`c&h=0Spo#eK1Fq@HJl2fRI$Cl()(Fr zme*O}jrWW$;3G-ekk-M#q{~w?myf{+gdTDlAqe7mKVNZ^7dyi5)ZsJpjR&zs>=3rn$sc+_vPsDztpV^Neqyh<&=x4?^iJc<-s><6=;wjn=+stl6p{EgXw8^gG+`m3zl_+lN6YbMSQO)X zV0IG&VOK)6Eb58j;i%@PvQ{v!@Q|7BfhsP$b;pzQ?*ha`YiqxBU!BNU0C7`H5a&9dLa=W1x;PA9{-`96q=~9 za}g>6>_|a?r60pe4A$V&se`erc$i06iwzgs$W8@y>~uIJRQ@T1DRwP7JaaVFm!#%D z(Lz5Uzcw_NhTbv^m3xMjjhuwLqM-^%h1aPu__C$3nxHp*KcnRa937MvQv3+83M#TD zfxf4>_+mHb_Y$CdEFasfqkd3ka8*>GmD)3DaoD8;%+U*!qa&Cw1r1CLB8ucy6x8jvY| zOrUfSRz#2P=9g%t%~$ZSyIX_&=rJEEfFw2#+kzp;TaeWP$@MUxBuQIE@DjN0WO*9~F)~Qtzk%DJN5w69 zEfaRUKOfx;aRX-m17_DY)N{PWM;rGPs3ik#yq?Wa=9a@N4A!;uWX*F3z}JBf#TV6x+JfWJY9!O06kpmkT-u>pS;597e zOO6={2!axQ-Ig~Q(JU>~bVT*n)3io})2)9owwEt0{1$tc&o|Eu()icZ!1p(U(VaR^ zV+YKqIAJnr=5!#TK>bmzU><|%4{(~eHT4u;3M~)?*p!aj2GXwN z%8tkiY^p(LIMNbq8>O!zn!KZ9WN!_!L-0SeFbBwac`F@c-e1M6c1qr4{uY)O7v{oTgejFwpCBH1uE?;Ni{!oz%YRK!MEkAW*VhZX1<5>vi z0;bnkjq*XwWA=d)qPusYzF;@fj`Wm8U$gn6dc|n9a0nA}Oox#S+wtLTr22VRFBD)u zbX*;P`E$4@RT&KyO6bcT4TNIBtHm5e*C~vuxbB199Lc-S(;bh~JJqN^U`W}aISa|^ z=K{4EgQZQoQZe~GjxwFk1tdQ{Rz1L?uD41k{+`)7#wqUY z16QCAdD(p~z&~OlgB!VOUTCh-8z2GuE*GJmQ%FKz=XP;UM2^u3h5@sdxJ6)fd*xJ|G4aggc)oti+uzLnk;>e)lr+d52y6nbi& z7S(2>i3N;7eGn0Q13Kx74Lh-hiT<0fA+XI_!n;lEG%8jKq?FeN1BaazF@^0=95ayE z_VhQP`vmlJf#GY=*l@iZU9ohx))T52|J5L3)XhlTp=I8LIb-(OeQkf%%fx97A~2~{ zG2;CaFz0AD!Y+Bt>*=iF3Y|FGiSPCv2d_m6*}FwNnJ2n--}cTo0+n!?974pAk)wLq zEE9TKGhLm!p%M=UOnWIvzYY}GvQZx8Y&;9T0Aaw!p3Ax2y@{^rnlMGth>*aM(rmQd zr>3zq_>(71q$9>2Q|zpty%n4mk&*ZE4;SUSB~3xg2J*L+wo0?c@_fZ9Ga4Fwxk-G znXzmMxL2FZ%5op>KTFZr4EZ}KYrNQr8s(Oe@8$Qix36>WN0}s@#9|Lu3qtMnlU%Ap zm`p#@DB_dIu!v(UTtAc8c@W76>0zVh0`wX?V-7+muEErtbxgd_Q%%W51dCopW(d}c zXg3_>Rl&aR>$5$B5rO`*ZUwQGGWe;FNa9~!dmW=3PcQU1Q=094~b#R*+eB8=0YB#lZ`oCm1SZa6v$ zPyLGvExbJ`o4aqqOi&3BB}qJ47o(8**v*r4kqblZaua=gUL7310#@K>32+as zheCfRk_6uX;zi!IH;?9lAP=1ki4}Diq=Pp>Ko%%>(FJve8tOvMy_A*smi1_374i`R zPEN%q5t0V~p%#2~pqsKqAebd7?Y2QTQ8WsTc*C*LuNJ z+_dn$b68&h=?n}pQ;(GZ);I7eKad(hbROE0Xr(NHH>R;)4#Egn_k~W_iqxX!2T_cD zdzNq+f$JT+PV(T0D$BEJFuu#1B{DZyV8tZjoKlt@!PqgP8^|s|fBlrX;M=?c>By&? zB)O4dUZVj!w(MQh?w*HFqxG0eu!TG7&+oOSaS&Q%6y`T@{GgOIqH9W9V^X+w5$4Hl zbfWa**1BUk3yi3Gl;p^XdvV=)vJz<)qmmxuPN}aK+-Drya3Co|g8w9|Kg@pEnni0p zK&N2V^1sI+<)J**s^i~tmr&Y|m!7op+{_|RYcLF%nzcCl*kCN{eBr%UEe#q-?Emnc zM^NA13VA=wH8$jO598~I7q4PZWjNS@x#xdX2`fb(^U_cMN@8*f`5R{-UG;k=I~kW< zyjC&baQ1o`@3vwXKpoW!y7)z!gdKg|&uB9=loR8OtVJ#=M>J)vqjhy&b__Ha(JCq(>@&Ln(QM;G|$s& z@N8bghHYb`smX4q?H4*x-Q3rk&RN#S6vHT*N8>{sn8MZQ#hQEsNztpl0AzXs+yP&v zVQ&>!Sa~sW!1B>%%%In8u{NtF{2dMER5?~}K~TDR6~hRSr`=MF?TMpQPwpuS%jtZ? zaEVY=YLzgw^*{Sa>UQC!}*P;tP0;yU(*bwL*o*p^yTLos!>Q;|B(Y!CZh~O@hI)vHgcN zD7qE~X0$?5o{82mU`^_%Ov0q+tG0=G|Cx((rl>w9WS&NTF|!N8We`NTR8O{&gGO~F zwTQr5J;F*CzoNk%hgXc(?M7(8bOW&PJ%irP1+-WowXxoA2B~A@ks>vis*ln0?6SEJ zHTzUdDZCG|iL%~KpV)G^!{}z;!XRhKY`%X_82V+`g}w-osOgwX9q9DHD6^#$OX~`E z`3z+7NZrU1IHq~BSq38R@ASnY!(T3<^Zo&ArE zYu-NtTd99~5p$}tXMUgqCoFeqYL@ait3~l=J=lD)u04hh%_$ExE6jW+3`g-LO(1xH ztJevOC~W2vALc=Ce{8>NxTN-mW~Rlft^FP}j1DL#bZNgAVnDH;^ka!@OOK zAz^|&5alZ{d%*8QaNdDkm0*c$=+d|*4u|w(25hU%PHY4KU-f+@%TFSc&kfUhi5AP{T{ZCZ5bpL!VWpF@2syja2HFSint zTZws%Dd;D@(H!$cpb<5d<{BeuQF8#T0z(trQg z3?NoK4{Yo1Er$m}uKH2?UxBr;g|L;t*+MBLzK8Pr2&~U1d~*@Kv&I$FOemPK&3$0x_YCuHnkM#*&Yt#1 zKwh8nfzmP*LqG~BrSmNN<#kgE1Gcjz^|bWcEr(G7D*Vejj77eUUfPwdF_avSzJ?Cx z(K~~5gO2@PTC{{Y!ry$6xfaS;YY~1>zP~;__%b8;YkvdUxsTDMBYO2+A6v5qpE{2G z_ihMFqFn;2P2(AD2Ce>I-~5XaYDm?g-$YM)9XQfycIZ-SBf7wH+9-KxK)cI?U(uiC{>S}OU6VrnPyvCPIYrbM z>!vhyz7cl+PL(z1(O|xgSk?VuTrB+)qnrjZb}*nre@rbftwyR2%qI3j-M@g*K_2c* zz`Cde^)o*(hMGYAIPk+w)#~>@2jB7>!AzD$%jv>5ss2N<+lNtQZWw9pROwz$Wx@OX z`ZQz~YbeDoHwNWbKnYsau*k(o?$^J82T|Zj*6+*v$as?mK(8*engyO_{y#9E&&2l_ zTX7Zo?w~oAR|C=xV%M44rwq;MzzzBzLrHi|?|<9<0$Yphgn>5*c?=_7KI&KfsiB67 z2huQspQbKINn-%Ze}991Nog z^`!1%8txyeT+kndqIa^8z68aYL&1Gqi5V*47!Mjts6Q@}7|aY-Opmf!$K65;;qD=t zar9B>y9{PFABZ6o(PX?qVke1}U32jrhbd--ukLkNS!g-g_3PEyu}1} z1k-~!k>}Ac6ms9ehLy(c@6{(f%KrA>$;3^X!>!7NTG+aW zjw_K?gn3o)Nfa4KHF0!+fvyS6i1VFgm*qup|ZiO4ay68nHNg4YxBv77g*6Ss8qH|EB)j)`O_-F4eRrsKE(8UgC96 zwHsMjM{PQ*d3N?veyeL2Xf^*CAKE2>eQfQJHcW=TqML^0P^hSZ ziwgg^h6exXcHQd%vv#mlMwS$^7T#uL1%=(S214vp$b19Ng^yNdk*Cz2yAj{e^&fs- z!MR2EeZs<>Nj@{AJxX1N`M3flQPuIj?p*lf!BN_{!*9I#rEhS_FvF;|#ZPI7urBq@ zV(6;64{aNA3`=k?({2ABeM>AM5rL&%&A{aILetQj4FnnCLkZNOF&5S64RXhISOw zj4NNR)9oETTlG?2@Zpo+w;7t~Gm&~;iGs5hiX+ud>4lnia=)>yrU;?NbK4b!7`LjY zp1T@#fkq33d}n__DBQ{Xo@NQicJ`dRm1U}W&TCnXC9N(u(0`0(MB~y*$|_9TQSF!} zMl3JFR?Re0q#cdg%N0_7zu3m*#k}F}&&Tw)q8fI5-H}M%q!@|{X!Z)M4pypk%z6~* z(6^vm#C%L@^#cW*^oqMqPrgBK(BF~6(52o?@zU^+1Xf9Ck3(|Cp%jWfhv$J8!*V4L zzp{$bI=+_J+qWI!Gy4j{v~z~@4Ocj~%}^$3ds%JOY=CLn1)=OT?_V-c(;w8P6Uo1= zTCdv(dt?8*_|NqNX!K*!=eH#48fSmV*B)?gHUUdmeu3ZClDJ^+c|(7ZD*ZC$Zz%e3 z*-qLF7fW>ChhtkVV}Mu?sk=dYCI{4`8gnQFxYmDz&H6f%&q(Hg(#Pr-HZzcYQ52Y4e2WzgfB9HIJn{Z6-=!bC zp^Lv;Vxl@uFQ2)yQ$?(*1M>;8By_JiCaa6>W}O!LrBB05F^aC9-bp*oU59R7w&uIB z?d0RIMclp8uv3LnHls0F$7B-5AKZ6~(kep-tYH@Pq`xs({|+zLX=if-$*+IdRkw)5 zj|0)Fd9{!b=*(NHG~DjP#B@~vjkY{*Ao8xaJS(GKrc$p0=>s{@TH71Pgj~5(`|M>N z4ajC+II)zvGN|`#`&UXWTOaD~wn#!`Pl0oP+w&tiq>D{}F*0!-W%dB>E0WL~D78K? z5^ln#3hM-)CY2BHmD$;Onp{Sc3B_SSQcw8#HD(!Rx!*{5&M zW#e019F+nIOG0f(OJ!}HvTg55KwP28-8pwhhuX#TmH9UA~469*^s_WjNna z;L4B;xkhk>&-tOtclpHGRD8cxpa;&}0!qd%fG6NE2p_WsR^-Jm9|lHieOH3ImG3e~ zr=1f5*tO1V>A8T}3jbKT)Vmm_`ju~CM16DLkfw4X<{c)8_*2Ca@ULnbj_;hFrTaj0 zA-=I>h)eP%63z}DaRLA1srr6!xIGtZ;<7iV@`BEf9k8;b*8HcLCo~et0_{)nu=XK5 zGaA3gR7*tZGGP5if5fa2^r7YdxxWY2O><@|I6ZOqv|zNWdLXSj_sPvSA&IpAIJ$Ez zP~=^mWMTv}Kd-WeWYM99OmRF$jxQB|&8TGWhuB?|S@Zd_`RE#-P86dnovQ&vMw=*ofXK`iFLMP5fjLCku-IcWhWd6g&E0EPxf7HlA% zp*I$)9KC@iF|2PL-KazT!OQ6OX)29K9DegT7wL2o%Sk3sY4Y4Xl%?6#b@dJndX!ai zE)^|AH5Yc31+FXw3^W|yNNL(4IWU|Ke_H3=C0&5t&2Yh`pmLe_OzaXbL68q;!PV|v z;$kHIyWOLB36CJt31r`BL3P6j7jcsP1wjyzhPn<)qU#i5%qYuXyKuNlVJI{lbk2p6 zj~zIf!qs=#+ZFf2=4NRoDj6^Qp7pU;3}xd$GvoKuD@7#}t~C-<^a~c1xbY!rHVuUb z@q?6s$=EZLN~_MN&GGL`TxF>HjrEL|Q+dJU_;L1!PqV&(tn3WKQ0pxASNtm@P*P&i z2fy*9l3Wb>6f4n1MC~w@B5{lW?p*5_M2);l%}npLy@E@mePMuYyx=P;IE13zzT3%m z8%Y(PH~ca;t_Bpd>5S?$6#TkbJS|ywk*<>rwE%=|;Pj<;<%N??%63#re1)_%iuBp& zl%5eue#}&C22})=-{qErS^>M-q;CUN`)h8-x-X8tL`A4_m~ljhMH)T86TWr~(9hK6 zyywysWr?9|8Uw@Yt^%)44c+F6Z9f9P8Sbcuvj zOVu6Vg$UwRdW~325GC+Sib^(Nhx~Bx9Q=8ZOSGP&TCYzBI(JFykyQt7ZP_Q}V*T&w z3bv|R2Yo&Ix*WvX*qSi|P-sfO`ab8+8??7&G2EKp$kx@m=#=3@q;{W{lVmmKB6WD1 zgQ;BdmxMd!YrB9Jjs}r|n#hvRkcZ0IDviG6ab(>U+sM$(k*z}=zD52vqL~O5AhE!= zR~<-FoM`coZM1_wT;0wcbMzJI)!>bONuLsGcqliZ3Y(X^sL~7Djrw%Oi3-;s{Ctel z^?J%h_xe!mg+sY+Znx0Z`6^DKy?)z6c{WYd9h&shUM()}#?0*CNu(i3zwF(?BnLgc zi9vf4!EFJ@4)wAJ5;qg6#dY_o7NS?Rc1vGzd1V&Xyppk3Xx7+AY}}fSt_2-gzn8I# zY=2=QOO3uTAAOAHzeiW&V1(&#t|_}rTZfefRUg{B8UX~tQ+whdtpFq2UkNn6oHLaI znmE=E7hViYN-$;>C_r)XW|PTUMQ#DLV+U%0-Nj;~i(?wr)>{^w2+Io0%qRwpm8Gt! z0EVIeRgH??lB8}+12tyEUf!|$YVK4T3yu&yV-&E3yDK@aD_LI`>%caWSQ`xK9sTOi zd#EjeozM{R3bY{vaKHo$Y3WO1iB&zL6ZHz! zFx&cb)IZ$52!~HMan~?x4o&4zI$Ub(6778fyp7vgCsqTwi&d0w>2UQThlB_Ydx6ts z8oPoOc;lF%9-coGU;DVA;PNx{BDH=F)Q5};m#R*{>xM%5da3O^P8sS7oz&AXKMxSf@6nBbO64x54w@%BMAcS0QlKG5e!WX}eZr z=zL;H07ZaH>H$@qDdq7)aVsP4F;-}SjE>M(mO zQKeGVPlfnhU9R`hQT(Z@o=#0Exp)W)ryr6&z(6!|+L(cwiQu5=Z5|BZRREa!g66sBhJA;ZG6D6E4Ldx{*I8R zKSs@NCztay@O`3pxu%J#yGO9h56h}x)=j7K55_61Sv|)wTWqLm*y-No5gZHCxvt8J z+Sj6>^0mKe-4*z5scg8)_I4I_YbZHZbKxc(m&;2FN-nU}H%0&^rqLOLB!lYBWxC-~ zQy0Z1!5oCXz0m53I3N9LBaT<-FU9P?zGNl&Wphu*)tFN07DFDrx8EG2K;OcS&OHJ$OT_W<%wkt+a&euDB!{~p3xzy$ z^c=VmMEZ6X`X~0AlbOQwS)q{C_!P6nJPml2vd6ZqSNxSi1p>L^JVQD{E3D734&mZDZFMd@$$;%Y!89L&}x#+80nxx2yG!Z>* z&+1H4ztL^BSASJ?pi>T)*mK*8LBjNwRs7U!nA4O;IJS;j2v?0vwrtgAMs6NVB+bI{z5p^qXS2X#v%Le31DQU z>yg&eM#mK8Neej(GpJfRBT(SuyzQk0k>?1}Q&!?L0XQh{WN9@1CG3*;f-G<}i1$~C z8c(Zc3tk5>$7r}nn_sM_`uKY|9$}~VZoDjQy}Q-15XWJ@!hB{>vaI*yf-b0@%5kd~ zsoVdl)1BD-Q{L7b^H-lfhFeIhH$J40-t66w#rW74Q{p6Eq_m|$0qfR$c7mOOJVDh#_&n!Hw+`EL?j6DIGke_pwpMc z=0ZqW9SUxr5fXmvm;kwWMJK0H{3#1uPC&=$EgV@z^iwTsjVj6h^7IkUUu0|31AjF$j+LO75nT?0EOJ&@spf3L2Jc5l0_(=3Lg#nv&JH~CQSot z{ti>W@Bp%5hj|TgLaZ-ilUzkO-+Vdom+|1W!yddMi)qeEl*=!A9}=)ZNxgm zeh~^>Vr2t`ydEYR+MHXctHum!5Ktffg0By9{7!6_3oDRWk3{DW{tb8)3VnWo89#Tu zbmF+r8!ybY3pIDGU*rNHV*(%FjWTI^dLWPl1yY}$gGEi?Jowb5h)Jr!t@lFTchKyj zHR)_b-}|T_1v@ttdm%>VgyZnii;brr%)$)!Q#vKs-`bESEC6I-(E<~x*0tH-lI#IJ z-1u6kMk*1AHqxU(_2_z>(xX7#mgfaJldJ z`*&}uAbQ|Y37a3d3;F+^=m|BQo=pF1(=J~jQUwF8AqU7MO zcHwsijapkx&bbfQuY@ik8Z}rOE5WE-(ov*cL>TLPY7mojV)-8S44uB<26h~ADclYw z(976YLSD|N1j<(alg970+`SQjjZJ?HyRZN+{R1PxF*->htpDs!6x0v<>?&#u3Gd

    v$tVy*Gkwfre_!KR9cZn1CAj9=& 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 IZ~5i_0dw;gFaQ7m delta 124644 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�#?3OCTkY{BF_`Z^9^sE*jR@ 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 z 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�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 diff --git a/firmware/fpga/dsp/nco.py b/firmware/fpga/dsp/nco.py index 7419e011..38bae44b 100755 --- a/firmware/fpga/dsp/nco.py +++ b/firmware/fpga/dsp/nco.py @@ -6,7 +6,7 @@ from math import pi, sin, cos -from amaranth import Module, Signal, Mux, Cat +from amaranth import Module, Signal, DomainRenamer, Mux, Cat from amaranth.lib import wiring, memory from amaranth.lib.wiring import In, Out @@ -38,9 +38,10 @@ class NCO(wiring.Component): Returned result for cos(phase), sin(phase). """ - def __init__(self, phase_width=24, output_width=10): + def __init__(self, phase_width=24, output_width=10, domain="sync"): self.phase_width = phase_width self.output_width = output_width + self._domain = domain super().__init__({ "phase": In(phase_width), "en": In(1), @@ -61,7 +62,7 @@ class NCO(wiring.Component): init=({"i": round(lut_scale * cos(x)), "q": round(lut_scale * sin(x))} for x in lut_phases) ) m.submodules.table = table = memory.Memory(data=lut_data) - table_rd = table.read_port(domain="sync") + table_rd = table.read_port(domain=self._domain) # 3 MSBs of the phase word: sign, quadrant, octant. o, q, s = self.phase[-3:] @@ -99,5 +100,8 @@ class NCO(wiring.Component): e_s2.q .eq(Mux(neg_sin, -e_s1.q, e_s1.q)), ] m.d.sync += self.output.eq(e_s2) + + if self._domain != "sync": + m = DomainRenamer(self._domain)(m) return m diff --git a/firmware/fpga/top/ext_precision_rx.py b/firmware/fpga/top/ext_precision_rx.py index 3284278a..3d486519 100644 --- a/firmware/fpga/top/ext_precision_rx.py +++ b/firmware/fpga/top/ext_precision_rx.py @@ -4,7 +4,8 @@ # Copyright (c) 2025 Great Scott Gadgets # SPDX-License-Identifier: BSD-3-Clause -from amaranth import Elaboratable, Module, Cat, DomainRenamer, Signal +from amaranth import Elaboratable, Module, Cat, DomainRenamer, Signal, Mux +from amaranth.lib import cdc from amaranth.lib.wiring import connect from amaranth_future import fixed @@ -15,7 +16,9 @@ from dsp.fir import FIRFilter from dsp.fir_mac16 import HalfBandDecimatorMAC16 from dsp.cic import CICDecimator from dsp.dc_block import DCBlock -from dsp.quarter_shift import QuarterShift +from dsp.nco import NCO +from dsp.mixer import ComplexMultiplier + from util import ClockConverter, IQSample @@ -56,10 +59,21 @@ class Top(Elaboratable): taps_hb2 = [ -6, 0, 19, 0, -44, 0, 89, 0, -163, 0, 278, 0, -452, 0, 711, 0, -1113, 0, 1800, 0, -3298, 0, 10370, 16384, 10370, 0, -3298, 0, 1800, 0, -1113, 0, 711, 0, -452, 0, 278, 0, -163, 0, 89, 0, -44, 0, 19, 0, -6] taps_hb2 = [ tap/16384/2 for tap in taps_hb2 ] + # NCO and mixer. + m.submodules.nco = nco = NCO(phase_width=16, output_width=10, domain=adc_clk) + mixer = DomainRenamer(adc_clk)(ComplexMultiplier(IQSample(8), IQSample(10), IQSample(8), always_ready=True)) + mixer.input = mixer.a + mixer.output = mixer.c + m.d.comb += [ + mixer.b.p.eq(nco.output), + mixer.b.valid.eq(1), + nco.en.eq(1), + ] + rx_chain = { - # DC block and quarter shift. + # DC block and mixer. "dc_block": DCBlock(width=8, num_channels=2, domain=adc_clk), - "quarter_shift": DomainRenamer(adc_clk)(QuarterShift()), + "mixer": mixer, # CIC mandatory first stage with compensator. "cic": CICDecimator(2, 4, (4,8,16,32), width_in=8, width_out=12, num_channels=2, always_ready=True, domain=adc_clk), @@ -93,20 +107,19 @@ class Top(Elaboratable): rx_decim_stb = Signal() rx_decim_cic = Signal.like(rx_chain["cic"].factor) spi_regs.add_sfr(0x02, read=rx_decim, write_signal=rx_decim_new, write_strobe=rx_decim_stb) - rx_pstep = spi_regs.add_register(0x03, init=0) + rx_nco = spi_regs.add_register(0x03, init=0) m.d.comb += [ # Trigger enable. mcu_intf.trigger_en .eq(ctrl[7]), - - # RX settings. - rx_chain["dc_block"].enable .eq(ctrl[0]), - rx_chain["quarter_shift"].enable .eq(rx_pstep[-2]), - rx_chain["quarter_shift"].up .eq(rx_pstep[-1]), - - # RX decimation rate. - rx_chain["cic"].factor .eq(rx_decim_cic), ] + + # RX DC block. + m.submodules.dc_block_cdc = cdc.FFSynchronizer(ctrl[0], rx_chain["dc_block"].enable, o_domain=adc_clk) + + # RX decimation rate. + m.submodules.rx_decim_cdc = cdc.FFSynchronizer(rx_decim_cic, rx_chain["cic"].factor, o_domain=adc_clk) + with m.If(rx_decim_stb): with m.If(rx_decim_new < 4): m.d.sync += rx_decim.eq(4) @@ -115,6 +128,11 @@ class Top(Elaboratable): m.d.sync += rx_decim.eq(rx_decim_new) m.d.sync += rx_decim_cic.eq(rx_decim_new-2) + # NCO control. + rx_nco_ad = Signal(8) + m.submodules.nco_phase_cdc = cdc.FFSynchronizer(rx_nco, rx_nco_ad, o_domain=adc_clk) + m.d[adc_clk] += nco.phase.eq(nco.phase - (rx_nco_ad << 8)) + return m From da1358076e88fdf62897a50f218325dc29c99370 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 2 Apr 2026 06:53:20 +0100 Subject: [PATCH 071/238] Jenkinsfile: move 'hubs all off' to a function. --- Jenkinsfile | 62 +++++++++++++++++++++-------------------------------- 1 file changed, 24 insertions(+), 38 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 2ee5b9e5..1a1eb3da 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -22,25 +22,7 @@ pipeline { sh './ci-scripts/install_host.sh' sh './ci-scripts/build_h1_firmware.sh' script { - try { - // Allow 20 seconds for the USB hub port power server to respond - timeout(time: 20, unit: 'SECONDS') { - sh 'hubs all off' - } - } catch (FlowInterruptedException err) { - // Check if the cause was specifically an exceeded timeout - def cause = err.getCauses().get(0) - if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { - echo "USB hub port power server command timeout reached." - throw err // Re-throw the exception to fail the build - } else { - echo "Build interrupted for another reason." - throw err // Re-throw the exception to fail the build - } - } catch (Exception err) { - echo "An unrelated error occurred: ${err.getMessage()}" - throw err - } + allOff(); } retry(3) { script { @@ -178,25 +160,7 @@ pipeline { sh './ci-scripts/install_host.sh' sh './ci-scripts/build_hpro_firmware.sh' script { - try { - // Allow 20 seconds for the USB hub port power server to respond - timeout(time: 20, unit: 'SECONDS') { - sh 'hubs all off' - } - } catch (FlowInterruptedException err) { - // Check if the cause was specifically an exceeded timeout - def cause = err.getCauses().get(0) - if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { - echo "USB hub port power server command timeout reached." - throw err // Re-throw the exception to fail the build - } else { - echo "Build interrupted for another reason." - throw err // Re-throw the exception to fail the build - } - } catch (Exception err) { - echo "An unrelated error occurred: ${err.getMessage()}" - throw err - } + allOff(); } retry(3) { script { @@ -284,3 +248,25 @@ pipeline { } } } + +def allOff() { + try { + // Allow 20 seconds for the USB hub port power server to respond + timeout(time: 20, unit: 'SECONDS') { + sh 'hubs all off' + } + } catch (FlowInterruptedException err) { + // Check if the cause was specifically an exceeded timeout + def cause = err.getCauses().get(0) + if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { + echo "USB hub port power server command timeout reached." + throw err // Re-throw the exception to fail the build + } else { + echo "Build interrupted for another reason." + throw err // Re-throw the exception to fail the build + } + } catch (Exception err) { + echo "An unrelated error occurred: ${err.getMessage()}" + throw err + } +} From dc79c298a2bbc650b1ead0b8e340497e7b5e3338 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 2 Apr 2026 07:04:35 +0100 Subject: [PATCH 072/238] Jenkinsfile: Add reset() helper function. --- Jenkinsfile | 142 +++++++++++----------------------------------------- 1 file changed, 28 insertions(+), 114 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 1a1eb3da..7936a567 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -26,50 +26,14 @@ pipeline { } retry(3) { script { - try { - // Allow 20 seconds for the USB hub port power server to respond - timeout(time: 20, unit: 'SECONDS') { - sh 'hubs h1_eut reset' - } - } catch (FlowInterruptedException err) { - // Check if the cause was specifically an exceeded timeout - def cause = err.getCauses().get(0) - if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { - echo "USB hub port power server command timeout reached." - throw err // Re-throw the exception to fail the build - } else { - echo "Build interrupted for another reason." - throw err // Re-throw the exception to fail the build - } - } catch (Exception err) { - echo "An unrelated error occurred: ${err.getMessage()}" - throw err - } + reset('h1_eut') } sh 'sleep 1s' sh './ci-scripts/test_host.sh' } retry(3) { script { - try { - // Allow 20 seconds for the USB hub port power server to respond - timeout(time: 20, unit: 'SECONDS') { - sh 'hubs h1_tester h1_eut reset' - } - } catch (FlowInterruptedException err) { - // Check if the cause was specifically an exceeded timeout - def cause = err.getCauses().get(0) - if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { - echo "USB hub port power server command timeout reached." - throw err // Re-throw the exception to fail the build - } else { - echo "Build interrupted for another reason." - throw err // Re-throw the exception to fail the build - } - } catch (Exception err) { - echo "An unrelated error occurred: ${err.getMessage()}" - throw err - } + reset('h1_tester h1_eut') } sh 'sleep 1s' script { @@ -98,48 +62,12 @@ pipeline { } } script { - try { - // Allow 20 seconds for the USB hub port power server to respond - timeout(time: 20, unit: 'SECONDS') { - sh 'hubs all off' - } - } catch (FlowInterruptedException err) { - // Check if the cause was specifically an exceeded timeout - def cause = err.getCauses().get(0) - if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { - echo "USB hub port power server command timeout reached." - throw err // Re-throw the exception to fail the build - } else { - echo "Build interrupted for another reason." - throw err // Re-throw the exception to fail the build - } - } catch (Exception err) { - echo "An unrelated error occurred: ${err.getMessage()}" - throw err - } + allOff() } } retry(3) { script { - try { - // Allow 20 seconds for the USB hub port power server to respond - timeout(time: 20, unit: 'SECONDS') { - sh 'hubs h1_eut reset' - } - } catch (FlowInterruptedException err) { - // Check if the cause was specifically an exceeded timeout - def cause = err.getCauses().get(0) - if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { - echo "USB hub port power server command timeout reached." - throw err // Re-throw the exception to fail the build - } else { - echo "Build interrupted for another reason." - throw err // Re-throw the exception to fail the build - } - } catch (Exception err) { - echo "An unrelated error occurred: ${err.getMessage()}" - throw err - } + reset('h1_eut') } sh 'sleep 1s' sh 'python3 ci-scripts/test_sgpio_debug.py' @@ -164,50 +92,14 @@ pipeline { } retry(3) { script { - try { - // Allow 20 seconds for the USB hub port power server to respond - timeout(time: 20, unit: 'SECONDS') { - sh 'hubs hpro_eut reset' - } - } catch (FlowInterruptedException err) { - // Check if the cause was specifically an exceeded timeout - def cause = err.getCauses().get(0) - if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { - echo "USB hub port power server command timeout reached." - throw err // Re-throw the exception to fail the build - } else { - echo "Build interrupted for another reason." - throw err // Re-throw the exception to fail the build - } - } catch (Exception err) { - echo "An unrelated error occurred: ${err.getMessage()}" - throw err - } + reset('hpro_eut') } sh 'sleep 1s' sh './ci-scripts/test_host.sh' } retry(3) { script { - try { - // Allow 10 seconds for the USB hub port power server to respond - timeout(time: 20, unit: 'SECONDS') { - sh 'hubs hpro_tester hpro_eut reset' - } - } catch (FlowInterruptedException err) { - // Check if the cause was specifically an exceeded timeout - def cause = err.getCauses().get(0) - if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { - echo "USB hub port power server command timeout reached." - throw err // Re-throw the exception to fail the build - } else { - echo "Build interrupted for another reason." - throw err // Re-throw the exception to fail the build - } - } catch (Exception err) { - echo "An unrelated error occurred: ${err.getMessage()}" - throw err - } + reset('hpro_tester hpro_eut') } sh 'sleep 1s' script { @@ -270,3 +162,25 @@ def allOff() { throw err } } + +def reset(devices) { + try { + // Allow 20 seconds for the USB hub port power server to respond + timeout(time: 20, unit: 'SECONDS') { + sh "hubs ${devices} reset" + } + } catch (FlowInterruptedException err) { + // Check if the cause was specifically an exceeded timeout + def cause = err.getCauses().get(0) + if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { + echo "USB hub port power server command timeout reached." + throw err // Re-throw the exception to fail the build + } else { + echo "Build interrupted for another reason." + throw err // Re-throw the exception to fail the build + } + } catch (Exception err) { + echo "An unrelated error occurred: ${err.getMessage()}" + throw err + } +} From 601a77a9da9c2a265909b31cf1a65fc3b6faf524 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 2 Apr 2026 07:15:47 +0100 Subject: [PATCH 073/238] Jenkinsfile: Add runCommand() helper function. --- Jenkinsfile | 97 ++++++++++++++--------------------------------------- 1 file changed, 26 insertions(+), 71 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 7936a567..2b03c4de 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -37,31 +37,14 @@ pipeline { } sh 'sleep 1s' script { - try { - // Allow 5 minutes for the test to run - timeout(time: 5, unit: 'MINUTES') { - sh '''python3 ci-scripts/hackrf_test.py --ci --log log \ - --hostdir host/build/hackrf-tools/src/ \ - --fwupdate firmware/hackrf_usb/build/ \ - --tester 0000000000000000325866e629a25623 \ - --eut RunningFromRAM --unattended --rev r4''' - } - } catch (FlowInterruptedException err) { - // Check if the cause was specifically an exceeded timeout - def cause = err.getCauses().get(0) - if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { - echo "HackRF One Test timeout limit reached." - throw err // Re-throw the exception to fail the build - } else { - echo "Build interrupted for another reason." - throw err // Re-throw the exception to fail the build - } - } catch (Exception err) { - echo "An unrelated error occurred: ${err.getMessage()}" - throw err - } - } - script { + // Allow 5 minutes for the test to run + runCommand(5, 'MINUTES', "HackRF One Test", + '''python3 ci-scripts/hackrf_test.py --ci --log log \ + --hostdir host/build/hackrf-tools/src/ \ + --fwupdate firmware/hackrf_usb/build/ \ + --tester 0000000000000000325866e629a25623 \ + --eut RunningFromRAM --unattended --rev r4''' + ) allOff() } } @@ -103,29 +86,14 @@ pipeline { } sh 'sleep 1s' script { - try { - // Allow 5 minutes for the test to run - timeout(time: 5, unit: 'MINUTES') { - sh '''python3 ci-scripts/hackrf_pro_test.py --ci --log log \ - --hostdir host/build/hackrf-tools/src \ - --fwupdate firmware/hackrf_usb/build \ - --tester 0000000000000000a06063c82338145f \ - --eut RunningFromRAM -p --rev r1.2''' - } - } catch (FlowInterruptedException err) { - // Check if the cause was specifically an exceeded timeout - def cause = err.getCauses().get(0) - if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { - echo "HackRF Pro Test timeout limit reached." - throw err // Re-throw the exception to fail the build - } else { - echo "Build interrupted for another reason." - throw err // Re-throw the exception to fail the build - } - } catch (Exception err) { - echo "An unrelated error occurred: ${err.getMessage()}" - throw err - } + // Allow 5 minutes for the test to run + runCommand(5, 'MINUTES', "HackRF Pro Test", + '''python3 ci-scripts/hackrf_pro_test.py --ci --log log \ + --hostdir host/build/hackrf-tools/src \ + --fwupdate firmware/hackrf_usb/build \ + --tester 0000000000000000a06063c82338145f \ + --eut RunningFromRAM -p --rev r1.2''' + ) } } } @@ -142,38 +110,25 @@ pipeline { } def allOff() { - try { - // Allow 20 seconds for the USB hub port power server to respond - timeout(time: 20, unit: 'SECONDS') { - sh 'hubs all off' - } - } catch (FlowInterruptedException err) { - // Check if the cause was specifically an exceeded timeout - def cause = err.getCauses().get(0) - if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { - echo "USB hub port power server command timeout reached." - throw err // Re-throw the exception to fail the build - } else { - echo "Build interrupted for another reason." - throw err // Re-throw the exception to fail the build - } - } catch (Exception err) { - echo "An unrelated error occurred: ${err.getMessage()}" - throw err - } + // Allow 20 seconds for the USB hub port power server to respond + runCommand(20, 'SECONDS', 'USB hub port power server command', "hubs all off") } def reset(devices) { + // Allow 20 seconds for the USB hub port power server to respond + runCommand(20, 'SECONDS', 'USB hub port power server command', "hubs ${devices} reset") +} + +def runCommand(time, unit, title, cmd) { try { - // Allow 20 seconds for the USB hub port power server to respond - timeout(time: 20, unit: 'SECONDS') { - sh "hubs ${devices} reset" + timeout(time: time, unit: unit) { + sh "${cmd}" } } catch (FlowInterruptedException err) { // Check if the cause was specifically an exceeded timeout def cause = err.getCauses().get(0) if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { - echo "USB hub port power server command timeout reached." + echo "${title} timeout reached." throw err // Re-throw the exception to fail the build } else { echo "Build interrupted for another reason." From 020e57b2f5c10214a9cb44a9f8c9bf92c4a62a8a Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Fri, 20 Mar 2026 10:16:09 +0200 Subject: [PATCH 074/238] firmware: replace include guards with #pragma once --- firmware/common/adc.h | 5 +--- firmware/common/bitband.h | 5 +--- firmware/common/clkin.h | 5 +--- firmware/common/cpld_jtag.h | 5 +--- firmware/common/cpld_xc2c.h | 5 +--- firmware/common/crc.h | 5 +--- firmware/common/da7219.h | 5 +--- firmware/common/delay.h | 7 +++--- firmware/common/fault_handler.h | 5 +--- firmware/common/firmware_info.h | 5 +--- firmware/common/fixed_point.h | 5 +--- firmware/common/fpga.h | 5 +--- firmware/common/fpga_regs.def | 7 ++---- firmware/common/gpdma.h | 5 +--- firmware/common/gpio.h | 5 +--- firmware/common/gpio_lpc.h | 5 +--- firmware/common/hackrf_core.h | 5 +--- firmware/common/hackrf_ui.h | 5 +--- firmware/common/i2c_bus.h | 5 +--- firmware/common/i2c_lpc.h | 5 +--- firmware/common/ice40_spi.h | 5 +--- firmware/common/locking.h | 5 +--- firmware/common/lz4_blk.h | 5 +--- firmware/common/lz4_buf.h | 5 +--- firmware/common/m0_state.h | 5 +--- firmware/common/max2831.h | 5 +--- firmware/common/max2831_regs.def | 28 +++++++++++++++++++---- firmware/common/max2831_target.h | 5 +--- firmware/common/max2837.h | 5 +--- firmware/common/max2837_regs.def | 27 ++++++++++++++++++---- firmware/common/max2837_target.h | 5 +--- firmware/common/max2839.h | 5 +--- firmware/common/max2839_regs.def | 27 ++++++++++++++++++---- firmware/common/max2839_target.h | 5 ---- firmware/common/max283x.h | 5 +--- firmware/common/max2871.h | 4 +--- firmware/common/max2871_regs.h | 5 ++-- firmware/common/max5864.h | 5 +--- firmware/common/max5864_target.h | 5 +--- firmware/common/mixer.h | 5 +--- firmware/common/operacake.h | 5 +--- firmware/common/operacake_sctimer.h | 5 +--- firmware/common/platform_detect.h | 5 +--- firmware/common/platform_gpio.h | 5 +--- firmware/common/platform_scu.h | 5 +--- firmware/common/portapack.h | 5 +--- firmware/common/rad1o/decoder.h | 5 +--- firmware/common/rad1o/display.h | 5 +--- firmware/common/rad1o/draw.h | 5 +--- firmware/common/rad1o/fonts.h | 5 +--- firmware/common/rad1o/print.h | 5 +--- firmware/common/rad1o/render.h | 5 ++-- firmware/common/rad1o/smallfonts.h | 6 ++--- firmware/common/rad1o/ubuntu18.h | 5 +--- firmware/common/radio.h | 5 +--- firmware/common/rf_path.h | 5 +--- firmware/common/rffc5071.h | 5 +--- firmware/common/rffc5071_regs.def | 5 +--- firmware/common/rffc5071_spi.h | 5 +--- firmware/common/rom_iap.h | 7 ++---- firmware/common/sct.h | 2 ++ firmware/common/selftest.h | 5 +--- firmware/common/sgpio.h | 5 +--- firmware/common/si5351c.h | 5 +--- firmware/common/spi_bus.h | 5 +--- firmware/common/spi_ssp.h | 5 +--- firmware/common/streaming.h | 5 +--- firmware/common/tune_config.h | 5 +--- firmware/common/tuning.h | 5 +--- firmware/common/ui_portapack.h | 5 +--- firmware/common/ui_rad1o.h | 5 +--- firmware/common/usb.h | 5 +--- firmware/common/usb_queue.h | 4 +--- firmware/common/usb_request.h | 5 +--- firmware/common/usb_standard_request.h | 5 +--- firmware/common/usb_type.h | 5 +--- firmware/common/w25q80bv.h | 5 +--- firmware/common/w25q80bv_target.h | 5 +--- firmware/hackrf_usb/usb_api_adc.h | 5 +--- firmware/hackrf_usb/usb_api_board_info.h | 5 +--- firmware/hackrf_usb/usb_api_cpld.h | 5 +--- firmware/hackrf_usb/usb_api_m0_state.h | 5 +--- firmware/hackrf_usb/usb_api_operacake.h | 5 +--- firmware/hackrf_usb/usb_api_praline.h | 5 +--- firmware/hackrf_usb/usb_api_register.h | 5 +--- firmware/hackrf_usb/usb_api_selftest.h | 5 +--- firmware/hackrf_usb/usb_api_spiflash.h | 5 +--- firmware/hackrf_usb/usb_api_sweep.h | 5 +--- firmware/hackrf_usb/usb_api_transceiver.h | 5 +--- firmware/hackrf_usb/usb_api_ui.h | 5 +--- firmware/hackrf_usb/usb_bulk_buffer.h | 5 +--- firmware/hackrf_usb/usb_descriptor.h | 2 ++ firmware/hackrf_usb/usb_device.h | 5 +--- firmware/hackrf_usb/usb_endpoint.h | 5 +--- 94 files changed, 167 insertions(+), 369 deletions(-) diff --git a/firmware/common/adc.h b/firmware/common/adc.h index 94481678..b74125af 100644 --- a/firmware/common/adc.h +++ b/firmware/common/adc.h @@ -19,12 +19,9 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __ADC_H__ -#define __ADC_H__ +#pragma once #include uint16_t adc_read(uint8_t pin); void adc_off(void); - -#endif // __ADC_H__ diff --git a/firmware/common/bitband.h b/firmware/common/bitband.h index dcf7aefb..8a0afed5 100644 --- a/firmware/common/bitband.h +++ b/firmware/common/bitband.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __BITBAND_H__ -#define __BITBAND_H__ +#pragma once #include @@ -37,5 +36,3 @@ void peripheral_bitband_clear( uint32_t peripheral_bitband_get( volatile void* const peripheral_address, const uint_fast8_t bit_number); - -#endif //__BITBAND_H__ diff --git a/firmware/common/clkin.h b/firmware/common/clkin.h index 2f2fa274..2cef67cf 100644 --- a/firmware/common/clkin.h +++ b/firmware/common/clkin.h @@ -19,12 +19,9 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __CLKIN_H__ -#define __CLKIN_H__ +#pragma once #include void clkin_detect_init(void); uint32_t clkin_frequency(void); - -#endif //__CLKIN_H__ diff --git a/firmware/common/cpld_jtag.h b/firmware/common/cpld_jtag.h index 9219dbcb..c052334d 100644 --- a/firmware/common/cpld_jtag.h +++ b/firmware/common/cpld_jtag.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __CPLD_JTAG_H__ -#define __CPLD_JTAG_H__ +#pragma once #include @@ -59,5 +58,3 @@ int cpld_jtag_program( unsigned char* const buffer, refill_buffer_cb refill); unsigned char cpld_jtag_get_next_byte(void); - -#endif //__CPLD_JTAG_H__ diff --git a/firmware/common/cpld_xc2c.h b/firmware/common/cpld_xc2c.h index 26ac8fa4..c48dae31 100644 --- a/firmware/common/cpld_xc2c.h +++ b/firmware/common/cpld_xc2c.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __CPLD_XC2C_H__ -#define __CPLD_XC2C_H__ +#pragma once #include #include @@ -69,5 +68,3 @@ bool cpld_xc2c64a_jtag_sram_verify( extern const cpld_xc2c64a_program_t cpld_hackrf_program_sram; extern const cpld_xc2c64a_verify_t cpld_hackrf_verify; extern const cpld_xc2c64a_row_addresses_t cpld_hackrf_row_addresses; - -#endif /*__CPLD_XC2C_H__*/ diff --git a/firmware/common/crc.h b/firmware/common/crc.h index f8acf5fc..ee33d7df 100644 --- a/firmware/common/crc.h +++ b/firmware/common/crc.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __CRC_H__ -#define __CRC_H__ +#pragma once #include #include @@ -35,5 +34,3 @@ typedef struct { void crc32_init(crc32_t* const crc); void crc32_update(crc32_t* const crc, const uint8_t* const data, const size_t byte_count); uint32_t crc32_digest(const crc32_t* const crc); - -#endif //__CRC_H__ diff --git a/firmware/common/da7219.h b/firmware/common/da7219.h index f0289240..c81ece20 100644 --- a/firmware/common/da7219.h +++ b/firmware/common/da7219.h @@ -19,13 +19,10 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __DA7219_H -#define __DA7219_H +#pragma once #include #define DA7219_ADDRESS 0x1A bool da7219_detect(void); - -#endif /* __DA7219_H */ diff --git a/firmware/common/delay.h b/firmware/common/delay.h index 123141ba..870ba39e 100644 --- a/firmware/common/delay.h +++ b/firmware/common/delay.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __DELAY_H -#define __DELAY_H +#pragma once #ifdef __cplusplus extern "C" { @@ -31,4 +30,6 @@ extern "C" { void delay(uint32_t duration); void delay_us_at_mhz(uint32_t us, uint32_t mhz); -#endif /* __DELAY_H */ +#ifdef __cplusplus +} +#endif diff --git a/firmware/common/fault_handler.h b/firmware/common/fault_handler.h index efccea24..d0edd6a5 100644 --- a/firmware/common/fault_handler.h +++ b/firmware/common/fault_handler.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __FAULT_HANDLER__ -#define __FAULT_HANDLER__ +#pragma once #include @@ -71,5 +70,3 @@ static armv7m_scb_t* const SCB = (armv7m_scb_t*) SCB_BASE; #define SCB_HFSR_DEBUGEVT (1 << 31) #define SCB_HFSR_FORCED (1 << 30) #define SCB_HFSR_VECTTBL (1 << 1) - -#endif //__FAULT_HANDLER__ diff --git a/firmware/common/firmware_info.h b/firmware/common/firmware_info.h index fb087008..a7ae09f6 100644 --- a/firmware/common/firmware_info.h +++ b/firmware/common/firmware_info.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef FIRMWARE_INFO_H -#define FIRMWARE_INFO_H +#pragma once #include @@ -33,5 +32,3 @@ struct firmware_info_t { } __attribute__((packed, aligned(1))); extern const struct firmware_info_t firmware_info; - -#endif \ No newline at end of file diff --git a/firmware/common/fixed_point.h b/firmware/common/fixed_point.h index 500d2e54..65656e19 100644 --- a/firmware/common/fixed_point.h +++ b/firmware/common/fixed_point.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __FIXED_POINT_H__ -#define __FIXED_POINT_H__ +#pragma once #include @@ -32,5 +31,3 @@ typedef uint64_t fp_40_24_t; /* one in 40.24 fixed-point */ #define FP_ONE_HZ (1 << 24) - -#endif /*__FIXED_POINT_H__*/ diff --git a/firmware/common/fpga.h b/firmware/common/fpga.h index bf78cf08..3ba3b652 100644 --- a/firmware/common/fpga.h +++ b/firmware/common/fpga.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __FPGA_H -#define __FPGA_H +#pragma once #include #include @@ -94,5 +93,3 @@ bool fpga_image_load(struct fpga_loader_t* loader, unsigned int index); bool fpga_spi_selftest(void); bool fpga_sgpio_selftest(void); bool fpga_if_xcvr_selftest(void); - -#endif // __FPGA_H diff --git a/firmware/common/fpga_regs.def b/firmware/common/fpga_regs.def index 5964657b..0a8ce828 100644 --- a/firmware/common/fpga_regs.def +++ b/firmware/common/fpga_regs.def @@ -1,7 +1,7 @@ /* -*- mode: c -*- * * Copyright 2012 Michael Ossmann - * Copyright 2025 Great Scott Gadgets + * Copyright 2025-2026 Great Scott Gadgets * * This file is part of HackRF. * @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __FPGA_REGS_DEF -#define __FPGA_REGS_DEF +#pragma once #define FPGA_REG_SET_CLEAN(_d, _r) (_d->regs_dirty &= ~(1UL<<_r)) #define FPGA_REG_SET_DIRTY(_d, _r) (_d->regs_dirty |= (1UL<<_r)) @@ -71,5 +70,3 @@ __MREG__(FPGA_STANDARD_TX_INTRP, 5, 0, 3) /* REG 06 (6): TX_PSTEP */ __MREG__(FPGA_STANDARD_TX_PSTEP, 6, 0, 8) - -#endif // __FPGA_REGS_DEF diff --git a/firmware/common/gpdma.h b/firmware/common/gpdma.h index 053f83a8..dc469da9 100644 --- a/firmware/common/gpdma.h +++ b/firmware/common/gpdma.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __GPDMA_H__ -#define __GPDMA_H__ +#pragma once #include #include @@ -40,5 +39,3 @@ void gpdma_lli_enable_interrupt(gpdma_lli_t* const lli); void gpdma_lli_create_loop(gpdma_lli_t* const lli, const size_t lli_count); void gpdma_lli_create_oneshot(gpdma_lli_t* const lli, const size_t lli_count); - -#endif /*__GPDMA_H__*/ diff --git a/firmware/common/gpio.h b/firmware/common/gpio.h index 387b91a3..749fa021 100644 --- a/firmware/common/gpio.h +++ b/firmware/common/gpio.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __GPIO_H__ -#define __GPIO_H__ +#pragma once #include @@ -35,5 +34,3 @@ void gpio_output(gpio_t gpio); void gpio_input(gpio_t gpio); void gpio_write(gpio_t gpio, const bool value); bool gpio_read(gpio_t gpio); - -#endif /*__GPIO_H__*/ diff --git a/firmware/common/gpio_lpc.h b/firmware/common/gpio_lpc.h index f018e43c..68905ef9 100644 --- a/firmware/common/gpio_lpc.h +++ b/firmware/common/gpio_lpc.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __GPIO_LPC_H__ -#define __GPIO_LPC_H__ +#pragma once #include @@ -69,5 +68,3 @@ struct gpio { .gpio_w = GPIO_LPC_W(_port_num, _pin_num), \ } // clang-format on - -#endif /*__GPIO_LPC_H__*/ diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 74a171a1..e3396ae2 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __HACKRF_CORE_H -#define __HACKRF_CORE_H +#pragma once #ifdef __cplusplus extern "C" { @@ -146,5 +145,3 @@ void pps_out_set(const uint8_t value); #ifdef __cplusplus } #endif - -#endif /* __HACKRF_CORE_H */ diff --git a/firmware/common/hackrf_ui.h b/firmware/common/hackrf_ui.h index 24d2fa8e..7b08a597 100644 --- a/firmware/common/hackrf_ui.h +++ b/firmware/common/hackrf_ui.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef HACKRF_UI_H -#define HACKRF_UI_H +#pragma once #include #include @@ -71,5 +70,3 @@ typedef struct { */ const hackrf_ui_t* hackrf_ui(void); void hackrf_ui_set_enable(bool); - -#endif diff --git a/firmware/common/i2c_bus.h b/firmware/common/i2c_bus.h index 95431437..1e85e440 100644 --- a/firmware/common/i2c_bus.h +++ b/firmware/common/i2c_bus.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __I2C_BUS_H__ -#define __I2C_BUS_H__ +#pragma once #include #include @@ -51,5 +50,3 @@ void i2c_bus_transfer( const size_t tx_count, uint8_t* const rx, const size_t rx_count); - -#endif /*__I2C_BUS_H__*/ diff --git a/firmware/common/i2c_lpc.h b/firmware/common/i2c_lpc.h index c4f3e8c3..c94ca253 100644 --- a/firmware/common/i2c_lpc.h +++ b/firmware/common/i2c_lpc.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __I2C_LPC_H__ -#define __I2C_LPC_H__ +#pragma once #include #include @@ -43,5 +42,3 @@ void i2c_lpc_transfer( uint8_t* const data_rx, const size_t count_rx); bool i2c_probe(i2c_bus_t* const bus, const uint_fast8_t device_address); - -#endif /*__I2C_LPC_H__*/ diff --git a/firmware/common/ice40_spi.h b/firmware/common/ice40_spi.h index 92ce6280..ef97acc6 100644 --- a/firmware/common/ice40_spi.h +++ b/firmware/common/ice40_spi.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __ICE40_SPI_H -#define __ICE40_SPI_H +#pragma once #include #include @@ -47,5 +46,3 @@ bool ice40_spi_syscfg_program( uint8_t* buf, size_t (*read_block_cb)(void* ctx), void* read_ctx); - -#endif // __ICE40_SPI_H diff --git a/firmware/common/locking.h b/firmware/common/locking.h index 5620f2f9..54ba7a70 100644 --- a/firmware/common/locking.h +++ b/firmware/common/locking.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __LOCKING_H__ -#define __LOCKING_H__ +#pragma once #include @@ -51,5 +50,3 @@ static inline uint32_t store_exclusive(uint32_t val, volatile uint32_t* addr) return 0; } #endif - -#endif /* __LOCKING_H__ */ diff --git a/firmware/common/lz4_blk.h b/firmware/common/lz4_blk.h index 19c8207e..f4e25f7a 100644 --- a/firmware/common/lz4_blk.h +++ b/firmware/common/lz4_blk.h @@ -19,12 +19,9 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __LZ4_BLK_H -#define __LZ4_BLK_H +#pragma once #include #include int lz4_blk_decompress(const uint8_t* src, uint8_t* dst, size_t length); - -#endif \ No newline at end of file diff --git a/firmware/common/lz4_buf.h b/firmware/common/lz4_buf.h index b9dec589..ab073d43 100644 --- a/firmware/common/lz4_buf.h +++ b/firmware/common/lz4_buf.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __LZ4_BUF_H -#define __LZ4_BUF_H +#pragma once #include @@ -31,5 +30,3 @@ extern uint8_t lz4_in_buf[LZ4_BUFFER_SIZE]; extern uint8_t lz4_out_buf[LZ4_BUFFER_SIZE]; - -#endif /*__LZ4_BUF_H */ diff --git a/firmware/common/m0_state.h b/firmware/common/m0_state.h index cd0391fc..b7c26e8b 100644 --- a/firmware/common/m0_state.h +++ b/firmware/common/m0_state.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __M0_STATE_H__ -#define __M0_STATE_H__ +#pragma once #include @@ -60,5 +59,3 @@ enum m0_error { extern volatile struct m0_state m0_state; void m0_set_mode(enum m0_mode mode); - -#endif /*__M0_STATE_H__*/ diff --git a/firmware/common/max2831.h b/firmware/common/max2831.h index 9298247a..a5b58afc 100644 --- a/firmware/common/max2831.h +++ b/firmware/common/max2831.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __MAX2831_H -#define __MAX2831_H +#pragma once #include #include @@ -108,5 +107,3 @@ extern void max2831_tx(max2831_driver_t* const drv); extern void max2831_rx(max2831_driver_t* const drv); extern void max2831_tx_calibration(max2831_driver_t* const drv); extern void max2831_rx_calibration(max2831_driver_t* const drv); - -#endif // __MAX2831_H diff --git a/firmware/common/max2831_regs.def b/firmware/common/max2831_regs.def index fb8fa8a9..fd09707d 100644 --- a/firmware/common/max2831_regs.def +++ b/firmware/common/max2831_regs.def @@ -1,7 +1,27 @@ -/* -*- mode: c -*- */ +/* -*- mode: c -*- + * + * Copyright 2012 Michael Ossmann + * Copyright 2025-2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ -#ifndef __MAX2831_REGS_DEF -#define __MAX2831_REGS_DEF +#pragma once /* Generate static inline accessors that operate on the global * regs. Done this way to (1) allow defs to be scraped out and used @@ -128,5 +148,3 @@ __MREG__(MAX2831_RXIQ_VCM,15,10,2) // RX I/Q output common mode #define MAX2831_RXIQ_VCM_1_2 1 // 1.2V #define MAX2831_RXIQ_VCM_1_3 2 // 1.3V #define MAX2831_RXIQ_VCM_1_45 3 // 1.45V - -#endif // __MAX2831_REGS_DEF \ No newline at end of file diff --git a/firmware/common/max2831_target.h b/firmware/common/max2831_target.h index 11671b73..072faf22 100644 --- a/firmware/common/max2831_target.h +++ b/firmware/common/max2831_target.h @@ -19,12 +19,9 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __MAX2831_TARGET_H -#define __MAX2831_TARGET_H +#pragma once #include "max2831.h" void max2831_target_init(max2831_driver_t* const drv); void max2831_target_set_mode(max2831_driver_t* const drv, const max2831_mode_t new_mode); - -#endif // __MAX2831_TARGET_H diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index 0c7a65c8..b934b2ed 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __MAX2837_H -#define __MAX2837_H +#pragma once #include #include @@ -91,5 +90,3 @@ bool max2837_set_txvga_gain(max2837_driver_t* const drv, const uint32_t gain_db) extern void max2837_tx(max2837_driver_t* const drv); extern void max2837_rx(max2837_driver_t* const drv); - -#endif // __MAX2837_H diff --git a/firmware/common/max2837_regs.def b/firmware/common/max2837_regs.def index 0aa2f9e5..67eb6dd7 100644 --- a/firmware/common/max2837_regs.def +++ b/firmware/common/max2837_regs.def @@ -1,7 +1,26 @@ -/* -*- mode: c -*- */ +/* -*- mode: c -*- * + * Copyright 2012 Michael Ossmann + * Copyright 2025-2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ -#ifndef __MAX2837_REGS_DEF -#define __MAX2837_REGS_DEF +#pragma once /* Generate static inline accessors that operate on the global * regs. Done this way to (1) allow defs to be scraped out and used @@ -404,5 +423,3 @@ __MREG__(MAX2837_FUSE_RTH,30,9,1) // 0 -> 992/0uA correction, 15 -> 0/992uA correction ... if TX_DCCORR_SPI_EN __MREG__(MAX2837_TX_DCCORR_I,31,4,5) __MREG__(MAX2837_TX_DCCORR_Q,31,9,5) - -#endif // __MAX2837_REGS_DEF diff --git a/firmware/common/max2837_target.h b/firmware/common/max2837_target.h index 75d87698..2910791e 100644 --- a/firmware/common/max2837_target.h +++ b/firmware/common/max2837_target.h @@ -21,12 +21,9 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __MAX2837_TARGET_H -#define __MAX2837_TARGET_H +#pragma once #include "max2837.h" void max2837_target_init(max2837_driver_t* const drv); void max2837_target_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode); - -#endif // __MAX2837_TARGET_H diff --git a/firmware/common/max2839.h b/firmware/common/max2839.h index ac238fe2..3647d067 100644 --- a/firmware/common/max2839.h +++ b/firmware/common/max2839.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __MAX2839_H -#define __MAX2839_H +#pragma once #include #include @@ -93,5 +92,3 @@ bool max2839_set_txvga_gain(max2839_driver_t* const drv, const uint32_t gain_db) extern void max2839_tx(max2839_driver_t* const drv); extern void max2839_rx(max2839_driver_t* const drv); - -#endif // __MAX2839_H diff --git a/firmware/common/max2839_regs.def b/firmware/common/max2839_regs.def index bee66846..11b1d80d 100644 --- a/firmware/common/max2839_regs.def +++ b/firmware/common/max2839_regs.def @@ -1,7 +1,26 @@ -/* -*- mode: c -*- */ +/* -*- mode: c -*- * + * Copyright 2012 Michael Ossmann + * Copyright 2025-2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ -#ifndef __MAX2839_REGS_DEF -#define __MAX2839_REGS_DEF +#pragma once /* Generate static inline accessors that operate on the global * regs. Done this way to (1) allow defs to be scraped out and used @@ -255,5 +274,3 @@ __MREG__(MAX2839_PA_DAC_Voltage_Mode_Output_Select,30,9,1) __MREG__(MAX2839_TX_DC_Offset_Correction_QChannel,31,5,6) __MREG__(MAX2839_RESERVED_31_8,31,8,3) __MREG__(MAX2839_PA_DAC_Clk_Divide_Ratio,31,9,1) - -#endif // __MAX2839_REGS_DEF diff --git a/firmware/common/max2839_target.h b/firmware/common/max2839_target.h index 89488243..0c21e98d 100644 --- a/firmware/common/max2839_target.h +++ b/firmware/common/max2839_target.h @@ -21,12 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __MAX2839_TARGET_H -#define __MAX2839_TARGET_H - #include "max2839.h" void max2839_target_init(max2839_driver_t* const drv); void max2839_target_set_mode(max2839_driver_t* const drv, const max2839_mode_t new_mode); - -#endif // __MAX2839_TARGET_H diff --git a/firmware/common/max283x.h b/firmware/common/max283x.h index e67bf8de..a96c908f 100644 --- a/firmware/common/max283x.h +++ b/firmware/common/max283x.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __MAX283x_H -#define __MAX283x_H +#pragma once #include #include @@ -126,5 +125,3 @@ void max283x_set_rx_hpf_frequency( /* Perform MAX2831 TX and RX calibration. */ void max283x_tx_calibration(max283x_driver_t* const drv); void max283x_rx_calibration(max283x_driver_t* const drv); - -#endif // __MAX283x_H diff --git a/firmware/common/max2871.h b/firmware/common/max2871.h index 3cc9bb3a..eb1ecbf0 100644 --- a/firmware/common/max2871.h +++ b/firmware/common/max2871.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef MAX2871_H -#define MAX2871_H +#pragma once #include @@ -39,4 +38,3 @@ extern void max2871_setup(max2871_driver_t* const drv); extern uint64_t max2871_set_frequency(max2871_driver_t* const drv, uint16_t mhz); extern void max2871_enable(max2871_driver_t* const drv); extern void max2871_disable(max2871_driver_t* const drv); -#endif diff --git a/firmware/common/max2871_regs.h b/firmware/common/max2871_regs.h index a18f6217..b0dbdacf 100644 --- a/firmware/common/max2871_regs.h +++ b/firmware/common/max2871_regs.h @@ -19,8 +19,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef MAX2871_REGS_H -#define MAX2871_REGS_H +#pragma once + #include #define MAX2871_VASA (1 << 9) @@ -75,4 +75,3 @@ void max2871_set_F01(uint32_t v); void max2871_set_LD(uint32_t v); void max2871_set_ADCS(uint32_t v); void max2871_set_ADCM(uint32_t v); -#endif diff --git a/firmware/common/max5864.h b/firmware/common/max5864.h index 0ce2c6e1..fbac7af5 100644 --- a/firmware/common/max5864.h +++ b/firmware/common/max5864.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __MAX5864_H -#define __MAX5864_H +#pragma once #include "spi_bus.h" @@ -41,5 +40,3 @@ void max5864_idle(max5864_driver_t* const drv); void max5864_rx(max5864_driver_t* const drv); void max5864_tx(max5864_driver_t* const drv); void max5864_xcvr(max5864_driver_t* const drv); - -#endif // __MAX5864_H diff --git a/firmware/common/max5864_target.h b/firmware/common/max5864_target.h index 2ddd9ed1..a162e0ac 100644 --- a/firmware/common/max5864_target.h +++ b/firmware/common/max5864_target.h @@ -20,11 +20,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __MAX5864_TARGET_H__ -#define __MAX5864_TARGET_H__ +#pragma once #include "max5864.h" void max5864_target_init(max5864_driver_t* const drv); - -#endif /*__MAX5864_TARGET_H__*/ diff --git a/firmware/common/mixer.h b/firmware/common/mixer.h index bfd638bb..d2eb57e9 100644 --- a/firmware/common/mixer.h +++ b/firmware/common/mixer.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __MIXER_H -#define __MIXER_H +#pragma once #if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) #include "rffc5071.h" @@ -41,5 +40,3 @@ extern uint64_t mixer_set_frequency(mixer_driver_t* const mixer, uint64_t hz); extern void mixer_enable(mixer_driver_t* const mixer); extern void mixer_disable(mixer_driver_t* const mixer); extern void mixer_set_gpo(mixer_driver_t* const drv, uint8_t gpo); - -#endif // __MIXER_H diff --git a/firmware/common/operacake.h b/firmware/common/operacake.h index 39da6ef0..b604c513 100644 --- a/firmware/common/operacake.h +++ b/firmware/common/operacake.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __OPERACAKE_H -#define __OPERACAKE_H +#pragma once #ifdef __cplusplus extern "C" { @@ -57,5 +56,3 @@ uint16_t gpio_test(uint8_t address); #ifdef __cplusplus } #endif - -#endif /* __OPERACAKE_H */ diff --git a/firmware/common/operacake_sctimer.h b/firmware/common/operacake_sctimer.h index 805b3cf9..04c86e92 100644 --- a/firmware/common/operacake_sctimer.h +++ b/firmware/common/operacake_sctimer.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __OPERACAKE_SCTIMER_H -#define __OPERACAKE_SCTIMER_H +#pragma once #include #include @@ -37,5 +36,3 @@ void operacake_sctimer_enable(bool enable); void operacake_sctimer_set_dwell_times(struct operacake_dwell_times* times, int n); void operacake_sctimer_stop(void); void operacake_sctimer_reset_state(void); - -#endif /* __OPERACAKE_SCTIMER_H */ diff --git a/firmware/common/platform_detect.h b/firmware/common/platform_detect.h index f02e733b..4f0f0f43 100644 --- a/firmware/common/platform_detect.h +++ b/firmware/common/platform_detect.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __PLATFORM_DETECT_H__ -#define __PLATFORM_DETECT_H__ +#pragma once #include @@ -76,5 +75,3 @@ void detect_hardware_platform(void); board_id_t detected_platform(void); board_rev_t detected_revision(void); uint32_t supported_platform(void); - -#endif //__PLATFORM_DETECT_H__ diff --git a/firmware/common/platform_gpio.h b/firmware/common/platform_gpio.h index e327e4ba..14f0c067 100644 --- a/firmware/common/platform_gpio.h +++ b/firmware/common/platform_gpio.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __PLATFORM_GPIO_H -#define __PLATFORM_GPIO_H +#pragma once #ifdef __cplusplus extern "C" { @@ -369,5 +368,3 @@ static const struct gpio GPIO7_25 = GPIO(7, 25); #ifdef __cplusplus } #endif - -#endif /* __PLATFORM_GPIO_H */ diff --git a/firmware/common/platform_scu.h b/firmware/common/platform_scu.h index 793eefa5..2b4b42f0 100644 --- a/firmware/common/platform_scu.h +++ b/firmware/common/platform_scu.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __PLATFORM_SCU_H -#define __PLATFORM_SCU_H +#pragma once #ifdef __cplusplus extern "C" { @@ -307,5 +306,3 @@ const platform_scu_t* platform_scu(void); #ifdef __cplusplus } #endif - -#endif /* __PLATFORM_SCU_H */ diff --git a/firmware/common/portapack.h b/firmware/common/portapack.h index d4dda66e..1a43af10 100644 --- a/firmware/common/portapack.h +++ b/firmware/common/portapack.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __PORTAPACK_H__ -#define __PORTAPACK_H__ +#pragma once #include #include @@ -85,5 +84,3 @@ void portapack_draw_bitmap( const ui_color_t background); ui_bitmap_t portapack_font_glyph(const ui_font_t* const font, const char c); - -#endif /*__PORTAPACK_H__*/ diff --git a/firmware/common/rad1o/decoder.h b/firmware/common/rad1o/decoder.h index 5f1bcda4..5575ef93 100644 --- a/firmware/common/rad1o/decoder.h +++ b/firmware/common/rad1o/decoder.h @@ -1,8 +1,5 @@ -#ifndef __RAD1O_DECODER_H__ -#define __RAD1O_DECODER_H__ +#pragma once #include uint8_t* rad1o_pk_decode(const uint8_t* data, int* len); - -#endif diff --git a/firmware/common/rad1o/display.h b/firmware/common/rad1o/display.h index 63711dfc..af5da5e1 100644 --- a/firmware/common/rad1o/display.h +++ b/firmware/common/rad1o/display.h @@ -1,5 +1,4 @@ -#ifndef __RAD1O_DISPLAY_H__ -#define __RAD1O_DISPLAY_H__ +#pragma once #include @@ -27,5 +26,3 @@ void rad1o_lcdFill(uint8_t f); void rad1o_lcdDisplay(void); void rad1o_lcdSetPixel(uint8_t x, uint8_t y, uint8_t f); uint8_t* rad1o_lcdGetBuffer(void); - -#endif diff --git a/firmware/common/rad1o/draw.h b/firmware/common/rad1o/draw.h index c8f6708b..dfdaaf68 100644 --- a/firmware/common/rad1o/draw.h +++ b/firmware/common/rad1o/draw.h @@ -1,9 +1,6 @@ -#ifndef __RAD1O_DRAW_H__ -#define __RAD1O_DRAW_H__ +#pragma once #include void rad1o_drawHLine(uint8_t y, uint8_t x1, uint8_t x2, uint8_t color); void rad1o_drawVLine(uint8_t x, uint8_t y1, uint8_t y2, uint8_t color); - -#endif diff --git a/firmware/common/rad1o/fonts.h b/firmware/common/rad1o/fonts.h index 98e0a7ac..bd1ce0b5 100644 --- a/firmware/common/rad1o/fonts.h +++ b/firmware/common/rad1o/fonts.h @@ -1,5 +1,4 @@ -#ifndef __RAD1O_FONTS_H__ -#define __RAD1O_FONTS_H__ +#pragma once #include @@ -31,5 +30,3 @@ typedef const struct FONT_DEF* FONT; #define FONT_DEFAULT 0 #define FONT_INTERNAL 1 #define FONT_EXTERNAL 2 - -#endif diff --git a/firmware/common/rad1o/print.h b/firmware/common/rad1o/print.h index 19ef1631..8981da25 100644 --- a/firmware/common/rad1o/print.h +++ b/firmware/common/rad1o/print.h @@ -1,5 +1,4 @@ -#ifndef __RAD1O_PRINT_H__ -#define __RAD1O_PRINT_H__ +#pragma once #include @@ -9,5 +8,3 @@ void rad1o_lcdClear(void); void rad1o_lcdMoveCrsr(int32_t dx, int32_t dy); void rad1o_lcdSetCrsr(int32_t dx, int32_t dy); void rad1o_setSystemFont(void); - -#endif diff --git a/firmware/common/rad1o/render.h b/firmware/common/rad1o/render.h index 1c623381..8d97b6e1 100644 --- a/firmware/common/rad1o/render.h +++ b/firmware/common/rad1o/render.h @@ -1,5 +1,4 @@ -#ifndef __RENDER_H_ -#define __RENDER_H_ +#pragma once #include @@ -10,4 +9,4 @@ void rad1o_setIntFont(const struct FONT_DEF* font); int rad1o_getFontHeight(void); int rad1o_DoString(int sx, int sy, const char* s); int rad1o_DoChar(int sx, int sy, int c); -#endif + diff --git a/firmware/common/rad1o/smallfonts.h b/firmware/common/rad1o/smallfonts.h index af69bf27..3204e62a 100644 --- a/firmware/common/rad1o/smallfonts.h +++ b/firmware/common/rad1o/smallfonts.h @@ -35,12 +35,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************/ -#ifndef __RAD1O_SMALLFONTS_H__ -#define __RAD1O_SMALLFONTS_H__ + +#pragma once /* Partially based on original code for the KS0108 by Stephane Rey */ /* Current version by Kevin Townsend */ extern const struct FONT_DEF Font_7x8; - -#endif diff --git a/firmware/common/rad1o/ubuntu18.h b/firmware/common/rad1o/ubuntu18.h index 38b58e76..b8d28b07 100644 --- a/firmware/common/rad1o/ubuntu18.h +++ b/firmware/common/rad1o/ubuntu18.h @@ -1,6 +1,3 @@ -#ifndef __RAD1O_UBUNTU18_H__ -#define __RAD1O_UBUNTU18_H__ +#pragma once extern const struct FONT_DEF Font_Ubuntu18pt; - -#endif diff --git a/firmware/common/radio.h b/firmware/common/radio.h index 7b526a9d..d384f189 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __RF_CONFIG_H__ -#define __RF_CONFIG_H__ +#pragma once #include #include @@ -254,5 +253,3 @@ bool radio_update(radio_t* const radio); * the request bank for the new mode. */ void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode); - -#endif /*__RF_CONFIG_H__*/ diff --git a/firmware/common/rf_path.h b/firmware/common/rf_path.h index 2d098d86..ff912fe0 100644 --- a/firmware/common/rf_path.h +++ b/firmware/common/rf_path.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __RFPATH_H__ -#define __RFPATH_H__ +#pragma once #include @@ -96,5 +95,3 @@ void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter) void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable); void rf_path_set_antenna(rf_path_t* const rf_path, const uint_fast8_t enable); - -#endif /*__RFPATH_H__*/ diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index 506f1a09..1ddf4728 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __RFFC5071_H -#define __RFFC5071_H +#pragma once #include #include @@ -71,5 +70,3 @@ extern void rffc5071_set_gpo(rffc5071_driver_t* const drv, uint8_t); extern bool rffc5071_poll_ld(rffc5071_driver_t* const drv, uint8_t* prelock_state); #endif extern bool rffc5071_check_lock(rffc5071_driver_t* const drv); - -#endif // __RFFC5071_H diff --git a/firmware/common/rffc5071_regs.def b/firmware/common/rffc5071_regs.def index 022010c0..dd352a03 100644 --- a/firmware/common/rffc5071_regs.def +++ b/firmware/common/rffc5071_regs.def @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __RFFC5071_REGS_DEF -#define __RFFC5071_REGS_DEF +#pragma once #define RFFC5071_REG_SET_CLEAN(_d, _r) (_d->regs_dirty &= ~(1UL<<_r)) #define RFFC5071_REG_SET_DIRTY(_d, _r) (_d->regs_dirty |= (1UL<<_r)) @@ -257,5 +256,3 @@ __MREG__(RFFC5071_LFSR,30,9,1) __MREG__(RFFC5071_TSEL,30,10,2) __MREG__(RFFC5071_TMUX,30,12,3) __MREG__(RFFC5071_TEN,30,15,1) - -#endif // __RFFC5071_REGS_DEF diff --git a/firmware/common/rffc5071_spi.h b/firmware/common/rffc5071_spi.h index 7df2d8bf..ab10b47b 100644 --- a/firmware/common/rffc5071_spi.h +++ b/firmware/common/rffc5071_spi.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __RFFC5071_SPI_H -#define __RFFC5071_SPI_H +#pragma once #include @@ -41,5 +40,3 @@ void rffc5071_spi_transfer_gather( spi_bus_t* const bus, const spi_transfer_t* const transfer, const size_t count); - -#endif // __RFFC5071_SPI_H diff --git a/firmware/common/rom_iap.h b/firmware/common/rom_iap.h index 50cfcf93..8b027342 100644 --- a/firmware/common/rom_iap.h +++ b/firmware/common/rom_iap.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __ROM_IAP__ -#define __ROM_IAP__ +#pragma once #include #include @@ -93,7 +92,7 @@ typedef enum INVALID_FLASH_UNIT = 0x00000014, /* Invalid flash unit. */ USER_CODE_CHECKSUM = 0x00000015, ERROR_SETTING_ACTIVE_PARTITION = 0x00000016, - + /* Special Error */ ERROR_IAP_NOT_IMPLEMENTED = 0x00000100 /* IAP is not implemented in this part */ } isp_iap_ret_code_t; @@ -118,5 +117,3 @@ typedef struct { bool iap_is_implemented(void); isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res); - -#endif //__ROM_IAP__ diff --git a/firmware/common/sct.h b/firmware/common/sct.h index 61c43199..5bedfa75 100644 --- a/firmware/common/sct.h +++ b/firmware/common/sct.h @@ -19,6 +19,8 @@ * Boston, MA 02110-1301, USA. */ +#pragma once + #include #include diff --git a/firmware/common/selftest.h b/firmware/common/selftest.h index 86ee2213..28e02415 100644 --- a/firmware/common/selftest.h +++ b/firmware/common/selftest.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __SELFTEST_H -#define __SELFTEST_H +#pragma once #include #include @@ -76,5 +75,3 @@ typedef struct { } selftest_t; extern selftest_t selftest; - -#endif // __SELFTEST_H diff --git a/firmware/common/sgpio.h b/firmware/common/sgpio.h index 08d7d222..f1cf5a0f 100644 --- a/firmware/common/sgpio.h +++ b/firmware/common/sgpio.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __SGPIO_H__ -#define __SGPIO_H__ +#pragma once #include #include @@ -50,5 +49,3 @@ void sgpio_cpld_stream_disable(sgpio_config_t* const config); bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config); void sgpio_cpld_set_mixer_invert(sgpio_config_t* const config, uint_fast8_t invert); - -#endif //__SGPIO_H__ diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index d151a74d..8168477e 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __SI5351C_H -#define __SI5351C_H +#pragma once #ifdef __cplusplus extern "C" { @@ -115,5 +114,3 @@ void si5351c_set_phase( #ifdef __cplusplus } #endif - -#endif /* __SI5351C_H */ diff --git a/firmware/common/spi_bus.h b/firmware/common/spi_bus.h index cd885644..4e6caee2 100644 --- a/firmware/common/spi_bus.h +++ b/firmware/common/spi_bus.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __SPI_BUS_H__ -#define __SPI_BUS_H__ +#pragma once #include @@ -52,5 +51,3 @@ void spi_bus_transfer_gather( spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count); - -#endif /*__SPI_BUS_H__*/ diff --git a/firmware/common/spi_ssp.h b/firmware/common/spi_ssp.h index 2325f49f..64cd2ee1 100644 --- a/firmware/common/spi_ssp.h +++ b/firmware/common/spi_ssp.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __SPI_SSP_H__ -#define __SPI_SSP_H__ +#pragma once #include #include @@ -46,5 +45,3 @@ void spi_ssp_transfer_gather( spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count); - -#endif /*__SPI_SSP_H__*/ diff --git a/firmware/common/streaming.h b/firmware/common/streaming.h index 47f466c1..47af5120 100644 --- a/firmware/common/streaming.h +++ b/firmware/common/streaming.h @@ -21,12 +21,9 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __STREAMING_H__ -#define __STREAMING_H__ +#pragma once #include void baseband_streaming_enable(sgpio_config_t* const sgpio_config); void baseband_streaming_disable(sgpio_config_t* const sgpio_config); - -#endif /*__STREAMING_H__*/ diff --git a/firmware/common/tune_config.h b/firmware/common/tune_config.h index dd21d028..7fc76af9 100644 --- a/firmware/common/tune_config.h +++ b/firmware/common/tune_config.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __TUNE_CONFIG_H__ -#define __TUNE_CONFIG_H__ +#pragma once #ifdef PRALINE #include "fpga.h" @@ -391,5 +390,3 @@ static const tune_config_t praline_tune_config_rx[] = { }; // clang-format on #endif - -#endif /*__TUNE_CONFIG_H__*/ diff --git a/firmware/common/tuning.h b/firmware/common/tuning.h index b76dbcc3..559638ac 100644 --- a/firmware/common/tuning.h +++ b/firmware/common/tuning.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __TUNING_H__ -#define __TUNING_H__ +#pragma once #include #include @@ -46,5 +45,3 @@ bool tuning_set_frequency( const uint64_t freq, const uint32_t offset); #endif - -#endif /*__TUNING_H__*/ diff --git a/firmware/common/ui_portapack.h b/firmware/common/ui_portapack.h index 0565cf6a..e0695839 100644 --- a/firmware/common/ui_portapack.h +++ b/firmware/common/ui_portapack.h @@ -20,11 +20,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __UI_PORTAPACK_H__ -#define __UI_PORTAPACK_H__ +#pragma once #include "hackrf_ui.h" const hackrf_ui_t* portapack_hackrf_ui_init(void) __attribute__((weak)); - -#endif /*__UI_PORTAPACK_H__*/ diff --git a/firmware/common/ui_rad1o.h b/firmware/common/ui_rad1o.h index 5b3e7421..73350d11 100644 --- a/firmware/common/ui_rad1o.h +++ b/firmware/common/ui_rad1o.h @@ -20,11 +20,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __UI_RAD1O_H__ -#define __UI_RAD1O_H__ +#pragma once #include "hackrf_ui.h" const hackrf_ui_t* rad1o_ui_setup(void) __attribute__((weak)); - -#endif /*__UI_RAD1O_H__*/ diff --git a/firmware/common/usb.h b/firmware/common/usb.h index ee2ff9b6..9445728a 100644 --- a/firmware/common/usb.h +++ b/firmware/common/usb.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_H__ -#define __USB_H__ +#pragma once #include #include @@ -77,5 +76,3 @@ void usb_endpoint_schedule_append( const usb_endpoint_t* const endpoint, usb_transfer_descriptor_t* const tail_td, usb_transfer_descriptor_t* const new_td); - -#endif //__USB_H__ diff --git a/firmware/common/usb_queue.h b/firmware/common/usb_queue.h index 8793558f..66849362 100644 --- a/firmware/common/usb_queue.h +++ b/firmware/common/usb_queue.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_QUEUE_H__ -#define __USB_QUEUE_H__ +#pragma once #include @@ -82,4 +81,3 @@ void usb_queue_init(usb_queue_t* const queue); void usb_queue_transfer_complete(usb_endpoint_t* const endpoint); -#endif //__USB_QUEUE_H__ diff --git a/firmware/common/usb_request.h b/firmware/common/usb_request.h index 40d5013d..c61d77d6 100644 --- a/firmware/common/usb_request.h +++ b/firmware/common/usb_request.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_REQUEST_H__ -#define __USB_REQUEST_H__ +#pragma once #include "usb_type.h" @@ -61,5 +60,3 @@ void usb_setup_complete(usb_endpoint_t* const endpoint); void usb_control_in_complete(usb_endpoint_t* const endpoint); void usb_control_out_complete(usb_endpoint_t* const endpoint); - -#endif //__USB_REQUEST_H__ diff --git a/firmware/common/usb_standard_request.h b/firmware/common/usb_standard_request.h index e9ea9f69..84a8c458 100644 --- a/firmware/common/usb_standard_request.h +++ b/firmware/common/usb_standard_request.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_STANDARD_REQUEST_H__ -#define __USB_STANDARD_REQUEST_H__ +#pragma once #include #include @@ -50,5 +49,3 @@ usb_transfer_type_t usb_endpoint_descriptor_transfer_type( bool usb_set_configuration( usb_device_t* const device, const uint_fast8_t configuration_number); - -#endif //__USB_STANDARD_REQUEST_H__ diff --git a/firmware/common/usb_type.h b/firmware/common/usb_type.h index b268c6bb..2f68b91f 100644 --- a/firmware/common/usb_type.h +++ b/firmware/common/usb_type.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_TYPE_H__ -#define __USB_TYPE_H__ +#pragma once #include @@ -157,5 +156,3 @@ struct usb_endpoint_t { void (*setup_complete)(usb_endpoint_t* const endpoint); void (*transfer_complete)(usb_endpoint_t* const endpoint); }; - -#endif //__USB_TYPE_H__ diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index f737afe6..4361f4b7 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __W25Q80BV_H__ -#define __W25Q80BV_H__ +#pragma once #include #include @@ -69,5 +68,3 @@ void w25q80bv_read( uint32_t len, uint8_t* const data); void w25q80bv_clear_status(w25q80bv_driver_t* const drv); - -#endif //__W25Q80BV_H__ diff --git a/firmware/common/w25q80bv_target.h b/firmware/common/w25q80bv_target.h index 2fad7aa3..8da28d25 100644 --- a/firmware/common/w25q80bv_target.h +++ b/firmware/common/w25q80bv_target.h @@ -20,11 +20,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __W25Q80BV_TARGET_H__ -#define __W25Q80BV_TARGET_H__ +#pragma once #include "w25q80bv.h" void w25q80bv_target_init(w25q80bv_driver_t* const drv); - -#endif /*__W25Q80BV_TARGET_H__*/ diff --git a/firmware/hackrf_usb/usb_api_adc.h b/firmware/hackrf_usb/usb_api_adc.h index e321267e..ed4e7f93 100644 --- a/firmware/hackrf_usb/usb_api_adc.h +++ b/firmware/hackrf_usb/usb_api_adc.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_API_ADC_H__ -#define __USB_API_ADC_H__ +#pragma once #include #include @@ -28,5 +27,3 @@ usb_request_status_t usb_vendor_request_adc_read( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); - -#endif // __USB_API_ADC_H__ diff --git a/firmware/hackrf_usb/usb_api_board_info.h b/firmware/hackrf_usb/usb_api_board_info.h index 77e4066d..ec50d7ce 100644 --- a/firmware/hackrf_usb/usb_api_board_info.h +++ b/firmware/hackrf_usb/usb_api_board_info.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_API_BOARD_INFO_H__ -#define __USB_API_BOARD_INFO_H__ +#pragma once #include @@ -52,5 +51,3 @@ usb_request_status_t usb_vendor_request_read_board_rev( usb_request_status_t usb_vendor_request_read_supported_platform( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); - -#endif /* end of include guard: __USB_API_BOARD_INFO_H__ */ diff --git a/firmware/hackrf_usb/usb_api_cpld.h b/firmware/hackrf_usb/usb_api_cpld.h index f508ea5f..786a9160 100644 --- a/firmware/hackrf_usb/usb_api_cpld.h +++ b/firmware/hackrf_usb/usb_api_cpld.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_API_CPLD_H__ -#define __USB_API_CPLD_H__ +#pragma once #include #include @@ -32,5 +31,3 @@ void cpld_update(void); usb_request_status_t usb_vendor_request_cpld_checksum( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); - -#endif /* end of include guard: __USB_API_CPLD_H__ */ diff --git a/firmware/hackrf_usb/usb_api_m0_state.h b/firmware/hackrf_usb/usb_api_m0_state.h index 4e7ba2a4..a08188d7 100644 --- a/firmware/hackrf_usb/usb_api_m0_state.h +++ b/firmware/hackrf_usb/usb_api_m0_state.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __M0_STATE_USB_H__ -#define __M0_STATE_USB_H__ +#pragma once #include #include @@ -28,5 +27,3 @@ usb_request_status_t usb_vendor_request_get_m0_state( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); - -#endif /*__M0_STATE_USB_H__*/ diff --git a/firmware/hackrf_usb/usb_api_operacake.h b/firmware/hackrf_usb/usb_api_operacake.h index 6e772ec1..824311aa 100644 --- a/firmware/hackrf_usb/usb_api_operacake.h +++ b/firmware/hackrf_usb/usb_api_operacake.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_API_OPERACAKE_H__ -#define __USB_API_OPERACAKE_H__ +#pragma once #include #include @@ -53,5 +52,3 @@ usb_request_status_t usb_vendor_request_operacake_get_mode( usb_request_status_t usb_vendor_request_operacake_set_dwell_times( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); - -#endif /* end of include guard: __USB_API_OPERACAKE_H__ */ diff --git a/firmware/hackrf_usb/usb_api_praline.h b/firmware/hackrf_usb/usb_api_praline.h index df96c921..97816373 100644 --- a/firmware/hackrf_usb/usb_api_praline.h +++ b/firmware/hackrf_usb/usb_api_praline.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_API_PRALINE_H__ -#define __USB_API_PRALINE_H__ +#pragma once #include #include @@ -44,5 +43,3 @@ usb_request_status_t usb_vendor_request_set_narrowband_filter( usb_request_status_t usb_vendor_request_set_fpga_bitstream( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); - -#endif /* end of include guard: __USB_API_PRALINE_H__ */ diff --git a/firmware/hackrf_usb/usb_api_register.h b/firmware/hackrf_usb/usb_api_register.h index c94710cb..24825144 100644 --- a/firmware/hackrf_usb/usb_api_register.h +++ b/firmware/hackrf_usb/usb_api_register.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_API_REGISTER_H__ -#define __USB_API_REGISTER_H__ +#pragma once #include #include @@ -71,5 +70,3 @@ usb_request_status_t usb_vendor_request_write_radio_reg( usb_request_status_t usb_vendor_request_read_radio_reg( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); - -#endif /* end of include guard: __USB_API_REGISTER_H__ */ diff --git a/firmware/hackrf_usb/usb_api_selftest.h b/firmware/hackrf_usb/usb_api_selftest.h index 69478653..7f5af7da 100644 --- a/firmware/hackrf_usb/usb_api_selftest.h +++ b/firmware/hackrf_usb/usb_api_selftest.h @@ -19,8 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_API_SELFTEST_H -#define __USB_API_SELFTEST_H +#pragma once #include #include @@ -32,5 +31,3 @@ usb_request_status_t usb_vendor_request_read_selftest( usb_request_status_t usb_vendor_request_test_rtc_osc( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); - -#endif // __USB_API_SELFTEST_H diff --git a/firmware/hackrf_usb/usb_api_spiflash.h b/firmware/hackrf_usb/usb_api_spiflash.h index 726734a2..f8e3209f 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.h +++ b/firmware/hackrf_usb/usb_api_spiflash.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_API_SPIFLASH_H__ -#define __USB_API_SPIFLASH_H__ +#pragma once #include #include @@ -42,5 +41,3 @@ usb_request_status_t usb_vendor_request_spiflash_status( usb_request_status_t usb_vendor_request_spiflash_clear_status( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); - -#endif /* end of include guard: __USB_API_SPIFLASH_H__ */ diff --git a/firmware/hackrf_usb/usb_api_sweep.h b/firmware/hackrf_usb/usb_api_sweep.h index 95cfe848..cf4c84ad 100644 --- a/firmware/hackrf_usb/usb_api_sweep.h +++ b/firmware/hackrf_usb/usb_api_sweep.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_API_SWEEP_H__ -#define __USB_API_SWEEP_H__ +#pragma once #include @@ -38,5 +37,3 @@ usb_request_status_t usb_vendor_request_init_sweep( const usb_transfer_stage_t stage); void sweep_mode(uint32_t seq); - -#endif /* __USB_API_SWEEP_H__ */ diff --git a/firmware/hackrf_usb/usb_api_transceiver.h b/firmware/hackrf_usb/usb_api_transceiver.h index e28e6bbb..02385acf 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.h +++ b/firmware/hackrf_usb/usb_api_transceiver.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_API_TRANSCEIVER_H__ -#define __USB_API_TRANSCEIVER_H__ +#pragma once #include @@ -83,5 +82,3 @@ void transceiver_shutdown(void); void rx_mode(uint32_t seq); void tx_mode(uint32_t seq); void off_mode(uint32_t seq); - -#endif /*__USB_API_TRANSCEIVER_H__*/ diff --git a/firmware/hackrf_usb/usb_api_ui.h b/firmware/hackrf_usb/usb_api_ui.h index 62eecfa7..56688ca1 100644 --- a/firmware/hackrf_usb/usb_api_ui.h +++ b/firmware/hackrf_usb/usb_api_ui.h @@ -20,8 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_API_UI_H__ -#define __USB_API_UI_H__ +#pragma once #include #include @@ -29,5 +28,3 @@ usb_request_status_t usb_vendor_request_set_ui_enable( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); - -#endif /* end of include guard: __USB_API_UI_H__ */ diff --git a/firmware/hackrf_usb/usb_bulk_buffer.h b/firmware/hackrf_usb/usb_bulk_buffer.h index f3021bf5..e21a84ff 100644 --- a/firmware/hackrf_usb/usb_bulk_buffer.h +++ b/firmware/hackrf_usb/usb_bulk_buffer.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_BULK_BUFFER_H__ -#define __USB_BULK_BUFFER_H__ +#pragma once #include @@ -34,5 +33,3 @@ * unless you also adjust the ldscripts. */ extern uint8_t usb_bulk_buffer[USB_BULK_BUFFER_SIZE]; - -#endif /*__USB_BULK_BUFFER_H__*/ diff --git a/firmware/hackrf_usb/usb_descriptor.h b/firmware/hackrf_usb/usb_descriptor.h index 2c2990e0..097ccce0 100644 --- a/firmware/hackrf_usb/usb_descriptor.h +++ b/firmware/hackrf_usb/usb_descriptor.h @@ -20,6 +20,8 @@ * Boston, MA 02110-1301, USA. */ +#pragma once + #include extern uint8_t usb_descriptor_device[]; diff --git a/firmware/hackrf_usb/usb_device.h b/firmware/hackrf_usb/usb_device.h index 05008dca..79df298d 100644 --- a/firmware/hackrf_usb/usb_device.h +++ b/firmware/hackrf_usb/usb_device.h @@ -21,11 +21,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_DEVICE_H__ -#define __USB_DEVICE_H__ +#pragma once #include extern usb_device_t usb_device; - -#endif /* end of include guard: __USB_DEVICE_H__ */ diff --git a/firmware/hackrf_usb/usb_endpoint.h b/firmware/hackrf_usb/usb_endpoint.h index acb86ab5..e96094f6 100644 --- a/firmware/hackrf_usb/usb_endpoint.h +++ b/firmware/hackrf_usb/usb_endpoint.h @@ -21,8 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __USB_ENDPOINT_H__ -#define __USB_ENDPOINT_H__ +#pragma once #include #include @@ -38,5 +37,3 @@ extern USB_DECLARE_QUEUE(usb_endpoint_bulk_in); extern usb_endpoint_t usb_endpoint_bulk_out; extern USB_DECLARE_QUEUE(usb_endpoint_bulk_out); - -#endif /* end of include guard: __USB_ENDPOINT_H__ */ From 5f8601b8c888a66b9d04683e3f71fdc9ca54faf7 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Fri, 20 Mar 2026 10:18:09 +0200 Subject: [PATCH 075/238] host: replace include guards with #pragma once --- firmware/common/rad1o/render.h | 1 - firmware/common/usb_queue.h | 1 - host/libhackrf/src/hackrf.h | 5 +---- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/firmware/common/rad1o/render.h b/firmware/common/rad1o/render.h index 8d97b6e1..535ee471 100644 --- a/firmware/common/rad1o/render.h +++ b/firmware/common/rad1o/render.h @@ -9,4 +9,3 @@ void rad1o_setIntFont(const struct FONT_DEF* font); int rad1o_getFontHeight(void); int rad1o_DoString(int sx, int sy, const char* s); int rad1o_DoChar(int sx, int sy, int c); - diff --git a/firmware/common/usb_queue.h b/firmware/common/usb_queue.h index 66849362..33f6def2 100644 --- a/firmware/common/usb_queue.h +++ b/firmware/common/usb_queue.h @@ -80,4 +80,3 @@ int usb_transfer_schedule_ack(const usb_endpoint_t* const endpoint); void usb_queue_init(usb_queue_t* const queue); void usb_queue_transfer_complete(usb_endpoint_t* const endpoint); - diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index e00ba3ff..eeca65e0 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -21,8 +21,7 @@ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABI ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __HACKRF_H__ -#define __HACKRF_H__ +#pragma once #include #include @@ -2389,5 +2388,3 @@ extern ADDAPI int ADDCALL hackrf_radio_write_register( #ifdef __cplusplus } // __cplusplus defined. #endif - -#endif /*__HACKRF_H__*/ From e9986d4601624ecc0dc56408a450e9129770c21f Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Wed, 1 Apr 2026 10:33:44 +0200 Subject: [PATCH 076/238] repo: add include-what-you-use mapping file for libopencm3 --- firmware/common/radio.c | 1 - firmware/common/usb.c | 1 - firmware/hackrf_usb/hackrf_usb.c | 3 +-- firmware/hackrf_usb/usb_api_sweep.c | 1 - firmware/libopencm3.imp | 11 +++++++++++ 5 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 firmware/libopencm3.imp diff --git a/firmware/common/radio.c b/firmware/common/radio.c index cb441a64..d22ba700 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -22,7 +22,6 @@ #include #include -#include #include "fixed_point.h" #include "hackrf_core.h" diff --git a/firmware/common/usb.c b/firmware/common/usb.c index 64cd6c08..026b7ec9 100644 --- a/firmware/common/usb.c +++ b/firmware/common/usb.c @@ -25,7 +25,6 @@ #include #include -#include #include #include diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 6170ce6d..3126ac0c 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -25,9 +25,8 @@ #include #include -#include -#include #include +#include #include #include diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index 782f69cd..2ad3203d 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -24,7 +24,6 @@ #include #include -#include #include #include diff --git a/firmware/libopencm3.imp b/firmware/libopencm3.imp new file mode 100644 index 00000000..1cf19631 --- /dev/null +++ b/firmware/libopencm3.imp @@ -0,0 +1,11 @@ +# include-what-you-use mapping file for libopencm3/ +# +# Usage: include-what-you-use -Xiwyu;--mapping_file=libopencm3.imp + +[ + # allow libopencm3 to take responsibility for architecture-specific dispatch of nvic.h includes + { "include": ["", "private", "", "public"] }, + { "include": ["\"libopencm3/lpc43xx/m0/nvic.h\"", "private", "", "public"] }, + { "include": ["", "private", "", "public"] }, + { "include": ["\"libopencm3/lpc43xx/m4/nvic.h\"", "private", "", "public"] }, +] From 1c29079faf82ea4fff80a2b50ea4069222b4cb2f Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Wed, 1 Apr 2026 19:42:32 -0400 Subject: [PATCH 077/238] Reset only sample clock outputs when changing rate --- firmware/common/hackrf_core.c | 4 +- firmware/common/si5351c.c | 77 ++++++++++++++++++++++++++--------- firmware/common/si5351c.h | 14 ++++--- 3 files changed, 69 insertions(+), 26 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 8db0e855..241c2e3d 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -325,7 +325,7 @@ fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program) } /* Reset PLL to synchronize output clock phase. */ - si5351c_reset_pll(&clock_gen); + si5351c_reset_pll(&clock_gen, SI5351C_PLL_A); #endif if (streaming) { @@ -622,7 +622,7 @@ void clock_gen_init(void) si5351c_configure_clock_control(&clock_gen); si5351c_set_clock_source(&clock_gen, PLL_SOURCE_XTAL); // soft reset - si5351c_reset_pll(&clock_gen); + si5351c_reset_pll(&clock_gen, SI5351C_PLL_BOTH); si5351c_enable_clock_outputs(&clock_gen); } diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 8b6e52fd..ceb9f4a9 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -41,6 +41,7 @@ static enum pll_sources active_clock_source = PLL_SOURCE_UNINITIALIZED; /* External clock output default is deactivated as it creates noise */ static bool clkout_enabled = false; +static uint8_t outputs_disabled = 0xff; /* write to single register */ void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val) @@ -73,7 +74,30 @@ void si5351c_write( /* Disable all CLKx outputs. */ void si5351c_disable_all_outputs(si5351c_driver_t* const drv) { - uint8_t data[] = {3, 0xFF}; + outputs_disabled = 0xff; + uint8_t data[] = {3, outputs_disabled}; + si5351c_write(drv, data, sizeof(data)); +} + +/* Disable all CLKx outputs using selected PLL. */ +void si5351c_disable_pll_outputs(si5351c_driver_t* const drv, si5351c_pll_t pll) +{ + /* + * Bitmask defines outputs using PLL B. Other outputs are assumed to + * use PLL A. + */ + uint8_t pllb_outputs = 0x00; + if (detected_platform() == BOARD_ID_PRALINE) { + pllb_outputs = 0x30; + } + + if (pll & SI5351C_PLL_A) { + outputs_disabled |= ~pllb_outputs; + } + if (pll & SI5351C_PLL_B) { + outputs_disabled |= pllb_outputs; + } + uint8_t data[] = {3, outputs_disabled}; si5351c_write(drv, data, sizeof(data)); } @@ -156,11 +180,19 @@ void si5351c_configure_pll_multisynth( si5351c_write(drv, data, sizeof(data)); } -void si5351c_reset_pll(si5351c_driver_t* const drv) +void si5351c_reset_pll(si5351c_driver_t* const drv, si5351c_pll_t pll) { - si5351c_disable_all_outputs(drv); - /* reset PLLA and PLLB */ - uint8_t data[] = {177, 0xA0}; + uint8_t value = 0; + + if (pll & SI5351C_PLL_A) { + value |= 0x20; + } + if (pll & SI5351C_PLL_B) { + value |= 0x80; + } + + si5351c_disable_pll_outputs(drv, pll); + uint8_t data[] = {177, value}; si5351c_write(drv, data, sizeof(data)); delay_us_at_mhz(2000, 204); si5351c_enable_clock_outputs(drv); @@ -202,11 +234,10 @@ void si5351c_configure_multisynth( void si5351c_configure_clock_control(si5351c_driver_t* const drv) { - const uint8_t pll = SI5351C_CLK_PLL_SRC_A; uint8_t clkout_ctrl; if (clkout_enabled) { - clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | + clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA); } else { @@ -217,20 +248,20 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv) /* External clock output is kept in current state */ uint8_t data[] = { 16, - SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) | + SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA), - SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | + SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA) | SI5351C_CLK_INV, - SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | + SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA), clkout_ctrl, - SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | + SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA) | SI5351C_CLK_INV, - SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | + SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA), SI5351C_CLK_POWERDOWN | @@ -239,10 +270,10 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv) SI5351C_CLK_INT_MODE /* not connected, but: PLL B int mode */ }; if (detected_platform() == BOARD_ID_HACKRF1_R9) { - data[1] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC_A | + data[1] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA); - data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC_A | + data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA); data[3] = clkout_ctrl; @@ -252,20 +283,27 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv) } #ifdef PRALINE /* CLK0: AFE_CLK */ - data[1] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) | + data[1] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA); /* CLK1: SCT_CLK and FPGA_CLK */ - data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) | + data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA); + /* CLK3: CLKOUT */ + clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) | + SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | + SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA); /* CLK4: XCVR_CLK */ - data[5] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | + data[5] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA) | SI5351C_CLK_INV; + data[6] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) | + SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | + SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA); if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { /* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */ - data[3] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) | + data[3] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA); } else { @@ -317,6 +355,7 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) SI5351C_CLK_DISABLE(clkout); uint8_t data[] = {SI5351C_REG_OUTPUT_EN, value}; si5351c_write(drv, data, sizeof(data)); + outputs_disabled = value; #if defined(HACKRF_ONE) if (detected_platform() == BOARD_ID_HACKRF1_R9) { @@ -375,7 +414,7 @@ void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_source } si5351c_configure_pll_multisynth(drv, source); active_clock_source = source; - si5351c_reset_pll(drv); + si5351c_reset_pll(drv, SI5351C_PLL_BOTH); } bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv) diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index d151a74d..52438886 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -39,10 +39,6 @@ extern "C" { #define SI5351C_CLK_INT_MODE (1 << 6) #define SI5351C_CLK_FRAC_MODE (0 << 6) -#define SI5351C_CLK_PLL_SRC(x) (x << 5) -#define SI5351C_CLK_PLL_SRC_A 0 -#define SI5351C_CLK_PLL_SRC_B 1 - #define SI5351C_CLK_INV (1 << 4) #define SI5351C_CLK_SRC(x) (x << 2) @@ -60,6 +56,14 @@ extern "C" { #define SI5351C_LOS (1 << 4) #define SI5351C_REVID 0x03 +typedef enum { + SI5351C_PLL_A = 1, + SI5351C_PLL_B = 2, + SI5351C_PLL_BOTH = 3, +} si5351c_pll_t; + +#define SI5351C_CLK_PLL_SRC(x) ((x & SI5351C_PLL_B) << 4) + enum pll_sources { PLL_SOURCE_UNINITIALIZED = -1, PLL_SOURCE_XTAL = 0, @@ -82,7 +86,7 @@ void si5351c_configure_pll_sources( void si5351c_configure_pll_multisynth( si5351c_driver_t* const drv, const enum pll_sources source); -void si5351c_reset_pll(si5351c_driver_t* const drv); +void si5351c_reset_pll(si5351c_driver_t* const drv, si5351c_pll_t pll); void si5351c_configure_multisynth( si5351c_driver_t* const drv, const uint_fast8_t ms_number, From 98bdd30197c92d5a77f66a80c27656a13d8fe35f Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 2 Apr 2026 14:11:33 +0200 Subject: [PATCH 078/238] ci: add a includes-check workflow that runs include-what-you-use on the firmware sources --- .github/workflows/includes-check.yml | 74 ++++++++++++++++++++++++++++ firmware/CMakeLists.txt | 7 +++ firmware/include-what-you-use.cmake | 38 ++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 .github/workflows/includes-check.yml create mode 100644 firmware/include-what-you-use.cmake diff --git a/.github/workflows/includes-check.yml b/.github/workflows/includes-check.yml new file mode 100644 index 00000000..f3848754 --- /dev/null +++ b/.github/workflows/includes-check.yml @@ -0,0 +1,74 @@ +name: Check includes +on: [push, pull_request] + +jobs: + includes-check: + runs-on: ubuntu-latest + strategy: + matrix: + board: ['HACKRF_ONE', 'JAWBREAKER', 'RAD1O', 'PRALINE'] + cmake: ['3.10.0', 'latest'] + + # Don't cancel all builds when one fails + fail-fast: false + + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + - name: Setup cmake + uses: jwlawson/actions-setup-cmake@v2 + with: + cmake-version: ${{ matrix.cmake }} + + - name: Install Arm GNU Toolchain + uses: carlosperate/arm-none-eabi-gcc-action@v1 + + - name: Install dependencies + run: | + python3 -m venv environment && source environment/bin/activate + python3 -m pip install PyYAML + sudo apt update + sudo apt install iwyu + + - name: Build libopencm3 + shell: bash + working-directory: ${{github.workspace}}/firmware/libopencm3/ + run: | + source ../../environment/bin/activate + make + + - name: Create Build Environment + run: cmake -E make_directory ${{github.workspace}}/firmware/build + + - name: Configure CMake + shell: bash + working-directory: ${{github.workspace}}/firmware/build + run: cmake $GITHUB_WORKSPACE/firmware/ -DCMAKE_BUILD_TYPE=Release -DBOARD=${{ matrix.board }} -DCHECK_INCLUDES=1 + + - name: Build + working-directory: ${{github.workspace}}/firmware/build + shell: bash + run: | + source ../../environment/bin/activate + output="$(cmake --build . --config Release 2>&1)" + while IFS= read -r line + do + if [[ "${line}" == "Warning: include-what-you-use"* ]]; then + exit_code=1 + dump=1 + elif [[ "${line}" == "---" ]]; then + dump=0 + fi + if [[ ${dump} == "1" ]]; then + echo "${line}" + fi + done <<< ${output} + if [[ ${exit_code} == "1" ]]; then + echo "Includes check failed for board target: ${{ matrix.board }}" + else + echo "Includes check succeeded for board target: ${{ matrix.board }}" + fi + echo $(include-what-you-use --version) + exit ${exit_code} diff --git a/firmware/CMakeLists.txt b/firmware/CMakeLists.txt index 10c2d09d..611e7870 100644 --- a/firmware/CMakeLists.txt +++ b/firmware/CMakeLists.txt @@ -20,10 +20,17 @@ # Top directory CMake project for HackRF firmware +option(CHECK_INCLUDES + "Check firmware sources for unused includes and transitive dependencies. (Requires iwyu)" OFF) + cmake_minimum_required(VERSION 3.10.0) set(CMAKE_TOOLCHAIN_FILE toolchain-arm-cortex-m.cmake) project (hackrf_firmware_all C) +if(CHECK_INCLUDES) + include(include-what-you-use.cmake) +endif() + add_subdirectory(blinky) add_subdirectory(hackrf_usb) diff --git a/firmware/include-what-you-use.cmake b/firmware/include-what-you-use.cmake new file mode 100644 index 00000000..b5c1bc7e --- /dev/null +++ b/firmware/include-what-you-use.cmake @@ -0,0 +1,38 @@ +# Copyright 2026 Great Scott Gadgets +# +# This file is part of HackRF. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +cmake_minimum_required(VERSION 3.10.0) + +find_program(IWYU_COMMAND NAMES include-what-you-use) +if(NOT IWYU_COMMAND) + message(FATAL_ERROR "Could not find the include-what-you-use executable.") +endif() + +# include-what-you-use arguments: +# +# --no_fwd_decls - Disable forward declaration suggestions. +# --mapping_file - Specify mapping files for excluding suggestions. +# +list(APPEND IWYU_COMMAND + -Xiwyu --no_fwd_decls + -Xiwyu --mapping_file=${CMAKE_SOURCE_DIR}/libopencm3.imp) + +set(CMAKE_C_INCLUDE_WHAT_YOU_USE ${IWYU_COMMAND}) +set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${IWYU_COMMAND}) From a06232270eb06db83255127a8e279884e570d324 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 7 Apr 2026 04:34:20 +0100 Subject: [PATCH 079/238] Fix issues with clang-format version detection. Recent versions include a suffix in brackets, e.g: $ clang-format --version Debian clang-format version 21.1.8 (3+b1) Require a specific version rather than a minimum one, due to differences in output between versions. --- tools/reformat-source.sh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/reformat-source.sh b/tools/reformat-source.sh index 754717c4..525c9afc 100755 --- a/tools/reformat-source.sh +++ b/tools/reformat-source.sh @@ -1,12 +1,14 @@ #!/bin/bash -VERSION=`clang-format --version | grep -o '[^ ]*$' | cut -d '.' -f 1` -if [ "$VERSION" -ge "14" ]; then +REQUIRED_VERSION=14 + +VERSION=`clang-format --version | grep -o 'version [^ ]' | cut -d ' ' -f 2 | cut -d '.' -f 1` +if [ "$VERSION" -eq "$REQUIRED_VERSION" ]; then CLANG_FORMAT=clang-format -elif clang-format-14 --version > /dev/null; then - CLANG_FORMAT=clang-format-14 +elif command -v clang-format-$REQUIRED_VERSION > /dev/null; then + CLANG_FORMAT=clang-format-$REQUIRED_VERSION else - echo "clang-format version 14 or higher is required." + echo "clang-format version $REQUIRED_VERSION is required." exit 1 fi From b11f6b2f7e21a001e27c762d89c9dbea1a0e5ff8 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Fri, 20 Mar 2026 15:19:45 +0200 Subject: [PATCH 080/238] firmware: standardize struct+typedef usage --- firmware/common/cpld_jtag.h | 4 ++-- firmware/common/fault_handler.h | 6 ++---- firmware/common/fpga.h | 7 ++----- firmware/common/gpio_lpc.h | 2 +- firmware/common/i2c_lpc.h | 2 +- firmware/common/ice40_spi.h | 7 ++----- firmware/common/portapack.c | 2 +- firmware/common/portapack.h | 14 +++++++------- firmware/common/radio.h | 2 +- firmware/common/rf_path.h | 2 +- firmware/common/rffc5071_spi.h | 2 +- firmware/common/sgpio.h | 2 +- firmware/common/spi_ssp.h | 2 +- firmware/common/ui_portapack.c | 2 +- 14 files changed, 24 insertions(+), 32 deletions(-) diff --git a/firmware/common/cpld_jtag.h b/firmware/common/cpld_jtag.h index c052334d..60036759 100644 --- a/firmware/common/cpld_jtag.h +++ b/firmware/common/cpld_jtag.h @@ -25,7 +25,7 @@ #include "gpio.h" -typedef struct jtag_gpio_t { +typedef struct { gpio_t gpio_tck; #ifndef PRALINE gpio_t gpio_tms; @@ -38,7 +38,7 @@ typedef struct jtag_gpio_t { #endif } jtag_gpio_t; -typedef struct jtag_t { +typedef struct { jtag_gpio_t* const gpio; } jtag_t; diff --git a/firmware/common/fault_handler.h b/firmware/common/fault_handler.h index d0edd6a5..0b499acb 100644 --- a/firmware/common/fault_handler.h +++ b/firmware/common/fault_handler.h @@ -29,9 +29,7 @@ // TODO: Move all this to a Cortex-M(?) include file, since these // structures are supposedly the same between processors (to an // undetermined extent). -typedef struct armv7m_scb_t armv7m_scb_t; - -struct armv7m_scb_t { +typedef struct { volatile const uint32_t CPUID; volatile uint32_t ICSR; volatile uint32_t VTOR; @@ -63,7 +61,7 @@ struct armv7m_scb_t { volatile const uint32_t ID_ISAR4; volatile const uint32_t __reserved_0x74_0x87[5]; volatile uint32_t CPACR; -} __attribute__((packed)); +} __attribute__((packed)) armv7m_scb_t; static armv7m_scb_t* const SCB = (armv7m_scb_t*) SCB_BASE; diff --git a/firmware/common/fpga.h b/firmware/common/fpga.h index 3ba3b652..4aa54239 100644 --- a/firmware/common/fpga.h +++ b/firmware/common/fpga.h @@ -36,14 +36,11 @@ typedef enum { FPGA_QUARTER_SHIFT_MODE_DOWN = 0b01, } fpga_quarter_shift_mode_t; -struct fpga_driver_t; // IWYU pragma: keep - fixed in #1704 -typedef struct fpga_driver_t fpga_driver_t; - -struct fpga_driver_t { +typedef struct { ice40_spi_driver_t* bus; uint8_t regs[FPGA_NUM_REGS]; uint8_t regs_dirty; -}; +} fpga_driver_t; struct fpga_loader_t { /* Start address added as an offset to all read() calls. */ diff --git a/firmware/common/gpio_lpc.h b/firmware/common/gpio_lpc.h index 68905ef9..0987537f 100644 --- a/firmware/common/gpio_lpc.h +++ b/firmware/common/gpio_lpc.h @@ -29,7 +29,7 @@ * register #defines and API declarations into separate header files. */ -typedef struct gpio_port { +typedef struct { volatile uint32_t dir; /* +0x000 */ uint32_t _reserved0[31]; volatile uint32_t mask; /* +0x080 */ diff --git a/firmware/common/i2c_lpc.h b/firmware/common/i2c_lpc.h index c94ca253..f5b8230e 100644 --- a/firmware/common/i2c_lpc.h +++ b/firmware/common/i2c_lpc.h @@ -28,7 +28,7 @@ #include "i2c_bus.h" -typedef struct i2c_lpc_config_t { +typedef struct { const uint16_t duty_cycle_count; } i2c_lpc_config_t; diff --git a/firmware/common/ice40_spi.h b/firmware/common/ice40_spi.h index ef97acc6..4ceddffa 100644 --- a/firmware/common/ice40_spi.h +++ b/firmware/common/ice40_spi.h @@ -28,15 +28,12 @@ #include "gpio.h" #include "spi_bus.h" -struct ice40_spi_driver_t; // IWYU pragma: keep - fixed in #1704 -typedef struct ice40_spi_driver_t ice40_spi_driver_t; - -struct ice40_spi_driver_t { +typedef struct { spi_bus_t* const bus; gpio_t gpio_select; gpio_t gpio_creset; gpio_t gpio_cdone; -}; +} ice40_spi_driver_t; void ice40_spi_target_init(ice40_spi_driver_t* const drv); uint8_t ice40_spi_read(ice40_spi_driver_t* const drv, uint8_t r); diff --git a/firmware/common/portapack.c b/firmware/common/portapack.c index fefa2f11..455df871 100644 --- a/firmware/common/portapack.c +++ b/firmware/common/portapack.c @@ -38,7 +38,7 @@ static void portapack_sleep_milliseconds(const uint32_t milliseconds) delay(milliseconds * 40800); } -typedef struct portapack_if_t { +typedef struct { gpio_t gpio_dir; gpio_t gpio_lcd_rdx; gpio_t gpio_lcd_wrx; diff --git a/firmware/common/portapack.h b/firmware/common/portapack.h index 1a43af10..fdc369b8 100644 --- a/firmware/common/portapack.h +++ b/firmware/common/portapack.h @@ -28,31 +28,31 @@ #define ARRAY_SIZEOF(x) (sizeof(x) / sizeof(x[0])) -typedef struct ui_color_t { +typedef struct { uint16_t v; } ui_color_t; -typedef struct ui_point_t { +typedef struct { int16_t x; int16_t y; } ui_point_t; -typedef struct ui_size_t { +typedef struct { int16_t width; int16_t height; } ui_size_t; -typedef struct ui_rect_t { +typedef struct { ui_point_t point; ui_size_t size; } ui_rect_t; -typedef struct ui_bitmap_t { +typedef struct { ui_size_t size; const uint8_t* const data; } ui_bitmap_t; -typedef struct ui_font_t { +typedef struct { const ui_size_t glyph_size; const uint8_t* const data; char c_start; @@ -60,7 +60,7 @@ typedef struct ui_font_t { size_t data_stride; } ui_font_t; -typedef struct portapack_t { +typedef struct { } portapack_t; void portapack_init(void); diff --git a/firmware/common/radio.h b/firmware/common/radio.h index d384f189..0c171d47 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -215,7 +215,7 @@ typedef enum { */ typedef fp_40_24_t (*sample_rate_fn)(const fp_40_24_t sample_rate, const bool program); -typedef struct radio_t { +typedef struct { radio_config_mode_t config_mode; uint64_t config[RADIO_NUM_BANKS][RADIO_NUM_REGS]; volatile uint32_t regs_dirty; diff --git a/firmware/common/rf_path.h b/firmware/common/rf_path.h index ff912fe0..1ac0e243 100644 --- a/firmware/common/rf_path.h +++ b/firmware/common/rf_path.h @@ -45,7 +45,7 @@ typedef enum { RF_PATH_FILTER_HIGH_PASS = 2, } rf_path_filter_t; -typedef struct rf_path_t { +typedef struct { uint8_t switchctrl; #ifdef HACKRF_ONE gpio_t gpio_hp; diff --git a/firmware/common/rffc5071_spi.h b/firmware/common/rffc5071_spi.h index ab10b47b..552d0769 100644 --- a/firmware/common/rffc5071_spi.h +++ b/firmware/common/rffc5071_spi.h @@ -27,7 +27,7 @@ #include "gpio.h" #include "spi_bus.h" -typedef struct rffc5071_spi_config_t { +typedef struct { gpio_t gpio_select; gpio_t gpio_clock; gpio_t gpio_data; diff --git a/firmware/common/sgpio.h b/firmware/common/sgpio.h index f1cf5a0f..a3b6b2eb 100644 --- a/firmware/common/sgpio.h +++ b/firmware/common/sgpio.h @@ -32,7 +32,7 @@ typedef enum { SGPIO_DIRECTION_TX, } sgpio_direction_t; -typedef struct sgpio_config_t { +typedef struct { gpio_t gpio_q_invert; #ifndef PRALINE gpio_t gpio_trigger_enable; diff --git a/firmware/common/spi_ssp.h b/firmware/common/spi_ssp.h index 64cd2ee1..822772b5 100644 --- a/firmware/common/spi_ssp.h +++ b/firmware/common/spi_ssp.h @@ -30,7 +30,7 @@ #include "gpio.h" #include "spi_bus.h" -typedef struct ssp_config_t { +typedef struct { ssp_datasize_t data_bits; ssp_cpol_cpha_t spi_mode; uint8_t serial_clock_rate; diff --git a/firmware/common/ui_portapack.c b/firmware/common/ui_portapack.c index 8a44db04..aaa96cb0 100644 --- a/firmware/common/ui_portapack.c +++ b/firmware/common/ui_portapack.c @@ -393,7 +393,7 @@ static ui_point_t portapack_lcd_draw_string(ui_point_t point, const char* s) return point; } -typedef struct draw_list_t { +typedef struct { const ui_bitmap_t* bitmap; const ui_point_t point; } draw_list_t; From d49b5b1f13379318f06df71ee74aaf437f39a2d5 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Fri, 20 Mar 2026 10:46:24 +0200 Subject: [PATCH 081/238] firmware: standardize recursive struct+typedef usage --- firmware/common/i2c_bus.h | 13 +++++-------- firmware/common/max2831.h | 13 ++++++------- firmware/common/max2837.h | 13 ++++++------- firmware/common/max2839.h | 13 ++++++------- firmware/common/max5864.h | 9 +++------ firmware/common/spi_bus.h | 18 +++++++++--------- firmware/common/usb_queue.h | 12 +++++------- firmware/common/usb_type.h | 14 ++++++-------- firmware/common/w25q80bv.h | 9 +++------ 9 files changed, 49 insertions(+), 65 deletions(-) diff --git a/firmware/common/i2c_bus.h b/firmware/common/i2c_bus.h index 1e85e440..7519ba14 100644 --- a/firmware/common/i2c_bus.h +++ b/firmware/common/i2c_bus.h @@ -25,21 +25,18 @@ #include #include -struct i2c_bus_t; // IWYU pragma: keep - fixed in #1704 -typedef struct i2c_bus_t i2c_bus_t; - -struct i2c_bus_t { +typedef struct _i2c_bus_t { void* const obj; - void (*start)(i2c_bus_t* const bus, const void* const config); - void (*stop)(i2c_bus_t* const bus); + void (*start)(struct _i2c_bus_t* const bus, const void* const config); + void (*stop)(struct _i2c_bus_t* const bus); void (*transfer)( - i2c_bus_t* const bus, + struct _i2c_bus_t* const bus, const uint_fast8_t peripheral_address, const uint8_t* const tx, const size_t tx_count, uint8_t* const rx, const size_t rx_count); -}; +} i2c_bus_t; void i2c_bus_start(i2c_bus_t* const bus, const void* const config); void i2c_bus_stop(i2c_bus_t* const bus); diff --git a/firmware/common/max2831.h b/firmware/common/max2831.h index a5b58afc..18154649 100644 --- a/firmware/common/max2831.h +++ b/firmware/common/max2831.h @@ -47,22 +47,21 @@ typedef enum { MAX2831_RX_HPF_600_KHZ = 3, } max2831_rx_hpf_freq_t; -struct max2831_driver_t; // IWYU pragma: keep - fixed in #1704 -typedef struct max2831_driver_t max2831_driver_t; - -struct max2831_driver_t { +typedef struct _max2831_driver_t { spi_bus_t* bus; gpio_t gpio_enable; gpio_t gpio_rxtx; gpio_t gpio_rxhp; gpio_t gpio_ld; - void (*target_init)(max2831_driver_t* const drv); - void (*set_mode)(max2831_driver_t* const drv, const max2831_mode_t new_mode); + void (*target_init)(struct _max2831_driver_t* const drv); + void (*set_mode)( + struct _max2831_driver_t* const drv, + const max2831_mode_t new_mode); max2831_mode_t mode; uint16_t regs[MAX2831_NUM_REGS]; uint16_t regs_dirty; uint32_t desired_lpf_bw; -}; +} max2831_driver_t; /* Initialize chip. */ extern void max2831_setup(max2831_driver_t* const drv); diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index b934b2ed..748bafe0 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -40,20 +40,19 @@ typedef enum { MAX2837_MODE_RX } max2837_mode_t; -struct max2837_driver_t; // IWYU pragma: keep - fixed in #1704 -typedef struct max2837_driver_t max2837_driver_t; - -struct max2837_driver_t { +typedef struct _max2837_driver_t { spi_bus_t* bus; gpio_t gpio_enable; gpio_t gpio_rx_enable; gpio_t gpio_tx_enable; - void (*target_init)(max2837_driver_t* const drv); - void (*set_mode)(max2837_driver_t* const drv, const max2837_mode_t new_mode); + void (*target_init)(struct _max2837_driver_t* const drv); + void (*set_mode)( + struct _max2837_driver_t* const drv, + const max2837_mode_t new_mode); max2837_mode_t mode; uint16_t regs[MAX2837_NUM_REGS]; uint32_t regs_dirty; -}; +} max2837_driver_t; /* Initialize chip. */ extern void max2837_setup(max2837_driver_t* const drv); diff --git a/firmware/common/max2839.h b/firmware/common/max2839.h index 3647d067..b6c21194 100644 --- a/firmware/common/max2839.h +++ b/firmware/common/max2839.h @@ -43,19 +43,18 @@ typedef enum { MAX2839_MODE_CLKOUT, } max2839_mode_t; -struct max2839_driver_t; // IWYU pragma: keep - fixed in #1704 -typedef struct max2839_driver_t max2839_driver_t; - -struct max2839_driver_t { +typedef struct _max2839_driver_t { spi_bus_t* bus; gpio_t gpio_enable; gpio_t gpio_rxtx; - void (*target_init)(max2839_driver_t* const drv); - void (*set_mode)(max2839_driver_t* const drv, const max2839_mode_t new_mode); + void (*target_init)(struct _max2839_driver_t* const drv); + void (*set_mode)( + struct _max2839_driver_t* const drv, + const max2839_mode_t new_mode); max2839_mode_t mode; uint16_t regs[MAX2839_NUM_REGS]; uint32_t regs_dirty; -}; +} max2839_driver_t; /* Initialize chip. */ extern void max2839_setup(max2839_driver_t* const drv); diff --git a/firmware/common/max5864.h b/firmware/common/max5864.h index fbac7af5..56d730cc 100644 --- a/firmware/common/max5864.h +++ b/firmware/common/max5864.h @@ -24,13 +24,10 @@ #include "spi_bus.h" -struct max5864_driver_t; // IWYU pragma: keep - fixed in #1704 -typedef struct max5864_driver_t max5864_driver_t; - -struct max5864_driver_t { +typedef struct _max5864_driver_t { spi_bus_t* const bus; - void (*target_init)(max5864_driver_t* const drv); -}; + void (*target_init)(struct _max5864_driver_t* const drv); +} max5864_driver_t; void max5864_setup(max5864_driver_t* const drv); diff --git a/firmware/common/spi_bus.h b/firmware/common/spi_bus.h index 4e6caee2..07d5787d 100644 --- a/firmware/common/spi_bus.h +++ b/firmware/common/spi_bus.h @@ -29,20 +29,20 @@ typedef struct { const size_t count; } spi_transfer_t; -struct spi_bus_t; // IWYU pragma: keep - fixed in #1704 -typedef struct spi_bus_t spi_bus_t; - -struct spi_bus_t { +typedef struct _spi_bus_t { void* const obj; const void* config; - void (*start)(spi_bus_t* const bus, const void* const config); - void (*stop)(spi_bus_t* const bus); - void (*transfer)(spi_bus_t* const bus, void* const data, const size_t count); + void (*start)(struct _spi_bus_t* const bus, const void* const config); + void (*stop)(struct _spi_bus_t* const bus); + void (*transfer)( + struct _spi_bus_t* const bus, + void* const data, + const size_t count); void (*transfer_gather)( - spi_bus_t* const bus, + struct _spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count); -}; +} spi_bus_t; void spi_bus_start(spi_bus_t* const bus, const void* const config); void spi_bus_stop(spi_bus_t* const bus); diff --git a/firmware/common/usb_queue.h b/firmware/common/usb_queue.h index 33f6def2..b6134946 100644 --- a/firmware/common/usb_queue.h +++ b/firmware/common/usb_queue.h @@ -29,27 +29,25 @@ #include "usb_type.h" -typedef struct _usb_transfer_t usb_transfer_t; -typedef struct _usb_queue_t usb_queue_t; typedef void (*transfer_completion_cb)(void*, unsigned int); // This is an opaque datatype. Thou shall not touch these members. -struct _usb_transfer_t { +typedef struct _usb_transfer_t { struct _usb_transfer_t* next; usb_transfer_descriptor_t td ATTR_ALIGNED(64); unsigned int maximum_length; struct _usb_queue_t* queue; transfer_completion_cb completion_cb; void* user_data; -}; +} usb_transfer_t; // This is an opaque datatype. Thou shall not touch these members. -struct _usb_queue_t { - struct usb_endpoint_t* endpoint; +typedef struct _usb_queue_t { + usb_endpoint_t* endpoint; const unsigned int pool_size; usb_transfer_t* volatile free_transfers; usb_transfer_t* volatile active; -}; +} usb_queue_t; #define USB_DECLARE_QUEUE(endpoint_name) struct _usb_queue_t endpoint_name##_queue; #define USB_DEFINE_QUEUE(endpoint_name, _pool_size) \ diff --git a/firmware/common/usb_type.h b/firmware/common/usb_type.h index 2f68b91f..44810de5 100644 --- a/firmware/common/usb_type.h +++ b/firmware/common/usb_type.h @@ -144,15 +144,13 @@ typedef struct { uint8_t* wcid_extended_properties_descriptor; } usb_device_t; -typedef struct usb_endpoint_t usb_endpoint_t; - -struct usb_endpoint_t { +typedef struct _usb_endpoint_t { usb_setup_t setup; uint8_t buffer[32]; // Buffer for use during IN stage. const uint_fast8_t address; usb_device_t* const device; - usb_endpoint_t* const in; - usb_endpoint_t* const out; - void (*setup_complete)(usb_endpoint_t* const endpoint); - void (*transfer_complete)(usb_endpoint_t* const endpoint); -}; + struct _usb_endpoint_t* const in; + struct _usb_endpoint_t* const out; + void (*setup_complete)(struct _usb_endpoint_t* const endpoint); + void (*transfer_complete)(struct _usb_endpoint_t* const endpoint); +} usb_endpoint_t; diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index 4361f4b7..a43d6445 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -39,18 +39,15 @@ typedef union { uint8_t id_8b[8]; /* 8*8bits 64bits Unique ID */ } w25q80bv_unique_id_t; -struct w25q80bv_driver_t; // IWYU pragma: keep - fixed in #1704 -typedef struct w25q80bv_driver_t w25q80bv_driver_t; - -struct w25q80bv_driver_t { +typedef struct _w25q80bv_driver_t { spi_bus_t* bus; gpio_t gpio_hold; gpio_t gpio_wp; - void (*target_init)(w25q80bv_driver_t* const drv); + void (*target_init)(struct _w25q80bv_driver_t* const drv); size_t page_len; size_t num_pages; size_t num_bytes; -}; +} w25q80bv_driver_t; void w25q80bv_setup(w25q80bv_driver_t* const drv); void w25q80bv_get_full_status(w25q80bv_driver_t* const drv, uint8_t* data); From 8018feb1d03d8cc0d00a1371883520ed392be7db Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Wed, 8 Apr 2026 16:15:21 +0200 Subject: [PATCH 082/238] ci: run includes-check workflow on debian:13 --- .github/workflows/includes-check.yml | 36 ++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/.github/workflows/includes-check.yml b/.github/workflows/includes-check.yml index f3848754..4b3dd400 100644 --- a/.github/workflows/includes-check.yml +++ b/.github/workflows/includes-check.yml @@ -1,9 +1,16 @@ name: Check includes on: [push, pull_request] +defaults: + run: + shell: bash + jobs: includes-check: runs-on: ubuntu-latest + container: + image: "debian:13" + options: --user 0 strategy: matrix: board: ['HACKRF_ONE', 'JAWBREAKER', 'RAD1O', 'PRALINE'] @@ -13,7 +20,23 @@ jobs: fail-fast: false steps: - - uses: actions/checkout@v4 + + - name: Make it work on debian + run: | + apt update + apt install -y git python3 python3-pip python3-venv nodejs + # actions/checkout insists on putting the checkout in the + # working directory rather than ${{ github.workspace }}. + # + # This may just be because the 'runner' user does not exist + # in the docker image at startup. + # + # also see: https://github.com/actions/runner/issues/878 + useradd -ms /bin/bash runner + ln -s /__w /home/runner/work + + - name: Checkout repository + uses: actions/checkout@v6 with: submodules: true @@ -29,11 +52,10 @@ jobs: run: | python3 -m venv environment && source environment/bin/activate python3 -m pip install PyYAML - sudo apt update - sudo apt install iwyu + apt install -y iwyu + iwyu --version - name: Build libopencm3 - shell: bash working-directory: ${{github.workspace}}/firmware/libopencm3/ run: | source ../../environment/bin/activate @@ -43,13 +65,11 @@ jobs: run: cmake -E make_directory ${{github.workspace}}/firmware/build - name: Configure CMake - shell: bash working-directory: ${{github.workspace}}/firmware/build - run: cmake $GITHUB_WORKSPACE/firmware/ -DCMAKE_BUILD_TYPE=Release -DBOARD=${{ matrix.board }} -DCHECK_INCLUDES=1 + run: cmake ${{github.workspace}}/firmware/ -DCMAKE_BUILD_TYPE=Release -DBOARD=${{ matrix.board }} -DCHECK_INCLUDES=1 - name: Build working-directory: ${{github.workspace}}/firmware/build - shell: bash run: | source ../../environment/bin/activate output="$(cmake --build . --config Release 2>&1)" @@ -58,8 +78,10 @@ jobs: if [[ "${line}" == "Warning: include-what-you-use"* ]]; then exit_code=1 dump=1 + echo elif [[ "${line}" == "---" ]]; then dump=0 + echo fi if [[ ${dump} == "1" ]]; then echo "${line}" From c4bc07836471c70611f3e0b317f8d0c093a44aa1 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 9 Apr 2026 19:40:25 +0100 Subject: [PATCH 083/238] CI: switch from actions-setup-cmake to get-cmake. --- .github/workflows/build.yml | 8 ++++---- .github/workflows/includes-check.yml | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index eaa1d982..551a35d4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -60,9 +60,9 @@ jobs: - uses: actions/checkout@v4 - name: Setup cmake - uses: jwlawson/actions-setup-cmake@v2 + uses: lukka/get-cmake@latest with: - cmake-version: ${{ matrix.cmake }} + cmakeVersion: ${{ matrix.cmake }} if: matrix.sys.shell != 'msys2' - name: Install dependencies (macOS) @@ -175,9 +175,9 @@ jobs: submodules: true - name: Setup cmake - uses: jwlawson/actions-setup-cmake@v2 + uses: lukka/get-cmake@latest with: - cmake-version: ${{ matrix.cmake }} + cmakeVersion: ${{ matrix.cmake }} if: matrix.os != 'windows' - name: Install Arm GNU Toolchain diff --git a/.github/workflows/includes-check.yml b/.github/workflows/includes-check.yml index 4b3dd400..dfb631bd 100644 --- a/.github/workflows/includes-check.yml +++ b/.github/workflows/includes-check.yml @@ -24,7 +24,7 @@ jobs: - name: Make it work on debian run: | apt update - apt install -y git python3 python3-pip python3-venv nodejs + apt install -y git python3 python3-pip python3-venv nodejs unzip # actions/checkout insists on putting the checkout in the # working directory rather than ${{ github.workspace }}. # @@ -41,9 +41,9 @@ jobs: submodules: true - name: Setup cmake - uses: jwlawson/actions-setup-cmake@v2 + uses: lukka/get-cmake@latest with: - cmake-version: ${{ matrix.cmake }} + cmakeVersion: ${{ matrix.cmake }} - name: Install Arm GNU Toolchain uses: carlosperate/arm-none-eabi-gcc-action@v1 From 0cf5cc229828c5a24542dfb749e26b86872e3385 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Mon, 2 Mar 2026 19:04:43 -0500 Subject: [PATCH 084/238] Fix RX IF gain configuration --- firmware/common/radio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index d22ba700..86e5e190 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -521,13 +521,13 @@ static bool radio_update_gain(radio_t* const radio, uint64_t* bank) gain = bank[RADIO_GAIN_RX_IF]; if ((gain != RADIO_UNSET) && - (gain != radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF])) { + (gain != radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_IF])) { max283x_set_lna_gain(&max283x, gain); - radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] = gain; + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_IF] = gain; new_gain = true; - } else if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] == RADIO_UNSET) { + } else if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_IF] == RADIO_UNSET) { max283x_set_lna_gain(&max283x, DEFAULT_GAIN_IF); - radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] = DEFAULT_GAIN_IF; + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_IF] = DEFAULT_GAIN_IF; new_gain = true; } From 693b7e79f7e1962fb43b7d5f963108cbd7738b3d Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 9 Apr 2026 21:46:48 +0100 Subject: [PATCH 085/238] CI: conserve macOS runners by not building firmware for every board. --- .github/workflows/build.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 551a35d4..07b419e5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -164,6 +164,15 @@ jobs: exclude: - os: 'windows' cmake: '3.10.0' + # GitHub doesn't give us many macOS runners, so don't build for every board. + # We just need to know that building firmware works on macOS. Use PRALINE + # since that's the most complicated one due to FPGA bitstreams. + - os: 'macos' + board: 'HACKRF_ONE' + - os: 'macos' + board: 'JAWBREAKER' + - os: 'macos' + board: 'RAD1O' # Don't cancel all builds when one fails fail-fast: false From caa47500c5ff76e7794ec63e0a8c2314bb244f2d Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Fri, 3 Apr 2026 06:41:46 -0400 Subject: [PATCH 086/238] Show 0 in MHz column on PortaPack display The PortaPack UI hides leading zeros in the most significant digits. Previously zeros in the 1 MHz column and above were hidden. Now zeros in the 10 MHz column and above are hidden. --- firmware/common/ui_portapack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/ui_portapack.c b/firmware/common/ui_portapack.c index aaa96cb0..0ca2c225 100644 --- a/firmware/common/ui_portapack.c +++ b/firmware/common/ui_portapack.c @@ -525,7 +525,7 @@ static void portapack_ui_set_frequency(uint64_t frequency) char s[10]; for (int i = 0; i < 10; i++) { const char c = '0' + value % 10; - s[i] = ((i >= 6) && (value == 0)) ? ' ' : c; + s[i] = ((i >= 7) && (value == 0)) ? ' ' : c; value /= 10; } From 3f51f407fa17439563d23f63f92e2b21191b0fe7 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Wed, 8 Apr 2026 20:55:20 -0400 Subject: [PATCH 087/238] Move transceiver_mode_t to own header file --- firmware/common/hackrf_ui.c | 1 + firmware/common/hackrf_ui.h | 1 + firmware/common/radio.c | 4 ++- firmware/common/radio.h | 10 +------ firmware/common/transceiver_mode.h | 33 +++++++++++++++++++++++ firmware/common/ui_portapack.c | 1 + firmware/common/ui_rad1o.c | 1 + firmware/hackrf_usb/hackrf_usb.c | 1 + firmware/hackrf_usb/usb_api_sweep.c | 1 + firmware/hackrf_usb/usb_api_transceiver.c | 1 + firmware/hackrf_usb/usb_api_transceiver.h | 2 +- 11 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 firmware/common/transceiver_mode.h diff --git a/firmware/common/hackrf_ui.c b/firmware/common/hackrf_ui.c index dbf1cc24..6e230943 100644 --- a/firmware/common/hackrf_ui.c +++ b/firmware/common/hackrf_ui.c @@ -23,6 +23,7 @@ #include #include "hackrf_ui.h" +#include "transceiver_mode.h" #if defined(PRALINE) || defined(HACKRF_ONE) #include "ui_portapack.h" #endif diff --git a/firmware/common/hackrf_ui.h b/firmware/common/hackrf_ui.h index 7b08a597..1193d1c5 100644 --- a/firmware/common/hackrf_ui.h +++ b/firmware/common/hackrf_ui.h @@ -27,6 +27,7 @@ #include "radio.h" #include "rf_path.h" +#include "transceiver_mode.h" typedef void (*hackrf_ui_init_fn)(void); typedef void (*hackrf_ui_deinit_fn)(void); diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 86e5e190..71818f11 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -19,6 +19,8 @@ * Boston, MA 02110-1301, USA. */ +#include "radio.h" + #include #include @@ -28,8 +30,8 @@ #include "hackrf_ui.h" #include "max283x.h" #include "platform_detect.h" -#include "radio.h" #include "rf_path.h" +#include "transceiver_mode.h" #include "tuning.h" #if defined(PRALINE) #include "fpga.h" diff --git a/firmware/common/radio.h b/firmware/common/radio.h index 0c171d47..e75d2d90 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -27,6 +27,7 @@ #include #include "fixed_point.h" +#include "transceiver_mode.h" typedef enum { RADIO_OK = 1, @@ -60,15 +61,6 @@ typedef enum { CLOCK_SOURCE_PORTAPACK = 2, } clock_source_t; -typedef enum { - TRANSCEIVER_MODE_OFF = 0, - TRANSCEIVER_MODE_RX = 1, - TRANSCEIVER_MODE_TX = 2, - TRANSCEIVER_MODE_SS = 3, - TRANSCEIVER_MODE_CPLD_UPDATE = 4, - TRANSCEIVER_MODE_RX_SWEEP = 5, -} transceiver_mode_t; - /** * Configurable registers stored as uint64_t. Any register may be set to * RADIO_UNSET. When not RADIO_UNSET, some registers are read as a specific type diff --git a/firmware/common/transceiver_mode.h b/firmware/common/transceiver_mode.h new file mode 100644 index 00000000..dccb71b2 --- /dev/null +++ b/firmware/common/transceiver_mode.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012-2026 Great Scott Gadgets + * Copyright 2012 Jared Boone + * Copyright 2013 Benjamin Vernoux + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +typedef enum { + TRANSCEIVER_MODE_OFF = 0, + TRANSCEIVER_MODE_RX = 1, + TRANSCEIVER_MODE_TX = 2, + TRANSCEIVER_MODE_SS = 3, + TRANSCEIVER_MODE_CPLD_UPDATE = 4, + TRANSCEIVER_MODE_RX_SWEEP = 5, +} transceiver_mode_t; diff --git a/firmware/common/ui_portapack.c b/firmware/common/ui_portapack.c index 0ca2c225..4e862ca4 100644 --- a/firmware/common/ui_portapack.c +++ b/firmware/common/ui_portapack.c @@ -29,6 +29,7 @@ #include "portapack.h" #include "radio.h" #include "rf_path.h" +#include "transceiver_mode.h" /* Pixel data within a font or bitmap byte is "reversed": LSB is left-most pixel. */ diff --git a/firmware/common/ui_rad1o.c b/firmware/common/ui_rad1o.c index 977c5205..ce894cdf 100644 --- a/firmware/common/ui_rad1o.c +++ b/firmware/common/ui_rad1o.c @@ -29,6 +29,7 @@ #include "hackrf_core.h" #include "radio.h" #include "rf_path.h" +#include "transceiver_mode.h" #include "rad1o/display.h" #include "rad1o/draw.h" diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 3126ac0c..ee8f897d 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index 2ad3203d..d558a2de 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index ab3d6af4..80750aa4 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_transceiver.h b/firmware/hackrf_usb/usb_api_transceiver.h index 02385acf..df981c1e 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.h +++ b/firmware/hackrf_usb/usb_api_transceiver.h @@ -25,7 +25,7 @@ #include -#include +#include #include #include From 3e256d14154914a6fb376523c609dcf680f9b255 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 9 Apr 2026 00:19:24 -0400 Subject: [PATCH 088/238] Write RADIO_OPMODE when switching operating mode --- firmware/common/radio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 71818f11..7b01805e 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -705,6 +705,7 @@ void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode) } } + radio->config[RADIO_BANK_ACTIVE][RADIO_OPMODE] = mode; mark_dirty(radio, RADIO_OPMODE); nvic_enable_irq(NVIC_USB0_IRQ); radio_update(radio); From 0205dd441d70e677459d0e67f4ce96e1dd69818f Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Wed, 8 Apr 2026 21:11:35 -0400 Subject: [PATCH 089/238] Update UI opportunistically in sweep mode --- firmware/common/radio.c | 20 +++++++++++------ firmware/common/rf_path.c | 10 +++++++-- firmware/common/rf_path.h | 6 +++++- firmware/common/tuning.c | 31 ++++++++++++++++----------- firmware/common/tuning.h | 9 +++++--- firmware/hackrf_usb/usb_api_sweep.c | 33 +++++++++++++++++++++++++++++ 6 files changed, 84 insertions(+), 25 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 7b01805e..39fc5f0a 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -270,6 +270,11 @@ static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) bool set_lo = (requested_lo != RADIO_UNSET); bool set_img_reject = (requested_img_reject != RADIO_UNSET); + uint64_t opmode = bank[RADIO_OPMODE]; + if (opmode == RADIO_UNSET) { + opmode = radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]; + } + if (set_if && set_lo && set_img_reject) { bool new_if = (requested_if != @@ -284,7 +289,8 @@ static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) set_freq_explicit( requested_if / FP_ONE_HZ, requested_lo / FP_ONE_HZ, - requested_img_reject); + requested_img_reject, + opmode); radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF] = requested_if; radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_LO] = @@ -323,10 +329,6 @@ static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) if (applied_afe_rate == RADIO_UNSET) { return false; } - uint64_t opmode = bank[RADIO_OPMODE]; - if (opmode == RADIO_UNSET) { - opmode = radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]; - } const tune_config_t* tune_config = select_tune_config(opmode); const tune_config_t* applied_tune_config = select_tune_config(radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]); @@ -349,12 +351,16 @@ static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) fp_40_24_t offset = applied_afe_rate / 4; bool new_offset = (applied_offset != offset); if (new_rotation || new_offset || new_config || new_rf) { - tuning_set_frequency(tune_config, requested_rf_hz, offset / FP_ONE_HZ); + tuning_set_frequency( + tune_config, + requested_rf_hz, + offset / FP_ONE_HZ, + opmode); applied_offset = offset; } #else if (new_rf) { - set_freq(requested_rf_hz); + set_freq(requested_rf_hz, opmode); } #endif radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF] = requested_rf; diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 30c8c718..cf77f70c 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -34,6 +34,7 @@ #include "mixer.h" #include "platform_detect.h" #include "sgpio.h" +#include "transceiver_mode.h" #if defined(HACKRF_ONE) || defined(RAD1O) || defined(PRALINE) #include "platform_scu.h" #endif @@ -537,7 +538,10 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d hackrf_ui()->set_direction(direction); } -void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter) +void rf_path_set_filter( + rf_path_t* const rf_path, + const rf_path_filter_t filter, + const transceiver_mode_t opmode) { switch (filter) { default: @@ -560,7 +564,9 @@ void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter) switchctrl_set(rf_path, rf_path->switchctrl); - hackrf_ui()->set_filter(filter); + if (opmode != TRANSCEIVER_MODE_RX_SWEEP) { + hackrf_ui()->set_filter(filter); + } } void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable) diff --git a/firmware/common/rf_path.h b/firmware/common/rf_path.h index 1ac0e243..d9f45a30 100644 --- a/firmware/common/rf_path.h +++ b/firmware/common/rf_path.h @@ -25,6 +25,7 @@ #include +#include "transceiver_mode.h" #if defined(HACKRF_ONE) || defined(RAD1O) || defined(PRALINE) #include "gpio.h" #endif @@ -91,7 +92,10 @@ void rf_path_init(rf_path_t* const rf_path); void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t direction); -void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter); +void rf_path_set_filter( + rf_path_t* const rf_path, + const rf_path_filter_t filter, + const transceiver_mode_t opmode); void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable); void rf_path_set_antenna(rf_path_t* const rf_path, const uint_fast8_t enable); diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 47724e36..b2d49ec4 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -28,6 +28,7 @@ #include "max283x.h" #include "mixer.h" #include "sgpio.h" +#include "transceiver_mode.h" #if defined(PRALINE) || defined(HACKRF_ONE) #include "operacake.h" #endif @@ -79,7 +80,7 @@ static uint32_t max2837_freq_nominal_hz = 2560000000; * hz between 0 to 999999 Hz (not checked) * return false on error or true if success. */ -bool set_freq(const uint64_t freq) +bool set_freq(const uint64_t freq, const transceiver_mode_t opmode) { bool success; uint64_t mixer_freq_hz; @@ -92,7 +93,7 @@ bool set_freq(const uint64_t freq) max283x_mode_t prior_max283x_mode = max283x_mode(&max283x); max283x_set_mode(&max283x, MAX283x_MODE_STANDBY); if (freq_mhz < MAX_LP_FREQ_MHZ) { - rf_path_set_filter(&rf_path, RF_PATH_FILTER_LOW_PASS); + rf_path_set_filter(&rf_path, RF_PATH_FILTER_LOW_PASS, opmode); #ifdef RAD1O max2837_freq_nominal_hz = 2300 * FREQ_ONE_MHZ; #else @@ -105,7 +106,7 @@ bool set_freq(const uint64_t freq) max283x_set_frequency(&max283x, real_mixer_freq_hz - freq); 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); + rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS, opmode); /* mixer_freq_mhz <= not used in Bypass mode */ max283x_set_frequency(&max283x, freq); sgpio_cpld_set_mixer_invert(&sgpio_config, 0); @@ -124,7 +125,7 @@ bool set_freq(const uint64_t freq) max2837_freq_nominal_hz = (2500 * FREQ_ONE_MHZ) + ((freq - (MID2_HP_FREQ_MHZ * FREQ_ONE_MHZ)) / 9); } - rf_path_set_filter(&rf_path, RF_PATH_FILTER_HIGH_PASS); + rf_path_set_filter(&rf_path, RF_PATH_FILTER_HIGH_PASS, opmode); mixer_freq_hz = freq - max2837_freq_nominal_hz; /* Set Freq and read real freq */ real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_hz); @@ -136,7 +137,9 @@ bool set_freq(const uint64_t freq) } max283x_set_mode(&max283x, prior_max283x_mode); if (success) { - hackrf_ui()->set_frequency(freq); + if (opmode != TRANSCEIVER_MODE_RX_SWEEP) { + hackrf_ui()->set_frequency(freq); + } #ifdef HACKRF_ONE operacake_set_range(freq_mhz); #endif @@ -149,7 +152,8 @@ bool set_freq(const uint64_t freq) bool tuning_set_frequency( const tune_config_t* cfg, const uint64_t freq, - const uint32_t offset) + const uint32_t offset, + const transceiver_mode_t opmode) { uint64_t mixer_freq_hz; uint64_t real_mixer_freq_hz; @@ -175,11 +179,11 @@ bool tuning_set_frequency( max283x_set_mode(&max283x, MAX283x_MODE_STANDBY); if (cfg->if_mhz == 0) { - rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS); + rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS, opmode); max283x_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); + rf_path_set_filter(&rf_path, RF_PATH_FILTER_LOW_PASS, opmode); if (cfg->high_lo) { mixer_freq_hz = FREQ_ONE_MHZ * cfg->if_mhz + rf; real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_hz); @@ -192,7 +196,7 @@ bool tuning_set_frequency( sgpio_cpld_set_mixer_invert(&sgpio_config, 0); } } else { - rf_path_set_filter(&rf_path, RF_PATH_FILTER_HIGH_PASS); + rf_path_set_filter(&rf_path, RF_PATH_FILTER_HIGH_PASS, opmode); mixer_freq_hz = rf - FREQ_ONE_MHZ * cfg->if_mhz; real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_hz); max283x_set_frequency(&max283x, rf - real_mixer_freq_hz); @@ -200,7 +204,9 @@ bool tuning_set_frequency( } max283x_set_mode(&max283x, prior_max283x_mode); - hackrf_ui()->set_frequency(freq); + if (opmode != TRANSCEIVER_MODE_RX_SWEEP) { + hackrf_ui()->set_frequency(freq); + } operacake_set_range(freq_mhz); return true; } @@ -209,7 +215,8 @@ bool tuning_set_frequency( bool set_freq_explicit( const uint64_t if_freq_hz, const uint64_t lo_freq_hz, - const rf_path_filter_t path) + const rf_path_filter_t path, + const transceiver_mode_t opmode) { if ((if_freq_hz < ((uint64_t) ABS_MIN_BYPASS_FREQ_MHZ * FREQ_ONE_MHZ)) || (if_freq_hz > ((uint64_t) ABS_MAX_BYPASS_FREQ_MHZ * FREQ_ONE_MHZ))) { @@ -225,7 +232,7 @@ bool set_freq_explicit( return false; } - rf_path_set_filter(&rf_path, path); + rf_path_set_filter(&rf_path, path, opmode); max283x_set_frequency(&max283x, if_freq_hz); if (lo_freq_hz > if_freq_hz) { diff --git a/firmware/common/tuning.h b/firmware/common/tuning.h index 559638ac..1c4681db 100644 --- a/firmware/common/tuning.h +++ b/firmware/common/tuning.h @@ -27,21 +27,24 @@ #include #include "rf_path.h" +#include "transceiver_mode.h" #if defined(PRALINE) #include "tune_config.h" #endif #define FREQ_ONE_MHZ (1000ULL * 1000) -bool set_freq(const uint64_t freq); +bool set_freq(const uint64_t freq, const transceiver_mode_t opmode); bool set_freq_explicit( const uint64_t if_freq_hz, const uint64_t lo_freq_hz, - const rf_path_filter_t path); + const rf_path_filter_t path, + const transceiver_mode_t opmode); #ifdef PRALINE bool tuning_set_frequency( const tune_config_t* cfg, const uint64_t freq, - const uint32_t offset); + const uint32_t offset, + const transceiver_mode_t opmode); #endif diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index d558a2de..a9bfc695 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -27,8 +27,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -58,6 +60,31 @@ static uint32_t dwell_blocks = 0; static uint32_t step_width = 0; static uint32_t offset = 0; static enum sweep_style style = LINEAR; +static bool freq_ui_dirty = false; +static bool img_reject_ui_dirty = false; +static rf_path_filter_t img_reject; + +/* + * Opportunistic UI updates are made when time is available. Updates are + * prioritized to prevent a single update from taking too long. Lower priority + * changes to the image reject filter path display are done only if there is + * time remaining after the higher priority update to the frequency display. + */ +void update_ui(void) +{ + if (freq_ui_dirty) { + hackrf_ui()->set_frequency(sweep_freq + offset); + freq_ui_dirty = false; + } else if (img_reject_ui_dirty) { + const uint64_t new_img_reject = + radio_reg_read(&radio, RADIO_BANK_APPLIED, RADIO_IMAGE_REJECT); + if (new_img_reject != img_reject) { + img_reject = new_img_reject; + hackrf_ui()->set_filter(img_reject); + } + img_reject_ui_dirty = false; + } +} /* Do this before starting sweep mode with request_transceiver_mode(). */ usb_request_status_t usb_vendor_request_init_sweep( @@ -153,6 +180,9 @@ void sweep_mode(uint32_t seq) uint8_t* buffer; transceiver_startup(TRANSCEIVER_MODE_RX_SWEEP); + hackrf_ui()->set_frequency(sweep_freq + offset); + img_reject = radio_reg_read(&radio, RADIO_BANK_APPLIED, RADIO_IMAGE_REJECT); + hackrf_ui()->set_filter(img_reject); // Set M0 to RX first buffer, then wait. m0_state.threshold = 0x4000; @@ -235,6 +265,8 @@ void sweep_mode(uint32_t seq) (sweep_freq + offset) * FP_ONE_HZ); nvic_enable_irq(NVIC_USB0_IRQ); radio_update(&radio); + freq_ui_dirty = true; + img_reject_ui_dirty = true; blocks_queued = 0; } @@ -243,6 +275,7 @@ void sweep_mode(uint32_t seq) if (transceiver_request.seq != seq) { goto end; } + update_ui(); } // Set M0 to switch back to WAIT after filling next buffer. From 59c61c9aced28d01ecada28e9311264cfa59e854 Mon Sep 17 00:00:00 2001 From: mndza Date: Wed, 11 Mar 2026 14:07:34 +0100 Subject: [PATCH 090/238] Set optimal fractional divider values (P2, P3) when setting sample rate --- firmware/common/hackrf_core.c | 73 +++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 16 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 241c2e3d..012fb948 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -171,6 +171,60 @@ jtag_t jtag_cpld = { .gpio = &jtag_gpio_cpld, }; +/* + * Closest fraction to m/d with denominator <= max_den. + * Returns result in *r / *s with gcd(*r, *s) == 1 and 0 < *s <= max_den. + * Straight port from CPython's fractions, and better documented there. + */ +void limit_denominator( + uint64_t m, + uint64_t d, + const uint64_t max_den, + uint64_t* r, + uint64_t* s) +{ + if (d <= max_den) { + *r = m; + *s = d; + return; + } + + uint64_t p0 = 0, q0 = 1, p1 = 1, q1 = 0; + uint64_t n = m, orig_d = d; + uint64_t tmp; + + while (1) { + uint64_t a = n / d; + uint64_t q2 = q0 + a * q1; + + if (q2 > max_den) + break; + + tmp = p0 + a * p1; + p0 = p1; + q0 = q1; + p1 = tmp; + q1 = q2; + + tmp = n - a * d; + n = d; + d = tmp; + if (d == 0) + break; + } + + uint64_t k = (max_den - q0) / q1; + + /* Return closer candidate. */ + if (2 * d * (q0 + k * q1) <= orig_d) { + *r = p1; + *s = q1; + } else { + *r = p0 + k * p1; + *s = q0 + k * q1; + } +} + /* * Configure clock generator to produce sample clock in units of 1/(2**24) Hz. * Can be called with program=false for a dry run that returns the resultant @@ -207,24 +261,11 @@ fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program) * fixed-point type. */ n = (128 * vco) - (rate * (p1 + 512)); - d = rate / FP_ONE_HZ; - n += (d / 2); - p2 = n / d; - p3 = 1 << 24; + d = rate; - /* Reduce fraction. p3 is 1<<24, so gcd(p2, p3) is a power of 2 */ - unsigned int shift = p2 ? __builtin_ctz(p2) : 24; - p2 >>= shift; - p3 >>= shift; - - /* Convert fraction to valid denominator. */ + /* Reduce fraction. */ const uint64_t p3_max = 0xfffff; - if (p3 > p3_max) { - p2 *= p3_max; - p2 += (p3 / 2); - p2 /= p3; - p3 = p3_max; - } + limit_denominator(n, d, p3_max, &p2, &p3); /* Roll over to next p1 to enable integer mode. */ if (p2 >= p3) { From 5af101e45c8063faec3c36dd9958a3ae77262c93 Mon Sep 17 00:00:00 2001 From: mndza Date: Fri, 10 Apr 2026 17:42:44 +0200 Subject: [PATCH 091/238] Fixed-point format for sample rate with 36 fractional bits Fix overflowing division in sample_rate_set Avoid overflows in round_sample_rate --- firmware/common/fixed_point.h | 9 +++ firmware/common/fpga_selftest.c | 6 +- firmware/common/hackrf_core.c | 69 +++++++++++++++-------- firmware/common/hackrf_core.h | 2 +- firmware/common/radio.c | 31 +++++----- firmware/common/radio.h | 4 +- firmware/hackrf_usb/usb_api_transceiver.c | 18 ++++-- 7 files changed, 91 insertions(+), 48 deletions(-) diff --git a/firmware/common/fixed_point.h b/firmware/common/fixed_point.h index 65656e19..66cabe09 100644 --- a/firmware/common/fixed_point.h +++ b/firmware/common/fixed_point.h @@ -31,3 +31,12 @@ typedef uint64_t fp_40_24_t; /* one in 40.24 fixed-point */ #define FP_ONE_HZ (1 << 24) + +/* 28.36 fixed-point */ +typedef uint64_t fp_28_36_t; + +/* one million in 28.36 fixed-point */ +#define SR_FP_ONE_MHZ ((1000ULL * 1000ULL) << 36) + +/* one in 28.36 fixed-point */ +#define SR_FP_ONE_HZ (1ULL << 36) diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index cc1d8d9c..1e3a9936 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -199,7 +199,7 @@ bool fpga_if_xcvr_selftest(void) max283x_set_frequency(&max283x, 2500000000); // Capture 1: 4 Msps, tone at 0.5 MHz, narrowband filter OFF - sample_rate_set(4ULL * FP_ONE_MHZ, true); + sample_rate_set(4ULL * SR_FP_ONE_MHZ, true); delay_us_at_mhz(1000, 204); if (rx_samples(num_samples, 2000000) == -1) { timeout = true; @@ -222,7 +222,7 @@ bool fpga_if_xcvr_selftest(void) // Capture 3: 20 Msps, tone at 5 MHz, narrowband filter OFF fpga_set_tx_nco_pstep(&fpga, 255); - sample_rate_set(20ULL * FP_ONE_MHZ, true); + sample_rate_set(20ULL * SR_FP_ONE_MHZ, true); narrowband_filter_set(0); delay_us_at_mhz(1000, 204); if (rx_samples(num_samples, 2000000) == -1) { @@ -245,7 +245,7 @@ bool fpga_if_xcvr_selftest(void) &selftest.xcvr_measurements[3]); // Restore default settings. - sample_rate_set(10ULL * FP_ONE_MHZ, true); + sample_rate_set(10ULL * SR_FP_ONE_MHZ, true); rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_OFF); narrowband_filter_set(0); fpga_init(&fpga); diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 012fb948..80c73ccc 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -48,6 +48,8 @@ #include "ice40_spi.h" #endif +#include + i2c_bus_t i2c0 = { .obj = (void*) I2C0_BASE, .start = i2c_lpc_start, @@ -226,7 +228,7 @@ void limit_denominator( } /* - * Configure clock generator to produce sample clock in units of 1/(2**24) Hz. + * Configure clock generator to produce sample clock in units of 1/(2**36) Hz. * Can be called with program=false for a dry run that returns the resultant * frequency without actually configuring the clock generator. * @@ -239,12 +241,12 @@ void limit_denominator( * For more information see: * https://www.pa3fwm.nl/technotes/tn42a-si5351-programming.html */ -fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program) +fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) { - const fp_40_24_t vco = 800 * FP_ONE_MHZ; + const uint64_t vco_hz = 800 * 1000ULL * 1000ULL; uint64_t p1, p2, p3; - uint64_t n, d, q; - fp_40_24_t remainder, resultant_rate; + uint64_t n, d, q1, q2, q3, r1, r2; + fp_28_36_t resultant_rate; /* * First double the sample rate so that we can produce a clock at twice @@ -252,15 +254,34 @@ fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program) * and it is divided by two in an output divider to produce the actual * AFE clock. */ - fp_40_24_t rate = sample_rate * 2; + fp_28_36_t rate = sample_rate * 2; - p1 = ((128 * vco) / rate) - 512; - if (vco % rate) { - /* - * Compute numerator (p2) for denominator (p3) matching - * fixed-point type. - */ - n = (128 * vco) - (rate * (p1 + 512)); + /* + * As the numerator exceeds 64 bits, let's compute this as: + * N<<36 / r = ((N<<12) / r) << 24 + ((N<<12) % r) << 24) / r + * The numerator for the second addend may not fit in 64 bits, and + * that's where we take advantage of long division. + */ + const uint64_t A = (128 * vco_hz) << 12; + q1 = A / rate; + r1 = A % rate; + // Remaining bits with long division. + q2 = 0; + r2 = r1; + for (int j = 0; j < 24; j++) { + uint64_t msb = r2 >> 63; + r2 <<= 1; + q2 <<= 1; + if (msb || r2 >= rate) { + r2 -= rate; + q2 |= 1; + } + } + p1 = (q1 << 24) + q2 - 512; + + if (r2) { + /* Use the remainder for the fractional part. */ + n = r2; d = rate; /* Reduce fraction. */ @@ -285,19 +306,21 @@ fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program) if (p2 == 0) { /* Use unity denominator for integer mode. */ p3 = 1; - n = (vco * 128); + n = (128 * vco_hz) << 18; d = (p1 + 512); - n += (d / 2); - resultant_rate = n / d; + q1 = n / d; + r1 = n % d; + q2 = ((r1 << 18) + (d / 2)) / d; + resultant_rate = (q1 << 18) + q2; } else { - const uint64_t vco_hz = vco / FP_ONE_HZ; n = p3 * vco_hz * 128; d = p3 * (p1 + 512) + p2; - const uint64_t rate_hz = n / d; - remainder = (n - (d * rate_hz)) * FP_ONE_HZ; - remainder += (d / 2); - q = remainder / d; - resultant_rate = (rate_hz * FP_ONE_HZ) + q; + q1 = n / d; + r1 = n % d; + q2 = (r1 << 18) / d; + r2 = (r1 << 18) % d; + q3 = ((r2 << 18) + (d / 2)) / d; + resultant_rate = (q1 << 36) + (q2 << 18) + q3; } /* Return MCU sample rate, not AFE clock rate. */ @@ -658,7 +681,7 @@ void clock_gen_init(void) /* MS7/CLK7 is unused. */ /* Set to 10 MHz, the common rate between Jawbreaker and HackRF One. */ - sample_rate_set(10ULL * FP_ONE_MHZ, true); + sample_rate_set(10ULL * SR_FP_ONE_MHZ, true); si5351c_configure_clock_control(&clock_gen); si5351c_set_clock_source(&clock_gen, PLL_SOURCE_XTAL); diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index e3396ae2..539ce770 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -87,7 +87,7 @@ void enable_1v8_power(void); void disable_1v8_power(void); #endif -fp_40_24_t sample_rate_set(const fp_40_24_t sample_rate, const bool program); +fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program); clock_source_t activate_best_clock_source(void); diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 39fc5f0a..6dc609d9 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -151,15 +151,15 @@ static inline uint8_t compute_resample_log( return n; } -#define MIN_MCU_RATE (200000ULL * FP_ONE_HZ) -#define MAX_MCU_RATE (21800000ULL * FP_ONE_HZ) -#define DEFAULT_MCU_RATE (10000000ULL * FP_ONE_HZ) +#define MIN_MCU_RATE (200000ULL * SR_FP_ONE_HZ) +#define MAX_MCU_RATE (21800000ULL * SR_FP_ONE_HZ) +#define DEFAULT_MCU_RATE (10000000ULL * SR_FP_ONE_HZ) -static fp_40_24_t applied_afe_rate = RADIO_UNSET; +static fp_28_36_t applied_afe_rate = RADIO_UNSET; static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) { - fp_40_24_t rate, afe_rate; + fp_28_36_t rate, afe_rate; uint64_t previous_n; uint8_t n = 0; bool new_afe_rate = false; @@ -195,7 +195,7 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) switch (opmode) { case TRANSCEIVER_MODE_TX: case TRANSCEIVER_MODE_SS: - n = compute_resample_log(rate / FP_ONE_HZ, requested_n); + n = compute_resample_log(rate / SR_FP_ONE_HZ, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX]) { #ifdef PRALINE fpga_set_tx_interpolation_ratio(&fpga, n); @@ -204,7 +204,7 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) } break; default: - n = compute_resample_log(rate / FP_ONE_HZ, requested_n); + n = compute_resample_log(rate / SR_FP_ONE_HZ, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX]) { #ifdef PRALINE fpga_set_rx_decimation_ratio(&fpga, n); @@ -231,7 +231,8 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] = rate; if (rate != RADIO_UNSET) { /* Round to the nearest Hz for display. */ - const uint32_t rate_hz = (rate + (FP_ONE_HZ >> 1)) / FP_ONE_HZ; + const uint32_t rate_hz = + (rate + (SR_FP_ONE_HZ >> 1)) / SR_FP_ONE_HZ; hackrf_ui()->set_sample_rate(rate_hz); } } @@ -241,7 +242,7 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) #define DEFAULT_RF (2450ULL * FP_ONE_MHZ) -static fp_40_24_t applied_offset = RADIO_UNSET; +static fp_28_36_t applied_offset = RADIO_UNSET; #ifdef PRALINE static const tune_config_t* select_tune_config(uint64_t opmode) @@ -348,13 +349,13 @@ static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION] = tune_config->shift << 6; } - fp_40_24_t offset = applied_afe_rate / 4; + fp_28_36_t offset = applied_afe_rate / 4; bool new_offset = (applied_offset != offset); if (new_rotation || new_offset || new_config || new_rf) { tuning_set_frequency( tune_config, requested_rf_hz, - offset / FP_ONE_HZ, + offset / SR_FP_ONE_HZ, opmode); applied_offset = offset; } @@ -374,16 +375,16 @@ static uint32_t auto_bandwidth(radio_t* const radio) { uint64_t rotation = radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION]; - uint32_t sample_rate_hz = DEFAULT_MCU_RATE / FP_ONE_HZ; + uint32_t sample_rate_hz = DEFAULT_MCU_RATE / SR_FP_ONE_HZ; if (radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] != RADIO_UNSET) { - sample_rate_hz = - radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] / FP_ONE_HZ; + sample_rate_hz = radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] / + SR_FP_ONE_HZ; } uint32_t offset_hz = 0; if ((rotation != 0) && (rotation != RADIO_UNSET) && (applied_offset != RADIO_UNSET)) { - offset_hz = applied_offset / FP_ONE_HZ; + offset_hz = applied_offset / SR_FP_ONE_HZ; } const uint32_t bb_bandwidth = (sample_rate_hz * 3) / 4; diff --git a/firmware/common/radio.h b/firmware/common/radio.h index e75d2d90..2744dd4b 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -96,7 +96,7 @@ typedef enum { */ RADIO_ROTATION = 5, /** - * Sample rate (as seen by MCU/host) in 1/(2**24) Hz. + * Sample rate (as seen by MCU/host) in 1/(2**36) Hz. */ RADIO_SAMPLE_RATE = 6, /** @@ -205,7 +205,7 @@ typedef enum { * execute a dry run, returning the sample rate without configuring clock * generation. */ -typedef fp_40_24_t (*sample_rate_fn)(const fp_40_24_t sample_rate, const bool program); +typedef fp_28_36_t (*sample_rate_fn)(const fp_28_36_t sample_rate, const bool program); typedef struct { radio_config_mode_t config_mode; diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 80750aa4..d4b47f9f 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -161,15 +161,25 @@ usb_request_status_t usb_vendor_request_set_freq_explicit( } /* - * Convert fractional sample rate to units of 1/(2**24) Hz. + * Convert fractional sample rate to units of 1/(2**36) Hz. */ -static inline fp_40_24_t round_sample_rate(uint64_t num, uint32_t denom) +static inline fp_28_36_t round_sample_rate(uint64_t num, uint32_t denom) { - num *= FP_ONE_HZ; + uint64_t q1, r1, q2, r2, q3; + if (denom == 0) { denom = 1; } - return (num + (denom >> 1)) / denom; + + q1 = num / denom; + r1 = num % denom; + + q2 = (r1 << 32) / denom; + r2 = (r1 << 32) % denom; + + q3 = ((r2 << 4) + (denom >> 1)) / denom; + + return (q1 << 36) + (q2 << 4) + q3; } usb_request_status_t usb_vendor_request_set_sample_rate_frac( From b76c8759bddc48c23281ae838491ba8c8a965011 Mon Sep 17 00:00:00 2001 From: mndza Date: Fri, 10 Apr 2026 17:10:12 +0200 Subject: [PATCH 092/238] Decrease long division cycles in sample_rate_set --- firmware/common/hackrf_core.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 80c73ccc..cca0b541 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -256,19 +256,25 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) */ fp_28_36_t rate = sample_rate * 2; - /* - * As the numerator exceeds 64 bits, let's compute this as: - * N<<36 / r = ((N<<12) / r) << 24 + ((N<<12) % r) << 24) / r - * The numerator for the second addend may not fit in 64 bits, and - * that's where we take advantage of long division. + /* + * Computes p1 = (N << 36) / rate - 512, where N = 128 * vco_hz. + * + * Full numerator (N << 36) is 73 bits, so we split the division: + * + * (N << 36) / rate = ((N << 27) / rate) << 9 + * + (((N << 27) % rate) << 9) / rate + * + * IMPORTANT: Assumes sample rate is in [200e3 << 36, 43.6e6 << 36]. */ - const uint64_t A = (128 * vco_hz) << 12; + const uint64_t A = (128 * vco_hz) << 27; + q1 = A / rate; r1 = A % rate; - // Remaining bits with long division. + + // Remaining 9 bits with long division. q2 = 0; r2 = r1; - for (int j = 0; j < 24; j++) { + for (int j = 0; j < 9; j++) { uint64_t msb = r2 >> 63; r2 <<= 1; q2 <<= 1; @@ -277,7 +283,8 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) q2 |= 1; } } - p1 = (q1 << 24) + q2 - 512; + + p1 = (q1 << 9) + q2 - 512; if (r2) { /* Use the remainder for the fractional part. */ From 1b06ccf0f7b9ecd8b0715e6550d3d9d3a4122cee Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sat, 11 Apr 2026 23:46:55 +0100 Subject: [PATCH 093/238] Add macros to clarify fixed-point constants. --- firmware/common/fixed_point.h | 14 ++++++++++++++ firmware/common/fpga_selftest.c | 6 +++--- firmware/common/hackrf_core.c | 2 +- firmware/common/radio.c | 8 ++++---- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/firmware/common/fixed_point.h b/firmware/common/fixed_point.h index 66cabe09..b6908797 100644 --- a/firmware/common/fixed_point.h +++ b/firmware/common/fixed_point.h @@ -29,14 +29,28 @@ typedef uint64_t fp_40_24_t; /* one million in 40.24 fixed-point */ #define FP_ONE_MHZ ((1000ULL * 1000ULL) << 24) +/* one thousand in 40.24 fixed-point */ +#define FP_ONE_KHZ ((1000ULL) << 24) + /* one in 40.24 fixed-point */ #define FP_ONE_HZ (1 << 24) +#define FP_MHZ(mhz) (mhz##ULL * FP_ONE_MHZ) +#define FP_KHZ(khz) (khz##ULL * FP_ONE_KHZ) +#define FP_HZ(hz) (hz##ULL * FP_ONE_HZ) + /* 28.36 fixed-point */ typedef uint64_t fp_28_36_t; /* one million in 28.36 fixed-point */ #define SR_FP_ONE_MHZ ((1000ULL * 1000ULL) << 36) +/* one thousand in 28.36 fixed-point */ +#define SR_FP_ONE_KHZ (1000ULL << 36) + /* one in 28.36 fixed-point */ #define SR_FP_ONE_HZ (1ULL << 36) + +#define SR_FP_MHZ(mhz) (mhz##ULL * SR_FP_ONE_MHZ) +#define SR_FP_KHZ(khz) (khz##ULL * SR_FP_ONE_KHZ) +#define SR_FP_HZ(hz) (hz##ULL * SR_FP_ONE_HZ) diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index 1e3a9936..e2b773e4 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -199,7 +199,7 @@ bool fpga_if_xcvr_selftest(void) max283x_set_frequency(&max283x, 2500000000); // Capture 1: 4 Msps, tone at 0.5 MHz, narrowband filter OFF - sample_rate_set(4ULL * SR_FP_ONE_MHZ, true); + sample_rate_set(SR_FP_MHZ(4), true); delay_us_at_mhz(1000, 204); if (rx_samples(num_samples, 2000000) == -1) { timeout = true; @@ -222,7 +222,7 @@ bool fpga_if_xcvr_selftest(void) // Capture 3: 20 Msps, tone at 5 MHz, narrowband filter OFF fpga_set_tx_nco_pstep(&fpga, 255); - sample_rate_set(20ULL * SR_FP_ONE_MHZ, true); + sample_rate_set(SR_FP_MHZ(20), true); narrowband_filter_set(0); delay_us_at_mhz(1000, 204); if (rx_samples(num_samples, 2000000) == -1) { @@ -245,7 +245,7 @@ bool fpga_if_xcvr_selftest(void) &selftest.xcvr_measurements[3]); // Restore default settings. - sample_rate_set(10ULL * SR_FP_ONE_MHZ, true); + sample_rate_set(SR_FP_MHZ(10), true); rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_OFF); narrowband_filter_set(0); fpga_init(&fpga); diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index cca0b541..0534d480 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -688,7 +688,7 @@ void clock_gen_init(void) /* MS7/CLK7 is unused. */ /* Set to 10 MHz, the common rate between Jawbreaker and HackRF One. */ - sample_rate_set(10ULL * SR_FP_ONE_MHZ, true); + sample_rate_set(SR_FP_MHZ(10), true); si5351c_configure_clock_control(&clock_gen); si5351c_set_clock_source(&clock_gen, PLL_SOURCE_XTAL); diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 6dc609d9..d8d3a918 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -151,9 +151,9 @@ static inline uint8_t compute_resample_log( return n; } -#define MIN_MCU_RATE (200000ULL * SR_FP_ONE_HZ) -#define MAX_MCU_RATE (21800000ULL * SR_FP_ONE_HZ) -#define DEFAULT_MCU_RATE (10000000ULL * SR_FP_ONE_HZ) +#define MIN_MCU_RATE SR_FP_KHZ(200) +#define MAX_MCU_RATE SR_FP_KHZ(21800) +#define DEFAULT_MCU_RATE SR_FP_KHZ(10000) static fp_28_36_t applied_afe_rate = RADIO_UNSET; @@ -240,7 +240,7 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) return (new_afe_rate || new_rate || new_n); } -#define DEFAULT_RF (2450ULL * FP_ONE_MHZ) +#define DEFAULT_RF FP_MHZ(2450) static fp_28_36_t applied_offset = RADIO_UNSET; From 14d196d3dd634055b7cac50524feb166d0ea6ea9 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 9 Apr 2026 14:11:09 -0400 Subject: [PATCH 094/238] Use fixed-point type for tuning functions --- firmware/common/fpga_selftest.c | 4 +-- firmware/common/max2831.c | 44 ++++++++++-------------- firmware/common/max2831.h | 8 ++--- firmware/common/max2837.c | 59 +++++++++++++++------------------ firmware/common/max2837.h | 8 ++--- firmware/common/max2839.c | 59 +++++++++++++++------------------ firmware/common/max2839.h | 8 ++--- firmware/common/max283x.c | 8 ++--- firmware/common/max283x.h | 8 ++--- firmware/common/max2871.c | 12 ++++--- firmware/common/max2871.h | 7 ++-- firmware/common/mixer.c | 9 ++--- firmware/common/mixer.h | 6 ++-- firmware/common/rffc5071.c | 35 +++++++++---------- firmware/common/rffc5071.h | 7 ++-- firmware/common/tuning.c | 45 ++++++++++++++++--------- 16 files changed, 165 insertions(+), 162 deletions(-) diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index e2b773e4..c61d0692 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -1,5 +1,5 @@ /* - * Copyright 2025 Great Scott Gadgets + * Copyright 2025-2026 Great Scott Gadgets * * This file is part of HackRF. * @@ -196,7 +196,7 @@ bool fpga_if_xcvr_selftest(void) rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_RX_CALIBRATION); max283x_set_lna_gain(&max283x, 16); max283x_set_vga_gain(&max283x, 36); - max283x_set_frequency(&max283x, 2500000000); + max283x_set_frequency(&max283x, FP_MHZ(2500)); // Capture 1: 4 Msps, tone at 0.5 MHz, narrowband filter OFF sample_rate_set(SR_FP_MHZ(4), true); diff --git a/firmware/common/max2831.c b/firmware/common/max2831.c index efae9eb6..8d0bf3ff 100644 --- a/firmware/common/max2831.c +++ b/firmware/common/max2831.c @@ -1,5 +1,5 @@ /* - * Copyright 2025 Great Scott Gadgets + * Copyright 2025-2026 Great Scott Gadgets * * This file is part of HackRF. * @@ -30,6 +30,7 @@ #include #include #include "max2831.h" +#include "fixed_point.h" #include "max2831_regs.def" // private register def macros #include "selftest.h" #include "adc.h" @@ -222,35 +223,26 @@ void max2831_stop(max2831_driver_t* const drv) max2831_set_mode(drv, MAX2831_MODE_SHUTDOWN); } -void max2831_set_frequency(max2831_driver_t* const drv, uint32_t freq) +/* Assume 40 MHz reference clock with R divider of 2. */ +#define PFD_FREQ_HZ (20ULL * (1000ULL * 1000ULL)) + +void max2831_set_frequency(max2831_driver_t* const drv, fp_40_24_t freq) { - uint32_t div_frac; - uint32_t div_int; - uint32_t div_rem; - uint32_t div_cmp; - int i; + uint64_t div; - /* ASSUME 40MHz PLL. Ratio = F*R/40,000,000. */ - /* TODO: fixed to R=2. Check if it's worth exploring R=1. */ - freq += (20000000 >> 21); /* round to nearest frequency */ - div_int = freq / 20000000; - div_rem = freq % 20000000; - div_frac = 0; - div_cmp = 20000000; - for (i = 0; i < 20; i++) { - div_frac <<= 1; - div_rem <<= 1; - if (div_rem >= div_cmp) { - div_frac |= 0x1; - div_rem -= div_cmp; - } - } + freq += ((PFD_FREQ_HZ * FP_ONE_HZ) >> 21); /* round to nearest frequency */ + div = freq / PFD_FREQ_HZ; + + /* + * Shift from 40.24 fixed-point to 44.20 to match 20-bit fractional + * divider. + */ + div = div >> 4; - /* Write order matters? */ //set_MAX2831_SYN_REF_DIV(drv, MAX2831_SYN_REF_DIV_2); - set_MAX2831_SYN_INT(drv, div_int); - set_MAX2831_SYN_FRAC_HI(drv, (div_frac >> 6) & 0x3fff); - set_MAX2831_SYN_FRAC_LO(drv, div_frac & 0x3f); + set_MAX2831_SYN_INT(drv, (div >> 20) & 0xff); + set_MAX2831_SYN_FRAC_HI(drv, (div >> 6) & 0x3fff); + set_MAX2831_SYN_FRAC_LO(drv, div & 0x3f); max2831_regs_commit(drv); } diff --git a/firmware/common/max2831.h b/firmware/common/max2831.h index 18154649..11ded416 100644 --- a/firmware/common/max2831.h +++ b/firmware/common/max2831.h @@ -1,5 +1,5 @@ /* - * Copyright 2025 Great Scott Gadgets + * Copyright 2025-2026 Great Scott Gadgets * * This file is part of HackRF. * @@ -24,6 +24,7 @@ #include #include +#include "fixed_point.h" #include "gpio.h" #include "spi_bus.h" @@ -86,9 +87,8 @@ void max2831_set_mode(max2831_driver_t* const drv, const max2831_mode_t new_mode extern void max2831_start(max2831_driver_t* const drv); extern void max2831_stop(max2831_driver_t* const drv); -/* Set frequency in Hz. Frequency setting is a multi-step function - * where order of register writes matters. */ -extern void max2831_set_frequency(max2831_driver_t* const drv, uint32_t freq); +/* Set frequency in 1/(2**24) Hz */ +extern void max2831_set_frequency(max2831_driver_t* const drv, fp_40_24_t freq); uint32_t max2831_set_lpf_bandwidth( max2831_driver_t* const drv, const max2831_mode_t mode, diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index a3e91498..1a4f9648 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Will Code * Copyright 2014 Jared Boone * @@ -32,6 +32,7 @@ #include #include #include "max2837.h" +#include "fixed_point.h" #include "max2837_regs.def" // private register def macros #include "selftest.h" @@ -228,24 +229,23 @@ void max2837_stop(max2837_driver_t* const drv) max2837_set_mode(drv, MAX2837_MODE_SHUTDOWN); } -void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq) +/* Assume 40 MHz reference clock with R divider of 1. */ +#define PFD_FREQ_HZ (40ULL * (1000ULL * 1000ULL)) + +void max2837_set_frequency(max2837_driver_t* const drv, fp_40_24_t freq) { uint8_t band; uint8_t lna_band; - uint32_t div_frac; - uint32_t div_int; - uint32_t div_rem; - uint32_t div_cmp; - int i; + uint64_t div; /* Select band. Allow tuning outside specified bands. */ - if (freq < 2400000000U) { + if (freq < FP_MHZ(2400)) { band = MAX2837_LOGEN_BSW_2_3; lna_band = MAX2837_LNAband_2_4; - } else if (freq < 2500000000U) { + } else if (freq < FP_MHZ(2500)) { band = MAX2837_LOGEN_BSW_2_4; lna_band = MAX2837_LNAband_2_4; - } else if (freq < 2600000000U) { + } else if (freq < FP_MHZ(2600)) { band = MAX2837_LOGEN_BSW_2_5; lna_band = MAX2837_LNAband_2_6; } else { @@ -253,34 +253,29 @@ void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq) lna_band = MAX2837_LNAband_2_6; } - /* ASSUME 40MHz PLL. Ratio = F*(4/3)/40,000,000 = F/30,000,000 */ - freq += (30000000 >> 21); /* round to nearest frequency */ - div_int = freq / 30000000; - div_rem = freq % 30000000; - div_frac = 0; - div_cmp = 30000000; - for (i = 0; i < 20; i++) { - div_frac <<= 1; - div_rem <<= 1; - if (div_rem >= div_cmp) { - div_frac |= 0x1; - div_rem -= div_cmp; - } - } + fp_40_24_t vco = (freq * 4) / 3; + + vco += ((PFD_FREQ_HZ * FP_ONE_HZ) >> 21); /* round to nearest frequency */ + div = vco / PFD_FREQ_HZ; + + /* + * Shift from 40.24 fixed-point to 44.20 to match 20-bit fractional + * divider. + */ + div = div >> 4; /* Band settings */ set_MAX2837_LOGEN_BSW(drv, band); set_MAX2837_LNAband(drv, lna_band); - /* Write order matters here, so commit INT and FRAC_HI before - * committing FRAC_LO, which is the trigger for VCO - * auto-select. TODO - it's cleaner this way, but it would be - * faster to explicitly commit the registers explicitly so the - * dirty bits aren't scanned twice. */ - set_MAX2837_SYN_INT(drv, div_int); - set_MAX2837_SYN_FRAC_HI(drv, (div_frac >> 10) & 0x3ff); + /* + * Write order matters here, so commit INT and FRAC_HI before + * committing FRAC_LO, which is the trigger for VCO auto-select. + */ + set_MAX2837_SYN_INT(drv, (div >> 20) & 0xff); + set_MAX2837_SYN_FRAC_HI(drv, (div >> 10) & 0x3ff); max2837_regs_commit(drv); - set_MAX2837_SYN_FRAC_LO(drv, div_frac & 0x3ff); + set_MAX2837_SYN_FRAC_LO(drv, div & 0x3ff); max2837_regs_commit(drv); } diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index 748bafe0..d90844ce 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Will Code * Copyright 2014 Jared Boone * @@ -26,6 +26,7 @@ #include #include +#include "fixed_point.h" #include "gpio.h" #include "spi_bus.h" @@ -77,9 +78,8 @@ void max2837_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode extern void max2837_start(max2837_driver_t* const drv); extern void max2837_stop(max2837_driver_t* const drv); -/* Set frequency in Hz. Frequency setting is a multi-step function - * where order of register writes matters. */ -extern void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq); +/* Set frequency in 1/(2**24) Hz. */ +extern void max2837_set_frequency(max2837_driver_t* const drv, fp_40_24_t freq); uint32_t max2837_set_lpf_bandwidth( max2837_driver_t* const drv, const uint32_t bandwidth_hz); diff --git a/firmware/common/max2839.c b/firmware/common/max2839.c index 62c5561f..b2ef8ffb 100644 --- a/firmware/common/max2839.c +++ b/firmware/common/max2839.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Will Code * Copyright 2014 Jared Boone * @@ -32,6 +32,7 @@ #include #include #include "max2839.h" +#include "fixed_point.h" #include "max2839_regs.def" // private register def macros #include "selftest.h" @@ -239,53 +240,47 @@ void max2839_stop(max2839_driver_t* const drv) max2839_set_mode(drv, MAX2839_MODE_SHUTDOWN); } -void max2839_set_frequency(max2839_driver_t* const drv, uint32_t freq) +/* Assume 40 MHz reference clock with R divider of 1. */ +#define PFD_FREQ_HZ (40ULL * (1000ULL * 1000ULL)) + +void max2839_set_frequency(max2839_driver_t* const drv, fp_40_24_t freq) { uint8_t band; - uint32_t div_frac; - uint32_t div_int; - uint32_t div_rem; - uint32_t div_cmp; - int i; + uint64_t div; /* Select band. Allow tuning outside specified bands. */ - if (freq < 2400000000U) { + if (freq < FP_MHZ(2400)) { band = MAX2839_LOGEN_BSW_2_3; - } else if (freq < 2500000000U) { + } else if (freq < FP_MHZ(2500)) { band = MAX2839_LOGEN_BSW_2_4; - } else if (freq < 2600000000U) { + } else if (freq < FP_MHZ(2600)) { band = MAX2839_LOGEN_BSW_2_5; } else { band = MAX2839_LOGEN_BSW_2_6; } - /* ASSUME 40MHz PLL. Ratio = F*(4/3)/40,000,000 = F/30,000,000 */ - freq += (30000000 >> 21); /* round to nearest frequency */ - div_int = freq / 30000000; - div_rem = freq % 30000000; - div_frac = 0; - div_cmp = 30000000; - for (i = 0; i < 20; i++) { - div_frac <<= 1; - div_rem <<= 1; - if (div_rem >= div_cmp) { - div_frac |= 0x1; - div_rem -= div_cmp; - } - } + fp_40_24_t vco = (freq * 4) / 3; + + vco += ((PFD_FREQ_HZ * FP_ONE_HZ) >> 21); /* round to nearest frequency */ + div = vco / PFD_FREQ_HZ; + + /* + * Shift from 40.24 fixed-point to 44.20 to match 20-bit fractional + * divider. + */ + div = div >> 4; /* Band settings */ set_MAX2839_LOGEN_BSW(drv, band); - /* Write order matters here, so commit INT and FRAC_HI before - * committing FRAC_LO, which is the trigger for VCO - * auto-select. TODO - it's cleaner this way, but it would be - * faster to explicitly commit the registers explicitly so the - * dirty bits aren't scanned twice. */ - set_MAX2839_SYN_INT(drv, div_int); - set_MAX2839_SYN_FRAC_HI(drv, (div_frac >> 10) & 0x3ff); + /* + * Write order matters here, so commit INT and FRAC_HI before + * committing FRAC_LO, which is the trigger for VCO auto-select. + */ + set_MAX2839_SYN_INT(drv, (div >> 20) & 0xff); + set_MAX2839_SYN_FRAC_HI(drv, (div >> 10) & 0x3ff); max2839_regs_commit(drv); - set_MAX2839_SYN_FRAC_LO(drv, div_frac & 0x3ff); + set_MAX2839_SYN_FRAC_LO(drv, div & 0x3ff); max2839_regs_commit(drv); } diff --git a/firmware/common/max2839.h b/firmware/common/max2839.h index b6c21194..1836bda2 100644 --- a/firmware/common/max2839.h +++ b/firmware/common/max2839.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Will Code * Copyright 2014 Jared Boone * @@ -26,6 +26,7 @@ #include #include +#include "fixed_point.h" #include "gpio.h" #include "spi_bus.h" @@ -79,9 +80,8 @@ void max2839_set_mode(max2839_driver_t* const drv, const max2839_mode_t new_mode extern void max2839_start(max2839_driver_t* const drv); extern void max2839_stop(max2839_driver_t* const drv); -/* Set frequency in Hz. Frequency setting is a multi-step function - * where order of register writes matters. */ -extern void max2839_set_frequency(max2839_driver_t* const drv, uint32_t freq); +/* Set frequency in 1/(2**24) Hz. */ +extern void max2839_set_frequency(max2839_driver_t* const drv, fp_40_24_t freq); uint32_t max2839_set_lpf_bandwidth( max2839_driver_t* const drv, const uint32_t bandwidth_hz); diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index 7c5de380..4a9f39db 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Will Code * Copyright 2014 Jared Boone * @@ -25,6 +25,7 @@ #include "max283x.h" +#include "fixed_point.h" #include "platform_gpio.h" #include "spi_bus.h" #if defined(PRALINE) @@ -288,9 +289,8 @@ void max283x_stop(max283x_driver_t* const drv) } } -/* Set frequency in Hz. Frequency setting is a multi-step function - * where order of register writes matters. */ -void max283x_set_frequency(max283x_driver_t* const drv, uint32_t freq) +/* Set frequency in 1/(2**24) Hz. */ +void max283x_set_frequency(max283x_driver_t* const drv, fp_40_24_t freq) { switch (drv->type) { #ifdef PRALINE diff --git a/firmware/common/max283x.h b/firmware/common/max283x.h index a96c908f..0fd7ac85 100644 --- a/firmware/common/max283x.h +++ b/firmware/common/max283x.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Will Code * Copyright 2014 Jared Boone * @@ -26,6 +26,7 @@ #include #include +#include "fixed_point.h" #if defined(PRALINE) #include "max2831.h" #else @@ -101,9 +102,8 @@ void max283x_set_mode(max283x_driver_t* const drv, const max283x_mode_t new_mode void max283x_start(max283x_driver_t* const drv); void max283x_stop(max283x_driver_t* const drv); -/* Set frequency in Hz. Frequency setting is a multi-step function - * where order of register writes matters. */ -void max283x_set_frequency(max283x_driver_t* const drv, uint32_t freq); +/* Set frequency in 1/(2**24) Hz. */ +void max283x_set_frequency(max283x_driver_t* const drv, fp_40_24_t freq); uint32_t max283x_set_lpf_bandwidth( max283x_driver_t* const drv, const max283x_mode_t mode, diff --git a/firmware/common/max2871.c b/firmware/common/max2871.c index 2d9b0c29..16ba18f1 100644 --- a/firmware/common/max2871.c +++ b/firmware/common/max2871.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2022 Great Scott Gadgets + * Copyright 2015-2026 Great Scott Gadgets * * This file is part of HackRF. * @@ -24,6 +24,7 @@ #include #include +#include "fixed_point.h" #include "max2871_regs.h" #include "selftest.h" #include "platform_scu.h" @@ -132,7 +133,7 @@ void max2871_setup(max2871_driver_t* const drv) max2871_write_registers(drv); - max2871_set_frequency(drv, 3500); + max2871_set_frequency(drv, FP_MHZ(3500)); } static void delay_ms(int ms) @@ -228,9 +229,10 @@ static void max2871_write_registers(max2871_driver_t* const drv) } } -/* Set frequency (MHz). */ -uint64_t max2871_set_frequency(max2871_driver_t* const drv, uint16_t mhz) +/* Set frequency in 1/(2**24) Hz, rounded to nearest 40 MHz. */ +fp_40_24_t max2871_set_frequency(max2871_driver_t* const drv, fp_40_24_t lo) { + uint16_t mhz = lo / FP_ONE_MHZ; int n = mhz / 40; int diva = 0; @@ -251,7 +253,7 @@ uint64_t max2871_set_frequency(max2871_driver_t* const drv, uint16_t mhz) max2871_set_RFA_EN(1); max2871_write_registers(drv); - return (mhz / 40) * 40 * 1000000; + return (mhz / 40) * FP_MHZ(40); } void max2871_enable(max2871_driver_t* const drv) diff --git a/firmware/common/max2871.h b/firmware/common/max2871.h index eb1ecbf0..1b3e1a13 100644 --- a/firmware/common/max2871.h +++ b/firmware/common/max2871.h @@ -1,5 +1,5 @@ /* - * Copyright 2017 Great Scott Gadgets + * Copyright 2017-2026 Great Scott Gadgets * * This file is part of HackRF. * @@ -21,8 +21,7 @@ #pragma once -#include - +#include "fixed_point.h" #include "gpio.h" typedef struct { @@ -35,6 +34,6 @@ typedef struct { } max2871_driver_t; extern void max2871_setup(max2871_driver_t* const drv); -extern uint64_t max2871_set_frequency(max2871_driver_t* const drv, uint16_t mhz); +extern fp_40_24_t max2871_set_frequency(max2871_driver_t* const drv, fp_40_24_t lo); extern void max2871_enable(max2871_driver_t* const drv); extern void max2871_disable(max2871_driver_t* const drv); diff --git a/firmware/common/mixer.c b/firmware/common/mixer.c index cc598701..c663c28c 100644 --- a/firmware/common/mixer.c +++ b/firmware/common/mixer.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 Great Scott Gadgets + * Copyright 2017-2026 Great Scott Gadgets * * This file is part of HackRF. * @@ -21,6 +21,7 @@ #include "mixer.h" +#include "fixed_point.h" #include "platform_gpio.h" #if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) #include "rffc5071.h" @@ -84,12 +85,12 @@ void mixer_setup(mixer_driver_t* const mixer) #endif } -uint64_t mixer_set_frequency(mixer_driver_t* const mixer, uint64_t hz) +fp_40_24_t mixer_set_frequency(mixer_driver_t* const mixer, fp_40_24_t lo) { #if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) - return rffc5071_set_frequency(mixer, hz); + return rffc5071_set_frequency(mixer, lo); #elif defined(RAD1O) - return max2871_set_frequency(mixer, hz / 1000000); + return max2871_set_frequency(mixer, lo); #endif } diff --git a/firmware/common/mixer.h b/firmware/common/mixer.h index d2eb57e9..9ef3c602 100644 --- a/firmware/common/mixer.h +++ b/firmware/common/mixer.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2014 Jared Boone * * This file is part of HackRF. @@ -22,6 +22,8 @@ #pragma once +#include "fixed_point.h" + #if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) #include "rffc5071.h" typedef rffc5071_driver_t mixer_driver_t; @@ -35,7 +37,7 @@ extern void mixer_bus_setup(mixer_driver_t* const mixer); extern void mixer_setup(mixer_driver_t* const mixer); /* Set frequency (Hz). */ -extern uint64_t mixer_set_frequency(mixer_driver_t* const mixer, uint64_t hz); +extern fp_40_24_t mixer_set_frequency(mixer_driver_t* const mixer, fp_40_24_t lo); extern void mixer_enable(mixer_driver_t* const mixer); extern void mixer_disable(mixer_driver_t* const mixer); diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 177537f5..c229d417 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2014 Jared Boone * * This file is part of HackRF. @@ -39,6 +39,7 @@ #endif #include "delay.h" +#include "fixed_point.h" #include "rffc5071.h" #include "rffc5071_regs.def" // private register def macros #include "selftest.h" @@ -153,7 +154,7 @@ void rffc5071_lock_test(rffc5071_driver_t* const drv) for (int i = 0; i < NUM_LOCK_ATTEMPTS; i++) { // Tune to 100MHz. - rffc5071_set_frequency(drv, 100000000); + rffc5071_set_frequency(drv, FP_MHZ(100)); rffc5071_enable(drv); // Wait 1ms. @@ -257,23 +258,23 @@ void rffc5071_enable(rffc5071_driver_t* const drv) } } -#define FREQ_ONE_MHZ (1000ULL * 1000ULL) -#define REF_FREQ (40 * FREQ_ONE_MHZ) -#define LO_MAX (5400 * FREQ_ONE_MHZ) +#define REF_FREQ_HZ (40ULL * (1000ULL * 1000ULL)) +#define MIN_LO FP_KHZ(84375) +#define MAX_LO FP_MHZ(5400) -/* configure frequency synthesizer (lo in Hz) */ -uint64_t rffc5071_config_synth(rffc5071_driver_t* const drv, uint64_t lo) +/* configure frequency synthesizer (lo in 1/(2**24) Hz) */ +fp_40_24_t rffc5071_config_synth(rffc5071_driver_t* const drv, fp_40_24_t lo) { - uint64_t fvco; + fp_40_24_t fvco; uint8_t fbkdivlog; uint16_t n; - uint64_t tune_freq_hz; + fp_40_24_t tune_freq; uint16_t p1nmsb; uint8_t p1nlsb; /* Calculate n_lo (no division) */ uint8_t n_lo = 0; - uint64_t x = LO_MAX >> 1; + fp_40_24_t x = MAX_LO >> 1; while ((x >= lo) && (n_lo < 5)) { n_lo++; x >>= 1; @@ -285,7 +286,7 @@ uint64_t rffc5071_config_synth(rffc5071_driver_t* const drv, uint64_t lo) * Higher charge pump leakage setting and fbkdivlog are required above * 3.2 GHz. */ - if (fvco > (3200 * FREQ_ONE_MHZ)) { + if (fvco > FP_MHZ(3200)) { fbkdivlog = 2; set_RFFC5071_PLLCPL(drv, 3); } else { @@ -293,7 +294,7 @@ uint64_t rffc5071_config_synth(rffc5071_driver_t* const drv, uint64_t lo) set_RFFC5071_PLLCPL(drv, 2); } - uint64_t tmp_n = (fvco << (24ULL - fbkdivlog)) / REF_FREQ; + uint64_t tmp_n = (fvco / REF_FREQ_HZ) >> fbkdivlog; /* Round to nearest step = ref_MHz / 2**s. For s=6, step=625000 Hz */ /* This also ensures the lowest 22-s fractional bits are set to 0. */ @@ -305,7 +306,7 @@ uint64_t rffc5071_config_synth(rffc5071_driver_t* const drv, uint64_t lo) p1nmsb = (tmp_n >> 8ULL) & 0xffff; p1nlsb = tmp_n & 0xff; - tune_freq_hz = (tmp_n * REF_FREQ) >> (24 - fbkdivlog + n_lo); + tune_freq = ((tmp_n * REF_FREQ_HZ) << fbkdivlog) >> n_lo; /* Path 2 */ set_RFFC5071_P2LODIV(drv, n_lo); @@ -319,14 +320,14 @@ uint64_t rffc5071_config_synth(rffc5071_driver_t* const drv, uint64_t lo) rffc5071_regs_commit(drv); - return tune_freq_hz; + return tune_freq; } -uint64_t rffc5071_set_frequency(rffc5071_driver_t* const drv, uint64_t hz) +fp_40_24_t rffc5071_set_frequency(rffc5071_driver_t* const drv, fp_40_24_t lo) { - uint32_t tune_freq; + fp_40_24_t tune_freq; - tune_freq = rffc5071_config_synth(drv, hz); + tune_freq = rffc5071_config_synth(drv, lo); if (enabled) { set_RFFC5071_RELOK(drv, 1); rffc5071_regs_commit(drv); diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index 1ddf4728..098f1628 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2014 Jared Boone * * This file is part of HackRF. @@ -25,6 +25,7 @@ #include #include +#include "fixed_point.h" #include "gpio.h" #include "spi_bus.h" @@ -59,8 +60,8 @@ extern void rffc5071_reg_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t * provided routines for those operations. */ extern void rffc5071_regs_commit(rffc5071_driver_t* const drv); -/* Set frequency (Hz). */ -extern uint64_t rffc5071_set_frequency(rffc5071_driver_t* const drv, uint64_t hz); +/* Set frequency in 1/(2**24) Hz. */ +extern fp_40_24_t rffc5071_set_frequency(rffc5071_driver_t* const drv, fp_40_24_t lo); extern void rffc5071_enable(rffc5071_driver_t* const drv); extern void rffc5071_disable(rffc5071_driver_t* const drv); diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index b2d49ec4..000ede9d 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Jared Boone * Copyright 2013 Benjamin Vernoux * @@ -23,6 +23,7 @@ #include "tuning.h" +#include "fixed_point.h" #include "hackrf_core.h" #include "hackrf_ui.h" #include "max283x.h" @@ -102,13 +103,15 @@ bool set_freq(const uint64_t freq, const transceiver_mode_t opmode) #endif mixer_freq_hz = max2837_freq_nominal_hz + freq; /* Set Freq and read real freq */ - real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_hz); - max283x_set_frequency(&max283x, real_mixer_freq_hz - freq); + real_mixer_freq_hz = + mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ) / + FP_ONE_HZ; + max283x_set_frequency(&max283x, (real_mixer_freq_hz - freq) * FP_ONE_HZ); 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, opmode); /* mixer_freq_mhz <= not used in Bypass mode */ - max283x_set_frequency(&max283x, freq); + max283x_set_frequency(&max283x, freq * FP_ONE_HZ); 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) { @@ -128,8 +131,10 @@ bool set_freq(const uint64_t freq, const transceiver_mode_t opmode) rf_path_set_filter(&rf_path, RF_PATH_FILTER_HIGH_PASS, opmode); mixer_freq_hz = freq - max2837_freq_nominal_hz; /* Set Freq and read real freq */ - real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_hz); - max283x_set_frequency(&max283x, freq - real_mixer_freq_hz); + real_mixer_freq_hz = + mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ) / + FP_ONE_HZ; + max283x_set_frequency(&max283x, (freq - real_mixer_freq_hz) * FP_ONE_HZ); sgpio_cpld_set_mixer_invert(&sgpio_config, 0); } else { /* Error freq_mhz too high */ @@ -180,26 +185,36 @@ bool tuning_set_frequency( if (cfg->if_mhz == 0) { rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS, opmode); - max283x_set_frequency(&max283x, rf); + max283x_set_frequency(&max283x, rf * FP_ONE_HZ); 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, opmode); if (cfg->high_lo) { mixer_freq_hz = FREQ_ONE_MHZ * cfg->if_mhz + rf; - real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_hz); - max283x_set_frequency(&max283x, real_mixer_freq_hz - rf); + real_mixer_freq_hz = + mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ) / + FP_ONE_HZ; + max283x_set_frequency( + &max283x, + (real_mixer_freq_hz - rf) * FP_ONE_HZ); sgpio_cpld_set_mixer_invert(&sgpio_config, 1); } else { mixer_freq_hz = FREQ_ONE_MHZ * cfg->if_mhz - rf; - real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_hz); - max283x_set_frequency(&max283x, real_mixer_freq_hz + rf); + real_mixer_freq_hz = + mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ) / + FP_ONE_HZ; + max283x_set_frequency( + &max283x, + (real_mixer_freq_hz + rf) * FP_ONE_HZ); sgpio_cpld_set_mixer_invert(&sgpio_config, 0); } } else { rf_path_set_filter(&rf_path, RF_PATH_FILTER_HIGH_PASS, opmode); mixer_freq_hz = rf - FREQ_ONE_MHZ * cfg->if_mhz; - real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_hz); - max283x_set_frequency(&max283x, rf - real_mixer_freq_hz); + real_mixer_freq_hz = + mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ) / + FP_ONE_HZ; + max283x_set_frequency(&max283x, (rf - real_mixer_freq_hz) * FP_ONE_HZ); sgpio_cpld_set_mixer_invert(&sgpio_config, 0); } @@ -233,7 +248,7 @@ bool set_freq_explicit( } rf_path_set_filter(&rf_path, path, opmode); - max283x_set_frequency(&max283x, if_freq_hz); + max283x_set_frequency(&max283x, if_freq_hz * FP_ONE_HZ); if (lo_freq_hz > if_freq_hz) { sgpio_cpld_set_mixer_invert(&sgpio_config, 1); @@ -241,7 +256,7 @@ bool set_freq_explicit( sgpio_cpld_set_mixer_invert(&sgpio_config, 0); } if (path != RF_PATH_FILTER_BYPASS) { - (void) mixer_set_frequency(&mixer, lo_freq_hz); + (void) mixer_set_frequency(&mixer, lo_freq_hz * FP_ONE_HZ); } return true; } From e84e867a6c1e3a9e27c8367f8bc0ae7cb06232f1 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 9 Apr 2026 14:14:11 -0400 Subject: [PATCH 095/238] Return tuned frequency from tuning functions --- firmware/common/max2831.c | 4 +++- firmware/common/max2831.h | 2 +- firmware/common/max2837.c | 4 +++- firmware/common/max2837.h | 2 +- firmware/common/max2839.c | 4 +++- firmware/common/max2839.h | 2 +- firmware/common/max283x.c | 9 +++++---- firmware/common/max283x.h | 2 +- 8 files changed, 18 insertions(+), 11 deletions(-) diff --git a/firmware/common/max2831.c b/firmware/common/max2831.c index 8d0bf3ff..ee621b23 100644 --- a/firmware/common/max2831.c +++ b/firmware/common/max2831.c @@ -226,7 +226,7 @@ void max2831_stop(max2831_driver_t* const drv) /* Assume 40 MHz reference clock with R divider of 2. */ #define PFD_FREQ_HZ (20ULL * (1000ULL * 1000ULL)) -void max2831_set_frequency(max2831_driver_t* const drv, fp_40_24_t freq) +fp_40_24_t max2831_set_frequency(max2831_driver_t* const drv, fp_40_24_t freq) { uint64_t div; @@ -244,6 +244,8 @@ void max2831_set_frequency(max2831_driver_t* const drv, fp_40_24_t freq) set_MAX2831_SYN_FRAC_HI(drv, (div >> 6) & 0x3fff); set_MAX2831_SYN_FRAC_LO(drv, div & 0x3f); max2831_regs_commit(drv); + + return PFD_FREQ_HZ * (div << 4); } typedef struct { diff --git a/firmware/common/max2831.h b/firmware/common/max2831.h index 11ded416..58b15283 100644 --- a/firmware/common/max2831.h +++ b/firmware/common/max2831.h @@ -88,7 +88,7 @@ extern void max2831_start(max2831_driver_t* const drv); extern void max2831_stop(max2831_driver_t* const drv); /* Set frequency in 1/(2**24) Hz */ -extern void max2831_set_frequency(max2831_driver_t* const drv, fp_40_24_t freq); +extern fp_40_24_t max2831_set_frequency(max2831_driver_t* const drv, fp_40_24_t freq); uint32_t max2831_set_lpf_bandwidth( max2831_driver_t* const drv, const max2831_mode_t mode, diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index 1a4f9648..c0073226 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -232,7 +232,7 @@ void max2837_stop(max2837_driver_t* const drv) /* Assume 40 MHz reference clock with R divider of 1. */ #define PFD_FREQ_HZ (40ULL * (1000ULL * 1000ULL)) -void max2837_set_frequency(max2837_driver_t* const drv, fp_40_24_t freq) +fp_40_24_t max2837_set_frequency(max2837_driver_t* const drv, fp_40_24_t freq) { uint8_t band; uint8_t lna_band; @@ -277,6 +277,8 @@ void max2837_set_frequency(max2837_driver_t* const drv, fp_40_24_t freq) max2837_regs_commit(drv); set_MAX2837_SYN_FRAC_LO(drv, div & 0x3ff); max2837_regs_commit(drv); + + return ((PFD_FREQ_HZ * 3) / 4) * (div << 4); } typedef struct { diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index d90844ce..f348568b 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -79,7 +79,7 @@ extern void max2837_start(max2837_driver_t* const drv); extern void max2837_stop(max2837_driver_t* const drv); /* Set frequency in 1/(2**24) Hz. */ -extern void max2837_set_frequency(max2837_driver_t* const drv, fp_40_24_t freq); +extern fp_40_24_t max2837_set_frequency(max2837_driver_t* const drv, fp_40_24_t freq); uint32_t max2837_set_lpf_bandwidth( max2837_driver_t* const drv, const uint32_t bandwidth_hz); diff --git a/firmware/common/max2839.c b/firmware/common/max2839.c index b2ef8ffb..27db1dee 100644 --- a/firmware/common/max2839.c +++ b/firmware/common/max2839.c @@ -243,7 +243,7 @@ void max2839_stop(max2839_driver_t* const drv) /* Assume 40 MHz reference clock with R divider of 1. */ #define PFD_FREQ_HZ (40ULL * (1000ULL * 1000ULL)) -void max2839_set_frequency(max2839_driver_t* const drv, fp_40_24_t freq) +fp_40_24_t max2839_set_frequency(max2839_driver_t* const drv, fp_40_24_t freq) { uint8_t band; uint64_t div; @@ -282,6 +282,8 @@ void max2839_set_frequency(max2839_driver_t* const drv, fp_40_24_t freq) max2839_regs_commit(drv); set_MAX2839_SYN_FRAC_LO(drv, div & 0x3ff); max2839_regs_commit(drv); + + return ((PFD_FREQ_HZ * 3) / 4) * (div << 4); } typedef struct { diff --git a/firmware/common/max2839.h b/firmware/common/max2839.h index 1836bda2..7b9c253e 100644 --- a/firmware/common/max2839.h +++ b/firmware/common/max2839.h @@ -81,7 +81,7 @@ extern void max2839_start(max2839_driver_t* const drv); extern void max2839_stop(max2839_driver_t* const drv); /* Set frequency in 1/(2**24) Hz. */ -extern void max2839_set_frequency(max2839_driver_t* const drv, fp_40_24_t freq); +extern fp_40_24_t max2839_set_frequency(max2839_driver_t* const drv, fp_40_24_t freq); uint32_t max2839_set_lpf_bandwidth( max2839_driver_t* const drv, const uint32_t bandwidth_hz); diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index 4a9f39db..1a226ee2 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -290,23 +290,24 @@ void max283x_stop(max283x_driver_t* const drv) } /* Set frequency in 1/(2**24) Hz. */ -void max283x_set_frequency(max283x_driver_t* const drv, fp_40_24_t freq) +fp_40_24_t max283x_set_frequency(max283x_driver_t* const drv, fp_40_24_t freq) { switch (drv->type) { #ifdef PRALINE case MAX2831_VARIANT: - max2831_set_frequency(&drv->drv.max2831, freq); + return max2831_set_frequency(&drv->drv.max2831, freq); break; #else case MAX2837_VARIANT: - max2837_set_frequency(&drv->drv.max2837, freq); + return max2837_set_frequency(&drv->drv.max2837, freq); break; case MAX2839_VARIANT: - max2839_set_frequency(&drv->drv.max2839, freq); + return max2839_set_frequency(&drv->drv.max2839, freq); break; #endif } + return 0; } uint32_t max283x_set_lpf_bandwidth( diff --git a/firmware/common/max283x.h b/firmware/common/max283x.h index 0fd7ac85..4856114f 100644 --- a/firmware/common/max283x.h +++ b/firmware/common/max283x.h @@ -103,7 +103,7 @@ void max283x_start(max283x_driver_t* const drv); void max283x_stop(max283x_driver_t* const drv); /* Set frequency in 1/(2**24) Hz. */ -void max283x_set_frequency(max283x_driver_t* const drv, fp_40_24_t freq); +fp_40_24_t max283x_set_frequency(max283x_driver_t* const drv, fp_40_24_t freq); uint32_t max283x_set_lpf_bandwidth( max283x_driver_t* const drv, const max283x_mode_t mode, From d032dedf9f765d25cdecea0b6a980222357cba31 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 9 Apr 2026 14:18:02 -0400 Subject: [PATCH 096/238] Add program option to tuning functions --- firmware/common/fpga_selftest.c | 2 +- firmware/common/max2831.c | 21 +++++++++----- firmware/common/max2831.h | 7 +++-- firmware/common/max2837.c | 35 +++++++++++++--------- firmware/common/max2837.h | 7 +++-- firmware/common/max2839.c | 33 ++++++++++++--------- firmware/common/max2839.h | 7 +++-- firmware/common/max283x.c | 16 +++++++---- firmware/common/max283x.h | 5 +++- firmware/common/max2871.c | 22 +++++++------- firmware/common/max2871.h | 7 ++++- firmware/common/mixer.c | 8 ++++-- firmware/common/mixer.h | 7 ++++- firmware/common/rffc5071.c | 51 +++++++++++++++++++-------------- firmware/common/rffc5071.h | 5 +++- firmware/common/tuning.c | 47 +++++++++++++++++++----------- 16 files changed, 179 insertions(+), 101 deletions(-) diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index c61d0692..270d3ff4 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -196,7 +196,7 @@ bool fpga_if_xcvr_selftest(void) rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_RX_CALIBRATION); max283x_set_lna_gain(&max283x, 16); max283x_set_vga_gain(&max283x, 36); - max283x_set_frequency(&max283x, FP_MHZ(2500)); + max283x_set_frequency(&max283x, FP_MHZ(2500), true); // Capture 1: 4 Msps, tone at 0.5 MHz, narrowband filter OFF sample_rate_set(SR_FP_MHZ(4), true); diff --git a/firmware/common/max2831.c b/firmware/common/max2831.c index ee621b23..f0afaccc 100644 --- a/firmware/common/max2831.c +++ b/firmware/common/max2831.c @@ -27,9 +27,11 @@ * pirate commands to do the same thing. */ +#include "max2831.h" + +#include #include #include -#include "max2831.h" #include "fixed_point.h" #include "max2831_regs.def" // private register def macros #include "selftest.h" @@ -226,7 +228,10 @@ void max2831_stop(max2831_driver_t* const drv) /* Assume 40 MHz reference clock with R divider of 2. */ #define PFD_FREQ_HZ (20ULL * (1000ULL * 1000ULL)) -fp_40_24_t max2831_set_frequency(max2831_driver_t* const drv, fp_40_24_t freq) +fp_40_24_t max2831_set_frequency( + max2831_driver_t* const drv, + fp_40_24_t freq, + bool program) { uint64_t div; @@ -239,11 +244,13 @@ fp_40_24_t max2831_set_frequency(max2831_driver_t* const drv, fp_40_24_t freq) */ div = div >> 4; - //set_MAX2831_SYN_REF_DIV(drv, MAX2831_SYN_REF_DIV_2); - set_MAX2831_SYN_INT(drv, (div >> 20) & 0xff); - set_MAX2831_SYN_FRAC_HI(drv, (div >> 6) & 0x3fff); - set_MAX2831_SYN_FRAC_LO(drv, div & 0x3f); - max2831_regs_commit(drv); + if (program) { + //set_MAX2831_SYN_REF_DIV(drv, MAX2831_SYN_REF_DIV_2); + set_MAX2831_SYN_INT(drv, (div >> 20) & 0xff); + set_MAX2831_SYN_FRAC_HI(drv, (div >> 6) & 0x3fff); + set_MAX2831_SYN_FRAC_LO(drv, div & 0x3f); + max2831_regs_commit(drv); + } return PFD_FREQ_HZ * (div << 4); } diff --git a/firmware/common/max2831.h b/firmware/common/max2831.h index 58b15283..0885fd39 100644 --- a/firmware/common/max2831.h +++ b/firmware/common/max2831.h @@ -21,8 +21,8 @@ #pragma once -#include #include +#include #include "fixed_point.h" #include "gpio.h" @@ -88,7 +88,10 @@ extern void max2831_start(max2831_driver_t* const drv); extern void max2831_stop(max2831_driver_t* const drv); /* Set frequency in 1/(2**24) Hz */ -extern fp_40_24_t max2831_set_frequency(max2831_driver_t* const drv, fp_40_24_t freq); +extern fp_40_24_t max2831_set_frequency( + max2831_driver_t* const drv, + fp_40_24_t freq, + bool program); uint32_t max2831_set_lpf_bandwidth( max2831_driver_t* const drv, const max2831_mode_t mode, diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index c0073226..b5f09239 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -29,9 +29,11 @@ * pirate commands to do the same thing. */ +#include "max2837.h" + +#include #include #include -#include "max2837.h" #include "fixed_point.h" #include "max2837_regs.def" // private register def macros #include "selftest.h" @@ -232,7 +234,10 @@ void max2837_stop(max2837_driver_t* const drv) /* Assume 40 MHz reference clock with R divider of 1. */ #define PFD_FREQ_HZ (40ULL * (1000ULL * 1000ULL)) -fp_40_24_t max2837_set_frequency(max2837_driver_t* const drv, fp_40_24_t freq) +fp_40_24_t max2837_set_frequency( + max2837_driver_t* const drv, + fp_40_24_t freq, + bool program) { uint8_t band; uint8_t lna_band; @@ -264,19 +269,21 @@ fp_40_24_t max2837_set_frequency(max2837_driver_t* const drv, fp_40_24_t freq) */ div = div >> 4; - /* Band settings */ - set_MAX2837_LOGEN_BSW(drv, band); - set_MAX2837_LNAband(drv, lna_band); + if (program) { + /* Band settings */ + set_MAX2837_LOGEN_BSW(drv, band); + set_MAX2837_LNAband(drv, lna_band); - /* - * Write order matters here, so commit INT and FRAC_HI before - * committing FRAC_LO, which is the trigger for VCO auto-select. - */ - set_MAX2837_SYN_INT(drv, (div >> 20) & 0xff); - set_MAX2837_SYN_FRAC_HI(drv, (div >> 10) & 0x3ff); - max2837_regs_commit(drv); - set_MAX2837_SYN_FRAC_LO(drv, div & 0x3ff); - max2837_regs_commit(drv); + /* + * Write order matters here, so commit INT and FRAC_HI before + * committing FRAC_LO, which is the trigger for VCO auto-select. + */ + set_MAX2837_SYN_INT(drv, (div >> 20) & 0xff); + set_MAX2837_SYN_FRAC_HI(drv, (div >> 10) & 0x3ff); + max2837_regs_commit(drv); + set_MAX2837_SYN_FRAC_LO(drv, div & 0x3ff); + max2837_regs_commit(drv); + } return ((PFD_FREQ_HZ * 3) / 4) * (div << 4); } diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index f348568b..f32bde6e 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -23,8 +23,8 @@ #pragma once -#include #include +#include #include "fixed_point.h" #include "gpio.h" @@ -79,7 +79,10 @@ extern void max2837_start(max2837_driver_t* const drv); extern void max2837_stop(max2837_driver_t* const drv); /* Set frequency in 1/(2**24) Hz. */ -extern fp_40_24_t max2837_set_frequency(max2837_driver_t* const drv, fp_40_24_t freq); +extern fp_40_24_t max2837_set_frequency( + max2837_driver_t* const drv, + fp_40_24_t freq, + bool program); uint32_t max2837_set_lpf_bandwidth( max2837_driver_t* const drv, const uint32_t bandwidth_hz); diff --git a/firmware/common/max2839.c b/firmware/common/max2839.c index 27db1dee..a34c2d75 100644 --- a/firmware/common/max2839.c +++ b/firmware/common/max2839.c @@ -29,9 +29,11 @@ * pirate commands to do the same thing. */ +#include "max2839.h" + +#include #include #include -#include "max2839.h" #include "fixed_point.h" #include "max2839_regs.def" // private register def macros #include "selftest.h" @@ -243,7 +245,10 @@ void max2839_stop(max2839_driver_t* const drv) /* Assume 40 MHz reference clock with R divider of 1. */ #define PFD_FREQ_HZ (40ULL * (1000ULL * 1000ULL)) -fp_40_24_t max2839_set_frequency(max2839_driver_t* const drv, fp_40_24_t freq) +fp_40_24_t max2839_set_frequency( + max2839_driver_t* const drv, + fp_40_24_t freq, + bool program) { uint8_t band; uint64_t div; @@ -270,18 +275,20 @@ fp_40_24_t max2839_set_frequency(max2839_driver_t* const drv, fp_40_24_t freq) */ div = div >> 4; - /* Band settings */ - set_MAX2839_LOGEN_BSW(drv, band); + if (program) { + /* Band settings */ + set_MAX2839_LOGEN_BSW(drv, band); - /* - * Write order matters here, so commit INT and FRAC_HI before - * committing FRAC_LO, which is the trigger for VCO auto-select. - */ - set_MAX2839_SYN_INT(drv, (div >> 20) & 0xff); - set_MAX2839_SYN_FRAC_HI(drv, (div >> 10) & 0x3ff); - max2839_regs_commit(drv); - set_MAX2839_SYN_FRAC_LO(drv, div & 0x3ff); - max2839_regs_commit(drv); + /* + * Write order matters here, so commit INT and FRAC_HI before + * committing FRAC_LO, which is the trigger for VCO auto-select. + */ + set_MAX2839_SYN_INT(drv, (div >> 20) & 0xff); + set_MAX2839_SYN_FRAC_HI(drv, (div >> 10) & 0x3ff); + max2839_regs_commit(drv); + set_MAX2839_SYN_FRAC_LO(drv, div & 0x3ff); + max2839_regs_commit(drv); + } return ((PFD_FREQ_HZ * 3) / 4) * (div << 4); } diff --git a/firmware/common/max2839.h b/firmware/common/max2839.h index 7b9c253e..0e397294 100644 --- a/firmware/common/max2839.h +++ b/firmware/common/max2839.h @@ -23,8 +23,8 @@ #pragma once -#include #include +#include #include "fixed_point.h" #include "gpio.h" @@ -81,7 +81,10 @@ extern void max2839_start(max2839_driver_t* const drv); extern void max2839_stop(max2839_driver_t* const drv); /* Set frequency in 1/(2**24) Hz. */ -extern fp_40_24_t max2839_set_frequency(max2839_driver_t* const drv, fp_40_24_t freq); +extern fp_40_24_t max2839_set_frequency( + max2839_driver_t* const drv, + fp_40_24_t freq, + bool program); uint32_t max2839_set_lpf_bandwidth( max2839_driver_t* const drv, const uint32_t bandwidth_hz); diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index 1a226ee2..c0e912e5 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -21,10 +21,11 @@ * Boston, MA 02110-1301, USA. */ -#include - #include "max283x.h" +#include +#include + #include "fixed_point.h" #include "platform_gpio.h" #include "spi_bus.h" @@ -290,20 +291,23 @@ void max283x_stop(max283x_driver_t* const drv) } /* Set frequency in 1/(2**24) Hz. */ -fp_40_24_t max283x_set_frequency(max283x_driver_t* const drv, fp_40_24_t freq) +fp_40_24_t max283x_set_frequency( + max283x_driver_t* const drv, + fp_40_24_t freq, + bool program) { switch (drv->type) { #ifdef PRALINE case MAX2831_VARIANT: - return max2831_set_frequency(&drv->drv.max2831, freq); + return max2831_set_frequency(&drv->drv.max2831, freq, program); break; #else case MAX2837_VARIANT: - return max2837_set_frequency(&drv->drv.max2837, freq); + return max2837_set_frequency(&drv->drv.max2837, freq, program); break; case MAX2839_VARIANT: - return max2839_set_frequency(&drv->drv.max2839, freq); + return max2839_set_frequency(&drv->drv.max2839, freq, program); break; #endif } diff --git a/firmware/common/max283x.h b/firmware/common/max283x.h index 4856114f..db5a93f8 100644 --- a/firmware/common/max283x.h +++ b/firmware/common/max283x.h @@ -103,7 +103,10 @@ void max283x_start(max283x_driver_t* const drv); void max283x_stop(max283x_driver_t* const drv); /* Set frequency in 1/(2**24) Hz. */ -fp_40_24_t max283x_set_frequency(max283x_driver_t* const drv, fp_40_24_t freq); +fp_40_24_t max283x_set_frequency( + max283x_driver_t* const drv, + fp_40_24_t freq, + bool program); uint32_t max283x_set_lpf_bandwidth( max283x_driver_t* const drv, const max283x_mode_t mode, diff --git a/firmware/common/max2871.c b/firmware/common/max2871.c index 16ba18f1..e783f80f 100644 --- a/firmware/common/max2871.c +++ b/firmware/common/max2871.c @@ -133,7 +133,7 @@ void max2871_setup(max2871_driver_t* const drv) max2871_write_registers(drv); - max2871_set_frequency(drv, FP_MHZ(3500)); + max2871_set_frequency(drv, FP_MHZ(3500), true); } static void delay_ms(int ms) @@ -230,7 +230,7 @@ static void max2871_write_registers(max2871_driver_t* const drv) } /* Set frequency in 1/(2**24) Hz, rounded to nearest 40 MHz. */ -fp_40_24_t max2871_set_frequency(max2871_driver_t* const drv, fp_40_24_t lo) +fp_40_24_t max2871_set_frequency(max2871_driver_t* const drv, fp_40_24_t lo, bool program) { uint16_t mhz = lo / FP_ONE_MHZ; int n = mhz / 40; @@ -241,17 +241,19 @@ fp_40_24_t max2871_set_frequency(max2871_driver_t* const drv, fp_40_24_t lo) diva += 1; } - max2871_set_RFA_EN(0); - max2871_write_registers(drv); + if (program) { + max2871_set_RFA_EN(0); + max2871_write_registers(drv); - max2871_set_N(n); - max2871_set_DIVA(diva); - max2871_write_registers(drv); + max2871_set_N(n); + max2871_set_DIVA(diva); + max2871_write_registers(drv); - while (max2871_spi_read(drv) & MAX2871_VASA) {} + while (max2871_spi_read(drv) & MAX2871_VASA) {} - max2871_set_RFA_EN(1); - max2871_write_registers(drv); + max2871_set_RFA_EN(1); + max2871_write_registers(drv); + } return (mhz / 40) * FP_MHZ(40); } diff --git a/firmware/common/max2871.h b/firmware/common/max2871.h index 1b3e1a13..682ee8c0 100644 --- a/firmware/common/max2871.h +++ b/firmware/common/max2871.h @@ -21,6 +21,8 @@ #pragma once +#include + #include "fixed_point.h" #include "gpio.h" @@ -34,6 +36,9 @@ typedef struct { } max2871_driver_t; extern void max2871_setup(max2871_driver_t* const drv); -extern fp_40_24_t max2871_set_frequency(max2871_driver_t* const drv, fp_40_24_t lo); +extern fp_40_24_t max2871_set_frequency( + max2871_driver_t* const drv, + fp_40_24_t lo, + bool program); extern void max2871_enable(max2871_driver_t* const drv); extern void max2871_disable(max2871_driver_t* const drv); diff --git a/firmware/common/mixer.c b/firmware/common/mixer.c index c663c28c..8623ee6b 100644 --- a/firmware/common/mixer.c +++ b/firmware/common/mixer.c @@ -21,6 +21,8 @@ #include "mixer.h" +#include + #include "fixed_point.h" #include "platform_gpio.h" #if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) @@ -85,12 +87,12 @@ void mixer_setup(mixer_driver_t* const mixer) #endif } -fp_40_24_t mixer_set_frequency(mixer_driver_t* const mixer, fp_40_24_t lo) +fp_40_24_t mixer_set_frequency(mixer_driver_t* const mixer, fp_40_24_t lo, bool program) { #if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) - return rffc5071_set_frequency(mixer, lo); + return rffc5071_set_frequency(mixer, lo, program); #elif defined(RAD1O) - return max2871_set_frequency(mixer, lo); + return max2871_set_frequency(mixer, lo, program); #endif } diff --git a/firmware/common/mixer.h b/firmware/common/mixer.h index 9ef3c602..6ba47d75 100644 --- a/firmware/common/mixer.h +++ b/firmware/common/mixer.h @@ -22,6 +22,8 @@ #pragma once +#include + #include "fixed_point.h" #if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) @@ -37,7 +39,10 @@ extern void mixer_bus_setup(mixer_driver_t* const mixer); extern void mixer_setup(mixer_driver_t* const mixer); /* Set frequency (Hz). */ -extern fp_40_24_t mixer_set_frequency(mixer_driver_t* const mixer, fp_40_24_t lo); +extern fp_40_24_t mixer_set_frequency( + mixer_driver_t* const mixer, + fp_40_24_t lo, + bool program); extern void mixer_enable(mixer_driver_t* const mixer); extern void mixer_disable(mixer_driver_t* const mixer); diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index c229d417..c6d12492 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -31,6 +31,7 @@ * that the RFFC5071 includes a second mixer. */ +#include #include #include @@ -154,7 +155,7 @@ void rffc5071_lock_test(rffc5071_driver_t* const drv) for (int i = 0; i < NUM_LOCK_ATTEMPTS; i++) { // Tune to 100MHz. - rffc5071_set_frequency(drv, FP_MHZ(100)); + rffc5071_set_frequency(drv, FP_MHZ(100), true); rffc5071_enable(drv); // Wait 1ms. @@ -263,7 +264,7 @@ void rffc5071_enable(rffc5071_driver_t* const drv) #define MAX_LO FP_MHZ(5400) /* configure frequency synthesizer (lo in 1/(2**24) Hz) */ -fp_40_24_t rffc5071_config_synth(rffc5071_driver_t* const drv, fp_40_24_t lo) +fp_40_24_t rffc5071_config_synth(rffc5071_driver_t* const drv, fp_40_24_t lo, bool program) { fp_40_24_t fvco; uint8_t fbkdivlog; @@ -271,6 +272,7 @@ fp_40_24_t rffc5071_config_synth(rffc5071_driver_t* const drv, fp_40_24_t lo) fp_40_24_t tune_freq; uint16_t p1nmsb; uint8_t p1nlsb; + uint8_t charge_pump_leakage; /* Calculate n_lo (no division) */ uint8_t n_lo = 0; @@ -288,10 +290,10 @@ fp_40_24_t rffc5071_config_synth(rffc5071_driver_t* const drv, fp_40_24_t lo) */ if (fvco > FP_MHZ(3200)) { fbkdivlog = 2; - set_RFFC5071_PLLCPL(drv, 3); + charge_pump_leakage = 3; } else { fbkdivlog = 1; - set_RFFC5071_PLLCPL(drv, 2); + charge_pump_leakage = 2; } uint64_t tmp_n = (fvco / REF_FREQ_HZ) >> fbkdivlog; @@ -302,33 +304,40 @@ fp_40_24_t rffc5071_config_synth(rffc5071_driver_t* const drv, fp_40_24_t lo) const uint8_t d = (24 - fbkdivlog + n_lo) - s; tmp_n = ((tmp_n + (1 << (d - 1))) >> d) << d; - n = tmp_n >> 24ULL; - p1nmsb = (tmp_n >> 8ULL) & 0xffff; - p1nlsb = tmp_n & 0xff; - tune_freq = ((tmp_n * REF_FREQ_HZ) << fbkdivlog) >> n_lo; - /* Path 2 */ - set_RFFC5071_P2LODIV(drv, n_lo); - set_RFFC5071_P2N(drv, n); - set_RFFC5071_P2PRESC(drv, fbkdivlog); - set_RFFC5071_P2NMSB(drv, p1nmsb); - if (s > 14) { - /* Only set when the step size is small enough. */ - set_RFFC5071_P2NLSB(drv, p1nlsb); - } + if (program) { + set_RFFC5071_PLLCPL(drv, charge_pump_leakage); - rffc5071_regs_commit(drv); + n = tmp_n >> 24ULL; + p1nmsb = (tmp_n >> 8ULL) & 0xffff; + p1nlsb = tmp_n & 0xff; + + /* Path 2 */ + set_RFFC5071_P2LODIV(drv, n_lo); + set_RFFC5071_P2N(drv, n); + set_RFFC5071_P2PRESC(drv, fbkdivlog); + set_RFFC5071_P2NMSB(drv, p1nmsb); + if (s > 14) { + /* Only set when the step size is small enough. */ + set_RFFC5071_P2NLSB(drv, p1nlsb); + } + + rffc5071_regs_commit(drv); + } return tune_freq; } -fp_40_24_t rffc5071_set_frequency(rffc5071_driver_t* const drv, fp_40_24_t lo) +fp_40_24_t rffc5071_set_frequency( + rffc5071_driver_t* const drv, + fp_40_24_t lo, + bool program) { fp_40_24_t tune_freq; - tune_freq = rffc5071_config_synth(drv, lo); - if (enabled) { + tune_freq = rffc5071_config_synth(drv, lo, program); + if (enabled && program) { set_RFFC5071_RELOK(drv, 1); rffc5071_regs_commit(drv); } diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index 098f1628..41e0509d 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -61,7 +61,10 @@ extern void rffc5071_reg_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t extern void rffc5071_regs_commit(rffc5071_driver_t* const drv); /* Set frequency in 1/(2**24) Hz. */ -extern fp_40_24_t rffc5071_set_frequency(rffc5071_driver_t* const drv, fp_40_24_t lo); +extern fp_40_24_t rffc5071_set_frequency( + rffc5071_driver_t* const drv, + fp_40_24_t lo, + bool program); extern void rffc5071_enable(rffc5071_driver_t* const drv); extern void rffc5071_disable(rffc5071_driver_t* const drv); diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 000ede9d..3f38fbd4 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -104,14 +104,17 @@ bool set_freq(const uint64_t freq, const transceiver_mode_t opmode) mixer_freq_hz = max2837_freq_nominal_hz + freq; /* Set Freq and read real freq */ real_mixer_freq_hz = - mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ) / + mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ, true) / FP_ONE_HZ; - max283x_set_frequency(&max283x, (real_mixer_freq_hz - freq) * FP_ONE_HZ); + max283x_set_frequency( + &max283x, + (real_mixer_freq_hz - freq) * FP_ONE_HZ, + true); 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, opmode); /* mixer_freq_mhz <= not used in Bypass mode */ - max283x_set_frequency(&max283x, freq * FP_ONE_HZ); + max283x_set_frequency(&max283x, freq * FP_ONE_HZ, true); 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) { @@ -132,9 +135,12 @@ bool set_freq(const uint64_t freq, const transceiver_mode_t opmode) mixer_freq_hz = freq - max2837_freq_nominal_hz; /* Set Freq and read real freq */ real_mixer_freq_hz = - mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ) / + mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ, true) / FP_ONE_HZ; - max283x_set_frequency(&max283x, (freq - real_mixer_freq_hz) * FP_ONE_HZ); + max283x_set_frequency( + &max283x, + (freq - real_mixer_freq_hz) * FP_ONE_HZ, + true); sgpio_cpld_set_mixer_invert(&sgpio_config, 0); } else { /* Error freq_mhz too high */ @@ -185,36 +191,45 @@ bool tuning_set_frequency( if (cfg->if_mhz == 0) { rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS, opmode); - max283x_set_frequency(&max283x, rf * FP_ONE_HZ); + max283x_set_frequency(&max283x, rf * FP_ONE_HZ, true); 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, opmode); if (cfg->high_lo) { mixer_freq_hz = FREQ_ONE_MHZ * cfg->if_mhz + rf; - real_mixer_freq_hz = - mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ) / + real_mixer_freq_hz = mixer_set_frequency( + &mixer, + mixer_freq_hz * FP_ONE_HZ, + true) / FP_ONE_HZ; max283x_set_frequency( &max283x, - (real_mixer_freq_hz - rf) * FP_ONE_HZ); + (real_mixer_freq_hz - rf) * FP_ONE_HZ, + true); sgpio_cpld_set_mixer_invert(&sgpio_config, 1); } else { mixer_freq_hz = FREQ_ONE_MHZ * cfg->if_mhz - rf; - real_mixer_freq_hz = - mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ) / + real_mixer_freq_hz = mixer_set_frequency( + &mixer, + mixer_freq_hz * FP_ONE_HZ, + true) / FP_ONE_HZ; max283x_set_frequency( &max283x, - (real_mixer_freq_hz + rf) * FP_ONE_HZ); + (real_mixer_freq_hz + rf) * FP_ONE_HZ, + true); sgpio_cpld_set_mixer_invert(&sgpio_config, 0); } } else { rf_path_set_filter(&rf_path, RF_PATH_FILTER_HIGH_PASS, opmode); mixer_freq_hz = rf - FREQ_ONE_MHZ * cfg->if_mhz; real_mixer_freq_hz = - mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ) / + mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ, true) / FP_ONE_HZ; - max283x_set_frequency(&max283x, (rf - real_mixer_freq_hz) * FP_ONE_HZ); + max283x_set_frequency( + &max283x, + (rf - real_mixer_freq_hz) * FP_ONE_HZ, + true); sgpio_cpld_set_mixer_invert(&sgpio_config, 0); } @@ -248,7 +263,7 @@ bool set_freq_explicit( } rf_path_set_filter(&rf_path, path, opmode); - max283x_set_frequency(&max283x, if_freq_hz * FP_ONE_HZ); + max283x_set_frequency(&max283x, if_freq_hz * FP_ONE_HZ, true); if (lo_freq_hz > if_freq_hz) { sgpio_cpld_set_mixer_invert(&sgpio_config, 1); @@ -256,7 +271,7 @@ bool set_freq_explicit( sgpio_cpld_set_mixer_invert(&sgpio_config, 0); } if (path != RF_PATH_FILTER_BYPASS) { - (void) mixer_set_frequency(&mixer, lo_freq_hz * FP_ONE_HZ); + (void) mixer_set_frequency(&mixer, lo_freq_hz * FP_ONE_HZ, true); } return true; } From 207ed04f6b0395624933e4e626ea4d3ea1ac2432 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 9 Apr 2026 14:19:09 -0400 Subject: [PATCH 097/238] Restrict tuning frequency in tuning functions --- firmware/common/max2831.c | 7 +++++++ firmware/common/max2837.c | 9 +++++++++ firmware/common/max2839.c | 9 +++++++++ firmware/common/max2871.c | 9 +++++++++ firmware/common/rffc5071.c | 6 ++++++ 5 files changed, 40 insertions(+) diff --git a/firmware/common/max2831.c b/firmware/common/max2831.c index f0afaccc..05d5cb29 100644 --- a/firmware/common/max2831.c +++ b/firmware/common/max2831.c @@ -38,6 +38,7 @@ #include "adc.h" #define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) /* Default register values. */ static const uint16_t max2831_regs_default[MAX2831_NUM_REGS] = { @@ -228,6 +229,9 @@ void max2831_stop(max2831_driver_t* const drv) /* Assume 40 MHz reference clock with R divider of 2. */ #define PFD_FREQ_HZ (20ULL * (1000ULL * 1000ULL)) +#define MIN_FREQ FP_MHZ(2000) +#define MAX_FREQ FP_MHZ(3000) + fp_40_24_t max2831_set_frequency( max2831_driver_t* const drv, fp_40_24_t freq, @@ -235,6 +239,9 @@ fp_40_24_t max2831_set_frequency( { uint64_t div; + freq = MIN(freq, MAX_FREQ); + freq = MAX(freq, MIN_FREQ); + freq += ((PFD_FREQ_HZ * FP_ONE_HZ) >> 21); /* round to nearest frequency */ div = freq / PFD_FREQ_HZ; diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index b5f09239..561a17f9 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -38,6 +38,9 @@ #include "max2837_regs.def" // private register def macros #include "selftest.h" +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + /* Default register values. */ static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = { 0x150, /* 0 */ @@ -234,6 +237,9 @@ void max2837_stop(max2837_driver_t* const drv) /* Assume 40 MHz reference clock with R divider of 1. */ #define PFD_FREQ_HZ (40ULL * (1000ULL * 1000ULL)) +#define MIN_FREQ FP_MHZ(2000) +#define MAX_FREQ FP_MHZ(3000) + fp_40_24_t max2837_set_frequency( max2837_driver_t* const drv, fp_40_24_t freq, @@ -243,6 +249,9 @@ fp_40_24_t max2837_set_frequency( uint8_t lna_band; uint64_t div; + freq = MIN(freq, MAX_FREQ); + freq = MAX(freq, MIN_FREQ); + /* Select band. Allow tuning outside specified bands. */ if (freq < FP_MHZ(2400)) { band = MAX2837_LOGEN_BSW_2_3; diff --git a/firmware/common/max2839.c b/firmware/common/max2839.c index a34c2d75..87917ed8 100644 --- a/firmware/common/max2839.c +++ b/firmware/common/max2839.c @@ -38,6 +38,9 @@ #include "max2839_regs.def" // private register def macros #include "selftest.h" +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + static uint8_t requested_lna_gain = 0; static uint8_t requested_vga_gain = 0; @@ -245,6 +248,9 @@ void max2839_stop(max2839_driver_t* const drv) /* Assume 40 MHz reference clock with R divider of 1. */ #define PFD_FREQ_HZ (40ULL * (1000ULL * 1000ULL)) +#define MIN_FREQ FP_MHZ(2000) +#define MAX_FREQ FP_MHZ(3000) + fp_40_24_t max2839_set_frequency( max2839_driver_t* const drv, fp_40_24_t freq, @@ -253,6 +259,9 @@ fp_40_24_t max2839_set_frequency( uint8_t band; uint64_t div; + freq = MIN(freq, MAX_FREQ); + freq = MAX(freq, MIN_FREQ); + /* Select band. Allow tuning outside specified bands. */ if (freq < FP_MHZ(2400)) { band = MAX2839_LOGEN_BSW_2_3; diff --git a/firmware/common/max2871.c b/firmware/common/max2871.c index e783f80f..4c5a94b2 100644 --- a/firmware/common/max2871.c +++ b/firmware/common/max2871.c @@ -37,6 +37,9 @@ #include #endif +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + static uint32_t max2871_spi_read(max2871_driver_t* const drv); static void max2871_spi_write(max2871_driver_t* const drv, uint8_t r, uint32_t v); static void max2871_write_registers(max2871_driver_t* const drv); @@ -229,9 +232,15 @@ static void max2871_write_registers(max2871_driver_t* const drv) } } +#define MIN_LO FP_MHZ(40) +#define MAX_LO FP_MHZ(6000) + /* Set frequency in 1/(2**24) Hz, rounded to nearest 40 MHz. */ fp_40_24_t max2871_set_frequency(max2871_driver_t* const drv, fp_40_24_t lo, bool program) { + lo = MIN(lo, MAX_LO); + lo = MAX(lo, MIN_LO); + uint16_t mhz = lo / FP_ONE_MHZ; int n = mhz / 40; int diva = 0; diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index c6d12492..ffe958c1 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -48,6 +48,9 @@ #include "platform_scu.h" #endif +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + static bool enabled = false; /* Default register values from vendor documentation or software. */ @@ -274,6 +277,9 @@ fp_40_24_t rffc5071_config_synth(rffc5071_driver_t* const drv, fp_40_24_t lo, bo uint8_t p1nlsb; uint8_t charge_pump_leakage; + lo = MIN(lo, MAX_LO); + lo = MAX(lo, MIN_LO); + /* Calculate n_lo (no division) */ uint8_t n_lo = 0; fp_40_24_t x = MAX_LO >> 1; From 4366b492069ee03a946169ee221f27632fe2a154 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 9 Apr 2026 14:27:27 -0400 Subject: [PATCH 098/238] Refactor radio tuning - Store applied settings in radio registers - Support arbitrary combinations of tuning registers --- firmware/common/radio.c | 388 +++++++++++++++++++++++++++++---------- firmware/common/tuning.c | 282 ++++++---------------------- firmware/common/tuning.h | 36 ++-- 3 files changed, 356 insertions(+), 350 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index d8d3a918..7f274c05 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -28,15 +28,20 @@ #include "fixed_point.h" #include "hackrf_core.h" #include "hackrf_ui.h" +#include "mixer.h" #include "max283x.h" #include "platform_detect.h" #include "rf_path.h" +#include "sgpio.h" #include "transceiver_mode.h" #include "tuning.h" #if defined(PRALINE) #include "fpga.h" #include "tune_config.h" #endif +#if defined(HACKRF_ONE) || defined(PRALINE) + #include "operacake.h" +#endif #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define MAX(x, y) ((x) > (y) ? (x) : (y)) @@ -240,139 +245,316 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) return (new_afe_rate || new_rate || new_n); } -#define DEFAULT_RF FP_MHZ(2450) - -static fp_28_36_t applied_offset = RADIO_UNSET; - -#ifdef PRALINE -static const tune_config_t* select_tune_config(uint64_t opmode) +/* + * Compute frequency offset in 1/(2**24) Hz for a given rotation. This is an + * unsigned value that does not indicate direction of frequency shift. + */ +static fp_40_24_t compute_offset(radio_t* const radio, uint64_t opmode, uint64_t rotation) { + uint64_t n; + fp_40_24_t offset = 0; + const fp_28_36_t mcu_rate = radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE]; + switch (opmode) { case TRANSCEIVER_MODE_TX: case TRANSCEIVER_MODE_SS: - return praline_tune_config_tx; - case TRANSCEIVER_MODE_RX_SWEEP: - return praline_tune_config_rx_sweep; + n = radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX]; + break; default: - return praline_tune_config_rx; + n = radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX]; } + if ((rotation != 0) && (rotation != RADIO_UNSET) && (mcu_rate != RADIO_UNSET) && + (n != RADIO_UNSET)) { + const fp_40_24_t afe_rate = mcu_rate >> (12 - n); + if (rotation & 0x80) { + rotation = 0x100 - rotation; + } + offset = (afe_rate * rotation) >> 8; + } + return offset; +} + +/* + * Convert center frequency of analog baseband (as seen by ADC/DAC) to center + * frequency of digital baseband (as seen by MCU). + */ +static fp_40_24_t digital_from_analog_rf( + radio_t* const radio, + const fp_40_24_t arf, + uint64_t opmode, + uint64_t rotation) +{ + fp_40_24_t offset = compute_offset(radio, opmode, rotation); + fp_40_24_t drf = arf; + if (rotation > 0x80) { + if (offset > arf) { + drf = offset - arf; + } else { + drf = arf - offset; + } + } else if ((rotation & 0x7f) > 0x00) { + drf = arf + offset; + } + return drf; +} + +#ifdef PRALINE +/* + * Convert center frequency of digital baseband (as seen by MCU) to center + * frequency of analog baseband (as seen by ADC/DAC). + */ +static fp_40_24_t analog_from_digital_rf( + radio_t* const radio, + const fp_40_24_t drf, + uint64_t opmode, + uint64_t rotation) +{ + fp_40_24_t offset = compute_offset(radio, opmode, rotation); + fp_40_24_t arf = drf; + if (rotation > 0x80) { + arf = drf + offset; + } else if ((rotation & 0x7f) > 0x00) { + if (offset > drf) { + arf = offset - drf; + } else { + arf = drf - offset; + } + } + return arf; +} + +static const tune_config_t* select_tune_config(uint64_t opmode, fp_40_24_t freq_rf) +{ + const tune_config_t* tune_config; + + switch (opmode) { + case TRANSCEIVER_MODE_TX: + case TRANSCEIVER_MODE_SS: + tune_config = praline_tune_config_tx; + break; + case TRANSCEIVER_MODE_RX_SWEEP: + tune_config = praline_tune_config_rx_sweep; + break; + default: + tune_config = praline_tune_config_rx; + } + while ((tune_config->rf_range_end_mhz != 0) || (tune_config->if_mhz != 0)) { + if ((freq_rf == 0) || + (tune_config->rf_range_end_mhz > (freq_rf / FP_ONE_MHZ))) { + break; + } + tune_config++; + } + return tune_config; } #endif static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) { - uint8_t rotation = 0; - uint64_t requested_rf = bank[RADIO_FREQUENCY_RF]; + bool new_freq = false; + bool high_lo = false; + bool invert_spectrum = false; + + const uint64_t requested_rf = bank[RADIO_FREQUENCY_RF]; const uint64_t requested_if = bank[RADIO_FREQUENCY_IF]; const uint64_t requested_lo = bank[RADIO_FREQUENCY_LO]; const uint64_t requested_img_reject = bank[RADIO_IMAGE_REJECT]; + const uint64_t requested_rotation = bank[RADIO_ROTATION]; - bool set_if = (requested_if != RADIO_UNSET); - bool set_lo = (requested_lo != RADIO_UNSET); - bool set_img_reject = (requested_img_reject != RADIO_UNSET); + const uint64_t applied_rf = radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF]; + const uint64_t applied_if = radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF]; + const uint64_t applied_lo = radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_LO]; + const uint64_t applied_img_reject = + radio->config[RADIO_BANK_APPLIED][RADIO_IMAGE_REJECT]; + const uint64_t applied_rotation = + radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION]; + + uint64_t freq_rf = applied_rf; + uint64_t analog_rf = applied_rf; + uint64_t freq_if = applied_if; + uint64_t freq_lo = applied_lo; + uint64_t img_reject = applied_img_reject; + uint64_t rotation = applied_rotation; uint64_t opmode = bank[RADIO_OPMODE]; if (opmode == RADIO_UNSET) { opmode = radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]; } - if (set_if && set_lo && set_img_reject) { - bool new_if = - (requested_if != - radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF]); - bool new_lo = - (requested_lo != - radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_LO]); - bool new_img_reject = - (requested_img_reject != - radio->config[RADIO_BANK_APPLIED][RADIO_IMAGE_REJECT]); - if (new_if || new_lo || new_img_reject) { - set_freq_explicit( - requested_if / FP_ONE_HZ, - requested_lo / FP_ONE_HZ, - requested_img_reject, - opmode); - radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF] = - requested_if; - radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_LO] = - requested_lo; - radio->config[RADIO_BANK_APPLIED][RADIO_IMAGE_REJECT] = - requested_img_reject; - radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF] = - RADIO_UNSET; + /* Restrict requested settings to valid ranges. */ + if (requested_img_reject != RADIO_UNSET) { + switch (requested_img_reject) { + case RF_PATH_FILTER_LOW_PASS: + case RF_PATH_FILTER_HIGH_PASS: + img_reject = requested_img_reject; + break; + default: + img_reject = RF_PATH_FILTER_BYPASS; } -#ifdef PRALINE - const uint64_t requested_rotation = bank[RADIO_ROTATION]; + } + if (requested_if != RADIO_UNSET) { + freq_if = max283x_set_frequency(&max283x, requested_if, false); + } + if (requested_lo != RADIO_UNSET) { + freq_lo = mixer_set_frequency(&mixer, freq_lo, false); + } + if (detected_platform() == BOARD_ID_PRALINE) { if (requested_rotation != RADIO_UNSET) { rotation = requested_rotation; - } else if (radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION] != RADIO_UNSET) { - return true; } + switch (opmode) { + case TRANSCEIVER_MODE_RX: + case TRANSCEIVER_MODE_RX_SWEEP: + /* Round to nearest supported rotation. */ + rotation = (rotation + 0x20) & 0xc0; + if (rotation == 0x80) { + rotation = 0; + } + break; + default: + rotation = 0; + } + } else { + rotation = 0; + } + + /* Handle requested RF (auto-tune). */ + if (requested_rf != RADIO_UNSET) { + if (requested_img_reject == RADIO_UNSET) { + img_reject = select_img_reject(requested_rf); + } + freq_rf = restrict_rf(requested_rf, img_reject); + + /* Look up settings appropriate for requested RF. */ + if (detected_platform() == BOARD_ID_PRALINE) { +#ifdef PRALINE + const tune_config_t* tune_config = + select_tune_config(opmode, freq_rf); + if (requested_rotation == RADIO_UNSET) { + rotation = (uint8_t) (tune_config->shift) << 6; + } + analog_rf = + analog_from_digital_rf(radio, freq_rf, opmode, rotation); + if (requested_if == RADIO_UNSET) { + if (tune_config->if_mhz == 0) { + freq_if = analog_rf; + } else { + freq_if = tune_config->if_mhz * FP_ONE_MHZ; + } + } + high_lo = tune_config->high_lo; +#endif + } else { + /* Use graduated or fixed IF on older platforms. */ + if (requested_if == RADIO_UNSET) { + freq_if = select_graduated_if(freq_rf, img_reject); + } + high_lo = (img_reject == RF_PATH_FILTER_LOW_PASS); + analog_rf = freq_rf; + } + + /* Compute precise LO. This is done first because the mixer LO is set in coarse steps. */ + if (requested_lo == RADIO_UNSET) { + switch (img_reject) { + case RF_PATH_FILTER_LOW_PASS: + if (high_lo) { + freq_lo = freq_if + analog_rf; + } else { + freq_lo = freq_if - analog_rf; + } + break; + case RF_PATH_FILTER_HIGH_PASS: + freq_lo = analog_rf - freq_if; + break; + default: + freq_lo = RADIO_UNSET; + } + if (freq_lo != RADIO_UNSET) { + freq_lo = mixer_set_frequency(&mixer, freq_lo, false); + } + } + + /* Recompute IF, compensating for rounding of mixer LO. */ + if (requested_if == RADIO_UNSET) { + switch (img_reject) { + case RF_PATH_FILTER_LOW_PASS: + if (high_lo) { + freq_if = freq_lo - analog_rf; + } else { + freq_if = freq_lo + analog_rf; + } + break; + case RF_PATH_FILTER_HIGH_PASS: + freq_if = analog_rf - freq_lo; + } + } + } + + /* Apply settings. */ + if ((freq_if != applied_if) && (freq_if != RADIO_UNSET)) { + freq_if = max283x_set_frequency(&max283x, freq_if, true); + radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF] = freq_if; + new_freq = true; + } + if ((freq_lo != applied_lo) && (freq_lo != RADIO_UNSET)) { + freq_lo = mixer_set_frequency(&mixer, freq_lo, true); + radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_LO] = freq_lo; + new_freq = true; + } + if ((img_reject != applied_img_reject) && (img_reject != RADIO_UNSET)) { + rf_path_set_filter(&rf_path, img_reject, opmode); + radio->config[RADIO_BANK_APPLIED][RADIO_IMAGE_REJECT] = img_reject; + new_freq = true; + } + if ((rotation != applied_rotation) && (rotation != RADIO_UNSET)) { +#ifdef PRALINE fpga_set_rx_quarter_shift_mode(&fpga, rotation >> 6); #endif radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION] = rotation; - return true; + new_freq = true; } - if (requested_rf == RADIO_UNSET) { - if (radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF] == - RADIO_UNSET) { - requested_rf = DEFAULT_RF; - } else { - return false; - } - } - - bool new_rf = - (radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF] != requested_rf); - uint64_t requested_rf_hz = requested_rf / FP_ONE_HZ; -#ifdef PRALINE - if (applied_afe_rate == RADIO_UNSET) { - return false; - } - const tune_config_t* tune_config = select_tune_config(opmode); - const tune_config_t* applied_tune_config = - select_tune_config(radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]); - bool new_config = (applied_tune_config != tune_config); - while ((tune_config->rf_range_end_mhz != 0) || (tune_config->if_mhz != 0)) { - if ((requested_rf_hz == 0) || - (tune_config->rf_range_end_mhz > (requested_rf_hz / FREQ_ONE_MHZ))) { + /* Compute precise RF. */ + if ((img_reject != RADIO_UNSET) && (freq_if != RADIO_UNSET) && + (rotation != RADIO_UNSET) && + ((freq_lo != RADIO_UNSET) || (img_reject == RF_PATH_FILTER_BYPASS))) { + switch (img_reject) { + case RF_PATH_FILTER_LOW_PASS: + if (freq_lo > freq_if) { + analog_rf = freq_lo - freq_if; + invert_spectrum = true; + } else { + analog_rf = freq_if - freq_lo; + } break; + case RF_PATH_FILTER_HIGH_PASS: + analog_rf = freq_if + freq_lo; + break; + default: + analog_rf = freq_if; } - tune_config++; + freq_rf = digital_from_analog_rf(radio, analog_rf, opmode, rotation); } - bool new_rotation = - (radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION] != - ((uint64_t) tune_config->shift << 6)); - if (new_rotation) { - fpga_set_rx_quarter_shift_mode(&fpga, tune_config->shift); - radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION] = - tune_config->shift << 6; - } - fp_28_36_t offset = applied_afe_rate / 4; - bool new_offset = (applied_offset != offset); - if (new_rotation || new_offset || new_config || new_rf) { - tuning_set_frequency( - tune_config, - requested_rf_hz, - offset / SR_FP_ONE_HZ, - opmode); - applied_offset = offset; - } -#else - if (new_rf) { - set_freq(requested_rf_hz, opmode); + if ((freq_rf != applied_rf) && (freq_rf != RADIO_UNSET)) { + radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF] = freq_rf; + new_freq = true; } + + if (new_freq) { + sgpio_cpld_set_mixer_invert(&sgpio_config, invert_spectrum); + if (opmode != TRANSCEIVER_MODE_RX_SWEEP) { + hackrf_ui()->set_frequency(freq_rf / FP_ONE_MHZ); + } +#if defined(PRALINE) || defined(HACKRF_ONE) + operacake_set_range(freq_rf / FP_ONE_MHZ); #endif - radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF] = requested_rf; - radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF] = RADIO_UNSET; - radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_LO] = RADIO_UNSET; - radio->config[RADIO_BANK_APPLIED][RADIO_IMAGE_REJECT] = RADIO_UNSET; - return true; + } + return new_freq; } -static uint32_t auto_bandwidth(radio_t* const radio) +static uint32_t auto_bandwidth(radio_t* const radio, uint64_t opmode) { + uint32_t offset_hz = 0; uint64_t rotation = radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION]; uint32_t sample_rate_hz = DEFAULT_MCU_RATE / SR_FP_ONE_HZ; @@ -381,11 +563,8 @@ static uint32_t auto_bandwidth(radio_t* const radio) SR_FP_ONE_HZ; } - uint32_t offset_hz = 0; - if ((rotation != 0) && (rotation != RADIO_UNSET) && - (applied_offset != RADIO_UNSET)) { - offset_hz = applied_offset / SR_FP_ONE_HZ; - } + const fp_40_24_t offset = compute_offset(radio, opmode, rotation); + offset_hz = offset >> 24; const uint32_t bb_bandwidth = (sample_rate_hz * 3) / 4; const uint32_t lpf_bandwidth = bb_bandwidth + offset_hz * 2; @@ -400,10 +579,15 @@ static bool radio_update_bandwidth(radio_t* const radio, uint64_t* bank) { bool new_bw = false; + uint64_t opmode = bank[RADIO_OPMODE]; + if (opmode == RADIO_UNSET) { + opmode = radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]; + } + #ifdef PRALINE /* Praline legacy mode always sets baseband bandwidth automatically. */ (void) bank; - uint32_t lpf_bandwidth = auto_bandwidth(radio); + uint32_t lpf_bandwidth = auto_bandwidth(radio, opmode); if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != lpf_bandwidth) { max283x_set_lpf_bandwidth(&max283x, MAX283x_MODE_TX, lpf_bandwidth); @@ -450,7 +634,7 @@ static bool radio_update_bandwidth(radio_t* const radio, uint64_t* bank) lpf_bandwidth = radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF]; } if (lpf_bandwidth == RADIO_UNSET) { - lpf_bandwidth = auto_bandwidth(radio); + lpf_bandwidth = auto_bandwidth(radio, opmode); } if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != lpf_bandwidth) { diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 3f38fbd4..7fe48bf0 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -24,254 +24,84 @@ #include "tuning.h" #include "fixed_point.h" -#include "hackrf_core.h" -#include "hackrf_ui.h" -#include "max283x.h" -#include "mixer.h" -#include "sgpio.h" -#include "transceiver_mode.h" -#if defined(PRALINE) || defined(HACKRF_ONE) - #include "operacake.h" -#endif +#include "platform_detect.h" + +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + #ifdef PRALINE - #include "fpga.h" -#endif - -#ifndef PRALINE - - #define MIN_LP_FREQ_MHZ (0) - #define MAX_LP_FREQ_MHZ (2170ULL) - - #define ABS_MIN_BYPASS_FREQ_MHZ (2000ULL) - #define MIN_BYPASS_FREQ_MHZ (MAX_LP_FREQ_MHZ) - #define MAX_BYPASS_FREQ_MHZ (2740ULL) - #define ABS_MAX_BYPASS_FREQ_MHZ (3000ULL) - - #define MIN_HP_FREQ_MHZ (MAX_BYPASS_FREQ_MHZ) - #define MID1_HP_FREQ_MHZ (3600ULL) - #define MID2_HP_FREQ_MHZ (5100ULL) - #define MAX_HP_FREQ_MHZ (7250ULL) - - #define MIN_LO_FREQ_HZ (84375000ULL) - #define MAX_LO_FREQ_HZ (5400000000ULL) - + #define MIN_BYPASS_FREQ FP_MHZ(2320) + #define MAX_BYPASS_FREQ FP_MHZ(2580) #else - - #define MIN_LP_FREQ_MHZ (0) - #define MAX_LP_FREQ_MHZ (2320ULL) - - #define ABS_MIN_BYPASS_FREQ_MHZ (2000ULL) - #define MIN_BYPASS_FREQ_MHZ (MAX_LP_FREQ_MHZ) - #define MAX_BYPASS_FREQ_MHZ (2580ULL) - #define ABS_MAX_BYPASS_FREQ_MHZ (3000ULL) - - #define MIN_HP_FREQ_MHZ (MAX_BYPASS_FREQ_MHZ) - #define MAX_HP_FREQ_MHZ (7250ULL) - - #define MIN_LO_FREQ_HZ (84375000ULL) - #define MAX_LO_FREQ_HZ (5400000000ULL) - + #define MIN_BYPASS_FREQ FP_MHZ(2170) + #define MAX_BYPASS_FREQ FP_MHZ(2740) #endif -#ifndef PRALINE -static uint32_t max2837_freq_nominal_hz = 2560000000; +#define MID1_HP_FREQ FP_MHZ(3600) +#define MID2_HP_FREQ FP_MHZ(5100) +#define MAX_HP_FREQ FP_MHZ(7250) -/* - * 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. - */ -bool set_freq(const uint64_t freq, const transceiver_mode_t opmode) +fp_40_24_t select_graduated_if(fp_40_24_t freq_rf, rf_path_filter_t img_reject) { - bool success; - uint64_t mixer_freq_hz; - uint64_t real_mixer_freq_hz; + fp_40_24_t freq_if; - const uint32_t freq_mhz = freq / FREQ_ONE_MHZ; - - success = true; - - max283x_mode_t prior_max283x_mode = max283x_mode(&max283x); - max283x_set_mode(&max283x, MAX283x_MODE_STANDBY); - if (freq_mhz < MAX_LP_FREQ_MHZ) { - rf_path_set_filter(&rf_path, RF_PATH_FILTER_LOW_PASS, opmode); - #ifdef RAD1O - max2837_freq_nominal_hz = 2300 * FREQ_ONE_MHZ; - #else - /* IF is graduated from 2650 MHz to 2340 MHz */ - max2837_freq_nominal_hz = (2650 * FREQ_ONE_MHZ) - (freq / 7); - #endif - mixer_freq_hz = max2837_freq_nominal_hz + freq; - /* Set Freq and read real freq */ - real_mixer_freq_hz = - mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ, true) / - FP_ONE_HZ; - max283x_set_frequency( - &max283x, - (real_mixer_freq_hz - freq) * FP_ONE_HZ, - true); - 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, opmode); - /* mixer_freq_mhz <= not used in Bypass mode */ - max283x_set_frequency(&max283x, freq * FP_ONE_HZ, true); - 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) { + switch (img_reject) { + case RF_PATH_FILTER_LOW_PASS: + if (detected_platform() == BOARD_ID_RAD1O) { + freq_if = FP_MHZ(2300); + } else { + /* IF is graduated from 2650 MHz to 2340 MHz */ + freq_if = FP_MHZ(2650) - (freq_rf / 7); + } + break; + case RF_PATH_FILTER_HIGH_PASS: + if (freq_rf < (MID1_HP_FREQ)) { /* IF is graduated from 2170 MHz to 2740 MHz */ - max2837_freq_nominal_hz = (MIN_BYPASS_FREQ_MHZ * FREQ_ONE_MHZ) + - (((freq - (MAX_BYPASS_FREQ_MHZ * FREQ_ONE_MHZ)) * 57) / - 86); - } else if (freq_mhz < MID2_HP_FREQ_MHZ) { + freq_if = (MIN_BYPASS_FREQ) + + (((freq_rf - (MAX_BYPASS_FREQ)) * 57) / 86); + } else if (freq_rf < (MID2_HP_FREQ)) { /* IF is graduated from 2350 MHz to 2650 MHz */ - max2837_freq_nominal_hz = (2350 * FREQ_ONE_MHZ) + - ((freq - (MID1_HP_FREQ_MHZ * FREQ_ONE_MHZ)) / 5); + freq_if = FP_MHZ(2350) + ((freq_rf - (MID1_HP_FREQ)) / 5); } else { /* IF is graduated from 2500 MHz to 2738 MHz */ - max2837_freq_nominal_hz = (2500 * FREQ_ONE_MHZ) + - ((freq - (MID2_HP_FREQ_MHZ * FREQ_ONE_MHZ)) / 9); + freq_if = FP_MHZ(2500) + ((freq_rf - (MID2_HP_FREQ)) / 9); } - rf_path_set_filter(&rf_path, RF_PATH_FILTER_HIGH_PASS, opmode); - mixer_freq_hz = freq - max2837_freq_nominal_hz; - /* Set Freq and read real freq */ - real_mixer_freq_hz = - mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ, true) / - FP_ONE_HZ; - max283x_set_frequency( - &max283x, - (freq - real_mixer_freq_hz) * FP_ONE_HZ, - true); - sgpio_cpld_set_mixer_invert(&sgpio_config, 0); - } else { - /* Error freq_mhz too high */ - success = false; + break; + default: + freq_if = freq_rf; } - max283x_set_mode(&max283x, prior_max283x_mode); - if (success) { - if (opmode != TRANSCEIVER_MODE_RX_SWEEP) { - hackrf_ui()->set_frequency(freq); - } - #ifdef HACKRF_ONE - operacake_set_range(freq_mhz); - #endif - } - return success; + return freq_if; } -#else - -bool tuning_set_frequency( - const tune_config_t* cfg, - const uint64_t freq, - const uint32_t offset, - const transceiver_mode_t opmode) +rf_path_filter_t select_img_reject(fp_40_24_t freq_rf) { - uint64_t mixer_freq_hz; - uint64_t real_mixer_freq_hz; - - if (freq > (MAX_HP_FREQ_MHZ * FREQ_ONE_MHZ)) { - return false; - } - - 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; - } - - max283x_mode_t prior_max283x_mode = max283x_mode(&max283x); - max283x_set_mode(&max283x, MAX283x_MODE_STANDBY); - - if (cfg->if_mhz == 0) { - rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS, opmode); - max283x_set_frequency(&max283x, rf * FP_ONE_HZ, true); - 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, opmode); - if (cfg->high_lo) { - mixer_freq_hz = FREQ_ONE_MHZ * cfg->if_mhz + rf; - real_mixer_freq_hz = mixer_set_frequency( - &mixer, - mixer_freq_hz * FP_ONE_HZ, - true) / - FP_ONE_HZ; - max283x_set_frequency( - &max283x, - (real_mixer_freq_hz - rf) * FP_ONE_HZ, - true); - sgpio_cpld_set_mixer_invert(&sgpio_config, 1); - } else { - mixer_freq_hz = FREQ_ONE_MHZ * cfg->if_mhz - rf; - real_mixer_freq_hz = mixer_set_frequency( - &mixer, - mixer_freq_hz * FP_ONE_HZ, - true) / - FP_ONE_HZ; - max283x_set_frequency( - &max283x, - (real_mixer_freq_hz + rf) * FP_ONE_HZ, - true); - sgpio_cpld_set_mixer_invert(&sgpio_config, 0); - } + if (freq_rf > (MAX_BYPASS_FREQ)) { + return RF_PATH_FILTER_HIGH_PASS; + } else if (freq_rf >= (MIN_BYPASS_FREQ)) { + return RF_PATH_FILTER_BYPASS; } else { - rf_path_set_filter(&rf_path, RF_PATH_FILTER_HIGH_PASS, opmode); - mixer_freq_hz = rf - FREQ_ONE_MHZ * cfg->if_mhz; - real_mixer_freq_hz = - mixer_set_frequency(&mixer, mixer_freq_hz * FP_ONE_HZ, true) / - FP_ONE_HZ; - max283x_set_frequency( - &max283x, - (rf - real_mixer_freq_hz) * FP_ONE_HZ, - true); - sgpio_cpld_set_mixer_invert(&sgpio_config, 0); + return RF_PATH_FILTER_LOW_PASS; } - - max283x_set_mode(&max283x, prior_max283x_mode); - if (opmode != TRANSCEIVER_MODE_RX_SWEEP) { - hackrf_ui()->set_frequency(freq); - } - operacake_set_range(freq_mhz); - return true; } -#endif -bool set_freq_explicit( - const uint64_t if_freq_hz, - const uint64_t lo_freq_hz, - const rf_path_filter_t path, - const transceiver_mode_t opmode) +fp_40_24_t restrict_rf(fp_40_24_t freq_rf, rf_path_filter_t img_reject) { - if ((if_freq_hz < ((uint64_t) ABS_MIN_BYPASS_FREQ_MHZ * FREQ_ONE_MHZ)) || - (if_freq_hz > ((uint64_t) ABS_MAX_BYPASS_FREQ_MHZ * FREQ_ONE_MHZ))) { - return false; - } + fp_40_24_t min_rf = 0; + fp_40_24_t max_rf = MAX_HP_FREQ; - if ((path != RF_PATH_FILTER_BYPASS) && - ((lo_freq_hz < MIN_LO_FREQ_HZ) || (lo_freq_hz > MAX_LO_FREQ_HZ))) { - return false; + switch (img_reject) { + case RF_PATH_FILTER_LOW_PASS: + max_rf = MIN_BYPASS_FREQ; + break; + case RF_PATH_FILTER_HIGH_PASS: + min_rf = MAX_BYPASS_FREQ; + break; + default: + min_rf = MIN_BYPASS_FREQ; + max_rf = MAX_BYPASS_FREQ; } + freq_rf = MIN(freq_rf, max_rf); + freq_rf = MAX(freq_rf, min_rf); - if (path > 2) { - return false; - } - - rf_path_set_filter(&rf_path, path, opmode); - max283x_set_frequency(&max283x, if_freq_hz * FP_ONE_HZ, true); - - if (lo_freq_hz > if_freq_hz) { - sgpio_cpld_set_mixer_invert(&sgpio_config, 1); - } else { - sgpio_cpld_set_mixer_invert(&sgpio_config, 0); - } - if (path != RF_PATH_FILTER_BYPASS) { - (void) mixer_set_frequency(&mixer, lo_freq_hz * FP_ONE_HZ, true); - } - return true; + return freq_rf; } diff --git a/firmware/common/tuning.h b/firmware/common/tuning.h index 1c4681db..a338cd28 100644 --- a/firmware/common/tuning.h +++ b/firmware/common/tuning.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Jared Boone * Copyright 2013 Benjamin Vernoux * @@ -23,28 +23,20 @@ #pragma once -#include -#include - +#include "fixed_point.h" #include "rf_path.h" -#include "transceiver_mode.h" -#if defined(PRALINE) - #include "tune_config.h" -#endif -#define FREQ_ONE_MHZ (1000ULL * 1000) +/** + * Select fixed or graduated IF for a given RF and image reject filter. + */ +fp_40_24_t select_graduated_if(fp_40_24_t freq_rf, rf_path_filter_t img_reject); -bool set_freq(const uint64_t freq, const transceiver_mode_t opmode); -bool set_freq_explicit( - const uint64_t if_freq_hz, - const uint64_t lo_freq_hz, - const rf_path_filter_t path, - const transceiver_mode_t opmode); +/** + * Select image reject filter appropriate for a given RF. + */ +rf_path_filter_t select_img_reject(fp_40_24_t freq_rf); -#ifdef PRALINE -bool tuning_set_frequency( - const tune_config_t* cfg, - const uint64_t freq, - const uint32_t offset, - const transceiver_mode_t opmode); -#endif +/** + * Restrict RF to range appropriate for a given image reject filter. + */ +fp_40_24_t restrict_rf(fp_40_24_t freq_rf, rf_path_filter_t img_reject); From 5a82627a2b6735d4b5d6e7a202955937987b8c79 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 9 Apr 2026 14:30:11 -0400 Subject: [PATCH 099/238] Clean up static applied_afe_rate --- firmware/common/radio.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 7f274c05..a551c0ec 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -160,11 +160,9 @@ static inline uint8_t compute_resample_log( #define MAX_MCU_RATE SR_FP_KHZ(21800) #define DEFAULT_MCU_RATE SR_FP_KHZ(10000) -static fp_28_36_t applied_afe_rate = RADIO_UNSET; - static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) { - fp_28_36_t rate, afe_rate; + fp_28_36_t rate, afe_rate, previous_rate, previous_afe_rate; uint64_t previous_n; uint8_t n = 0; bool new_afe_rate = false; @@ -222,16 +220,21 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) if (radio->sample_rate_cb) { afe_rate = rate << n; afe_rate = radio->sample_rate_cb(afe_rate, false); - new_afe_rate = (afe_rate != applied_afe_rate); + previous_rate = radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE]; + if ((previous_n == RADIO_UNSET) || previous_rate == RADIO_UNSET) { + previous_afe_rate = RADIO_UNSET; + } else { + previous_afe_rate = previous_rate << previous_n; + } + new_afe_rate = (afe_rate != previous_afe_rate); if (new_afe_rate) { afe_rate = radio->sample_rate_cb(afe_rate, true); - applied_afe_rate = afe_rate; } } else { return false; } rate = afe_rate >> n; - new_rate = (rate != radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE]); + new_rate = (rate != previous_rate); if (new_rate) { radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] = rate; if (rate != RADIO_UNSET) { From 3d616df7622e71161ac57ecaa69da22c9c269858 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 9 Apr 2026 14:31:10 -0400 Subject: [PATCH 100/238] Store rotation in 32-bit format --- firmware/common/radio.c | 22 +++++++++++----------- firmware/common/radio.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index a551c0ec..0692274c 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -269,10 +269,10 @@ static fp_40_24_t compute_offset(radio_t* const radio, uint64_t opmode, uint64_t if ((rotation != 0) && (rotation != RADIO_UNSET) && (mcu_rate != RADIO_UNSET) && (n != RADIO_UNSET)) { const fp_40_24_t afe_rate = mcu_rate >> (12 - n); - if (rotation & 0x80) { - rotation = 0x100 - rotation; + if (rotation & 0x80000000) { + rotation = 0x100000000 - rotation; } - offset = (afe_rate * rotation) >> 8; + offset = (afe_rate * (rotation >> 24)) >> 8; } return offset; } @@ -289,13 +289,13 @@ static fp_40_24_t digital_from_analog_rf( { fp_40_24_t offset = compute_offset(radio, opmode, rotation); fp_40_24_t drf = arf; - if (rotation > 0x80) { + if (rotation > 0x80000000) { if (offset > arf) { drf = offset - arf; } else { drf = arf - offset; } - } else if ((rotation & 0x7f) > 0x00) { + } else if ((rotation & 0x7fffffff) > 0) { drf = arf + offset; } return drf; @@ -314,9 +314,9 @@ static fp_40_24_t analog_from_digital_rf( { fp_40_24_t offset = compute_offset(radio, opmode, rotation); fp_40_24_t arf = drf; - if (rotation > 0x80) { + if (rotation > 0x80000000) { arf = drf + offset; - } else if ((rotation & 0x7f) > 0x00) { + } else if ((rotation & 0x7fffffff) > 0) { if (offset > drf) { arf = offset - drf; } else { @@ -409,8 +409,8 @@ static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) case TRANSCEIVER_MODE_RX: case TRANSCEIVER_MODE_RX_SWEEP: /* Round to nearest supported rotation. */ - rotation = (rotation + 0x20) & 0xc0; - if (rotation == 0x80) { + rotation = (rotation + 0x20000000) & 0xc0000000; + if (rotation == 0x80000000) { rotation = 0; } break; @@ -434,7 +434,7 @@ static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) const tune_config_t* tune_config = select_tune_config(opmode, freq_rf); if (requested_rotation == RADIO_UNSET) { - rotation = (uint8_t) (tune_config->shift) << 6; + rotation = (uint64_t) (tune_config->shift) << 30; } analog_rf = analog_from_digital_rf(radio, freq_rf, opmode, rotation); @@ -511,7 +511,7 @@ static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) } if ((rotation != applied_rotation) && (rotation != RADIO_UNSET)) { #ifdef PRALINE - fpga_set_rx_quarter_shift_mode(&fpga, rotation >> 6); + fpga_set_rx_quarter_shift_mode(&fpga, rotation >> 30); #endif radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION] = rotation; new_freq = true; diff --git a/firmware/common/radio.h b/firmware/common/radio.h index 2744dd4b..a0e40730 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -91,7 +91,7 @@ typedef enum { */ RADIO_IMAGE_REJECT = 4, /** - * Digital frequency conversion of type uint8_t in tau/256 steps with + * Digital frequency conversion of type uint8_t in tau/(2**32) steps with * respect to AFE clock. */ RADIO_ROTATION = 5, From 1e69ee09b72c7c3077f94694cb48d62b1311e178 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 14 Apr 2026 12:25:52 +0100 Subject: [PATCH 101/238] Remove some superfluous parentheses. --- firmware/common/tuning.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 7fe48bf0..f613ab30 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -55,11 +55,11 @@ fp_40_24_t select_graduated_if(fp_40_24_t freq_rf, rf_path_filter_t img_reject) } break; case RF_PATH_FILTER_HIGH_PASS: - if (freq_rf < (MID1_HP_FREQ)) { + if (freq_rf < MID1_HP_FREQ) { /* IF is graduated from 2170 MHz to 2740 MHz */ - freq_if = (MIN_BYPASS_FREQ) + + freq_if = MIN_BYPASS_FREQ + (((freq_rf - (MAX_BYPASS_FREQ)) * 57) / 86); - } else if (freq_rf < (MID2_HP_FREQ)) { + } else if (freq_rf < MID2_HP_FREQ) { /* IF is graduated from 2350 MHz to 2650 MHz */ freq_if = FP_MHZ(2350) + ((freq_rf - (MID1_HP_FREQ)) / 5); } else { @@ -75,9 +75,9 @@ fp_40_24_t select_graduated_if(fp_40_24_t freq_rf, rf_path_filter_t img_reject) rf_path_filter_t select_img_reject(fp_40_24_t freq_rf) { - if (freq_rf > (MAX_BYPASS_FREQ)) { + if (freq_rf > MAX_BYPASS_FREQ) { return RF_PATH_FILTER_HIGH_PASS; - } else if (freq_rf >= (MIN_BYPASS_FREQ)) { + } else if (freq_rf >= MIN_BYPASS_FREQ) { return RF_PATH_FILTER_BYPASS; } else { return RF_PATH_FILTER_LOW_PASS; From 59e8670c51f91a1779e730a23e447bc0dffcec6e Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 9 Apr 2026 15:41:12 -0400 Subject: [PATCH 102/238] Ensure correct gains displayed in PortaPack UI Previously it was possible, though rare, for an update of an RX gain setting to be displayed during TX mode or for an update of a TX gain setting to be displayed during RX mode. --- firmware/common/ui_portapack.c | 111 +++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 48 deletions(-) diff --git a/firmware/common/ui_portapack.c b/firmware/common/ui_portapack.c index 4e862ca4..8912777f 100644 --- a/firmware/common/ui_portapack.c +++ b/firmware/common/ui_portapack.c @@ -495,6 +495,9 @@ static void portapack_radio_path_item_update( static rf_path_direction_t portapack_direction = RF_PATH_DIRECTION_OFF; static bool portapack_lna_on = false; +static uint32_t tx_if_gain = 0; +static uint32_t rx_if_gain = 0; +static uint32_t rx_bb_gain = 0; static void portapack_radio_path_redraw(void) { @@ -569,51 +572,6 @@ static void portapack_ui_set_sample_rate(uint32_t sample_rate) #endif } -static void portapack_ui_set_direction(const rf_path_direction_t direction) -{ - switch (direction) { - case RF_PATH_DIRECTION_TX: - portapack_radio_path_item_update( - RADIO_DRAW_LIST_ITEM_WAVES, - &bitmap_waves_tx); - portapack_radio_path_item_update( - RADIO_DRAW_LIST_ITEM_RF_AMP, - portapack_lna_on ? &bitmap_amp_tx : &bitmap_wire_24); - portapack_radio_path_item_update( - RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, - &bitmap_amp_tx); - portapack_radio_path_item_update( - RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, - &bitmap_wire_24); - portapack_ui_draw_string(RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, " "); - break; - - case RF_PATH_DIRECTION_RX: - portapack_radio_path_item_update( - RADIO_DRAW_LIST_ITEM_WAVES, - &bitmap_waves_rx); - portapack_radio_path_item_update( - RADIO_DRAW_LIST_ITEM_RF_AMP, - portapack_lna_on ? &bitmap_amp_rx : &bitmap_wire_24); - portapack_radio_path_item_update( - RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, - &bitmap_amp_rx); - portapack_radio_path_item_update( - RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, - &bitmap_amp_rx); - break; - - case RF_PATH_DIRECTION_OFF: - default: - portapack_radio_path_item_update( - RADIO_DRAW_LIST_ITEM_WAVES, - &bitmap_blank_24); - break; - } - - portapack_direction = direction; -} - static void portapack_ui_set_filter_bw(uint32_t bandwidth) { portapack_ui_draw_bw_mhz(RADIO_DRAW_LIST_ITEM_BB_FILTER, bandwidth); @@ -634,12 +592,18 @@ static void portapack_ui_set_lna_power(bool lna_on) static void portapack_ui_set_bb_lna_gain(const uint32_t gain_db) { - portapack_ui_draw_db(RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, gain_db); + rx_if_gain = gain_db; + if (portapack_direction == RF_PATH_DIRECTION_RX) { + portapack_ui_draw_db(RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, gain_db); + } } static void portapack_ui_set_bb_vga_gain(const uint32_t gain_db) { - portapack_ui_draw_db(RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, gain_db); + rx_bb_gain = gain_db; + if (portapack_direction == RF_PATH_DIRECTION_RX) { + portapack_ui_draw_db(RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, gain_db); + } } static void portapack_ui_set_bb_tx_vga_gain(const uint32_t gain_db) @@ -648,7 +612,10 @@ static void portapack_ui_set_bb_tx_vga_gain(const uint32_t gain_db) * According to the MAX2837 datasheet diagram, there is no baseband gain in the TX path. * This gets called when the TX IF gain is changed. */ - portapack_ui_draw_db(RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, gain_db); + tx_if_gain = gain_db; + if (portapack_direction == RF_PATH_DIRECTION_TX) { + portapack_ui_draw_db(RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, gain_db); + } } static void portapack_ui_set_first_if_frequency(const uint64_t frequency) @@ -724,6 +691,54 @@ static bool portapack_ui_operacake_gpio_compatible(void) return false; } +static void portapack_ui_set_direction(const rf_path_direction_t direction) +{ + portapack_direction = direction; + + switch (direction) { + case RF_PATH_DIRECTION_TX: + portapack_radio_path_item_update( + RADIO_DRAW_LIST_ITEM_WAVES, + &bitmap_waves_tx); + portapack_radio_path_item_update( + RADIO_DRAW_LIST_ITEM_RF_AMP, + portapack_lna_on ? &bitmap_amp_tx : &bitmap_wire_24); + portapack_radio_path_item_update( + RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, + &bitmap_amp_tx); + portapack_radio_path_item_update( + RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, + &bitmap_wire_24); + portapack_ui_draw_string(RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, " "); + portapack_ui_set_bb_tx_vga_gain(tx_if_gain); + break; + + case RF_PATH_DIRECTION_RX: + portapack_radio_path_item_update( + RADIO_DRAW_LIST_ITEM_WAVES, + &bitmap_waves_rx); + portapack_radio_path_item_update( + RADIO_DRAW_LIST_ITEM_RF_AMP, + portapack_lna_on ? &bitmap_amp_rx : &bitmap_wire_24); + portapack_radio_path_item_update( + RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, + &bitmap_amp_rx); + portapack_radio_path_item_update( + RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, + &bitmap_amp_rx); + portapack_ui_set_bb_vga_gain(rx_bb_gain); + portapack_ui_set_bb_lna_gain(rx_if_gain); + break; + + case RF_PATH_DIRECTION_OFF: + default: + portapack_radio_path_item_update( + RADIO_DRAW_LIST_ITEM_WAVES, + &bitmap_blank_24); + break; + } +} + const hackrf_ui_t portapack_hackrf_ui = { &portapack_ui_init, &portapack_ui_deinit, From 57285507d1c34e64b6e975bdd3a8a4f71d60d001 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 9 Apr 2026 18:44:18 -0400 Subject: [PATCH 103/238] Add radio configuration update callback Co-authored-by: Martin Ling --- firmware/common/radio.c | 208 +++++++++------------- firmware/common/radio.h | 22 +++ firmware/common/rf_path.c | 17 +- firmware/common/rf_path.h | 6 +- firmware/hackrf_usb/hackrf_usb.c | 122 +++++++++++++ firmware/hackrf_usb/usb_api_transceiver.c | 8 - 6 files changed, 233 insertions(+), 150 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 0692274c..ac150ca1 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -27,21 +27,16 @@ #include "fixed_point.h" #include "hackrf_core.h" -#include "hackrf_ui.h" #include "mixer.h" #include "max283x.h" #include "platform_detect.h" #include "rf_path.h" -#include "sgpio.h" #include "transceiver_mode.h" #include "tuning.h" #if defined(PRALINE) #include "fpga.h" #include "tune_config.h" #endif -#if defined(HACKRF_ONE) || defined(PRALINE) - #include "operacake.h" -#endif #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define MAX(x, y) ((x) > (y) ? (x) : (y)) @@ -106,12 +101,12 @@ uint64_t radio_reg_read( return radio->config[bank][reg]; } -static bool radio_update_direction(radio_t* const radio, uint64_t* bank) +static uint32_t radio_update_direction(radio_t* const radio, uint64_t* bank) { const uint64_t requested = bank[RADIO_OPMODE]; if (requested == RADIO_UNSET) { - return false; + return 0; } rf_path_direction_t direction; @@ -129,7 +124,7 @@ static bool radio_update_direction(radio_t* const radio, uint64_t* bank) } radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE] = requested; rf_path_set_direction(&rf_path, direction); - return true; + return (1 << RADIO_OPMODE); } #define MAX_AFE_RATE_HZ (40000000UL) @@ -160,7 +155,7 @@ static inline uint8_t compute_resample_log( #define MAX_MCU_RATE SR_FP_KHZ(21800) #define DEFAULT_MCU_RATE SR_FP_KHZ(10000) -static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) +static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank) { fp_28_36_t rate, afe_rate, previous_rate, previous_afe_rate; uint64_t previous_n; @@ -231,21 +226,15 @@ static bool radio_update_sample_rate(radio_t* const radio, uint64_t* bank) afe_rate = radio->sample_rate_cb(afe_rate, true); } } else { - return false; + return 0; } rate = afe_rate >> n; new_rate = (rate != previous_rate); if (new_rate) { radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE] = rate; - if (rate != RADIO_UNSET) { - /* Round to the nearest Hz for display. */ - const uint32_t rate_hz = - (rate + (SR_FP_ONE_HZ >> 1)) / SR_FP_ONE_HZ; - hackrf_ui()->set_sample_rate(rate_hz); - } } - return (new_afe_rate || new_rate || new_n); + return ((new_afe_rate || new_rate || new_n) << RADIO_SAMPLE_RATE); } /* @@ -352,11 +341,10 @@ static const tune_config_t* select_tune_config(uint64_t opmode, fp_40_24_t freq_ } #endif -static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) +static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) { - bool new_freq = false; + uint32_t changed = 0; bool high_lo = false; - bool invert_spectrum = false; const uint64_t requested_rf = bank[RADIO_FREQUENCY_RF]; const uint64_t requested_if = bank[RADIO_FREQUENCY_IF]; @@ -497,24 +485,24 @@ static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) if ((freq_if != applied_if) && (freq_if != RADIO_UNSET)) { freq_if = max283x_set_frequency(&max283x, freq_if, true); radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF] = freq_if; - new_freq = true; + changed |= (1 << RADIO_FREQUENCY_IF); } if ((freq_lo != applied_lo) && (freq_lo != RADIO_UNSET)) { freq_lo = mixer_set_frequency(&mixer, freq_lo, true); radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_LO] = freq_lo; - new_freq = true; + changed |= (1 << RADIO_FREQUENCY_LO); } if ((img_reject != applied_img_reject) && (img_reject != RADIO_UNSET)) { - rf_path_set_filter(&rf_path, img_reject, opmode); + rf_path_set_filter(&rf_path, img_reject); radio->config[RADIO_BANK_APPLIED][RADIO_IMAGE_REJECT] = img_reject; - new_freq = true; + changed |= (1 << RADIO_IMAGE_REJECT); } if ((rotation != applied_rotation) && (rotation != RADIO_UNSET)) { #ifdef PRALINE fpga_set_rx_quarter_shift_mode(&fpga, rotation >> 30); #endif radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION] = rotation; - new_freq = true; + changed |= (1 << RADIO_ROTATION); } /* Compute precise RF. */ @@ -525,7 +513,6 @@ static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) case RF_PATH_FILTER_LOW_PASS: if (freq_lo > freq_if) { analog_rf = freq_lo - freq_if; - invert_spectrum = true; } else { analog_rf = freq_if - freq_lo; } @@ -540,19 +527,10 @@ static bool radio_update_frequency(radio_t* const radio, uint64_t* bank) } if ((freq_rf != applied_rf) && (freq_rf != RADIO_UNSET)) { radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF] = freq_rf; - new_freq = true; + changed |= (1 << RADIO_FREQUENCY_RF); } - if (new_freq) { - sgpio_cpld_set_mixer_invert(&sgpio_config, invert_spectrum); - if (opmode != TRANSCEIVER_MODE_RX_SWEEP) { - hackrf_ui()->set_frequency(freq_rf / FP_ONE_MHZ); - } -#if defined(PRALINE) || defined(HACKRF_ONE) - operacake_set_range(freq_rf / FP_ONE_MHZ); -#endif - } - return new_freq; + return changed; } static uint32_t auto_bandwidth(radio_t* const radio, uint64_t opmode) @@ -578,9 +556,9 @@ static uint32_t auto_bandwidth(radio_t* const radio, uint64_t opmode) return lpf_bandwidth; } -static bool radio_update_bandwidth(radio_t* const radio, uint64_t* bank) +static uint32_t radio_update_bandwidth(radio_t* const radio, uint64_t* bank) { - bool new_bw = false; + uint32_t changed = 0; uint64_t opmode = bank[RADIO_OPMODE]; if (opmode == RADIO_UNSET) { @@ -595,12 +573,12 @@ static bool radio_update_bandwidth(radio_t* const radio, uint64_t* bank) if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != lpf_bandwidth) { max283x_set_lpf_bandwidth(&max283x, MAX283x_MODE_TX, lpf_bandwidth); radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = lpf_bandwidth; - new_bw = true; + changed |= (1 << RADIO_XCVR_TX_LPF); } if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] != lpf_bandwidth) { max283x_set_lpf_bandwidth(&max283x, MAX283x_MODE_RX, lpf_bandwidth); radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] = lpf_bandwidth; - new_bw = true; + changed |= (1 << RADIO_XCVR_RX_LPF); } bool narrow_lpf_enable = false; bool applied_narrow_lpf_enable = @@ -612,14 +590,14 @@ static bool radio_update_bandwidth(radio_t* const radio, uint64_t* bank) narrowband_filter_set(narrow_lpf_enable); radio->config[RADIO_BANK_APPLIED][RADIO_RX_NARROW_LPF] = narrow_lpf_enable; - new_bw = true; + changed |= (1 << RADIO_RX_NARROW_LPF); } /* Always set HPF bandwidth to 30 kHz for now. */ const max283x_rx_hpf_freq_t hpf_bandwidth = MAX283x_RX_HPF_30_KHZ; if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] != hpf_bandwidth) { max283x_set_rx_hpf_frequency(&max283x, hpf_bandwidth); radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] = hpf_bandwidth; - new_bw = true; + changed |= (1 << RADIO_XCVR_RX_HPF); } #else uint64_t lpf_bandwidth; @@ -646,20 +624,22 @@ static bool radio_update_bandwidth(radio_t* const radio, uint64_t* bank) radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_TX] = lpf_bandwidth; radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = lpf_bandwidth; radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] = lpf_bandwidth; - new_bw = true; + changed |= + ((1 << RADIO_BB_BANDWIDTH_RX) | (1 << RADIO_BB_BANDWIDTH_TX) | + (1 << RADIO_XCVR_TX_LPF) | (1 << RADIO_XCVR_RX_LPF)); } #endif - return new_bw; + return changed; } #define DEFAULT_GAIN_RF (0) #define DEFAULT_GAIN_IF (16) #define DEFAULT_GAIN_BB (12) -static bool radio_update_gain(radio_t* const radio, uint64_t* bank) +static uint32_t radio_update_gain(radio_t* const radio, uint64_t* bank) { - bool new_gain = false; - uint64_t gain; + uint32_t changed = 0; + uint64_t gain, tx_rf_gain, rx_rf_gain; uint64_t opmode = bank[RADIO_OPMODE]; if (opmode == RADIO_UNSET) { opmode = radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]; @@ -673,34 +653,34 @@ static bool radio_update_gain(radio_t* const radio, uint64_t* bank) switch (opmode) { case TRANSCEIVER_MODE_TX: case TRANSCEIVER_MODE_SS: - gain = bank[RADIO_GAIN_TX_RF]; - if (gain == RADIO_UNSET) { - gain = DEFAULT_GAIN_RF; + tx_rf_gain = bank[RADIO_GAIN_TX_RF]; + if (tx_rf_gain == RADIO_UNSET) { + tx_rf_gain = DEFAULT_GAIN_RF; } - rf_path_set_lna(&rf_path, gain); - if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_RF] != gain) { - new_gain = true; - } - radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_RF] = gain; - radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_RF] = 0; + rf_path_set_lna(&rf_path, tx_rf_gain); + rx_rf_gain = 0; break; case TRANSCEIVER_MODE_RX: case TRANSCEIVER_MODE_RX_SWEEP: - gain = bank[RADIO_GAIN_RX_RF]; - if (gain == RADIO_UNSET) { - gain = DEFAULT_GAIN_RF; + rx_rf_gain = bank[RADIO_GAIN_RX_RF]; + if (rx_rf_gain == RADIO_UNSET) { + rx_rf_gain = DEFAULT_GAIN_RF; } - rf_path_set_lna(&rf_path, gain); - if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_RF] != gain) { - new_gain = true; - } - radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_RF] = gain; - radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_RF] = 0; + rf_path_set_lna(&rf_path, rx_rf_gain); + tx_rf_gain = 0; break; default: rf_path_set_lna(&rf_path, 0); - radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_RF] = 0; - radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_RF] = 0; + tx_rf_gain = 0; + rx_rf_gain = 0; + } + if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_RF] != tx_rf_gain) { + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_RF] = tx_rf_gain; + changed |= (1 << RADIO_GAIN_TX_RF); + } + if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_RF] != rx_rf_gain) { + radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_RF] = rx_rf_gain; + changed |= (1 << RADIO_GAIN_RX_RF); } gain = bank[RADIO_GAIN_TX_IF]; @@ -708,11 +688,11 @@ static bool radio_update_gain(radio_t* const radio, uint64_t* bank) (gain != radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF])) { max283x_set_txvga_gain(&max283x, gain); radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] = gain; - new_gain = true; + changed |= (1 << RADIO_GAIN_TX_IF); } else if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] == RADIO_UNSET) { max283x_set_txvga_gain(&max283x, DEFAULT_GAIN_IF); radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_TX_IF] = DEFAULT_GAIN_IF; - new_gain = true; + changed |= (1 << RADIO_GAIN_TX_IF); } gain = bank[RADIO_GAIN_RX_IF]; @@ -720,11 +700,11 @@ static bool radio_update_gain(radio_t* const radio, uint64_t* bank) (gain != radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_IF])) { max283x_set_lna_gain(&max283x, gain); radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_IF] = gain; - new_gain = true; + changed |= (1 << RADIO_GAIN_RX_IF); } else if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_IF] == RADIO_UNSET) { max283x_set_lna_gain(&max283x, DEFAULT_GAIN_IF); radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_IF] = DEFAULT_GAIN_IF; - new_gain = true; + changed |= (1 << RADIO_GAIN_RX_IF); } gain = bank[RADIO_GAIN_RX_BB]; @@ -732,39 +712,39 @@ static bool radio_update_gain(radio_t* const radio, uint64_t* bank) (gain != radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_BB])) { max283x_set_vga_gain(&max283x, gain); radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_BB] = gain; - new_gain = true; + changed |= (1 << RADIO_GAIN_RX_BB); } else if (radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_BB] == RADIO_UNSET) { max283x_set_vga_gain(&max283x, DEFAULT_GAIN_BB); radio->config[RADIO_BANK_APPLIED][RADIO_GAIN_RX_BB] = DEFAULT_GAIN_BB; - new_gain = true; + changed |= (1 << RADIO_GAIN_RX_BB); } - return new_gain; + return changed; } -static bool radio_update_bias_tee(radio_t* const radio, uint64_t* bank) +static uint32_t radio_update_bias_tee(radio_t* const radio, uint64_t* bank) { if (detected_platform() == BOARD_ID_JAWBREAKER) { - return false; + return 0; } const uint64_t requested = bank[RADIO_BIAS_TEE]; const bool enable = requested; if (requested == RADIO_UNSET) { - return false; + return 0; } if (radio->config[RADIO_BANK_APPLIED][RADIO_BIAS_TEE] == (uint64_t) enable) { - return false; + return 0; } rf_path_set_antenna(&rf_path, enable); radio->config[RADIO_BANK_APPLIED][RADIO_BIAS_TEE] = enable; - return true; + return (1 << RADIO_BIAS_TEE); } -static bool radio_update_trigger(radio_t* const radio, uint64_t* bank) +static uint32_t radio_update_trigger(radio_t* const radio, uint64_t* bank) { const uint64_t requested = bank[RADIO_TRIGGER]; bool enable = requested; @@ -774,20 +754,20 @@ static bool radio_update_trigger(radio_t* const radio, uint64_t* bank) } if (radio->config[RADIO_BANK_APPLIED][RADIO_TRIGGER] == (uint64_t) enable) { - return false; + return 0; } trigger_enable(enable); radio->config[RADIO_BANK_APPLIED][RADIO_TRIGGER] = enable; - return true; + return (1 << RADIO_TRIGGER); } -static bool radio_update_dc_block(radio_t* const radio, uint64_t* bank) +static uint32_t radio_update_dc_block(radio_t* const radio, uint64_t* bank) { #ifndef PRALINE (void) radio; (void) bank; - return false; + return 0; #else const uint64_t requested = bank[RADIO_DC_BLOCK]; bool enable = requested; @@ -797,12 +777,12 @@ static bool radio_update_dc_block(radio_t* const radio, uint64_t* bank) } if (radio->config[RADIO_BANK_APPLIED][RADIO_DC_BLOCK] == (uint64_t) enable) { - return false; + return 0; } fpga_set_rx_dc_block_enable(&fpga, enable); radio->config[RADIO_BANK_APPLIED][RADIO_DC_BLOCK] = enable; - return true; + return (1 << RADIO_DC_BLOCK); #endif } @@ -811,6 +791,7 @@ bool radio_update(radio_t* const radio) uint64_t tmp_bank[RADIO_NUM_REGS]; nvic_disable_irq(NVIC_USB0_IRQ); uint32_t dirty = radio->regs_dirty; + uint32_t changed = 0; if (dirty == 0) { nvic_enable_irq(NVIC_USB0_IRQ); return false; @@ -819,56 +800,41 @@ bool radio_update(radio_t* const radio) memcpy(&tmp_bank[0], &(radio->config[RADIO_BANK_ACTIVE][0]), sizeof(tmp_bank)); nvic_enable_irq(NVIC_USB0_IRQ); - bool dir = false; - bool rate = false; - bool freq = false; - bool bw = false; - bool gain = false; - bool bias = false; - bool trig = false; - bool dc = false; - - if ((dirty & - ((1 << RADIO_SAMPLE_RATE) | (1 << RADIO_RESAMPLE_TX) | - (1 << RADIO_RESAMPLE_RX))) || + if ((dirty & RADIO_REG_GROUP_RATE) || ((detected_platform() == BOARD_ID_PRALINE) && (dirty & (1 << RADIO_OPMODE)))) { - rate = radio_update_sample_rate(radio, &tmp_bank[0]); + changed |= radio_update_sample_rate(radio, &tmp_bank[0]); } - if ((dirty & - ((1 << RADIO_FREQUENCY_RF) | (1 << RADIO_FREQUENCY_IF) | - (1 << RADIO_FREQUENCY_LO) | (1 << RADIO_IMAGE_REJECT) | - (1 << RADIO_ROTATION))) || + if ((dirty & RADIO_REG_GROUP_FREQ) || ((detected_platform() == BOARD_ID_PRALINE) && - (rate || (dirty & (1 << RADIO_OPMODE))))) { - freq = radio_update_frequency(radio, &tmp_bank[0]); + ((changed & RADIO_REG_GROUP_RATE) || (dirty & (1 << RADIO_OPMODE))))) { + changed |= radio_update_frequency(radio, &tmp_bank[0]); } - if ((dirty & - ((1 << RADIO_BB_BANDWIDTH_TX) | (1 << RADIO_BB_BANDWIDTH_RX) | - (1 << RADIO_XCVR_TX_LPF) | (1 << RADIO_XCVR_RX_LPF) | - (1 << RADIO_XCVR_RX_HPF) | (1 << RADIO_RX_NARROW_LPF))) || - ((detected_platform() == BOARD_ID_PRALINE) && (rate || freq))) { - bw = radio_update_bandwidth(radio, &tmp_bank[0]); + if ((dirty & RADIO_REG_GROUP_BW) || + ((detected_platform() == BOARD_ID_PRALINE) && + (changed & (RADIO_REG_GROUP_RATE | RADIO_REG_GROUP_FREQ)))) { + changed |= radio_update_bandwidth(radio, &tmp_bank[0]); } - if (dirty & - ((1 << RADIO_GAIN_TX_RF) | (1 << RADIO_GAIN_TX_IF) | (1 << RADIO_GAIN_RX_RF) | - (1 << RADIO_GAIN_RX_IF) | (1 << RADIO_GAIN_RX_BB) | (1 << RADIO_OPMODE))) { - gain = radio_update_gain(radio, &tmp_bank[0]); + if (dirty & (RADIO_REG_GROUP_GAIN | (1 << RADIO_OPMODE))) { + changed |= radio_update_gain(radio, &tmp_bank[0]); } if (dirty & ((1 << RADIO_BIAS_TEE) | (1 << RADIO_OPMODE))) { - bias = radio_update_bias_tee(radio, &tmp_bank[0]); + changed |= radio_update_bias_tee(radio, &tmp_bank[0]); } if (dirty & (1 << RADIO_TRIGGER)) { - trig = radio_update_trigger(radio, &tmp_bank[0]); + changed |= radio_update_trigger(radio, &tmp_bank[0]); } if (dirty & (1 << RADIO_DC_BLOCK)) { - dc = radio_update_dc_block(radio, &tmp_bank[0]); + changed |= radio_update_dc_block(radio, &tmp_bank[0]); } if (dirty & (1 << RADIO_OPMODE)) { - dir = radio_update_direction(radio, &tmp_bank[0]); + changed |= radio_update_direction(radio, &tmp_bank[0]); } - return trig || dir || rate || freq || bw || gain || bias || dc; + if (radio->update_cb) { + radio->update_cb(changed); + } + return (changed != 0); } void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode) diff --git a/firmware/common/radio.h b/firmware/common/radio.h index a0e40730..83f72441 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -177,6 +177,20 @@ typedef enum { #define RADIO_NUM_REGS (23) #define RADIO_UNSET (0xffffffffffffffff) +/* register groups for bitfield convenience */ +#define RADIO_REG_GROUP_RATE \ + ((1 << RADIO_SAMPLE_RATE) | (1 << RADIO_RESAMPLE_TX) | (1 << RADIO_RESAMPLE_RX)) +#define RADIO_REG_GROUP_FREQ \ + ((1 << RADIO_FREQUENCY_RF) | (1 << RADIO_FREQUENCY_IF) | \ + (1 << RADIO_FREQUENCY_LO) | (1 << RADIO_IMAGE_REJECT) | (1 << RADIO_ROTATION)) +#define RADIO_REG_GROUP_BW \ + ((1 << RADIO_BB_BANDWIDTH_TX) | (1 << RADIO_BB_BANDWIDTH_RX) | \ + (1 << RADIO_XCVR_TX_LPF) | (1 << RADIO_XCVR_RX_LPF) | \ + (1 << RADIO_XCVR_RX_HPF) | (1 << RADIO_RX_NARROW_LPF)) +#define RADIO_REG_GROUP_GAIN \ + ((1 << RADIO_GAIN_TX_RF) | (1 << RADIO_GAIN_TX_IF) | (1 << RADIO_GAIN_RX_RF) | \ + (1 << RADIO_GAIN_RX_IF) | (1 << RADIO_GAIN_RX_BB)) + /** * Register bank RADIO_BANK_ACTIVE stores the active configuration. Active * register settings are copied to the applied register when applied. @@ -207,11 +221,19 @@ typedef enum { */ typedef fp_28_36_t (*sample_rate_fn)(const fp_28_36_t sample_rate, const bool program); +/** + * An optional callback may be provided that is called after each time the + * radio configuration has been updated. The single argument is a bitfield + * indicating registers that have been changed. + */ +typedef void (*update_fn)(const uint32_t changed_regs); + typedef struct { radio_config_mode_t config_mode; uint64_t config[RADIO_NUM_BANKS][RADIO_NUM_REGS]; volatile uint32_t regs_dirty; sample_rate_fn sample_rate_cb; + update_fn update_cb; } radio_t; void radio_init(radio_t* const radio); diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index cf77f70c..9fdb20de 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -28,13 +28,11 @@ #endif #include "hackrf_core.h" -#include "hackrf_ui.h" #include "max283x.h" #include "max5864.h" #include "mixer.h" #include "platform_detect.h" #include "sgpio.h" -#include "transceiver_mode.h" #if defined(HACKRF_ONE) || defined(RAD1O) || defined(PRALINE) #include "platform_scu.h" #endif @@ -534,14 +532,9 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d } switchctrl_set(rf_path, rf_path->switchctrl); - - hackrf_ui()->set_direction(direction); } -void rf_path_set_filter( - rf_path_t* const rf_path, - const rf_path_filter_t filter, - const transceiver_mode_t opmode) +void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter) { switch (filter) { default: @@ -563,10 +556,6 @@ void rf_path_set_filter( } switchctrl_set(rf_path, rf_path->switchctrl); - - if (opmode != TRANSCEIVER_MODE_RX_SWEEP) { - hackrf_ui()->set_filter(filter); - } } void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable) @@ -590,8 +579,6 @@ void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable) } switchctrl_set(rf_path, rf_path->switchctrl); - - hackrf_ui()->set_lna_power(enable); } /* antenna port power control */ @@ -604,6 +591,4 @@ void rf_path_set_antenna(rf_path_t* const rf_path, const uint_fast8_t enable) } switchctrl_set(rf_path, rf_path->switchctrl); - - hackrf_ui()->set_antenna_bias(enable); } diff --git a/firmware/common/rf_path.h b/firmware/common/rf_path.h index d9f45a30..1ac0e243 100644 --- a/firmware/common/rf_path.h +++ b/firmware/common/rf_path.h @@ -25,7 +25,6 @@ #include -#include "transceiver_mode.h" #if defined(HACKRF_ONE) || defined(RAD1O) || defined(PRALINE) #include "gpio.h" #endif @@ -92,10 +91,7 @@ void rf_path_init(rf_path_t* const rf_path); void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t direction); -void rf_path_set_filter( - rf_path_t* const rf_path, - const rf_path_filter_t filter, - const transceiver_mode_t opmode); +void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter); void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable); void rf_path_set_antenna(rf_path_t* const rf_path, const uint_fast8_t enable); diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index ee8f897d..8a165e19 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -300,6 +302,125 @@ struct fpga_loader_t fpga_loader = { }; #endif +void radio_changed(const uint32_t changed) +{ + const uint64_t opmode = radio_reg_read(&radio, RADIO_BANK_APPLIED, RADIO_OPMODE); + + if (changed & (1 << RADIO_OPMODE)) { + switch (opmode) { + case TRANSCEIVER_MODE_TX: + case TRANSCEIVER_MODE_SS: + hackrf_ui()->set_direction(RF_PATH_DIRECTION_TX); + break; + case TRANSCEIVER_MODE_RX: + case TRANSCEIVER_MODE_RX_SWEEP: + hackrf_ui()->set_direction(RF_PATH_DIRECTION_RX); + break; + default: + hackrf_ui()->set_direction(RF_PATH_DIRECTION_OFF); + break; + } + } + if (changed & (1 << RADIO_SAMPLE_RATE)) { + const uint64_t rate = + radio_reg_read(&radio, RADIO_BANK_APPLIED, RADIO_SAMPLE_RATE); + hackrf_ui()->set_sample_rate(rate / SR_FP_ONE_HZ); + } + if (changed & (RADIO_REG_GROUP_FREQ)) { + const uint64_t img_reject = + radio_reg_read(&radio, RADIO_BANK_APPLIED, RADIO_IMAGE_REJECT); + const uint64_t freq_lo = + radio_reg_read(&radio, RADIO_BANK_APPLIED, RADIO_FREQUENCY_LO); + const uint64_t freq_if = + radio_reg_read(&radio, RADIO_BANK_APPLIED, RADIO_FREQUENCY_IF); + const bool invert_spectrum = + ((img_reject == RF_PATH_FILTER_LOW_PASS) && (freq_lo > freq_if)); + sgpio_cpld_set_mixer_invert(&sgpio_config, invert_spectrum); + } + if (changed & (1 << RADIO_FREQUENCY_RF)) { + const uint64_t freq = + radio_reg_read(&radio, RADIO_BANK_APPLIED, RADIO_FREQUENCY_RF); + if (opmode != TRANSCEIVER_MODE_RX_SWEEP) { + hackrf_ui()->set_frequency(freq / FP_ONE_HZ); + } +#if defined(HACKRF_ONE) || defined(PRALINE) + operacake_set_range(freq / FP_ONE_MHZ); +#endif + } + if (changed & (1 << RADIO_IMAGE_REJECT)) { + if (opmode != TRANSCEIVER_MODE_RX_SWEEP) { + const uint64_t img_reject = radio_reg_read( + &radio, + RADIO_BANK_APPLIED, + RADIO_IMAGE_REJECT); + hackrf_ui()->set_filter(img_reject); + } + } + if (changed & + ((1 << RADIO_BB_BANDWIDTH_TX) | (1 << RADIO_BB_BANDWIDTH_RX) | + (1 << RADIO_OPMODE))) { + uint64_t bw; + + switch (opmode) { + case TRANSCEIVER_MODE_TX: + case TRANSCEIVER_MODE_SS: + bw = radio_reg_read( + &radio, + RADIO_BANK_APPLIED, + RADIO_BB_BANDWIDTH_TX); + break; + default: + bw = radio_reg_read( + &radio, + RADIO_BANK_APPLIED, + RADIO_BB_BANDWIDTH_RX); + } + hackrf_ui()->set_filter_bw(bw); + } + if (changed & + ((1 << RADIO_GAIN_TX_RF) | (1 << RADIO_GAIN_RX_RF) | (1 << RADIO_OPMODE))) { + const uint64_t tx_rf = + radio_reg_read(&radio, RADIO_BANK_APPLIED, RADIO_GAIN_TX_RF); + const uint64_t rx_rf = + radio_reg_read(&radio, RADIO_BANK_APPLIED, RADIO_GAIN_RX_RF); + bool enable; + + switch (opmode) { + case TRANSCEIVER_MODE_TX: + case TRANSCEIVER_MODE_SS: + enable = tx_rf; + break; + case TRANSCEIVER_MODE_RX: + case TRANSCEIVER_MODE_RX_SWEEP: + enable = rx_rf; + break; + default: + enable = false; + } + hackrf_ui()->set_lna_power(enable); + } + if (changed & (1 << RADIO_GAIN_TX_IF)) { + const uint64_t tx_if = + radio_reg_read(&radio, RADIO_BANK_APPLIED, RADIO_GAIN_TX_IF); + hackrf_ui()->set_bb_tx_vga_gain(tx_if); + } + if (changed & (1 << RADIO_GAIN_RX_IF)) { + const uint64_t rx_if = + radio_reg_read(&radio, RADIO_BANK_APPLIED, RADIO_GAIN_RX_IF); + hackrf_ui()->set_bb_lna_gain(rx_if); + } + if (changed & (1 << RADIO_GAIN_RX_BB)) { + const uint64_t rx_bb = + radio_reg_read(&radio, RADIO_BANK_APPLIED, RADIO_GAIN_RX_BB); + hackrf_ui()->set_bb_vga_gain(rx_bb); + } + if (changed & (1 << RADIO_BIAS_TEE)) { + const uint64_t enable = + radio_reg_read(&radio, RADIO_BANK_APPLIED, RADIO_BIAS_TEE); + hackrf_ui()->set_antenna_bias(enable); + } +} + int main(void) { // Copy M0 image from ROM before SPIFI is disabled @@ -369,6 +490,7 @@ int main(void) fpga_spi_selftest(); fpga_sgpio_selftest(); #endif + radio.update_cb = radio_changed; radio_init(&radio); #if (defined HACKRF_ONE || defined PRALINE) diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index d4b47f9f..12c516c9 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -28,7 +28,6 @@ #include #include -#include #include #include #include @@ -83,7 +82,6 @@ usb_request_status_t usb_vendor_request_set_baseband_filter_bandwidth( RADIO_BANK_ACTIVE, RADIO_BB_BANDWIDTH_RX, bandwidth); - hackrf_ui()->set_filter_bw(bandwidth); usb_transfer_schedule_ack(endpoint->in); } return USB_REQUEST_STATUS_OK; @@ -231,7 +229,6 @@ usb_request_status_t usb_vendor_request_set_lna_gain( uint8_t gain = endpoint->setup.index; radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_GAIN_RX_IF, gain); endpoint->buffer[0] = RADIO_OK; - hackrf_ui()->set_bb_lna_gain(gain); usb_transfer_schedule_block( endpoint->in, &endpoint->buffer, @@ -251,7 +248,6 @@ usb_request_status_t usb_vendor_request_set_vga_gain( uint8_t gain = endpoint->setup.index; radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_GAIN_RX_BB, gain); endpoint->buffer[0] = RADIO_OK; - hackrf_ui()->set_bb_vga_gain(gain); usb_transfer_schedule_block( endpoint->in, &endpoint->buffer, @@ -271,7 +267,6 @@ usb_request_status_t usb_vendor_request_set_txvga_gain( uint8_t gain = endpoint->setup.index; radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_GAIN_TX_IF, gain); endpoint->buffer[0] = RADIO_OK; - hackrf_ui()->set_bb_tx_vga_gain(gain); usb_transfer_schedule_block( endpoint->in, &endpoint->buffer, @@ -333,7 +328,6 @@ void transceiver_shutdown(void) void transceiver_startup(const transceiver_mode_t mode) { radio_switch_opmode(&radio, mode); - hackrf_ui()->set_transceiver_mode(mode); switch (mode) { case TRANSCEIVER_MODE_RX_SWEEP: @@ -486,8 +480,6 @@ void tx_mode(uint32_t seq) void off_mode(uint32_t seq) { - hackrf_ui()->set_transceiver_mode(TRANSCEIVER_MODE_OFF); - while (transceiver_request.seq == seq) { radio_update(&radio); } From 43454dd512c5582cce2629341a3259c0291642dc Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 12 Mar 2026 02:02:59 +0000 Subject: [PATCH 104/238] Move sgpio_configure calls to radio_changed callback. --- firmware/common/rf_path.c | 5 ----- firmware/hackrf_usb/hackrf_usb.c | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 9fdb20de..4407960a 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -32,7 +32,6 @@ #include "max5864.h" #include "mixer.h" #include "platform_detect.h" -#include "sgpio.h" #if defined(HACKRF_ONE) || defined(RAD1O) || defined(PRALINE) #include "platform_scu.h" #endif @@ -479,7 +478,6 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d max5864_tx(&max5864); ssp1_set_mode_max283x(); max283x_tx(&max283x); - sgpio_configure(&sgpio_config, SGPIO_DIRECTION_TX); break; case RF_PATH_DIRECTION_RX: @@ -497,7 +495,6 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d max5864_rx(&max5864); ssp1_set_mode_max283x(); max283x_rx(&max283x); - sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); break; #ifdef PRALINE @@ -513,7 +510,6 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d } else { max283x_rx_calibration(&max283x); } - sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); break; #endif @@ -527,7 +523,6 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d max5864_standby(&max5864); ssp1_set_mode_max283x(); max283x_set_mode(&max283x, MAX283x_MODE_STANDBY); - sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); break; } diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 8a165e19..c365e9bc 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -310,13 +310,16 @@ void radio_changed(const uint32_t changed) switch (opmode) { case TRANSCEIVER_MODE_TX: case TRANSCEIVER_MODE_SS: + sgpio_configure(&sgpio_config, SGPIO_DIRECTION_TX); hackrf_ui()->set_direction(RF_PATH_DIRECTION_TX); break; case TRANSCEIVER_MODE_RX: case TRANSCEIVER_MODE_RX_SWEEP: + sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); hackrf_ui()->set_direction(RF_PATH_DIRECTION_RX); break; default: + sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); hackrf_ui()->set_direction(RF_PATH_DIRECTION_OFF); break; } From 1b37541237139fa8f99a9583ee126e232942cb1d Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 15 Apr 2026 19:02:42 +0100 Subject: [PATCH 105/238] Correct GPIO pin assignments for CPLD JTAG on Jawbreaker. --- firmware/common/hackrf_core.c | 2 +- firmware/common/platform_gpio.c | 9 +++++++-- firmware/common/platform_gpio.h | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 0534d480..1535e1e8 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -947,7 +947,7 @@ void pin_setup(void) #endif jtag_gpio_cpld.gpio_tck = gpio->cpld_tck; -#if defined(HACKRF_ONE) || defined(RAD1O) +#if defined(HACKRF_ONE) || defined(RAD1O) || defined(JAWBREAKER) jtag_gpio_cpld.gpio_tms = gpio->cpld_tms; jtag_gpio_cpld.gpio_tdi = gpio->cpld_tdi; jtag_gpio_cpld.gpio_tdo = gpio->cpld_tdo; diff --git a/firmware/common/platform_gpio.c b/firmware/common/platform_gpio.c index df07fc2a..3e0db2c6 100644 --- a/firmware/common/platform_gpio.c +++ b/firmware/common/platform_gpio.c @@ -131,17 +131,22 @@ const platform_gpio_t* platform_gpio(void) #endif /* CPLD JTAG interface GPIO pins_FPGA config pins in Praline */ - gpio.cpld_tck = &GPIO3_0; + gpio.cpld_tck = &GPIO3_0; #if defined(PRALINE) gpio.fpga_cfg_creset = &GPIO2_11; gpio.fpga_cfg_cdone = &GPIO5_14; gpio.fpga_cfg_spi_cs = &GPIO2_10; +#else + gpio.cpld_tdo = &GPIO5_18; #endif #if defined(HACKRF_ONE) || defined(RAD1O) - gpio.cpld_tdo = &GPIO5_18; gpio.cpld_tms = &GPIO3_4; gpio.cpld_tdi = &GPIO3_1; #endif +#if defined(JAWBREAKER) + gpio.cpld_tms = &GPIO3_1; + gpio.cpld_tdi = &GPIO3_4; +#endif #if defined(HACKRF_ONE) || defined(PRALINE) gpio.cpld_pp_tms = &GPIO1_1; gpio.cpld_pp_tdo = &GPIO1_8; diff --git a/firmware/common/platform_gpio.h b/firmware/common/platform_gpio.h index 14f0c067..9c32925c 100644 --- a/firmware/common/platform_gpio.h +++ b/firmware/common/platform_gpio.h @@ -109,7 +109,7 @@ typedef struct { /* CPLD JTAG interface GPIO pins, FPGA config pins in Praline */ gpio_t cpld_tck; -#if defined(HACKRF_ONE) || defined(RAD1O) +#if defined(HACKRF_ONE) || defined(RAD1O) || defined(JAWBREAKER) gpio_t cpld_tdo; gpio_t cpld_tms; gpio_t cpld_tdi; From 94d1517153ad677e9f349a655ce3f8d9bd1e4025 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Wed, 15 Apr 2026 14:47:08 -0400 Subject: [PATCH 106/238] Correct SCU config for CPLD JTAG on Jawbreaker --- firmware/common/platform_scu.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/firmware/common/platform_scu.c b/firmware/common/platform_scu.c index df611bd2..a4365635 100644 --- a/firmware/common/platform_scu.c +++ b/firmware/common/platform_scu.c @@ -85,11 +85,14 @@ const platform_scu_t* platform_scu(void) scu.PINMUX_FPGA_CRESET = (P5_2); /* GPIO2[11] on P5_2 */ scu.PINMUX_FPGA_CDONE = (P4_10); /* GPIO5[14] */ scu.PINMUX_FPGA_SPI_CS = (P5_1); /* GPIO2[10] */ -#elif defined(RAD1O) || defined(HACKRF_ONE) +#else + scu.PINMUX_CPLD_TDO = (P9_5); /* GPIO5[18] */ +#endif +#if defined(RAD1O) || defined(HACKRF_ONE) scu.PINMUX_CPLD_TMS = (P6_5); /* GPIO3[ 4] */ scu.PINMUX_CPLD_TDI = (P6_2); /* GPIO3[ 1] */ - scu.PINMUX_CPLD_TDO = (P9_5); /* GPIO5[18] */ -#else +#endif +#if defined(JAWBREAKER) scu.PINMUX_CPLD_TMS = (P6_2); /* GPIO3[ 1] */ scu.PINMUX_CPLD_TDI = (P6_5); /* GPIO3[ 4] */ #endif From a36f5ca08ae97c021b42a3b2ab3da61179b944fc Mon Sep 17 00:00:00 2001 From: grvvy Date: Thu, 16 Apr 2026 16:30:16 -0600 Subject: [PATCH 107/238] ci: increase wait time after running spiflash, add support for building firmware for different boards --- Jenkinsfile | 155 +++++++++--------- ...ild_hpro_firmware.sh => build_firmware.sh} | 2 +- ci-scripts/build_h1_firmware.sh | 9 - ci-scripts/hackrf_pro_test.py | 4 +- 4 files changed, 82 insertions(+), 88 deletions(-) rename ci-scripts/{build_hpro_firmware.sh => build_firmware.sh} (80%) delete mode 100755 ci-scripts/build_h1_firmware.sh diff --git a/Jenkinsfile b/Jenkinsfile index 2b03c4de..bf79d51e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,100 +1,101 @@ import org.jenkinsci.plugins.workflow.steps.FlowInterruptedException +def docker_args = '''--group-add=20 --group-add=46 --device-cgroup-rule="c 189:* rmw" \ + --device-cgroup-rule="c 166:* rmw" -v /dev/bus/usb:/dev/bus/usb \ + -v /tmp/req_pipe:/tmp/req_pipe -v /tmp/res_pipe:/tmp/res_pipe''' + +def h1_test = '''python3 ci-scripts/hackrf_test.py --ci --log log \ + --hostdir host/build/hackrf-tools/src/ \ + --fwupdate firmware/hackrf_usb/build/ \ + --tester 0000000000000000325866e629a25623 \ + --eut RunningFromRAM --unattended --rev r4''' + +def hpro_test = '''python3 ci-scripts/hackrf_pro_test.py --ci --log log \ + --hostdir host/build/hackrf-tools/src \ + --fwupdate firmware/hackrf_usb/build \ + --tester 0000000000000000a06063c82338145f \ + --eut RunningFromRAM -p --rev r1.2''' + pipeline { agent any stages { stage('Build Docker Image') { + options { + timeout(time: 20, unit: 'MINUTES') + } steps { sh 'docker build -t hackrf https://github.com/greatscottgadgets/hackrf.git' } } - stage('Test HackRF One') { + stage('Test HackRF One with BOARD=HACKRF_ONE') { agent { docker { image 'hackrf' reuseNode true - args '''--group-add=20 --group-add=46 --device-cgroup-rule="c 189:* rmw" \ - --device-cgroup-rule="c 166:* rmw" -v /dev/bus/usb:/dev/bus/usb \ - -v /tmp/req_pipe:/tmp/req_pipe -v /tmp/res_pipe:/tmp/res_pipe''' + args docker_args } } + options { + timeout(time: 20, unit: 'MINUTES') + } steps { sh './ci-scripts/install_host.sh' - sh './ci-scripts/build_h1_firmware.sh' + sh './ci-scripts/build_firmware.sh HACKRF_ONE' script { - allOff(); + allOff() + reset('h1_eut') } + sh 'sleep 1s' retry(3) { - script { - reset('h1_eut') - } - sh 'sleep 1s' sh './ci-scripts/test_host.sh' } - retry(3) { - script { - reset('h1_tester h1_eut') - } - sh 'sleep 1s' - script { - // Allow 5 minutes for the test to run - runCommand(5, 'MINUTES', "HackRF One Test", - '''python3 ci-scripts/hackrf_test.py --ci --log log \ - --hostdir host/build/hackrf-tools/src/ \ - --fwupdate firmware/hackrf_usb/build/ \ - --tester 0000000000000000325866e629a25623 \ - --eut RunningFromRAM --unattended --rev r4''' - ) - allOff() - } + script { + reset('h1_tester h1_eut') } + sh 'sleep 1s' + script { + // Allow up to 3 retries 5 minutes each for the HIL test + runCommand(3, 5, 'MINUTES', "HackRF One Test", h1_test) + } + script { + allOff() + reset('h1_eut') + } + sh 'sleep 1s' retry(3) { - script { - reset('h1_eut') - } - sh 'sleep 1s' sh 'python3 ci-scripts/test_sgpio_debug.py' } } } - stage('Test HackRF Pro') { + stage('Test HackRF Pro with BOARD=PRALINE') { agent { docker { image 'hackrf' reuseNode true - args '''--group-add=20 --group-add=46 --device-cgroup-rule="c 189:* rmw" \ - --device-cgroup-rule="c 166:* rmw" -v /dev/bus/usb:/dev/bus/usb \ - -v /tmp/req_pipe:/tmp/req_pipe -v /tmp/res_pipe:/tmp/res_pipe''' + args "$docker_args" } } + options { + timeout(time: 20, unit: 'MINUTES') + } steps { sh './ci-scripts/install_host.sh' - sh './ci-scripts/build_hpro_firmware.sh' + sh './ci-scripts/build_firmware.sh PRALINE' script { - allOff(); + allOff() + reset('hpro_eut') } + sh 'sleep 1s' retry(3) { - script { - reset('hpro_eut') - } - sh 'sleep 1s' sh './ci-scripts/test_host.sh' } - retry(3) { - script { - reset('hpro_tester hpro_eut') - } - sh 'sleep 1s' - script { - // Allow 5 minutes for the test to run - runCommand(5, 'MINUTES', "HackRF Pro Test", - '''python3 ci-scripts/hackrf_pro_test.py --ci --log log \ - --hostdir host/build/hackrf-tools/src \ - --fwupdate firmware/hackrf_usb/build \ - --tester 0000000000000000a06063c82338145f \ - --eut RunningFromRAM -p --rev r1.2''' - ) - } + script { + reset('hpro_tester hpro_eut') + } + sh 'sleep 1s' + script { + // Allow up to 3 retries 5 minutes each for the HIL test + runCommand(3, 5, 'MINUTES', "HackRF Pro Test", hpro_test) } } } @@ -110,32 +111,34 @@ pipeline { } def allOff() { - // Allow 20 seconds for the USB hub port power server to respond - runCommand(20, 'SECONDS', 'USB hub port power server command', "hubs all off") + // Allow up to 3 retries, 20 seconds each, for the USB hub port power server to respond appropriately + runCommand(3, 20, 'SECONDS', 'USB hub port power server command', "hubs all off") } def reset(devices) { - // Allow 20 seconds for the USB hub port power server to respond - runCommand(20, 'SECONDS', 'USB hub port power server command', "hubs ${devices} reset") + // Allow up to 3 retries, 20 seconds each, for the USB hub port power server to respond appropriately + runCommand(3, 20, 'SECONDS', 'USB hub port power server command', "hubs ${devices} reset") } -def runCommand(time, unit, title, cmd) { - try { - timeout(time: time, unit: unit) { - sh "${cmd}" +def runCommand(retries, time, unit, title, cmd) { + retry(retries) { + try { + timeout(time: time, unit: unit) { + sh "${cmd}" + } + } catch (FlowInterruptedException err) { + // Check if the cause was specifically an exceeded timeout + def cause = err.getCauses().get(0) + if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { + echo "${title} timeout reached." + throw err // Re-throw the exception to fail the build + } else { + echo "Build interrupted for another reason." + throw err // Re-throw the exception to fail the build + } + } catch (Exception err) { + echo "An unrelated error occurred: ${err.getMessage()}" + throw err } - } catch (FlowInterruptedException err) { - // Check if the cause was specifically an exceeded timeout - def cause = err.getCauses().get(0) - if (cause instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { - echo "${title} timeout reached." - throw err // Re-throw the exception to fail the build - } else { - echo "Build interrupted for another reason." - throw err // Re-throw the exception to fail the build - } - } catch (Exception err) { - echo "An unrelated error occurred: ${err.getMessage()}" - throw err } } diff --git a/ci-scripts/build_hpro_firmware.sh b/ci-scripts/build_firmware.sh similarity index 80% rename from ci-scripts/build_hpro_firmware.sh rename to ci-scripts/build_firmware.sh index 830d4bf7..b6fc4ec4 100755 --- a/ci-scripts/build_hpro_firmware.sh +++ b/ci-scripts/build_firmware.sh @@ -4,6 +4,6 @@ git submodule init git submodule update cd firmware/hackrf_usb rm -rf build -cmake -DBOARD=PRALINE -B build +cmake -DBOARD=$1 -B build cmake --build build cd ../.. diff --git a/ci-scripts/build_h1_firmware.sh b/ci-scripts/build_h1_firmware.sh deleted file mode 100755 index 762d64de..00000000 --- a/ci-scripts/build_h1_firmware.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -e -git submodule init -git submodule update -cd firmware/hackrf_usb -rm -rf build -cmake -DBOARD=HACKRF_ONE -B build -cmake --build build -cd ../.. diff --git a/ci-scripts/hackrf_pro_test.py b/ci-scripts/hackrf_pro_test.py index 1e9ac9f4..3d0b1c63 100644 --- a/ci-scripts/hackrf_pro_test.py +++ b/ci-scripts/hackrf_pro_test.py @@ -1413,11 +1413,11 @@ def program(bin_dir, fw_dir, serial, unattended=False): if spiflash.returncode != 0: log(spiflash.stdout + spiflash.stderr) fail(70) + time.sleep(3) then = time.time() device_found = False while time.time() < (then + 5): - time.sleep(1) flash_info = subprocess.run([bin_dir + "/hackrf_info"], capture_output=True, timeout=TIMEOUT) if serial == "RunningFromRAM" and not unattended: @@ -1433,7 +1433,7 @@ def program(bin_dir, fw_dir, serial, unattended=False): if serial in flash_info.stdout.decode('utf-8', errors='ignore'): device_found = True break - time.sleep(0.1) + time.sleep(1) if not device_found: fail(75) From 5120383da39f6d8f0a7bdaf67900fbea5b0076dc Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 3 Apr 2026 20:48:53 +0100 Subject: [PATCH 108/238] Universalize: platform_gpio.{c,h} Co-authored-by: Antoine van Gelder --- firmware/common/platform_gpio.c | 381 ++++++++++++++++++++------------ firmware/common/platform_gpio.h | 29 ++- 2 files changed, 255 insertions(+), 155 deletions(-) diff --git a/firmware/common/platform_gpio.c b/firmware/common/platform_gpio.c index 3e0db2c6..f9a44903 100644 --- a/firmware/common/platform_gpio.c +++ b/firmware/common/platform_gpio.c @@ -23,9 +23,7 @@ #include -#if defined(HACKRF_ONE) - #include "platform_detect.h" -#endif +#include "platform_detect.h" // clang-format off @@ -36,180 +34,287 @@ const platform_gpio_t* platform_gpio(void) return _platform_gpio; } + board_id_t board_id = detected_platform(); static platform_gpio_t gpio; /* LEDs */ gpio.led[0] = &GPIO2_1; gpio.led[1] = &GPIO2_2; gpio.led[2] = &GPIO2_8; + switch (board_id) { + case BOARD_ID_RAD1O: #if defined(RAD1O) - gpio.led[3] = &GPIO5_26; -#elif defined(PRALINE) - gpio.led[3] = &GPIO4_6; + gpio.led[3] = &GPIO5_26; #endif + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + gpio.led[3] = &GPIO4_6; +#endif + break; + default: + break; + } /* Power Supply Control */ -#if defined(PRALINE) - gpio.gpio_1v2_enable = &GPIO4_7; - gpio.gpio_3v3aux_enable_n = &GPIO5_15; -#else - gpio.gpio_1v8_enable = &GPIO3_6; + switch (board_id) { + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + gpio.gpio_1v2_enable = &GPIO4_7; + gpio.gpio_3v3aux_enable_n = &GPIO5_15; #endif + break; + default: + gpio.gpio_1v8_enable = &GPIO3_6; + break; + } /* MAX283x GPIO (XCVR_CTL / CS_XCVR) PinMux */ -#if defined(PRALINE) - gpio.max283x_select = &GPIO6_28; - gpio.max283x_enable = &GPIO7_1; - gpio.max283x_rx_enable = &GPIO7_2; - gpio.max2831_rxhp = &GPIO6_29; - gpio.max2831_ld = &GPIO4_11; -#else - gpio.max283x_select = &GPIO0_15; - gpio.max283x_enable = &GPIO2_6; - gpio.max283x_rx_enable = &GPIO2_5; - gpio.max283x_tx_enable = &GPIO2_4; + switch (board_id) { + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + gpio.max283x_select = &GPIO6_28; + gpio.max283x_enable = &GPIO7_1; + gpio.max283x_rx_enable = &GPIO7_2; + gpio.max2831_rxhp = &GPIO6_29; + gpio.max2831_ld = &GPIO4_11; #endif + break; + default: + gpio.max283x_select = &GPIO0_15; + gpio.max283x_enable = &GPIO2_6; + gpio.max283x_rx_enable = &GPIO2_5; + gpio.max283x_tx_enable = &GPIO2_4; + break; + } /* MAX5864 SPI chip select (AD_CS / CS_AD) GPIO PinMux */ -#if defined(PRALINE) - gpio.max5864_select = &GPIO6_30; -#else - gpio.max5864_select = &GPIO2_7; + switch (board_id) { + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + gpio.max5864_select = &GPIO6_30; #endif + break; + default: + gpio.max5864_select = &GPIO2_7; + break; + } /* RF supply (VAA) control */ -#if defined(HACKRF_ONE) - gpio.vaa_disable = &GPIO2_9; -#elif defined(PRALINE) - gpio.vaa_disable = &GPIO4_1; -#elif defined(RAD1O) - gpio.vaa_enable = &GPIO2_9; + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + gpio.vaa_disable = &GPIO2_9; #endif + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + gpio.vaa_disable = &GPIO4_1; +#endif + break; + case BOARD_ID_RAD1O: +#if defined(RAD1O) + gpio.vaa_enable = &GPIO2_9; +#endif + break; + default: + break; + } /* W25Q80BV Flash */ - gpio.w25q80bv_hold = &GPIO1_14; - gpio.w25q80bv_wp = &GPIO1_15; - gpio.w25q80bv_select = &GPIO5_11; + gpio.w25q80bv_hold = &GPIO1_14; + gpio.w25q80bv_wp = &GPIO1_15; + gpio.w25q80bv_select = &GPIO5_11; /* RF switch control */ -#if defined(HACKRF_ONE) - gpio.hp = &GPIO2_0; - gpio.lp = &GPIO2_10; - gpio.tx_mix_bp = &GPIO2_11; - gpio.no_mix_bypass = &GPIO1_0; - gpio.rx_mix_bp = &GPIO2_12; - gpio.tx_amp = &GPIO2_15; - gpio.tx = &GPIO5_15; - gpio.mix_bypass = &GPIO5_16; - gpio.rx = &GPIO5_5; - gpio.no_tx_amp_pwr = &GPIO3_5; - gpio.amp_bypass = &GPIO0_14; - gpio.rx_amp = &GPIO1_11; - gpio.no_rx_amp_pwr = &GPIO1_12; - // HackRF One rev 9 - gpio.h1r9_rx = &GPIO0_7; - gpio.h1r9_no_ant_pwr = &GPIO2_4; -#elif defined(RAD1O) - gpio.tx_rx_n = &GPIO1_11; - gpio.tx_rx = &GPIO0_14; - gpio.by_mix = &GPIO1_12; - gpio.by_mix_n = &GPIO2_10; - gpio.by_amp = &GPIO1_0; - gpio.by_amp_n = &GPIO5_5; - gpio.mixer_en = &GPIO5_16; - gpio.low_high_filt = &GPIO2_11; - gpio.low_high_filt_n = &GPIO2_12; - gpio.tx_amp = &GPIO2_15; - gpio.rx_lna = &GPIO5_15; -#elif defined(PRALINE) - gpio.tx_en = &GPIO3_4; - gpio.mix_en_n = &GPIO3_2; - gpio.mix_en_n_r1_0 = &GPIO5_6; - gpio.lpf_en = &GPIO4_8; - gpio.rf_amp_en = &GPIO4_9; - gpio.ant_bias_en_n = &GPIO1_12; + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + gpio.hp = &GPIO2_0; + gpio.lp = &GPIO2_10; + gpio.tx_mix_bp = &GPIO2_11; + gpio.no_mix_bypass = &GPIO1_0; + gpio.rx_mix_bp = &GPIO2_12; + gpio.tx_amp = &GPIO2_15; + gpio.tx = &GPIO5_15; + gpio.mix_bypass = &GPIO5_16; + gpio.rx = &GPIO5_5; + gpio.no_tx_amp_pwr = &GPIO3_5; + gpio.amp_bypass = &GPIO0_14; + gpio.rx_amp = &GPIO1_11; + gpio.no_rx_amp_pwr = &GPIO1_12; + // HackRF One rev 9 + gpio.h1r9_rx = &GPIO0_7; + gpio.h1r9_no_ant_pwr = &GPIO2_4; #endif + break; + case BOARD_ID_RAD1O: +#if defined(RAD1O) + gpio.tx_rx_n = &GPIO1_11; + gpio.tx_rx = &GPIO0_14; + gpio.by_mix = &GPIO1_12; + gpio.by_mix_n = &GPIO2_10; + gpio.by_amp = &GPIO1_0; + gpio.by_amp_n = &GPIO5_5; + gpio.mixer_en = &GPIO5_16; + gpio.low_high_filt = &GPIO2_11; + gpio.low_high_filt_n = &GPIO2_12; + gpio.tx_amp = &GPIO2_15; + gpio.rx_lna = &GPIO5_15; +#endif + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + gpio.tx_en = &GPIO3_4; + gpio.mix_en_n = &GPIO3_2; + gpio.mix_en_n_r1_0 = &GPIO5_6; + gpio.lpf_en = &GPIO4_8; + gpio.rf_amp_en = &GPIO4_9; + gpio.ant_bias_en_n = &GPIO1_12; +#endif + break; + case BOARD_ID_JELLYBEAN: + case BOARD_ID_JAWBREAKER: + break; + default: + break; + } /* CPLD JTAG interface GPIO pins_FPGA config pins in Praline */ - gpio.cpld_tck = &GPIO3_0; -#if defined(PRALINE) - gpio.fpga_cfg_creset = &GPIO2_11; - gpio.fpga_cfg_cdone = &GPIO5_14; - gpio.fpga_cfg_spi_cs = &GPIO2_10; -#else - gpio.cpld_tdo = &GPIO5_18; + gpio.cpld_tck = &GPIO3_0; + switch (board_id) { + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + gpio.fpga_cfg_creset = &GPIO2_11; + gpio.fpga_cfg_cdone = &GPIO5_14; + gpio.fpga_cfg_spi_cs = &GPIO2_10; #endif -#if defined(HACKRF_ONE) || defined(RAD1O) - gpio.cpld_tms = &GPIO3_4; - gpio.cpld_tdi = &GPIO3_1; + break; + default: +#if !defined(PRALINE) || defined(UNIVERSAL) + gpio.cpld_tdo = &GPIO5_18; + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + case BOARD_ID_RAD1O: + gpio.cpld_tms = &GPIO3_4; + gpio.cpld_tdi = &GPIO3_1; + break; + case BOARD_ID_JAWBREAKER: + gpio.cpld_tms = &GPIO3_1; + gpio.cpld_tdi = &GPIO3_4; + break; + default: + break; + } #endif -#if defined(JAWBREAKER) - gpio.cpld_tms = &GPIO3_1; - gpio.cpld_tdi = &GPIO3_4; -#endif -#if defined(HACKRF_ONE) || defined(PRALINE) - gpio.cpld_pp_tms = &GPIO1_1; - gpio.cpld_pp_tdo = &GPIO1_8; + break; + } + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + case BOARD_ID_PRALINE: +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + gpio.cpld_pp_tms = &GPIO1_1; + gpio.cpld_pp_tdo = &GPIO1_8; #endif + break; + default: + break; + } /* Other CPLD interface GPIO pins */ -#if !defined(PRALINE) - gpio.trigger_enable = &GPIO5_12; + switch (board_id) { + case BOARD_ID_PRALINE: + break; + default: +#if !defined(PRALINE) || defined(UNIVERSAL) + gpio.trigger_enable = &GPIO5_12; #endif - gpio.q_invert = &GPIO0_13; + break; + } + gpio.q_invert = &GPIO0_13; /* RFFC5071 GPIO serial interface PinMux */ -#if defined(JAWBREAKER) || defined(HACKRF_ONE) - gpio.rffc5072_select = &GPIO2_13; - gpio.rffc5072_clock = &GPIO5_6; - gpio.rffc5072_data = &GPIO3_3; - gpio.rffc5072_reset = &GPIO2_14; -#elif defined(RAD1O) - gpio.vco_ce = &GPIO2_13; - gpio.vco_sclk = &GPIO5_6; - gpio.vco_sdata = &GPIO3_3; - gpio.vco_le = &GPIO2_14; - gpio.vco_mux = &GPIO5_25; - gpio.synt_rfout_en = &GPIO3_5; -#elif defined(PRALINE) - gpio.rffc5072_select = &GPIO2_13; - gpio.rffc5072_clock = &GPIO5_18; - gpio.rffc5072_data = &GPIO4_14; - gpio.rffc5072_reset = &GPIO2_14; - gpio.rffc5072_ld = &GPIO6_25; + switch (board_id) { + case BOARD_ID_JAWBREAKER: + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: +#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(UNIVERSAL) + gpio.rffc5072_select = &GPIO2_13; + gpio.rffc5072_clock = &GPIO5_6; + gpio.rffc5072_data = &GPIO3_3; + gpio.rffc5072_reset = &GPIO2_14; #endif - - /* Praline */ -#if defined(PRALINE) - gpio.p2_ctrl0 = &GPIO7_3; - gpio.p2_ctrl1 = &GPIO7_4; - gpio.p1_ctrl0 = &GPIO0_14; - gpio.p1_ctrl1 = &GPIO5_16; - gpio.p1_ctrl2 = &GPIO3_5; - gpio.clkin_ctrl = &GPIO0_15; - gpio.aa_en = &GPIO1_7; - gpio.trigger_in = &GPIO6_26; - gpio.trigger_out = &GPIO5_6; - gpio.pps_out = &GPIO5_5; + break; + case BOARD_ID_RAD1O: +#if defined(RAD1O) + gpio.vco_ce = &GPIO2_13; + gpio.vco_sclk = &GPIO5_6; + gpio.vco_sdata = &GPIO3_3; + gpio.vco_le = &GPIO2_14; + gpio.vco_mux = &GPIO5_25; + gpio.synt_rfout_en = &GPIO3_5; #endif + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + gpio.rffc5072_select = &GPIO2_13; + gpio.rffc5072_clock = &GPIO5_18; + gpio.rffc5072_data = &GPIO4_14; + gpio.rffc5072_reset = &GPIO2_14; + gpio.rffc5072_ld = &GPIO6_25; +#endif + break; + default: + break; + } - /* HackRF One r9 */ -#if defined(HACKRF_ONE) - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - /* HackRF One r9 clock control */ - gpio.h1r9_clkin_en = &GPIO5_15; - gpio.h1r9_clkout_en = &GPIO0_9; - gpio.h1r9_mcu_clk_en = &GPIO0_8; - - /* HackRF One r9 power control */ - gpio.h1r9_1v8_enable = &GPIO2_9; - gpio.h1r9_vaa_disable = &GPIO3_6; - - gpio.h1r9_trigger_enable = &GPIO5_5; +#if defined(PRALINE) || defined(UNIVERSAL) + switch (board_id) { + case BOARD_ID_PRALINE: + gpio.p2_ctrl0 = &GPIO7_3; + gpio.p2_ctrl1 = &GPIO7_4; + gpio.p1_ctrl0 = &GPIO0_14; + gpio.p1_ctrl1 = &GPIO5_16; + gpio.p1_ctrl2 = &GPIO3_5; + gpio.clkin_ctrl = &GPIO0_15; + gpio.aa_en = &GPIO1_7; + gpio.trigger_in = &GPIO6_26; + gpio.trigger_out = &GPIO5_6; + gpio.pps_out = &GPIO5_5; + break; + default: + break; } #endif - /* RAD1O */ +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + /* HackRF One r9 clock control */ + switch (board_id) { + case BOARD_ID_HACKRF1_R9: + gpio.h1r9_clkin_en = &GPIO5_15; + gpio.h1r9_clkout_en = &GPIO0_9; + gpio.h1r9_mcu_clk_en = &GPIO0_8; + break; + default: + break; + } + + switch (board_id) { + case BOARD_ID_HACKRF1_R9: + gpio.h1r9_1v8_enable = &GPIO2_9; + gpio.h1r9_vaa_disable = &GPIO3_6; + gpio.h1r9_trigger_enable = &GPIO5_5; + break; + default: + break; + } +#endif + + /* rad1o LCD */ #if defined(RAD1O) gpio.lcd_cs = &GPIO4_12; /* P9_0 */ gpio.lcd_bl_en = &GPIO0_8; /* P1_1 */ @@ -217,11 +322,9 @@ const platform_gpio_t* platform_gpio(void) #endif /* Portapack */ -#if defined(HACKRF_ONE) || defined(PRALINE) +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) gpio.io_stbx = &GPIO5_0; /* P2_0 */ gpio.addr = &GPIO5_1; /* P2_1 */ - gpio.lcd_te = &GPIO5_3; /* P2_3 */ - gpio.unused = &GPIO5_7; /* P2_8 */ gpio.lcd_rdx = &GPIO5_4; /* P2_4 */ gpio.lcd_wrx = &GPIO1_10; /* P2_9 */ gpio.dir = &GPIO1_13; /* P2_13 */ diff --git a/firmware/common/platform_gpio.h b/firmware/common/platform_gpio.h index 9c32925c..16767136 100644 --- a/firmware/common/platform_gpio.h +++ b/firmware/common/platform_gpio.h @@ -30,7 +30,7 @@ extern "C" { typedef struct { /* LEDs */ -#if defined(PRALINE) || defined(RAD1O) +#if defined(PRALINE) || defined(UNIVERSAL) || defined(RAD1O) gpio_t led[4]; #else gpio_t led[3]; @@ -38,7 +38,7 @@ typedef struct { /* Power Supply Control */ gpio_t gpio_1v8_enable; -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) gpio_t gpio_1v2_enable; gpio_t gpio_3v3aux_enable_n; #endif @@ -48,7 +48,7 @@ typedef struct { gpio_t max283x_enable; gpio_t max283x_rx_enable; gpio_t max283x_tx_enable; -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) gpio_t max2831_rxhp; gpio_t max2831_ld; #endif @@ -68,7 +68,7 @@ typedef struct { gpio_t w25q80bv_select; /* RF switch control */ -#if defined(HACKRF_ONE) +#if defined(HACKRF_ONE) || defined(UNIVERSAL) gpio_t hp; gpio_t lp; gpio_t tx_mix_bp; @@ -98,7 +98,7 @@ typedef struct { gpio_t tx_amp; gpio_t rx_lna; #endif -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) gpio_t tx_en; gpio_t mix_en_n; gpio_t mix_en_n_r1_0; @@ -109,23 +109,23 @@ typedef struct { /* CPLD JTAG interface GPIO pins, FPGA config pins in Praline */ gpio_t cpld_tck; -#if defined(HACKRF_ONE) || defined(RAD1O) || defined(JAWBREAKER) - gpio_t cpld_tdo; +#if !defined(PRALINE) || defined(UNIVERSAL) gpio_t cpld_tms; gpio_t cpld_tdi; + gpio_t cpld_tdo; #endif -#if defined(HACKRF_ONE) || defined(PRALINE) +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) gpio_t cpld_pp_tms; gpio_t cpld_pp_tdo; #endif -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) gpio_t fpga_cfg_creset; gpio_t fpga_cfg_cdone; gpio_t fpga_cfg_spi_cs; #endif /* Other CPLD interface GPIO pins */ -#if !defined(PRALINE) +#if !defined(PRALINE) || defined(UNIVERSAL) gpio_t trigger_enable; #endif gpio_t q_invert; @@ -144,7 +144,7 @@ typedef struct { gpio_t synt_rfout_en; // RAD1O /* Praline */ -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) gpio_t p2_ctrl0; gpio_t p2_ctrl1; gpio_t p1_ctrl0; @@ -157,8 +157,7 @@ typedef struct { gpio_t pps_out; #endif - /* HackRF One r9 */ -#if defined(HACKRF_ONE) +#if defined(HACKRF_ONE) || defined(UNIVERSAL) /* HackRF One r9 clock control */ gpio_t h1r9_clkin_en; gpio_t h1r9_clkout_en; @@ -177,11 +176,9 @@ typedef struct { #endif /* Portapack */ -#if defined(HACKRF_ONE) || defined(PRALINE) +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) gpio_t io_stbx; gpio_t addr; - __attribute__((unused)) gpio_t lcd_te; - __attribute__((unused)) gpio_t unused; gpio_t lcd_rdx; gpio_t lcd_wrx; gpio_t dir; From 6176dbcdd52ba72cb4772f998329e1d269b9b90c Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 3 Apr 2026 21:18:01 +0100 Subject: [PATCH 109/238] Universalize: platform_scu.{c,h} Co-authored-by: Antoine van Gelder --- firmware/common/hackrf_core.c | 2 +- firmware/common/platform_scu.c | 597 ++++++++++++++++++++------------- firmware/common/platform_scu.h | 76 +++-- 3 files changed, 405 insertions(+), 270 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 1535e1e8..25e3b870 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -947,7 +947,7 @@ void pin_setup(void) #endif jtag_gpio_cpld.gpio_tck = gpio->cpld_tck; -#if defined(HACKRF_ONE) || defined(RAD1O) || defined(JAWBREAKER) +#if !defined(PRALINE) || defined(UNIVERSAL) jtag_gpio_cpld.gpio_tms = gpio->cpld_tms; jtag_gpio_cpld.gpio_tdi = gpio->cpld_tdi; jtag_gpio_cpld.gpio_tdo = gpio->cpld_tdo; diff --git a/firmware/common/platform_scu.c b/firmware/common/platform_scu.c index a4365635..edd6ee0e 100644 --- a/firmware/common/platform_scu.c +++ b/firmware/common/platform_scu.c @@ -25,6 +25,8 @@ #include +#include "platform_detect.h" + // clang-format off const platform_scu_t* platform_scu(void) @@ -34,44 +36,68 @@ const platform_scu_t* platform_scu(void) return _platform_scu; } + board_id_t board_id = detected_platform(); static platform_scu_t scu; /* LED PinMux */ scu.PINMUX_LED1 = SCU_PINMUX_LED1; /* GPIO2[1] on P4_1 */ scu.PINMUX_LED2 = SCU_PINMUX_LED2; /* GPIO2[2] on P4_2 */ scu.PINMUX_LED3 = SCU_PINMUX_LED3; /* GPIO2[8] on P6_12 */ -#if defined(PRALINE) - scu.PINMUX_LED4 = (P8_6); /* GPIO4[6] on P8_6 */ -#elif defined(RAD1O) - scu.PINMUX_LED4 = (PB_6); /* GPIO5[26] on PB_6 */ + switch (board_id) { + case BOARD_ID_RAD1O: +#if defined(RAD1O) + scu.PINMUX_LED4 = (PB_6); /* GPIO5[26] on PB_6 */ #endif + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + scu.PINMUX_LED4 = (P8_6); /* GPIO4[6] on P8_6 */ +#endif + break; + default: + break; + } /* Power Supply PinMux */ - scu.PINMUX_EN1V8 = (P6_10); /* GPIO3[6] on P6_10 */ - scu.PINMUX_EN1V2 = (P8_7); /* GPIO4[7] on P8_7 */ -#if defined(PRALINE) - scu.PINMUX_EN3V3_AUX_N = (P6_7); /* GPIO5[15] on P6_7 */ - scu.PINMUX_EN3V3_OC_N = (P6_11); /* GPIO3[7] on P6_11 */ + scu.PINMUX_EN1V8 = (P6_10); /* GPIO3[6] on P6_10 */ + scu.PINMUX_EN1V2 = (P8_7); /* GPIO4[7] on P8_7 */ + switch (board_id) { + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + scu.PINMUX_EN3V3_AUX_N = (P6_7); /* GPIO5[15] on P6_7 */ + scu.PINMUX_EN3V3_OC_N = (P6_11); /* GPIO3[7] on P6_11 */ #endif + break; + default: + break; + } /* GPIO Input PinMux */ scu.PINMUX_BOOT0 = (P1_1); /* GPIO0[8] on P1_1 */ scu.PINMUX_BOOT1 = (P1_2); /* GPIO0[9] on P1_2 */ -#if !defined(HACKRF_ONE) - scu.PINMUX_BOOT2 = (P2_8); /* GPIO5[7] on P2_8 */ - scu.PINMUX_BOOT3 = (P2_9); /* GPIO1[10] on P2_9 */ + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + break; + default: +#if !defined(HACKRF_ONE) || defined(UNIVERSAL) + scu.PINMUX_BOOT2 = (P2_8); /* GPIO5[7] on P2_8 */ + scu.PINMUX_BOOT3 = (P2_9); /* GPIO1[10] on P2_9 */ #endif - scu.PINMUX_PP_LCD_TE = (P2_3); /* GPIO5[3] on P2_3 */ - scu.PINMUX_PP_LCD_RDX = (P2_4); /* GPIO5[4] on P2_4 */ - scu.PINMUX_PP_UNUSED = (P2_8); /* GPIO5[7] on P2_8 */ - scu.PINMUX_PP_LCD_WRX = (P2_9); /* GPIO1[10] on P2_9 */ - scu.PINMUX_PP_DIR = (P2_13); /* GPIO1[13] on P2_13 */ + break; + } /* USB peripheral */ + switch (board_id) { + case BOARD_ID_JAWBREAKER: #if defined(JAWBREAKER) - scu.PINMUX_USB_LED0 = (P6_8); - scu.PINMUX_USB_LED1 = (P6_7); + scu.PINMUX_USB_LED0 = (P6_8); + scu.PINMUX_USB_LED1 = (P6_7); #endif + break; + default: + break; + } /* SSP1 Peripheral PinMux */ scu.SSP1_CIPO = (P1_3); /* P1_3 */ @@ -80,172 +106,242 @@ const platform_scu_t* platform_scu(void) scu.SSP1_CS = (P1_20); /* P1_20 */ /* CPLD JTAG interface */ - scu.PINMUX_CPLD_TCK = (P6_1); /* GPIO3[ 0] */ -#if defined(PRALINE) - scu.PINMUX_FPGA_CRESET = (P5_2); /* GPIO2[11] on P5_2 */ - scu.PINMUX_FPGA_CDONE = (P4_10); /* GPIO5[14] */ - scu.PINMUX_FPGA_SPI_CS = (P5_1); /* GPIO2[10] */ -#else - scu.PINMUX_CPLD_TDO = (P9_5); /* GPIO5[18] */ + scu.PINMUX_CPLD_TCK = (P6_1); /* GPIO3[ 0] */ + switch (board_id) { + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + scu.PINMUX_FPGA_CRESET = (P5_2); /* GPIO2[11] on P5_2 */ + scu.PINMUX_FPGA_CDONE = (P4_10); /* GPIO5[14] */ + scu.PINMUX_FPGA_SPI_CS = (P5_1); /* GPIO2[10] */ #endif -#if defined(RAD1O) || defined(HACKRF_ONE) - scu.PINMUX_CPLD_TMS = (P6_5); /* GPIO3[ 4] */ - scu.PINMUX_CPLD_TDI = (P6_2); /* GPIO3[ 1] */ -#endif -#if defined(JAWBREAKER) - scu.PINMUX_CPLD_TMS = (P6_2); /* GPIO3[ 1] */ - scu.PINMUX_CPLD_TDI = (P6_5); /* GPIO3[ 4] */ + break; + default: + break; + } +#if !defined(PRALINE) || defined(UNIVERSAL) + scu.PINMUX_CPLD_TDO = (P9_5); /* GPIO5[18] */ + switch (board_id) { + case BOARD_ID_RAD1O: + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + scu.PINMUX_CPLD_TMS = (P6_5); /* GPIO3[ 4] */ + scu.PINMUX_CPLD_TDI = (P6_2); /* GPIO3[ 1] */ + break; + default: + scu.PINMUX_CPLD_TMS = (P6_2); /* GPIO3[ 1] */ + scu.PINMUX_CPLD_TDI = (P6_5); /* GPIO3[ 4] */ + break; + } #endif /* CPLD SGPIO interface */ -#if defined(PRALINE) - scu.PINMUX_SGPIO0 = (P0_0); - scu.PINMUX_SGPIO1 = (P0_1); - scu.PINMUX_SGPIO2 = (P1_15); - scu.PINMUX_SGPIO3 = (P1_16); - scu.PINMUX_SGPIO4 = (P9_4); - scu.PINMUX_SGPIO5 = (P6_6); - scu.PINMUX_SGPIO6 = (P2_2); - scu.PINMUX_SGPIO7 = (P1_0); - scu.PINMUX_SGPIO8 = (P8_0); - scu.PINMUX_SGPIO9 = (P9_3); - scu.PINMUX_SGPIO10 = (P8_2); - scu.PINMUX_SGPIO11 = (P1_17); - scu.PINMUX_SGPIO12 = (P1_18); - scu.PINMUX_SGPIO14 = (P1_18); - scu.PINMUX_SGPIO15 = (P1_18); + switch (board_id) { + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + scu.PINMUX_SGPIO0 = (P0_0); + scu.PINMUX_SGPIO1 = (P0_1); + scu.PINMUX_SGPIO2 = (P1_15); + scu.PINMUX_SGPIO3 = (P1_16); + scu.PINMUX_SGPIO4 = (P9_4); + scu.PINMUX_SGPIO5 = (P6_6); + scu.PINMUX_SGPIO6 = (P2_2); + scu.PINMUX_SGPIO7 = (P1_0); + scu.PINMUX_SGPIO8 = (P8_0); + scu.PINMUX_SGPIO9 = (P9_3); + scu.PINMUX_SGPIO10 = (P8_2); + scu.PINMUX_SGPIO11 = (P1_17); + scu.PINMUX_SGPIO12 = (P1_18); + scu.PINMUX_SGPIO14 = (P1_18); + scu.PINMUX_SGPIO15 = (P1_18); - scu.PINMUX_SGPIO0_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION3); - scu.PINMUX_SGPIO1_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION3); - scu.PINMUX_SGPIO2_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); - scu.PINMUX_SGPIO3_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); - scu.PINMUX_SGPIO4_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); - scu.PINMUX_SGPIO5_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); - scu.PINMUX_SGPIO6_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu.PINMUX_SGPIO7_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); - scu.PINMUX_SGPIO8_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu.PINMUX_SGPIO9_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); - scu.PINMUX_SGPIO10_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu.PINMUX_SGPIO11_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); - scu.PINMUX_SGPIO12_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu.PINMUX_SGPIO14_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu.PINMUX_SGPIO15_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); -#else - scu.PINMUX_SGPIO0 = (P0_0); - scu.PINMUX_SGPIO1 = (P0_1); - scu.PINMUX_SGPIO2 = (P1_15); - scu.PINMUX_SGPIO3 = (P1_16); - scu.PINMUX_SGPIO4 = (P6_3); - scu.PINMUX_SGPIO5 = (P6_6); - scu.PINMUX_SGPIO6 = (P2_2); - scu.PINMUX_SGPIO7 = (P1_0); - scu.PINMUX_SGPIO8 = (P9_6); - scu.PINMUX_SGPIO9 = (P4_3); - scu.PINMUX_SGPIO10 = (P1_14); - scu.PINMUX_SGPIO11 = (P1_17); - scu.PINMUX_SGPIO12 = (P1_18); - scu.PINMUX_SGPIO14 = (P4_9); - scu.PINMUX_SGPIO15 = (P4_10); - - scu.PINMUX_SGPIO0_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION3); - scu.PINMUX_SGPIO1_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION3); - scu.PINMUX_SGPIO2_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); - scu.PINMUX_SGPIO3_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); - scu.PINMUX_SGPIO4_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); - scu.PINMUX_SGPIO5_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); - scu.PINMUX_SGPIO6_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu.PINMUX_SGPIO7_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); - scu.PINMUX_SGPIO8_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); - scu.PINMUX_SGPIO9_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION7); - scu.PINMUX_SGPIO10_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); - scu.PINMUX_SGPIO11_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); - scu.PINMUX_SGPIO12_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu.PINMUX_SGPIO14_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu.PINMUX_SGPIO15_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.PINMUX_SGPIO0_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION3); + scu.PINMUX_SGPIO1_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION3); + scu.PINMUX_SGPIO2_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu.PINMUX_SGPIO3_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu.PINMUX_SGPIO4_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO5_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu.PINMUX_SGPIO6_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.PINMUX_SGPIO7_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO8_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.PINMUX_SGPIO9_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO10_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.PINMUX_SGPIO11_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO12_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.PINMUX_SGPIO14_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.PINMUX_SGPIO15_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); #endif + break; + default: +#if !defined(PRALINE) || defined(UNIVERSAL) + scu.PINMUX_SGPIO0 = (P0_0); + scu.PINMUX_SGPIO1 = (P0_1); + scu.PINMUX_SGPIO2 = (P1_15); + scu.PINMUX_SGPIO3 = (P1_16); + scu.PINMUX_SGPIO4 = (P6_3); + scu.PINMUX_SGPIO5 = (P6_6); + scu.PINMUX_SGPIO6 = (P2_2); + scu.PINMUX_SGPIO7 = (P1_0); + scu.PINMUX_SGPIO8 = (P9_6); + scu.PINMUX_SGPIO9 = (P4_3); + scu.PINMUX_SGPIO10 = (P1_14); + scu.PINMUX_SGPIO11 = (P1_17); + scu.PINMUX_SGPIO12 = (P1_18); + scu.PINMUX_SGPIO14 = (P4_9); + scu.PINMUX_SGPIO15 = (P4_10); + + scu.PINMUX_SGPIO0_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION3); + scu.PINMUX_SGPIO1_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION3); + scu.PINMUX_SGPIO2_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu.PINMUX_SGPIO3_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu.PINMUX_SGPIO4_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu.PINMUX_SGPIO5_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu.PINMUX_SGPIO6_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.PINMUX_SGPIO7_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO8_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO9_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION7); + scu.PINMUX_SGPIO10_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO11_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu.PINMUX_SGPIO12_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.PINMUX_SGPIO14_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.PINMUX_SGPIO15_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); +#endif + break; + } scu.TRIGGER_EN = (P4_8); /* GPIO5[12] on P4_8 */ /* MAX283x GPIO (XCVR_CTL) PinMux */ -#if defined(PRALINE) - scu.XCVR_ENABLE = PE_1; /* GPIO7[1] on PE_1 */ - scu.XCVR_RXENABLE = PE_2; /* GPIO7[2] on PE_2 */ - scu.XCVR_CS = PD_14; /* GPIO6[28] on PD_14 */ - scu.XCVR_RXHP = PD_15; /* GPIO6[29] on PD_15 */ - scu.XCVR_LD = P9_6; /* GPIO4[11] on P9_6 */ - - scu.XCVR_ENABLE_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu.XCVR_RXENABLE_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu.XCVR_CS_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu.XCVR_RXHP_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu.XCVR_LD_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0 | - SCU_CONF_EPD_EN_PULLDOWN | SCU_CONF_EPUN_DIS_PULLUP); -#elif defined(JAWBREAKER) || defined(HACKRF_ONE) - scu.XCVR_ENABLE = P4_6; /* GPIO2[6] on P4_6 */ - scu.XCVR_RXENABLE = P4_5; /* GPIO2[5] on P4_5 */ - scu.XCVR_TXENABLE = P4_4; /* GPIO2[4] on P4_4 */ - scu.XCVR_CS = P1_20; /* GPIO0[15] on P1_20 */ - - scu.XCVR_ENABLE_PINCFG = (SCU_GPIO_FAST); - scu.XCVR_RXENABLE_PINCFG = (SCU_GPIO_FAST); - scu.XCVR_TXENABLE_PINCFG = (SCU_GPIO_FAST); - scu.XCVR_CS_PINCFG = (SCU_GPIO_FAST); -#elif defined(RAD1O) - scu.XCVR_RXHP = P8_1; /* GPIO[] on P8_1 */ - scu.XCVR_B6 = P8_2; /* GPIO[] on P8_2 */ - scu.XCVR_B7 = P9_3; /* GPIO[] on P9_3 */ + switch (board_id) { + case BOARD_ID_RAD1O: +#if defined(RAD1O) + scu.XCVR_RXHP = P8_1; /* GPIO[] on P8_1 */ + scu.XCVR_B6 = P8_2; /* GPIO[] on P8_2 */ + scu.XCVR_B7 = P9_3; /* GPIO[] on P9_3 */ #endif + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + scu.XCVR_ENABLE = PE_1; /* GPIO7[1] on PE_1 */ + scu.XCVR_RXENABLE = PE_2; /* GPIO7[2] on PE_2 */ + scu.XCVR_CS = PD_14; /* GPIO6[28] on PD_14 */ + scu.XCVR_RXHP = PD_15; /* GPIO6[29] on PD_15 */ + scu.XCVR_LD = P9_6; /* GPIO4[11] on P9_6 */ + + scu.XCVR_ENABLE_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.XCVR_RXENABLE_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.XCVR_CS_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.XCVR_RXHP_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.XCVR_LD_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0 | + SCU_CONF_EPD_EN_PULLDOWN | SCU_CONF_EPUN_DIS_PULLUP); +#endif + break; + case BOARD_ID_JAWBREAKER: + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: +#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(UNIVERSAL) + scu.XCVR_ENABLE = P4_6; /* GPIO2[6] on P4_6 */ + scu.XCVR_RXENABLE = P4_5; /* GPIO2[5] on P4_5 */ + scu.XCVR_TXENABLE = P4_4; /* GPIO2[4] on P4_4 */ + scu.XCVR_CS = P1_20; /* GPIO0[15] on P1_20 */ + + scu.XCVR_ENABLE_PINCFG = (SCU_GPIO_FAST); + scu.XCVR_RXENABLE_PINCFG = (SCU_GPIO_FAST); + scu.XCVR_TXENABLE_PINCFG = (SCU_GPIO_FAST); + scu.XCVR_CS_PINCFG = (SCU_GPIO_FAST); +#endif + break; + default: + break; + } /* MAX5864 SPI chip select (AD_CS) GPIO PinMux */ -#if defined(PRALINE) - scu.AD_CS = (PD_16); /* GPIO6[30] on PD_16 */ - scu.AD_CS_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); -#else - scu.AD_CS = (P5_7); /* GPIO2[7] on P5_7 */ - scu.AD_CS_PINCFG = (SCU_GPIO_FAST); + switch (board_id) { + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + scu.AD_CS = (PD_16); /* GPIO6[30] on PD_16 */ + scu.AD_CS_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); #endif + break; + default: + scu.AD_CS = (P5_7); /* GPIO2[7] on P5_7 */ + scu.AD_CS_PINCFG = (SCU_GPIO_FAST); + break; + } /* RFFC5071 GPIO serial interface PinMux */ -#if defined(PRALINE) - scu.MIXER_ENX = (P5_4); /* GPIO2[13] on P5_4 */ - scu.MIXER_SCLK = (P9_5); /* GPIO5[18] on P9_5 */ - scu.MIXER_SDATA = (P9_2); /* GPIO4[14] on P9_2 */ - scu.MIXER_RESETX = (P5_5); /* GPIO2[14] on P5_5 */ - scu.MIXER_LD = (PD_11); /* GPIO6[25] on PD_11 */ + switch (board_id) { + case BOARD_ID_JAWBREAKER: + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: +#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(UNIVERSAL) + scu.MIXER_ENX = (P5_4); /* GPIO2[13] on P5_4 */ + scu.MIXER_SCLK = (P2_6); /* GPIO5[6] on P2_6 */ + scu.MIXER_SDATA = (P6_4); /* GPIO3[3] on P6_4 */ + scu.MIXER_RESETX = (P5_5); /* GPIO2[14] on P5_5 */ - scu.MIXER_SCLK_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu.MIXER_SDATA_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu.MIXER_LD_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); -#elif defined(JAWBREAKER) || defined(HACKRF_ONE) - scu.MIXER_ENX = (P5_4); /* GPIO2[13] on P5_4 */ - scu.MIXER_SCLK = (P2_6); /* GPIO5[6] on P2_6 */ - scu.MIXER_SDATA = (P6_4); /* GPIO3[3] on P6_4 */ - scu.MIXER_RESETX = (P5_5); /* GPIO2[14] on P5_5 */ - - scu.MIXER_SCLK_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu.MIXER_SDATA_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); -#elif defined(RAD1O) - scu.VCO_CE = (P5_4); /* GPIO2[13] on P5_4 */ - scu.VCO_SCLK = (P2_6); /* GPIO5[6] on P2_6 */ - scu.VCO_SDATA = (P6_4); /* GPIO3[3] on P6_4 */ - scu.VCO_LE = (P5_5); /* GPIO2[14] on P5_5 */ - scu.VCO_MUX = (PB_5); /* GPIO5[25] on PB_5 */ - scu.MIXER_EN = (P6_8); /* GPIO5[16] on P6_8 */ - scu.SYNT_RFOUT_EN = (P6_9); /* GPIO3[5] on P6_9 */ + scu.MIXER_SCLK_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.MIXER_SDATA_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); #endif + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + scu.MIXER_ENX = (P5_4); /* GPIO2[13] on P5_4 */ + scu.MIXER_SCLK = (P9_5); /* GPIO5[18] on P9_5 */ + scu.MIXER_SDATA = (P9_2); /* GPIO4[14] on P9_2 */ + scu.MIXER_RESETX = (P5_5); /* GPIO2[14] on P5_5 */ + scu.MIXER_LD = (PD_11); /* GPIO6[25] on PD_11 */ + + scu.MIXER_SCLK_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.MIXER_SDATA_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.MIXER_LD_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); +#endif + break; + case BOARD_ID_RAD1O: +#if defined(RAD1O) + scu.VCO_CE = (P5_4); /* GPIO2[13] on P5_4 */ + scu.VCO_SCLK = (P2_6); /* GPIO5[6] on P2_6 */ + scu.VCO_SDATA = (P6_4); /* GPIO3[3] on P6_4 */ + scu.VCO_LE = (P5_5); /* GPIO2[14] on P5_5 */ + scu.VCO_MUX = (PB_5); /* GPIO5[25] on PB_5 */ + scu.MIXER_EN = (P6_8); /* GPIO5[16] on P6_8 */ + scu.SYNT_RFOUT_EN = (P6_9); /* GPIO3[5] on P6_9 */ +#endif + break; + default: + break; + } /* RF LDO control */ + switch (board_id) { + case BOARD_ID_JAWBREAKER: #if defined(JAWBREAKER) - scu.RF_LDO_ENABLE = (P5_0); /* GPIO2[9] on P5_0 */ + scu.RF_LDO_ENABLE = (P5_0); /* GPIO2[9] on P5_0 */ #endif + break; + default: + break; + } /* RF supply (VAA) control */ -#if defined(PRALINE) - scu.NO_VAA_ENABLE = P8_1; /* GPIO4[1] on P8_1 */ -#elif defined(HACKRF_ONE) - scu.NO_VAA_ENABLE = P5_0; /* GPIO2[9] on P5_0 */ -#elif defined(RAD1O) - scu.VAA_ENABLE = P5_0; /* GPIO2[9] on P5_0 */ + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + scu.NO_VAA_ENABLE = P5_0; /* GPIO2[9] on P5_0 */ #endif + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + scu.NO_VAA_ENABLE = P8_1; /* GPIO4[1] on P8_1 */ +#endif + break; + case BOARD_ID_RAD1O: +#if defined(RAD1O) + scu.VAA_ENABLE = P5_0; /* GPIO2[9] on P5_0 */ +#endif + break; + default: + break; + } /* SPI flash */ scu.SSP0_CIPO = (P3_6); @@ -256,79 +352,105 @@ const platform_scu_t* platform_scu(void) scu.FLASH_WP = (P3_5); /* GPIO1[15] on P3_5 */ /* RF switch control */ -#if defined(PRALINE) - scu.TX_EN = P6_5; /* GPIO3[4] on P6_5 */ - scu.MIX_EN_N = P6_3; /* GPIO3[2] on P6_3 */ - scu.MIX_EN_N_R1_0 = P2_6; /* GPIO5[6] on P2_6 */ - scu.LPF_EN = PA_1; /* GPIO4[8] on PA_1 */ - scu.RF_AMP_EN = PA_2; /* GPIO4[9] on PA_2 */ - scu.ANT_BIAS_EN_N = P2_12; /* GPIO1[12] on P2_12 */ - scu.ANT_BIAS_OC_N = P2_11; /* GPIO1[11] on P2_11 */ -#elif defined(HACKRF_ONE) - scu.HP = P4_0; /* GPIO2[0] on P4_0 */ - scu.LP = P5_1; /* GPIO2[10] on P5_1 */ - scu.TX_MIX_BP = P5_2; /* GPIO2[11] on P5_2 */ - scu.NO_MIX_BYPASS = P1_7; /* GPIO1[0] on P1_7 */ - scu.RX_MIX_BP = P5_3; /* GPIO2[12] on P5_3 */ - scu.TX_AMP = P5_6; /* GPIO2[15] on P5_6 */ - scu.TX = P6_7; /* GPIO5[15] on P6_7 */ - scu.MIX_BYPASS = P6_8; /* GPIO5[16] on P6_8 */ - scu.RX = P2_5; /* GPIO5[5] on P2_5 */ - scu.NO_TX_AMP_PWR = P6_9; /* GPIO3[5] on P6_9 */ - scu.AMP_BYPASS = P2_10; /* GPIO0[14] on P2_10 */ - scu.RX_AMP = P2_11; /* GPIO1[11] on P2_11 */ - scu.NO_RX_AMP_PWR = P2_12; /* GPIO1[12] on P2_12 */ -#elif defined(RAD1O) - scu.BY_AMP = P1_7; /* GPIO1[0] on P1_7 */ - scu.BY_AMP_N = P2_5; /* GPIO5[5] on P2_5 */ - scu.TX_RX = P2_10; /* GPIO0[14] on P2_10 */ - scu.TX_RX_N = P2_11; /* GPIO1[11] on P2_11 */ - scu.BY_MIX = P2_12; /* GPIO1[12] on P2_12 */ - scu.BY_MIX_N = P5_1; /* GPIO2[10] on P5_1 */ - scu.LOW_HIGH_FILT = P5_2; /* GPIO2[11] on P5_2 */ - scu.LOW_HIGH_FILT_N = P5_3; /* GPIO2[12] on P5_3 */ - scu.TX_AMP = P5_6; /* GPIO2[15] on P5_6 */ - scu.RX_LNA = P6_7; /* GPIO5[15] on P6_7 */ + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + scu.HP = P4_0; /* GPIO2[0] on P4_0 */ + scu.LP = P5_1; /* GPIO2[10] on P5_1 */ + scu.TX_MIX_BP = P5_2; /* GPIO2[11] on P5_2 */ + scu.NO_MIX_BYPASS = P1_7; /* GPIO1[0] on P1_7 */ + scu.RX_MIX_BP = P5_3; /* GPIO2[12] on P5_3 */ + scu.TX_AMP = P5_6; /* GPIO2[15] on P5_6 */ + scu.TX = P6_7; /* GPIO5[15] on P6_7 */ + scu.MIX_BYPASS = P6_8; /* GPIO5[16] on P6_8 */ + scu.RX = P2_5; /* GPIO5[5] on P2_5 */ + scu.NO_TX_AMP_PWR = P6_9; /* GPIO3[5] on P6_9 */ + scu.AMP_BYPASS = P2_10; /* GPIO0[14] on P2_10 */ + scu.RX_AMP = P2_11; /* GPIO1[11] on P2_11 */ + scu.NO_RX_AMP_PWR = P2_12; /* GPIO1[12] on P2_12 */ #endif + break; + case BOARD_ID_RAD1O: +#if defined(RAD1O) + scu.BY_AMP = P1_7; /* GPIO1[0] on P1_7 */ + scu.BY_AMP_N = P2_5; /* GPIO5[5] on P2_5 */ + scu.TX_RX = P2_10; /* GPIO0[14] on P2_10 */ + scu.TX_RX_N = P2_11; /* GPIO1[11] on P2_11 */ + scu.BY_MIX = P2_12; /* GPIO1[12] on P2_12 */ + scu.BY_MIX_N = P5_1; /* GPIO2[10] on P5_1 */ + scu.LOW_HIGH_FILT = P5_2; /* GPIO2[11] on P5_2 */ + scu.LOW_HIGH_FILT_N = P5_3; /* GPIO2[12] on P5_3 */ + scu.TX_AMP = P5_6; /* GPIO2[15] on P5_6 */ + scu.RX_LNA = P6_7; /* GPIO5[15] on P6_7 */ +#endif + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + scu.TX_EN = P6_5; /* GPIO3[4] on P6_5 */ + scu.MIX_EN_N = P6_3; /* GPIO3[2] on P6_3 */ + scu.MIX_EN_N_R1_0 = P2_6; /* GPIO5[6] on P2_6 */ + scu.LPF_EN = PA_1; /* GPIO4[8] on PA_1 */ + scu.RF_AMP_EN = PA_2; /* GPIO4[9] on PA_2 */ + scu.ANT_BIAS_EN_N = P2_12; /* GPIO1[12] on P2_12 */ + scu.ANT_BIAS_OC_N = P2_11; /* GPIO1[11] on P2_11 */ +#endif + break; + default: + break; + } /* Praline */ -#if defined(PRALINE) - scu.P2_CTRL0 = (PE_3); /* GPIO7[3] on PE_3 */ - scu.P2_CTRL1 = (PE_4); /* GPIO7[4] on PE_4 */ - scu.P1_CTRL0 = (P2_10); /* GPIO0[14] on P2_10 */ - scu.P1_CTRL1 = (P6_8); /* GPIO5[16] on P6_8 */ - scu.P1_CTRL2 = (P6_9); /* GPIO3[5] on P6_9 */ - scu.CLKIN_CTRL = (P1_20); /* GPIO0[15] on P1_20 */ - scu.AA_EN = (P1_14); /* GPIO1[7] on P1_14 */ - scu.TRIGGER_IN = (PD_12); /* GPIO6[26] on PD_12 */ - scu.TRIGGER_OUT = (P2_6); /* GPIO5[6] on P2_6 */ - scu.PPS_OUT = (P2_5); /* GPIO5[5] on P2_5 */ +#if defined(PRALINE) || defined(UNIVERSAL) + switch (board_id) { + case BOARD_ID_PRALINE: + scu.P2_CTRL0 = (PE_3); /* GPIO7[3] on PE_3 */ + scu.P2_CTRL1 = (PE_4); /* GPIO7[4] on PE_4 */ + scu.P1_CTRL0 = (P2_10); /* GPIO0[14] on P2_10 */ + scu.P1_CTRL1 = (P6_8); /* GPIO5[16] on P6_8 */ + scu.P1_CTRL2 = (P6_9); /* GPIO3[5] on P6_9 */ + scu.CLKIN_CTRL = (P1_20); /* GPIO0[15] on P1_20 */ + scu.AA_EN = (P1_14); /* GPIO1[7] on P1_14 */ + scu.TRIGGER_IN = (PD_12); /* GPIO6[26] on PD_12 */ + scu.TRIGGER_OUT = (P2_6); /* GPIO5[6] on P2_6 */ + scu.PPS_OUT = (P2_5); /* GPIO5[5] on P2_5 */ - scu.P2_CTRL0_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu.P2_CTRL1_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu.P1_CTRL0_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu.P1_CTRL1_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu.P1_CTRL2_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu.CLKIN_CTRL_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu.AA_EN_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu.TRIGGER_IN_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu.TRIGGER_OUT_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu.PPS_OUT_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.P2_CTRL0_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.P2_CTRL1_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.P1_CTRL0_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.P1_CTRL1_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.P1_CTRL2_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.CLKIN_CTRL_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.AA_EN_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu.TRIGGER_IN_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.TRIGGER_OUT_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.PPS_OUT_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + break; + default: + break; + } #endif /* HackRF One r9 */ -#if defined(HACKRF_ONE) - scu.H1R9_CLKIN_EN = P6_7; /* GPIO5[15] on P6_7 */ - scu.H1R9_CLKOUT_EN = P1_2; /* GPIO0[9] on P1_2 = has boot pull-down; */ - scu.H1R9_MCU_CLK_EN = P1_1; /* GPIO0[8] on P1_1 = has boot pull-up; */ - scu.H1R9_RX = P2_7; /* GPIO0[7] on P4_4 = has boot pull-up; */ - scu.H1R9_NO_ANT_PWR = P4_4; /* GPIO2[4] on P4_4 */ - scu.H1R9_EN1V8 = P5_0; /* GPIO2[9] on P5_0 */ - scu.H1R9_NO_VAA_EN = P6_10; /* GPIO3[6] on P6_10 */ - scu.H1R9_TRIGGER_EN = P2_5; /* GPIO5[5] on P2_5 */ +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + switch (board_id) { + case BOARD_ID_HACKRF1_R9: + scu.H1R9_CLKIN_EN = P6_7; /* GPIO5[15] on P6_7 */ + scu.H1R9_CLKOUT_EN = P1_2; /* GPIO0[9] on P1_2 = has boot pull-down; */ + scu.H1R9_MCU_CLK_EN = P1_1; /* GPIO0[8] on P1_1 = has boot pull-up; */ + scu.H1R9_RX = P2_7; /* GPIO0[7] on P4_4 = has boot pull-up; */ + scu.H1R9_NO_ANT_PWR = P4_4; /* GPIO2[4] on P4_4 */ + scu.H1R9_EN1V8 = P5_0; /* GPIO2[9] on P5_0 */ + scu.H1R9_NO_VAA_EN = P6_10; /* GPIO3[6] on P6_10 */ + scu.H1R9_TRIGGER_EN = P2_5; /* GPIO5[5] on P2_5 */ + break; + default: + break; + } #endif - /* Miscellaneous */ + /* Expansion headers */ +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) scu.PINMUX_PP_D0 = (P7_0); /* GPIO3[8] */ scu.PINMUX_PP_D1 = (P7_1); /* GPIO3[9] */ scu.PINMUX_PP_D2 = (P7_2); /* GPIO3[10] */ @@ -338,16 +460,11 @@ const platform_scu_t* platform_scu(void) scu.PINMUX_PP_D6 = (P7_6); /* GPIO3[14] */ scu.PINMUX_PP_D7 = (P7_7); /* GPIO3[15] */ - /* TODO add other Pins */ - - scu.PINMUX_GPIO3_8 = (P7_0); /* GPIO3[8] */ - scu.PINMUX_GPIO3_9 = (P7_1); /* GPIO3[9] */ - scu.PINMUX_GPIO3_10 = (P7_2); /* GPIO3[10] */ - scu.PINMUX_GPIO3_11 = (P7_3); /* GPIO3[11] */ - scu.PINMUX_GPIO3_12 = (P7_4); /* GPIO3[12] */ - scu.PINMUX_GPIO3_13 = (P7_5); /* GPIO3[13] */ - scu.PINMUX_GPIO3_14 = (P7_6); /* GPIO3[14] */ - scu.PINMUX_GPIO3_15 = (P7_7); /* GPIO3[15] */ + scu.PINMUX_PP_LCD_TE = (P2_3); /* GPIO5[3] on P2_3 */ + scu.PINMUX_PP_LCD_RDX = (P2_4); /* GPIO5[4] on P2_4 */ + scu.PINMUX_PP_UNUSED = (P2_8); /* GPIO5[7] on P2_8 */ + scu.PINMUX_PP_LCD_WRX = (P2_9); /* GPIO1[10] on P2_9 */ + scu.PINMUX_PP_DIR = (P2_13); /* GPIO1[13] on P2_13 */ scu.PINMUX_PP_TDO = (P1_5); /* GPIO1[8] */ scu.PINMUX_SD_POW = (P1_5); /* GPIO1[8] */ @@ -365,6 +482,16 @@ const platform_scu_t* platform_scu(void) scu.PINMUX_U0_TXD = (P2_0); /* GPIO5[0] */ scu.PINMUX_U0_RXD = (P2_1); /* GPIO5[1] */ + scu.PINMUX_GPIO3_8 = (P7_0); /* GPIO3[8] */ + scu.PINMUX_GPIO3_9 = (P7_1); /* GPIO3[9] */ + scu.PINMUX_GPIO3_10 = (P7_2); /* GPIO3[10] */ + scu.PINMUX_GPIO3_11 = (P7_3); /* GPIO3[11] */ + scu.PINMUX_GPIO3_12 = (P7_4); /* GPIO3[12] */ + scu.PINMUX_GPIO3_13 = (P7_5); /* GPIO3[13] */ + scu.PINMUX_GPIO3_14 = (P7_6); /* GPIO3[14] */ + scu.PINMUX_GPIO3_15 = (P7_7); /* GPIO3[15] */ +#endif + scu.PINMUX_ISP = (P2_7); /* GPIO0[7] */ scu.PINMUX_GP_CLKIN = (P4_7); diff --git a/firmware/common/platform_scu.h b/firmware/common/platform_scu.h index 2b4b42f0..2c5365e3 100644 --- a/firmware/common/platform_scu.h +++ b/firmware/common/platform_scu.h @@ -34,18 +34,17 @@ extern "C" { */ typedef struct { - /* LED PinMux */ + /* GPIO Output PinMux */ scu_grp_pin_t PINMUX_LED1; scu_grp_pin_t PINMUX_LED2; scu_grp_pin_t PINMUX_LED3; -#if defined(RAD1O) || defined(PRALINE) +#if defined(RAD1O) || defined(PRALINE) || defined(UNIVERSAL) scu_grp_pin_t PINMUX_LED4; #endif - /* Power Supply PinMux */ scu_grp_pin_t PINMUX_EN1V8; scu_grp_pin_t PINMUX_EN1V2; -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) scu_grp_pin_t PINMUX_EN3V3_AUX_N; scu_grp_pin_t PINMUX_EN3V3_OC_N; #endif @@ -53,7 +52,7 @@ typedef struct { /* GPIO Input PinMux */ scu_grp_pin_t PINMUX_BOOT0; scu_grp_pin_t PINMUX_BOOT1; -#if !defined(HACKRF_ONE) +#if !defined(HACKRF_ONE) || defined(UNIVERSAL) scu_grp_pin_t PINMUX_BOOT2; scu_grp_pin_t PINMUX_BOOT3; #endif @@ -76,16 +75,15 @@ typedef struct { scu_grp_pin_t SSP1_CS; /* CPLD JTAG interface */ -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) scu_grp_pin_t PINMUX_FPGA_CRESET; scu_grp_pin_t PINMUX_FPGA_CDONE; scu_grp_pin_t PINMUX_FPGA_SPI_CS; -#else +#endif scu_grp_pin_t PINMUX_CPLD_TDO; + scu_grp_pin_t PINMUX_CPLD_TCK; scu_grp_pin_t PINMUX_CPLD_TMS; scu_grp_pin_t PINMUX_CPLD_TDI; -#endif - scu_grp_pin_t PINMUX_CPLD_TCK; /* CPLD SGPIO interface */ scu_grp_pin_t PINMUX_SGPIO0; @@ -121,36 +119,45 @@ typedef struct { scu_grp_pin_t TRIGGER_EN; /* MAX283x GPIO (XCVR_CTL) PinMux */ - scu_grp_pin_t XCVR_RXHP; // RAD1O, PRALINE - scu_grp_pin_t XCVR_B6; // RAD1O - scu_grp_pin_t XCVR_B7; // RAD1O - scu_grp_pin_t XCVR_ENABLE; // PRALINE, HACKRF_ONE - scu_grp_pin_t XCVR_RXENABLE; // PRALINE, HACKRF_ONE - scu_grp_pin_t XCVR_CS; // PRALINE, HACKRF_ONE - scu_grp_pin_t XCVR_LD; // PRALINE - uint32_t XCVR_ENABLE_PINCFG; // PRALINE, HACKRF_ONE - uint32_t XCVR_RXENABLE_PINCFG; // PRALINE, HACKRF_ONE - uint32_t XCVR_CS_PINCFG; // PRALINE, HACKRF_ONE - uint32_t XCVR_RXHP_PINCFG; // PRALINE - uint32_t XCVR_LD_PINCFG; // PRALINE - scu_grp_pin_t XCVR_TXENABLE; // HACKRF_ONE - uint32_t XCVR_TXENABLE_PINCFG; // HACKRF_ONE + scu_grp_pin_t XCVR_ENABLE; + scu_grp_pin_t XCVR_RXENABLE; + scu_grp_pin_t XCVR_TXENABLE; + scu_grp_pin_t XCVR_CS; + uint32_t XCVR_ENABLE_PINCFG; + uint32_t XCVR_RXENABLE_PINCFG; + uint32_t XCVR_TXENABLE_PINCFG; + uint32_t XCVR_CS_PINCFG; +#if defined(PRALINE) || defined(UNIVERSAL) + scu_grp_pin_t XCVR_LD; + uint32_t XCVR_LD_PINCFG; + uint32_t XCVR_RXHP_PINCFG; +#endif +#if defined(RAD1O) || defined(PRALINE) || defined(UNIVERSAL) + scu_grp_pin_t XCVR_RXHP; +#endif +#if defined(RAD1O) + scu_grp_pin_t XCVR_B6; + scu_grp_pin_t XCVR_B7; +#endif /* MAX5864 SPI chip select (AD_CS) GPIO PinMux */ scu_grp_pin_t AD_CS; scu_grp_pin_t AD_CS_PINCFG; /* RFFC5071 GPIO serial interface PinMux */ +#if !defined(RAD1O) scu_grp_pin_t MIXER_ENX; scu_grp_pin_t MIXER_SCLK; scu_grp_pin_t MIXER_SDATA; scu_grp_pin_t MIXER_RESETX; uint32_t MIXER_SCLK_PINCFG; uint32_t MIXER_SDATA_PINCFG; -#if defined(PRALINE) +#endif +#if defined(PRALINE) || defined(UNIVERSAL) scu_grp_pin_t MIXER_LD; uint32_t MIXER_LD_PINCFG; -#elif defined(RAD1O) +#endif +#if defined(RAD1O) scu_grp_pin_t VCO_CE; scu_grp_pin_t VCO_SCLK; scu_grp_pin_t VCO_SDATA; @@ -166,9 +173,10 @@ typedef struct { #endif /* RF supply (VAA) control */ -#if defined(PRALINE) || defined(HACKRF_ONE) +#if defined(PRALINE) || defined(HACKRF_ONE) || defined(UNIVERSAL) scu_grp_pin_t NO_VAA_ENABLE; -#elif defined(RAD1O) +#endif +#if defined(RAD1O) scu_grp_pin_t VAA_ENABLE; #endif @@ -181,7 +189,7 @@ typedef struct { scu_grp_pin_t FLASH_WP; /* RF switch control */ -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) scu_grp_pin_t TX_EN; scu_grp_pin_t MIX_EN_N; scu_grp_pin_t MIX_EN_N_R1_0; @@ -189,7 +197,8 @@ typedef struct { scu_grp_pin_t RF_AMP_EN; scu_grp_pin_t ANT_BIAS_EN_N; scu_grp_pin_t ANT_BIAS_OC_N; -#elif defined(HACKRF_ONE) +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) scu_grp_pin_t HP; scu_grp_pin_t LP; scu_grp_pin_t TX_MIX_BP; @@ -203,7 +212,8 @@ typedef struct { scu_grp_pin_t AMP_BYPASS; scu_grp_pin_t RX_AMP; scu_grp_pin_t NO_RX_AMP_PWR; -#elif defined(RAD1O) +#endif +#if defined(RAD1O) scu_grp_pin_t BY_AMP; scu_grp_pin_t BY_AMP_N; scu_grp_pin_t TX_RX; @@ -217,7 +227,7 @@ typedef struct { #endif /* Praline */ -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) scu_grp_pin_t P2_CTRL0; scu_grp_pin_t P2_CTRL1; scu_grp_pin_t P1_CTRL0; @@ -242,7 +252,7 @@ typedef struct { #endif /* HackRF One r9 */ -#if defined(HACKRF_ONE) +#if defined(HACKRF_ONE) || defined(UNIVERSAL) scu_grp_pin_t H1R9_CLKIN_EN; scu_grp_pin_t H1R9_CLKOUT_EN; scu_grp_pin_t H1R9_MCU_CLK_EN; @@ -262,9 +272,7 @@ typedef struct { scu_grp_pin_t PINMUX_PP_D5; scu_grp_pin_t PINMUX_PP_D6; scu_grp_pin_t PINMUX_PP_D7; - /* TODO add other Pins */ - scu_grp_pin_t PINMUX_GPIO3_8; scu_grp_pin_t PINMUX_GPIO3_9; scu_grp_pin_t PINMUX_GPIO3_10; From d0ac3183f597974b13daf2c5e81dfb9520c5cf25 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 3 Apr 2026 21:37:14 +0100 Subject: [PATCH 110/238] Universalize: cpld_jtag.{c,h} Co-authored-by: Antoine van Gelder --- firmware/common/cpld_jtag.c | 85 ++++++++++++++++++++++++++----------- firmware/common/cpld_jtag.h | 4 +- 2 files changed, 62 insertions(+), 27 deletions(-) diff --git a/firmware/common/cpld_jtag.c b/firmware/common/cpld_jtag.c index 4ef9ce5d..21991db0 100644 --- a/firmware/common/cpld_jtag.c +++ b/firmware/common/cpld_jtag.c @@ -19,16 +19,17 @@ * Boston, MA 02110-1301, USA. */ -#if !defined(PRALINE) +#if !defined(PRALINE) || defined(UNIVERSAL) #include #endif #include "cpld_jtag.h" -#if !defined(PRALINE) +#include "platform_detect.h" +#if !defined(PRALINE) || defined(UNIVERSAL) #include "xapp058/micro.h" #endif -#ifndef PRALINE +#if !defined(PRALINE) || defined(UNIVERSAL) static refill_buffer_cb refill_buffer; static uint32_t xsvf_buffer_len, xsvf_pos; static unsigned char* xsvf_buffer; @@ -38,52 +39,86 @@ void cpld_jtag_take(jtag_t* const jtag) { const jtag_gpio_t* const gpio = jtag->gpio; + board_id_t board_id = detected_platform(); + /* Set initial GPIO state to the voltages of the internal or external pull-ups/downs, * to avoid any glitches. */ -#if (defined HACKRF_ONE || defined PRALINE) - gpio_set(gpio->gpio_pp_tms); + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + case BOARD_ID_PRALINE: +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + gpio_set(gpio->gpio_pp_tms); #endif + break; + default: + break; + } gpio_clear(gpio->gpio_tck); -#ifndef PRALINE - gpio_set(gpio->gpio_tms); - gpio_set(gpio->gpio_tdi); + if (board_id != BOARD_ID_PRALINE) { +#if !defined(PRALINE) || defined(UNIVERSAL) + gpio_set(gpio->gpio_tms); + gpio_set(gpio->gpio_tdi); #endif + } -#if (defined HACKRF_ONE || defined PRALINE) - /* Do not drive PortaPack-specific TMS pin initially, just to be cautious. */ - gpio_input(gpio->gpio_pp_tms); - gpio_input(gpio->gpio_pp_tdo); + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + case BOARD_ID_PRALINE: +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + /* Do not drive PortaPack-specific TMS pin initially, just to be cautious. */ + gpio_input(gpio->gpio_pp_tms); + gpio_input(gpio->gpio_pp_tdo); #endif + break; + default: + break; + } gpio_output(gpio->gpio_tck); -#ifndef PRALINE - gpio_output(gpio->gpio_tms); - gpio_output(gpio->gpio_tdi); - gpio_input(gpio->gpio_tdo); + if (board_id != BOARD_ID_PRALINE) { +#if !defined(PRALINE) || defined(UNIVERSAL) + gpio_output(gpio->gpio_tms); + gpio_output(gpio->gpio_tdi); + gpio_input(gpio->gpio_tdo); #endif + } } void cpld_jtag_release(jtag_t* const jtag) { const jtag_gpio_t* const gpio = jtag->gpio; + board_id_t board_id = detected_platform(); + /* Make all pins inputs when JTAG interface not active. * Let the pull-ups/downs do the work. */ -#if (defined HACKRF_ONE || defined PRALINE) - /* Do not drive PortaPack-specific pins, initially, just to be cautious. */ - gpio_input(gpio->gpio_pp_tms); - gpio_input(gpio->gpio_pp_tdo); + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + case BOARD_ID_PRALINE: +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + /* Do not drive PortaPack-specific pins, initially, just to be cautious. */ + gpio_input(gpio->gpio_pp_tms); + gpio_input(gpio->gpio_pp_tdo); #endif + break; + default: + break; + } gpio_input(gpio->gpio_tck); -#ifndef PRALINE - gpio_input(gpio->gpio_tms); - gpio_input(gpio->gpio_tdi); - gpio_input(gpio->gpio_tdo); + if (board_id != BOARD_ID_PRALINE) { +#if !defined(PRALINE) || defined(UNIVERSAL) + gpio_input(gpio->gpio_tms); + gpio_input(gpio->gpio_tdi); + gpio_input(gpio->gpio_tdo); #endif + } } -#ifndef PRALINE +#if !defined(PRALINE) || defined(UNIVERSAL) /* return 0 if success else return error code see xsvfExecute() */ int cpld_jtag_program( jtag_t* const jtag, diff --git a/firmware/common/cpld_jtag.h b/firmware/common/cpld_jtag.h index 60036759..939e5d94 100644 --- a/firmware/common/cpld_jtag.h +++ b/firmware/common/cpld_jtag.h @@ -27,12 +27,12 @@ typedef struct { gpio_t gpio_tck; -#ifndef PRALINE +#if !defined(PRALINE) || defined(UNIVERSAL) gpio_t gpio_tms; gpio_t gpio_tdi; gpio_t gpio_tdo; #endif -#if (defined HACKRF_ONE || defined PRALINE) +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) gpio_t gpio_pp_tms; gpio_t gpio_pp_tdo; #endif From 8d4570d2cbc6e820da9381865402414713e08f53 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 3 Apr 2026 21:39:02 +0100 Subject: [PATCH 111/238] Universalize: max283x.{c,h} Co-authored-by: Antoine van Gelder --- firmware/common/max283x.c | 270 ++++++++++++++++++++++---------------- firmware/common/max283x.h | 21 ++- firmware/common/rf_path.c | 8 +- 3 files changed, 181 insertions(+), 118 deletions(-) diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index c0e912e5..54b596bc 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -29,31 +29,36 @@ #include "fixed_point.h" #include "platform_gpio.h" #include "spi_bus.h" -#if defined(PRALINE) - #include "max2831.h" + +#if defined(PRALINE) || defined(UNIVERSAL) #include "max2831_target.h" -#else - #include "max2837.h" +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) #include "max2837_target.h" - #include "max2839.h" +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) #include "max2839_target.h" #endif extern spi_bus_t spi_bus_ssp1; -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) max2831_driver_t max2831 = { .bus = &spi_bus_ssp1, .target_init = max2831_target_init, .set_mode = max2831_target_set_mode, }; -#else +#endif + +#if !defined(PRALINE) || defined(UNIVERSAL) max2837_driver_t max2837 = { .bus = &spi_bus_ssp1, .target_init = max2837_target_init, .set_mode = max2837_target_set_mode, }; +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) max2839_driver_t max2839 = { .bus = &spi_bus_ssp1, .target_init = max2839_target_init, @@ -69,36 +74,43 @@ void max283x_setup(max283x_driver_t* const drv, max283x_variant_t type) const platform_gpio_t* gpio = platform_gpio(); /* MAX283x GPIO PinMux */ -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) max2831.gpio_enable = gpio->max283x_enable; max2831.gpio_rxtx = gpio->max283x_rx_enable; max2831.gpio_rxhp = gpio->max2831_rxhp; max2831.gpio_ld = gpio->max2831_ld; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) max2837.gpio_enable = gpio->max283x_enable; max2837.gpio_rx_enable = gpio->max283x_rx_enable; max2837.gpio_tx_enable = gpio->max283x_tx_enable; +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) max2839.gpio_enable = gpio->max283x_enable; max2839.gpio_rxtx = gpio->max283x_rx_enable; #endif - switch (type) { -#ifdef PRALINE + switch (drv->type) { +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: memcpy(&drv->drv.max2831, &max2831, sizeof(max2831)); max2831_setup(&drv->drv.max2831); break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: memcpy(&drv->drv.max2837, &max2837, sizeof(max2837)); max2837_setup(&drv->drv.max2837); break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: memcpy(&drv->drv.max2839, &max2839, sizeof(max2839)); max2839_setup(&drv->drv.max2839); break; #endif + default: + break; } } @@ -106,44 +118,42 @@ void max283x_setup(max283x_driver_t* const drv, max283x_variant_t type) uint16_t max283x_num_regs(max283x_driver_t* const drv) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: return MAX2831_NUM_REGS; - break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: return MAX2837_NUM_REGS; - break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: return MAX2839_NUM_REGS; - break; #endif + default: + return 0; } - - return 0; } /* Returns the maximum data register value supported by the driver. */ uint16_t max283x_data_regs_max_value(max283x_driver_t* const drv) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: return MAX2831_DATA_REGS_MAX_VALUE; - break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: return MAX2837_DATA_REGS_MAX_VALUE; - break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: return MAX2839_DATA_REGS_MAX_VALUE; - break; #endif + default: + return 0; } - - return 0; } /* Read a register via SPI. Save a copy to memory and return @@ -151,22 +161,21 @@ uint16_t max283x_data_regs_max_value(max283x_driver_t* const drv) uint16_t max283x_reg_read(max283x_driver_t* const drv, uint8_t r) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: return max2831_reg_read(&drv->drv.max2831, r); - break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: return max2837_reg_read(&drv->drv.max2837, r); - break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: return max2839_reg_read(&drv->drv.max2839, r); - break; #endif + default: + return 0; } - - return 0; } /* Write value to register via SPI and save a copy to memory. Mark @@ -174,19 +183,23 @@ uint16_t max283x_reg_read(max283x_driver_t* const drv, uint8_t r) void max283x_reg_write(max283x_driver_t* const drv, uint8_t r, uint16_t v) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: max2831_reg_write(&drv->drv.max2831, r, v); break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: max2837_reg_write(&drv->drv.max2837, r, v); break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: max2839_reg_write(&drv->drv.max2839, r, v); break; #endif + default: + break; } } @@ -196,97 +209,113 @@ void max283x_reg_write(max283x_driver_t* const drv, uint8_t r, uint16_t v) void max283x_regs_commit(max283x_driver_t* const drv) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: max2831_regs_commit(&drv->drv.max2831); break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: max2837_regs_commit(&drv->drv.max2837); break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: max2839_regs_commit(&drv->drv.max2839); break; #endif + default: + break; } } void max283x_set_mode(max283x_driver_t* const drv, const max283x_mode_t new_mode) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: max2831_set_mode(&drv->drv.max2831, (max2831_mode_t) new_mode); break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: max2837_set_mode(&drv->drv.max2837, (max2837_mode_t) new_mode); break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: max2839_set_mode(&drv->drv.max2839, (max2839_mode_t) new_mode); break; #endif + default: + break; } } max283x_mode_t max283x_mode(max283x_driver_t* const drv) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: return (max283x_mode_t) max2831_mode(&drv->drv.max2831); - break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: return (max283x_mode_t) max2837_mode(&drv->drv.max2837); - break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: return (max283x_mode_t) max2839_mode(&drv->drv.max2839); - break; #endif + default: + return 0; } - return 0; } /* Turn on/off all chip functions. Does not control oscillator and CLKOUT */ void max283x_start(max283x_driver_t* const drv) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: max2831_start(&drv->drv.max2831); break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: max2837_start(&drv->drv.max2837); break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: max2839_start(&drv->drv.max2839); break; #endif + default: + break; } } void max283x_stop(max283x_driver_t* const drv) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: max2831_stop(&drv->drv.max2831); break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: max2837_stop(&drv->drv.max2837); break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: max2839_stop(&drv->drv.max2839); break; #endif + default: + break; } } @@ -297,19 +326,23 @@ fp_40_24_t max283x_set_frequency( bool program) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: return max2831_set_frequency(&drv->drv.max2831, freq, program); break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: return max2837_set_frequency(&drv->drv.max2837, freq, program); break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: return max2839_set_frequency(&drv->drv.max2839, freq, program); break; #endif + default: + break; } return 0; } @@ -324,189 +357,206 @@ uint32_t max283x_set_lpf_bandwidth( #endif switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: return max2831_set_lpf_bandwidth( &drv->drv.max2831, (max2831_mode_t) mode, bandwidth_hz); - break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: return max2837_set_lpf_bandwidth(&drv->drv.max2837, bandwidth_hz); - break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: return max2839_set_lpf_bandwidth(&drv->drv.max2839, bandwidth_hz); - break; #endif + default: + return 0; } - - return 0; } bool max283x_set_lna_gain(max283x_driver_t* const drv, const uint32_t gain_db) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: return max2831_set_lna_gain(&drv->drv.max2831, gain_db); - break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: return max2837_set_lna_gain(&drv->drv.max2837, gain_db); - break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: return max2839_set_lna_gain(&drv->drv.max2839, gain_db); - break; #endif + default: + return false; } - - return false; } bool max283x_set_vga_gain(max283x_driver_t* const drv, const uint32_t gain_db) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: return max2831_set_vga_gain(&drv->drv.max2831, gain_db); - break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: return max2837_set_vga_gain(&drv->drv.max2837, gain_db); - break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: return max2839_set_vga_gain(&drv->drv.max2839, gain_db); - break; #endif + default: + return false; } - - return false; } bool max283x_set_txvga_gain(max283x_driver_t* const drv, const uint32_t gain_db) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: return max2831_set_txvga_gain(&drv->drv.max2831, gain_db); - break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: return max2837_set_txvga_gain(&drv->drv.max2837, gain_db); - break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: return max2839_set_txvga_gain(&drv->drv.max2839, gain_db); - break; #endif + default: + return false; } - - return false; } void max283x_tx(max283x_driver_t* const drv) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: max2831_tx(&drv->drv.max2831); break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: max2837_tx(&drv->drv.max2837); break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: max2839_tx(&drv->drv.max2839); break; #endif + default: + break; } } void max283x_rx(max283x_driver_t* const drv) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: max2831_rx(&drv->drv.max2831); break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: max2837_rx(&drv->drv.max2837); break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: max2839_rx(&drv->drv.max2839); break; #endif + default: + break; } } +/* Set MAX2831 receiver high-pass filter corner frequency in Hz */ void max283x_set_rx_hpf_frequency( max283x_driver_t* const drv, const max283x_rx_hpf_freq_t freq) { -#ifndef PRALINE +#if !defined(PRALINE) (void) freq; #endif switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: max2831_set_rx_hpf_frequency( &drv->drv.max2831, (max2831_rx_hpf_freq_t) freq); break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: // unsupported break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: // unsupported break; #endif + default: + break; } } void max283x_tx_calibration(max283x_driver_t* const drv) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: max2831_tx_calibration(&drv->drv.max2831); break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: // unsupported - use max283x_set_mode instead break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: // unsupported - use max283x_set_mode instead break; #endif + default: + break; } } void max283x_rx_calibration(max283x_driver_t* const drv) { switch (drv->type) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case MAX2831_VARIANT: max2831_rx_calibration(&drv->drv.max2831); break; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) case MAX2837_VARIANT: // unsupported - use max283x_set_mode instead break; - +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) case MAX2839_VARIANT: // unsupported - use max283x_set_mode instead break; #endif + default: + break; } } diff --git a/firmware/common/max283x.h b/firmware/common/max283x.h index db5a93f8..87da59b4 100644 --- a/firmware/common/max283x.h +++ b/firmware/common/max283x.h @@ -27,10 +27,13 @@ #include #include "fixed_point.h" -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) #include "max2831.h" -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) #include "max2837.h" +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) #include "max2839.h" #endif @@ -52,10 +55,13 @@ typedef enum { } max283x_rx_hpf_freq_t; typedef enum { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) MAX2831_VARIANT, -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) MAX2837_VARIANT, +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) MAX2839_VARIANT, #endif } max283x_variant_t; @@ -64,10 +70,13 @@ typedef struct { max283x_variant_t type; union { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) max2831_driver_t max2831; -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) max2837_driver_t max2837; +#endif +#if defined(HACKRF_ONE) || defined(UNIVERSAL) max2839_driver_t max2839; #endif } drv; diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 4407960a..bce921ea 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -31,7 +31,9 @@ #include "max283x.h" #include "max5864.h" #include "mixer.h" -#include "platform_detect.h" +#if defined(HACKRF_ONE) || defined(PRALINE) + #include "platform_detect.h" +#endif #if defined(HACKRF_ONE) || defined(RAD1O) || defined(PRALINE) #include "platform_scu.h" #endif @@ -441,12 +443,14 @@ void rf_path_init(rf_path_t* const rf_path) ssp1_set_mode_max283x(); #ifdef PRALINE max283x_setup(&max283x, MAX2831_VARIANT); -#else +#elif defined(HACKRF_ONE) if (detected_platform() == BOARD_ID_HACKRF1_R9) { max283x_setup(&max283x, MAX2839_VARIANT); } else { max283x_setup(&max283x, MAX2837_VARIANT); } +#else + max283x_setup(&max283x, MAX2837_VARIANT); #endif max283x_start(&max283x); From c913e81ed619703a62d06de302166c2ec9fbce2d Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 3 Apr 2026 22:00:17 +0100 Subject: [PATCH 112/238] Universalize: rffc5071.{c,h} Co-authored-by: Antoine van Gelder --- firmware/common/rffc5071.c | 59 +++++++++++++++++++++++++++----------- firmware/common/rffc5071.h | 4 +-- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index ffe958c1..89befe98 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -35,16 +35,17 @@ #include #include -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) #include #endif #include "delay.h" #include "fixed_point.h" +#include "platform_detect.h" #include "rffc5071.h" #include "rffc5071_regs.def" // private register def macros #include "selftest.h" -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) #include "platform_scu.h" #endif @@ -109,15 +110,19 @@ void rffc5071_init(rffc5071_driver_t* const drv) */ void rffc5071_setup(rffc5071_driver_t* const drv) { + board_id_t board_id = detected_platform(); + gpio_set(drv->gpio_reset); gpio_output(drv->gpio_reset); -#ifdef PRALINE - /* Configure mixer PLL lock detect pin */ - const platform_scu_t* scu = platform_scu(); - scu_pinmux(scu->MIXER_LD, scu->MIXER_LD_PINCFG); - gpio_input(drv->gpio_ld); + if (board_id == BOARD_ID_PRALINE) { +#if defined(PRALINE) || defined(UNIVERSAL) + /* Configure mixer PLL lock detect pin */ + const platform_scu_t* scu = platform_scu(); + scu_pinmux(scu->MIXER_LD, scu->MIXER_LD_PINCFG); + gpio_input(drv->gpio_ld); #endif + } rffc5071_init(drv); @@ -135,10 +140,16 @@ void rffc5071_setup(rffc5071_driver_t* const drv) set_RFFC5071_FULLD(drv, 0); set_RFFC5071_MODE(drv, 1); -#if defined(PRALINE) || defined(HACKRF_ONE) - /* Enable GPO Lock output signal */ - set_RFFC5071_LOCK(drv, 1); -#endif + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + case BOARD_ID_PRALINE: + /* Enable GPO Lock output signal */ + set_RFFC5071_LOCK(drv, 1); + break; + default: + break; + } /* Enable reference oscillator standby */ set_RFFC5071_REFST(drv, 1); @@ -181,13 +192,17 @@ void rffc5071_lock_test(rffc5071_driver_t* const drv) bool rffc5071_check_lock(rffc5071_driver_t* const drv) { -#ifdef PRALINE - return gpio_read(drv->gpio_ld); + if (detected_platform() == BOARD_ID_PRALINE) { +#if defined(PRALINE) || defined(UNIVERSAL) + return gpio_read(drv->gpio_ld); #else - set_RFFC5071_READSEL(drv, 0b0001); - rffc5071_regs_commit(drv); - return !!(rffc5071_reg_read(drv, RFFC5071_READBACK_REG) & 0x8000); + return false; #endif + } else { + set_RFFC5071_READSEL(drv, 0b0001); + rffc5071_regs_commit(drv); + return !!(rffc5071_reg_read(drv, RFFC5071_READBACK_REG) & 0x8000); + } } static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) @@ -360,9 +375,17 @@ void rffc5071_set_gpo(rffc5071_driver_t* const drv, uint8_t gpo) rffc5071_regs_commit(drv); } -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) bool rffc5071_poll_ld(rffc5071_driver_t* const drv, uint8_t* prelock_state) { + // This is only supported on Praline hardware. + // + // For all other boards we'll just return true to avoid a situation where a + // a caller is waiting for a lock signal that will never be detected. + if (detected_platform() != BOARD_ID_PRALINE) { + return true; + } + // The RFFC5072 can be configured to output PLL lock status on // GPO4. The lock detect signal is produced by a window detector // on the VCO tuning voltage. It goes high to show PLL lock when @@ -428,7 +451,9 @@ bool rffc5071_poll_ld(rffc5071_driver_t* const drv, uint8_t* prelock_state) uint8_t rsm_state = (rb >> 11) & 0b11111; // get gpo4 lock detect signal + #if defined(PRALINE) || defined(UNIVERSAL) bool gpo4_ld = gpio_read(drv->gpio_ld); + #endif // parse state switch (rsm_state) { diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index 41e0509d..6a0c4ce2 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -35,7 +35,7 @@ typedef struct { spi_bus_t* const bus; gpio_t gpio_reset; -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) gpio_t gpio_ld; #endif uint16_t regs[RFFC5071_NUM_REGS]; @@ -70,7 +70,7 @@ extern void rffc5071_enable(rffc5071_driver_t* const drv); extern void rffc5071_disable(rffc5071_driver_t* const drv); extern void rffc5071_set_gpo(rffc5071_driver_t* const drv, uint8_t); -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) extern bool rffc5071_poll_ld(rffc5071_driver_t* const drv, uint8_t* prelock_state); #endif extern bool rffc5071_check_lock(rffc5071_driver_t* const drv); From cfd729597c883a2ec5917852c33bf7b2df5d4e35 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 3 Apr 2026 22:04:35 +0100 Subject: [PATCH 113/238] Universalize: si5351.c Co-authored-by: Antoine van Gelder --- firmware/common/si5351c.c | 119 ++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 55 deletions(-) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index ceb9f4a9..b50aad81 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -23,7 +23,7 @@ #include #include -#if defined(HACKRF_ONE) +#if defined(HACKRF_ONE) || defined(UNIVERSAL) #include #endif @@ -32,7 +32,7 @@ #include "platform_detect.h" #include "selftest.h" #include "si5351c.h" -#if defined(HACKRF_ONE) +#if defined(HACKRF_ONE) || defined(UNIVERSAL) #include "gpio.h" #include "platform_gpio.h" #include "platform_scu.h" @@ -235,6 +235,7 @@ void si5351c_configure_multisynth( void si5351c_configure_clock_control(si5351c_driver_t* const drv) { uint8_t clkout_ctrl; + board_id_t board_id = detected_platform(); if (clkout_enabled) { clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | @@ -269,7 +270,8 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv) SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /* not connected, but: PLL B int mode */ }; - if (detected_platform() == BOARD_ID_HACKRF1_R9) { + if (board_id == BOARD_ID_HACKRF1_R9) { +#if defined(HACKRF_ONE) || defined(UNIVERSAL) data[1] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA); @@ -280,37 +282,41 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv) data[4] = SI5351C_CLK_POWERDOWN; data[5] = SI5351C_CLK_POWERDOWN; data[6] = SI5351C_CLK_POWERDOWN; +#endif } -#ifdef PRALINE - /* CLK0: AFE_CLK */ - data[1] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA); - /* CLK1: SCT_CLK and FPGA_CLK */ - data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA); - /* CLK3: CLKOUT */ - clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA); - /* CLK4: XCVR_CLK */ - data[5] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA) | SI5351C_CLK_INV; - data[6] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA); - if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { - /* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */ - data[3] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | + if (board_id == BOARD_ID_PRALINE) { +#if defined(PRALINE) || defined(UNIVERSAL) + /* CLK0: AFE_CLK */ + data[1] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | + SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | + SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA); + /* CLK1: SCT_CLK and FPGA_CLK */ + data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA); - } else { - /* CLK2: MCU_CLK */ - data[3] = SI5351C_CLK_POWERDOWN; - } + /* CLK3: CLKOUT */ + clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) | + SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | + SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA); + /* CLK4: XCVR_CLK */ + data[5] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) | + SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | + SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA) | SI5351C_CLK_INV; + data[6] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) | + SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | + SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA); + if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { + /* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */ + data[3] = SI5351C_CLK_FRAC_MODE | + SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | + SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | + SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA); + } else { + /* CLK2: MCU_CLK */ + data[3] = SI5351C_CLK_POWERDOWN; + } #endif + } si5351c_write(drv, data, sizeof(data)); } @@ -325,30 +331,34 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) /* 7: Clock to CPU is deactivated as it is not used and creates noise */ /* 3: External clock output is deactivated by default */ -#ifndef PRALINE - uint8_t value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | - SI5351C_CLK_ENABLE(2) | SI5351C_CLK_ENABLE(4) | SI5351C_CLK_ENABLE(5) | - SI5351C_CLK_DISABLE(6) | SI5351C_CLK_DISABLE(7); -#else - uint8_t value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | - SI5351C_CLK_ENABLE(4) | SI5351C_CLK_ENABLE(5) | SI5351C_CLK_DISABLE(6) | - SI5351C_CLK_DISABLE(7); - if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { - /* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */ - value |= SI5351C_CLK_ENABLE(2); - } else { - value |= SI5351C_CLK_DISABLE(2); - } -#endif + board_id_t board_id = detected_platform(); uint8_t clkout = 3; + uint8_t value; - /* HackRF One r9 has only three clock generator outputs. */ - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - clkout = 2; + if (board_id == BOARD_ID_PRALINE) { value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | - SI5351C_CLK_DISABLE(3) | SI5351C_CLK_DISABLE(4) | - SI5351C_CLK_DISABLE(5) | SI5351C_CLK_DISABLE(6) | + SI5351C_CLK_ENABLE(4) | SI5351C_CLK_ENABLE(5) | + SI5351C_CLK_DISABLE(6) | SI5351C_CLK_DISABLE(7); + if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { + /* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */ + value |= SI5351C_CLK_ENABLE(2); + } else { + value |= SI5351C_CLK_DISABLE(2); + } + } else { + value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | + SI5351C_CLK_ENABLE(2) | SI5351C_CLK_ENABLE(4) | + SI5351C_CLK_ENABLE(5) | SI5351C_CLK_DISABLE(6) | SI5351C_CLK_DISABLE(7); + + /* HackRF One r9 has only three clock generator outputs. */ + if (board_id == BOARD_ID_HACKRF1_R9) { + clkout = 2; + value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | + SI5351C_CLK_DISABLE(3) | SI5351C_CLK_DISABLE(4) | + SI5351C_CLK_DISABLE(5) | SI5351C_CLK_DISABLE(6) | + SI5351C_CLK_DISABLE(7); + } } value |= (clkout_enabled) ? SI5351C_CLK_ENABLE(clkout) : @@ -357,16 +367,16 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) si5351c_write(drv, data, sizeof(data)); outputs_disabled = value; -#if defined(HACKRF_ONE) if (detected_platform() == BOARD_ID_HACKRF1_R9) { +#if defined(HACKRF_ONE) || defined(UNIVERSAL) const platform_gpio_t* gpio = platform_gpio(); if (clkout_enabled) { gpio_set(gpio->h1r9_clkout_en); } else { gpio_clear(gpio->h1r9_clkout_en); } - } #endif + } } void si5351c_set_int_mode( @@ -466,8 +476,8 @@ void si5351c_init(si5351c_driver_t* const drv) selftest.report.pass = false; } -#if defined(HACKRF_ONE) if (detected_platform() == BOARD_ID_HACKRF1_R9) { +#if defined(HACKRF_ONE) || defined(UNIVERSAL) const platform_gpio_t* gpio = platform_gpio(); const platform_scu_t* scu = platform_scu(); @@ -485,9 +495,8 @@ void si5351c_init(si5351c_driver_t* const drv) scu_pinmux(scu->H1R9_MCU_CLK_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); gpio_clear(gpio->h1r9_mcu_clk_en); gpio_output(gpio->h1r9_mcu_clk_en); - } #endif - (void) drv; + } } /* From cdc17d5e6791b918e4f0afa0f0eaa44334e9bbf1 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 3 Apr 2026 22:05:13 +0100 Subject: [PATCH 114/238] Universalize: rf_path.{c,h} Co-authored-by: Antoine van Gelder --- firmware/common/rf_path.c | 354 ++++++++++++++++++++++---------------- firmware/common/rf_path.h | 77 +++++---- 2 files changed, 243 insertions(+), 188 deletions(-) diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index bce921ea..a361f442 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -23,7 +23,7 @@ #include "rf_path.h" -#if defined(HACKRF_ONE) || defined(RAD1O) || defined(PRALINE) +#if !defined(JAWBREAKER) #include #endif @@ -31,10 +31,8 @@ #include "max283x.h" #include "max5864.h" #include "mixer.h" -#if defined(HACKRF_ONE) || defined(PRALINE) - #include "platform_detect.h" -#endif -#if defined(HACKRF_ONE) || defined(RAD1O) || defined(PRALINE) +#include "platform_detect.h" +#if !defined(JAWBREAKER) #include "platform_scu.h" #endif @@ -94,17 +92,18 @@ #define SWITCHCTRL_ANT_PWR (1 << 6) /* turn on antenna port power */ -#ifdef HACKRF_ONE - +#if defined(HACKRF_ONE) || defined(UNIVERSAL) static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) { + board_id_t board_id = detected_platform(); + if (ctrl & SWITCHCTRL_TX) { - if (detected_platform() != BOARD_ID_HACKRF1_R9) { + if (board_id != BOARD_ID_HACKRF1_R9) { gpio_set(rf_path->gpio_tx); } gpio_clear(rf_path->gpio_rx); } else { - if (detected_platform() != BOARD_ID_HACKRF1_R9) { + if (board_id != BOARD_ID_HACKRF1_R9) { gpio_clear(rf_path->gpio_tx); } gpio_set(rf_path->gpio_rx); @@ -167,7 +166,7 @@ static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) gpio_set(rf_path->gpio_no_rx_amp_pwr); } - if (detected_platform() == BOARD_ID_HACKRF1_R9) { + if (board_id == BOARD_ID_HACKRF1_R9) { if (ctrl & SWITCHCTRL_ANT_PWR) { gpio_clear(rf_path->gpio_h1r9_no_ant_pwr); } else { @@ -187,7 +186,7 @@ static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) } #endif -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) static void switchctrl_set_praline(rf_path_t* const rf_path, uint8_t ctrl) { if (ctrl & SWITCHCTRL_TX) { @@ -228,7 +227,7 @@ static void switchctrl_set_praline(rf_path_t* const rf_path, uint8_t ctrl) } #endif -#ifdef RAD1O +#if defined(RAD1O) static void switchctrl_set_rad1o(rf_path_t* const rf_path, uint8_t ctrl) { if (ctrl & SWITCHCTRL_TX) { @@ -295,169 +294,220 @@ static void switchctrl_set_rad1o(rf_path_t* const rf_path, uint8_t ctrl) static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) { -#ifdef JAWBREAKER - (void) rf_path; /* silence unused param warning */ - mixer_set_gpo(&mixer, gpo); -#elif HACKRF_ONE - switchctrl_set_hackrf_one(rf_path, gpo); -#elif PRALINE - switchctrl_set_praline(rf_path, gpo); -#elif RAD1O - switchctrl_set_rad1o(rf_path, gpo); -#else - (void) gpo; +#if defined(JAWBREAKER) + (void) rf_path; #endif + + switch (detected_platform()) { + case BOARD_ID_JAWBREAKER: +#if defined(JAWBREAKER) + mixer_set_gpo(&mixer, gpo); +#endif + break; + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + switchctrl_set_hackrf_one(rf_path, gpo); +#endif + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + switchctrl_set_praline(rf_path, gpo); +#endif + break; + case BOARD_ID_RAD1O: +#if defined(RAD1O) + switchctrl_set_rad1o(rf_path, gpo); +#endif + break; + default: + break; + } } void rf_path_pin_setup(rf_path_t* const rf_path) { +#if defined(JAWBREAKER) + (void) rf_path; +#endif + + board_id_t board_id = detected_platform(); #if !defined(JAWBREAKER) const platform_scu_t* scu = platform_scu(); #endif -#ifdef HACKRF_ONE - /* Configure RF switch control signals */ - // clang-format off - scu_pinmux(scu->HP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->LP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->TX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->NO_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->RX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu_pinmux(scu->NO_TX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->AMP_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->RX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - // clang-format on - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - scu_pinmux(scu->H1R9_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->H1R9_NO_ANT_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - gpio_clear(rf_path->gpio_h1r9_no_ant_pwr); - gpio_output(rf_path->gpio_h1r9_no_ant_pwr); - scu_pinmux(scu->H1R9_NO_VAA_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - } else { - scu_pinmux(scu->TX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu_pinmux(scu->RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - gpio_output(rf_path->gpio_tx); - scu_pinmux(scu->NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - } + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + /* Configure RF switch control signals */ + // clang-format off + scu_pinmux(scu->HP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->LP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->TX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->NO_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->RX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu_pinmux(scu->NO_TX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->AMP_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->RX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + // clang-format on + if (board_id == BOARD_ID_HACKRF1_R9) { + scu_pinmux(scu->H1R9_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux( + scu->H1R9_NO_ANT_PWR, + SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + gpio_clear(rf_path->gpio_h1r9_no_ant_pwr); + gpio_output(rf_path->gpio_h1r9_no_ant_pwr); + scu_pinmux( + scu->H1R9_NO_VAA_EN, + SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + } else { + scu_pinmux(scu->TX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu_pinmux(scu->RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + gpio_output(rf_path->gpio_tx); + scu_pinmux(scu->NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + } - /* - * Safe (initial) switch settings turn off both amplifiers and antenna port - * power and enable both amp bypass and mixer bypass. - */ - switchctrl_set(rf_path, SWITCHCTRL_SAFE); + /* + * Safe (initial) switch settings turn off both amplifiers and antenna port + * power and enable both amp bypass and mixer bypass. + */ + switchctrl_set(rf_path, SWITCHCTRL_SAFE); - /* Configure RF switch control signals as outputs */ - gpio_output(rf_path->gpio_amp_bypass); - gpio_output(rf_path->gpio_no_mix_bypass); - gpio_output(rf_path->gpio_rx_amp); - gpio_output(rf_path->gpio_no_rx_amp_pwr); - gpio_output(rf_path->gpio_hp); - gpio_output(rf_path->gpio_lp); - gpio_output(rf_path->gpio_tx_mix_bp); - gpio_output(rf_path->gpio_rx_mix_bp); - gpio_output(rf_path->gpio_tx_amp); - gpio_output(rf_path->gpio_no_tx_amp_pwr); - gpio_output(rf_path->gpio_mix_bypass); - gpio_output(rf_path->gpio_rx); -#elif RAD1O - /* Configure RF switch control signals */ - // clang-format off - scu_pinmux(scu->BY_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->BY_AMP_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu_pinmux(scu->TX_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->TX_RX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->BY_MIX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->BY_MIX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->LOW_HIGH_FILT, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->LOW_HIGH_FILT_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->RX_LNA, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu_pinmux(scu->MIXER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - // clang-format on - - /* Configure RF power supply (VAA) switch */ - scu_pinmux(scu->VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - - /* - * Safe (initial) switch settings turn off both amplifiers and antenna port - * power and enable both amp bypass and mixer bypass. - */ - switchctrl_set(rf_path, SWITCHCTRL_SAFE); - - /* Configure RF switch control signals as outputs */ - gpio_output(rf_path->gpio_tx_rx_n); - gpio_output(rf_path->gpio_tx_rx); - gpio_output(rf_path->gpio_by_mix); - gpio_output(rf_path->gpio_by_mix_n); - gpio_output(rf_path->gpio_by_amp); - gpio_output(rf_path->gpio_by_amp_n); - gpio_output(rf_path->gpio_mixer_en); - gpio_output(rf_path->gpio_low_high_filt); - gpio_output(rf_path->gpio_low_high_filt_n); - gpio_output(rf_path->gpio_tx_amp); - gpio_output(rf_path->gpio_rx_lna); -#elif PRALINE - /* Configure RF switch control signals */ - scu_pinmux(scu->TX_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - board_rev_t rev = detected_revision(); - if ((rev == BOARD_REV_PRALINE_R1_0) || (rev == BOARD_REV_GSG_PRALINE_R1_0)) { - scu_pinmux(scu->MIX_EN_N_R1_0, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - } else { - scu_pinmux(scu->MIX_EN_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - } - scu_pinmux(scu->LPF_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->RF_AMP_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - - /* Configure antenna port power control signal */ - scu_pinmux(scu->ANT_BIAS_EN_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - - /* Configure RF power supply (VAA) switch */ - scu_pinmux(scu->NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - - /* - * Safe (initial) switch settings turn off both amplifiers and antenna port - * power and enable both amp bypass and mixer bypass. - */ - switchctrl_set(rf_path, SWITCHCTRL_SAFE); - - /* Configure RF switch control signals as outputs */ - gpio_output(rf_path->gpio_ant_bias_en_n); - gpio_output(rf_path->gpio_tx_en); - gpio_output(rf_path->gpio_mix_en_n); - gpio_output(rf_path->gpio_lpf_en); - gpio_output(rf_path->gpio_rf_amp_en); -#else - (void) rf_path; /* silence unused param warning */ + /* Configure RF switch control signals as outputs */ + gpio_output(rf_path->gpio_amp_bypass); + gpio_output(rf_path->gpio_no_mix_bypass); + gpio_output(rf_path->gpio_rx_amp); + gpio_output(rf_path->gpio_no_rx_amp_pwr); + gpio_output(rf_path->gpio_hp); + gpio_output(rf_path->gpio_lp); + gpio_output(rf_path->gpio_tx_mix_bp); + gpio_output(rf_path->gpio_rx_mix_bp); + gpio_output(rf_path->gpio_tx_amp); + gpio_output(rf_path->gpio_no_tx_amp_pwr); + gpio_output(rf_path->gpio_mix_bypass); + gpio_output(rf_path->gpio_rx); #endif + break; + case BOARD_ID_RAD1O: +#if defined(RAD1O) + /* Configure RF switch control signals */ + // clang-format off + scu_pinmux(scu->BY_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->BY_AMP_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu_pinmux(scu->TX_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->TX_RX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->BY_MIX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->BY_MIX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->LOW_HIGH_FILT, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->LOW_HIGH_FILT_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->RX_LNA, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu_pinmux(scu->MIXER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + // clang-format on + + /* Configure RF power supply (VAA) switch */ + scu_pinmux(scu->VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + + /* + * Safe (initial) switch settings turn off both amplifiers and antenna port + * power and enable both amp bypass and mixer bypass. + */ + switchctrl_set(rf_path, SWITCHCTRL_SAFE); + + /* Configure RF switch control signals as outputs */ + gpio_output(rf_path->gpio_tx_rx_n); + gpio_output(rf_path->gpio_tx_rx); + gpio_output(rf_path->gpio_by_mix); + gpio_output(rf_path->gpio_by_mix_n); + gpio_output(rf_path->gpio_by_amp); + gpio_output(rf_path->gpio_by_amp_n); + gpio_output(rf_path->gpio_mixer_en); + gpio_output(rf_path->gpio_low_high_filt); + gpio_output(rf_path->gpio_low_high_filt_n); + gpio_output(rf_path->gpio_tx_amp); + gpio_output(rf_path->gpio_rx_lna); +#endif + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + /* Configure RF switch control signals */ + scu_pinmux(scu->TX_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + board_rev_t rev = detected_revision(); + if ((rev == BOARD_REV_PRALINE_R1_0) || + (rev == BOARD_REV_GSG_PRALINE_R1_0)) { + scu_pinmux(scu->MIX_EN_N_R1_0, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + } else { + scu_pinmux(scu->MIX_EN_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + } + scu_pinmux(scu->LPF_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->RF_AMP_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + + /* Configure antenna port power control signal */ + scu_pinmux(scu->ANT_BIAS_EN_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + + /* Configure RF power supply (VAA) switch */ + scu_pinmux(scu->NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + + /* + * Safe (initial) switch settings turn off both amplifiers and antenna port + * power and enable both amp bypass and mixer bypass. + */ + switchctrl_set(rf_path, SWITCHCTRL_SAFE); + + /* Configure RF switch control signals as outputs */ + gpio_output(rf_path->gpio_ant_bias_en_n); + gpio_output(rf_path->gpio_tx_en); + gpio_output(rf_path->gpio_mix_en_n); + gpio_output(rf_path->gpio_lpf_en); + gpio_output(rf_path->gpio_rf_amp_en); +#endif + break; + default: + break; + } } void rf_path_init(rf_path_t* const rf_path) { + board_id_t board_id = detected_platform(); + ssp1_set_mode_max5864(); max5864_setup(&max5864); max5864_shutdown(&max5864); ssp1_set_mode_max283x(); -#ifdef PRALINE - max283x_setup(&max283x, MAX2831_VARIANT); -#elif defined(HACKRF_ONE) - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - max283x_setup(&max283x, MAX2839_VARIANT); - } else { - max283x_setup(&max283x, MAX2837_VARIANT); - } -#else - max283x_setup(&max283x, MAX2837_VARIANT); + switch (board_id) { + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + max283x_setup(&max283x, MAX2831_VARIANT); #endif + break; + case BOARD_ID_HACKRF1_R9: +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + max283x_setup(&max283x, MAX2839_VARIANT); +#endif + break; + default: +#if !defined(PRALINE) || defined(UNIVERSAL) + max283x_setup(&max283x, MAX2837_VARIANT); +#endif + break; + } max283x_start(&max283x); - // On HackRF One, the mixer is now set up earlier in boot. -#ifndef HACKRF_ONE - mixer_setup(&mixer); -#endif + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + // On HackRF One, the mixer is now set up earlier in boot. + break; + default: + mixer_setup(&mixer); + break; + } rf_path->switchctrl = SWITCHCTRL_SAFE; } @@ -501,7 +551,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d max283x_rx(&max283x); break; -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) case RF_PATH_DIRECTION_TX_CALIBRATION: case RF_PATH_DIRECTION_RX_CALIBRATION: rf_path->switchctrl &= ~SWITCHCTRL_TX; diff --git a/firmware/common/rf_path.h b/firmware/common/rf_path.h index 1ac0e243..64634b3d 100644 --- a/firmware/common/rf_path.h +++ b/firmware/common/rf_path.h @@ -25,7 +25,7 @@ #include -#if defined(HACKRF_ONE) || defined(RAD1O) || defined(PRALINE) +#if !defined(JAWBREAKER) #include "gpio.h" #endif @@ -33,7 +33,7 @@ typedef enum { RF_PATH_DIRECTION_OFF, RF_PATH_DIRECTION_RX, RF_PATH_DIRECTION_TX, -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) RF_PATH_DIRECTION_TX_CALIBRATION, RF_PATH_DIRECTION_RX_CALIBRATION, #endif @@ -47,43 +47,48 @@ typedef enum { typedef struct { uint8_t switchctrl; -#ifdef HACKRF_ONE - gpio_t gpio_hp; - gpio_t gpio_lp; - gpio_t gpio_tx_mix_bp; - gpio_t gpio_no_mix_bypass; - gpio_t gpio_rx_mix_bp; - gpio_t gpio_tx_amp; - gpio_t gpio_tx; - gpio_t gpio_mix_bypass; - gpio_t gpio_rx; - gpio_t gpio_no_tx_amp_pwr; - gpio_t gpio_amp_bypass; - gpio_t gpio_rx_amp; - gpio_t gpio_no_rx_amp_pwr; - // In HackRF One r9 this control signal has been moved to the microcontroller. - gpio_t gpio_h1r9_no_ant_pwr; + + struct { +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + gpio_t gpio_hp; + gpio_t gpio_lp; + gpio_t gpio_tx_mix_bp; + gpio_t gpio_no_mix_bypass; + gpio_t gpio_rx_mix_bp; + gpio_t gpio_tx_amp; + gpio_t gpio_tx; + gpio_t gpio_mix_bypass; + gpio_t gpio_rx; + gpio_t gpio_no_tx_amp_pwr; + gpio_t gpio_amp_bypass; + gpio_t gpio_rx_amp; + gpio_t gpio_no_rx_amp_pwr; + // In HackRF One r9 this control signal has been moved to the microcontroller. + gpio_t gpio_h1r9_no_ant_pwr; #endif -#ifdef RAD1O - gpio_t gpio_tx_rx_n; - gpio_t gpio_tx_rx; - gpio_t gpio_by_mix; - gpio_t gpio_by_mix_n; - gpio_t gpio_by_amp; - gpio_t gpio_by_amp_n; - gpio_t gpio_mixer_en; - gpio_t gpio_low_high_filt; - gpio_t gpio_low_high_filt_n; - gpio_t gpio_tx_amp; - gpio_t gpio_rx_lna; + +#if defined(RAD1O) + gpio_t gpio_tx_rx_n; + gpio_t gpio_tx_rx; + gpio_t gpio_by_mix; + gpio_t gpio_by_mix_n; + gpio_t gpio_by_amp; + gpio_t gpio_by_amp_n; + gpio_t gpio_mixer_en; + gpio_t gpio_low_high_filt; + gpio_t gpio_low_high_filt_n; + gpio_t gpio_tx_amp; + gpio_t gpio_rx_lna; #endif -#ifdef PRALINE - gpio_t gpio_tx_en; - gpio_t gpio_mix_en_n; - gpio_t gpio_lpf_en; - gpio_t gpio_rf_amp_en; - gpio_t gpio_ant_bias_en_n; + +#if defined(PRALINE) || defined(UNIVERSAL) + gpio_t gpio_tx_en; + gpio_t gpio_mix_en_n; + gpio_t gpio_lpf_en; + gpio_t gpio_rf_amp_en; + gpio_t gpio_ant_bias_en_n; #endif + }; } rf_path_t; void rf_path_pin_setup(rf_path_t* const rf_path); From 3aaa7185bd49d27a918fc7f810d5e5a1572245fe Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sat, 4 Apr 2026 00:32:50 +0100 Subject: [PATCH 115/238] Universalize: mixer.{c,h}, usb_api_register.c Co-authored-by: Antoine van Gelder --- firmware/common/mixer.c | 157 +++++++++++++++++-------- firmware/common/mixer.h | 27 ++++- firmware/common/rf_path.c | 9 +- firmware/hackrf_usb/hackrf_usb.c | 8 +- firmware/hackrf_usb/usb_api_register.c | 52 ++++++-- 5 files changed, 185 insertions(+), 68 deletions(-) diff --git a/firmware/common/mixer.c b/firmware/common/mixer.c index 8623ee6b..9e1afb32 100644 --- a/firmware/common/mixer.c +++ b/firmware/common/mixer.c @@ -25,101 +25,164 @@ #include "fixed_point.h" #include "platform_gpio.h" -#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) +#if defined(RAD1O) + #include "max2871.h" +#else + #include "platform_detect.h" #include "rffc5071.h" #include "rffc5071_spi.h" #include "spi_bus.h" -#elif defined(RAD1O) - #include "max2871.h" #endif -#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) +#if !defined(RAD1O) static rffc5071_spi_config_t rffc5071_spi_config; -spi_bus_t spi_bus_rffc5071 = { +static spi_bus_t spi_bus_rffc5071 = { .config = &rffc5071_spi_config, .start = rffc5071_spi_start, .stop = rffc5071_spi_stop, .transfer = rffc5071_spi_transfer, .transfer_gather = rffc5071_spi_transfer_gather, }; +#endif mixer_driver_t mixer = { - .bus = &spi_bus_rffc5071, -}; -#elif defined(RAD1O) -mixer_driver_t mixer = {}; +#if !defined(RAD1O) + .rffc5071.bus = &spi_bus_rffc5071, #endif +}; void mixer_bus_setup(mixer_driver_t* const mixer) { +#if defined(RAD1O) (void) mixer; - -#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) +#else const platform_gpio_t* gpio = platform_gpio(); - rffc5071_spi_config = (rffc5071_spi_config_t){ - .gpio_select = gpio->rffc5072_select, - .gpio_clock = gpio->rffc5072_clock, - .gpio_data = gpio->rffc5072_data, - }; - spi_bus_start(&spi_bus_rffc5071, &rffc5071_spi_config); #endif + + switch (mixer->type) { + case RFFC5071_VARIANT: +#if !defined(RAD1O) + rffc5071_spi_config = (rffc5071_spi_config_t){ + .gpio_select = gpio->rffc5072_select, + .gpio_clock = gpio->rffc5072_clock, + .gpio_data = gpio->rffc5072_data, + }; + spi_bus_start(&spi_bus_rffc5071, &rffc5071_spi_config); +#endif + break; + case MAX2871_VARIANT: + break; + } } -void mixer_setup(mixer_driver_t* const mixer) +void mixer_setup(mixer_driver_t* const mixer, mixer_variant_t type) { + mixer->type = type; + const platform_gpio_t* gpio = platform_gpio(); -#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) - mixer->gpio_reset = gpio->rffc5072_reset; - #if defined(PRALINE) - mixer->gpio_ld = gpio->rffc5072_ld; + /* Mixer GPIO serial interface PinMux */ + switch (mixer->type) { + case RFFC5071_VARIANT: +#if !defined(RAD1O) + mixer->rffc5071.gpio_reset = gpio->rffc5072_reset; + if (detected_platform() == BOARD_ID_PRALINE) { + #if defined(PRALINE) || defined(UNIVERSAL) + mixer->rffc5071.gpio_ld = gpio->rffc5072_ld; #endif - rffc5071_setup(mixer); -#elif defined(RAD1O) - mixer->gpio_vco_ce = gpio->vco_ce; - mixer->gpio_vco_sclk = gpio->vco_sclk; - mixer->gpio_vco_sdata = gpio->vco_sdata; - mixer->gpio_vco_le = gpio->vco_le; - mixer->gpio_synt_rfout_en = gpio->synt_rfout_en; - mixer->gpio_vco_mux = gpio->vco_mux; - max2871_setup(mixer); + } #endif + break; + case MAX2871_VARIANT: +#if defined(RAD1O) + mixer->max2871.gpio_vco_ce = gpio->vco_ce; + mixer->max2871.gpio_vco_sclk = gpio->vco_sclk; + mixer->max2871.gpio_vco_sdata = gpio->vco_sdata; + mixer->max2871.gpio_vco_le = gpio->vco_le; + mixer->max2871.gpio_synt_rfout_en = gpio->synt_rfout_en; + mixer->max2871.gpio_vco_mux = gpio->vco_mux; +#endif + break; + } + + switch (mixer->type) { + case RFFC5071_VARIANT: +#if !defined(RAD1O) + rffc5071_setup(&mixer->rffc5071); +#endif + break; + case MAX2871_VARIANT: +#if defined(RAD1O) + max2871_setup(&mixer->max2871); +#endif + break; + } } fp_40_24_t mixer_set_frequency(mixer_driver_t* const mixer, fp_40_24_t lo, bool program) { -#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) - return rffc5071_set_frequency(mixer, lo, program); -#elif defined(RAD1O) - return max2871_set_frequency(mixer, lo, program); + switch (mixer->type) { + case RFFC5071_VARIANT: +#if !defined(RAD1O) + return rffc5071_set_frequency(&mixer->rffc5071, lo, program); #endif + break; + case MAX2871_VARIANT: +#if defined(RAD1O) + return max2871_set_frequency(&mixer->max2871, lo, program); +#endif + break; + } + + return 0; } void mixer_enable(mixer_driver_t* const mixer) { -#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) - rffc5071_enable(mixer); -#elif defined(RAD1O) - max2871_enable(mixer); + switch (mixer->type) { + case RFFC5071_VARIANT: +#if !defined(RAD1O) + rffc5071_enable(&mixer->rffc5071); #endif + break; + case MAX2871_VARIANT: +#if defined(RAD1O) + max2871_enable(&mixer->max2871); +#endif + break; + } } void mixer_disable(mixer_driver_t* const mixer) { -#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) - rffc5071_disable(mixer); -#elif defined(RAD1O) - max2871_disable(mixer); + switch (mixer->type) { + case RFFC5071_VARIANT: +#if !defined(RAD1O) + rffc5071_disable(&mixer->rffc5071); #endif + break; + case MAX2871_VARIANT: +#if defined(RAD1O) + max2871_disable(&mixer->max2871); +#endif + break; + } } void mixer_set_gpo(mixer_driver_t* const mixer, uint8_t gpo) { -#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) - rffc5071_set_gpo(mixer, gpo); -#elif defined(RAD1O) - (void) mixer; +#if defined(RAD1O) (void) gpo; #endif + + switch (mixer->type) { + case RFFC5071_VARIANT: +#if !defined(RAD1O) + rffc5071_set_gpo(&mixer->rffc5071, gpo); +#endif + break; + case MAX2871_VARIANT: + break; + } } diff --git a/firmware/common/mixer.h b/firmware/common/mixer.h index 6ba47d75..0afacb6b 100644 --- a/firmware/common/mixer.h +++ b/firmware/common/mixer.h @@ -26,17 +26,32 @@ #include "fixed_point.h" -#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) - #include "rffc5071.h" -typedef rffc5071_driver_t mixer_driver_t; -#elif defined(RAD1O) +#if defined(RAD1O) #include "max2871.h" -typedef max2871_driver_t mixer_driver_t; +#else + #include "rffc5071.h" #endif +typedef enum { + RFFC5071_VARIANT, + MAX2871_VARIANT, +} mixer_variant_t; + +typedef struct { + mixer_variant_t type; + + union { +#if defined(RAD1O) + max2871_driver_t max2871; +#else + rffc5071_driver_t rffc5071; +#endif + }; +} mixer_driver_t; + #include extern void mixer_bus_setup(mixer_driver_t* const mixer); -extern void mixer_setup(mixer_driver_t* const mixer); +extern void mixer_setup(mixer_driver_t* const mixer, mixer_variant_t type); /* Set frequency (Hz). */ extern fp_40_24_t mixer_set_frequency( diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index a361f442..5e892668 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -504,8 +504,15 @@ void rf_path_init(rf_path_t* const rf_path) case BOARD_ID_HACKRF1_R9: // On HackRF One, the mixer is now set up earlier in boot. break; + case BOARD_ID_RAD1O: +#if defined(RAD1O) + mixer_setup(&mixer, MAX2871_VARIANT); +#endif + break; default: - mixer_setup(&mixer); +#if !defined(RAD1O) + mixer_setup(&mixer, RFFC5071_VARIANT); +#endif break; } rf_path->switchctrl = SWITCHCTRL_SAFE; diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index c365e9bc..93308cda 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -47,7 +47,7 @@ #include #include #include -#if defined(HACKRF_ONE) +#if !defined(RAD1O) #include #endif #if defined(PRALINE) || defined(HACKRF_ONE) @@ -432,7 +432,9 @@ int main(void) // This will be cleared if any self-test check fails. selftest.report.pass = true; + // Detect hardware platform before we do anything else. detect_hardware_platform(); + pin_shutdown(); #ifndef RAD1O clock_gen_shutdown(); @@ -464,7 +466,7 @@ int main(void) #ifdef HACKRF_ONE // Set up mixer before enabling RF power, because its // GPO is used to control the antenna bias tee. - mixer_setup(&mixer); + mixer_setup(&mixer, RFFC5071_VARIANT); #endif #if (defined HACKRF_ONE || defined RAD1O) enable_rf_power(); @@ -526,7 +528,7 @@ int main(void) rf_path_init(&rf_path); #ifndef RAD1O - rffc5071_lock_test(&mixer); + rffc5071_lock_test(&mixer.rffc5071); #endif #ifdef PRALINE diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index 01d9fa8f..b74589ec 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -30,17 +30,19 @@ #include #include +#include #include #include #include #include #include -#if defined(PRALINE) || defined(HACKRF_ONE) || defined(JAWBREAKER) - #include -#endif -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) #include #endif +#if !defined(RAD1O) + #include + #include +#endif usb_request_status_t usb_vendor_request_write_max283x( usb_endpoint_t* const endpoint, @@ -136,20 +138,29 @@ usb_request_status_t usb_vendor_request_read_si5351c( } } -#ifndef RAD1O usb_request_status_t usb_vendor_request_write_rffc5071( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { +#if defined(RAD1O) + (void) endpoint; + (void) stage; + if (detected_platform() == BOARD_ID_RAD1O) { + return USB_REQUEST_STATUS_STALL; + } +#endif + if (stage == USB_TRANSFER_STAGE_SETUP) { +#if !defined(RAD1O) if (endpoint->setup.index < RFFC5071_NUM_REGS) { rffc5071_reg_write( - &mixer, + &mixer.rffc5071, endpoint->setup.index, endpoint->setup.value); usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } +#endif return USB_REQUEST_STATUS_STALL; } else { return USB_REQUEST_STATUS_OK; @@ -160,10 +171,19 @@ usb_request_status_t usb_vendor_request_read_rffc5071( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { - uint16_t value; +#if defined(RAD1O) + (void) endpoint; + (void) stage; + if (detected_platform() == BOARD_ID_RAD1O) { + return USB_REQUEST_STATUS_STALL; + } +#endif + if (stage == USB_TRANSFER_STAGE_SETUP) { +#if !defined(RAD1O) + uint16_t value; if (endpoint->setup.index < RFFC5071_NUM_REGS) { - value = rffc5071_reg_read(&mixer, endpoint->setup.index); + value = rffc5071_reg_read(&mixer.rffc5071, endpoint->setup.index); endpoint->buffer[0] = value & 0xff; endpoint->buffer[1] = value >> 8; usb_transfer_schedule_block( @@ -175,12 +195,12 @@ usb_request_status_t usb_vendor_request_read_rffc5071( usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } +#endif return USB_REQUEST_STATUS_STALL; } else { return USB_REQUEST_STATUS_OK; } } -#endif usb_request_status_t usb_vendor_request_set_clkout_enable( usb_endpoint_t* const endpoint, @@ -266,13 +286,18 @@ usb_request_status_t usb_vendor_request_user_config_set_bias_t_opts( return USB_REQUEST_STATUS_OK; } -#ifdef PRALINE usb_request_status_t usb_vendor_request_write_fpga_reg( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { + if (detected_platform() != BOARD_ID_PRALINE) { + return USB_REQUEST_STATUS_STALL; + } + if (stage == USB_TRANSFER_STAGE_SETUP) { +#if defined(PRALINE) || defined(UNIVERSAL) fpga_reg_write(&fpga, endpoint->setup.index, endpoint->setup.value); +#endif usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } @@ -283,7 +308,12 @@ usb_request_status_t usb_vendor_request_read_fpga_reg( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { + if (detected_platform() != BOARD_ID_PRALINE) { + return USB_REQUEST_STATUS_STALL; + } + if (stage == USB_TRANSFER_STAGE_SETUP) { +#if defined(PRALINE) || defined(UNIVERSAL) const uint8_t value = fpga_reg_read(&fpga, endpoint->setup.index); endpoint->buffer[0] = value; usb_transfer_schedule_block( @@ -292,11 +322,11 @@ usb_request_status_t usb_vendor_request_read_fpga_reg( 1, NULL, NULL); +#endif usb_transfer_schedule_ack(endpoint->out); } return USB_REQUEST_STATUS_OK; } -#endif /* * Each register is transferred as a uint8_t register number followed by a From 275b75fc8558cb0ab7e72f2c47e714ab9e44d920 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sat, 4 Apr 2026 00:51:41 +0100 Subject: [PATCH 116/238] Universalize: tuning.{c,h}, tune_config.h Co-authored-by: Antoine van Gelder --- firmware/common/tune_config.h | 2 +- firmware/common/tuning.c | 37 ++++++++++++++++++-------------- firmware/common/tuning.h | 2 ++ firmware/hackrf_usb/hackrf_usb.c | 4 +++- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/firmware/common/tune_config.h b/firmware/common/tune_config.h index 7fc76af9..34c692e6 100644 --- a/firmware/common/tune_config.h +++ b/firmware/common/tune_config.h @@ -21,7 +21,7 @@ #pragma once -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) #include "fpga.h" typedef struct { diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index f613ab30..9c863beb 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -29,18 +29,23 @@ #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define MAX(x, y) ((x) > (y) ? (x) : (y)) -#ifdef PRALINE - #define MIN_BYPASS_FREQ FP_MHZ(2320) - #define MAX_BYPASS_FREQ FP_MHZ(2580) -#else - #define MIN_BYPASS_FREQ FP_MHZ(2170) - #define MAX_BYPASS_FREQ FP_MHZ(2740) -#endif - #define MID1_HP_FREQ FP_MHZ(3600) #define MID2_HP_FREQ FP_MHZ(5100) #define MAX_HP_FREQ FP_MHZ(7250) +static fp_40_24_t min_bypass_freq = FP_MHZ(2170); +static fp_40_24_t max_bypass_freq = FP_MHZ(2740); + +void tuning_setup(void) +{ +#if defined(PRALINE) || defined(UNIVERSAL) + if (detected_platform() == BOARD_ID_PRALINE) { + min_bypass_freq = FP_MHZ(2320); + max_bypass_freq = FP_MHZ(2580); + } +#endif +} + fp_40_24_t select_graduated_if(fp_40_24_t freq_rf, rf_path_filter_t img_reject) { fp_40_24_t freq_if; @@ -57,8 +62,8 @@ fp_40_24_t select_graduated_if(fp_40_24_t freq_rf, rf_path_filter_t img_reject) case RF_PATH_FILTER_HIGH_PASS: if (freq_rf < MID1_HP_FREQ) { /* IF is graduated from 2170 MHz to 2740 MHz */ - freq_if = MIN_BYPASS_FREQ + - (((freq_rf - (MAX_BYPASS_FREQ)) * 57) / 86); + freq_if = min_bypass_freq + + (((freq_rf - (max_bypass_freq)) * 57) / 86); } else if (freq_rf < MID2_HP_FREQ) { /* IF is graduated from 2350 MHz to 2650 MHz */ freq_if = FP_MHZ(2350) + ((freq_rf - (MID1_HP_FREQ)) / 5); @@ -75,9 +80,9 @@ fp_40_24_t select_graduated_if(fp_40_24_t freq_rf, rf_path_filter_t img_reject) rf_path_filter_t select_img_reject(fp_40_24_t freq_rf) { - if (freq_rf > MAX_BYPASS_FREQ) { + if (freq_rf > max_bypass_freq) { return RF_PATH_FILTER_HIGH_PASS; - } else if (freq_rf >= MIN_BYPASS_FREQ) { + } else if (freq_rf >= min_bypass_freq) { return RF_PATH_FILTER_BYPASS; } else { return RF_PATH_FILTER_LOW_PASS; @@ -91,14 +96,14 @@ fp_40_24_t restrict_rf(fp_40_24_t freq_rf, rf_path_filter_t img_reject) switch (img_reject) { case RF_PATH_FILTER_LOW_PASS: - max_rf = MIN_BYPASS_FREQ; + max_rf = min_bypass_freq; break; case RF_PATH_FILTER_HIGH_PASS: - min_rf = MAX_BYPASS_FREQ; + min_rf = max_bypass_freq; break; default: - min_rf = MIN_BYPASS_FREQ; - max_rf = MAX_BYPASS_FREQ; + min_rf = min_bypass_freq; + max_rf = max_bypass_freq; } freq_rf = MIN(freq_rf, max_rf); freq_rf = MAX(freq_rf, min_rf); diff --git a/firmware/common/tuning.h b/firmware/common/tuning.h index a338cd28..db123ee3 100644 --- a/firmware/common/tuning.h +++ b/firmware/common/tuning.h @@ -26,6 +26,8 @@ #include "fixed_point.h" #include "rf_path.h" +void tuning_setup(void); + /** * Select fixed or graduated IF for a given RF and image reject filter. */ diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 93308cda..3238ca0e 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -40,8 +40,9 @@ #include #include #include -#include #include +#include +#include #include #include #include @@ -463,6 +464,7 @@ int main(void) clock_gen_init(); #endif #endif + tuning_setup(); #ifdef HACKRF_ONE // Set up mixer before enabling RF power, because its // GPO is used to control the antenna bias tee. From 233951c9c9fae3dd36af8e62edd44dc35997764c Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sat, 4 Apr 2026 00:53:20 +0100 Subject: [PATCH 117/238] Universalize: hackrf_ui.c Co-authored-by: Antoine van Gelder --- firmware/common/hackrf_ui.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/firmware/common/hackrf_ui.c b/firmware/common/hackrf_ui.c index 6e230943..ac16a444 100644 --- a/firmware/common/hackrf_ui.c +++ b/firmware/common/hackrf_ui.c @@ -23,8 +23,9 @@ #include #include "hackrf_ui.h" +#include "platform_detect.h" #include "transceiver_mode.h" -#if defined(PRALINE) || defined(HACKRF_ONE) +#if defined(PRALINE) || defined(HACKRF_ONE) || defined(UNIVERSAL) #include "ui_portapack.h" #endif #if defined(RAD1O) @@ -82,16 +83,26 @@ const hackrf_ui_t* hackrf_ui(void) { /* Detect on first use. If no UI hardware is detected, use a stub function table. */ if (ui == NULL && ui_enabled) { -#if (defined HACKRF_ONE || defined PRALINE) - if (portapack_hackrf_ui_init) { - ui = portapack_hackrf_ui_init(); - } + switch (detected_platform()) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + case BOARD_ID_PRALINE: +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + if (portapack_hackrf_ui_init) { + ui = portapack_hackrf_ui_init(); + } #endif -#ifdef RAD1O - if (rad1o_ui_setup) { - ui = rad1o_ui_setup(); - } + break; + case BOARD_ID_RAD1O: +#if defined(RAD1O) + if (rad1o_ui_setup) { + ui = rad1o_ui_setup(); + } #endif + break; + default: + break; + } } if (ui == NULL) { From 9285573f0bbdec44e586daf14be92c68f7ac72cd Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sat, 4 Apr 2026 00:54:12 +0100 Subject: [PATCH 118/238] Universalize: operacake_sctimer.c Co-authored-by: Antoine van Gelder --- firmware/common/operacake_sctimer.c | 40 +++++++++++++++++------------ 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/firmware/common/operacake_sctimer.c b/firmware/common/operacake_sctimer.c index 9ae37567..21ce3d7e 100644 --- a/firmware/common/operacake_sctimer.c +++ b/firmware/common/operacake_sctimer.c @@ -30,6 +30,8 @@ #include #endif +#include + #include "delay.h" #include "sct.h" @@ -95,25 +97,31 @@ void operacake_sctimer_init(void) P7_0, SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); -#ifndef PRALINE - // Configure the SGPIO to output the clock (f=2 * sample clock) on pin 12 - SGPIO_OUT_MUX_CFG12 = SGPIO_OUT_MUX_CFG_P_OUT_CFG(0x08) | // clkout output mode - SGPIO_OUT_MUX_CFG_P_OE_CFG(0); // gpio_oe - SGPIO_GPIO_OENREG |= BIT12; + uint8_t sct_clock_input; + if (detected_platform() != BOARD_ID_PRALINE) { +#if !defined(PRALINE) || defined(UNIVERSAL) + // Configure the SGPIO to output the clock (f=2 * sample clock) on pin 12 + SGPIO_OUT_MUX_CFG12 = + SGPIO_OUT_MUX_CFG_P_OUT_CFG(0x08) | // clkout output mode + SGPIO_OUT_MUX_CFG_P_OE_CFG(0); // gpio_oe + SGPIO_GPIO_OENREG |= BIT12; - // Use the GIMA to connect the SGPIO clock to the SCTimer - GIMA_CTIN_1_IN = 0x2 << 4; // Route SGPIO12 to SCTIN1 + // Use the GIMA to connect the SGPIO clock to the SCTimer + GIMA_CTIN_1_IN = 0x2 << 4; // Route SGPIO12 to SCTIN1 - uint8_t sct_clock_input = SCT_CONFIG_CKSEL_RISING_EDGES_ON_INPUT_1; -#else - // Configure pin P6_4 as SCT_IN_6 - scu_pinmux(P6_4, SCU_CLK_IN | SCU_CONF_FUNCTION1); - - // Use the GIMA to connect MS0/CLK1 (SCT_CLK) on pin P6_4 to the SCTimer - GIMA_CTIN_6_IN = 0x0 << 4; - - uint8_t sct_clock_input = SCT_CONFIG_CKSEL_RISING_EDGES_ON_INPUT_6; + sct_clock_input = SCT_CONFIG_CKSEL_RISING_EDGES_ON_INPUT_1; #endif + } else { +#if defined(PRALINE) || defined(UNIVERSAL) + // Configure pin P6_4 as SCT_IN_6 + scu_pinmux(P6_4, SCU_CLK_IN | SCU_CONF_FUNCTION1); + + // Use the GIMA to connect MS0/CLK1 (SCT_CLK) on pin P6_4 to the SCTimer + GIMA_CTIN_6_IN = 0x0 << 4; + + sct_clock_input = SCT_CONFIG_CKSEL_RISING_EDGES_ON_INPUT_6; +#endif + } // We configure this register first, because the user manual says to SCT_CONFIG |= SCT_CONFIG_UNIFY_32_BIT | SCT_CONFIG_CLKMODE_PRESCALED_BUS_CLOCK | From ed1a4d0e9e0938cddb83636f5a079c9a4ca30b9b Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sat, 4 Apr 2026 00:55:40 +0100 Subject: [PATCH 119/238] Universalize: w25q80bv.c Co-authored-by: Antoine van Gelder --- firmware/common/w25q80bv.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index 9e7e1acd..f569bedf 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -27,10 +27,11 @@ * programming the flash. */ -#include "w25q80bv.h" - -#include #include +#include + +#include "platform_detect.h" +#include "w25q80bv.h" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) @@ -59,13 +60,13 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv) uint8_t device_id; drv->page_len = 256U; -#ifdef PRALINE - drv->num_pages = 16384U; - drv->num_bytes = 4194304U; -#else - drv->num_pages = 4096U; - drv->num_bytes = 1048576U; -#endif + if (detected_platform() == BOARD_ID_PRALINE) { + drv->num_pages = 16384U; + drv->num_bytes = 4194304U; + } else { + drv->num_pages = 4096U; + drv->num_bytes = 1048576U; + } drv->target_init(drv); From 54dfdd9174f2bf90ad2179b3b74e611986373961 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sat, 4 Apr 2026 00:56:31 +0100 Subject: [PATCH 120/238] Universalize: sgpio.{c,h} Co-authored-by: Antoine van Gelder --- firmware/common/sgpio.c | 14 ++++++++------ firmware/common/sgpio.h | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index f364d7b0..ac755d51 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -58,7 +58,7 @@ void sgpio_configure_pin_functions(sgpio_config_t* const config) scu_pinmux(scu->PINMUX_SGPIO15, scu->PINMUX_SGPIO15_PINCFG); /* GPIO5[14] */ if (detected_platform() == BOARD_ID_HACKRF1_R9) { -#if defined(HACKRF_ONE) +#if defined(HACKRF_ONE) || defined(UNIVERSAL) scu_pinmux( scu->H1R9_TRIGGER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[5] */ @@ -72,10 +72,12 @@ void sgpio_configure_pin_functions(sgpio_config_t* const config) sgpio_cpld_set_mixer_invert(config, 0); gpio_output(config->gpio_q_invert); -#ifndef PRALINE - trigger_enable(false); - gpio_output(config->gpio_trigger_enable); + if (detected_platform() != BOARD_ID_PRALINE) { +#if !defined(PRALINE) || defined(UNIVERSAL) + trigger_enable(false); + gpio_output(config->gpio_trigger_enable); #endif + } } void sgpio_set_slice_mode(sgpio_config_t* const config, const bool multi_slice) @@ -157,11 +159,11 @@ void sgpio_configure(sgpio_config_t* const config, const sgpio_direction_t direc SGPIO_OUT_MUX_CFG_P_OE_CFG(0) // gpio_oe (state set by GPIO_OEREG) | SGPIO_OUT_MUX_CFG_P_OUT_CFG(0) // dout_doutm1 (1-bit mode) ; - SGPIO_OUT_MUX_CFG(10) = // GPIO10: Output: disable + SGPIO_OUT_MUX_CFG(10) = // GPIO10: Output: disable SGPIO_OUT_MUX_CFG_P_OE_CFG(0) // gpio_oe (state set by GPIO_OEREG) | SGPIO_OUT_MUX_CFG_P_OUT_CFG(4) // gpio_out (level set by GPIO_OUTREG) ; - SGPIO_OUT_MUX_CFG(11) = // GPIO11: Output: direction + SGPIO_OUT_MUX_CFG(11) = // GPIO11: Output: direction SGPIO_OUT_MUX_CFG_P_OE_CFG(0) // gpio_oe (state set by GPIO_OEREG) | SGPIO_OUT_MUX_CFG_P_OUT_CFG(4) // gpio_out (level set by GPIO_OUTREG) ; diff --git a/firmware/common/sgpio.h b/firmware/common/sgpio.h index a3b6b2eb..f6fdf213 100644 --- a/firmware/common/sgpio.h +++ b/firmware/common/sgpio.h @@ -34,7 +34,7 @@ typedef enum { typedef struct { gpio_t gpio_q_invert; -#ifndef PRALINE +#if !defined(PRALINE) || defined(UNIVERSAL) gpio_t gpio_trigger_enable; #endif bool slice_mode_multislice; From 6c4023e1791883d51d83a4e91ca8897556e90b3d Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sat, 4 Apr 2026 00:57:58 +0100 Subject: [PATCH 121/238] Universalize: radio.c Co-authored-by: Antoine van Gelder --- firmware/common/radio.c | 184 +++++++++++++++++++++------------------- 1 file changed, 96 insertions(+), 88 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index ac150ca1..ff97a814 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -33,7 +33,7 @@ #include "rf_path.h" #include "transceiver_mode.h" #include "tuning.h" -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) #include "fpga.h" #include "tune_config.h" #endif @@ -195,18 +195,22 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank) case TRANSCEIVER_MODE_SS: n = compute_resample_log(rate / SR_FP_ONE_HZ, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX]) { -#ifdef PRALINE - fpga_set_tx_interpolation_ratio(&fpga, n); + if (detected_platform() == BOARD_ID_PRALINE) { +#if defined(PRALINE) || defined(UNIVERSAL) + fpga_set_tx_interpolation_ratio(&fpga, n); #endif + } radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX] = n; } break; default: n = compute_resample_log(rate / SR_FP_ONE_HZ, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX]) { -#ifdef PRALINE - fpga_set_rx_decimation_ratio(&fpga, n); + if (detected_platform() == BOARD_ID_PRALINE) { +#if defined(PRALINE) || defined(UNIVERSAL) + fpga_set_rx_decimation_ratio(&fpga, n); #endif + } radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX] = n; } } @@ -290,7 +294,7 @@ static fp_40_24_t digital_from_analog_rf( return drf; } -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) /* * Convert center frequency of digital baseband (as seen by MCU) to center * frequency of analog baseband (as seen by ADC/DAC). @@ -418,7 +422,7 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) /* Look up settings appropriate for requested RF. */ if (detected_platform() == BOARD_ID_PRALINE) { -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) const tune_config_t* tune_config = select_tune_config(opmode, freq_rf); if (requested_rotation == RADIO_UNSET) { @@ -498,9 +502,11 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) changed |= (1 << RADIO_IMAGE_REJECT); } if ((rotation != applied_rotation) && (rotation != RADIO_UNSET)) { -#ifdef PRALINE - fpga_set_rx_quarter_shift_mode(&fpga, rotation >> 30); + if (detected_platform() == BOARD_ID_PRALINE) { +#if defined(PRALINE) || defined(UNIVERSAL) + fpga_set_rx_quarter_shift_mode(&fpga, rotation >> 30); #endif + } radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION] = rotation; changed |= (1 << RADIO_ROTATION); } @@ -565,70 +571,74 @@ static uint32_t radio_update_bandwidth(radio_t* const radio, uint64_t* bank) opmode = radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]; } -#ifdef PRALINE - /* Praline legacy mode always sets baseband bandwidth automatically. */ - (void) bank; - uint32_t lpf_bandwidth = auto_bandwidth(radio, opmode); + if (detected_platform() == BOARD_ID_PRALINE) { +#if defined(PRALINE) || defined(UNIVERSAL) + /* Praline legacy mode always sets baseband bandwidth automatically. */ + (void) bank; + uint32_t lpf_bandwidth = auto_bandwidth(radio, opmode); - if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != lpf_bandwidth) { - max283x_set_lpf_bandwidth(&max283x, MAX283x_MODE_TX, lpf_bandwidth); - radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = lpf_bandwidth; - changed |= (1 << RADIO_XCVR_TX_LPF); - } - if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] != lpf_bandwidth) { - max283x_set_lpf_bandwidth(&max283x, MAX283x_MODE_RX, lpf_bandwidth); - radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] = lpf_bandwidth; - changed |= (1 << RADIO_XCVR_RX_LPF); - } - bool narrow_lpf_enable = false; - bool applied_narrow_lpf_enable = - radio->config[RADIO_BANK_APPLIED][RADIO_RX_NARROW_LPF]; - if (lpf_bandwidth <= 1750000) { - narrow_lpf_enable = true; - } - if (applied_narrow_lpf_enable != narrow_lpf_enable) { - narrowband_filter_set(narrow_lpf_enable); - radio->config[RADIO_BANK_APPLIED][RADIO_RX_NARROW_LPF] = - narrow_lpf_enable; - changed |= (1 << RADIO_RX_NARROW_LPF); - } - /* Always set HPF bandwidth to 30 kHz for now. */ - const max283x_rx_hpf_freq_t hpf_bandwidth = MAX283x_RX_HPF_30_KHZ; - if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] != hpf_bandwidth) { - max283x_set_rx_hpf_frequency(&max283x, hpf_bandwidth); - radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] = hpf_bandwidth; - changed |= (1 << RADIO_XCVR_RX_HPF); - } -#else - uint64_t lpf_bandwidth; - lpf_bandwidth = bank[RADIO_XCVR_TX_LPF]; - if (lpf_bandwidth == RADIO_UNSET) { - lpf_bandwidth = bank[RADIO_XCVR_RX_LPF]; - } - if (lpf_bandwidth == RADIO_UNSET) { - lpf_bandwidth = bank[RADIO_BB_BANDWIDTH_TX]; - } - if (lpf_bandwidth == RADIO_UNSET) { - lpf_bandwidth = bank[RADIO_BB_BANDWIDTH_RX]; - } - if (lpf_bandwidth == RADIO_UNSET) { - lpf_bandwidth = radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF]; - } - if (lpf_bandwidth == RADIO_UNSET) { - lpf_bandwidth = auto_bandwidth(radio, opmode); - } - - if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != lpf_bandwidth) { - max283x_set_lpf_bandwidth(&max283x, MAX283x_MODE_TX, lpf_bandwidth); - radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_RX] = lpf_bandwidth; - radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_TX] = lpf_bandwidth; - radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = lpf_bandwidth; - radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] = lpf_bandwidth; - changed |= - ((1 << RADIO_BB_BANDWIDTH_RX) | (1 << RADIO_BB_BANDWIDTH_TX) | - (1 << RADIO_XCVR_TX_LPF) | (1 << RADIO_XCVR_RX_LPF)); - } + if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != lpf_bandwidth) { + max283x_set_lpf_bandwidth(&max283x, MAX283x_MODE_TX, lpf_bandwidth); + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = lpf_bandwidth; + changed |= (1 << RADIO_XCVR_TX_LPF); + } + if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] != lpf_bandwidth) { + max283x_set_lpf_bandwidth(&max283x, MAX283x_MODE_RX, lpf_bandwidth); + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] = lpf_bandwidth; + changed |= (1 << RADIO_XCVR_RX_LPF); + } + bool narrow_lpf_enable = false; + bool applied_narrow_lpf_enable = + radio->config[RADIO_BANK_APPLIED][RADIO_RX_NARROW_LPF]; + if (lpf_bandwidth <= 1750000) { + narrow_lpf_enable = true; + } + if (applied_narrow_lpf_enable != narrow_lpf_enable) { + narrowband_filter_set(narrow_lpf_enable); + radio->config[RADIO_BANK_APPLIED][RADIO_RX_NARROW_LPF] = + narrow_lpf_enable; + changed |= (1 << RADIO_RX_NARROW_LPF); + } + /* Always set HPF bandwidth to 30 kHz for now. */ + const max283x_rx_hpf_freq_t hpf_bandwidth = MAX283x_RX_HPF_30_KHZ; + if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] != hpf_bandwidth) { + max283x_set_rx_hpf_frequency(&max283x, hpf_bandwidth); + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] = hpf_bandwidth; + changed |= (1 << RADIO_XCVR_RX_HPF); + } #endif + } else { +#if !defined(PRALINE) || defined(UNIVERSAL) + uint64_t lpf_bandwidth; + lpf_bandwidth = bank[RADIO_XCVR_TX_LPF]; + if (lpf_bandwidth == RADIO_UNSET) { + lpf_bandwidth = bank[RADIO_XCVR_RX_LPF]; + } + if (lpf_bandwidth == RADIO_UNSET) { + lpf_bandwidth = bank[RADIO_BB_BANDWIDTH_TX]; + } + if (lpf_bandwidth == RADIO_UNSET) { + lpf_bandwidth = bank[RADIO_BB_BANDWIDTH_RX]; + } + if (lpf_bandwidth == RADIO_UNSET) { + lpf_bandwidth = radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF]; + } + if (lpf_bandwidth == RADIO_UNSET) { + lpf_bandwidth = auto_bandwidth(radio, opmode); + } + + if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != lpf_bandwidth) { + max283x_set_lpf_bandwidth(&max283x, MAX283x_MODE_TX, lpf_bandwidth); + radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_RX] = lpf_bandwidth; + radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_TX] = lpf_bandwidth; + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = lpf_bandwidth; + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] = lpf_bandwidth; + changed |= + ((1 << RADIO_BB_BANDWIDTH_RX) | (1 << RADIO_BB_BANDWIDTH_TX) | + (1 << RADIO_XCVR_TX_LPF) | (1 << RADIO_XCVR_RX_LPF)); + } +#endif + } return changed; } @@ -764,26 +774,24 @@ static uint32_t radio_update_trigger(radio_t* const radio, uint64_t* bank) static uint32_t radio_update_dc_block(radio_t* const radio, uint64_t* bank) { -#ifndef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) + if (detected_platform() == BOARD_ID_PRALINE) { + const uint64_t requested = bank[RADIO_DC_BLOCK]; + bool enable = requested; + + if (radio->config[RADIO_BANK_APPLIED][RADIO_DC_BLOCK] == (uint64_t) enable) { + return 0; + } + + fpga_set_rx_dc_block_enable(&fpga, enable); + radio->config[RADIO_BANK_APPLIED][RADIO_DC_BLOCK] = enable; + return (1 << RADIO_DC_BLOCK); + } +#else (void) radio; (void) bank; - return 0; -#else - const uint64_t requested = bank[RADIO_DC_BLOCK]; - bool enable = requested; - - if (requested == RADIO_UNSET) { - enable = true; - } - - if (radio->config[RADIO_BANK_APPLIED][RADIO_DC_BLOCK] == (uint64_t) enable) { - return 0; - } - - fpga_set_rx_dc_block_enable(&fpga, enable); - radio->config[RADIO_BANK_APPLIED][RADIO_DC_BLOCK] = enable; - return (1 << RADIO_DC_BLOCK); #endif + return 0; } bool radio_update(radio_t* const radio) From 938c020f3b5b146e322c88402325c831e7c5cb8a Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sat, 4 Apr 2026 01:09:30 +0100 Subject: [PATCH 122/238] Universalize: hackrf_core.{c,h}, selftest.h Co-authored-by: Antoine van Gelder --- firmware/common/hackrf_core.c | 781 +++++++++++++++++++++------------- firmware/common/hackrf_core.h | 18 +- firmware/common/selftest.h | 9 +- 3 files changed, 504 insertions(+), 304 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 25e3b870..c8b66443 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -25,7 +25,7 @@ #include #include #include -#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(PRALINE) +#if !defined(RAD1O) #include #endif @@ -41,10 +41,10 @@ #include "platform_scu.h" #include "spi_bus.h" #include "w25q80bv_target.h" -#if defined(HACKRF_ONE) || defined(PRALINE) +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) #include "portapack.h" #endif -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) #include "ice40_spi.h" #endif @@ -124,7 +124,7 @@ ssp_config_t ssp_config_w25q80bv = { .clock_prescale_rate = 2, }; -spi_bus_t spi_bus_ssp0 = { +static spi_bus_t spi_bus_ssp0 = { .obj = (void*) SSP0_BASE, .config = &ssp_config_w25q80bv, .start = spi_ssp_start, @@ -142,8 +142,8 @@ sgpio_config_t sgpio_config = { .slice_mode_multislice = true, }; -#ifdef PRALINE -ssp_config_t ssp_config_ice40_fpga = { +#if defined(PRALINE) || defined(UNIVERSAL) +static ssp_config_t ssp_config_ice40_fpga = { .data_bits = SSP_DATA_8BITS, .spi_mode = SSP_CPOL_1_CPHA_1, .serial_clock_rate = 21, @@ -163,11 +163,9 @@ radio_t radio = { .sample_rate_cb = sample_rate_set, }; -rf_path_t rf_path = { - .switchctrl = 0, -}; +rf_path_t rf_path; -jtag_gpio_t jtag_gpio_cpld = {}; +jtag_gpio_t jtag_gpio_cpld; jtag_t jtag_cpld = { .gpio = &jtag_gpio_cpld, @@ -343,61 +341,77 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) sgpio_cpld_stream_disable(&sgpio_config); } -#ifndef PRALINE - /* Integer mode can be enabled if p1 is even and p2 is zero. */ - if (p1 & 0x1 || p2) { - si5351c_set_int_mode(&clock_gen, 0, 0); - } else { - si5351c_set_int_mode(&clock_gen, 0, 1); - } + if (detected_platform() != BOARD_ID_PRALINE) { +#if !defined(PRALINE) || defined(UNIVERSAL) + /* Integer mode can be enabled if p1 is even and p2 is zero. */ + if (p1 & 0x1 || p2) { + si5351c_set_int_mode(&clock_gen, 0, 0); + } else { + si5351c_set_int_mode(&clock_gen, 0, 1); + } - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - /* - * On HackRF One r9 all sample clocks are externally derived - * from MS1/CLK1 operating at twice the sample rate. - */ - si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 0); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + /* + * On HackRF One r9 all sample clocks are externally derived + * from MS1/CLK1 operating at twice the sample rate. + */ + si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 0); + } else { + /* + * On other platforms the clock generator produces three + * different sample clocks, all derived from multisynth 0. + */ + /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ + si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); + + /* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ + si5351c_configure_multisynth( + &clock_gen, + 1, + 0, + 0, + 0, + 0); //p1 doesn't matter + + /* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */ + si5351c_configure_multisynth( + &clock_gen, + 2, + 0, + 0, + 0, + 0); //p1 doesn't matter + } +#endif } else { - /* - * On other platforms the clock generator produces three - * different sample clocks, all derived from multisynth 0. - */ - /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ +#if defined(PRALINE) || defined(UNIVERSAL) + /* MS0/CLK0 is the source for the MAX5864 (AFE_CLK). */ si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); - /* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ - si5351c_configure_multisynth(&clock_gen, 1, 0, 0, 0, 0); //p1 doesn't matter + /* MS1/CLK1 is the source for the FPGA (FPGA_CLK and SCT_CLK). */ + si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 1); - /* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */ - si5351c_configure_multisynth(&clock_gen, 2, 0, 0, 0, 0); //p1 doesn't matter - } -#else - /* MS0/CLK0 is the source for the MAX5864 (AFE_CLK). */ - si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); + /* Delay FPGA_CLK relative to AFE_CLK. */ + uint8_t phase_offset = 0; + if (p1 < 2100) { + phase_offset = (p1 >> 4) - 6; + } + si5351c_set_phase(&clock_gen, 1, phase_offset); - /* MS1/CLK1 is the source for the FPGA (FPGA_CLK and SCT_CLK). */ - si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 1); + if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { + /* + * On older boards FPGA_CLK is on CLK2 while SCT_CLK is on + * CLK1. We configure both so that behavior is consistent with + * newer boards that use CLK1 for both FPGA_CLK and SCT_CLK. + */ + si5351c_configure_multisynth(&clock_gen, 2, p1, p2, p3, 1); + si5351c_set_phase(&clock_gen, 2, phase_offset); + } - /* Delay FPGA_CLK relative to AFE_CLK. */ - uint8_t phase_offset = 0; - if (p1 < 2100) { - phase_offset = (p1 >> 4) - 6; - } - si5351c_set_phase(&clock_gen, 1, phase_offset); - - if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { - /* - * On older boards FPGA_CLK is on CLK2 while SCT_CLK is on - * CLK1. We configure both so that behavior is consistent with - * newer boards that use CLK1 for both FPGA_CLK and SCT_CLK. - */ - si5351c_configure_multisynth(&clock_gen, 2, p1, p2, p3, 1); - si5351c_set_phase(&clock_gen, 2, phase_offset); - } - - /* Reset PLL to synchronize output clock phase. */ - si5351c_reset_pll(&clock_gen, SI5351C_PLL_A); + /* Reset PLL to synchronize output clock phase. */ + si5351c_reset_pll(&clock_gen, SI5351C_PLL_A); #endif + } if (streaming) { sgpio_cpld_stream_enable(&sgpio_config); @@ -549,7 +563,7 @@ void cpu_clock_init(void) CGU_BASE_SSP1_CLK = CGU_BASE_SSP1_CLK_AUTOBLOCK(1) | CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1); -#if (defined JAWBREAKER || defined HACKRF_ONE || defined PRALINE) +#if !defined(RAD1O) /* Disable unused clocks */ /* Start with PLLs */ CGU_PLL0AUDIO_CTRL = CGU_PLL0AUDIO_CTRL_PD(1); @@ -707,12 +721,20 @@ void clock_gen_shutdown(void) clock_source_t activate_best_clock_source(void) { -#if (defined HACKRF_ONE || defined PRALINE) - /* Ensure PortaPack reference oscillator is off while checking for external clock input. */ - if (portapack_reference_oscillator && portapack()) { - portapack_reference_oscillator(false); - } + switch (detected_platform()) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + case BOARD_ID_PRALINE: +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + /* Ensure PortaPack reference oscillator is off while checking for external clock input. */ + if (portapack_reference_oscillator && portapack()) { + portapack_reference_oscillator(false); + } #endif + break; + default: + break; + } clock_source_t source = CLOCK_SOURCE_HACKRF; @@ -720,18 +742,26 @@ clock_source_t activate_best_clock_source(void) if (si5351c_clkin_signal_valid(&clock_gen)) { source = CLOCK_SOURCE_EXTERNAL; } else { -#if (defined HACKRF_ONE || defined PRALINE) - /* Enable PortaPack reference oscillator (if present), and check for valid clock. */ - if (portapack_reference_oscillator && portapack()) { - portapack_reference_oscillator(true); - delay(510000); /* loop iterations @ 204MHz for >10ms for oscillator to enable. */ - if (si5351c_clkin_signal_valid(&clock_gen)) { - source = CLOCK_SOURCE_PORTAPACK; - } else { - portapack_reference_oscillator(false); + switch (detected_platform()) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + case BOARD_ID_PRALINE: +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + /* Enable PortaPack reference oscillator (if present), and check for valid clock. */ + if (portapack_reference_oscillator && portapack()) { + portapack_reference_oscillator(true); + delay(510000); /* loop iterations @ 204MHz for >10ms for oscillator to enable. */ + if (si5351c_clkin_signal_valid(&clock_gen)) { + source = CLOCK_SOURCE_PORTAPACK; + } else { + portapack_reference_oscillator(false); + } } - } #endif + break; + default: + break; + } /* No external or PortaPack clock was found. Use HackRF Si5351C crystal. */ } @@ -753,7 +783,7 @@ void ssp1_set_mode_max5864(void) spi_bus_start(max5864.bus, &ssp_config_max5864); } -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) void ssp1_set_mode_ice40(void) { spi_bus_start(&spi_bus_ssp1, &ssp_config_ice40_fpga); @@ -762,12 +792,14 @@ void ssp1_set_mode_ice40(void) void pin_shutdown(void) { - const platform_gpio_t* gpio = platform_gpio(); - const platform_scu_t* scu = platform_scu(); - /* Configure all GPIO as Input (safe state) */ gpio_init(); + /* Detect Platform */ + board_id_t board_id = detected_platform(); + const platform_gpio_t* gpio = platform_gpio(); + const platform_scu_t* scu = platform_scu(); + /* TDI and TMS pull-ups are required in all JTAG-compliant devices. * * The HackRF CPLD is always present, so let the CPLD pull up its TDI and TMS. @@ -782,119 +814,159 @@ void pin_shutdown(void) * * LPC43xx pull-up and pull-down resistors are approximately 53K. */ -#if (defined HACKRF_ONE || defined PRALINE) - scu_pinmux(scu->PINMUX_PP_TMS, SCU_GPIO_PUP | SCU_CONF_FUNCTION0); - scu_pinmux(scu->PINMUX_PP_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + case BOARD_ID_PRALINE: +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + scu_pinmux(scu->PINMUX_PP_TMS, SCU_GPIO_PUP | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_PP_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); #endif + break; + default: + break; + } scu_pinmux(scu->PINMUX_CPLD_TCK, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); -#ifndef PRALINE - scu_pinmux(scu->PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - scu_pinmux(scu->PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - scu_pinmux(scu->PINMUX_CPLD_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); + if (board_id != BOARD_ID_PRALINE) { +#if !defined(PRALINE) || defined(UNIVERSAL) + scu_pinmux(scu->PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_CPLD_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); #endif + } /* Configure SCU Pin Mux as GPIO */ scu_pinmux(scu->PINMUX_LED1, SCU_GPIO_NOPULL); scu_pinmux(scu->PINMUX_LED2, SCU_GPIO_NOPULL); scu_pinmux(scu->PINMUX_LED3, SCU_GPIO_NOPULL); -#ifdef RAD1O - scu_pinmux(scu->PINMUX_LED4, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION4); + switch (board_id) { + case BOARD_ID_RAD1O: +#if defined(RAD1O) + scu_pinmux(scu->PINMUX_LED4, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION4); #endif -#ifdef PRALINE - scu_pinmux(scu->PINMUX_LED4, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + scu_pinmux(scu->PINMUX_LED4, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); #endif + break; + default: + break; + } /* Configure USB indicators */ -#ifdef JAWBREAKER - scu_pinmux(scu->PINMUX_USB_LED0, SCU_CONF_FUNCTION3); - scu_pinmux(scu->PINMUX_USB_LED1, SCU_CONF_FUNCTION3); + if (board_id == BOARD_ID_JAWBREAKER) { +#if defined(JAWBREAKER) + scu_pinmux(scu->PINMUX_USB_LED0, SCU_CONF_FUNCTION3); + scu_pinmux(scu->PINMUX_USB_LED1, SCU_CONF_FUNCTION3); #endif - -#ifdef PRALINE - disable_1v2_power(); - disable_3v3aux_power(); - gpio_output(gpio->gpio_1v2_enable); - gpio_output(gpio->gpio_3v3aux_enable_n); - scu_pinmux(scu->PINMUX_EN1V2, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(scu->PINMUX_EN3V3_AUX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); -#else - disable_1v8_power(); - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - #ifdef HACKRF_ONE - gpio_output(gpio->h1r9_1v8_enable); - scu_pinmux(scu->H1R9_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - #endif - } else { - gpio_output(gpio->gpio_1v8_enable); - scu_pinmux(scu->PINMUX_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); } + + switch (board_id) { + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + disable_1v2_power(); + disable_3v3aux_power(); + gpio_output(gpio->gpio_1v2_enable); + gpio_output(gpio->gpio_3v3aux_enable_n); + scu_pinmux(scu->PINMUX_EN1V2, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_EN3V3_AUX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); #endif - -#if (defined HACKRF_ONE || defined PRALINE) - /* Safe state: start with VAA turned off: */ - disable_rf_power(); - - /* Configure RF power supply (VAA) switch control signal as output */ - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - #ifdef HACKRF_ONE - gpio_output(gpio->h1r9_vaa_disable); - #endif - } else { - gpio_output(gpio->vaa_disable); + break; + default: + disable_1v8_power(); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + gpio_output(gpio->h1r9_1v8_enable); + scu_pinmux(scu->H1R9_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); +#endif + } else { + gpio_output(gpio->gpio_1v8_enable); + scu_pinmux(scu->PINMUX_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + } + break; } + + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + case BOARD_ID_PRALINE: +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + /* Safe state: start with VAA turned off: */ + disable_rf_power(); + + /* Configure RF power supply (VAA) switch control signal as output */ + if (board_id == BOARD_ID_HACKRF1_R9) { + #if defined(HACKRF_ONE) || defined(UNIVERSAL) + gpio_output(gpio->h1r9_vaa_disable); + #endif + } else { + gpio_output(gpio->vaa_disable); + } + break; #endif + case BOARD_ID_RAD1O: +#if defined(RAD1O) + /* Safe state: start with VAA turned off: */ + disable_rf_power(); -#ifdef RAD1O - /* Safe state: start with VAA turned off: */ - disable_rf_power(); + /* Configure RF power supply (VAA) switch control signal as output */ + gpio_output(gpio->vaa_enable); - /* Configure RF power supply (VAA) switch control signal as output */ - gpio_output(gpio->vaa_enable); + /* Disable unused clock outputs. They generate noise. */ + scu_pinmux(CLK0, SCU_CLK_IN | SCU_CONF_FUNCTION7); + scu_pinmux(CLK2, SCU_CLK_IN | SCU_CONF_FUNCTION7); - /* Disable unused clock outputs. They generate noise. */ - scu_pinmux(CLK0, SCU_CLK_IN | SCU_CONF_FUNCTION7); - scu_pinmux(CLK2, SCU_CLK_IN | SCU_CONF_FUNCTION7); - - scu_pinmux(scu->PINMUX_GPIO3_10, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); - scu_pinmux(scu->PINMUX_GPIO3_11, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_GPIO3_10, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_GPIO3_11, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); #endif + break; + default: + break; + } -#ifdef PRALINE - scu_pinmux(scu->P2_CTRL0, scu->P2_CTRL0_PINCFG); - scu_pinmux(scu->P2_CTRL1, scu->P2_CTRL1_PINCFG); - scu_pinmux(scu->P1_CTRL0, scu->P1_CTRL0_PINCFG); - scu_pinmux(scu->P1_CTRL1, scu->P1_CTRL1_PINCFG); - scu_pinmux(scu->P1_CTRL2, scu->P1_CTRL2_PINCFG); - scu_pinmux(scu->CLKIN_CTRL, scu->CLKIN_CTRL_PINCFG); - scu_pinmux(scu->AA_EN, scu->AA_EN_PINCFG); - scu_pinmux(scu->TRIGGER_IN, scu->TRIGGER_IN_PINCFG); - scu_pinmux(scu->TRIGGER_OUT, scu->TRIGGER_OUT_PINCFG); - scu_pinmux(scu->PPS_OUT, scu->PPS_OUT_PINCFG); - scu_pinmux(scu->PINMUX_FPGA_CRESET, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - scu_pinmux(scu->PINMUX_FPGA_CDONE, SCU_GPIO_PUP | SCU_CONF_FUNCTION4); - scu_pinmux(scu->PINMUX_FPGA_SPI_CS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + switch (board_id) { + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + scu_pinmux(scu->P2_CTRL0, scu->P2_CTRL0_PINCFG); + scu_pinmux(scu->P2_CTRL1, scu->P2_CTRL1_PINCFG); + scu_pinmux(scu->P1_CTRL0, scu->P1_CTRL0_PINCFG); + scu_pinmux(scu->P1_CTRL1, scu->P1_CTRL1_PINCFG); + scu_pinmux(scu->P1_CTRL2, scu->P1_CTRL2_PINCFG); + scu_pinmux(scu->CLKIN_CTRL, scu->CLKIN_CTRL_PINCFG); + scu_pinmux(scu->AA_EN, scu->AA_EN_PINCFG); + scu_pinmux(scu->TRIGGER_IN, scu->TRIGGER_IN_PINCFG); + scu_pinmux(scu->TRIGGER_OUT, scu->TRIGGER_OUT_PINCFG); + scu_pinmux(scu->PPS_OUT, scu->PPS_OUT_PINCFG); + scu_pinmux(scu->PINMUX_FPGA_CRESET, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_FPGA_CDONE, SCU_GPIO_PUP | SCU_CONF_FUNCTION4); + scu_pinmux(scu->PINMUX_FPGA_SPI_CS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - p2_ctrl_set(P2_SIGNAL_CLK3); - p1_ctrl_set(P1_SIGNAL_CLKIN); - narrowband_filter_set(0); - clkin_ctrl_set(CLKIN_SIGNAL_P22); + p2_ctrl_set(P2_SIGNAL_CLK3); + p1_ctrl_set(P1_SIGNAL_CLKIN); + narrowband_filter_set(0); + clkin_ctrl_set(CLKIN_SIGNAL_P22); - gpio_output(gpio->p2_ctrl0); - gpio_output(gpio->p2_ctrl1); - gpio_output(gpio->p1_ctrl0); - gpio_output(gpio->p1_ctrl1); - gpio_output(gpio->p1_ctrl2); - gpio_output(gpio->clkin_ctrl); - gpio_output(gpio->pps_out); - gpio_output(gpio->aa_en); - gpio_input(gpio->trigger_in); - gpio_input(gpio->trigger_out); - gpio_clear(gpio->fpga_cfg_spi_cs); - gpio_output(gpio->fpga_cfg_spi_cs); - gpio_clear(gpio->fpga_cfg_creset); - gpio_output(gpio->fpga_cfg_creset); - gpio_input(gpio->fpga_cfg_cdone); + gpio_output(gpio->p2_ctrl0); + gpio_output(gpio->p2_ctrl1); + gpio_output(gpio->p1_ctrl0); + gpio_output(gpio->p1_ctrl1); + gpio_output(gpio->p1_ctrl2); + gpio_output(gpio->clkin_ctrl); + gpio_output(gpio->pps_out); + gpio_output(gpio->aa_en); + gpio_input(gpio->trigger_in); + gpio_input(gpio->trigger_out); + gpio_clear(gpio->fpga_cfg_spi_cs); + gpio_output(gpio->fpga_cfg_spi_cs); + gpio_clear(gpio->fpga_cfg_creset); + gpio_output(gpio->fpga_cfg_creset); + gpio_input(gpio->fpga_cfg_cdone); #endif + break; + default: + break; + } /* enable input on SCL and SDA pins */ SCU_SFSI2C0 = SCU_I2C0_NOMINAL; @@ -903,30 +975,43 @@ void pin_shutdown(void) /* Run after pin_shutdown() and prior to enabling power supplies. */ void pin_setup(void) { + /* Detect Platform */ + board_id_t board_id = detected_platform(); const platform_gpio_t* gpio = platform_gpio(); const platform_scu_t* scu = platform_scu(); + /* Configure LEDs */ led_off(0); led_off(1); led_off(2); -#ifdef RAD1O - led_off(3); -#endif + switch (board_id) { + case BOARD_ID_RAD1O: + led_off(3); + default: + break; + } gpio_output(gpio->led[0]); gpio_output(gpio->led[1]); gpio_output(gpio->led[2]); -#if (defined RAD1O || defined PRALINE) - gpio_output(gpio->led[3]); + switch (board_id) { + case BOARD_ID_RAD1O: + case BOARD_ID_PRALINE: +#if defined(RAD1O) || defined(PRALINE) || defined(UNIVERSAL) + gpio_output(gpio->led[3]); #endif + break; + default: + break; + } /* Configure drivers and driver pins */ ssp_config_max283x.gpio_select = gpio->max283x_select; -#if defined(PRALINE) - ssp_config_max283x.data_bits = SSP_DATA_9BITS; // send 2 words -#else - ssp_config_max283x.data_bits = SSP_DATA_16BITS; -#endif + if (board_id == BOARD_ID_PRALINE) { + ssp_config_max283x.data_bits = SSP_DATA_9BITS; // send 2 words + } else { + ssp_config_max283x.data_bits = SSP_DATA_16BITS; + } ssp_config_max5864.gpio_select = gpio->max5864_select; @@ -935,11 +1020,13 @@ void pin_setup(void) spi_flash.gpio_wp = gpio->w25q80bv_wp; sgpio_config.gpio_q_invert = gpio->q_invert; -#if !defined(PRALINE) - sgpio_config.gpio_trigger_enable = gpio->trigger_enable; + if (board_id != BOARD_ID_PRALINE) { +#if !defined(PRALINE) || defined(UNIVERSAL) + sgpio_config.gpio_trigger_enable = gpio->trigger_enable; #endif + } -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) ssp_config_ice40_fpga.gpio_select = gpio->fpga_cfg_spi_cs; ice40.gpio_select = gpio->fpga_cfg_spi_cs; ice40.gpio_creset = gpio->fpga_cfg_creset; @@ -952,73 +1039,102 @@ void pin_setup(void) jtag_gpio_cpld.gpio_tdi = gpio->cpld_tdi; jtag_gpio_cpld.gpio_tdo = gpio->cpld_tdo; #endif -#if defined(HACKRF_ONE) || defined(PRALINE) - jtag_gpio_cpld.gpio_pp_tms = gpio->cpld_pp_tms; - jtag_gpio_cpld.gpio_pp_tdo = gpio->cpld_pp_tdo; + if (board_id != BOARD_ID_PRALINE) { +#if !defined(PRALINE) || defined(UNIVERSAL) + jtag_gpio_cpld.gpio_tms = gpio->cpld_tms; + jtag_gpio_cpld.gpio_tdi = gpio->cpld_tdi; + jtag_gpio_cpld.gpio_tdo = gpio->cpld_tdo; #endif + } + switch (board_id) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + case BOARD_ID_PRALINE: +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + jtag_gpio_cpld.gpio_pp_tms = gpio->cpld_pp_tms; + jtag_gpio_cpld.gpio_pp_tdo = gpio->cpld_pp_tdo; +#endif + break; + default: + break; + } ssp1_set_mode_max283x(); mixer_bus_setup(&mixer); -#if defined(HACKRF_ONE) if (detected_platform() == BOARD_ID_HACKRF1_R9) { - rf_path.gpio_rx = gpio->h1r9_rx; +#if defined(HACKRF_ONE) || defined(UNIVERSAL) sgpio_config.gpio_trigger_enable = gpio->h1r9_trigger_enable; - } #endif + } - /* Configure RF path */ -#if defined(HACKRF_ONE) - rf_path = (rf_path_t){ - .switchctrl = 0, - .gpio_hp = gpio->hp, - .gpio_lp = gpio->lp, - .gpio_tx_mix_bp = gpio->tx_mix_bp, - .gpio_no_mix_bypass = gpio->no_mix_bypass, - .gpio_rx_mix_bp = gpio->rx_mix_bp, - .gpio_tx_amp = gpio->tx_amp, - .gpio_tx = gpio->tx, - .gpio_mix_bypass = gpio->mix_bypass, - .gpio_rx = gpio->rx, - .gpio_no_tx_amp_pwr = gpio->no_tx_amp_pwr, - .gpio_amp_bypass = gpio->amp_bypass, - .gpio_rx_amp = gpio->rx_amp, - .gpio_no_rx_amp_pwr = gpio->no_rx_amp_pwr, - }; - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - rf_path.gpio_rx = gpio->h1r9_rx; - rf_path.gpio_h1r9_no_ant_pwr = gpio->h1r9_no_ant_pwr; - } -#elif defined(RAD1O) - rf_path = (rf_path_t){ - .switchctrl = 0, - .gpio_tx_rx_n = gpio->tx_rx_n, - .gpio_tx_rx = gpio->tx_rx, - .gpio_by_mix = gpio->by_mix, - .gpio_by_mix_n = gpio->by_mix_n, - .gpio_by_amp = gpio->by_amp, - .gpio_by_amp_n = gpio->by_amp_n, - .gpio_mixer_en = gpio->mixer_en, - .gpio_low_high_filt = gpio->low_high_filt, - .gpio_low_high_filt_n = gpio->low_high_filt_n, - .gpio_tx_amp = gpio->tx_amp, - .gpio_rx_lna = gpio->rx_lna, - }; -#elif defined(PRALINE) - rf_path = (rf_path_t){ - .switchctrl = 0, - .gpio_tx_en = gpio->tx_en, - .gpio_mix_en_n = gpio->mix_en_n, - .gpio_lpf_en = gpio->lpf_en, - .gpio_rf_amp_en = gpio->rf_amp_en, - .gpio_ant_bias_en_n = gpio->ant_bias_en_n, - }; - board_rev_t rev = detected_revision(); - if ((rev == BOARD_REV_PRALINE_R1_0) || (rev == BOARD_REV_GSG_PRALINE_R1_0)) { - rf_path.gpio_mix_en_n = gpio->mix_en_n_r1_0; - } + // initialize rf_path struct and assign gpio's + switch (board_id) { + case BOARD_ID_JAWBREAKER: + break; + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + rf_path = (rf_path_t){ + .switchctrl = 0, + .gpio_hp = gpio->hp, + .gpio_lp = gpio->lp, + .gpio_tx_mix_bp = gpio->tx_mix_bp, + .gpio_no_mix_bypass = gpio->no_mix_bypass, + .gpio_rx_mix_bp = gpio->rx_mix_bp, + .gpio_tx_amp = gpio->tx_amp, + .gpio_tx = gpio->tx, + .gpio_mix_bypass = gpio->mix_bypass, + .gpio_rx = gpio->rx, + .gpio_no_tx_amp_pwr = gpio->no_tx_amp_pwr, + .gpio_amp_bypass = gpio->amp_bypass, + .gpio_rx_amp = gpio->rx_amp, + .gpio_no_rx_amp_pwr = gpio->no_rx_amp_pwr, + }; + if (board_id == BOARD_ID_HACKRF1_R9) { + rf_path.gpio_rx = gpio->h1r9_rx; + rf_path.gpio_h1r9_no_ant_pwr = gpio->h1r9_no_ant_pwr; + } #endif + break; + case BOARD_ID_RAD1O: +#if defined(RAD1O) + rf_path = (rf_path_t){ + .switchctrl = 0, + .gpio_tx_rx_n = gpio->tx_rx_n, + .gpio_tx_rx = gpio->tx_rx, + .gpio_by_mix = gpio->by_mix, + .gpio_by_mix_n = gpio->by_mix_n, + .gpio_by_amp = gpio->by_amp, + .gpio_by_amp_n = gpio->by_amp_n, + .gpio_mixer_en = gpio->mixer_en, + .gpio_low_high_filt = gpio->low_high_filt, + .gpio_low_high_filt_n = gpio->low_high_filt_n, + .gpio_tx_amp = gpio->tx_amp, + .gpio_rx_lna = gpio->rx_lna, + }; +#endif + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + rf_path = (rf_path_t){ + .switchctrl = 0, + .gpio_tx_en = gpio->tx_en, + .gpio_mix_en_n = gpio->mix_en_n, + .gpio_lpf_en = gpio->lpf_en, + .gpio_rf_amp_en = gpio->rf_amp_en, + .gpio_ant_bias_en_n = gpio->ant_bias_en_n, + }; + if ((detected_revision() == BOARD_REV_PRALINE_R1_0) || + (detected_revision() == BOARD_REV_GSG_PRALINE_R1_0)) { + rf_path.gpio_mix_en_n = gpio->mix_en_n_r1_0; + } +#endif + break; + default: + break; + } rf_path_pin_setup(&rf_path); /* Configure external clock in */ @@ -1027,52 +1143,86 @@ void pin_setup(void) sgpio_configure_pin_functions(&sgpio_config); } -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) void enable_1v2_power(void) { - gpio_set(platform_gpio()->gpio_1v2_enable); + switch (detected_platform()) { + case BOARD_ID_PRALINE: + gpio_set(platform_gpio()->gpio_1v2_enable); + break; + default: + break; + } } void disable_1v2_power(void) { - gpio_clear(platform_gpio()->gpio_1v2_enable); + switch (detected_platform()) { + case BOARD_ID_PRALINE: + gpio_clear(platform_gpio()->gpio_1v2_enable); + break; + default: + break; + } } void enable_3v3aux_power(void) { - gpio_clear(platform_gpio()->gpio_3v3aux_enable_n); + switch (detected_platform()) { + case BOARD_ID_PRALINE: + gpio_clear(platform_gpio()->gpio_3v3aux_enable_n); + break; + default: + break; + } } void disable_3v3aux_power(void) { - gpio_set(platform_gpio()->gpio_3v3aux_enable_n); + switch (detected_platform()) { + case BOARD_ID_PRALINE: + gpio_set(platform_gpio()->gpio_3v3aux_enable_n); + break; + default: + break; + } } -#else +#endif + void enable_1v8_power(void) { - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - #ifdef HACKRF_ONE + switch (detected_platform()) { + case BOARD_ID_HACKRF1_R9: +#if defined(HACKRF_ONE) || defined(UNIVERSAL) gpio_set(platform_gpio()->h1r9_1v8_enable); - #endif - } else { +#endif + break; + case BOARD_ID_PRALINE: + break; + default: gpio_set(platform_gpio()->gpio_1v8_enable); + break; } } void disable_1v8_power(void) { - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - #ifdef HACKRF_ONE + switch (detected_platform()) { + case BOARD_ID_HACKRF1_R9: +#if defined(HACKRF_ONE) || defined(UNIVERSAL) gpio_clear(platform_gpio()->h1r9_1v8_enable); - #endif - } else { +#endif + break; + case BOARD_ID_PRALINE: + break; + default: gpio_clear(platform_gpio()->gpio_1v8_enable); + break; } } -#endif -#ifdef HACKRF_ONE -void enable_rf_power(void) +#if defined(HACKRF_ONE) || defined(UNIVERSAL) +static inline void enable_rf_power_hackrf_one(void) { const platform_gpio_t* gpio = platform_gpio(); uint32_t i; @@ -1089,7 +1239,7 @@ void enable_rf_power(void) } } -void disable_rf_power(void) +static inline void disable_rf_power_hackrf_one(void) { if (detected_platform() == BOARD_ID_HACKRF1_R9) { gpio_set(platform_gpio()->h1r9_vaa_disable); @@ -1099,8 +1249,8 @@ void disable_rf_power(void) } #endif -#ifdef PRALINE -void enable_rf_power(void) +#if defined(PRALINE) || defined(UNIVERSAL) +static inline void enable_rf_power_praline(void) { gpio_clear(platform_gpio()->vaa_disable); @@ -1108,14 +1258,14 @@ void enable_rf_power(void) delay(1000000); } -void disable_rf_power(void) +static inline void disable_rf_power_praline(void) { gpio_set(platform_gpio()->vaa_disable); } #endif -#ifdef RAD1O -void enable_rf_power(void) +#if defined(RAD1O) +static inline void enable_rf_power_rad1o(void) { gpio_set(platform_gpio()->vaa_enable); @@ -1123,33 +1273,77 @@ void enable_rf_power(void) delay(1000000); } -void disable_rf_power(void) +static inline void disable_rf_power_rad1o(void) { gpio_clear(platform_gpio()->vaa_enable); } #endif -#ifdef PRALINE -void led_on(const led_t led) +void enable_rf_power(void) { - gpio_clear(platform_gpio()->led[led]); -} - -void led_off(const led_t led) -{ - gpio_set(platform_gpio()->led[led]); -} -#else -void led_on(const led_t led) -{ - gpio_set(platform_gpio()->led[led]); -} - -void led_off(const led_t led) -{ - gpio_clear(platform_gpio()->led[led]); -} + switch (detected_platform()) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + enable_rf_power_hackrf_one(); #endif + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + enable_rf_power_praline(); +#endif + break; + case BOARD_ID_RAD1O: +#if defined(RAD1O) + enable_rf_power_rad1o(); +#endif + break; + default: + break; + } +} + +void disable_rf_power(void) +{ + switch (detected_platform()) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + disable_rf_power_hackrf_one(); +#endif + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + disable_rf_power_praline(); +#endif + break; + case BOARD_ID_RAD1O: +#if defined(RAD1O) + disable_rf_power_rad1o(); +#endif + break; + default: + break; + } +} + +void led_on(const led_t led) +{ + if (detected_platform() == BOARD_ID_PRALINE) { + gpio_clear(platform_gpio()->led[led]); + } else { + gpio_set(platform_gpio()->led[led]); + } +} + +void led_off(const led_t led) +{ + if (detected_platform() == BOARD_ID_PRALINE) { + gpio_set(platform_gpio()->led[led]); + } else { + gpio_clear(platform_gpio()->led[led]); + } +} void led_toggle(const led_t led) { @@ -1158,26 +1352,33 @@ void led_toggle(const led_t led) void set_leds(const uint8_t state) { + board_id_t board_id = detected_platform(); + int num_leds = 3; -#if (defined RAD1O || defined PRALINE) - num_leds = 4; -#endif + if (board_id == BOARD_ID_RAD1O || board_id == BOARD_ID_PRALINE) { + num_leds = 4; + } + for (int i = 0; i < num_leds; i++) { -#ifdef PRALINE - gpio_write(platform_gpio()->led[i], ((state >> i) & 1) == 0); -#else - gpio_write(platform_gpio()->led[i], ((state >> i) & 1) == 1); -#endif + if (board_id == BOARD_ID_PRALINE) { + gpio_write(platform_gpio()->led[i], ((state >> i) & 1) == 0); + } else { + gpio_write(platform_gpio()->led[i], ((state >> i) & 1) == 1); + } } } void trigger_enable(const bool enable) { -#ifndef PRALINE - gpio_write(sgpio_config.gpio_trigger_enable, enable); -#else - fpga_set_trigger_enable(&fpga, enable); + if (detected_platform() != BOARD_ID_PRALINE) { +#if !defined(PRALINE) || defined(UNIVERSAL) + gpio_write(sgpio_config.gpio_trigger_enable, enable); #endif + } else { +#if defined(PRALINE) || defined(UNIVERSAL) + fpga_set_trigger_enable(&fpga, enable); +#endif + } } void halt_and_flash(const uint32_t duration) @@ -1195,7 +1396,7 @@ void halt_and_flash(const uint32_t duration) } } -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) void p1_ctrl_set(const p1_ctrl_signal_t signal) { const platform_gpio_t* gpio = platform_gpio(); diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 539ce770..93bc44c9 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Benjamin Vernoux * Copyright 2012 Jared Boone * @@ -42,7 +42,7 @@ extern "C" { #include "si5351c.h" #include "spi_ssp.h" #include "w25q80bv.h" -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) #include "fpga.h" #include "ice40_spi.h" #endif @@ -51,7 +51,8 @@ extern "C" { extern si5351c_driver_t clock_gen; extern ssp_config_t ssp_config_w25q80bv; -#ifdef PRALINE +extern max283x_driver_t max283x; +#if defined(PRALINE) || defined(UNIVERSAL) extern ice40_spi_driver_t ice40; extern fpga_driver_t fpga; #endif @@ -70,28 +71,27 @@ void clock_gen_init(void); void clock_gen_shutdown(void); void ssp1_set_mode_max283x(void); void ssp1_set_mode_max5864(void); -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) void ssp1_set_mode_ice40(void); #endif void pin_shutdown(void); void pin_setup(void); -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) void enable_1v2_power(void); void disable_1v2_power(void); void enable_3v3aux_power(void); void disable_3v3aux_power(void); -#else +#endif void enable_1v8_power(void); void disable_1v8_power(void); -#endif fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program); clock_source_t activate_best_clock_source(void); -#if (defined HACKRF_ONE || defined RAD1O || defined PRALINE) +#if defined(RAD1O) || defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) void enable_rf_power(void); void disable_rf_power(void); #endif @@ -112,7 +112,7 @@ void trigger_enable(const bool enable); void halt_and_flash(const uint32_t duration); -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) typedef enum { P1_SIGNAL_TRIGGER_IN = 0, P1_SIGNAL_AUX_CLK1 = 1, diff --git a/firmware/common/selftest.h b/firmware/common/selftest.h index 28e02415..8223a582 100644 --- a/firmware/common/selftest.h +++ b/firmware/common/selftest.h @@ -37,23 +37,22 @@ typedef uint8_t test_result_t; typedef struct { uint16_t mixer_id; -#ifndef RAD1O +#if !defined(RAD1O) bool mixer_locks[NUM_LOCK_ATTEMPTS]; #endif -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) uint16_t max2831_mux_rssi_1; uint16_t max2831_mux_temp; uint16_t max2831_mux_rssi_2; bool max2831_mux_test_ok; -#else +#endif uint16_t max283x_readback_bad_value; uint16_t max283x_readback_expected_value; uint8_t max283x_readback_register_count; uint8_t max283x_readback_total_registers; -#endif uint8_t si5351_rev_id; bool si5351_readback_ok; -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) test_result_t fpga_image_load; test_result_t fpga_spi; test_result_t sgpio_rx; From 85dfacf6efa420955c949aa426282ad7a1681d23 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sat, 4 Apr 2026 01:12:34 +0100 Subject: [PATCH 123/238] Universalize: firmware/hackrf_usb Co-authored-by: Antoine van Gelder --- firmware/hackrf_usb/hackrf_usb.c | 192 ++++++++++++++-------- firmware/hackrf_usb/usb_api_board_info.c | 15 +- firmware/hackrf_usb/usb_api_cpld.c | 10 ++ firmware/hackrf_usb/usb_api_praline.c | 21 +++ firmware/hackrf_usb/usb_api_register.h | 2 +- firmware/hackrf_usb/usb_api_selftest.c | 170 ++++++++++--------- firmware/hackrf_usb/usb_api_sweep.c | 19 ++- firmware/hackrf_usb/usb_api_transceiver.c | 11 ++ firmware/hackrf_usb/usb_descriptor.c | 132 +++++++++++---- firmware/hackrf_usb/usb_descriptor.h | 28 +++- firmware/hackrf_usb/usb_device.c | 43 ++++- firmware/hackrf_usb/usb_device.h | 13 ++ 12 files changed, 453 insertions(+), 203 deletions(-) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 3238ca0e..4952f85d 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -48,23 +48,22 @@ #include #include #include -#if !defined(RAD1O) - #include -#endif -#if defined(PRALINE) || defined(HACKRF_ONE) +#if defined(PRALINE) || defined(HACKRF_ONE) || defined(UNIVERSAL) #include #endif -#if defined(PRALINE) || defined(HACKRF_ONE) || defined(JAWBREAKER) +#if !defined(RAD1O) + #include #include #endif -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) #include #if !(defined(DFU_MODE) || defined(RAM_MODE)) #include #include #include #endif -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) #include #include #endif @@ -82,9 +81,10 @@ #include "usb_descriptor.h" #include "usb_device.h" #include "usb_endpoint.h" -#if defined(PRALINE) +#if defined(PRALINE) || defined(UNIVERSAL) #include "usb_api_praline.h" -#else +#endif +#if !defined(PRALINE) || defined(UNIVERSAL) #include "usb_api_cpld.h" #endif @@ -102,12 +102,12 @@ static usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_read_si5351c, usb_vendor_request_set_sample_rate_frac, usb_vendor_request_set_baseband_filter_bandwidth, -#ifdef RAD1O - NULL, // write_rffc5071 not used - NULL, // read_rffc5071 not used -#else +#if !defined(RAD1O) usb_vendor_request_write_rffc5071, usb_vendor_request_read_rffc5071, +#else + NULL, // write_rffc5071 not used + NULL, // read_rffc5071 not used #endif usb_vendor_request_erase_spiflash, usb_vendor_request_write_spiflash, @@ -122,7 +122,7 @@ static usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_set_vga_gain, usb_vendor_request_set_txvga_gain, NULL, // was set_if_freq -#if (defined HACKRF_ONE || defined PRALINE) +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) usb_vendor_request_set_antenna_enable, #else NULL, @@ -139,7 +139,7 @@ static usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_spiflash_status, usb_vendor_request_spiflash_clear_status, usb_vendor_request_operacake_gpio_test, -#ifdef HACKRF_ONE +#if defined(HACKRF_ONE) || defined(UNIVERSAL) usb_vendor_request_cpld_checksum, #else NULL, @@ -156,7 +156,7 @@ static usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_read_supported_platform, usb_vendor_request_set_leds, usb_vendor_request_user_config_set_bias_t_opts, -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) usb_vendor_request_write_fpga_reg, usb_vendor_request_read_fpga_reg, usb_vendor_request_p2_ctrl, @@ -252,7 +252,7 @@ void usb_set_descriptor_by_serial_number(void) } } -#ifndef PRALINE +#if !defined(PRALINE) || defined(UNIVERSAL) static bool cpld_jtag_sram_load(jtag_t* const jtag) { cpld_jtag_take(jtag); @@ -280,7 +280,7 @@ static void m0_rom_to_ram(void) memcpy(dest, (uint32_t*) (base + src), len); } -#if defined(PRALINE) && !(defined(DFU_MODE) || defined(RAM_MODE)) +#if (defined(PRALINE) || defined(UNIVERSAL)) && !(defined(DFU_MODE) || defined(RAM_MODE)) extern uint32_t _binary_fpga_bin_start; void fpga_loader_setup(void) @@ -347,7 +347,7 @@ void radio_changed(const uint32_t changed) if (opmode != TRANSCEIVER_MODE_RX_SWEEP) { hackrf_ui()->set_frequency(freq / FP_ONE_HZ); } -#if defined(HACKRF_ONE) || defined(PRALINE) +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) operacake_set_range(freq / FP_ONE_MHZ); #endif } @@ -435,74 +435,91 @@ int main(void) // Detect hardware platform before we do anything else. detect_hardware_platform(); + board_id_t board_id = detected_platform(); pin_shutdown(); -#ifndef RAD1O - clock_gen_shutdown(); -#endif + if (board_id != BOARD_ID_RAD1O) { + clock_gen_shutdown(); + } delay_us_at_mhz(10000, 96); pin_setup(); -#ifndef PRALINE - enable_1v8_power(); - #ifndef RAD1O - /* - * On rad1o, the clock generator power supply comes from the RF supply - * which is enabled later. On H1 and Jawbreaker, the clock generator is - * on the main 3V3 supply. - */ - clock_gen_init(); - #endif -#else - enable_3v3aux_power(); + if (board_id != BOARD_ID_PRALINE) { + enable_1v8_power(); + if (board_id != BOARD_ID_RAD1O) { + /* + * On rad1o, the clock generator power supply comes from the RF supply + * which is enabled later. On H1 and Jawbreaker, the clock generator is + * on the main 3V3 supply. + */ + clock_gen_init(); + } + } else { +#if defined(PRALINE) || defined(UNIVERSAL) + enable_3v3aux_power(); #if !defined(DFU_MODE) && !defined(RAM_MODE) - enable_1v2_power(); - enable_rf_power(); - /* - * On Praline, the clock generator power supply comes from 3V3FPGA - * which is enabled when 1V2FPGA is turned on. - */ - clock_gen_init(); + enable_1v2_power(); + enable_rf_power(); + /* + * On Praline, the clock generator power supply comes from 3V3FPGA + * which is enabled when 1V2FPGA is turned on. + */ + clock_gen_init(); #endif #endif + } tuning_setup(); -#ifdef HACKRF_ONE - // Set up mixer before enabling RF power, because its - // GPO is used to control the antenna bias tee. - mixer_setup(&mixer, RFFC5071_VARIANT); + if (board_id == BOARD_ID_HACKRF1_OG || board_id == BOARD_ID_HACKRF1_R9) { +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + // Set up mixer before enabling RF power, because its + // GPO is used to control the antenna bias tee. + mixer_setup(&mixer, RFFC5071_VARIANT); #endif -#if (defined HACKRF_ONE || defined RAD1O) - enable_rf_power(); -#endif -#ifdef RAD1O - clock_gen_init(); + } + if (board_id == BOARD_ID_HACKRF1_OG || board_id == BOARD_ID_HACKRF1_R9 || + board_id == BOARD_ID_RAD1O) { +#if defined(RAD1O) || defined(HACKRF_ONE) || defined(UNIVERSAL) + enable_rf_power(); #endif + } + if (board_id == BOARD_ID_RAD1O) { + clock_gen_init(); + } cpu_clock_init(); /* Wake the M0 */ ipc_halt_m0(); ipc_start_m0((uint32_t) &__ram_m0_start__); -#ifndef PRALINE - if (!cpld_jtag_sram_load(&jtag_cpld)) { - halt_and_flash(6000000); +#if !defined(PRALINE) || defined(UNIVERSAL) + if (board_id != BOARD_ID_PRALINE) { + if (!cpld_jtag_sram_load(&jtag_cpld)) { + halt_and_flash(6000000); + } } -#else - #if defined(DFU_MODE) || defined(RAM_MODE) - selftest.fpga_image_load = SKIPPED; - selftest.report.pass = false; - #else - fpga_image_load(&fpga_loader, 0); - #endif - delay_us_at_mhz(100, 204); - fpga_spi_selftest(); - fpga_sgpio_selftest(); #endif +#if defined(PRALINE) || defined(UNIVERSAL) + if (board_id == BOARD_ID_PRALINE) { + #if defined(DFU_MODE) || defined(RAM_MODE) + selftest.fpga_image_load = SKIPPED; + selftest.report.pass = false; + #else + fpga_image_load(&fpga_loader, 0); + #endif + delay_us_at_mhz(100, 204); + fpga_spi_selftest(); + fpga_sgpio_selftest(); + } +#endif + radio.update_cb = radio_changed; radio_init(&radio); -#if (defined HACKRF_ONE || defined PRALINE) - portapack_init(); + if (board_id == BOARD_ID_HACKRF1_OG || board_id == BOARD_ID_HACKRF1_R9 || + board_id == BOARD_ID_PRALINE) { +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + portapack_init(); #endif + } #ifndef DFU_MODE usb_set_descriptor_by_serial_number(); @@ -511,6 +528,35 @@ int main(void) usb_set_configuration_changed_cb(usb_configuration_changed); usb_peripheral_reset(); + switch (detected_platform()) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + memcpy(&usb_device, + &usb_device_hackrf_one, + sizeof(usb_device_hackrf_one)); +#endif + break; + case BOARD_ID_JAWBREAKER: +#if defined(JAWBREAKER) + memcpy(&usb_device, + &usb_device_jawbreaker, + sizeof(usb_device_jawbreaker)); +#endif + break; + case BOARD_ID_RAD1O: +#if defined(RAD1O) + memcpy(&usb_device, &usb_device_rad1o, sizeof(usb_device_rad1o)); +#endif + break; + case BOARD_ID_PRALINE: +#if defined(PRALINE) || defined(UNIVERSAL) + memcpy(&usb_device, &usb_device_praline, sizeof(usb_device_praline)); +#endif + break; + default: + break; + }; usb_device_init(0, &usb_device); usb_queue_init(&usb_endpoint_control_out_queue); @@ -529,13 +575,15 @@ int main(void) rf_path_init(&rf_path); -#ifndef RAD1O +#if !defined(RAD1O) rffc5071_lock_test(&mixer.rffc5071); #endif -#ifdef PRALINE - fpga_if_xcvr_selftest(); + if (board_id == BOARD_ID_PRALINE) { +#if defined(PRALINE) || defined(UNIVERSAL) + fpga_if_xcvr_selftest(); #endif + } if (da7219_detect()) { operacake_skip_i2c_address(DA7219_ADDRESS); @@ -581,11 +629,13 @@ int main(void) case TRANSCEIVER_MODE_RX_SWEEP: sweep_mode(request.seq); break; -#ifndef PRALINE case TRANSCEIVER_MODE_CPLD_UPDATE: - cpld_update(); - break; + if (board_id != BOARD_ID_PRALINE) { +#if !defined(PRALINE) || defined(UNIVERSAL) + cpld_update(); #endif + } + break; default: break; } diff --git a/firmware/hackrf_usb/usb_api_board_info.c b/firmware/hackrf_usb/usb_api_board_info.c index a1ad3bce..8e64ad7f 100644 --- a/firmware/hackrf_usb/usb_api_board_info.c +++ b/firmware/hackrf_usb/usb_api_board_info.c @@ -34,7 +34,7 @@ #include #include #include -#ifdef HACKRF_ONE +#if defined(HACKRF_ONE) || defined(UNIVERSAL) #include #include #endif @@ -131,18 +131,19 @@ usb_request_status_t usb_vendor_request_reset( if (stage == USB_TRANSFER_STAGE_SETUP) { pin_shutdown(); clock_gen_shutdown(); -#ifdef HACKRF_ONE - /* - * Set boot pins as inputs so that the bootloader reads them - * correctly after the reset. - */ if (detected_platform() == BOARD_ID_HACKRF1_R9) { +#if defined(HACKRF_ONE) || defined(UNIVERSAL) + /* + * Set boot pins as inputs so that the bootloader reads them + * correctly after the reset. + */ const platform_gpio_t* gpio = platform_gpio(); gpio_input(gpio->h1r9_mcu_clk_en); gpio_input(gpio->h1r9_clkout_en); gpio_input(gpio->h1r9_rx); - } #endif + } + wwdt_reset(100000); usb_transfer_schedule_ack(endpoint->in); diff --git a/firmware/hackrf_usb/usb_api_cpld.c b/firmware/hackrf_usb/usb_api_cpld.c index 7d8200c3..05636a0b 100644 --- a/firmware/hackrf_usb/usb_api_cpld.c +++ b/firmware/hackrf_usb/usb_api_cpld.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -90,6 +91,15 @@ usb_request_status_t usb_vendor_request_cpld_checksum( static uint32_t cpld_crc; uint8_t length; + switch (detected_platform()) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + // supported + break; + default: + return USB_REQUEST_STATUS_STALL; + } + if (stage == USB_TRANSFER_STAGE_SETUP) { cpld_jtag_take(&jtag_cpld); const bool checksum_success = cpld_xc2c64a_jtag_checksum( diff --git a/firmware/hackrf_usb/usb_api_praline.c b/firmware/hackrf_usb/usb_api_praline.c index 6a44da60..2a41b839 100644 --- a/firmware/hackrf_usb/usb_api_praline.c +++ b/firmware/hackrf_usb/usb_api_praline.c @@ -24,6 +24,7 @@ #include "usb_api_praline.h" #include +#include #include #include #include @@ -35,6 +36,10 @@ usb_request_status_t usb_vendor_request_p1_ctrl( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { + if (detected_platform() != BOARD_ID_PRALINE) { + return USB_REQUEST_STATUS_STALL; + } + if (stage == USB_TRANSFER_STAGE_SETUP) { p1_ctrl_set(endpoint->setup.value); usb_transfer_schedule_ack(endpoint->in); @@ -46,6 +51,10 @@ usb_request_status_t usb_vendor_request_p2_ctrl( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { + if (detected_platform() != BOARD_ID_PRALINE) { + return USB_REQUEST_STATUS_STALL; + } + if (stage == USB_TRANSFER_STAGE_SETUP) { p2_ctrl_set(endpoint->setup.value); usb_transfer_schedule_ack(endpoint->in); @@ -57,6 +66,10 @@ usb_request_status_t usb_vendor_request_clkin_ctrl( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { + if (detected_platform() != BOARD_ID_PRALINE) { + return USB_REQUEST_STATUS_STALL; + } + if (stage == USB_TRANSFER_STAGE_SETUP) { clkin_ctrl_set(endpoint->setup.value & 1); usb_transfer_schedule_ack(endpoint->in); @@ -68,6 +81,10 @@ usb_request_status_t usb_vendor_request_set_narrowband_filter( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { + if (detected_platform() != BOARD_ID_PRALINE) { + return USB_REQUEST_STATUS_STALL; + } + if (stage == USB_TRANSFER_STAGE_SETUP) { narrowband_filter_set(endpoint->setup.value); usb_transfer_schedule_ack(endpoint->in); @@ -86,6 +103,10 @@ usb_request_status_t usb_vendor_request_set_fpga_bitstream( #else extern struct fpga_loader_t fpga_loader; + if (detected_platform() != BOARD_ID_PRALINE) { + return USB_REQUEST_STATUS_STALL; + } + if (stage == USB_TRANSFER_STAGE_SETUP) { if (!fpga_image_load(&fpga_loader, endpoint->setup.value)) { return USB_REQUEST_STATUS_STALL; diff --git a/firmware/hackrf_usb/usb_api_register.h b/firmware/hackrf_usb/usb_api_register.h index 24825144..58a84aff 100644 --- a/firmware/hackrf_usb/usb_api_register.h +++ b/firmware/hackrf_usb/usb_api_register.h @@ -56,7 +56,7 @@ usb_request_status_t usb_vendor_request_set_leds( usb_request_status_t usb_vendor_request_user_config_set_bias_t_opts( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) usb_request_status_t usb_vendor_request_write_fpga_reg( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); diff --git a/firmware/hackrf_usb/usb_api_selftest.c b/firmware/hackrf_usb/usb_api_selftest.c index 4fe2e628..fa5267b5 100644 --- a/firmware/hackrf_usb/usb_api_selftest.c +++ b/firmware/hackrf_usb/usb_api_selftest.c @@ -21,20 +21,18 @@ #include #include -#if defined(PRALINE) || defined(HACKRF_ONE) || defined(JAWBREAKER) +#if !defined(RAD1O) #include #endif #include #include +#include #include #include #include #include -#if !defined(PRALINE) - #include -#endif #include "usb_api_selftest.h" @@ -63,7 +61,7 @@ void append(char** dest, size_t* capacity, const char* str) } } -#ifdef PRALINE +#if defined(PRALINE) || defined(UNIVERSAL) static const char* test_result_to_str(test_result_t result) { switch (result) { @@ -82,91 +80,105 @@ static const char* test_result_to_str(test_result_t result) void generate_selftest_report(void) { + board_id_t board_id = detected_platform(); + char* s = &selftest.report.msg[0]; size_t c = sizeof(selftest.report.msg); -#ifdef RAD1O - append(&s, &c, "Mixer: MAX2871, ID: "); - append(&s, &c, itoa(selftest.mixer_id, 10)); - append(&s, &c, "\n"); -#else - append(&s, &c, "Mixer: RFFC5072, ID: "); - append(&s, &c, itoa(selftest.mixer_id >> 3, 10)); - append(&s, &c, ", Rev: "); - append(&s, &c, itoa(selftest.mixer_id & 0x7, 10)); - append(&s, &c, ", Locks: "); - bool lock; - for (int i = 0; i < NUM_LOCK_ATTEMPTS; i++) { - lock = selftest.mixer_locks[i]; - append(&s, &c, itoa(lock, 2)); - } - if (lock) { - append(&s, &c, " (PASS)"); - } else { - append(&s, &c, " (FAIL)"); - } - append(&s, &c, "\n"); + if (board_id == BOARD_ID_RAD1O) { +#if defined(RAD1O) + append(&s, &c, "Mixer: MAX2871, ID: "); + append(&s, &c, itoa(selftest.mixer_id, 10)); + append(&s, &c, "\n"); #endif + } else { +#if !defined(RAD1O) + append(&s, &c, "Mixer: RFFC5072, ID: "); + append(&s, &c, itoa(selftest.mixer_id >> 3, 10)); + append(&s, &c, ", Rev: "); + append(&s, &c, itoa(selftest.mixer_id & 0x7, 10)); + append(&s, &c, ", Locks: "); + bool lock; + for (int i = 0; i < NUM_LOCK_ATTEMPTS; i++) { + lock = selftest.mixer_locks[i]; + append(&s, &c, itoa(lock, 2)); + } + if (lock) { + append(&s, &c, " (PASS)"); + } else { + append(&s, &c, " (FAIL)"); + } + append(&s, &c, "\n"); +#endif + } + append(&s, &c, "Clock: Si5351"); append(&s, &c, ", Rev: "); append(&s, &c, itoa(selftest.si5351_rev_id, 10)); append(&s, &c, ", readback: "); append(&s, &c, selftest.si5351_readback_ok ? "OK" : "FAIL"); append(&s, &c, "\n"); -#ifdef PRALINE - append(&s, &c, "Transceiver: MAX2831, RSSI mux test: "); - append(&s, &c, selftest.max2831_mux_test_ok ? "PASS" : "FAIL"); - append(&s, &c, "\n"); -#else - append(&s, &c, "Transceiver: "); - append(&s, - &c, - (detected_platform() == BOARD_ID_HACKRF1_R9 ? "MAX2839" : "MAX2837")); - append(&s, &c, ", readback success: "); - append(&s, &c, itoa(selftest.max283x_readback_register_count, 10)); - append(&s, &c, "/"); - append(&s, &c, itoa(selftest.max283x_readback_total_registers, 10)); - if (selftest.max283x_readback_register_count < - selftest.max283x_readback_total_registers) { - append(&s, &c, ", bad value: 0x"); - append(&s, &c, itoa(selftest.max283x_readback_bad_value, 10)); - append(&s, &c, ", expected: 0x"); - append(&s, &c, itoa(selftest.max283x_readback_expected_value, 10)); - } - append(&s, &c, "\n"); -#endif -#ifdef PRALINE - append(&s, &c, "FPGA configuration: "); - append(&s, &c, test_result_to_str(selftest.fpga_image_load)); - append(&s, &c, "\n"); - append(&s, &c, "FPGA SPI: "); - append(&s, &c, test_result_to_str(selftest.fpga_spi)); - append(&s, &c, "\n"); - append(&s, &c, "SGPIO RX test: "); - append(&s, &c, test_result_to_str(selftest.sgpio_rx)); - append(&s, &c, "\n"); - append(&s, &c, "Loopback test: "); - append(&s, &c, test_result_to_str(selftest.xcvr_loopback)); - append(&s, &c, "\n"); - // Dump transceiver loopback measurements. - for (int i = 0; i < 4; ++i) { - struct xcvr_measurements* m = &selftest.xcvr_measurements[i]; - append(&s, &c, " "); - append(&s, &c, itoa(i, 10)); - append(&s, &c, ":"); - append(&s, &c, itoa(m->zcs_i, 10)); - append(&s, &c, ","); - append(&s, &c, itoa(m->zcs_q, 10)); - append(&s, &c, ","); - append(&s, &c, itoa(m->max_mag_i, 10)); - append(&s, &c, ","); - append(&s, &c, itoa(m->max_mag_q, 10)); - append(&s, &c, ","); - append(&s, &c, itoa(m->avg_mag_sq_i, 10)); - append(&s, &c, ","); - append(&s, &c, itoa(m->avg_mag_sq_q, 10)); + + if (board_id == BOARD_ID_PRALINE) { +#if defined(PRALINE) || defined(UNIVERSAL) + append(&s, &c, "Transceiver: MAX2831, RSSI mux test: "); + append(&s, &c, selftest.max2831_mux_test_ok ? "PASS" : "FAIL"); append(&s, &c, "\n"); - } #endif + } else { +#if !defined(PRALINE) || defined(UNIVERSAL) + append(&s, &c, "Transceiver: "); + append(&s, &c, (board_id == BOARD_ID_HACKRF1_R9 ? "MAX2839" : "MAX2837")); + append(&s, &c, ", readback success: "); + append(&s, &c, itoa(selftest.max283x_readback_register_count, 10)); + append(&s, &c, "/"); + append(&s, &c, itoa(selftest.max283x_readback_total_registers, 10)); + if (selftest.max283x_readback_register_count < + selftest.max283x_readback_total_registers) { + append(&s, &c, ", bad value: 0x"); + append(&s, &c, itoa(selftest.max283x_readback_bad_value, 10)); + append(&s, &c, ", expected: 0x"); + append(&s, + &c, + itoa(selftest.max283x_readback_expected_value, 10)); + } + append(&s, &c, "\n"); +#endif + } + if (board_id == BOARD_ID_PRALINE) { +#if defined(PRALINE) || defined(UNIVERSAL) + append(&s, &c, "FPGA configuration: "); + append(&s, &c, test_result_to_str(selftest.fpga_image_load)); + append(&s, &c, "\n"); + append(&s, &c, "FPGA SPI: "); + append(&s, &c, test_result_to_str(selftest.fpga_spi)); + append(&s, &c, "\n"); + append(&s, &c, "SGPIO RX test: "); + append(&s, &c, test_result_to_str(selftest.sgpio_rx)); + append(&s, &c, "\n"); + append(&s, &c, "Loopback test: "); + append(&s, &c, test_result_to_str(selftest.xcvr_loopback)); + append(&s, &c, "\n"); + // Dump transceiver loopback measurements. + for (int i = 0; i < 4; ++i) { + struct xcvr_measurements* m = &selftest.xcvr_measurements[i]; + append(&s, &c, " "); + append(&s, &c, itoa(i, 10)); + append(&s, &c, ":"); + append(&s, &c, itoa(m->zcs_i, 10)); + append(&s, &c, ","); + append(&s, &c, itoa(m->zcs_q, 10)); + append(&s, &c, ","); + append(&s, &c, itoa(m->max_mag_i, 10)); + append(&s, &c, ","); + append(&s, &c, itoa(m->max_mag_q, 10)); + append(&s, &c, ","); + append(&s, &c, itoa(m->avg_mag_sq_i, 10)); + append(&s, &c, ","); + append(&s, &c, itoa(m->avg_mag_sq_q, 10)); + append(&s, &c, "\n"); + } +#endif + } } usb_request_status_t usb_vendor_request_read_selftest( diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index a9bfc695..4f7d8e57 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -46,11 +47,6 @@ #define MAX(x, y) ((x) > (y) ? (x) : (y)) #define FREQ_GRANULARITY 1000000 #define MAX_RANGES 10 -#ifndef PRALINE - #define THROWAWAY_BUFFERS 2 -#else - #define THROWAWAY_BUFFERS 1 -#endif static uint64_t sweep_freq; static uint16_t frequencies[MAX_RANGES * 2]; @@ -59,6 +55,7 @@ static uint16_t num_ranges = 0; static uint32_t dwell_blocks = 0; static uint32_t step_width = 0; static uint32_t offset = 0; +static uint32_t throwaway_buffers = 0; static enum sweep_style style = LINEAR; static bool freq_ui_dirty = false; static bool img_reject_ui_dirty = false; @@ -91,6 +88,12 @@ usb_request_status_t usb_vendor_request_init_sweep( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { + if (detected_platform() == BOARD_ID_PRALINE) { + throwaway_buffers = 1; + } else { + throwaway_buffers = 2; + } + uint32_t num_bytes; int i; if (stage == USB_TRANSFER_STAGE_SETUP) { @@ -144,7 +147,7 @@ void sweep_bulk_transfer_complete(void* user_data, unsigned int bytes_transferre // For each buffer transferred, we need to bump the count to allow // for the buffer(s) that are to be discarded. - m0_state.m4_count += (THROWAWAY_BUFFERS + 1) * 0x4000; + m0_state.m4_count += (throwaway_buffers + 1) * 0x4000; } void sweep_mode(uint32_t seq) @@ -200,7 +203,7 @@ void sweep_mode(uint32_t seq) // Set M0 to switch back to RX after we have received our // discard buffers. - m0_state.threshold += (0x4000 * THROWAWAY_BUFFERS); + m0_state.threshold += (0x4000 * throwaway_buffers); m0_state.next_mode = M0_MODE_RX; // Write metadata to buffer. @@ -225,7 +228,7 @@ void sweep_mode(uint32_t seq) NULL); // Use other buffer next time. - phase = (phase + 1) % THROWAWAY_BUFFERS; + phase = (phase + 1) % throwaway_buffers; if (++blocks_queued == dwell_blocks) { // Calculate next sweep frequency. diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 12c516c9..be16b1be 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -282,6 +283,16 @@ usb_request_status_t usb_vendor_request_set_antenna_enable( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { + switch (detected_platform()) { + case BOARD_ID_HACKRF1_OG: + case BOARD_ID_HACKRF1_R9: + case BOARD_ID_PRALINE: + // supported + break; + default: + return USB_REQUEST_STATUS_STALL; + } + if (stage == USB_TRANSFER_STAGE_SETUP) { radio_reg_write( &radio, diff --git a/firmware/hackrf_usb/usb_descriptor.c b/firmware/hackrf_usb/usb_descriptor.c index 7c98f0ca..f213f484 100644 --- a/firmware/hackrf_usb/usb_descriptor.c +++ b/firmware/hackrf_usb/usb_descriptor.c @@ -51,7 +51,8 @@ #define USB_STRING_LANGID (0x0409) -uint8_t usb_descriptor_device[] = { +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) +uint8_t usb_descriptor_device_hackrf[] = { 18, // bLength USB_DESCRIPTOR_TYPE_DEVICE, // bDescriptorType USB_WORD(0x0200), // bcdUSB @@ -60,13 +61,50 @@ uint8_t usb_descriptor_device[] = { 0x00, // bDeviceProtocol USB_MAX_PACKET0, // bMaxPacketSize0 USB_WORD(USB_VENDOR_ID), // idVendor - USB_WORD(USB_PRODUCT_ID), // idProduct + USB_WORD(0x6089), // idProduct USB_WORD(USB_API_VERSION), // bcdDevice 0x01, // iManufacturer 0x02, // iProduct 0x04, // iSerialNumber 0x01 // bNumConfigurations }; +#endif +#if defined(JAWBREAKER) +uint8_t usb_descriptor_device_jawbreaker[] = { + 18, // bLength + USB_DESCRIPTOR_TYPE_DEVICE, // bDescriptorType + USB_WORD(0x0200), // bcdUSB + 0x00, // bDeviceClass + 0x00, // bDeviceSubClass + 0x00, // bDeviceProtocol + USB_MAX_PACKET0, // bMaxPacketSize0 + USB_WORD(USB_VENDOR_ID), // idVendor + USB_WORD(0x604B), // idProduct + USB_WORD(USB_API_VERSION), // bcdDevice + 0x01, // iManufacturer + 0x02, // iProduct + 0x04, // iSerialNumber + 0x01 // bNumConfigurations +}; +#endif +#if defined(RAD1O) +uint8_t usb_descriptor_device_rad1o[] = { + 18, // bLength + USB_DESCRIPTOR_TYPE_DEVICE, // bDescriptorType + USB_WORD(0x0200), // bcdUSB + 0x00, // bDeviceClass + 0x00, // bDeviceSubClass + 0x00, // bDeviceProtocol + USB_MAX_PACKET0, // bMaxPacketSize0 + USB_WORD(USB_VENDOR_ID), // idVendor + USB_WORD(0xCC15), // idProduct + USB_WORD(USB_API_VERSION), // bcdDevice + 0x01, // iManufacturer + 0x02, // iProduct + 0x04, // iSerialNumber + 0x01 // bNumConfigurations +}; +#endif uint8_t usb_descriptor_device_qualifier[] = { 10, // bLength @@ -185,8 +223,8 @@ uint8_t usb_descriptor_string_manufacturer[] = { 's', 0x00, }; -uint8_t usb_descriptor_string_product[] = { -#ifdef HACKRF_ONE +#if defined(HACKRF_ONE) || defined(UNIVERSAL) +uint8_t usb_descriptor_string_product_hackrf_one[] = { 22, // bLength USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType 'H', 0x00, @@ -199,7 +237,26 @@ uint8_t usb_descriptor_string_product[] = { 'O', 0x00, 'n', 0x00, 'e', 0x00, -#elif JAWBREAKER +}; +#endif +#if defined(PRALINE) || defined(UNIVERSAL) +uint8_t usb_descriptor_string_product_praline[] = { + 22, // bLength + USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType + 'H', 0x00, + 'a', 0x00, + 'c', 0x00, + 'k', 0x00, + 'R', 0x00, + 'F', 0x00, + ' ', 0x00, + 'P', 0x00, + 'r', 0x00, + 'o', 0x00, +}; +#endif +#if defined(JAWBREAKER) +uint8_t usb_descriptor_string_product_jawbreaker[] = { 36, // bLength USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType 'H', 0x00, @@ -219,7 +276,10 @@ uint8_t usb_descriptor_string_product[] = { 'k', 0x00, 'e', 0x00, 'r', 0x00, -#elif RAD1O +}; +#endif +#if defined(RAD1O) +uint8_t usb_descriptor_string_product_rad1o[] = { 12, // bLength USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType 'r', 0x00, @@ -227,30 +287,8 @@ uint8_t usb_descriptor_string_product[] = { 'd', 0x00, '1', 0x00, 'o', 0x00, -#elif PRALINE - 22, // bLength - USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType - 'H', 0x00, - 'a', 0x00, - 'c', 0x00, - 'k', 0x00, - 'R', 0x00, - 'F', 0x00, - ' ', 0x00, - 'P', 0x00, - 'r', 0x00, - 'o', 0x00, -#else - 14, // bLength - USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType - 'H', 0x00, - 'a', 0x00, - 'c', 0x00, - 'k', 0x00, - 'R', 0x00, - 'F', 0x00, -#endif }; +#endif uint8_t usb_descriptor_string_config_description[] = { 24, // bLength @@ -291,14 +329,46 @@ uint8_t usb_descriptor_string_serial_number[] = { uint8_t usb_descriptor_string_serial_number[USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN]; #endif -uint8_t* usb_descriptor_strings[] = { +#if defined(HACKRF_ONE) || defined(UNIVERSAL) +uint8_t* usb_descriptor_strings_hackrf_one[] = { usb_descriptor_string_languages, usb_descriptor_string_manufacturer, - usb_descriptor_string_product, + usb_descriptor_string_product_hackrf_one, usb_descriptor_string_config_description, usb_descriptor_string_serial_number, 0, // TERMINATOR }; +#endif +#if defined(PRALINE) || defined(UNIVERSAL) +uint8_t* usb_descriptor_strings_praline[] = { + usb_descriptor_string_languages, + usb_descriptor_string_manufacturer, + usb_descriptor_string_product_praline, + usb_descriptor_string_config_description, + usb_descriptor_string_serial_number, + 0, // TERMINATOR +}; +#endif +#if defined(JAWBREAKER) +uint8_t* usb_descriptor_strings_jawbreaker[] = { + usb_descriptor_string_languages, + usb_descriptor_string_manufacturer, + usb_descriptor_string_product_jawbreaker, + usb_descriptor_string_config_description, + usb_descriptor_string_serial_number, + 0, // TERMINATOR +}; +#endif +#if defined(RAD1O) +uint8_t* usb_descriptor_strings_rad1o[] = { + usb_descriptor_string_languages, + usb_descriptor_string_manufacturer, + usb_descriptor_string_product_rad1o, + usb_descriptor_string_config_description, + usb_descriptor_string_serial_number, + 0, // TERMINATOR +}; +#endif uint8_t wcid_string_descriptor[] = { 18, // bLength diff --git a/firmware/hackrf_usb/usb_descriptor.h b/firmware/hackrf_usb/usb_descriptor.h index 097ccce0..93f3eb78 100644 --- a/firmware/hackrf_usb/usb_descriptor.h +++ b/firmware/hackrf_usb/usb_descriptor.h @@ -24,20 +24,42 @@ #include -extern uint8_t usb_descriptor_device[]; +#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) +extern uint8_t usb_descriptor_device_hackrf[]; +#endif +#if defined(JAWBREAKER) +extern uint8_t usb_descriptor_device_jawbreaker[]; +#endif +#if defined(RAD1O) +extern uint8_t usb_descriptor_device_rad1o[]; +#endif extern uint8_t usb_descriptor_device_qualifier[]; extern uint8_t usb_descriptor_configuration_full_speed[]; extern uint8_t usb_descriptor_configuration_high_speed[]; extern uint8_t usb_descriptor_string_languages[]; extern uint8_t usb_descriptor_string_manufacturer[]; -extern uint8_t usb_descriptor_string_product[]; +#if defined(HACKRF_ONE) || defined(UNIVERSAL) +extern uint8_t usb_descriptor_string_product_hackrf_one[]; +#endif +#if defined(PRALINE) || defined(UNIVERSAL) +extern uint8_t usb_descriptor_string_product_praline[]; +#endif +#if defined(JAWBREAKER) +extern uint8_t usb_descriptor_string_product_jawbreaker[]; +#endif +#if defined(RAD1O) +extern uint8_t usb_descriptor_string_product_rad1o[]; +#endif #define USB_DESCRIPTOR_STRING_SERIAL_LEN 32 #define USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN \ (USB_DESCRIPTOR_STRING_SERIAL_LEN * 2 + 2) /* UTF-16LE */ extern uint8_t usb_descriptor_string_serial_number[]; -extern uint8_t* usb_descriptor_strings[]; +extern uint8_t* usb_descriptor_strings_hackrf_one[]; +extern uint8_t* usb_descriptor_strings_jawbreaker[]; +extern uint8_t* usb_descriptor_strings_rad1o[]; +extern uint8_t* usb_descriptor_strings_praline[]; #define USB_WCID_VENDOR_REQ 0x19 extern uint8_t wcid_string_descriptor[]; diff --git a/firmware/hackrf_usb/usb_device.c b/firmware/hackrf_usb/usb_device.c index b689ce9f..4ad46424 100644 --- a/firmware/hackrf_usb/usb_device.c +++ b/firmware/hackrf_usb/usb_device.c @@ -45,12 +45,49 @@ usb_configuration_t* usb_configurations[] = { 0, }; -usb_device_t usb_device = { - .descriptor = usb_descriptor_device, - .descriptor_strings = usb_descriptor_strings, +usb_device_t usb_device; + +#if defined(HACKRF_ONE) || defined(UNIVERSAL) +const usb_device_t usb_device_hackrf_one = { + .descriptor = usb_descriptor_device_hackrf, + .descriptor_strings = usb_descriptor_strings_hackrf_one, .qualifier_descriptor = usb_descriptor_device_qualifier, .configurations = &usb_configurations, .configuration = 0, .wcid_string_descriptor = wcid_string_descriptor, .wcid_feature_descriptor = wcid_feature_descriptor, }; +#endif +#if defined(PRALINE) || defined(UNIVERSAL) +const usb_device_t usb_device_praline = { + .descriptor = usb_descriptor_device_hackrf, + .descriptor_strings = usb_descriptor_strings_praline, + .qualifier_descriptor = usb_descriptor_device_qualifier, + .configurations = &usb_configurations, + .configuration = 0, + .wcid_string_descriptor = wcid_string_descriptor, + .wcid_feature_descriptor = wcid_feature_descriptor, +}; +#endif +#if defined(JAWBREAKER) +const usb_device_t usb_device_jawbreaker = { + .descriptor = usb_descriptor_device_jawbreaker, + .descriptor_strings = usb_descriptor_strings_jawbreaker, + .qualifier_descriptor = usb_descriptor_device_qualifier, + .configurations = &usb_configurations, + .configuration = 0, + .wcid_string_descriptor = wcid_string_descriptor, + .wcid_feature_descriptor = wcid_feature_descriptor, +}; +#endif +#if defined(RAD1O) +const usb_device_t usb_device_rad1o = { + .descriptor = usb_descriptor_device_rad1o, + .descriptor_strings = usb_descriptor_strings_rad1o, + .qualifier_descriptor = usb_descriptor_device_qualifier, + .configurations = &usb_configurations, + .configuration = 0, + .wcid_string_descriptor = wcid_string_descriptor, + .wcid_feature_descriptor = wcid_feature_descriptor, +}; +#endif diff --git a/firmware/hackrf_usb/usb_device.h b/firmware/hackrf_usb/usb_device.h index 79df298d..528d084d 100644 --- a/firmware/hackrf_usb/usb_device.h +++ b/firmware/hackrf_usb/usb_device.h @@ -26,3 +26,16 @@ #include extern usb_device_t usb_device; + +#if defined(HACKRF_ONE) || defined(UNIVERSAL) +extern const usb_device_t usb_device_hackrf_one; +#endif +#if defined(PRALINE) || defined(UNIVERSAL) +extern const usb_device_t usb_device_praline; +#endif +#if defined(JAWBREAKER) +extern const usb_device_t usb_device_jawbreaker; +#endif +#if defined(RAD1O) +extern const usb_device_t usb_device_rad1o; +#endif From 3faa91ef85336b4f989b8fa1a8fb519bcf34c99a Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sat, 4 Apr 2026 01:13:09 +0100 Subject: [PATCH 124/238] Add UNIVERSAL board target. --- firmware/common/firmware_info.c | 3 +++ firmware/hackrf-common.cmake | 21 +++++++++++++++++---- firmware/hackrf_usb/CMakeLists.txt | 24 ++++++++++++++++++++++-- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/firmware/common/firmware_info.c b/firmware/common/firmware_info.c index 1ac02074..527dd19b 100644 --- a/firmware/common/firmware_info.c +++ b/firmware/common/firmware_info.c @@ -30,6 +30,9 @@ #define SUPPORTED_PLATFORM PLATFORM_RAD1O #elif PRALINE #define SUPPORTED_PLATFORM PLATFORM_PRALINE +#elif UNIVERSAL + #define SUPPORTED_PLATFORM \ + (PLATFORM_PRALINE | PLATFORM_HACKRF1_OG | PLATFORM_HACKRF1_R9) #else #define SUPPORTED_PLATFORM 0 #endif diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 26a24d6e..9a349b1e 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -74,7 +74,7 @@ if(NOT DEFINED BOARD) set(BOARD HACKRF_ONE) endif() -if(BOARD STREQUAL "HACKRF_ONE" OR BOARD STREQUAL "PRALINE") +if(BOARD STREQUAL "HACKRF_ONE" OR BOARD STREQUAL "PRALINE" OR BOARD STREQUAL "UNIVERSAL") set(MCU_PARTNO LPC4320) else() set(MCU_PARTNO LPC4330) @@ -195,7 +195,8 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/m0_state.c ${PATH_HACKRF_FIRMWARE_COMMON}/adc.c ${PATH_HACKRF_FIRMWARE_COMMON}/da7219.c - ) + ${PATH_HACKRF_FIRMWARE_COMMON}/max283x.c + ) if(BOARD STREQUAL "RAD1O") SET(SRC_M4 @@ -216,14 +217,26 @@ macro(DeclareTargets) ${SRC_M4} ${PATH_HACKRF_FIRMWARE_COMMON}/fpga.c ${PATH_HACKRF_FIRMWARE_COMMON}/ice40_spi.c - ${PATH_HACKRF_FIRMWARE_COMMON}/max283x.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2831.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2831_target.c ) else() SET(SRC_M4 ${SRC_M4} - ${PATH_HACKRF_FIRMWARE_COMMON}/max283x.c + ${PATH_HACKRF_FIRMWARE_COMMON}/max2837.c + ${PATH_HACKRF_FIRMWARE_COMMON}/max2837_target.c + ${PATH_HACKRF_FIRMWARE_COMMON}/max2839.c + ${PATH_HACKRF_FIRMWARE_COMMON}/max2839_target.c + ) + endif() + + if(BOARD STREQUAL "UNIVERSAL") + SET(SRC_M4 + ${SRC_M4} + ${PATH_HACKRF_FIRMWARE_COMMON}/fpga.c + ${PATH_HACKRF_FIRMWARE_COMMON}/ice40_spi.c + ${PATH_HACKRF_FIRMWARE_COMMON}/max2831.c + ${PATH_HACKRF_FIRMWARE_COMMON}/max2831_target.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2837.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2837_target.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2839.c diff --git a/firmware/hackrf_usb/CMakeLists.txt b/firmware/hackrf_usb/CMakeLists.txt index 3ab1beed..3fd3ea87 100644 --- a/firmware/hackrf_usb/CMakeLists.txt +++ b/firmware/hackrf_usb/CMakeLists.txt @@ -35,7 +35,7 @@ add_custom_command( OUTPUT ${PATH_PRALINE_FPGA_OBJ} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E copy ${PATH_PRALINE_FPGA_BIN} "fpga.bin" - COMMAND ${CMAKE_OBJCOPY} + COMMAND ${CMAKE_OBJCOPY} -I binary -O elf32-littlearm -B arm @@ -75,6 +75,26 @@ set(SRC_M4 set(SRC_M0 sgpio_m0.s) +if(BOARD STREQUAL "UNIVERSAL") + SET(SRC_M4 + ${SRC_M4} + usb_api_cpld.c + "${PATH_HACKRF_FIRMWARE_COMMON}/cpld_xc2c.c" + "${PATH_HACKRF_CPLD_DATA_C}" + "${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/lenval.c" + "${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/micro.c" + "${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/ports.c" + + "${PATH_HACKRF_FIRMWARE_COMMON}/lz4_blk.c" + "${PATH_HACKRF_FIRMWARE_COMMON}/fpga_image.c" + "${PATH_HACKRF_FIRMWARE_COMMON}/fpga_selftest.c" + usb_api_praline.c + ) + SET(OBJ_M4 + ${PATH_PRALINE_FPGA_OBJ} + ) +endif() + if(BOARD STREQUAL "PRALINE") SET(SRC_M4 ${SRC_M4} @@ -98,7 +118,7 @@ else() ) endif() -if(BOARD STREQUAL "HACKRF_ONE" OR BOARD STREQUAL "PRALINE") +if(BOARD STREQUAL "PRALINE" OR BOARD STREQUAL "HACKRF_ONE" OR BOARD STREQUAL "UNIVERSAL") SET(SRC_M4 ${SRC_M4} "${PATH_HACKRF_FIRMWARE_COMMON}/portapack.c" From 6387a0b1006a2492a4cb90b95b84756bb736a23e Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 2 Apr 2026 04:48:00 +0100 Subject: [PATCH 125/238] Add UNIVERSAL firmware build to GitHub Actions. --- .github/workflows/build.yml | 2 +- .github/workflows/includes-check.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 07b419e5..a93a27c1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -159,7 +159,7 @@ jobs: strategy: matrix: os: ['macos', 'ubuntu', 'windows'] - board: ['HACKRF_ONE', 'JAWBREAKER', 'RAD1O', 'PRALINE'] + board: ['HACKRF_ONE', 'JAWBREAKER', 'RAD1O', 'PRALINE', 'UNIVERSAL'] cmake: ['3.10.0', 'latest'] exclude: - os: 'windows' diff --git a/.github/workflows/includes-check.yml b/.github/workflows/includes-check.yml index dfb631bd..11640069 100644 --- a/.github/workflows/includes-check.yml +++ b/.github/workflows/includes-check.yml @@ -13,7 +13,7 @@ jobs: options: --user 0 strategy: matrix: - board: ['HACKRF_ONE', 'JAWBREAKER', 'RAD1O', 'PRALINE'] + board: ['HACKRF_ONE', 'JAWBREAKER', 'RAD1O', 'PRALINE', 'UNIVERSAL'] cmake: ['3.10.0', 'latest'] # Don't cancel all builds when one fails From 421af497447a9e2632f4ca7dad88229af1da6300 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 2 Apr 2026 07:45:08 +0100 Subject: [PATCH 126/238] Jenkinsfile: add tests with BOARD=UNIVERSAL. --- Jenkinsfile | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index bf79d51e..b41d6714 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -67,6 +67,46 @@ pipeline { } } } + stage('Test HackRF One with BOARD=UNIVERSAL') { + agent { + docker { + image 'hackrf' + reuseNode true + args docker_args + } + } + options { + timeout(time: 20, unit: 'MINUTES') + } + steps { + sh './ci-scripts/install_host.sh' + sh './ci-scripts/build_firmware.sh UNIVERSAL' + script { + allOff() + reset('h1_eut') + } + sh 'sleep 1s' + retry(3) { + sh './ci-scripts/test_host.sh' + } + script { + reset('h1_tester h1_eut') + } + sh 'sleep 1s' + script { + // Allow up to 3 retries 5 minutes each for the HIL test + runCommand(3, 5, 'MINUTES', "HackRF One Test", h1_test) + } + script { + allOff() + reset('h1_eut') + } + sh 'sleep 1s' + retry(3) { + sh 'python3 ci-scripts/test_sgpio_debug.py' + } + } + } stage('Test HackRF Pro with BOARD=PRALINE') { agent { docker { @@ -99,6 +139,38 @@ pipeline { } } } + stage('Test HackRF Pro with BOARD=UNIVERSAL') { + agent { + docker { + image 'hackrf' + reuseNode true + args "$docker_args" + } + } + options { + timeout(time: 20, unit: 'MINUTES') + } + steps { + sh './ci-scripts/install_host.sh' + sh './ci-scripts/build_firmware.sh UNIVERSAL' + script { + allOff() + reset('hpro_eut') + } + sh 'sleep 1s' + retry(3) { + sh './ci-scripts/test_host.sh' + } + script { + reset('hpro_tester hpro_eut') + } + sh 'sleep 1s' + script { + // Allow up to 3 retries 5 minutes each for the HIL test + runCommand(3, 5, 'MINUTES', "HackRF Pro Test", hpro_test) + } + } + } } post { always { From 9b5f342be024fce5ab0c421116af720a9ccf44c4 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 6 Apr 2026 21:21:01 +0100 Subject: [PATCH 127/238] max283x: Move platform switch inside max283x_setup(). --- firmware/common/max283x.c | 51 +++++++++++++++++---------------------- firmware/common/max283x.h | 2 +- firmware/common/rf_path.c | 18 +------------- 3 files changed, 24 insertions(+), 47 deletions(-) diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index 54b596bc..9c64d668 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -27,6 +27,7 @@ #include #include "fixed_point.h" +#include "platform_detect.h" #include "platform_gpio.h" #include "spi_bus.h" @@ -67,49 +68,41 @@ max2839_driver_t max2839 = { #endif /* Initialize chip. */ -void max283x_setup(max283x_driver_t* const drv, max283x_variant_t type) +void max283x_setup(max283x_driver_t* const drv) { - drv->type = type; - const platform_gpio_t* gpio = platform_gpio(); /* MAX283x GPIO PinMux */ + switch (detected_platform()) { + case BOARD_ID_PRALINE: #if defined(PRALINE) || defined(UNIVERSAL) - max2831.gpio_enable = gpio->max283x_enable; - max2831.gpio_rxtx = gpio->max283x_rx_enable; - max2831.gpio_rxhp = gpio->max2831_rxhp; - max2831.gpio_ld = gpio->max2831_ld; -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - max2837.gpio_enable = gpio->max283x_enable; - max2837.gpio_rx_enable = gpio->max283x_rx_enable; - max2837.gpio_tx_enable = gpio->max283x_tx_enable; -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - max2839.gpio_enable = gpio->max283x_enable; - max2839.gpio_rxtx = gpio->max283x_rx_enable; -#endif - - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: + drv->type = MAX2831_VARIANT; + max2831.gpio_enable = gpio->max283x_enable; + max2831.gpio_rxtx = gpio->max283x_rx_enable; + max2831.gpio_rxhp = gpio->max2831_rxhp; + max2831.gpio_ld = gpio->max2831_ld; memcpy(&drv->drv.max2831, &max2831, sizeof(max2831)); max2831_setup(&drv->drv.max2831); - break; #endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - memcpy(&drv->drv.max2837, &max2837, sizeof(max2837)); - max2837_setup(&drv->drv.max2837); break; -#endif + case BOARD_ID_HACKRF1_R9: #if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: + drv->type = MAX2839_VARIANT; + max2839.gpio_enable = gpio->max283x_enable; + max2839.gpio_rxtx = gpio->max283x_rx_enable; memcpy(&drv->drv.max2839, &max2839, sizeof(max2839)); max2839_setup(&drv->drv.max2839); - break; #endif + break; default: +#if !defined(PRALINE) || defined(UNIVERSAL) + drv->type = MAX2837_VARIANT; + max2837.gpio_enable = gpio->max283x_enable; + max2837.gpio_rx_enable = gpio->max283x_rx_enable; + max2837.gpio_tx_enable = gpio->max283x_tx_enable; + memcpy(&drv->drv.max2837, &max2837, sizeof(max2837)); + max2837_setup(&drv->drv.max2837); +#endif break; } } diff --git a/firmware/common/max283x.h b/firmware/common/max283x.h index 87da59b4..bcafff06 100644 --- a/firmware/common/max283x.h +++ b/firmware/common/max283x.h @@ -83,7 +83,7 @@ typedef struct { } max283x_driver_t; /* Initialize chip. */ -void max283x_setup(max283x_driver_t* const drv, max283x_variant_t type); +void max283x_setup(max283x_driver_t* const drv); /* Returns the number of registers supported by the driver. */ uint16_t max283x_num_regs(max283x_driver_t* const drv); diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 5e892668..f2234413 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -480,23 +480,7 @@ void rf_path_init(rf_path_t* const rf_path) max5864_shutdown(&max5864); ssp1_set_mode_max283x(); - switch (board_id) { - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) - max283x_setup(&max283x, MAX2831_VARIANT); -#endif - break; - case BOARD_ID_HACKRF1_R9: -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - max283x_setup(&max283x, MAX2839_VARIANT); -#endif - break; - default: -#if !defined(PRALINE) || defined(UNIVERSAL) - max283x_setup(&max283x, MAX2837_VARIANT); -#endif - break; - } + max283x_setup(&max283x); max283x_start(&max283x); switch (board_id) { From d4b2091b128d7b413e3e334fabcea89e5a39d08e Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 6 Apr 2026 22:58:34 +0100 Subject: [PATCH 128/238] max283x: Add macros to simplify variant-specific dispatch. --- firmware/common/max283x.c | 442 +++++++++----------------------------- 1 file changed, 100 insertions(+), 342 deletions(-) diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index 9c64d668..6a6d5f26 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -107,93 +107,95 @@ void max283x_setup(max283x_driver_t* const drv) } } +/* Macros to simplify dispatch of variant-specific operations. */ + +/* clang-format off */ + +#if defined(UNIVERSAL) + // UNIVERSAL: all variants + #define DISPATCH(_drv, _max2831, _max2837, _max2839) \ + if (_drv->type == MAX2831_VARIANT) { \ + _max2831; \ + } else if (_drv->type == MAX2837_VARIANT) { \ + _max2837; \ + } else { \ + _max2839; \ + } +#elif defined(HACKRF_ONE) + // HACKRF_ONE: MAX2837 and MAX2839 only + #define DISPATCH(_drv, _max2831, _max2837, _max2839) \ + if (_drv->type == MAX2837_VARIANT) { \ + _max2837; \ + } else { \ + _max2839; \ + } +#elif defined(PRALINE) + // PRALINE: MAX2831 only + #define DISPATCH(_drv, _max2831, _max2837, _max2839) \ + (void) drv; \ + _max2831 +#else + // JAWBREAKER, RAD1O: MAX2837 only + #define DISPATCH(_drv, _max2831, _max2837, _max2839) \ + (void) drv; \ + _max2837 +#endif + +#define CALL(_drv, _func, ...) \ + DISPATCH(drv, \ + max2831_ ## _func(&_drv->drv.max2831, ##__VA_ARGS__), \ + max2837_ ## _func(&_drv->drv.max2837, ##__VA_ARGS__), \ + max2839_ ## _func(&_drv->drv.max2839, ##__VA_ARGS__) \ + ); \ + +#define RESULT(_drv, _type, _func, ...) ({ \ + _type _result; \ + DISPATCH(drv, \ + _result = max2831_ ## _func(&_drv->drv.max2831, ##__VA_ARGS__), \ + _result = max2837_ ## _func(&_drv->drv.max2837, ##__VA_ARGS__), \ + _result = max2839_ ## _func(&_drv->drv.max2839, ##__VA_ARGS__) \ + ); \ + _result; \ +}) + +#define CONSTANT(_drv, _type, _name) ({\ + _type value; \ + DISPATCH(drv, \ + value = MAX2831_ ## _name, \ + value = MAX2837_ ## _name, \ + value = MAX2839_ ## _name \ + ); \ + value; \ +}) + +#define PRALINE_ONLY(_drv, _max2831) DISPATCH(_drv, _max2831, , ) + +/* clang-format on */ + /* Returns the number of registers supported by the driver. */ uint16_t max283x_num_regs(max283x_driver_t* const drv) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - return MAX2831_NUM_REGS; -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - return MAX2837_NUM_REGS; -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - return MAX2839_NUM_REGS; -#endif - default: - return 0; - } + return CONSTANT(drv, uint16_t, NUM_REGS); } /* Returns the maximum data register value supported by the driver. */ uint16_t max283x_data_regs_max_value(max283x_driver_t* const drv) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - return MAX2831_DATA_REGS_MAX_VALUE; -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - return MAX2837_DATA_REGS_MAX_VALUE; -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - return MAX2839_DATA_REGS_MAX_VALUE; -#endif - default: - return 0; - } + return CONSTANT(drv, uint16_t, DATA_REGS_MAX_VALUE); } /* Read a register via SPI. Save a copy to memory and return * value. Mark clean. */ uint16_t max283x_reg_read(max283x_driver_t* const drv, uint8_t r) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - return max2831_reg_read(&drv->drv.max2831, r); -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - return max2837_reg_read(&drv->drv.max2837, r); -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - return max2839_reg_read(&drv->drv.max2839, r); -#endif - default: - return 0; - } + return RESULT(drv, uint16_t, reg_read, r); } /* Write value to register via SPI and save a copy to memory. Mark * clean. */ void max283x_reg_write(max283x_driver_t* const drv, uint8_t r, uint16_t v) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - max2831_reg_write(&drv->drv.max2831, r, v); - break; -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - max2837_reg_write(&drv->drv.max2837, r, v); - break; -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - max2839_reg_write(&drv->drv.max2839, r, v); - break; -#endif - default: - break; - } + CALL(drv, reg_write, r, v); } /* Write all dirty registers via SPI from memory. Mark all clean. Some @@ -201,115 +203,36 @@ void max283x_reg_write(max283x_driver_t* const drv, uint8_t r, uint16_t v) * provided routines for those operations. */ void max283x_regs_commit(max283x_driver_t* const drv) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - max2831_regs_commit(&drv->drv.max2831); - break; -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - max2837_regs_commit(&drv->drv.max2837); - break; -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - max2839_regs_commit(&drv->drv.max2839); - break; -#endif - default: - break; - } + CALL(drv, regs_commit); } void max283x_set_mode(max283x_driver_t* const drv, const max283x_mode_t new_mode) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - max2831_set_mode(&drv->drv.max2831, (max2831_mode_t) new_mode); - break; -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - max2837_set_mode(&drv->drv.max2837, (max2837_mode_t) new_mode); - break; -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - max2839_set_mode(&drv->drv.max2839, (max2839_mode_t) new_mode); - break; -#endif - default: - break; - } + DISPATCH( + drv, + max2831_set_mode(&drv->drv.max2831, (max2831_mode_t) new_mode), + max2837_set_mode(&drv->drv.max2837, (max2837_mode_t) new_mode), + max2839_set_mode(&drv->drv.max2839, (max2839_mode_t) new_mode)); } max283x_mode_t max283x_mode(max283x_driver_t* const drv) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - return (max283x_mode_t) max2831_mode(&drv->drv.max2831); -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - return (max283x_mode_t) max2837_mode(&drv->drv.max2837); -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - return (max283x_mode_t) max2839_mode(&drv->drv.max2839); -#endif - default: - return 0; - } + DISPATCH( + drv, + return (max283x_mode_t) max2831_mode(&drv->drv.max2831), + return (max283x_mode_t) max2837_mode(&drv->drv.max2837), + return (max283x_mode_t) max2839_mode(&drv->drv.max2839)); } /* Turn on/off all chip functions. Does not control oscillator and CLKOUT */ void max283x_start(max283x_driver_t* const drv) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - max2831_start(&drv->drv.max2831); - break; -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - max2837_start(&drv->drv.max2837); - break; -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - max2839_start(&drv->drv.max2839); - break; -#endif - default: - break; - } + CALL(drv, start); } void max283x_stop(max283x_driver_t* const drv) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - max2831_stop(&drv->drv.max2831); - break; -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - max2837_stop(&drv->drv.max2837); - break; -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - max2839_stop(&drv->drv.max2839); - break; -#endif - default: - break; - } + CALL(drv, stop); } /* Set frequency in 1/(2**24) Hz. */ @@ -318,26 +241,7 @@ fp_40_24_t max283x_set_frequency( fp_40_24_t freq, bool program) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - return max2831_set_frequency(&drv->drv.max2831, freq, program); - break; -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - return max2837_set_frequency(&drv->drv.max2837, freq, program); - break; -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - return max2839_set_frequency(&drv->drv.max2839, freq, program); - break; -#endif - default: - break; - } - return 0; + return RESULT(drv, fp_40_24_t, set_frequency, freq, program); } uint32_t max283x_set_lpf_bandwidth( @@ -345,135 +249,42 @@ uint32_t max283x_set_lpf_bandwidth( const max283x_mode_t mode, const uint32_t bandwidth_hz) { -#ifndef PRALINE +#if !defined(PRALINE) (void) mode; #endif - - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: + DISPATCH( + drv, return max2831_set_lpf_bandwidth( &drv->drv.max2831, (max2831_mode_t) mode, - bandwidth_hz); -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - return max2837_set_lpf_bandwidth(&drv->drv.max2837, bandwidth_hz); -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - return max2839_set_lpf_bandwidth(&drv->drv.max2839, bandwidth_hz); -#endif - default: - return 0; - } + bandwidth_hz), + return max2837_set_lpf_bandwidth(&drv->drv.max2837, bandwidth_hz), + return max2839_set_lpf_bandwidth(&drv->drv.max2839, bandwidth_hz)); } bool max283x_set_lna_gain(max283x_driver_t* const drv, const uint32_t gain_db) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - return max2831_set_lna_gain(&drv->drv.max2831, gain_db); -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - return max2837_set_lna_gain(&drv->drv.max2837, gain_db); -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - return max2839_set_lna_gain(&drv->drv.max2839, gain_db); -#endif - default: - return false; - } + return RESULT(drv, bool, set_lna_gain, gain_db); } bool max283x_set_vga_gain(max283x_driver_t* const drv, const uint32_t gain_db) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - return max2831_set_vga_gain(&drv->drv.max2831, gain_db); -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - return max2837_set_vga_gain(&drv->drv.max2837, gain_db); -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - return max2839_set_vga_gain(&drv->drv.max2839, gain_db); -#endif - default: - return false; - } + return RESULT(drv, bool, set_vga_gain, gain_db); } bool max283x_set_txvga_gain(max283x_driver_t* const drv, const uint32_t gain_db) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - return max2831_set_txvga_gain(&drv->drv.max2831, gain_db); -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - return max2837_set_txvga_gain(&drv->drv.max2837, gain_db); -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - return max2839_set_txvga_gain(&drv->drv.max2839, gain_db); -#endif - default: - return false; - } + return RESULT(drv, bool, set_txvga_gain, gain_db); } void max283x_tx(max283x_driver_t* const drv) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - max2831_tx(&drv->drv.max2831); - break; -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - max2837_tx(&drv->drv.max2837); - break; -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - max2839_tx(&drv->drv.max2839); - break; -#endif - default: - break; - } + CALL(drv, tx); } void max283x_rx(max283x_driver_t* const drv) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - max2831_rx(&drv->drv.max2831); - break; -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - max2837_rx(&drv->drv.max2837); - break; -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - max2839_rx(&drv->drv.max2839); - break; -#endif - default: - break; - } + CALL(drv, rx); } /* Set MAX2831 receiver high-pass filter corner frequency in Hz */ @@ -481,75 +292,22 @@ void max283x_set_rx_hpf_frequency( max283x_driver_t* const drv, const max283x_rx_hpf_freq_t freq) { -#if !defined(PRALINE) +#if !defined(PRALINE) && !defined(UNIVERSAL) (void) freq; #endif - - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: + PRALINE_ONLY( + drv, max2831_set_rx_hpf_frequency( &drv->drv.max2831, - (max2831_rx_hpf_freq_t) freq); - break; -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - // unsupported - break; -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - // unsupported - break; -#endif - default: - break; - } + (max2831_rx_hpf_freq_t) freq)); } void max283x_tx_calibration(max283x_driver_t* const drv) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - max2831_tx_calibration(&drv->drv.max2831); - break; -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - // unsupported - use max283x_set_mode instead - break; -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - // unsupported - use max283x_set_mode instead - break; -#endif - default: - break; - } + PRALINE_ONLY(drv, max2831_tx_calibration(&drv->drv.max2831)); } void max283x_rx_calibration(max283x_driver_t* const drv) { - switch (drv->type) { -#if defined(PRALINE) || defined(UNIVERSAL) - case MAX2831_VARIANT: - max2831_rx_calibration(&drv->drv.max2831); - break; -#endif -#if !defined(PRALINE) || defined(UNIVERSAL) - case MAX2837_VARIANT: - // unsupported - use max283x_set_mode instead - break; -#endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - case MAX2839_VARIANT: - // unsupported - use max283x_set_mode instead - break; -#endif - default: - break; - } + PRALINE_ONLY(drv, max2831_rx_calibration(&drv->drv.max2831)); } From 439f6fd3554dda31782fb3db66dd6f061cd08ece Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 15 Apr 2026 02:05:24 +0100 Subject: [PATCH 129/238] firmware: Use macros to simplify platform-specific code. --- firmware/common/cpld_jtag.c | 64 +-- firmware/common/hackrf_core.c | 549 +++++++++-------------- firmware/common/hackrf_ui.c | 18 +- firmware/common/max283x.c | 44 +- firmware/common/mixer.c | 121 ++--- firmware/common/operacake_sctimer.c | 11 +- firmware/common/platform_detect.h | 111 +++++ firmware/common/platform_gpio.c | 235 +++------- firmware/common/platform_scu.c | 300 ++++--------- firmware/common/radio.c | 116 ++--- firmware/common/rf_path.c | 90 ++-- firmware/common/rffc5071.c | 37 +- firmware/common/sgpio.c | 15 +- firmware/common/si5351c.c | 48 +- firmware/common/tuning.c | 13 +- firmware/hackrf_usb/hackrf_usb.c | 118 ++--- firmware/hackrf_usb/usb_api_board_info.c | 6 +- firmware/hackrf_usb/usb_api_register.c | 138 +++--- firmware/hackrf_usb/usb_api_selftest.c | 37 +- 19 files changed, 822 insertions(+), 1249 deletions(-) diff --git a/firmware/common/cpld_jtag.c b/firmware/common/cpld_jtag.c index 21991db0..58359051 100644 --- a/firmware/common/cpld_jtag.c +++ b/firmware/common/cpld_jtag.c @@ -39,83 +39,55 @@ void cpld_jtag_take(jtag_t* const jtag) { const jtag_gpio_t* const gpio = jtag->gpio; - board_id_t board_id = detected_platform(); - /* Set initial GPIO state to the voltages of the internal or external pull-ups/downs, * to avoid any glitches. */ - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: - case BOARD_ID_PRALINE: -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + IF_EXPANSION_COMPATIBLE ( gpio_set(gpio->gpio_pp_tms); -#endif - break; - default: - break; - } + ) + gpio_clear(gpio->gpio_tck); - if (board_id != BOARD_ID_PRALINE) { -#if !defined(PRALINE) || defined(UNIVERSAL) + + IF_NOT_PRALINE ( gpio_set(gpio->gpio_tms); gpio_set(gpio->gpio_tdi); -#endif - } + ) - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: - case BOARD_ID_PRALINE: -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + IF_EXPANSION_COMPATIBLE ( /* Do not drive PortaPack-specific TMS pin initially, just to be cautious. */ gpio_input(gpio->gpio_pp_tms); gpio_input(gpio->gpio_pp_tdo); -#endif - break; - default: - break; - } + ) + gpio_output(gpio->gpio_tck); - if (board_id != BOARD_ID_PRALINE) { -#if !defined(PRALINE) || defined(UNIVERSAL) + + IF_NOT_PRALINE ( gpio_output(gpio->gpio_tms); gpio_output(gpio->gpio_tdi); gpio_input(gpio->gpio_tdo); -#endif - } + ) } void cpld_jtag_release(jtag_t* const jtag) { const jtag_gpio_t* const gpio = jtag->gpio; - board_id_t board_id = detected_platform(); - /* Make all pins inputs when JTAG interface not active. * Let the pull-ups/downs do the work. */ - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: - case BOARD_ID_PRALINE: -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + IF_EXPANSION_COMPATIBLE ( /* Do not drive PortaPack-specific pins, initially, just to be cautious. */ gpio_input(gpio->gpio_pp_tms); gpio_input(gpio->gpio_pp_tdo); -#endif - break; - default: - break; - } + ) + gpio_input(gpio->gpio_tck); - if (board_id != BOARD_ID_PRALINE) { -#if !defined(PRALINE) || defined(UNIVERSAL) + + IF_NOT_PRALINE ( gpio_input(gpio->gpio_tms); gpio_input(gpio->gpio_tdi); gpio_input(gpio->gpio_tdo); -#endif - } + ) } #if !defined(PRALINE) || defined(UNIVERSAL) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index c8b66443..689a2a30 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -341,8 +341,7 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) sgpio_cpld_stream_disable(&sgpio_config); } - if (detected_platform() != BOARD_ID_PRALINE) { -#if !defined(PRALINE) || defined(UNIVERSAL) + IF_NOT_PRALINE ( /* Integer mode can be enabled if p1 is even and p2 is zero. */ if (p1 & 0x1 || p2) { si5351c_set_int_mode(&clock_gen, 0, 0); @@ -350,13 +349,14 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) si5351c_set_int_mode(&clock_gen, 0, 1); } - if (detected_platform() == BOARD_ID_HACKRF1_R9) { + IF_H1_R9 ( /* * On HackRF One r9 all sample clocks are externally derived * from MS1/CLK1 operating at twice the sample rate. */ si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 0); - } else { + ) + IF_NOT_H1_R9 ( /* * On other platforms the clock generator produces three * different sample clocks, all derived from multisynth 0. @@ -381,10 +381,9 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) 0, 0, 0); //p1 doesn't matter - } -#endif - } else { -#if defined(PRALINE) || defined(UNIVERSAL) + ) + ) + IF_PRALINE ( /* MS0/CLK0 is the source for the MAX5864 (AFE_CLK). */ si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); @@ -410,8 +409,7 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) /* Reset PLL to synchronize output clock phase. */ si5351c_reset_pll(&clock_gen, SI5351C_PLL_A); -#endif - } + ) if (streaming) { sgpio_cpld_stream_enable(&sgpio_config); @@ -563,73 +561,75 @@ void cpu_clock_init(void) CGU_BASE_SSP1_CLK = CGU_BASE_SSP1_CLK_AUTOBLOCK(1) | CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1); -#if !defined(RAD1O) - /* Disable unused clocks */ - /* Start with PLLs */ - CGU_PLL0AUDIO_CTRL = CGU_PLL0AUDIO_CTRL_PD(1); + IF_NOT_RAD1O ( + /* Disable unused clocks */ + /* Start with PLLs */ + CGU_PLL0AUDIO_CTRL = CGU_PLL0AUDIO_CTRL_PD(1); - /* Dividers */ - CGU_IDIVA_CTRL = CGU_IDIVA_CTRL_PD(1); - CGU_IDIVB_CTRL = CGU_IDIVB_CTRL_PD(1); - CGU_IDIVC_CTRL = CGU_IDIVC_CTRL_PD(1); - CGU_IDIVD_CTRL = CGU_IDIVD_CTRL_PD(1); - CGU_IDIVE_CTRL = CGU_IDIVE_CTRL_PD(1); + /* Dividers */ + CGU_IDIVA_CTRL = CGU_IDIVA_CTRL_PD(1); + CGU_IDIVB_CTRL = CGU_IDIVB_CTRL_PD(1); + CGU_IDIVC_CTRL = CGU_IDIVC_CTRL_PD(1); + CGU_IDIVD_CTRL = CGU_IDIVD_CTRL_PD(1); + CGU_IDIVE_CTRL = CGU_IDIVE_CTRL_PD(1); - /* Base clocks */ - CGU_BASE_SPIFI_CLK = CGU_BASE_SPIFI_CLK_PD(1); /* SPIFI is only used at boot */ - CGU_BASE_USB1_CLK = CGU_BASE_USB1_CLK_PD(1); /* USB1 is not exposed on HackRF */ - CGU_BASE_PHY_RX_CLK = CGU_BASE_PHY_RX_CLK_PD(1); - CGU_BASE_PHY_TX_CLK = CGU_BASE_PHY_TX_CLK_PD(1); - CGU_BASE_LCD_CLK = CGU_BASE_LCD_CLK_PD(1); - CGU_BASE_VADC_CLK = CGU_BASE_VADC_CLK_PD(1); - CGU_BASE_SDIO_CLK = CGU_BASE_SDIO_CLK_PD(1); - CGU_BASE_UART0_CLK = CGU_BASE_UART0_CLK_PD(1); - CGU_BASE_UART1_CLK = CGU_BASE_UART1_CLK_PD(1); - CGU_BASE_UART2_CLK = CGU_BASE_UART2_CLK_PD(1); - CGU_BASE_UART3_CLK = CGU_BASE_UART3_CLK_PD(1); - CGU_BASE_OUT_CLK = CGU_BASE_OUT_CLK_PD(1); - CGU_BASE_AUDIO_CLK = CGU_BASE_AUDIO_CLK_PD(1); - CGU_BASE_CGU_OUT0_CLK = CGU_BASE_CGU_OUT0_CLK_PD(1); - CGU_BASE_CGU_OUT1_CLK = CGU_BASE_CGU_OUT1_CLK_PD(1); + /* Base clocks */ + CGU_BASE_SPIFI_CLK = + CGU_BASE_SPIFI_CLK_PD(1); /* SPIFI is only used at boot */ + CGU_BASE_USB1_CLK = + CGU_BASE_USB1_CLK_PD(1); /* USB1 is not exposed on HackRF */ + CGU_BASE_PHY_RX_CLK = CGU_BASE_PHY_RX_CLK_PD(1); + CGU_BASE_PHY_TX_CLK = CGU_BASE_PHY_TX_CLK_PD(1); + CGU_BASE_LCD_CLK = CGU_BASE_LCD_CLK_PD(1); + CGU_BASE_VADC_CLK = CGU_BASE_VADC_CLK_PD(1); + CGU_BASE_SDIO_CLK = CGU_BASE_SDIO_CLK_PD(1); + CGU_BASE_UART0_CLK = CGU_BASE_UART0_CLK_PD(1); + CGU_BASE_UART1_CLK = CGU_BASE_UART1_CLK_PD(1); + CGU_BASE_UART2_CLK = CGU_BASE_UART2_CLK_PD(1); + CGU_BASE_UART3_CLK = CGU_BASE_UART3_CLK_PD(1); + CGU_BASE_OUT_CLK = CGU_BASE_OUT_CLK_PD(1); + CGU_BASE_AUDIO_CLK = CGU_BASE_AUDIO_CLK_PD(1); + CGU_BASE_CGU_OUT0_CLK = CGU_BASE_CGU_OUT0_CLK_PD(1); + CGU_BASE_CGU_OUT1_CLK = CGU_BASE_CGU_OUT1_CLK_PD(1); - /* Disable unused peripheral clocks */ - CCU1_CLK_APB1_CAN1_CFG = 0; - CCU1_CLK_APB1_I2S_CFG = 0; - CCU1_CLK_APB1_MOTOCONPWM_CFG = 0; - //CCU1_CLK_APB3_ADC0_CFG = 0; - CCU1_CLK_APB3_ADC1_CFG = 0; - CCU1_CLK_APB3_CAN0_CFG = 0; - CCU1_CLK_APB3_DAC_CFG = 0; - //CCU1_CLK_M4_DMA_CFG = 0; - CCU1_CLK_M4_EMC_CFG = 0; - CCU1_CLK_M4_EMCDIV_CFG = 0; - CCU1_CLK_M4_ETHERNET_CFG = 0; - CCU1_CLK_M4_LCD_CFG = 0; - CCU1_CLK_M4_QEI_CFG = 0; - CCU1_CLK_M4_RITIMER_CFG = 0; - // CCU1_CLK_M4_SCT_CFG = 0; - CCU1_CLK_M4_SDIO_CFG = 0; - CCU1_CLK_M4_SPIFI_CFG = 0; - CCU1_CLK_M4_TIMER0_CFG = 0; - //CCU1_CLK_M4_TIMER1_CFG = 0; - //CCU1_CLK_M4_TIMER2_CFG = 0; - CCU1_CLK_M4_TIMER3_CFG = 0; - CCU1_CLK_M4_UART1_CFG = 0; - CCU1_CLK_M4_USART0_CFG = 0; - CCU1_CLK_M4_USART2_CFG = 0; - CCU1_CLK_M4_USART3_CFG = 0; - CCU1_CLK_M4_USB1_CFG = 0; - CCU1_CLK_M4_VADC_CFG = 0; - // CCU1_CLK_SPIFI_CFG = 0; - // CCU1_CLK_USB1_CFG = 0; - // CCU1_CLK_VADC_CFG = 0; - // CCU2_CLK_APB0_UART1_CFG = 0; - // CCU2_CLK_APB0_USART0_CFG = 0; - // CCU2_CLK_APB2_USART2_CFG = 0; - // CCU2_CLK_APB2_USART3_CFG = 0; - // CCU2_CLK_APLL_CFG = 0; - // CCU2_CLK_SDIO_CFG = 0; -#endif + /* Disable unused peripheral clocks */ + CCU1_CLK_APB1_CAN1_CFG = 0; + CCU1_CLK_APB1_I2S_CFG = 0; + CCU1_CLK_APB1_MOTOCONPWM_CFG = 0; + //CCU1_CLK_APB3_ADC0_CFG = 0; + CCU1_CLK_APB3_ADC1_CFG = 0; + CCU1_CLK_APB3_CAN0_CFG = 0; + CCU1_CLK_APB3_DAC_CFG = 0; + //CCU1_CLK_M4_DMA_CFG = 0; + CCU1_CLK_M4_EMC_CFG = 0; + CCU1_CLK_M4_EMCDIV_CFG = 0; + CCU1_CLK_M4_ETHERNET_CFG = 0; + CCU1_CLK_M4_LCD_CFG = 0; + CCU1_CLK_M4_QEI_CFG = 0; + CCU1_CLK_M4_RITIMER_CFG = 0; + // CCU1_CLK_M4_SCT_CFG = 0; + CCU1_CLK_M4_SDIO_CFG = 0; + CCU1_CLK_M4_SPIFI_CFG = 0; + CCU1_CLK_M4_TIMER0_CFG = 0; + //CCU1_CLK_M4_TIMER1_CFG = 0; + //CCU1_CLK_M4_TIMER2_CFG = 0; + CCU1_CLK_M4_TIMER3_CFG = 0; + CCU1_CLK_M4_UART1_CFG = 0; + CCU1_CLK_M4_USART0_CFG = 0; + CCU1_CLK_M4_USART2_CFG = 0; + CCU1_CLK_M4_USART3_CFG = 0; + CCU1_CLK_M4_USB1_CFG = 0; + CCU1_CLK_M4_VADC_CFG = 0; + // CCU1_CLK_SPIFI_CFG = 0; + // CCU1_CLK_USB1_CFG = 0; + // CCU1_CLK_VADC_CFG = 0; + // CCU2_CLK_APB0_UART1_CFG = 0; + // CCU2_CLK_APB0_USART0_CFG = 0; + // CCU2_CLK_APB2_USART2_CFG = 0; + // CCU2_CLK_APB2_USART3_CFG = 0; + // CCU2_CLK_APLL_CFG = 0; + // CCU2_CLK_SDIO_CFG = 0; + ) } void clock_gen_init(void) @@ -670,7 +670,7 @@ void clock_gen_init(void) * CLK7 -> AUX_CLK2 */ - if (detected_platform() == BOARD_ID_HACKRF1_R9) { + IF_H1_R9 ( /* MS0/CLK0 is the reference for both RFFC5071 and MAX2839. */ si5351c_configure_multisynth( &clock_gen, @@ -679,7 +679,8 @@ void clock_gen_init(void) 0, 1, 0); /* 800/20 = 40MHz */ - } else { + ) + IF_NOT_H1_R9 ( /* MS4/CLK4 is the source for the RFFC5071 mixer (MAX2837 on rad1o). */ si5351c_configure_multisynth( &clock_gen, @@ -696,7 +697,7 @@ void clock_gen_init(void) 0, 1, 0); /* 800/20 = 40MHz */ - } + ) /* MS6/CLK6 is unused. */ /* MS7/CLK7 is unused. */ @@ -721,20 +722,12 @@ void clock_gen_shutdown(void) clock_source_t activate_best_clock_source(void) { - switch (detected_platform()) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: - case BOARD_ID_PRALINE: -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + IF_EXPANSION_COMPATIBLE ( /* Ensure PortaPack reference oscillator is off while checking for external clock input. */ if (portapack_reference_oscillator && portapack()) { portapack_reference_oscillator(false); } -#endif - break; - default: - break; - } + ) clock_source_t source = CLOCK_SOURCE_HACKRF; @@ -742,11 +735,7 @@ clock_source_t activate_best_clock_source(void) if (si5351c_clkin_signal_valid(&clock_gen)) { source = CLOCK_SOURCE_EXTERNAL; } else { - switch (detected_platform()) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: - case BOARD_ID_PRALINE: -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + IF_EXPANSION_COMPATIBLE ( /* Enable PortaPack reference oscillator (if present), and check for valid clock. */ if (portapack_reference_oscillator && portapack()) { portapack_reference_oscillator(true); @@ -757,11 +746,7 @@ clock_source_t activate_best_clock_source(void) portapack_reference_oscillator(false); } } -#endif - break; - default: - break; - } + ) /* No external or PortaPack clock was found. Use HackRF Si5351C crystal. */ } @@ -796,7 +781,6 @@ void pin_shutdown(void) gpio_init(); /* Detect Platform */ - board_id_t board_id = detected_platform(); const platform_gpio_t* gpio = platform_gpio(); const platform_scu_t* scu = platform_scu(); @@ -814,99 +798,69 @@ void pin_shutdown(void) * * LPC43xx pull-up and pull-down resistors are approximately 53K. */ - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: - case BOARD_ID_PRALINE: -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + IF_EXPANSION_COMPATIBLE ( scu_pinmux(scu->PINMUX_PP_TMS, SCU_GPIO_PUP | SCU_CONF_FUNCTION0); scu_pinmux(scu->PINMUX_PP_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); -#endif - break; - default: - break; - } + ) scu_pinmux(scu->PINMUX_CPLD_TCK, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); - if (board_id != BOARD_ID_PRALINE) { -#if !defined(PRALINE) || defined(UNIVERSAL) + IF_NOT_PRALINE ( scu_pinmux(scu->PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); scu_pinmux(scu->PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); scu_pinmux(scu->PINMUX_CPLD_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); -#endif - } + ) /* Configure SCU Pin Mux as GPIO */ scu_pinmux(scu->PINMUX_LED1, SCU_GPIO_NOPULL); scu_pinmux(scu->PINMUX_LED2, SCU_GPIO_NOPULL); scu_pinmux(scu->PINMUX_LED3, SCU_GPIO_NOPULL); - switch (board_id) { - case BOARD_ID_RAD1O: -#if defined(RAD1O) + IF_RAD1O ( scu_pinmux(scu->PINMUX_LED4, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION4); -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( scu_pinmux(scu->PINMUX_LED4, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); -#endif - break; - default: - break; - } + ) /* Configure USB indicators */ - if (board_id == BOARD_ID_JAWBREAKER) { -#if defined(JAWBREAKER) + IF_JAWBREAKER ( scu_pinmux(scu->PINMUX_USB_LED0, SCU_CONF_FUNCTION3); scu_pinmux(scu->PINMUX_USB_LED1, SCU_CONF_FUNCTION3); -#endif - } + ) - switch (board_id) { - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( disable_1v2_power(); disable_3v3aux_power(); gpio_output(gpio->gpio_1v2_enable); gpio_output(gpio->gpio_3v3aux_enable_n); scu_pinmux(scu->PINMUX_EN1V2, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(scu->PINMUX_EN3V3_AUX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); -#endif - break; - default: + ) + + IF_NOT_PRALINE ( disable_1v8_power(); - if (detected_platform() == BOARD_ID_HACKRF1_R9) { -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_H1_R9 ( gpio_output(gpio->h1r9_1v8_enable); scu_pinmux(scu->H1R9_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); -#endif - } else { + ) + IF_NOT_H1_R9 ( gpio_output(gpio->gpio_1v8_enable); scu_pinmux(scu->PINMUX_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - } - break; - } + ) + ) - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: - case BOARD_ID_PRALINE: -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + IF_H1_OR_PRALINE ( /* Safe state: start with VAA turned off: */ disable_rf_power(); /* Configure RF power supply (VAA) switch control signal as output */ - if (board_id == BOARD_ID_HACKRF1_R9) { - #if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_H1_R9 ( gpio_output(gpio->h1r9_vaa_disable); - #endif - } else { + ) + IF_NOT_H1_R9 ( gpio_output(gpio->vaa_disable); - } - break; -#endif - case BOARD_ID_RAD1O: -#if defined(RAD1O) + ) + ) + + IF_RAD1O ( /* Safe state: start with VAA turned off: */ disable_rf_power(); @@ -919,15 +873,9 @@ void pin_shutdown(void) scu_pinmux(scu->PINMUX_GPIO3_10, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); scu_pinmux(scu->PINMUX_GPIO3_11, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); -#endif - break; - default: - break; - } + ) - switch (board_id) { - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( scu_pinmux(scu->P2_CTRL0, scu->P2_CTRL0_PINCFG); scu_pinmux(scu->P2_CTRL1, scu->P2_CTRL1_PINCFG); scu_pinmux(scu->P1_CTRL0, scu->P1_CTRL0_PINCFG); @@ -962,11 +910,7 @@ void pin_shutdown(void) gpio_clear(gpio->fpga_cfg_creset); gpio_output(gpio->fpga_cfg_creset); gpio_input(gpio->fpga_cfg_cdone); -#endif - break; - default: - break; - } + ) /* enable input on SCL and SDA pins */ SCU_SFSI2C0 = SCU_I2C0_NOMINAL; @@ -976,7 +920,6 @@ void pin_shutdown(void) void pin_setup(void) { /* Detect Platform */ - board_id_t board_id = detected_platform(); const platform_gpio_t* gpio = platform_gpio(); const platform_scu_t* scu = platform_scu(); @@ -984,34 +927,26 @@ void pin_setup(void) led_off(0); led_off(1); led_off(2); - switch (board_id) { - case BOARD_ID_RAD1O: + IF_FOUR_LEDS ( led_off(3); - default: - break; - } + ) gpio_output(gpio->led[0]); gpio_output(gpio->led[1]); gpio_output(gpio->led[2]); - switch (board_id) { - case BOARD_ID_RAD1O: - case BOARD_ID_PRALINE: -#if defined(RAD1O) || defined(PRALINE) || defined(UNIVERSAL) + + IF_FOUR_LEDS ( gpio_output(gpio->led[3]); -#endif - break; - default: - break; - } + ) /* Configure drivers and driver pins */ ssp_config_max283x.gpio_select = gpio->max283x_select; - if (board_id == BOARD_ID_PRALINE) { - ssp_config_max283x.data_bits = SSP_DATA_9BITS; // send 2 words - } else { + IF_NOT_PRALINE ( ssp_config_max283x.data_bits = SSP_DATA_16BITS; - } + ) + IF_PRALINE ( + ssp_config_max283x.data_bits = SSP_DATA_9BITS; // send 2 words + ) ssp_config_max5864.gpio_select = gpio->max5864_select; @@ -1020,62 +955,41 @@ void pin_setup(void) spi_flash.gpio_wp = gpio->w25q80bv_wp; sgpio_config.gpio_q_invert = gpio->q_invert; - if (board_id != BOARD_ID_PRALINE) { -#if !defined(PRALINE) || defined(UNIVERSAL) - sgpio_config.gpio_trigger_enable = gpio->trigger_enable; -#endif - } -#if defined(PRALINE) || defined(UNIVERSAL) - ssp_config_ice40_fpga.gpio_select = gpio->fpga_cfg_spi_cs; - ice40.gpio_select = gpio->fpga_cfg_spi_cs; - ice40.gpio_creset = gpio->fpga_cfg_creset; - ice40.gpio_cdone = gpio->fpga_cfg_cdone; -#endif + IF_NOT_PRALINE ( + sgpio_config.gpio_trigger_enable = gpio->trigger_enable; + ) + + IF_PRALINE ( + ssp_config_ice40_fpga.gpio_select = gpio->fpga_cfg_spi_cs; + ice40.gpio_select = gpio->fpga_cfg_spi_cs; + ice40.gpio_creset = gpio->fpga_cfg_creset; + ice40.gpio_cdone = gpio->fpga_cfg_cdone; + ) jtag_gpio_cpld.gpio_tck = gpio->cpld_tck; -#if !defined(PRALINE) || defined(UNIVERSAL) - jtag_gpio_cpld.gpio_tms = gpio->cpld_tms; - jtag_gpio_cpld.gpio_tdi = gpio->cpld_tdi; - jtag_gpio_cpld.gpio_tdo = gpio->cpld_tdo; -#endif - if (board_id != BOARD_ID_PRALINE) { -#if !defined(PRALINE) || defined(UNIVERSAL) + + IF_NOT_PRALINE ( jtag_gpio_cpld.gpio_tms = gpio->cpld_tms; jtag_gpio_cpld.gpio_tdi = gpio->cpld_tdi; jtag_gpio_cpld.gpio_tdo = gpio->cpld_tdo; -#endif - } - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: - case BOARD_ID_PRALINE: -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + ) + + IF_EXPANSION_COMPATIBLE ( jtag_gpio_cpld.gpio_pp_tms = gpio->cpld_pp_tms; jtag_gpio_cpld.gpio_pp_tdo = gpio->cpld_pp_tdo; -#endif - break; - default: - break; - } + ) ssp1_set_mode_max283x(); mixer_bus_setup(&mixer); - if (detected_platform() == BOARD_ID_HACKRF1_R9) { -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_H1_R9 ( sgpio_config.gpio_trigger_enable = gpio->h1r9_trigger_enable; -#endif - } + ) // initialize rf_path struct and assign gpio's - switch (board_id) { - case BOARD_ID_JAWBREAKER: - break; - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_HACKRF_ONE ( rf_path = (rf_path_t){ .switchctrl = 0, .gpio_hp = gpio->hp, @@ -1092,14 +1006,13 @@ void pin_setup(void) .gpio_rx_amp = gpio->rx_amp, .gpio_no_rx_amp_pwr = gpio->no_rx_amp_pwr, }; - if (board_id == BOARD_ID_HACKRF1_R9) { + IF_H1_R9 ( rf_path.gpio_rx = gpio->h1r9_rx; rf_path.gpio_h1r9_no_ant_pwr = gpio->h1r9_no_ant_pwr; - } -#endif - break; - case BOARD_ID_RAD1O: -#if defined(RAD1O) + ) + ) + + IF_RAD1O ( rf_path = (rf_path_t){ .switchctrl = 0, .gpio_tx_rx_n = gpio->tx_rx_n, @@ -1114,10 +1027,9 @@ void pin_setup(void) .gpio_tx_amp = gpio->tx_amp, .gpio_rx_lna = gpio->rx_lna, }; -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + + IF_PRALINE ( rf_path = (rf_path_t){ .switchctrl = 0, .gpio_tx_en = gpio->tx_en, @@ -1130,11 +1042,8 @@ void pin_setup(void) (detected_revision() == BOARD_REV_GSG_PRALINE_R1_0)) { rf_path.gpio_mix_en_n = gpio->mix_en_n_r1_0; } -#endif - break; - default: - break; - } + ) + rf_path_pin_setup(&rf_path); /* Configure external clock in */ @@ -1146,79 +1055,55 @@ void pin_setup(void) #if defined(PRALINE) || defined(UNIVERSAL) void enable_1v2_power(void) { - switch (detected_platform()) { - case BOARD_ID_PRALINE: + IF_PRALINE ( gpio_set(platform_gpio()->gpio_1v2_enable); - break; - default: - break; - } + ) } void disable_1v2_power(void) { - switch (detected_platform()) { - case BOARD_ID_PRALINE: + IF_PRALINE ( gpio_clear(platform_gpio()->gpio_1v2_enable); - break; - default: - break; - } + ) } void enable_3v3aux_power(void) { - switch (detected_platform()) { - case BOARD_ID_PRALINE: + IF_PRALINE ( gpio_clear(platform_gpio()->gpio_3v3aux_enable_n); - break; - default: - break; - } + ) } void disable_3v3aux_power(void) { - switch (detected_platform()) { - case BOARD_ID_PRALINE: + IF_PRALINE ( gpio_set(platform_gpio()->gpio_3v3aux_enable_n); - break; - default: - break; - } + ) } #endif void enable_1v8_power(void) { - switch (detected_platform()) { - case BOARD_ID_HACKRF1_R9: -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - gpio_set(platform_gpio()->h1r9_1v8_enable); -#endif - break; - case BOARD_ID_PRALINE: - break; - default: - gpio_set(platform_gpio()->gpio_1v8_enable); - break; - } + IF_NOT_PRALINE ( + IF_H1_R9 ( + gpio_set(platform_gpio()->h1r9_1v8_enable); + ) + IF_NOT_H1_R9 ( + gpio_set(platform_gpio()->gpio_1v8_enable); + ) + ) } void disable_1v8_power(void) { - switch (detected_platform()) { - case BOARD_ID_HACKRF1_R9: -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - gpio_clear(platform_gpio()->h1r9_1v8_enable); -#endif - break; - case BOARD_ID_PRALINE: - break; - default: - gpio_clear(platform_gpio()->gpio_1v8_enable); - break; - } + IF_NOT_PRALINE ( + IF_H1_R9 ( + gpio_clear(platform_gpio()->h1r9_1v8_enable); + ) + IF_NOT_H1_R9 ( + gpio_clear(platform_gpio()->gpio_1v8_enable); + ) + ) } #if defined(HACKRF_ONE) || defined(UNIVERSAL) @@ -1281,68 +1166,48 @@ static inline void disable_rf_power_rad1o(void) void enable_rf_power(void) { - switch (detected_platform()) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_HACKRF_ONE ( enable_rf_power_hackrf_one(); -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( enable_rf_power_praline(); -#endif - break; - case BOARD_ID_RAD1O: -#if defined(RAD1O) + ) + IF_RAD1O ( enable_rf_power_rad1o(); -#endif - break; - default: - break; - } + ) } void disable_rf_power(void) { - switch (detected_platform()) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_HACKRF_ONE ( disable_rf_power_hackrf_one(); -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( disable_rf_power_praline(); -#endif - break; - case BOARD_ID_RAD1O: -#if defined(RAD1O) + ) + IF_RAD1O ( disable_rf_power_rad1o(); -#endif - break; - default: - break; - } + ) } void led_on(const led_t led) { - if (detected_platform() == BOARD_ID_PRALINE) { + IF_PRALINE ( gpio_clear(platform_gpio()->led[led]); - } else { + ) + IF_NOT_PRALINE ( gpio_set(platform_gpio()->led[led]); - } + ) } void led_off(const led_t led) { - if (detected_platform() == BOARD_ID_PRALINE) { + IF_PRALINE ( gpio_set(platform_gpio()->led[led]); - } else { + ) + IF_NOT_PRALINE ( gpio_clear(platform_gpio()->led[led]); - } + ) } void led_toggle(const led_t led) @@ -1352,33 +1217,29 @@ void led_toggle(const led_t led) void set_leds(const uint8_t state) { - board_id_t board_id = detected_platform(); - int num_leds = 3; - if (board_id == BOARD_ID_RAD1O || board_id == BOARD_ID_PRALINE) { + IF_FOUR_LEDS ( num_leds = 4; - } + ) for (int i = 0; i < num_leds; i++) { - if (board_id == BOARD_ID_PRALINE) { + IF_PRALINE ( gpio_write(platform_gpio()->led[i], ((state >> i) & 1) == 0); - } else { + ) + IF_NOT_PRALINE ( gpio_write(platform_gpio()->led[i], ((state >> i) & 1) == 1); - } + ) } } void trigger_enable(const bool enable) { - if (detected_platform() != BOARD_ID_PRALINE) { -#if !defined(PRALINE) || defined(UNIVERSAL) + IF_NOT_PRALINE ( gpio_write(sgpio_config.gpio_trigger_enable, enable); -#endif - } else { -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( fpga_set_trigger_enable(&fpga, enable); -#endif - } + ) } void halt_and_flash(const uint32_t duration) diff --git a/firmware/common/hackrf_ui.c b/firmware/common/hackrf_ui.c index ac16a444..092ec12b 100644 --- a/firmware/common/hackrf_ui.c +++ b/firmware/common/hackrf_ui.c @@ -83,26 +83,16 @@ const hackrf_ui_t* hackrf_ui(void) { /* Detect on first use. If no UI hardware is detected, use a stub function table. */ if (ui == NULL && ui_enabled) { - switch (detected_platform()) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: - case BOARD_ID_PRALINE: -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + IF_EXPANSION_COMPATIBLE ( if (portapack_hackrf_ui_init) { ui = portapack_hackrf_ui_init(); } -#endif - break; - case BOARD_ID_RAD1O: -#if defined(RAD1O) + ) + IF_RAD1O ( if (rad1o_ui_setup) { ui = rad1o_ui_setup(); } -#endif - break; - default: - break; - } + ) } if (ui == NULL) { diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index 6a6d5f26..feb7837d 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -73,9 +73,7 @@ void max283x_setup(max283x_driver_t* const drv) const platform_gpio_t* gpio = platform_gpio(); /* MAX283x GPIO PinMux */ - switch (detected_platform()) { - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( drv->type = MAX2831_VARIANT; max2831.gpio_enable = gpio->max283x_enable; max2831.gpio_rxtx = gpio->max283x_rx_enable; @@ -83,28 +81,24 @@ void max283x_setup(max283x_driver_t* const drv) max2831.gpio_ld = gpio->max2831_ld; memcpy(&drv->drv.max2831, &max2831, sizeof(max2831)); max2831_setup(&drv->drv.max2831); -#endif - break; - case BOARD_ID_HACKRF1_R9: -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - drv->type = MAX2839_VARIANT; - max2839.gpio_enable = gpio->max283x_enable; - max2839.gpio_rxtx = gpio->max283x_rx_enable; - memcpy(&drv->drv.max2839, &max2839, sizeof(max2839)); - max2839_setup(&drv->drv.max2839); -#endif - break; - default: -#if !defined(PRALINE) || defined(UNIVERSAL) - drv->type = MAX2837_VARIANT; - max2837.gpio_enable = gpio->max283x_enable; - max2837.gpio_rx_enable = gpio->max283x_rx_enable; - max2837.gpio_tx_enable = gpio->max283x_tx_enable; - memcpy(&drv->drv.max2837, &max2837, sizeof(max2837)); - max2837_setup(&drv->drv.max2837); -#endif - break; - } + ) + IF_NOT_PRALINE ( + IF_H1_R9 ( + drv->type = MAX2839_VARIANT; + max2839.gpio_enable = gpio->max283x_enable; + max2839.gpio_rxtx = gpio->max283x_rx_enable; + memcpy(&drv->drv.max2839, &max2839, sizeof(max2839)); + max2839_setup(&drv->drv.max2839); + ) + IF_NOT_H1_R9 ( + drv->type = MAX2837_VARIANT; + max2837.gpio_enable = gpio->max283x_enable; + max2837.gpio_rx_enable = gpio->max283x_rx_enable; + max2837.gpio_tx_enable = gpio->max283x_tx_enable; + memcpy(&drv->drv.max2837, &max2837, sizeof(max2837)); + max2837_setup(&drv->drv.max2837); + ) + ) } /* Macros to simplify dispatch of variant-specific operations. */ diff --git a/firmware/common/mixer.c b/firmware/common/mixer.c index 9e1afb32..0706170b 100644 --- a/firmware/common/mixer.c +++ b/firmware/common/mixer.c @@ -24,11 +24,11 @@ #include #include "fixed_point.h" +#include "platform_detect.h" #include "platform_gpio.h" #if defined(RAD1O) #include "max2871.h" #else - #include "platform_detect.h" #include "rffc5071.h" #include "rffc5071_spi.h" #include "spi_bus.h" @@ -54,26 +54,18 @@ mixer_driver_t mixer = { void mixer_bus_setup(mixer_driver_t* const mixer) { -#if defined(RAD1O) (void) mixer; -#else - const platform_gpio_t* gpio = platform_gpio(); -#endif - switch (mixer->type) { - case RFFC5071_VARIANT: -#if !defined(RAD1O) + IF_NOT_RAD1O ( + const platform_gpio_t* gpio = platform_gpio(); + rffc5071_spi_config = (rffc5071_spi_config_t){ .gpio_select = gpio->rffc5072_select, .gpio_clock = gpio->rffc5072_clock, .gpio_data = gpio->rffc5072_data, }; spi_bus_start(&spi_bus_rffc5071, &rffc5071_spi_config); -#endif - break; - case MAX2871_VARIANT: - break; - } + ) } void mixer_setup(mixer_driver_t* const mixer, mixer_variant_t type) @@ -83,106 +75,67 @@ void mixer_setup(mixer_driver_t* const mixer, mixer_variant_t type) const platform_gpio_t* gpio = platform_gpio(); /* Mixer GPIO serial interface PinMux */ - switch (mixer->type) { - case RFFC5071_VARIANT: -#if !defined(RAD1O) + IF_PRALINE ( + mixer->rffc5071.gpio_ld = gpio->rffc5072_ld + ); + + IF_NOT_RAD1O ( mixer->rffc5071.gpio_reset = gpio->rffc5072_reset; - if (detected_platform() == BOARD_ID_PRALINE) { - #if defined(PRALINE) || defined(UNIVERSAL) - mixer->rffc5071.gpio_ld = gpio->rffc5072_ld; - #endif - } -#endif - break; - case MAX2871_VARIANT: -#if defined(RAD1O) + rffc5071_setup(&mixer->rffc5071); + ) + + IF_RAD1O ( mixer->max2871.gpio_vco_ce = gpio->vco_ce; mixer->max2871.gpio_vco_sclk = gpio->vco_sclk; mixer->max2871.gpio_vco_sdata = gpio->vco_sdata; mixer->max2871.gpio_vco_le = gpio->vco_le; mixer->max2871.gpio_synt_rfout_en = gpio->synt_rfout_en; mixer->max2871.gpio_vco_mux = gpio->vco_mux; -#endif - break; - } - - switch (mixer->type) { - case RFFC5071_VARIANT: -#if !defined(RAD1O) - rffc5071_setup(&mixer->rffc5071); -#endif - break; - case MAX2871_VARIANT: -#if defined(RAD1O) max2871_setup(&mixer->max2871); -#endif - break; - } + ) } fp_40_24_t mixer_set_frequency(mixer_driver_t* const mixer, fp_40_24_t lo, bool program) { - switch (mixer->type) { - case RFFC5071_VARIANT: -#if !defined(RAD1O) + IF_NOT_RAD1O ( return rffc5071_set_frequency(&mixer->rffc5071, lo, program); -#endif - break; - case MAX2871_VARIANT: -#if defined(RAD1O) - return max2871_set_frequency(&mixer->max2871, lo, program); -#endif - break; - } + ) - return 0; + IF_RAD1O ( + return max2871_set_frequency(&mixer->max2871, lo, program); + ) } void mixer_enable(mixer_driver_t* const mixer) { - switch (mixer->type) { - case RFFC5071_VARIANT: -#if !defined(RAD1O) + IF_NOT_RAD1O ( rffc5071_enable(&mixer->rffc5071); -#endif - break; - case MAX2871_VARIANT: -#if defined(RAD1O) + ) + + IF_RAD1O ( max2871_enable(&mixer->max2871); -#endif - break; - } + ) } void mixer_disable(mixer_driver_t* const mixer) { - switch (mixer->type) { - case RFFC5071_VARIANT: -#if !defined(RAD1O) + IF_NOT_RAD1O ( rffc5071_disable(&mixer->rffc5071); -#endif - break; - case MAX2871_VARIANT: -#if defined(RAD1O) + ) + + IF_RAD1O ( max2871_disable(&mixer->max2871); -#endif - break; - } + ) } void mixer_set_gpo(mixer_driver_t* const mixer, uint8_t gpo) { -#if defined(RAD1O) - (void) gpo; -#endif - - switch (mixer->type) { - case RFFC5071_VARIANT: -#if !defined(RAD1O) + IF_NOT_RAD1O ( rffc5071_set_gpo(&mixer->rffc5071, gpo); -#endif - break; - case MAX2871_VARIANT: - break; - } + ) + + IF_RAD1O ( + (void) mixer; + (void) gpo; + ) } diff --git a/firmware/common/operacake_sctimer.c b/firmware/common/operacake_sctimer.c index 21ce3d7e..82bb6400 100644 --- a/firmware/common/operacake_sctimer.c +++ b/firmware/common/operacake_sctimer.c @@ -98,8 +98,7 @@ void operacake_sctimer_init(void) SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); uint8_t sct_clock_input; - if (detected_platform() != BOARD_ID_PRALINE) { -#if !defined(PRALINE) || defined(UNIVERSAL) + IF_NOT_PRALINE ( // Configure the SGPIO to output the clock (f=2 * sample clock) on pin 12 SGPIO_OUT_MUX_CFG12 = SGPIO_OUT_MUX_CFG_P_OUT_CFG(0x08) | // clkout output mode @@ -110,9 +109,8 @@ void operacake_sctimer_init(void) GIMA_CTIN_1_IN = 0x2 << 4; // Route SGPIO12 to SCTIN1 sct_clock_input = SCT_CONFIG_CKSEL_RISING_EDGES_ON_INPUT_1; -#endif - } else { -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( // Configure pin P6_4 as SCT_IN_6 scu_pinmux(P6_4, SCU_CLK_IN | SCU_CONF_FUNCTION1); @@ -120,8 +118,7 @@ void operacake_sctimer_init(void) GIMA_CTIN_6_IN = 0x0 << 4; sct_clock_input = SCT_CONFIG_CKSEL_RISING_EDGES_ON_INPUT_6; -#endif - } + ) // We configure this register first, because the user manual says to SCT_CONFIG |= SCT_CONFIG_UNIFY_32_BIT | SCT_CONFIG_CLKMODE_PRESCALED_BUS_CLOCK | diff --git a/firmware/common/platform_detect.h b/firmware/common/platform_detect.h index 4f0f0f43..f8bc53b9 100644 --- a/firmware/common/platform_detect.h +++ b/firmware/common/platform_detect.h @@ -31,6 +31,117 @@ #define PLATFORM_HACKRF1_R9 (1 << 3) #define PLATFORM_PRALINE (1 << 4) +/* clang-format off */ + +/* Helper macros for platform-specific code. */ +#if defined(UNIVERSAL) + #define IF_PRALINE(...) \ + if (detected_platform() == BOARD_ID_PRALINE) { __VA_ARGS__; } + #define IF_NOT_PRALINE(...) \ + if (detected_platform() != BOARD_ID_PRALINE) { __VA_ARGS__; } + #define IF_HACKRF_ONE(...) \ + switch (detected_platform()) { \ + case BOARD_ID_HACKRF1_OG: \ + case BOARD_ID_HACKRF1_R9: \ + { __VA_ARGS__; } \ + break; \ + default: \ + break; \ + } + #define IF_NOT_HACKRF_ONE(...) \ + switch (detected_platform()) { \ + case BOARD_ID_HACKRF1_OG: \ + case BOARD_ID_HACKRF1_R9: \ + break; \ + default: \ + { __VA_ARGS__; } \ + break; \ + } + #define IF_H1_R9(...) \ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { __VA_ARGS__; } + #define IF_NOT_H1_R9(...) \ + if (detected_platform() != BOARD_ID_HACKRF1_R9) { __VA_ARGS__; } + #define IF_RAD1O(...) + #define IF_NOT_RAD1O(...) { __VA_ARGS__; } + #define IF_JAWBREAKER(...) + #define IF_NOT_JAWBREAKER(...) { __VA_ARGS__; } + #define IF_H1_OR_PRALINE(...) { __VA_ARGS__; } + #define IF_H1_OR_RAD1O(...) IF_HACKRF_ONE(__VA_ARGS__) + #define IF_H1_OR_JAWBREAKER(...) IF_HACKRF_ONE(__VA_ARGS__) + #define IF_FOUR_LEDS(...) IF_PRALINE(__VA_ARGS__) + #define IF_EXPANSION_COMPATIBLE(...) { __VA_ARGS__; } +#elif defined(HACKRF_ONE) + #define IF_PRALINE(...) + #define IF_NOT_PRALINE(...) { __VA_ARGS__; } + #define IF_HACKRF_ONE(...) { __VA_ARGS__; } + #define IF_NOT_HACKRF_ONE(...) + #define IF_H1_R9(...) \ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { __VA_ARGS__; } + #define IF_NOT_H1_R9(...) \ + if (detected_platform() != BOARD_ID_HACKRF1_R9) { __VA_ARGS__; } + #define IF_RAD1O(...) + #define IF_NOT_RAD1O(...) { __VA_ARGS__; } + #define IF_JAWBREAKER(...) + #define IF_NOT_JAWBREAKER(...) { __VA_ARGS__; } + #define IF_H1_OR_PRALINE(...) { __VA_ARGS__; } + #define IF_H1_OR_RAD1O(...) { __VA_ARGS__; } + #define IF_H1_OR_JAWBREAKER(...) { __VA_ARGS__; } + #define IF_FOUR_LEDS(...) + #define IF_EXPANSION_COMPATIBLE(...) { __VA_ARGS__; } +#elif defined(PRALINE) + #define IF_PRALINE(...) { __VA_ARGS__; } + #define IF_NOT_PRALINE(...) + #define IF_HACKRF_ONE(...) + #define IF_NOT_HACKRF_ONE(...) { __VA_ARGS__; } + #define IF_H1_R9(...) + #define IF_NOT_H1_R9(...) { __VA_ARGS__; } + #define IF_RAD1O(...) + #define IF_NOT_RAD1O(...) { __VA_ARGS__; } + #define IF_JAWBREAKER(...) + #define IF_NOT_JAWBREAKER(...) { __VA_ARGS__; } + #define IF_H1_OR_PRALINE(...) { __VA_ARGS__; } + #define IF_H1_OR_RAD1O(...) + #define IF_H1_OR_JAWBREAKER(...) + #define IF_FOUR_LEDS(...) + #define IF_EXPANSION_COMPATIBLE(...) { __VA_ARGS__; } +#elif defined(RAD1O) + #define IF_PRALINE(...) + #define IF_NOT_PRALINE(...) { __VA_ARGS__; } + #define IF_HACKRF_ONE(...) + #define IF_NOT_HACKRF_ONE(...) { __VA_ARGS__; } + #define IF_H1_R9(...) + #define IF_NOT_H1_R9(...) { __VA_ARGS__; } + #define IF_RAD1O(...) { __VA_ARGS__; } + #define IF_NOT_RAD1O(...) + #define IF_JAWBREAKER(...) + #define IF_NOT_JAWBREAKER(...) { __VA_ARGS__; } + #define IF_H1_OR_PRALINE(...) + #define IF_H1_OR_RAD1O(...) { __VA_ARGS__; } + #define IF_H1_OR_JAWBREAKER(...) + #define IF_FOUR_LEDS(...) { __VA_ARGS__; } + #define IF_EXPANSION_COMPATIBLE(...) +#elif defined(JAWBREAKER) + #define IF_PRALINE(...) + #define IF_NOT_PRALINE(...) { __VA_ARGS__; } + #define IF_HACKRF_ONE(...) + #define IF_NOT_HACKRF_ONE(...) { __VA_ARGS__; } + #define IF_H1_R9(...) + #define IF_NOT_H1_R9(...) { __VA_ARGS__; } + #define IF_RAD1O(...) + #define IF_NOT_RAD1O(...) { __VA_ARGS__; } + #define IF_JAWBREAKER(...) { __VA_ARGS__; } + #define IF_NOT_JAWBREAKER(...) + #define IF_H1_OR_PRALINE(...) + #define IF_H1_OR_RAD1O(...) + #define IF_H1_OR_JAWBREAKER(...) { __VA_ARGS__; } + #define IF_FOUR_LEDS(...) + #define IF_EXPANSION_COMPATIBLE(...) +#else + #error "No recognised platform defined" +#endif + +/* clang-format on */ + typedef enum { BOARD_ID_JELLYBEAN = 0, BOARD_ID_JAWBREAKER = 1, diff --git a/firmware/common/platform_gpio.c b/firmware/common/platform_gpio.c index f9a44903..7f773b20 100644 --- a/firmware/common/platform_gpio.c +++ b/firmware/common/platform_gpio.c @@ -34,93 +34,61 @@ const platform_gpio_t* platform_gpio(void) return _platform_gpio; } - board_id_t board_id = detected_platform(); static platform_gpio_t gpio; /* LEDs */ gpio.led[0] = &GPIO2_1; gpio.led[1] = &GPIO2_2; gpio.led[2] = &GPIO2_8; - switch (board_id) { - case BOARD_ID_RAD1O: -#if defined(RAD1O) + IF_RAD1O ( gpio.led[3] = &GPIO5_26; -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( gpio.led[3] = &GPIO4_6; -#endif - break; - default: - break; - } + ) /* Power Supply Control */ - switch (board_id) { - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( gpio.gpio_1v2_enable = &GPIO4_7; gpio.gpio_3v3aux_enable_n = &GPIO5_15; -#endif - break; - default: + ) + IF_NOT_PRALINE ( gpio.gpio_1v8_enable = &GPIO3_6; - break; - } + ) /* MAX283x GPIO (XCVR_CTL / CS_XCVR) PinMux */ - switch (board_id) { - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( gpio.max283x_select = &GPIO6_28; gpio.max283x_enable = &GPIO7_1; gpio.max283x_rx_enable = &GPIO7_2; gpio.max2831_rxhp = &GPIO6_29; gpio.max2831_ld = &GPIO4_11; -#endif - break; - default: + ) + IF_NOT_PRALINE ( gpio.max283x_select = &GPIO0_15; gpio.max283x_enable = &GPIO2_6; gpio.max283x_rx_enable = &GPIO2_5; gpio.max283x_tx_enable = &GPIO2_4; - break; - } + ) /* MAX5864 SPI chip select (AD_CS / CS_AD) GPIO PinMux */ - switch (board_id) { - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( gpio.max5864_select = &GPIO6_30; -#endif - break; - default: + ) + IF_NOT_PRALINE ( gpio.max5864_select = &GPIO2_7; - break; - } + ) /* RF supply (VAA) control */ - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_HACKRF_ONE ( gpio.vaa_disable = &GPIO2_9; -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( gpio.vaa_disable = &GPIO4_1; -#endif - break; - case BOARD_ID_RAD1O: -#if defined(RAD1O) + ) + IF_RAD1O ( gpio.vaa_enable = &GPIO2_9; -#endif - break; - default: - break; - } + ) /* W25Q80BV Flash */ gpio.w25q80bv_hold = &GPIO1_14; @@ -128,10 +96,7 @@ const platform_gpio_t* platform_gpio(void) gpio.w25q80bv_select = &GPIO5_11; /* RF switch control */ - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_HACKRF_ONE ( gpio.hp = &GPIO2_0; gpio.lp = &GPIO2_10; gpio.tx_mix_bp = &GPIO2_11; @@ -145,13 +110,12 @@ const platform_gpio_t* platform_gpio(void) gpio.amp_bypass = &GPIO0_14; gpio.rx_amp = &GPIO1_11; gpio.no_rx_amp_pwr = &GPIO1_12; - // HackRF One rev 9 - gpio.h1r9_rx = &GPIO0_7; - gpio.h1r9_no_ant_pwr = &GPIO2_4; -#endif - break; - case BOARD_ID_RAD1O: -#if defined(RAD1O) + IF_H1_R9 ( + gpio.h1r9_rx = &GPIO0_7; + gpio.h1r9_no_ant_pwr = &GPIO2_4; + ) + ) + IF_RAD1O ( gpio.tx_rx_n = &GPIO1_11; gpio.tx_rx = &GPIO0_14; gpio.by_mix = &GPIO1_12; @@ -163,118 +127,70 @@ const platform_gpio_t* platform_gpio(void) gpio.low_high_filt_n = &GPIO2_12; gpio.tx_amp = &GPIO2_15; gpio.rx_lna = &GPIO5_15; -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( gpio.tx_en = &GPIO3_4; gpio.mix_en_n = &GPIO3_2; gpio.mix_en_n_r1_0 = &GPIO5_6; gpio.lpf_en = &GPIO4_8; gpio.rf_amp_en = &GPIO4_9; gpio.ant_bias_en_n = &GPIO1_12; -#endif - break; - case BOARD_ID_JELLYBEAN: - case BOARD_ID_JAWBREAKER: - break; - default: - break; - } + ) /* CPLD JTAG interface GPIO pins_FPGA config pins in Praline */ gpio.cpld_tck = &GPIO3_0; - switch (board_id) { - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( gpio.fpga_cfg_creset = &GPIO2_11; gpio.fpga_cfg_cdone = &GPIO5_14; gpio.fpga_cfg_spi_cs = &GPIO2_10; -#endif - break; - default: -#if !defined(PRALINE) || defined(UNIVERSAL) + ) + IF_NOT_PRALINE ( gpio.cpld_tdo = &GPIO5_18; - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: - case BOARD_ID_RAD1O: + IF_H1_OR_RAD1O ( gpio.cpld_tms = &GPIO3_4; gpio.cpld_tdi = &GPIO3_1; - break; - case BOARD_ID_JAWBREAKER: + ) + IF_JAWBREAKER ( gpio.cpld_tms = &GPIO3_1; gpio.cpld_tdi = &GPIO3_4; - break; - default: - break; - } -#endif - break; - } - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: - case BOARD_ID_PRALINE: -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + ) + ) + IF_EXPANSION_COMPATIBLE ( gpio.cpld_pp_tms = &GPIO1_1; gpio.cpld_pp_tdo = &GPIO1_8; -#endif - break; - default: - break; - } + ) /* Other CPLD interface GPIO pins */ - switch (board_id) { - case BOARD_ID_PRALINE: - break; - default: -#if !defined(PRALINE) || defined(UNIVERSAL) + IF_NOT_PRALINE ( gpio.trigger_enable = &GPIO5_12; -#endif - break; - } + ) gpio.q_invert = &GPIO0_13; /* RFFC5071 GPIO serial interface PinMux */ - switch (board_id) { - case BOARD_ID_JAWBREAKER: - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: -#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_NOT_RAD1O ( gpio.rffc5072_select = &GPIO2_13; gpio.rffc5072_clock = &GPIO5_6; gpio.rffc5072_data = &GPIO3_3; gpio.rffc5072_reset = &GPIO2_14; -#endif - break; - case BOARD_ID_RAD1O: -#if defined(RAD1O) + ) + IF_RAD1O ( gpio.vco_ce = &GPIO2_13; gpio.vco_sclk = &GPIO5_6; gpio.vco_sdata = &GPIO3_3; gpio.vco_le = &GPIO2_14; gpio.vco_mux = &GPIO5_25; gpio.synt_rfout_en = &GPIO3_5; -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( gpio.rffc5072_select = &GPIO2_13; gpio.rffc5072_clock = &GPIO5_18; gpio.rffc5072_data = &GPIO4_14; gpio.rffc5072_reset = &GPIO2_14; gpio.rffc5072_ld = &GPIO6_25; -#endif - break; - default: - break; - } + ) -#if defined(PRALINE) || defined(UNIVERSAL) - switch (board_id) { - case BOARD_ID_PRALINE: + /* Praline */ + IF_PRALINE ( gpio.p2_ctrl0 = &GPIO7_3; gpio.p2_ctrl1 = &GPIO7_4; gpio.p1_ctrl0 = &GPIO0_14; @@ -285,50 +201,33 @@ const platform_gpio_t* platform_gpio(void) gpio.trigger_in = &GPIO6_26; gpio.trigger_out = &GPIO5_6; gpio.pps_out = &GPIO5_5; - break; - default: - break; - } -#endif + ) -#if defined(HACKRF_ONE) || defined(UNIVERSAL) /* HackRF One r9 clock control */ - switch (board_id) { - case BOARD_ID_HACKRF1_R9: + IF_H1_R9 ( gpio.h1r9_clkin_en = &GPIO5_15; gpio.h1r9_clkout_en = &GPIO0_9; gpio.h1r9_mcu_clk_en = &GPIO0_8; - break; - default: - break; - } - - switch (board_id) { - case BOARD_ID_HACKRF1_R9: gpio.h1r9_1v8_enable = &GPIO2_9; gpio.h1r9_vaa_disable = &GPIO3_6; gpio.h1r9_trigger_enable = &GPIO5_5; - break; - default: - break; - } -#endif + ) /* rad1o LCD */ -#if defined(RAD1O) - gpio.lcd_cs = &GPIO4_12; /* P9_0 */ - gpio.lcd_bl_en = &GPIO0_8; /* P1_1 */ - gpio.lcd_reset = &GPIO5_17; /* P9_4 */ -#endif + IF_RAD1O ( + gpio.lcd_cs = &GPIO4_12; /* P9_0 */ + gpio.lcd_bl_en = &GPIO0_8; /* P1_1 */ + gpio.lcd_reset = &GPIO5_17; /* P9_4 */ + ) /* Portapack */ -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) - gpio.io_stbx = &GPIO5_0; /* P2_0 */ - gpio.addr = &GPIO5_1; /* P2_1 */ - gpio.lcd_rdx = &GPIO5_4; /* P2_4 */ - gpio.lcd_wrx = &GPIO1_10; /* P2_9 */ - gpio.dir = &GPIO1_13; /* P2_13 */ -#endif + IF_EXPANSION_COMPATIBLE ( + gpio.io_stbx = &GPIO5_0; /* P2_0 */ + gpio.addr = &GPIO5_1; /* P2_1 */ + gpio.lcd_rdx = &GPIO5_4; /* P2_4 */ + gpio.lcd_wrx = &GPIO1_10; /* P2_9 */ + gpio.dir = &GPIO1_13; /* P2_13 */ + ) _platform_gpio = &gpio; diff --git a/firmware/common/platform_scu.c b/firmware/common/platform_scu.c index edd6ee0e..9d3b0c5d 100644 --- a/firmware/common/platform_scu.c +++ b/firmware/common/platform_scu.c @@ -36,68 +36,40 @@ const platform_scu_t* platform_scu(void) return _platform_scu; } - board_id_t board_id = detected_platform(); static platform_scu_t scu; /* LED PinMux */ scu.PINMUX_LED1 = SCU_PINMUX_LED1; /* GPIO2[1] on P4_1 */ scu.PINMUX_LED2 = SCU_PINMUX_LED2; /* GPIO2[2] on P4_2 */ scu.PINMUX_LED3 = SCU_PINMUX_LED3; /* GPIO2[8] on P6_12 */ - switch (board_id) { - case BOARD_ID_RAD1O: -#if defined(RAD1O) + IF_RAD1O ( scu.PINMUX_LED4 = (PB_6); /* GPIO5[26] on PB_6 */ -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( scu.PINMUX_LED4 = (P8_6); /* GPIO4[6] on P8_6 */ -#endif - break; - default: - break; - } + ) /* Power Supply PinMux */ scu.PINMUX_EN1V8 = (P6_10); /* GPIO3[6] on P6_10 */ scu.PINMUX_EN1V2 = (P8_7); /* GPIO4[7] on P8_7 */ - switch (board_id) { - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( scu.PINMUX_EN3V3_AUX_N = (P6_7); /* GPIO5[15] on P6_7 */ scu.PINMUX_EN3V3_OC_N = (P6_11); /* GPIO3[7] on P6_11 */ -#endif - break; - default: - break; - } + ) /* GPIO Input PinMux */ scu.PINMUX_BOOT0 = (P1_1); /* GPIO0[8] on P1_1 */ scu.PINMUX_BOOT1 = (P1_2); /* GPIO0[9] on P1_2 */ - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: - break; - default: -#if !defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_NOT_HACKRF_ONE ( scu.PINMUX_BOOT2 = (P2_8); /* GPIO5[7] on P2_8 */ scu.PINMUX_BOOT3 = (P2_9); /* GPIO1[10] on P2_9 */ -#endif - break; - } + ) /* USB peripheral */ - switch (board_id) { - case BOARD_ID_JAWBREAKER: -#if defined(JAWBREAKER) + IF_JAWBREAKER ( scu.PINMUX_USB_LED0 = (P6_8); scu.PINMUX_USB_LED1 = (P6_7); -#endif - break; - default: - break; - } + ) /* SSP1 Peripheral PinMux */ scu.SSP1_CIPO = (P1_3); /* P1_3 */ @@ -107,37 +79,25 @@ const platform_scu_t* platform_scu(void) /* CPLD JTAG interface */ scu.PINMUX_CPLD_TCK = (P6_1); /* GPIO3[ 0] */ - switch (board_id) { - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( scu.PINMUX_FPGA_CRESET = (P5_2); /* GPIO2[11] on P5_2 */ scu.PINMUX_FPGA_CDONE = (P4_10); /* GPIO5[14] */ scu.PINMUX_FPGA_SPI_CS = (P5_1); /* GPIO2[10] */ -#endif - break; - default: - break; - } -#if !defined(PRALINE) || defined(UNIVERSAL) - scu.PINMUX_CPLD_TDO = (P9_5); /* GPIO5[18] */ - switch (board_id) { - case BOARD_ID_RAD1O: - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: + ) + IF_NOT_PRALINE ( + scu.PINMUX_CPLD_TDO = (P9_5); /* GPIO5[18] */ + ) + IF_H1_OR_RAD1O ( scu.PINMUX_CPLD_TMS = (P6_5); /* GPIO3[ 4] */ scu.PINMUX_CPLD_TDI = (P6_2); /* GPIO3[ 1] */ - break; - default: + ) + IF_JAWBREAKER ( scu.PINMUX_CPLD_TMS = (P6_2); /* GPIO3[ 1] */ scu.PINMUX_CPLD_TDI = (P6_5); /* GPIO3[ 4] */ - break; - } -#endif + ) /* CPLD SGPIO interface */ - switch (board_id) { - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( scu.PINMUX_SGPIO0 = (P0_0); scu.PINMUX_SGPIO1 = (P0_1); scu.PINMUX_SGPIO2 = (P1_15); @@ -169,10 +129,8 @@ const platform_scu_t* platform_scu(void) scu.PINMUX_SGPIO12_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu.PINMUX_SGPIO14_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu.PINMUX_SGPIO15_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); -#endif - break; - default: -#if !defined(PRALINE) || defined(UNIVERSAL) + ) + IF_NOT_PRALINE ( scu.PINMUX_SGPIO0 = (P0_0); scu.PINMUX_SGPIO1 = (P0_1); scu.PINMUX_SGPIO2 = (P1_15); @@ -204,22 +162,16 @@ const platform_scu_t* platform_scu(void) scu.PINMUX_SGPIO12_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu.PINMUX_SGPIO14_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.PINMUX_SGPIO15_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); -#endif - break; - } + ) scu.TRIGGER_EN = (P4_8); /* GPIO5[12] on P4_8 */ /* MAX283x GPIO (XCVR_CTL) PinMux */ - switch (board_id) { - case BOARD_ID_RAD1O: -#if defined(RAD1O) + IF_RAD1O ( scu.XCVR_RXHP = P8_1; /* GPIO[] on P8_1 */ scu.XCVR_B6 = P8_2; /* GPIO[] on P8_2 */ scu.XCVR_B7 = P9_3; /* GPIO[] on P9_3 */ -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( scu.XCVR_ENABLE = PE_1; /* GPIO7[1] on PE_1 */ scu.XCVR_RXENABLE = PE_2; /* GPIO7[2] on PE_2 */ scu.XCVR_CS = PD_14; /* GPIO6[28] on PD_14 */ @@ -232,12 +184,8 @@ const platform_scu_t* platform_scu(void) scu.XCVR_RXHP_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.XCVR_LD_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0 | SCU_CONF_EPD_EN_PULLDOWN | SCU_CONF_EPUN_DIS_PULLUP); -#endif - break; - case BOARD_ID_JAWBREAKER: - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: -#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(UNIVERSAL) + ) + IF_H1_OR_JAWBREAKER ( scu.XCVR_ENABLE = P4_6; /* GPIO2[6] on P4_6 */ scu.XCVR_RXENABLE = P4_5; /* GPIO2[5] on P4_5 */ scu.XCVR_TXENABLE = P4_4; /* GPIO2[4] on P4_4 */ @@ -247,32 +195,20 @@ const platform_scu_t* platform_scu(void) scu.XCVR_RXENABLE_PINCFG = (SCU_GPIO_FAST); scu.XCVR_TXENABLE_PINCFG = (SCU_GPIO_FAST); scu.XCVR_CS_PINCFG = (SCU_GPIO_FAST); -#endif - break; - default: - break; - } + ) /* MAX5864 SPI chip select (AD_CS) GPIO PinMux */ - switch (board_id) { - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( scu.AD_CS = (PD_16); /* GPIO6[30] on PD_16 */ scu.AD_CS_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); -#endif - break; - default: + ) + IF_NOT_PRALINE ( scu.AD_CS = (P5_7); /* GPIO2[7] on P5_7 */ scu.AD_CS_PINCFG = (SCU_GPIO_FAST); - break; - } + ) /* RFFC5071 GPIO serial interface PinMux */ - switch (board_id) { - case BOARD_ID_JAWBREAKER: - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: -#if defined(JAWBREAKER) || defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_H1_OR_JAWBREAKER ( scu.MIXER_ENX = (P5_4); /* GPIO2[13] on P5_4 */ scu.MIXER_SCLK = (P2_6); /* GPIO5[6] on P2_6 */ scu.MIXER_SDATA = (P6_4); /* GPIO3[3] on P6_4 */ @@ -280,10 +216,8 @@ const platform_scu_t* platform_scu(void) scu.MIXER_SCLK_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.MIXER_SDATA_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( scu.MIXER_ENX = (P5_4); /* GPIO2[13] on P5_4 */ scu.MIXER_SCLK = (P9_5); /* GPIO5[18] on P9_5 */ scu.MIXER_SDATA = (P9_2); /* GPIO4[14] on P9_2 */ @@ -293,10 +227,8 @@ const platform_scu_t* platform_scu(void) scu.MIXER_SCLK_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.MIXER_SDATA_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu.MIXER_LD_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); -#endif - break; - case BOARD_ID_RAD1O: -#if defined(RAD1O) + ) + IF_RAD1O ( scu.VCO_CE = (P5_4); /* GPIO2[13] on P5_4 */ scu.VCO_SCLK = (P2_6); /* GPIO5[6] on P2_6 */ scu.VCO_SDATA = (P6_4); /* GPIO3[3] on P6_4 */ @@ -304,44 +236,23 @@ const platform_scu_t* platform_scu(void) scu.VCO_MUX = (PB_5); /* GPIO5[25] on PB_5 */ scu.MIXER_EN = (P6_8); /* GPIO5[16] on P6_8 */ scu.SYNT_RFOUT_EN = (P6_9); /* GPIO3[5] on P6_9 */ -#endif - break; - default: - break; - } + ) /* RF LDO control */ - switch (board_id) { - case BOARD_ID_JAWBREAKER: -#if defined(JAWBREAKER) + IF_JAWBREAKER ( scu.RF_LDO_ENABLE = (P5_0); /* GPIO2[9] on P5_0 */ -#endif - break; - default: - break; - } + ) /* RF supply (VAA) control */ - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_HACKRF_ONE ( scu.NO_VAA_ENABLE = P5_0; /* GPIO2[9] on P5_0 */ -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( scu.NO_VAA_ENABLE = P8_1; /* GPIO4[1] on P8_1 */ -#endif - break; - case BOARD_ID_RAD1O: -#if defined(RAD1O) + ) + IF_RAD1O ( scu.VAA_ENABLE = P5_0; /* GPIO2[9] on P5_0 */ -#endif - break; - default: - break; - } + ) /* SPI flash */ scu.SSP0_CIPO = (P3_6); @@ -352,10 +263,7 @@ const platform_scu_t* platform_scu(void) scu.FLASH_WP = (P3_5); /* GPIO1[15] on P3_5 */ /* RF switch control */ - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_HACKRF_ONE ( scu.HP = P4_0; /* GPIO2[0] on P4_0 */ scu.LP = P5_1; /* GPIO2[10] on P5_1 */ scu.TX_MIX_BP = P5_2; /* GPIO2[11] on P5_2 */ @@ -369,10 +277,8 @@ const platform_scu_t* platform_scu(void) scu.AMP_BYPASS = P2_10; /* GPIO0[14] on P2_10 */ scu.RX_AMP = P2_11; /* GPIO1[11] on P2_11 */ scu.NO_RX_AMP_PWR = P2_12; /* GPIO1[12] on P2_12 */ -#endif - break; - case BOARD_ID_RAD1O: -#if defined(RAD1O) + ) + IF_RAD1O ( scu.BY_AMP = P1_7; /* GPIO1[0] on P1_7 */ scu.BY_AMP_N = P2_5; /* GPIO5[5] on P2_5 */ scu.TX_RX = P2_10; /* GPIO0[14] on P2_10 */ @@ -383,10 +289,8 @@ const platform_scu_t* platform_scu(void) scu.LOW_HIGH_FILT_N = P5_3; /* GPIO2[12] on P5_3 */ scu.TX_AMP = P5_6; /* GPIO2[15] on P5_6 */ scu.RX_LNA = P6_7; /* GPIO5[15] on P6_7 */ -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( scu.TX_EN = P6_5; /* GPIO3[4] on P6_5 */ scu.MIX_EN_N = P6_3; /* GPIO3[2] on P6_3 */ scu.MIX_EN_N_R1_0 = P2_6; /* GPIO5[6] on P2_6 */ @@ -394,16 +298,10 @@ const platform_scu_t* platform_scu(void) scu.RF_AMP_EN = PA_2; /* GPIO4[9] on PA_2 */ scu.ANT_BIAS_EN_N = P2_12; /* GPIO1[12] on P2_12 */ scu.ANT_BIAS_OC_N = P2_11; /* GPIO1[11] on P2_11 */ -#endif - break; - default: - break; - } + ) /* Praline */ -#if defined(PRALINE) || defined(UNIVERSAL) - switch (board_id) { - case BOARD_ID_PRALINE: + IF_PRALINE ( scu.P2_CTRL0 = (PE_3); /* GPIO7[3] on PE_3 */ scu.P2_CTRL1 = (PE_4); /* GPIO7[4] on PE_4 */ scu.P1_CTRL0 = (P2_10); /* GPIO0[14] on P2_10 */ @@ -425,16 +323,10 @@ const platform_scu_t* platform_scu(void) scu.TRIGGER_IN_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.TRIGGER_OUT_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.PPS_OUT_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - break; - default: - break; - } -#endif + ) /* HackRF One r9 */ -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - switch (board_id) { - case BOARD_ID_HACKRF1_R9: + IF_H1_R9 ( scu.H1R9_CLKIN_EN = P6_7; /* GPIO5[15] on P6_7 */ scu.H1R9_CLKOUT_EN = P1_2; /* GPIO0[9] on P1_2 = has boot pull-down; */ scu.H1R9_MCU_CLK_EN = P1_1; /* GPIO0[8] on P1_1 = has boot pull-up; */ @@ -443,54 +335,50 @@ const platform_scu_t* platform_scu(void) scu.H1R9_EN1V8 = P5_0; /* GPIO2[9] on P5_0 */ scu.H1R9_NO_VAA_EN = P6_10; /* GPIO3[6] on P6_10 */ scu.H1R9_TRIGGER_EN = P2_5; /* GPIO5[5] on P2_5 */ - break; - default: - break; - } -#endif + ) /* Expansion headers */ -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) - scu.PINMUX_PP_D0 = (P7_0); /* GPIO3[8] */ - scu.PINMUX_PP_D1 = (P7_1); /* GPIO3[9] */ - scu.PINMUX_PP_D2 = (P7_2); /* GPIO3[10] */ - scu.PINMUX_PP_D3 = (P7_3); /* GPIO3[11] */ - scu.PINMUX_PP_D4 = (P7_4); /* GPIO3[12] */ - scu.PINMUX_PP_D5 = (P7_5); /* GPIO3[13] */ - scu.PINMUX_PP_D6 = (P7_6); /* GPIO3[14] */ - scu.PINMUX_PP_D7 = (P7_7); /* GPIO3[15] */ + IF_EXPANSION_COMPATIBLE ( + scu.PINMUX_PP_D0 = (P7_0); /* GPIO3[8] */ + scu.PINMUX_PP_D1 = (P7_1); /* GPIO3[9] */ + scu.PINMUX_PP_D2 = (P7_2); /* GPIO3[10] */ + scu.PINMUX_PP_D3 = (P7_3); /* GPIO3[11] */ + scu.PINMUX_PP_D4 = (P7_4); /* GPIO3[12] */ + scu.PINMUX_PP_D5 = (P7_5); /* GPIO3[13] */ + scu.PINMUX_PP_D6 = (P7_6); /* GPIO3[14] */ + scu.PINMUX_PP_D7 = (P7_7); /* GPIO3[15] */ - scu.PINMUX_PP_LCD_TE = (P2_3); /* GPIO5[3] on P2_3 */ - scu.PINMUX_PP_LCD_RDX = (P2_4); /* GPIO5[4] on P2_4 */ - scu.PINMUX_PP_UNUSED = (P2_8); /* GPIO5[7] on P2_8 */ - scu.PINMUX_PP_LCD_WRX = (P2_9); /* GPIO1[10] on P2_9 */ - scu.PINMUX_PP_DIR = (P2_13); /* GPIO1[13] on P2_13 */ + scu.PINMUX_PP_LCD_TE = (P2_3); /* GPIO5[3] on P2_3 */ + scu.PINMUX_PP_LCD_RDX = (P2_4); /* GPIO5[4] on P2_4 */ + scu.PINMUX_PP_UNUSED = (P2_8); /* GPIO5[7] on P2_8 */ + scu.PINMUX_PP_LCD_WRX = (P2_9); /* GPIO1[10] on P2_9 */ + scu.PINMUX_PP_DIR = (P2_13); /* GPIO1[13] on P2_13 */ - scu.PINMUX_PP_TDO = (P1_5); /* GPIO1[8] */ - scu.PINMUX_SD_POW = (P1_5); /* GPIO1[8] */ - scu.PINMUX_SD_CMD = (P1_6); /* GPIO1[9] */ - scu.PINMUX_PP_TMS = (P1_8); /* GPIO1[1] */ - scu.PINMUX_SD_VOLT0 = (P1_8); /* GPIO1[1] */ - scu.PINMUX_SD_DAT0 = (P1_9); /* GPIO1[2] */ - scu.PINMUX_SD_DAT1 = (P1_10); /* GPIO1[3] */ - scu.PINMUX_SD_DAT2 = (P1_11); /* GPIO1[4] */ - scu.PINMUX_SD_DAT3 = (P1_12); /* GPIO1[5] */ - scu.PINMUX_SD_CD = (P1_13); /* GPIO1[6] */ + scu.PINMUX_PP_TDO = (P1_5); /* GPIO1[8] */ + scu.PINMUX_SD_POW = (P1_5); /* GPIO1[8] */ + scu.PINMUX_SD_CMD = (P1_6); /* GPIO1[9] */ + scu.PINMUX_PP_TMS = (P1_8); /* GPIO1[1] */ + scu.PINMUX_SD_VOLT0 = (P1_8); /* GPIO1[1] */ + scu.PINMUX_SD_DAT0 = (P1_9); /* GPIO1[2] */ + scu.PINMUX_SD_DAT1 = (P1_10); /* GPIO1[3] */ + scu.PINMUX_SD_DAT2 = (P1_11); /* GPIO1[4] */ + scu.PINMUX_SD_DAT3 = (P1_12); /* GPIO1[5] */ + scu.PINMUX_SD_CD = (P1_13); /* GPIO1[6] */ - scu.PINMUX_PP_IO_STBX = (P2_0); /* GPIO5[0] */ - scu.PINMUX_PP_ADDR = (P2_1); /* GPIO5[1] */ - scu.PINMUX_U0_TXD = (P2_0); /* GPIO5[0] */ - scu.PINMUX_U0_RXD = (P2_1); /* GPIO5[1] */ + scu.PINMUX_PP_IO_STBX = (P2_0); /* GPIO5[0] */ + scu.PINMUX_PP_ADDR = (P2_1); /* GPIO5[1] */ + scu.PINMUX_U0_TXD = (P2_0); /* GPIO5[0] */ + scu.PINMUX_U0_RXD = (P2_1); /* GPIO5[1] */ - scu.PINMUX_GPIO3_8 = (P7_0); /* GPIO3[8] */ - scu.PINMUX_GPIO3_9 = (P7_1); /* GPIO3[9] */ - scu.PINMUX_GPIO3_10 = (P7_2); /* GPIO3[10] */ - scu.PINMUX_GPIO3_11 = (P7_3); /* GPIO3[11] */ - scu.PINMUX_GPIO3_12 = (P7_4); /* GPIO3[12] */ - scu.PINMUX_GPIO3_13 = (P7_5); /* GPIO3[13] */ - scu.PINMUX_GPIO3_14 = (P7_6); /* GPIO3[14] */ - scu.PINMUX_GPIO3_15 = (P7_7); /* GPIO3[15] */ -#endif + scu.PINMUX_GPIO3_8 = (P7_0); /* GPIO3[8] */ + scu.PINMUX_GPIO3_9 = (P7_1); /* GPIO3[9] */ + scu.PINMUX_GPIO3_10 = (P7_2); /* GPIO3[10] */ + scu.PINMUX_GPIO3_11 = (P7_3); /* GPIO3[11] */ + scu.PINMUX_GPIO3_12 = (P7_4); /* GPIO3[12] */ + scu.PINMUX_GPIO3_13 = (P7_5); /* GPIO3[13] */ + scu.PINMUX_GPIO3_14 = (P7_6); /* GPIO3[14] */ + scu.PINMUX_GPIO3_15 = (P7_7); /* GPIO3[15] */ + ) scu.PINMUX_ISP = (P2_7); /* GPIO0[7] */ diff --git a/firmware/common/radio.c b/firmware/common/radio.c index ff97a814..a4d41c68 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -195,22 +195,18 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank) case TRANSCEIVER_MODE_SS: n = compute_resample_log(rate / SR_FP_ONE_HZ, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX]) { - if (detected_platform() == BOARD_ID_PRALINE) { -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( fpga_set_tx_interpolation_ratio(&fpga, n); -#endif - } + ) radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX] = n; } break; default: n = compute_resample_log(rate / SR_FP_ONE_HZ, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX]) { - if (detected_platform() == BOARD_ID_PRALINE) { -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( fpga_set_rx_decimation_ratio(&fpga, n); -#endif - } + ) radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX] = n; } } @@ -354,7 +350,9 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) const uint64_t requested_if = bank[RADIO_FREQUENCY_IF]; const uint64_t requested_lo = bank[RADIO_FREQUENCY_LO]; const uint64_t requested_img_reject = bank[RADIO_IMAGE_REJECT]; +#if defined(PRALINE) || defined(UNIVERSAL) const uint64_t requested_rotation = bank[RADIO_ROTATION]; +#endif const uint64_t applied_rf = radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF]; const uint64_t applied_if = radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF]; @@ -393,7 +391,7 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) if (requested_lo != RADIO_UNSET) { freq_lo = mixer_set_frequency(&mixer, freq_lo, false); } - if (detected_platform() == BOARD_ID_PRALINE) { + IF_PRALINE ( if (requested_rotation != RADIO_UNSET) { rotation = requested_rotation; } @@ -409,9 +407,10 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) default: rotation = 0; } - } else { + ) + IF_NOT_PRALINE ( rotation = 0; - } + ) /* Handle requested RF (auto-tune). */ if (requested_rf != RADIO_UNSET) { @@ -421,8 +420,7 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) freq_rf = restrict_rf(requested_rf, img_reject); /* Look up settings appropriate for requested RF. */ - if (detected_platform() == BOARD_ID_PRALINE) { -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( const tune_config_t* tune_config = select_tune_config(opmode, freq_rf); if (requested_rotation == RADIO_UNSET) { @@ -438,15 +436,15 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) } } high_lo = tune_config->high_lo; -#endif - } else { + ) + IF_NOT_PRALINE ( /* Use graduated or fixed IF on older platforms. */ if (requested_if == RADIO_UNSET) { freq_if = select_graduated_if(freq_rf, img_reject); } high_lo = (img_reject == RF_PATH_FILTER_LOW_PASS); analog_rf = freq_rf; - } + ) /* Compute precise LO. This is done first because the mixer LO is set in coarse steps. */ if (requested_lo == RADIO_UNSET) { @@ -502,11 +500,9 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) changed |= (1 << RADIO_IMAGE_REJECT); } if ((rotation != applied_rotation) && (rotation != RADIO_UNSET)) { - if (detected_platform() == BOARD_ID_PRALINE) { -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( fpga_set_rx_quarter_shift_mode(&fpga, rotation >> 30); -#endif - } + ) radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION] = rotation; changed |= (1 << RADIO_ROTATION); } @@ -571,20 +567,29 @@ static uint32_t radio_update_bandwidth(radio_t* const radio, uint64_t* bank) opmode = radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]; } - if (detected_platform() == BOARD_ID_PRALINE) { -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( /* Praline legacy mode always sets baseband bandwidth automatically. */ (void) bank; uint32_t lpf_bandwidth = auto_bandwidth(radio, opmode); - if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != lpf_bandwidth) { - max283x_set_lpf_bandwidth(&max283x, MAX283x_MODE_TX, lpf_bandwidth); - radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = lpf_bandwidth; + if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != + lpf_bandwidth) { + max283x_set_lpf_bandwidth( + &max283x, + MAX283x_MODE_TX, + lpf_bandwidth); + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = + lpf_bandwidth; changed |= (1 << RADIO_XCVR_TX_LPF); } - if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] != lpf_bandwidth) { - max283x_set_lpf_bandwidth(&max283x, MAX283x_MODE_RX, lpf_bandwidth); - radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] = lpf_bandwidth; + if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] != + lpf_bandwidth) { + max283x_set_lpf_bandwidth( + &max283x, + MAX283x_MODE_RX, + lpf_bandwidth); + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] = + lpf_bandwidth; changed |= (1 << RADIO_XCVR_RX_LPF); } bool narrow_lpf_enable = false; @@ -601,14 +606,15 @@ static uint32_t radio_update_bandwidth(radio_t* const radio, uint64_t* bank) } /* Always set HPF bandwidth to 30 kHz for now. */ const max283x_rx_hpf_freq_t hpf_bandwidth = MAX283x_RX_HPF_30_KHZ; - if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] != hpf_bandwidth) { + if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] != + hpf_bandwidth) { max283x_set_rx_hpf_frequency(&max283x, hpf_bandwidth); - radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] = hpf_bandwidth; + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_HPF] = + hpf_bandwidth; changed |= (1 << RADIO_XCVR_RX_HPF); } -#endif - } else { -#if !defined(PRALINE) || defined(UNIVERSAL) + ) + IF_NOT_PRALINE ( uint64_t lpf_bandwidth; lpf_bandwidth = bank[RADIO_XCVR_TX_LPF]; if (lpf_bandwidth == RADIO_UNSET) { @@ -621,24 +627,33 @@ static uint32_t radio_update_bandwidth(radio_t* const radio, uint64_t* bank) lpf_bandwidth = bank[RADIO_BB_BANDWIDTH_RX]; } if (lpf_bandwidth == RADIO_UNSET) { - lpf_bandwidth = radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF]; + lpf_bandwidth = + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF]; } if (lpf_bandwidth == RADIO_UNSET) { lpf_bandwidth = auto_bandwidth(radio, opmode); } - if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != lpf_bandwidth) { - max283x_set_lpf_bandwidth(&max283x, MAX283x_MODE_TX, lpf_bandwidth); - radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_RX] = lpf_bandwidth; - radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_TX] = lpf_bandwidth; - radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = lpf_bandwidth; - radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] = lpf_bandwidth; + if (radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] != + lpf_bandwidth) { + max283x_set_lpf_bandwidth( + &max283x, + MAX283x_MODE_TX, + lpf_bandwidth); + radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_RX] = + lpf_bandwidth; + radio->config[RADIO_BANK_APPLIED][RADIO_BB_BANDWIDTH_TX] = + lpf_bandwidth; + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_TX_LPF] = + lpf_bandwidth; + radio->config[RADIO_BANK_APPLIED][RADIO_XCVR_RX_LPF] = + lpf_bandwidth; changed |= - ((1 << RADIO_BB_BANDWIDTH_RX) | (1 << RADIO_BB_BANDWIDTH_TX) | - (1 << RADIO_XCVR_TX_LPF) | (1 << RADIO_XCVR_RX_LPF)); + ((1 << RADIO_BB_BANDWIDTH_RX) | + (1 << RADIO_BB_BANDWIDTH_TX) | (1 << RADIO_XCVR_TX_LPF) | + (1 << RADIO_XCVR_RX_LPF)); } -#endif - } + ) return changed; } @@ -774,24 +789,23 @@ static uint32_t radio_update_trigger(radio_t* const radio, uint64_t* bank) static uint32_t radio_update_dc_block(radio_t* const radio, uint64_t* bank) { -#if defined(PRALINE) || defined(UNIVERSAL) - if (detected_platform() == BOARD_ID_PRALINE) { + IF_PRALINE ( const uint64_t requested = bank[RADIO_DC_BLOCK]; bool enable = requested; - if (radio->config[RADIO_BANK_APPLIED][RADIO_DC_BLOCK] == (uint64_t) enable) { + if (radio->config[RADIO_BANK_APPLIED][RADIO_DC_BLOCK] == + (uint64_t) enable) { return 0; } fpga_set_rx_dc_block_enable(&fpga, enable); radio->config[RADIO_BANK_APPLIED][RADIO_DC_BLOCK] = enable; return (1 << RADIO_DC_BLOCK); - } -#else + ) + (void) radio; (void) bank; -#endif - return 0; + return false; } bool radio_update(radio_t* const radio) diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index f2234413..a757eceb 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -294,35 +294,19 @@ static void switchctrl_set_rad1o(rf_path_t* const rf_path, uint8_t ctrl) static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) { -#if defined(JAWBREAKER) - (void) rf_path; -#endif - - switch (detected_platform()) { - case BOARD_ID_JAWBREAKER: -#if defined(JAWBREAKER) + IF_JAWBREAKER ( + (void) rf_path; mixer_set_gpo(&mixer, gpo); -#endif - break; - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + ) + IF_HACKRF_ONE ( switchctrl_set_hackrf_one(rf_path, gpo); -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( switchctrl_set_praline(rf_path, gpo); -#endif - break; - case BOARD_ID_RAD1O: -#if defined(RAD1O) + ) + IF_RAD1O ( switchctrl_set_rad1o(rf_path, gpo); -#endif - break; - default: - break; - } + ) } void rf_path_pin_setup(rf_path_t* const rf_path) @@ -331,15 +315,11 @@ void rf_path_pin_setup(rf_path_t* const rf_path) (void) rf_path; #endif - board_id_t board_id = detected_platform(); #if !defined(JAWBREAKER) const platform_scu_t* scu = platform_scu(); #endif - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_HACKRF_ONE ( /* Configure RF switch control signals */ // clang-format off scu_pinmux(scu->HP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); @@ -354,7 +334,7 @@ void rf_path_pin_setup(rf_path_t* const rf_path) scu_pinmux(scu->RX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(scu->NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); // clang-format on - if (board_id == BOARD_ID_HACKRF1_R9) { + IF_H1_R9 ( scu_pinmux(scu->H1R9_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux( scu->H1R9_NO_ANT_PWR, @@ -364,12 +344,13 @@ void rf_path_pin_setup(rf_path_t* const rf_path) scu_pinmux( scu->H1R9_NO_VAA_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - } else { + ) + IF_NOT_H1_R9 ( scu_pinmux(scu->TX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(scu->RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); gpio_output(rf_path->gpio_tx); scu_pinmux(scu->NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - } + ) /* * Safe (initial) switch settings turn off both amplifiers and antenna port @@ -390,10 +371,8 @@ void rf_path_pin_setup(rf_path_t* const rf_path) gpio_output(rf_path->gpio_no_tx_amp_pwr); gpio_output(rf_path->gpio_mix_bypass); gpio_output(rf_path->gpio_rx); -#endif - break; - case BOARD_ID_RAD1O: -#if defined(RAD1O) + ) + IF_RAD1O ( /* Configure RF switch control signals */ // clang-format off scu_pinmux(scu->BY_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); @@ -430,10 +409,9 @@ void rf_path_pin_setup(rf_path_t* const rf_path) gpio_output(rf_path->gpio_low_high_filt_n); gpio_output(rf_path->gpio_tx_amp); gpio_output(rf_path->gpio_rx_lna); -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + + IF_PRALINE ( /* Configure RF switch control signals */ scu_pinmux(scu->TX_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); board_rev_t rev = detected_revision(); @@ -464,17 +442,11 @@ void rf_path_pin_setup(rf_path_t* const rf_path) gpio_output(rf_path->gpio_mix_en_n); gpio_output(rf_path->gpio_lpf_en); gpio_output(rf_path->gpio_rf_amp_en); -#endif - break; - default: - break; - } + ) } void rf_path_init(rf_path_t* const rf_path) { - board_id_t board_id = detected_platform(); - ssp1_set_mode_max5864(); max5864_setup(&max5864); max5864_shutdown(&max5864); @@ -483,22 +455,14 @@ void rf_path_init(rf_path_t* const rf_path) max283x_setup(&max283x); max283x_start(&max283x); - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: - // On HackRF One, the mixer is now set up earlier in boot. - break; - case BOARD_ID_RAD1O: -#if defined(RAD1O) + IF_RAD1O ( mixer_setup(&mixer, MAX2871_VARIANT); -#endif - break; - default: -#if !defined(RAD1O) - mixer_setup(&mixer, RFFC5071_VARIANT); -#endif - break; - } + ) + IF_NOT_RAD1O ( + IF_NOT_HACKRF_ONE ( + mixer_setup(&mixer, RFFC5071_VARIANT); + ) + ) rf_path->switchctrl = SWITCHCTRL_SAFE; } diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 89befe98..fbeb2d93 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -110,19 +110,15 @@ void rffc5071_init(rffc5071_driver_t* const drv) */ void rffc5071_setup(rffc5071_driver_t* const drv) { - board_id_t board_id = detected_platform(); - gpio_set(drv->gpio_reset); gpio_output(drv->gpio_reset); - if (board_id == BOARD_ID_PRALINE) { -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( /* Configure mixer PLL lock detect pin */ const platform_scu_t* scu = platform_scu(); scu_pinmux(scu->MIXER_LD, scu->MIXER_LD_PINCFG); gpio_input(drv->gpio_ld); -#endif - } + ) rffc5071_init(drv); @@ -140,16 +136,9 @@ void rffc5071_setup(rffc5071_driver_t* const drv) set_RFFC5071_FULLD(drv, 0); set_RFFC5071_MODE(drv, 1); - switch (board_id) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: - case BOARD_ID_PRALINE: - /* Enable GPO Lock output signal */ + IF_H1_OR_PRALINE ( set_RFFC5071_LOCK(drv, 1); - break; - default: - break; - } + ) /* Enable reference oscillator standby */ set_RFFC5071_REFST(drv, 1); @@ -192,17 +181,15 @@ void rffc5071_lock_test(rffc5071_driver_t* const drv) bool rffc5071_check_lock(rffc5071_driver_t* const drv) { - if (detected_platform() == BOARD_ID_PRALINE) { -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( return gpio_read(drv->gpio_ld); -#else - return false; -#endif - } else { + ) + IF_NOT_PRALINE ( set_RFFC5071_READSEL(drv, 0b0001); rffc5071_regs_commit(drv); return !!(rffc5071_reg_read(drv, RFFC5071_READBACK_REG) & 0x8000); - } + ) + return false; } static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) @@ -382,9 +369,9 @@ bool rffc5071_poll_ld(rffc5071_driver_t* const drv, uint8_t* prelock_state) // // For all other boards we'll just return true to avoid a situation where a // a caller is waiting for a lock signal that will never be detected. - if (detected_platform() != BOARD_ID_PRALINE) { + IF_NOT_PRALINE ( return true; - } + ) // The RFFC5072 can be configured to output PLL lock status on // GPO4. The lock detect signal is produced by a window detector @@ -451,9 +438,7 @@ bool rffc5071_poll_ld(rffc5071_driver_t* const drv, uint8_t* prelock_state) uint8_t rsm_state = (rb >> 11) & 0b11111; // get gpo4 lock detect signal - #if defined(PRALINE) || defined(UNIVERSAL) bool gpo4_ld = gpio_read(drv->gpio_ld); - #endif // parse state switch (rsm_state) { diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index ac755d51..86b6c58e 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -57,27 +57,24 @@ void sgpio_configure_pin_functions(sgpio_config_t* const config) scu_pinmux(scu->PINMUX_SGPIO14, scu->PINMUX_SGPIO14_PINCFG); /* GPIO5[13] */ scu_pinmux(scu->PINMUX_SGPIO15, scu->PINMUX_SGPIO15_PINCFG); /* GPIO5[14] */ - if (detected_platform() == BOARD_ID_HACKRF1_R9) { -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_H1_R9 ( scu_pinmux( scu->H1R9_TRIGGER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[5] */ -#endif - } else { + ) + IF_NOT_H1_R9 ( scu_pinmux( scu->TRIGGER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[12] */ - } + ) sgpio_cpld_set_mixer_invert(config, 0); gpio_output(config->gpio_q_invert); - if (detected_platform() != BOARD_ID_PRALINE) { -#if !defined(PRALINE) || defined(UNIVERSAL) + IF_NOT_PRALINE ( trigger_enable(false); gpio_output(config->gpio_trigger_enable); -#endif - } + ) } void sgpio_set_slice_mode(sgpio_config_t* const config, const bool multi_slice) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index b50aad81..dbedddf3 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -235,7 +235,6 @@ void si5351c_configure_multisynth( void si5351c_configure_clock_control(si5351c_driver_t* const drv) { uint8_t clkout_ctrl; - board_id_t board_id = detected_platform(); if (clkout_enabled) { clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | @@ -270,8 +269,7 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv) SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /* not connected, but: PLL B int mode */ }; - if (board_id == BOARD_ID_HACKRF1_R9) { -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_H1_R9 ( data[1] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA); @@ -282,10 +280,8 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv) data[4] = SI5351C_CLK_POWERDOWN; data[5] = SI5351C_CLK_POWERDOWN; data[6] = SI5351C_CLK_POWERDOWN; -#endif - } - if (board_id == BOARD_ID_PRALINE) { -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( /* CLK0: AFE_CLK */ data[1] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | @@ -315,8 +311,7 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv) /* CLK2: MCU_CLK */ data[3] = SI5351C_CLK_POWERDOWN; } -#endif - } + ) si5351c_write(drv, data, sizeof(data)); } @@ -331,11 +326,10 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) /* 7: Clock to CPU is deactivated as it is not used and creates noise */ /* 3: External clock output is deactivated by default */ - board_id_t board_id = detected_platform(); uint8_t clkout = 3; - uint8_t value; + uint8_t value = 0; - if (board_id == BOARD_ID_PRALINE) { + IF_PRALINE ( value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | SI5351C_CLK_ENABLE(4) | SI5351C_CLK_ENABLE(5) | SI5351C_CLK_DISABLE(6) | SI5351C_CLK_DISABLE(7); @@ -345,21 +339,22 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) } else { value |= SI5351C_CLK_DISABLE(2); } - } else { + ) + IF_NOT_PRALINE ( value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | SI5351C_CLK_ENABLE(2) | SI5351C_CLK_ENABLE(4) | SI5351C_CLK_ENABLE(5) | SI5351C_CLK_DISABLE(6) | SI5351C_CLK_DISABLE(7); /* HackRF One r9 has only three clock generator outputs. */ - if (board_id == BOARD_ID_HACKRF1_R9) { + IF_H1_R9 ( clkout = 2; value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | SI5351C_CLK_DISABLE(3) | SI5351C_CLK_DISABLE(4) | SI5351C_CLK_DISABLE(5) | SI5351C_CLK_DISABLE(6) | SI5351C_CLK_DISABLE(7); - } - } + ) + ) value |= (clkout_enabled) ? SI5351C_CLK_ENABLE(clkout) : SI5351C_CLK_DISABLE(clkout); @@ -367,16 +362,14 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) si5351c_write(drv, data, sizeof(data)); outputs_disabled = value; - if (detected_platform() == BOARD_ID_HACKRF1_R9) { -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_H1_R9 ( const platform_gpio_t* gpio = platform_gpio(); if (clkout_enabled) { gpio_set(gpio->h1r9_clkout_en); } else { gpio_clear(gpio->h1r9_clkout_en); } -#endif - } + ) } void si5351c_set_int_mode( @@ -406,8 +399,7 @@ void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_source return; } si5351c_disable_all_outputs(drv); - if (detected_platform() == BOARD_ID_HACKRF1_R9) { -#if defined(HACKRF_ONE) + IF_H1_R9 ( /* * HackRF One r9 always uses PLL A on the XTAL input * but externally switches that input to CLKIN. @@ -418,10 +410,10 @@ void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_source } else { gpio_clear(platform_gpio()->h1r9_clkin_en); } -#endif - } else { + ) + IF_NOT_H1_R9 ( si5351c_configure_pll_sources(drv, source); - } + ) si5351c_configure_pll_multisynth(drv, source); active_clock_source = source; si5351c_reset_pll(drv, SI5351C_PLL_BOTH); @@ -476,8 +468,7 @@ void si5351c_init(si5351c_driver_t* const drv) selftest.report.pass = false; } - if (detected_platform() == BOARD_ID_HACKRF1_R9) { -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_H1_R9 ( const platform_gpio_t* gpio = platform_gpio(); const platform_scu_t* scu = platform_scu(); @@ -495,8 +486,7 @@ void si5351c_init(si5351c_driver_t* const drv) scu_pinmux(scu->H1R9_MCU_CLK_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); gpio_clear(gpio->h1r9_mcu_clk_en); gpio_output(gpio->h1r9_mcu_clk_en); -#endif - } + ) } /* diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 9c863beb..347be0ae 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -38,12 +38,10 @@ static fp_40_24_t max_bypass_freq = FP_MHZ(2740); void tuning_setup(void) { -#if defined(PRALINE) || defined(UNIVERSAL) - if (detected_platform() == BOARD_ID_PRALINE) { + IF_PRALINE ( min_bypass_freq = FP_MHZ(2320); max_bypass_freq = FP_MHZ(2580); - } -#endif + ) } fp_40_24_t select_graduated_if(fp_40_24_t freq_rf, rf_path_filter_t img_reject) @@ -52,12 +50,13 @@ fp_40_24_t select_graduated_if(fp_40_24_t freq_rf, rf_path_filter_t img_reject) switch (img_reject) { case RF_PATH_FILTER_LOW_PASS: - if (detected_platform() == BOARD_ID_RAD1O) { + IF_RAD1O ( freq_if = FP_MHZ(2300); - } else { + ) + IF_NOT_RAD1O ( /* IF is graduated from 2650 MHz to 2340 MHz */ freq_if = FP_MHZ(2650) - (freq_rf / 7); - } + ) break; case RF_PATH_FILTER_HIGH_PASS: if (freq_rf < MID1_HP_FREQ) { diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 4952f85d..97a04737 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -347,9 +347,9 @@ void radio_changed(const uint32_t changed) if (opmode != TRANSCEIVER_MODE_RX_SWEEP) { hackrf_ui()->set_frequency(freq / FP_ONE_HZ); } -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) - operacake_set_range(freq / FP_ONE_MHZ); -#endif + IF_EXPANSION_COMPATIBLE ( + operacake_set_range(freq / FP_ONE_MHZ); + ) } if (changed & (1 << RADIO_IMAGE_REJECT)) { if (opmode != TRANSCEIVER_MODE_RX_SWEEP) { @@ -443,20 +443,9 @@ int main(void) } delay_us_at_mhz(10000, 96); pin_setup(); - if (board_id != BOARD_ID_PRALINE) { - enable_1v8_power(); - if (board_id != BOARD_ID_RAD1O) { - /* - * On rad1o, the clock generator power supply comes from the RF supply - * which is enabled later. On H1 and Jawbreaker, the clock generator is - * on the main 3V3 supply. - */ - clock_gen_init(); - } - } else { -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( enable_3v3aux_power(); - #if !defined(DFU_MODE) && !defined(RAM_MODE) +#if !defined(DFU_MODE) && !defined(RAM_MODE) enable_1v2_power(); enable_rf_power(); /* @@ -464,62 +453,60 @@ int main(void) * which is enabled when 1V2FPGA is turned on. */ clock_gen_init(); - #endif #endif - } + ) + IF_NOT_PRALINE ( + enable_1v8_power(); + IF_NOT_RAD1O ( + /* + * On rad1o, the clock generator power supply comes from the RF supply + * which is enabled later. On H1 and Jawbreaker, the clock generator is + * on the main 3V3 supply. + */ + clock_gen_init(); + ) + ) tuning_setup(); - if (board_id == BOARD_ID_HACKRF1_OG || board_id == BOARD_ID_HACKRF1_R9) { -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_HACKRF_ONE ( // Set up mixer before enabling RF power, because its // GPO is used to control the antenna bias tee. mixer_setup(&mixer, RFFC5071_VARIANT); -#endif - } - if (board_id == BOARD_ID_HACKRF1_OG || board_id == BOARD_ID_HACKRF1_R9 || - board_id == BOARD_ID_RAD1O) { -#if defined(RAD1O) || defined(HACKRF_ONE) || defined(UNIVERSAL) + ) + IF_H1_OR_RAD1O ( enable_rf_power(); -#endif - } - if (board_id == BOARD_ID_RAD1O) { + ) + IF_RAD1O ( clock_gen_init(); - } + ) cpu_clock_init(); /* Wake the M0 */ ipc_halt_m0(); ipc_start_m0((uint32_t) &__ram_m0_start__); -#if !defined(PRALINE) || defined(UNIVERSAL) - if (board_id != BOARD_ID_PRALINE) { + IF_NOT_PRALINE ( if (!cpld_jtag_sram_load(&jtag_cpld)) { halt_and_flash(6000000); } - } -#endif -#if defined(PRALINE) || defined(UNIVERSAL) - if (board_id == BOARD_ID_PRALINE) { - #if defined(DFU_MODE) || defined(RAM_MODE) + ) + IF_PRALINE ( +#if defined(DFU_MODE) || defined(RAM_MODE) selftest.fpga_image_load = SKIPPED; selftest.report.pass = false; - #else +#else fpga_image_load(&fpga_loader, 0); - #endif +#endif delay_us_at_mhz(100, 204); fpga_spi_selftest(); fpga_sgpio_selftest(); - } -#endif + ) radio.update_cb = radio_changed; radio_init(&radio); - if (board_id == BOARD_ID_HACKRF1_OG || board_id == BOARD_ID_HACKRF1_R9 || - board_id == BOARD_ID_PRALINE) { -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) + IF_EXPANSION_COMPATIBLE ( portapack_init(); -#endif - } + ) #ifndef DFU_MODE usb_set_descriptor_by_serial_number(); @@ -528,35 +515,22 @@ int main(void) usb_set_configuration_changed_cb(usb_configuration_changed); usb_peripheral_reset(); - switch (detected_platform()) { - case BOARD_ID_HACKRF1_OG: - case BOARD_ID_HACKRF1_R9: -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_HACKRF_ONE ( memcpy(&usb_device, &usb_device_hackrf_one, sizeof(usb_device_hackrf_one)); -#endif - break; - case BOARD_ID_JAWBREAKER: -#if defined(JAWBREAKER) + ) + IF_JAWBREAKER ( memcpy(&usb_device, &usb_device_jawbreaker, sizeof(usb_device_jawbreaker)); -#endif - break; - case BOARD_ID_RAD1O: -#if defined(RAD1O) + ) + IF_RAD1O ( memcpy(&usb_device, &usb_device_rad1o, sizeof(usb_device_rad1o)); -#endif - break; - case BOARD_ID_PRALINE: -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( memcpy(&usb_device, &usb_device_praline, sizeof(usb_device_praline)); -#endif - break; - default: - break; - }; + ) usb_device_init(0, &usb_device); usb_queue_init(&usb_endpoint_control_out_queue); @@ -579,11 +553,9 @@ int main(void) rffc5071_lock_test(&mixer.rffc5071); #endif - if (board_id == BOARD_ID_PRALINE) { -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( fpga_if_xcvr_selftest(); -#endif - } + ) if (da7219_detect()) { operacake_skip_i2c_address(DA7219_ADDRESS); @@ -630,11 +602,9 @@ int main(void) sweep_mode(request.seq); break; case TRANSCEIVER_MODE_CPLD_UPDATE: - if (board_id != BOARD_ID_PRALINE) { -#if !defined(PRALINE) || defined(UNIVERSAL) + IF_NOT_PRALINE ( cpld_update(); -#endif - } + ) break; default: break; diff --git a/firmware/hackrf_usb/usb_api_board_info.c b/firmware/hackrf_usb/usb_api_board_info.c index 8e64ad7f..eb91e5c9 100644 --- a/firmware/hackrf_usb/usb_api_board_info.c +++ b/firmware/hackrf_usb/usb_api_board_info.c @@ -131,8 +131,7 @@ usb_request_status_t usb_vendor_request_reset( if (stage == USB_TRANSFER_STAGE_SETUP) { pin_shutdown(); clock_gen_shutdown(); - if (detected_platform() == BOARD_ID_HACKRF1_R9) { -#if defined(HACKRF_ONE) || defined(UNIVERSAL) + IF_H1_R9 ( /* * Set boot pins as inputs so that the bootloader reads them * correctly after the reset. @@ -141,8 +140,7 @@ usb_request_status_t usb_vendor_request_reset( gpio_input(gpio->h1r9_mcu_clk_en); gpio_input(gpio->h1r9_clkout_en); gpio_input(gpio->h1r9_rx); -#endif - } + ) wwdt_reset(100000); diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index b74589ec..bf7e4985 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -142,64 +142,60 @@ usb_request_status_t usb_vendor_request_write_rffc5071( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { -#if defined(RAD1O) - (void) endpoint; - (void) stage; - if (detected_platform() == BOARD_ID_RAD1O) { + IF_RAD1O ( + (void) endpoint; + (void) stage; return USB_REQUEST_STATUS_STALL; - } -#endif + ) - if (stage == USB_TRANSFER_STAGE_SETUP) { -#if !defined(RAD1O) - if (endpoint->setup.index < RFFC5071_NUM_REGS) { - rffc5071_reg_write( - &mixer.rffc5071, - endpoint->setup.index, - endpoint->setup.value); - usb_transfer_schedule_ack(endpoint->in); - return USB_REQUEST_STATUS_OK; + IF_NOT_RAD1O ( + if (stage == USB_TRANSFER_STAGE_SETUP) { + if (endpoint->setup.index < RFFC5071_NUM_REGS) { + rffc5071_reg_write( + &mixer.rffc5071, + endpoint->setup.index, + endpoint->setup.value); + usb_transfer_schedule_ack(endpoint->in); + return USB_REQUEST_STATUS_OK; + } + return USB_REQUEST_STATUS_STALL; } -#endif - return USB_REQUEST_STATUS_STALL; - } else { return USB_REQUEST_STATUS_OK; - } + ) } usb_request_status_t usb_vendor_request_read_rffc5071( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { -#if defined(RAD1O) - (void) endpoint; - (void) stage; - if (detected_platform() == BOARD_ID_RAD1O) { + IF_RAD1O ( + (void) endpoint; + (void) stage; return USB_REQUEST_STATUS_STALL; - } -#endif + ) - if (stage == USB_TRANSFER_STAGE_SETUP) { -#if !defined(RAD1O) + IF_NOT_RAD1O ( uint16_t value; - if (endpoint->setup.index < RFFC5071_NUM_REGS) { - value = rffc5071_reg_read(&mixer.rffc5071, endpoint->setup.index); - endpoint->buffer[0] = value & 0xff; - endpoint->buffer[1] = value >> 8; - usb_transfer_schedule_block( - endpoint->in, - &endpoint->buffer, - 2, - NULL, - NULL); - usb_transfer_schedule_ack(endpoint->out); - return USB_REQUEST_STATUS_OK; + if (stage == USB_TRANSFER_STAGE_SETUP) { + if (endpoint->setup.index < RFFC5071_NUM_REGS) { + value = rffc5071_reg_read( + &mixer.rffc5071, + endpoint->setup.index); + endpoint->buffer[0] = value & 0xff; + endpoint->buffer[1] = value >> 8; + usb_transfer_schedule_block( + endpoint->in, + &endpoint->buffer, + 2, + NULL, + NULL); + usb_transfer_schedule_ack(endpoint->out); + return USB_REQUEST_STATUS_OK; + } + return USB_REQUEST_STATUS_STALL; } -#endif - return USB_REQUEST_STATUS_STALL; - } else { return USB_REQUEST_STATUS_OK; - } + ) } usb_request_status_t usb_vendor_request_set_clkout_enable( @@ -286,47 +282,47 @@ usb_request_status_t usb_vendor_request_user_config_set_bias_t_opts( return USB_REQUEST_STATUS_OK; } +#if defined(PRALINE) || defined(UNIVERSAL) usb_request_status_t usb_vendor_request_write_fpga_reg( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { - if (detected_platform() != BOARD_ID_PRALINE) { - return USB_REQUEST_STATUS_STALL; - } - - if (stage == USB_TRANSFER_STAGE_SETUP) { -#if defined(PRALINE) || defined(UNIVERSAL) - fpga_reg_write(&fpga, endpoint->setup.index, endpoint->setup.value); -#endif - usb_transfer_schedule_ack(endpoint->in); + IF_PRALINE ( + if (stage == USB_TRANSFER_STAGE_SETUP) { + fpga_reg_write( + &fpga, + endpoint->setup.index, + endpoint->setup.value); + usb_transfer_schedule_ack(endpoint->in); + } return USB_REQUEST_STATUS_OK; - } - return USB_REQUEST_STATUS_OK; + ) + + return USB_REQUEST_STATUS_STALL; } usb_request_status_t usb_vendor_request_read_fpga_reg( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { - if (detected_platform() != BOARD_ID_PRALINE) { - return USB_REQUEST_STATUS_STALL; - } + IF_PRALINE ( + if (stage == USB_TRANSFER_STAGE_SETUP) { + const uint8_t value = fpga_reg_read(&fpga, endpoint->setup.index); + endpoint->buffer[0] = value; + usb_transfer_schedule_block( + endpoint->in, + &endpoint->buffer, + 1, + NULL, + NULL); + usb_transfer_schedule_ack(endpoint->out); + } + return USB_REQUEST_STATUS_OK; + ) - if (stage == USB_TRANSFER_STAGE_SETUP) { -#if defined(PRALINE) || defined(UNIVERSAL) - const uint8_t value = fpga_reg_read(&fpga, endpoint->setup.index); - endpoint->buffer[0] = value; - usb_transfer_schedule_block( - endpoint->in, - &endpoint->buffer, - 1, - NULL, - NULL); -#endif - usb_transfer_schedule_ack(endpoint->out); - } - return USB_REQUEST_STATUS_OK; + return USB_REQUEST_STATUS_STALL; } +#endif /* * Each register is transferred as a uint8_t register number followed by a diff --git a/firmware/hackrf_usb/usb_api_selftest.c b/firmware/hackrf_usb/usb_api_selftest.c index fa5267b5..e25f387a 100644 --- a/firmware/hackrf_usb/usb_api_selftest.c +++ b/firmware/hackrf_usb/usb_api_selftest.c @@ -80,18 +80,14 @@ static const char* test_result_to_str(test_result_t result) void generate_selftest_report(void) { - board_id_t board_id = detected_platform(); - char* s = &selftest.report.msg[0]; size_t c = sizeof(selftest.report.msg); - if (board_id == BOARD_ID_RAD1O) { -#if defined(RAD1O) + IF_RAD1O ( append(&s, &c, "Mixer: MAX2871, ID: "); append(&s, &c, itoa(selftest.mixer_id, 10)); append(&s, &c, "\n"); -#endif - } else { -#if !defined(RAD1O) + ) + IF_NOT_RAD1O ( append(&s, &c, "Mixer: RFFC5072, ID: "); append(&s, &c, itoa(selftest.mixer_id >> 3, 10)); append(&s, &c, ", Rev: "); @@ -108,8 +104,7 @@ void generate_selftest_report(void) append(&s, &c, " (FAIL)"); } append(&s, &c, "\n"); -#endif - } + ) append(&s, &c, "Clock: Si5351"); append(&s, &c, ", Rev: "); @@ -118,16 +113,19 @@ void generate_selftest_report(void) append(&s, &c, selftest.si5351_readback_ok ? "OK" : "FAIL"); append(&s, &c, "\n"); - if (board_id == BOARD_ID_PRALINE) { -#if defined(PRALINE) || defined(UNIVERSAL) + IF_PRALINE ( append(&s, &c, "Transceiver: MAX2831, RSSI mux test: "); append(&s, &c, selftest.max2831_mux_test_ok ? "PASS" : "FAIL"); append(&s, &c, "\n"); -#endif - } else { -#if !defined(PRALINE) || defined(UNIVERSAL) + ) + IF_NOT_PRALINE ( append(&s, &c, "Transceiver: "); - append(&s, &c, (board_id == BOARD_ID_HACKRF1_R9 ? "MAX2839" : "MAX2837")); + IF_H1_R9 ( + append(&s, &c, "MAX2839"); + ) + IF_NOT_H1_R9 ( + append(&s, &c, "MAX2837"); + ) append(&s, &c, ", readback success: "); append(&s, &c, itoa(selftest.max283x_readback_register_count, 10)); append(&s, &c, "/"); @@ -142,10 +140,8 @@ void generate_selftest_report(void) itoa(selftest.max283x_readback_expected_value, 10)); } append(&s, &c, "\n"); -#endif - } - if (board_id == BOARD_ID_PRALINE) { -#if defined(PRALINE) || defined(UNIVERSAL) + ) + IF_PRALINE ( append(&s, &c, "FPGA configuration: "); append(&s, &c, test_result_to_str(selftest.fpga_image_load)); append(&s, &c, "\n"); @@ -177,8 +173,7 @@ void generate_selftest_report(void) append(&s, &c, itoa(m->avg_mag_sq_q, 10)); append(&s, &c, "\n"); } -#endif - } + ) } usb_request_status_t usb_vendor_request_read_selftest( From 7a6b09962402836745d74e133d46a5d95102a232 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 9 Apr 2026 18:27:46 +0100 Subject: [PATCH 130/238] firmware: Separate compile-time and runtime platform checks. --- firmware/common/cpld_jtag.c | 36 ++- firmware/common/hackrf_core.c | 366 +++++++++++++++-------- firmware/common/hackrf_ui.c | 16 +- firmware/common/max283x.c | 24 +- firmware/common/mixer.c | 74 +++-- firmware/common/operacake_sctimer.c | 12 +- firmware/common/platform_detect.h | 145 +++------ firmware/common/platform_gpio.c | 176 +++++++---- firmware/common/platform_scu.c | 176 +++++++---- firmware/common/radio.c | 60 ++-- firmware/common/rf_path.c | 72 +++-- firmware/common/rffc5071.c | 30 +- firmware/common/sgpio.c | 18 +- firmware/common/si5351c.c | 54 ++-- firmware/common/tuning.c | 18 +- firmware/hackrf_usb/hackrf_usb.c | 98 +++--- firmware/hackrf_usb/usb_api_board_info.c | 6 +- firmware/hackrf_usb/usb_api_register.c | 36 ++- firmware/hackrf_usb/usb_api_selftest.c | 42 ++- 19 files changed, 921 insertions(+), 538 deletions(-) diff --git a/firmware/common/cpld_jtag.c b/firmware/common/cpld_jtag.c index 58359051..b277b462 100644 --- a/firmware/common/cpld_jtag.c +++ b/firmware/common/cpld_jtag.c @@ -42,30 +42,38 @@ void cpld_jtag_take(jtag_t* const jtag) /* Set initial GPIO state to the voltages of the internal or external pull-ups/downs, * to avoid any glitches. */ - IF_EXPANSION_COMPATIBLE ( +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { gpio_set(gpio->gpio_pp_tms); - ) + } +#endif gpio_clear(gpio->gpio_tck); - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { gpio_set(gpio->gpio_tms); gpio_set(gpio->gpio_tdi); - ) + } +#endif - IF_EXPANSION_COMPATIBLE ( +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { /* Do not drive PortaPack-specific TMS pin initially, just to be cautious. */ gpio_input(gpio->gpio_pp_tms); gpio_input(gpio->gpio_pp_tdo); - ) + } +#endif gpio_output(gpio->gpio_tck); - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { gpio_output(gpio->gpio_tms); gpio_output(gpio->gpio_tdi); gpio_input(gpio->gpio_tdo); - ) + } +#endif } void cpld_jtag_release(jtag_t* const jtag) @@ -75,19 +83,23 @@ void cpld_jtag_release(jtag_t* const jtag) /* Make all pins inputs when JTAG interface not active. * Let the pull-ups/downs do the work. */ - IF_EXPANSION_COMPATIBLE ( +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { /* Do not drive PortaPack-specific pins, initially, just to be cautious. */ gpio_input(gpio->gpio_pp_tms); gpio_input(gpio->gpio_pp_tdo); - ) + } +#endif gpio_input(gpio->gpio_tck); - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { gpio_input(gpio->gpio_tms); gpio_input(gpio->gpio_tdi); gpio_input(gpio->gpio_tdo); - ) + } +#endif } #if !defined(PRALINE) || defined(UNIVERSAL) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 689a2a30..0ac7ae65 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -341,7 +341,8 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) sgpio_cpld_stream_disable(&sgpio_config); } - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { /* Integer mode can be enabled if p1 is even and p2 is zero. */ if (p1 & 0x1 || p2) { si5351c_set_int_mode(&clock_gen, 0, 0); @@ -349,14 +350,17 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) si5351c_set_int_mode(&clock_gen, 0, 1); } - IF_H1_R9 ( + #ifdef IS_H1_R9 + if (IS_H1_R9) { /* * On HackRF One r9 all sample clocks are externally derived * from MS1/CLK1 operating at twice the sample rate. */ si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 0); - ) - IF_NOT_H1_R9 ( + } + #endif + #ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { /* * On other platforms the clock generator produces three * different sample clocks, all derived from multisynth 0. @@ -381,9 +385,12 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) 0, 0, 0); //p1 doesn't matter - ) - ) - IF_PRALINE ( + } + #endif + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { /* MS0/CLK0 is the source for the MAX5864 (AFE_CLK). */ si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); @@ -409,7 +416,8 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) /* Reset PLL to synchronize output clock phase. */ si5351c_reset_pll(&clock_gen, SI5351C_PLL_A); - ) + } +#endif if (streaming) { sgpio_cpld_stream_enable(&sgpio_config); @@ -561,7 +569,8 @@ void cpu_clock_init(void) CGU_BASE_SSP1_CLK = CGU_BASE_SSP1_CLK_AUTOBLOCK(1) | CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1); - IF_NOT_RAD1O ( +#ifdef IS_NOT_RAD1O + if (IS_NOT_RAD1O) { /* Disable unused clocks */ /* Start with PLLs */ CGU_PLL0AUDIO_CTRL = CGU_PLL0AUDIO_CTRL_PD(1); @@ -629,7 +638,8 @@ void cpu_clock_init(void) // CCU2_CLK_APB2_USART3_CFG = 0; // CCU2_CLK_APLL_CFG = 0; // CCU2_CLK_SDIO_CFG = 0; - ) + } +#endif } void clock_gen_init(void) @@ -670,7 +680,8 @@ void clock_gen_init(void) * CLK7 -> AUX_CLK2 */ - IF_H1_R9 ( +#ifdef IS_H1_R9 + if (IS_H1_R9) { /* MS0/CLK0 is the reference for both RFFC5071 and MAX2839. */ si5351c_configure_multisynth( &clock_gen, @@ -679,8 +690,10 @@ void clock_gen_init(void) 0, 1, 0); /* 800/20 = 40MHz */ - ) - IF_NOT_H1_R9 ( + } +#endif +#ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { /* MS4/CLK4 is the source for the RFFC5071 mixer (MAX2837 on rad1o). */ si5351c_configure_multisynth( &clock_gen, @@ -697,7 +710,8 @@ void clock_gen_init(void) 0, 1, 0); /* 800/20 = 40MHz */ - ) + } +#endif /* MS6/CLK6 is unused. */ /* MS7/CLK7 is unused. */ @@ -722,12 +736,14 @@ void clock_gen_shutdown(void) clock_source_t activate_best_clock_source(void) { - IF_EXPANSION_COMPATIBLE ( +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { /* Ensure PortaPack reference oscillator is off while checking for external clock input. */ if (portapack_reference_oscillator && portapack()) { portapack_reference_oscillator(false); } - ) + } +#endif clock_source_t source = CLOCK_SOURCE_HACKRF; @@ -735,7 +751,8 @@ clock_source_t activate_best_clock_source(void) if (si5351c_clkin_signal_valid(&clock_gen)) { source = CLOCK_SOURCE_EXTERNAL; } else { - IF_EXPANSION_COMPATIBLE ( +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { /* Enable PortaPack reference oscillator (if present), and check for valid clock. */ if (portapack_reference_oscillator && portapack()) { portapack_reference_oscillator(true); @@ -746,7 +763,8 @@ clock_source_t activate_best_clock_source(void) portapack_reference_oscillator(false); } } - ) + } +#endif /* No external or PortaPack clock was found. Use HackRF Si5351C crystal. */ } @@ -798,69 +816,94 @@ void pin_shutdown(void) * * LPC43xx pull-up and pull-down resistors are approximately 53K. */ - IF_EXPANSION_COMPATIBLE ( +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { scu_pinmux(scu->PINMUX_PP_TMS, SCU_GPIO_PUP | SCU_CONF_FUNCTION0); scu_pinmux(scu->PINMUX_PP_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); - ) + } +#endif scu_pinmux(scu->PINMUX_CPLD_TCK, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { scu_pinmux(scu->PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); scu_pinmux(scu->PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); scu_pinmux(scu->PINMUX_CPLD_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); - ) + } +#endif /* Configure SCU Pin Mux as GPIO */ scu_pinmux(scu->PINMUX_LED1, SCU_GPIO_NOPULL); scu_pinmux(scu->PINMUX_LED2, SCU_GPIO_NOPULL); scu_pinmux(scu->PINMUX_LED3, SCU_GPIO_NOPULL); - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { scu_pinmux(scu->PINMUX_LED4, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION4); - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { scu_pinmux(scu->PINMUX_LED4, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - ) + } +#endif /* Configure USB indicators */ - IF_JAWBREAKER ( +#ifdef IS_JAWBREAKER + if (IS_JAWBREAKER) { scu_pinmux(scu->PINMUX_USB_LED0, SCU_CONF_FUNCTION3); scu_pinmux(scu->PINMUX_USB_LED1, SCU_CONF_FUNCTION3); - ) + } +#endif - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { disable_1v2_power(); disable_3v3aux_power(); gpio_output(gpio->gpio_1v2_enable); gpio_output(gpio->gpio_3v3aux_enable_n); scu_pinmux(scu->PINMUX_EN1V2, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(scu->PINMUX_EN3V3_AUX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - ) + } +#endif - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { disable_1v8_power(); - IF_H1_R9 ( + #ifdef IS_H1_R9 + if (IS_H1_R9) { gpio_output(gpio->h1r9_1v8_enable); scu_pinmux(scu->H1R9_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - ) - IF_NOT_H1_R9 ( + } + #endif + #ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { gpio_output(gpio->gpio_1v8_enable); scu_pinmux(scu->PINMUX_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - ) - ) + } + #endif + } +#endif - IF_H1_OR_PRALINE ( +#ifdef IS_H1_OR_PRALINE + if (IS_H1_OR_PRALINE) { /* Safe state: start with VAA turned off: */ disable_rf_power(); /* Configure RF power supply (VAA) switch control signal as output */ - IF_H1_R9 ( + #ifdef IS_H1_R9 + if (IS_H1_R9) { gpio_output(gpio->h1r9_vaa_disable); - ) - IF_NOT_H1_R9 ( + } + #endif + #ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { gpio_output(gpio->vaa_disable); - ) - ) + } + #endif + } +#endif - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { /* Safe state: start with VAA turned off: */ disable_rf_power(); @@ -873,9 +916,11 @@ void pin_shutdown(void) scu_pinmux(scu->PINMUX_GPIO3_10, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); scu_pinmux(scu->PINMUX_GPIO3_11, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); - ) + } +#endif - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { scu_pinmux(scu->P2_CTRL0, scu->P2_CTRL0_PINCFG); scu_pinmux(scu->P2_CTRL1, scu->P2_CTRL1_PINCFG); scu_pinmux(scu->P1_CTRL0, scu->P1_CTRL0_PINCFG); @@ -910,7 +955,8 @@ void pin_shutdown(void) gpio_clear(gpio->fpga_cfg_creset); gpio_output(gpio->fpga_cfg_creset); gpio_input(gpio->fpga_cfg_cdone); - ) + } +#endif /* enable input on SCL and SDA pins */ SCU_SFSI2C0 = SCU_I2C0_NOMINAL; @@ -927,26 +973,34 @@ void pin_setup(void) led_off(0); led_off(1); led_off(2); - IF_FOUR_LEDS ( +#ifdef IS_FOUR_LEDS + if (IS_FOUR_LEDS) { led_off(3); - ) + } +#endif gpio_output(gpio->led[0]); gpio_output(gpio->led[1]); gpio_output(gpio->led[2]); - IF_FOUR_LEDS ( +#ifdef IS_FOUR_LEDS + if (IS_FOUR_LEDS) { gpio_output(gpio->led[3]); - ) + } +#endif /* Configure drivers and driver pins */ ssp_config_max283x.gpio_select = gpio->max283x_select; - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { ssp_config_max283x.data_bits = SSP_DATA_16BITS; - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { ssp_config_max283x.data_bits = SSP_DATA_9BITS; // send 2 words - ) + } +#endif ssp_config_max5864.gpio_select = gpio->max5864_select; @@ -956,40 +1010,51 @@ void pin_setup(void) sgpio_config.gpio_q_invert = gpio->q_invert; - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { sgpio_config.gpio_trigger_enable = gpio->trigger_enable; - ) + } +#endif - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { ssp_config_ice40_fpga.gpio_select = gpio->fpga_cfg_spi_cs; ice40.gpio_select = gpio->fpga_cfg_spi_cs; ice40.gpio_creset = gpio->fpga_cfg_creset; ice40.gpio_cdone = gpio->fpga_cfg_cdone; - ) + } +#endif jtag_gpio_cpld.gpio_tck = gpio->cpld_tck; - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { jtag_gpio_cpld.gpio_tms = gpio->cpld_tms; jtag_gpio_cpld.gpio_tdi = gpio->cpld_tdi; jtag_gpio_cpld.gpio_tdo = gpio->cpld_tdo; - ) + } +#endif - IF_EXPANSION_COMPATIBLE ( +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { jtag_gpio_cpld.gpio_pp_tms = gpio->cpld_pp_tms; jtag_gpio_cpld.gpio_pp_tdo = gpio->cpld_pp_tdo; - ) + } +#endif ssp1_set_mode_max283x(); mixer_bus_setup(&mixer); - IF_H1_R9 ( +#ifdef IS_H1_R9 + if (IS_H1_R9) { sgpio_config.gpio_trigger_enable = gpio->h1r9_trigger_enable; - ) + } +#endif // initialize rf_path struct and assign gpio's - IF_HACKRF_ONE ( +#ifdef IS_HACKRF_ONE + if (IS_HACKRF_ONE) { rf_path = (rf_path_t){ .switchctrl = 0, .gpio_hp = gpio->hp, @@ -1006,13 +1071,17 @@ void pin_setup(void) .gpio_rx_amp = gpio->rx_amp, .gpio_no_rx_amp_pwr = gpio->no_rx_amp_pwr, }; - IF_H1_R9 ( + #ifdef IS_H1_R9 + if (IS_H1_R9) { rf_path.gpio_rx = gpio->h1r9_rx; rf_path.gpio_h1r9_no_ant_pwr = gpio->h1r9_no_ant_pwr; - ) - ) + } + #endif + } +#endif - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { rf_path = (rf_path_t){ .switchctrl = 0, .gpio_tx_rx_n = gpio->tx_rx_n, @@ -1027,9 +1096,11 @@ void pin_setup(void) .gpio_tx_amp = gpio->tx_amp, .gpio_rx_lna = gpio->rx_lna, }; - ) + } +#endif - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { rf_path = (rf_path_t){ .switchctrl = 0, .gpio_tx_en = gpio->tx_en, @@ -1042,7 +1113,8 @@ void pin_setup(void) (detected_revision() == BOARD_REV_GSG_PRALINE_R1_0)) { rf_path.gpio_mix_en_n = gpio->mix_en_n_r1_0; } - ) + } +#endif rf_path_pin_setup(&rf_path); @@ -1055,55 +1127,75 @@ void pin_setup(void) #if defined(PRALINE) || defined(UNIVERSAL) void enable_1v2_power(void) { - IF_PRALINE ( + #ifdef IS_PRALINE + if (IS_PRALINE) { gpio_set(platform_gpio()->gpio_1v2_enable); - ) + } + #endif } void disable_1v2_power(void) { - IF_PRALINE ( + #ifdef IS_PRALINE + if (IS_PRALINE) { gpio_clear(platform_gpio()->gpio_1v2_enable); - ) + } + #endif } void enable_3v3aux_power(void) { - IF_PRALINE ( + #ifdef IS_PRALINE + if (IS_PRALINE) { gpio_clear(platform_gpio()->gpio_3v3aux_enable_n); - ) + } + #endif } void disable_3v3aux_power(void) { - IF_PRALINE ( + #ifdef IS_PRALINE + if (IS_PRALINE) { gpio_set(platform_gpio()->gpio_3v3aux_enable_n); - ) + } + #endif } #endif void enable_1v8_power(void) { - IF_NOT_PRALINE ( - IF_H1_R9 ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { + #ifdef IS_H1_R9 + if (IS_H1_R9) { gpio_set(platform_gpio()->h1r9_1v8_enable); - ) - IF_NOT_H1_R9 ( + } + #endif + #ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { gpio_set(platform_gpio()->gpio_1v8_enable); - ) - ) + } + #endif + } +#endif } void disable_1v8_power(void) { - IF_NOT_PRALINE ( - IF_H1_R9 ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { + #ifdef IS_H1_R9 + if (IS_H1_R9) { gpio_clear(platform_gpio()->h1r9_1v8_enable); - ) - IF_NOT_H1_R9 ( + } + #endif + #ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { gpio_clear(platform_gpio()->gpio_1v8_enable); - ) - ) + } + #endif + } +#endif } #if defined(HACKRF_ONE) || defined(UNIVERSAL) @@ -1166,48 +1258,68 @@ static inline void disable_rf_power_rad1o(void) void enable_rf_power(void) { - IF_HACKRF_ONE ( +#ifdef IS_HACKRF_ONE + if (IS_HACKRF_ONE) { enable_rf_power_hackrf_one(); - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { enable_rf_power_praline(); - ) - IF_RAD1O ( + } +#endif +#ifdef IS_RAD1O + if (IS_RAD1O) { enable_rf_power_rad1o(); - ) + } +#endif } void disable_rf_power(void) { - IF_HACKRF_ONE ( +#ifdef IS_HACKRF_ONE + if (IS_HACKRF_ONE) { disable_rf_power_hackrf_one(); - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { disable_rf_power_praline(); - ) - IF_RAD1O ( + } +#endif +#ifdef IS_RAD1O + if (IS_RAD1O) { disable_rf_power_rad1o(); - ) + } +#endif } void led_on(const led_t led) { - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { gpio_clear(platform_gpio()->led[led]); - ) - IF_NOT_PRALINE ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { gpio_set(platform_gpio()->led[led]); - ) + } +#endif } void led_off(const led_t led) { - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { gpio_set(platform_gpio()->led[led]); - ) - IF_NOT_PRALINE ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { gpio_clear(platform_gpio()->led[led]); - ) + } +#endif } void led_toggle(const led_t led) @@ -1218,28 +1330,38 @@ void led_toggle(const led_t led) void set_leds(const uint8_t state) { int num_leds = 3; - IF_FOUR_LEDS ( +#ifdef IS_FOUR_LEDS + if (IS_FOUR_LEDS) { num_leds = 4; - ) + } +#endif for (int i = 0; i < num_leds; i++) { - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { gpio_write(platform_gpio()->led[i], ((state >> i) & 1) == 0); - ) - IF_NOT_PRALINE ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { gpio_write(platform_gpio()->led[i], ((state >> i) & 1) == 1); - ) + } +#endif } } void trigger_enable(const bool enable) { - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { gpio_write(sgpio_config.gpio_trigger_enable, enable); - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { fpga_set_trigger_enable(&fpga, enable); - ) + } +#endif } void halt_and_flash(const uint32_t duration) diff --git a/firmware/common/hackrf_ui.c b/firmware/common/hackrf_ui.c index 092ec12b..b90ccc14 100644 --- a/firmware/common/hackrf_ui.c +++ b/firmware/common/hackrf_ui.c @@ -23,8 +23,10 @@ #include #include "hackrf_ui.h" -#include "platform_detect.h" #include "transceiver_mode.h" +#if !defined(JAWBREAKER) + #include "platform_detect.h" +#endif #if defined(PRALINE) || defined(HACKRF_ONE) || defined(UNIVERSAL) #include "ui_portapack.h" #endif @@ -83,16 +85,20 @@ const hackrf_ui_t* hackrf_ui(void) { /* Detect on first use. If no UI hardware is detected, use a stub function table. */ if (ui == NULL && ui_enabled) { - IF_EXPANSION_COMPATIBLE ( +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { if (portapack_hackrf_ui_init) { ui = portapack_hackrf_ui_init(); } - ) - IF_RAD1O ( + } +#endif +#ifdef IS_RAD1O + if (IS_RAD1O) { if (rad1o_ui_setup) { ui = rad1o_ui_setup(); } - ) + } +#endif } if (ui == NULL) { diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index feb7837d..856c5d99 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -73,7 +73,8 @@ void max283x_setup(max283x_driver_t* const drv) const platform_gpio_t* gpio = platform_gpio(); /* MAX283x GPIO PinMux */ - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { drv->type = MAX2831_VARIANT; max2831.gpio_enable = gpio->max283x_enable; max2831.gpio_rxtx = gpio->max283x_rx_enable; @@ -81,24 +82,31 @@ void max283x_setup(max283x_driver_t* const drv) max2831.gpio_ld = gpio->max2831_ld; memcpy(&drv->drv.max2831, &max2831, sizeof(max2831)); max2831_setup(&drv->drv.max2831); - ) - IF_NOT_PRALINE ( - IF_H1_R9 ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { + #ifdef IS_H1_R9 + if (IS_H1_R9) { drv->type = MAX2839_VARIANT; max2839.gpio_enable = gpio->max283x_enable; max2839.gpio_rxtx = gpio->max283x_rx_enable; memcpy(&drv->drv.max2839, &max2839, sizeof(max2839)); max2839_setup(&drv->drv.max2839); - ) - IF_NOT_H1_R9 ( + } + #endif + #ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { drv->type = MAX2837_VARIANT; max2837.gpio_enable = gpio->max283x_enable; max2837.gpio_rx_enable = gpio->max283x_rx_enable; max2837.gpio_tx_enable = gpio->max283x_tx_enable; memcpy(&drv->drv.max2837, &max2837, sizeof(max2837)); max2837_setup(&drv->drv.max2837); - ) - ) + } + #endif + } +#endif } /* Macros to simplify dispatch of variant-specific operations. */ diff --git a/firmware/common/mixer.c b/firmware/common/mixer.c index 0706170b..fb921350 100644 --- a/firmware/common/mixer.c +++ b/firmware/common/mixer.c @@ -56,7 +56,8 @@ void mixer_bus_setup(mixer_driver_t* const mixer) { (void) mixer; - IF_NOT_RAD1O ( +#ifdef IS_NOT_RAD1O + if (IS_NOT_RAD1O) { const platform_gpio_t* gpio = platform_gpio(); rffc5071_spi_config = (rffc5071_spi_config_t){ @@ -65,7 +66,8 @@ void mixer_bus_setup(mixer_driver_t* const mixer) .gpio_data = gpio->rffc5072_data, }; spi_bus_start(&spi_bus_rffc5071, &rffc5071_spi_config); - ) + } +#endif } void mixer_setup(mixer_driver_t* const mixer, mixer_variant_t type) @@ -75,16 +77,21 @@ void mixer_setup(mixer_driver_t* const mixer, mixer_variant_t type) const platform_gpio_t* gpio = platform_gpio(); /* Mixer GPIO serial interface PinMux */ - IF_PRALINE ( - mixer->rffc5071.gpio_ld = gpio->rffc5072_ld - ); +#ifdef IS_PRALINE + if (IS_PRALINE) { + mixer->rffc5071.gpio_ld = gpio->rffc5072_ld; + } +#endif - IF_NOT_RAD1O ( +#ifdef IS_NOT_RAD1O + if (IS_NOT_RAD1O) { mixer->rffc5071.gpio_reset = gpio->rffc5072_reset; rffc5071_setup(&mixer->rffc5071); - ) + } +#endif - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { mixer->max2871.gpio_vco_ce = gpio->vco_ce; mixer->max2871.gpio_vco_sclk = gpio->vco_sclk; mixer->max2871.gpio_vco_sdata = gpio->vco_sdata; @@ -92,50 +99,67 @@ void mixer_setup(mixer_driver_t* const mixer, mixer_variant_t type) mixer->max2871.gpio_synt_rfout_en = gpio->synt_rfout_en; mixer->max2871.gpio_vco_mux = gpio->vco_mux; max2871_setup(&mixer->max2871); - ) + } +#endif } fp_40_24_t mixer_set_frequency(mixer_driver_t* const mixer, fp_40_24_t lo, bool program) { - IF_NOT_RAD1O ( +#ifdef IS_NOT_RAD1O + if (IS_NOT_RAD1O) { return rffc5071_set_frequency(&mixer->rffc5071, lo, program); - ) + } +#endif - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { return max2871_set_frequency(&mixer->max2871, lo, program); - ) + } +#endif } void mixer_enable(mixer_driver_t* const mixer) { - IF_NOT_RAD1O ( +#ifdef IS_NOT_RAD1O + if (IS_NOT_RAD1O) { rffc5071_enable(&mixer->rffc5071); - ) + } +#endif - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { max2871_enable(&mixer->max2871); - ) + } +#endif } void mixer_disable(mixer_driver_t* const mixer) { - IF_NOT_RAD1O ( +#ifdef IS_NOT_RAD1O + if (IS_NOT_RAD1O) { rffc5071_disable(&mixer->rffc5071); - ) + } +#endif - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { max2871_disable(&mixer->max2871); - ) + } +#endif } void mixer_set_gpo(mixer_driver_t* const mixer, uint8_t gpo) { - IF_NOT_RAD1O ( +#ifdef IS_NOT_RAD1O + if (IS_NOT_RAD1O) { rffc5071_set_gpo(&mixer->rffc5071, gpo); - ) + } +#endif - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { (void) mixer; (void) gpo; - ) + } +#endif } diff --git a/firmware/common/operacake_sctimer.c b/firmware/common/operacake_sctimer.c index 82bb6400..2dbe07d9 100644 --- a/firmware/common/operacake_sctimer.c +++ b/firmware/common/operacake_sctimer.c @@ -98,7 +98,8 @@ void operacake_sctimer_init(void) SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); uint8_t sct_clock_input; - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { // Configure the SGPIO to output the clock (f=2 * sample clock) on pin 12 SGPIO_OUT_MUX_CFG12 = SGPIO_OUT_MUX_CFG_P_OUT_CFG(0x08) | // clkout output mode @@ -109,8 +110,10 @@ void operacake_sctimer_init(void) GIMA_CTIN_1_IN = 0x2 << 4; // Route SGPIO12 to SCTIN1 sct_clock_input = SCT_CONFIG_CKSEL_RISING_EDGES_ON_INPUT_1; - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { // Configure pin P6_4 as SCT_IN_6 scu_pinmux(P6_4, SCU_CLK_IN | SCU_CONF_FUNCTION1); @@ -118,7 +121,8 @@ void operacake_sctimer_init(void) GIMA_CTIN_6_IN = 0x0 << 4; sct_clock_input = SCT_CONFIG_CKSEL_RISING_EDGES_ON_INPUT_6; - ) + } +#endif // We configure this register first, because the user manual says to SCT_CONFIG |= SCT_CONFIG_UNIFY_32_BIT | SCT_CONFIG_CLKMODE_PRESCALED_BUS_CLOCK | diff --git a/firmware/common/platform_detect.h b/firmware/common/platform_detect.h index f8bc53b9..0331fe9c 100644 --- a/firmware/common/platform_detect.h +++ b/firmware/common/platform_detect.h @@ -21,6 +21,7 @@ #pragma once +#include #include #define BOARD_REV_GSG (0x80) @@ -35,107 +36,57 @@ /* Helper macros for platform-specific code. */ #if defined(UNIVERSAL) - #define IF_PRALINE(...) \ - if (detected_platform() == BOARD_ID_PRALINE) { __VA_ARGS__; } - #define IF_NOT_PRALINE(...) \ - if (detected_platform() != BOARD_ID_PRALINE) { __VA_ARGS__; } - #define IF_HACKRF_ONE(...) \ - switch (detected_platform()) { \ - case BOARD_ID_HACKRF1_OG: \ - case BOARD_ID_HACKRF1_R9: \ - { __VA_ARGS__; } \ - break; \ - default: \ - break; \ - } - #define IF_NOT_HACKRF_ONE(...) \ - switch (detected_platform()) { \ - case BOARD_ID_HACKRF1_OG: \ - case BOARD_ID_HACKRF1_R9: \ - break; \ - default: \ - { __VA_ARGS__; } \ - break; \ - } - #define IF_H1_R9(...) \ - if (detected_platform() == BOARD_ID_HACKRF1_R9) { __VA_ARGS__; } - #define IF_NOT_H1_R9(...) \ - if (detected_platform() != BOARD_ID_HACKRF1_R9) { __VA_ARGS__; } - #define IF_RAD1O(...) - #define IF_NOT_RAD1O(...) { __VA_ARGS__; } - #define IF_JAWBREAKER(...) - #define IF_NOT_JAWBREAKER(...) { __VA_ARGS__; } - #define IF_H1_OR_PRALINE(...) { __VA_ARGS__; } - #define IF_H1_OR_RAD1O(...) IF_HACKRF_ONE(__VA_ARGS__) - #define IF_H1_OR_JAWBREAKER(...) IF_HACKRF_ONE(__VA_ARGS__) - #define IF_FOUR_LEDS(...) IF_PRALINE(__VA_ARGS__) - #define IF_EXPANSION_COMPATIBLE(...) { __VA_ARGS__; } + #define IS_PRALINE (detected_platform() == BOARD_ID_PRALINE) + #define IS_NOT_PRALINE (!IS_PRALINE) + #define IS_HACKRF_ONE ( \ + detected_platform() == BOARD_ID_HACKRF1_OG || \ + detected_platform() == BOARD_ID_HACKRF1_R9 \ + ) + #define IS_NOT_HACKRF_ONE (!IS_HACKRF_ONE) + #define IS_H1_R9 (detected_platform() == BOARD_ID_HACKRF1_R9) + #define IS_NOT_H1_R9 (!IS_H1_R9) + #define IS_NOT_RAD1O true + #define IS_NOT_JAWBREAKER true + #define IS_H1_OR_PRALINE true + #define IS_H1_OR_RAD1O IS_HACKRF_ONE + #define IS_H1_OR_JAWBREAKER IS_HACKRF_ONE + #define IS_FOUR_LEDS IS_PRALINE + #define IS_EXPANSION_COMPATIBLE true #elif defined(HACKRF_ONE) - #define IF_PRALINE(...) - #define IF_NOT_PRALINE(...) { __VA_ARGS__; } - #define IF_HACKRF_ONE(...) { __VA_ARGS__; } - #define IF_NOT_HACKRF_ONE(...) - #define IF_H1_R9(...) \ - if (detected_platform() == BOARD_ID_HACKRF1_R9) { __VA_ARGS__; } - #define IF_NOT_H1_R9(...) \ - if (detected_platform() != BOARD_ID_HACKRF1_R9) { __VA_ARGS__; } - #define IF_RAD1O(...) - #define IF_NOT_RAD1O(...) { __VA_ARGS__; } - #define IF_JAWBREAKER(...) - #define IF_NOT_JAWBREAKER(...) { __VA_ARGS__; } - #define IF_H1_OR_PRALINE(...) { __VA_ARGS__; } - #define IF_H1_OR_RAD1O(...) { __VA_ARGS__; } - #define IF_H1_OR_JAWBREAKER(...) { __VA_ARGS__; } - #define IF_FOUR_LEDS(...) - #define IF_EXPANSION_COMPATIBLE(...) { __VA_ARGS__; } + #define IS_NOT_PRALINE true + #define IS_HACKRF_ONE true + #define IS_H1_R9 (detected_platform() == BOARD_ID_HACKRF1_R9) + #define IS_NOT_H1_R9 (!IS_H1_R9) + #define IS_NOT_RAD1O true + #define IS_NOT_JAWBREAKER true + #define IS_H1_OR_PRALINE true + #define IS_H1_OR_RAD1O true + #define IS_H1_OR_JAWBREAKER true + #define IS_EXPANSION_COMPATIBLE true #elif defined(PRALINE) - #define IF_PRALINE(...) { __VA_ARGS__; } - #define IF_NOT_PRALINE(...) - #define IF_HACKRF_ONE(...) - #define IF_NOT_HACKRF_ONE(...) { __VA_ARGS__; } - #define IF_H1_R9(...) - #define IF_NOT_H1_R9(...) { __VA_ARGS__; } - #define IF_RAD1O(...) - #define IF_NOT_RAD1O(...) { __VA_ARGS__; } - #define IF_JAWBREAKER(...) - #define IF_NOT_JAWBREAKER(...) { __VA_ARGS__; } - #define IF_H1_OR_PRALINE(...) { __VA_ARGS__; } - #define IF_H1_OR_RAD1O(...) - #define IF_H1_OR_JAWBREAKER(...) - #define IF_FOUR_LEDS(...) - #define IF_EXPANSION_COMPATIBLE(...) { __VA_ARGS__; } + #define IS_PRALINE true + #define IS_NOT_HACKRF_ONE true + #define IS_NOT_H1_R9 true + #define IS_NOT_RAD1O true + #define IS_NOT_JAWBREAKER true + #define IS_H1_OR_PRALINE true + #define IS_FOUR_LEDS true + #define IS_EXPANSION_COMPATIBLE true #elif defined(RAD1O) - #define IF_PRALINE(...) - #define IF_NOT_PRALINE(...) { __VA_ARGS__; } - #define IF_HACKRF_ONE(...) - #define IF_NOT_HACKRF_ONE(...) { __VA_ARGS__; } - #define IF_H1_R9(...) - #define IF_NOT_H1_R9(...) { __VA_ARGS__; } - #define IF_RAD1O(...) { __VA_ARGS__; } - #define IF_NOT_RAD1O(...) - #define IF_JAWBREAKER(...) - #define IF_NOT_JAWBREAKER(...) { __VA_ARGS__; } - #define IF_H1_OR_PRALINE(...) - #define IF_H1_OR_RAD1O(...) { __VA_ARGS__; } - #define IF_H1_OR_JAWBREAKER(...) - #define IF_FOUR_LEDS(...) { __VA_ARGS__; } - #define IF_EXPANSION_COMPATIBLE(...) + #define IS_NOT_PRALINE true + #define IS_NOT_HACKRF_ONE true + #define IS_NOT_H1_R9 true + #define IS_RAD1O true + #define IS_NOT_JAWBREAKER true + #define IS_H1_OR_RAD1O true + #define IS_FOUR_LEDS true #elif defined(JAWBREAKER) - #define IF_PRALINE(...) - #define IF_NOT_PRALINE(...) { __VA_ARGS__; } - #define IF_HACKRF_ONE(...) - #define IF_NOT_HACKRF_ONE(...) { __VA_ARGS__; } - #define IF_H1_R9(...) - #define IF_NOT_H1_R9(...) { __VA_ARGS__; } - #define IF_RAD1O(...) - #define IF_NOT_RAD1O(...) { __VA_ARGS__; } - #define IF_JAWBREAKER(...) { __VA_ARGS__; } - #define IF_NOT_JAWBREAKER(...) - #define IF_H1_OR_PRALINE(...) - #define IF_H1_OR_RAD1O(...) - #define IF_H1_OR_JAWBREAKER(...) { __VA_ARGS__; } - #define IF_FOUR_LEDS(...) - #define IF_EXPANSION_COMPATIBLE(...) + #define IS_NOT_PRALINE true + #define IS_NOT_HACKRF_ONE true + #define IS_NOT_H1_R9 true + #define IS_NOT_RAD1O true + #define IS_JAWBREAKER true + #define IS_H1_OR_JAWBREAKER true #else #error "No recognised platform defined" #endif diff --git a/firmware/common/platform_gpio.c b/firmware/common/platform_gpio.c index 7f773b20..a5b892e8 100644 --- a/firmware/common/platform_gpio.c +++ b/firmware/common/platform_gpio.c @@ -40,55 +40,77 @@ const platform_gpio_t* platform_gpio(void) gpio.led[0] = &GPIO2_1; gpio.led[1] = &GPIO2_2; gpio.led[2] = &GPIO2_8; - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { gpio.led[3] = &GPIO5_26; - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { gpio.led[3] = &GPIO4_6; - ) + } +#endif /* Power Supply Control */ - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { gpio.gpio_1v2_enable = &GPIO4_7; gpio.gpio_3v3aux_enable_n = &GPIO5_15; - ) - IF_NOT_PRALINE ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { gpio.gpio_1v8_enable = &GPIO3_6; - ) + } +#endif /* MAX283x GPIO (XCVR_CTL / CS_XCVR) PinMux */ - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { gpio.max283x_select = &GPIO6_28; gpio.max283x_enable = &GPIO7_1; gpio.max283x_rx_enable = &GPIO7_2; gpio.max2831_rxhp = &GPIO6_29; gpio.max2831_ld = &GPIO4_11; - ) - IF_NOT_PRALINE ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { gpio.max283x_select = &GPIO0_15; gpio.max283x_enable = &GPIO2_6; gpio.max283x_rx_enable = &GPIO2_5; gpio.max283x_tx_enable = &GPIO2_4; - ) + } +#endif /* MAX5864 SPI chip select (AD_CS / CS_AD) GPIO PinMux */ - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { gpio.max5864_select = &GPIO6_30; - ) - IF_NOT_PRALINE ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { gpio.max5864_select = &GPIO2_7; - ) + } +#endif /* RF supply (VAA) control */ - IF_HACKRF_ONE ( +#ifdef IS_HACKRF_ONE + if (IS_HACKRF_ONE) { gpio.vaa_disable = &GPIO2_9; - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { gpio.vaa_disable = &GPIO4_1; - ) - IF_RAD1O ( + } +#endif +#ifdef IS_RAD1O + if (IS_RAD1O) { gpio.vaa_enable = &GPIO2_9; - ) + } +#endif /* W25Q80BV Flash */ gpio.w25q80bv_hold = &GPIO1_14; @@ -96,7 +118,8 @@ const platform_gpio_t* platform_gpio(void) gpio.w25q80bv_select = &GPIO5_11; /* RF switch control */ - IF_HACKRF_ONE ( +#ifdef IS_HACKRF_ONE + if (IS_HACKRF_ONE) { gpio.hp = &GPIO2_0; gpio.lp = &GPIO2_10; gpio.tx_mix_bp = &GPIO2_11; @@ -110,12 +133,16 @@ const platform_gpio_t* platform_gpio(void) gpio.amp_bypass = &GPIO0_14; gpio.rx_amp = &GPIO1_11; gpio.no_rx_amp_pwr = &GPIO1_12; - IF_H1_R9 ( +#ifdef IS_H1_R9 + if (IS_H1_R9) { gpio.h1r9_rx = &GPIO0_7; gpio.h1r9_no_ant_pwr = &GPIO2_4; - ) - ) - IF_RAD1O ( + } +#endif + } +#endif +#ifdef IS_RAD1O + if (IS_RAD1O) { gpio.tx_rx_n = &GPIO1_11; gpio.tx_rx = &GPIO0_14; gpio.by_mix = &GPIO1_12; @@ -127,70 +154,92 @@ const platform_gpio_t* platform_gpio(void) gpio.low_high_filt_n = &GPIO2_12; gpio.tx_amp = &GPIO2_15; gpio.rx_lna = &GPIO5_15; - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { gpio.tx_en = &GPIO3_4; gpio.mix_en_n = &GPIO3_2; gpio.mix_en_n_r1_0 = &GPIO5_6; gpio.lpf_en = &GPIO4_8; gpio.rf_amp_en = &GPIO4_9; gpio.ant_bias_en_n = &GPIO1_12; - ) + } +#endif /* CPLD JTAG interface GPIO pins_FPGA config pins in Praline */ gpio.cpld_tck = &GPIO3_0; - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { gpio.fpga_cfg_creset = &GPIO2_11; gpio.fpga_cfg_cdone = &GPIO5_14; gpio.fpga_cfg_spi_cs = &GPIO2_10; - ) - IF_NOT_PRALINE ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { gpio.cpld_tdo = &GPIO5_18; - IF_H1_OR_RAD1O ( - gpio.cpld_tms = &GPIO3_4; - gpio.cpld_tdi = &GPIO3_1; - ) - IF_JAWBREAKER ( - gpio.cpld_tms = &GPIO3_1; - gpio.cpld_tdi = &GPIO3_4; - ) - ) - IF_EXPANSION_COMPATIBLE ( + } +#endif +#ifdef IS_H1_OR_RAD1O + if (IS_H1_OR_RAD1O) { + gpio.cpld_tms = &GPIO3_4; + gpio.cpld_tdi = &GPIO3_1; + } +#endif +#ifdef IS_JAWBREAKER + if (IS_JAWBREAKER) { + gpio.cpld_tms = &GPIO3_1; + gpio.cpld_tdi = &GPIO3_4; + } +#endif +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { gpio.cpld_pp_tms = &GPIO1_1; gpio.cpld_pp_tdo = &GPIO1_8; - ) + } +#endif /* Other CPLD interface GPIO pins */ - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { gpio.trigger_enable = &GPIO5_12; - ) + } +#endif gpio.q_invert = &GPIO0_13; /* RFFC5071 GPIO serial interface PinMux */ - IF_NOT_RAD1O ( +#ifdef IS_NOT_RAD1O + if (IS_NOT_RAD1O) { gpio.rffc5072_select = &GPIO2_13; gpio.rffc5072_clock = &GPIO5_6; gpio.rffc5072_data = &GPIO3_3; gpio.rffc5072_reset = &GPIO2_14; - ) - IF_RAD1O ( + } +#endif +#ifdef IS_RAD1O + if (IS_RAD1O) { gpio.vco_ce = &GPIO2_13; gpio.vco_sclk = &GPIO5_6; gpio.vco_sdata = &GPIO3_3; gpio.vco_le = &GPIO2_14; gpio.vco_mux = &GPIO5_25; gpio.synt_rfout_en = &GPIO3_5; - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { gpio.rffc5072_select = &GPIO2_13; gpio.rffc5072_clock = &GPIO5_18; gpio.rffc5072_data = &GPIO4_14; gpio.rffc5072_reset = &GPIO2_14; gpio.rffc5072_ld = &GPIO6_25; - ) + } +#endif /* Praline */ - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { gpio.p2_ctrl0 = &GPIO7_3; gpio.p2_ctrl1 = &GPIO7_4; gpio.p1_ctrl0 = &GPIO0_14; @@ -201,33 +250,40 @@ const platform_gpio_t* platform_gpio(void) gpio.trigger_in = &GPIO6_26; gpio.trigger_out = &GPIO5_6; gpio.pps_out = &GPIO5_5; - ) + } +#endif /* HackRF One r9 clock control */ - IF_H1_R9 ( +#ifdef IS_H1_R9 + if (IS_H1_R9) { gpio.h1r9_clkin_en = &GPIO5_15; gpio.h1r9_clkout_en = &GPIO0_9; gpio.h1r9_mcu_clk_en = &GPIO0_8; gpio.h1r9_1v8_enable = &GPIO2_9; gpio.h1r9_vaa_disable = &GPIO3_6; gpio.h1r9_trigger_enable = &GPIO5_5; - ) + } +#endif /* rad1o LCD */ - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { gpio.lcd_cs = &GPIO4_12; /* P9_0 */ gpio.lcd_bl_en = &GPIO0_8; /* P1_1 */ gpio.lcd_reset = &GPIO5_17; /* P9_4 */ - ) + } +#endif /* Portapack */ - IF_EXPANSION_COMPATIBLE ( +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { gpio.io_stbx = &GPIO5_0; /* P2_0 */ gpio.addr = &GPIO5_1; /* P2_1 */ gpio.lcd_rdx = &GPIO5_4; /* P2_4 */ gpio.lcd_wrx = &GPIO1_10; /* P2_9 */ gpio.dir = &GPIO1_13; /* P2_13 */ - ) + } +#endif _platform_gpio = &gpio; diff --git a/firmware/common/platform_scu.c b/firmware/common/platform_scu.c index 9d3b0c5d..ef894745 100644 --- a/firmware/common/platform_scu.c +++ b/firmware/common/platform_scu.c @@ -42,34 +42,44 @@ const platform_scu_t* platform_scu(void) scu.PINMUX_LED1 = SCU_PINMUX_LED1; /* GPIO2[1] on P4_1 */ scu.PINMUX_LED2 = SCU_PINMUX_LED2; /* GPIO2[2] on P4_2 */ scu.PINMUX_LED3 = SCU_PINMUX_LED3; /* GPIO2[8] on P6_12 */ - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { scu.PINMUX_LED4 = (PB_6); /* GPIO5[26] on PB_6 */ - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { scu.PINMUX_LED4 = (P8_6); /* GPIO4[6] on P8_6 */ - ) + } +#endif /* Power Supply PinMux */ scu.PINMUX_EN1V8 = (P6_10); /* GPIO3[6] on P6_10 */ scu.PINMUX_EN1V2 = (P8_7); /* GPIO4[7] on P8_7 */ - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { scu.PINMUX_EN3V3_AUX_N = (P6_7); /* GPIO5[15] on P6_7 */ scu.PINMUX_EN3V3_OC_N = (P6_11); /* GPIO3[7] on P6_11 */ - ) + } +#endif /* GPIO Input PinMux */ scu.PINMUX_BOOT0 = (P1_1); /* GPIO0[8] on P1_1 */ scu.PINMUX_BOOT1 = (P1_2); /* GPIO0[9] on P1_2 */ - IF_NOT_HACKRF_ONE ( +#ifdef IS_NOT_HACKRF_ONE + if (IS_NOT_HACKRF_ONE) { scu.PINMUX_BOOT2 = (P2_8); /* GPIO5[7] on P2_8 */ scu.PINMUX_BOOT3 = (P2_9); /* GPIO1[10] on P2_9 */ - ) + } +#endif /* USB peripheral */ - IF_JAWBREAKER ( +#ifdef IS_JAWBREAKER + if (IS_JAWBREAKER) { scu.PINMUX_USB_LED0 = (P6_8); scu.PINMUX_USB_LED1 = (P6_7); - ) + } +#endif /* SSP1 Peripheral PinMux */ scu.SSP1_CIPO = (P1_3); /* P1_3 */ @@ -79,25 +89,34 @@ const platform_scu_t* platform_scu(void) /* CPLD JTAG interface */ scu.PINMUX_CPLD_TCK = (P6_1); /* GPIO3[ 0] */ - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { scu.PINMUX_FPGA_CRESET = (P5_2); /* GPIO2[11] on P5_2 */ scu.PINMUX_FPGA_CDONE = (P4_10); /* GPIO5[14] */ scu.PINMUX_FPGA_SPI_CS = (P5_1); /* GPIO2[10] */ - ) - IF_NOT_PRALINE ( - scu.PINMUX_CPLD_TDO = (P9_5); /* GPIO5[18] */ - ) - IF_H1_OR_RAD1O ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { + scu.PINMUX_CPLD_TDO = (P9_5); /* GPIO5[18] */ + } +#endif +#ifdef IS_H1_OR_RAD1O + if (IS_H1_OR_RAD1O) { scu.PINMUX_CPLD_TMS = (P6_5); /* GPIO3[ 4] */ scu.PINMUX_CPLD_TDI = (P6_2); /* GPIO3[ 1] */ - ) - IF_JAWBREAKER ( + } +#endif +#ifdef IS_JAWBREAKER + if (IS_JAWBREAKER) { scu.PINMUX_CPLD_TMS = (P6_2); /* GPIO3[ 1] */ scu.PINMUX_CPLD_TDI = (P6_5); /* GPIO3[ 4] */ - ) + } +#endif /* CPLD SGPIO interface */ - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { scu.PINMUX_SGPIO0 = (P0_0); scu.PINMUX_SGPIO1 = (P0_1); scu.PINMUX_SGPIO2 = (P1_15); @@ -129,8 +148,10 @@ const platform_scu_t* platform_scu(void) scu.PINMUX_SGPIO12_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu.PINMUX_SGPIO14_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu.PINMUX_SGPIO15_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - ) - IF_NOT_PRALINE ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { scu.PINMUX_SGPIO0 = (P0_0); scu.PINMUX_SGPIO1 = (P0_1); scu.PINMUX_SGPIO2 = (P1_15); @@ -162,16 +183,20 @@ const platform_scu_t* platform_scu(void) scu.PINMUX_SGPIO12_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu.PINMUX_SGPIO14_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.PINMUX_SGPIO15_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - ) + } +#endif scu.TRIGGER_EN = (P4_8); /* GPIO5[12] on P4_8 */ /* MAX283x GPIO (XCVR_CTL) PinMux */ - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { scu.XCVR_RXHP = P8_1; /* GPIO[] on P8_1 */ scu.XCVR_B6 = P8_2; /* GPIO[] on P8_2 */ scu.XCVR_B7 = P9_3; /* GPIO[] on P9_3 */ - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { scu.XCVR_ENABLE = PE_1; /* GPIO7[1] on PE_1 */ scu.XCVR_RXENABLE = PE_2; /* GPIO7[2] on PE_2 */ scu.XCVR_CS = PD_14; /* GPIO6[28] on PD_14 */ @@ -184,8 +209,10 @@ const platform_scu_t* platform_scu(void) scu.XCVR_RXHP_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.XCVR_LD_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0 | SCU_CONF_EPD_EN_PULLDOWN | SCU_CONF_EPUN_DIS_PULLUP); - ) - IF_H1_OR_JAWBREAKER ( + } +#endif +#ifdef IS_H1_OR_JAWBREAKER + if (IS_H1_OR_JAWBREAKER) { scu.XCVR_ENABLE = P4_6; /* GPIO2[6] on P4_6 */ scu.XCVR_RXENABLE = P4_5; /* GPIO2[5] on P4_5 */ scu.XCVR_TXENABLE = P4_4; /* GPIO2[4] on P4_4 */ @@ -195,20 +222,26 @@ const platform_scu_t* platform_scu(void) scu.XCVR_RXENABLE_PINCFG = (SCU_GPIO_FAST); scu.XCVR_TXENABLE_PINCFG = (SCU_GPIO_FAST); scu.XCVR_CS_PINCFG = (SCU_GPIO_FAST); - ) + } +#endif /* MAX5864 SPI chip select (AD_CS) GPIO PinMux */ - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { scu.AD_CS = (PD_16); /* GPIO6[30] on PD_16 */ scu.AD_CS_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - ) - IF_NOT_PRALINE ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { scu.AD_CS = (P5_7); /* GPIO2[7] on P5_7 */ scu.AD_CS_PINCFG = (SCU_GPIO_FAST); - ) + } +#endif /* RFFC5071 GPIO serial interface PinMux */ - IF_H1_OR_JAWBREAKER ( +#ifdef IS_H1_OR_JAWBREAKER + if (IS_H1_OR_JAWBREAKER) { scu.MIXER_ENX = (P5_4); /* GPIO2[13] on P5_4 */ scu.MIXER_SCLK = (P2_6); /* GPIO5[6] on P2_6 */ scu.MIXER_SDATA = (P6_4); /* GPIO3[3] on P6_4 */ @@ -216,8 +249,10 @@ const platform_scu_t* platform_scu(void) scu.MIXER_SCLK_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.MIXER_SDATA_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { scu.MIXER_ENX = (P5_4); /* GPIO2[13] on P5_4 */ scu.MIXER_SCLK = (P9_5); /* GPIO5[18] on P9_5 */ scu.MIXER_SDATA = (P9_2); /* GPIO4[14] on P9_2 */ @@ -227,8 +262,10 @@ const platform_scu_t* platform_scu(void) scu.MIXER_SCLK_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.MIXER_SDATA_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu.MIXER_LD_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - ) - IF_RAD1O ( + } +#endif +#ifdef IS_RAD1O + if (IS_RAD1O) { scu.VCO_CE = (P5_4); /* GPIO2[13] on P5_4 */ scu.VCO_SCLK = (P2_6); /* GPIO5[6] on P2_6 */ scu.VCO_SDATA = (P6_4); /* GPIO3[3] on P6_4 */ @@ -236,23 +273,32 @@ const platform_scu_t* platform_scu(void) scu.VCO_MUX = (PB_5); /* GPIO5[25] on PB_5 */ scu.MIXER_EN = (P6_8); /* GPIO5[16] on P6_8 */ scu.SYNT_RFOUT_EN = (P6_9); /* GPIO3[5] on P6_9 */ - ) + } +#endif /* RF LDO control */ - IF_JAWBREAKER ( +#ifdef IS_JAWBREAKER + if (IS_JAWBREAKER) { scu.RF_LDO_ENABLE = (P5_0); /* GPIO2[9] on P5_0 */ - ) + } +#endif /* RF supply (VAA) control */ - IF_HACKRF_ONE ( +#ifdef IS_HACKRF_ONE + if (IS_HACKRF_ONE) { scu.NO_VAA_ENABLE = P5_0; /* GPIO2[9] on P5_0 */ - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { scu.NO_VAA_ENABLE = P8_1; /* GPIO4[1] on P8_1 */ - ) - IF_RAD1O ( + } +#endif +#ifdef IS_RAD1O + if (IS_RAD1O) { scu.VAA_ENABLE = P5_0; /* GPIO2[9] on P5_0 */ - ) + } +#endif /* SPI flash */ scu.SSP0_CIPO = (P3_6); @@ -263,7 +309,8 @@ const platform_scu_t* platform_scu(void) scu.FLASH_WP = (P3_5); /* GPIO1[15] on P3_5 */ /* RF switch control */ - IF_HACKRF_ONE ( +#ifdef IS_HACKRF_ONE + if (IS_HACKRF_ONE) { scu.HP = P4_0; /* GPIO2[0] on P4_0 */ scu.LP = P5_1; /* GPIO2[10] on P5_1 */ scu.TX_MIX_BP = P5_2; /* GPIO2[11] on P5_2 */ @@ -277,8 +324,10 @@ const platform_scu_t* platform_scu(void) scu.AMP_BYPASS = P2_10; /* GPIO0[14] on P2_10 */ scu.RX_AMP = P2_11; /* GPIO1[11] on P2_11 */ scu.NO_RX_AMP_PWR = P2_12; /* GPIO1[12] on P2_12 */ - ) - IF_RAD1O ( + } +#endif +#ifdef IS_RAD1O + if (IS_RAD1O) { scu.BY_AMP = P1_7; /* GPIO1[0] on P1_7 */ scu.BY_AMP_N = P2_5; /* GPIO5[5] on P2_5 */ scu.TX_RX = P2_10; /* GPIO0[14] on P2_10 */ @@ -289,8 +338,10 @@ const platform_scu_t* platform_scu(void) scu.LOW_HIGH_FILT_N = P5_3; /* GPIO2[12] on P5_3 */ scu.TX_AMP = P5_6; /* GPIO2[15] on P5_6 */ scu.RX_LNA = P6_7; /* GPIO5[15] on P6_7 */ - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { scu.TX_EN = P6_5; /* GPIO3[4] on P6_5 */ scu.MIX_EN_N = P6_3; /* GPIO3[2] on P6_3 */ scu.MIX_EN_N_R1_0 = P2_6; /* GPIO5[6] on P2_6 */ @@ -298,10 +349,12 @@ const platform_scu_t* platform_scu(void) scu.RF_AMP_EN = PA_2; /* GPIO4[9] on PA_2 */ scu.ANT_BIAS_EN_N = P2_12; /* GPIO1[12] on P2_12 */ scu.ANT_BIAS_OC_N = P2_11; /* GPIO1[11] on P2_11 */ - ) + } +#endif /* Praline */ - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { scu.P2_CTRL0 = (PE_3); /* GPIO7[3] on PE_3 */ scu.P2_CTRL1 = (PE_4); /* GPIO7[4] on PE_4 */ scu.P1_CTRL0 = (P2_10); /* GPIO0[14] on P2_10 */ @@ -323,10 +376,12 @@ const platform_scu_t* platform_scu(void) scu.TRIGGER_IN_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.TRIGGER_OUT_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.PPS_OUT_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - ) + } +#endif /* HackRF One r9 */ - IF_H1_R9 ( +#ifdef IS_H1_R9 + if (IS_H1_R9) { scu.H1R9_CLKIN_EN = P6_7; /* GPIO5[15] on P6_7 */ scu.H1R9_CLKOUT_EN = P1_2; /* GPIO0[9] on P1_2 = has boot pull-down; */ scu.H1R9_MCU_CLK_EN = P1_1; /* GPIO0[8] on P1_1 = has boot pull-up; */ @@ -335,10 +390,12 @@ const platform_scu_t* platform_scu(void) scu.H1R9_EN1V8 = P5_0; /* GPIO2[9] on P5_0 */ scu.H1R9_NO_VAA_EN = P6_10; /* GPIO3[6] on P6_10 */ scu.H1R9_TRIGGER_EN = P2_5; /* GPIO5[5] on P2_5 */ - ) + } +#endif /* Expansion headers */ - IF_EXPANSION_COMPATIBLE ( +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { scu.PINMUX_PP_D0 = (P7_0); /* GPIO3[8] */ scu.PINMUX_PP_D1 = (P7_1); /* GPIO3[9] */ scu.PINMUX_PP_D2 = (P7_2); /* GPIO3[10] */ @@ -378,7 +435,8 @@ const platform_scu_t* platform_scu(void) scu.PINMUX_GPIO3_13 = (P7_5); /* GPIO3[13] */ scu.PINMUX_GPIO3_14 = (P7_6); /* GPIO3[14] */ scu.PINMUX_GPIO3_15 = (P7_7); /* GPIO3[15] */ - ) + } +#endif scu.PINMUX_ISP = (P2_7); /* GPIO0[7] */ diff --git a/firmware/common/radio.c b/firmware/common/radio.c index a4d41c68..a98587f4 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -195,18 +195,22 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank) case TRANSCEIVER_MODE_SS: n = compute_resample_log(rate / SR_FP_ONE_HZ, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX]) { - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { fpga_set_tx_interpolation_ratio(&fpga, n); - ) + } +#endif radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX] = n; } break; default: n = compute_resample_log(rate / SR_FP_ONE_HZ, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX]) { - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { fpga_set_rx_decimation_ratio(&fpga, n); - ) + } +#endif radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX] = n; } } @@ -391,7 +395,8 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) if (requested_lo != RADIO_UNSET) { freq_lo = mixer_set_frequency(&mixer, freq_lo, false); } - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { if (requested_rotation != RADIO_UNSET) { rotation = requested_rotation; } @@ -407,10 +412,13 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) default: rotation = 0; } - ) - IF_NOT_PRALINE ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { rotation = 0; - ) + } +#endif /* Handle requested RF (auto-tune). */ if (requested_rf != RADIO_UNSET) { @@ -420,7 +428,8 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) freq_rf = restrict_rf(requested_rf, img_reject); /* Look up settings appropriate for requested RF. */ - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { const tune_config_t* tune_config = select_tune_config(opmode, freq_rf); if (requested_rotation == RADIO_UNSET) { @@ -436,15 +445,18 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) } } high_lo = tune_config->high_lo; - ) - IF_NOT_PRALINE ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { /* Use graduated or fixed IF on older platforms. */ if (requested_if == RADIO_UNSET) { freq_if = select_graduated_if(freq_rf, img_reject); } high_lo = (img_reject == RF_PATH_FILTER_LOW_PASS); analog_rf = freq_rf; - ) + } +#endif /* Compute precise LO. This is done first because the mixer LO is set in coarse steps. */ if (requested_lo == RADIO_UNSET) { @@ -500,9 +512,11 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) changed |= (1 << RADIO_IMAGE_REJECT); } if ((rotation != applied_rotation) && (rotation != RADIO_UNSET)) { - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { fpga_set_rx_quarter_shift_mode(&fpga, rotation >> 30); - ) + } +#endif radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION] = rotation; changed |= (1 << RADIO_ROTATION); } @@ -567,7 +581,8 @@ static uint32_t radio_update_bandwidth(radio_t* const radio, uint64_t* bank) opmode = radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE]; } - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { /* Praline legacy mode always sets baseband bandwidth automatically. */ (void) bank; uint32_t lpf_bandwidth = auto_bandwidth(radio, opmode); @@ -613,8 +628,10 @@ static uint32_t radio_update_bandwidth(radio_t* const radio, uint64_t* bank) hpf_bandwidth; changed |= (1 << RADIO_XCVR_RX_HPF); } - ) - IF_NOT_PRALINE ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { uint64_t lpf_bandwidth; lpf_bandwidth = bank[RADIO_XCVR_TX_LPF]; if (lpf_bandwidth == RADIO_UNSET) { @@ -653,7 +670,8 @@ static uint32_t radio_update_bandwidth(radio_t* const radio, uint64_t* bank) (1 << RADIO_BB_BANDWIDTH_TX) | (1 << RADIO_XCVR_TX_LPF) | (1 << RADIO_XCVR_RX_LPF)); } - ) + } +#endif return changed; } @@ -789,7 +807,8 @@ static uint32_t radio_update_trigger(radio_t* const radio, uint64_t* bank) static uint32_t radio_update_dc_block(radio_t* const radio, uint64_t* bank) { - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { const uint64_t requested = bank[RADIO_DC_BLOCK]; bool enable = requested; @@ -801,7 +820,8 @@ static uint32_t radio_update_dc_block(radio_t* const radio, uint64_t* bank) fpga_set_rx_dc_block_enable(&fpga, enable); radio->config[RADIO_BANK_APPLIED][RADIO_DC_BLOCK] = enable; return (1 << RADIO_DC_BLOCK); - ) + } +#endif (void) radio; (void) bank; diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index a757eceb..5043bfe8 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -294,19 +294,27 @@ static void switchctrl_set_rad1o(rf_path_t* const rf_path, uint8_t ctrl) static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) { - IF_JAWBREAKER ( +#ifdef IS_JAWBREAKER + if (IS_JAWBREAKER) { (void) rf_path; mixer_set_gpo(&mixer, gpo); - ) - IF_HACKRF_ONE ( + } +#endif +#ifdef IS_HACKRF_ONE + if (IS_HACKRF_ONE) { switchctrl_set_hackrf_one(rf_path, gpo); - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { switchctrl_set_praline(rf_path, gpo); - ) - IF_RAD1O ( + } +#endif +#ifdef IS_RAD1O + if (IS_RAD1O) { switchctrl_set_rad1o(rf_path, gpo); - ) + } +#endif } void rf_path_pin_setup(rf_path_t* const rf_path) @@ -319,7 +327,8 @@ void rf_path_pin_setup(rf_path_t* const rf_path) const platform_scu_t* scu = platform_scu(); #endif - IF_HACKRF_ONE ( +#ifdef IS_HACKRF_ONE + if (IS_HACKRF_ONE) { /* Configure RF switch control signals */ // clang-format off scu_pinmux(scu->HP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); @@ -334,7 +343,8 @@ void rf_path_pin_setup(rf_path_t* const rf_path) scu_pinmux(scu->RX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(scu->NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); // clang-format on - IF_H1_R9 ( + #ifdef IS_H1_R9 + if (IS_H1_R9) { scu_pinmux(scu->H1R9_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux( scu->H1R9_NO_ANT_PWR, @@ -344,13 +354,16 @@ void rf_path_pin_setup(rf_path_t* const rf_path) scu_pinmux( scu->H1R9_NO_VAA_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - ) - IF_NOT_H1_R9 ( + } + #endif + #ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { scu_pinmux(scu->TX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(scu->RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); gpio_output(rf_path->gpio_tx); scu_pinmux(scu->NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - ) + } + #endif /* * Safe (initial) switch settings turn off both amplifiers and antenna port @@ -371,8 +384,10 @@ void rf_path_pin_setup(rf_path_t* const rf_path) gpio_output(rf_path->gpio_no_tx_amp_pwr); gpio_output(rf_path->gpio_mix_bypass); gpio_output(rf_path->gpio_rx); - ) - IF_RAD1O ( + } +#endif +#ifdef IS_RAD1O + if (IS_RAD1O) { /* Configure RF switch control signals */ // clang-format off scu_pinmux(scu->BY_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); @@ -409,9 +424,11 @@ void rf_path_pin_setup(rf_path_t* const rf_path) gpio_output(rf_path->gpio_low_high_filt_n); gpio_output(rf_path->gpio_tx_amp); gpio_output(rf_path->gpio_rx_lna); - ) + } +#endif - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { /* Configure RF switch control signals */ scu_pinmux(scu->TX_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); board_rev_t rev = detected_revision(); @@ -442,7 +459,8 @@ void rf_path_pin_setup(rf_path_t* const rf_path) gpio_output(rf_path->gpio_mix_en_n); gpio_output(rf_path->gpio_lpf_en); gpio_output(rf_path->gpio_rf_amp_en); - ) + } +#endif } void rf_path_init(rf_path_t* const rf_path) @@ -455,14 +473,20 @@ void rf_path_init(rf_path_t* const rf_path) max283x_setup(&max283x); max283x_start(&max283x); - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { mixer_setup(&mixer, MAX2871_VARIANT); - ) - IF_NOT_RAD1O ( - IF_NOT_HACKRF_ONE ( + } +#endif +#ifdef IS_NOT_RAD1O + if (IS_NOT_RAD1O) { + #ifdef IS_NOT_HACKRF_ONE + if (IS_NOT_HACKRF_ONE) { mixer_setup(&mixer, RFFC5071_VARIANT); - ) - ) + } + #endif + } +#endif rf_path->switchctrl = SWITCHCTRL_SAFE; } diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index fbeb2d93..ab0717ea 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -113,12 +113,14 @@ void rffc5071_setup(rffc5071_driver_t* const drv) gpio_set(drv->gpio_reset); gpio_output(drv->gpio_reset); - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { /* Configure mixer PLL lock detect pin */ const platform_scu_t* scu = platform_scu(); scu_pinmux(scu->MIXER_LD, scu->MIXER_LD_PINCFG); gpio_input(drv->gpio_ld); - ) + } +#endif rffc5071_init(drv); @@ -136,9 +138,11 @@ void rffc5071_setup(rffc5071_driver_t* const drv) set_RFFC5071_FULLD(drv, 0); set_RFFC5071_MODE(drv, 1); - IF_H1_OR_PRALINE ( +#ifdef IS_H1_OR_PRALINE + if (IS_H1_OR_PRALINE) { set_RFFC5071_LOCK(drv, 1); - ) + } +#endif /* Enable reference oscillator standby */ set_RFFC5071_REFST(drv, 1); @@ -181,14 +185,18 @@ void rffc5071_lock_test(rffc5071_driver_t* const drv) bool rffc5071_check_lock(rffc5071_driver_t* const drv) { - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { return gpio_read(drv->gpio_ld); - ) - IF_NOT_PRALINE ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { set_RFFC5071_READSEL(drv, 0b0001); rffc5071_regs_commit(drv); return !!(rffc5071_reg_read(drv, RFFC5071_READBACK_REG) & 0x8000); - ) + } +#endif return false; } @@ -369,9 +377,11 @@ bool rffc5071_poll_ld(rffc5071_driver_t* const drv, uint8_t* prelock_state) // // For all other boards we'll just return true to avoid a situation where a // a caller is waiting for a lock signal that will never be detected. - IF_NOT_PRALINE ( + #ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { return true; - ) + } + #endif // The RFFC5072 can be configured to output PLL lock status on // GPO4. The lock detect signal is produced by a window detector diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index 86b6c58e..4aa98265 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -57,24 +57,30 @@ void sgpio_configure_pin_functions(sgpio_config_t* const config) scu_pinmux(scu->PINMUX_SGPIO14, scu->PINMUX_SGPIO14_PINCFG); /* GPIO5[13] */ scu_pinmux(scu->PINMUX_SGPIO15, scu->PINMUX_SGPIO15_PINCFG); /* GPIO5[14] */ - IF_H1_R9 ( +#ifdef IS_H1_R9 + if (IS_H1_R9) { scu_pinmux( scu->H1R9_TRIGGER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[5] */ - ) - IF_NOT_H1_R9 ( + } +#endif +#ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { scu_pinmux( scu->TRIGGER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[12] */ - ) + } +#endif sgpio_cpld_set_mixer_invert(config, 0); gpio_output(config->gpio_q_invert); - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { trigger_enable(false); gpio_output(config->gpio_trigger_enable); - ) + } +#endif } void sgpio_set_slice_mode(sgpio_config_t* const config, const bool multi_slice) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index dbedddf3..a1466393 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -269,7 +269,8 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv) SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /* not connected, but: PLL B int mode */ }; - IF_H1_R9 ( +#ifdef IS_H1_R9 + if (IS_H1_R9) { data[1] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA); @@ -280,8 +281,10 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv) data[4] = SI5351C_CLK_POWERDOWN; data[5] = SI5351C_CLK_POWERDOWN; data[6] = SI5351C_CLK_POWERDOWN; - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { /* CLK0: AFE_CLK */ data[1] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | @@ -311,7 +314,8 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv) /* CLK2: MCU_CLK */ data[3] = SI5351C_CLK_POWERDOWN; } - ) + } +#endif si5351c_write(drv, data, sizeof(data)); } @@ -329,7 +333,8 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) uint8_t clkout = 3; uint8_t value = 0; - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | SI5351C_CLK_ENABLE(4) | SI5351C_CLK_ENABLE(5) | SI5351C_CLK_DISABLE(6) | SI5351C_CLK_DISABLE(7); @@ -339,22 +344,27 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) } else { value |= SI5351C_CLK_DISABLE(2); } - ) - IF_NOT_PRALINE ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | SI5351C_CLK_ENABLE(2) | SI5351C_CLK_ENABLE(4) | SI5351C_CLK_ENABLE(5) | SI5351C_CLK_DISABLE(6) | SI5351C_CLK_DISABLE(7); /* HackRF One r9 has only three clock generator outputs. */ - IF_H1_R9 ( + #ifdef IS_H1_R9 + if (IS_H1_R9) { clkout = 2; value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | SI5351C_CLK_DISABLE(3) | SI5351C_CLK_DISABLE(4) | SI5351C_CLK_DISABLE(5) | SI5351C_CLK_DISABLE(6) | SI5351C_CLK_DISABLE(7); - ) - ) + } + #endif + } +#endif value |= (clkout_enabled) ? SI5351C_CLK_ENABLE(clkout) : SI5351C_CLK_DISABLE(clkout); @@ -362,14 +372,16 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) si5351c_write(drv, data, sizeof(data)); outputs_disabled = value; - IF_H1_R9 ( +#ifdef IS_H1_R9 + if (IS_H1_R9) { const platform_gpio_t* gpio = platform_gpio(); if (clkout_enabled) { gpio_set(gpio->h1r9_clkout_en); } else { gpio_clear(gpio->h1r9_clkout_en); } - ) + } +#endif } void si5351c_set_int_mode( @@ -399,7 +411,8 @@ void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_source return; } si5351c_disable_all_outputs(drv); - IF_H1_R9 ( +#ifdef IS_H1_R9 + if (IS_H1_R9) { /* * HackRF One r9 always uses PLL A on the XTAL input * but externally switches that input to CLKIN. @@ -410,10 +423,13 @@ void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_source } else { gpio_clear(platform_gpio()->h1r9_clkin_en); } - ) - IF_NOT_H1_R9 ( + } +#endif +#ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { si5351c_configure_pll_sources(drv, source); - ) + } +#endif si5351c_configure_pll_multisynth(drv, source); active_clock_source = source; si5351c_reset_pll(drv, SI5351C_PLL_BOTH); @@ -468,7 +484,8 @@ void si5351c_init(si5351c_driver_t* const drv) selftest.report.pass = false; } - IF_H1_R9 ( +#ifdef IS_H1_R9 + if (IS_H1_R9) { const platform_gpio_t* gpio = platform_gpio(); const platform_scu_t* scu = platform_scu(); @@ -486,7 +503,8 @@ void si5351c_init(si5351c_driver_t* const drv) scu_pinmux(scu->H1R9_MCU_CLK_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); gpio_clear(gpio->h1r9_mcu_clk_en); gpio_output(gpio->h1r9_mcu_clk_en); - ) + } +#endif } /* diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 347be0ae..9e3c41ba 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -38,10 +38,12 @@ static fp_40_24_t max_bypass_freq = FP_MHZ(2740); void tuning_setup(void) { - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { min_bypass_freq = FP_MHZ(2320); max_bypass_freq = FP_MHZ(2580); - ) + } +#endif } fp_40_24_t select_graduated_if(fp_40_24_t freq_rf, rf_path_filter_t img_reject) @@ -50,13 +52,17 @@ fp_40_24_t select_graduated_if(fp_40_24_t freq_rf, rf_path_filter_t img_reject) switch (img_reject) { case RF_PATH_FILTER_LOW_PASS: - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { freq_if = FP_MHZ(2300); - ) - IF_NOT_RAD1O ( + } +#endif +#ifdef IS_NOT_RAD1O + if (IS_NOT_RAD1O) { /* IF is graduated from 2650 MHz to 2340 MHz */ freq_if = FP_MHZ(2650) - (freq_rf / 7); - ) + } +#endif break; case RF_PATH_FILTER_HIGH_PASS: if (freq_rf < MID1_HP_FREQ) { diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 97a04737..653a477a 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -443,9 +443,10 @@ int main(void) } delay_us_at_mhz(10000, 96); pin_setup(); - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { enable_3v3aux_power(); -#if !defined(DFU_MODE) && !defined(RAM_MODE) + #if !defined(DFU_MODE) && !defined(RAM_MODE) enable_1v2_power(); enable_rf_power(); /* @@ -453,60 +454,77 @@ int main(void) * which is enabled when 1V2FPGA is turned on. */ clock_gen_init(); + #endif + } #endif - ) - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { enable_1v8_power(); - IF_NOT_RAD1O ( + #ifdef IS_NOT_RAD1O + if (IS_NOT_RAD1O) { /* * On rad1o, the clock generator power supply comes from the RF supply * which is enabled later. On H1 and Jawbreaker, the clock generator is * on the main 3V3 supply. */ clock_gen_init(); - ) - ) + } + #endif + } +#endif tuning_setup(); - IF_HACKRF_ONE ( +#ifdef IS_HACKRF_ONE + if (IS_HACKRF_ONE) { // Set up mixer before enabling RF power, because its // GPO is used to control the antenna bias tee. mixer_setup(&mixer, RFFC5071_VARIANT); - ) - IF_H1_OR_RAD1O ( + } +#endif +#ifdef IS_H1_OR_RAD1O + if (IS_H1_OR_RAD1O) { enable_rf_power(); - ) - IF_RAD1O ( + } +#endif +#ifdef IS_RAD1O + if (IS_RAD1O) { clock_gen_init(); - ) + } +#endif cpu_clock_init(); /* Wake the M0 */ ipc_halt_m0(); ipc_start_m0((uint32_t) &__ram_m0_start__); - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { if (!cpld_jtag_sram_load(&jtag_cpld)) { halt_and_flash(6000000); } - ) - IF_PRALINE ( -#if defined(DFU_MODE) || defined(RAM_MODE) + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { + #if defined(DFU_MODE) || defined(RAM_MODE) selftest.fpga_image_load = SKIPPED; selftest.report.pass = false; -#else + #else fpga_image_load(&fpga_loader, 0); -#endif + #endif delay_us_at_mhz(100, 204); fpga_spi_selftest(); fpga_sgpio_selftest(); - ) + } +#endif radio.update_cb = radio_changed; radio_init(&radio); - IF_EXPANSION_COMPATIBLE ( +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { portapack_init(); - ) + } +#endif #ifndef DFU_MODE usb_set_descriptor_by_serial_number(); @@ -515,22 +533,30 @@ int main(void) usb_set_configuration_changed_cb(usb_configuration_changed); usb_peripheral_reset(); - IF_HACKRF_ONE ( +#ifdef IS_HACKRF_ONE + if (IS_HACKRF_ONE) { memcpy(&usb_device, &usb_device_hackrf_one, sizeof(usb_device_hackrf_one)); - ) - IF_JAWBREAKER ( + } +#endif +#ifdef IS_JAWBREAKER + if (IS_JAWBREAKER) { memcpy(&usb_device, &usb_device_jawbreaker, sizeof(usb_device_jawbreaker)); - ) - IF_RAD1O ( + } +#endif +#ifdef IS_RAD1O + if (IS_RAD1O) { memcpy(&usb_device, &usb_device_rad1o, sizeof(usb_device_rad1o)); - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { memcpy(&usb_device, &usb_device_praline, sizeof(usb_device_praline)); - ) + } +#endif usb_device_init(0, &usb_device); usb_queue_init(&usb_endpoint_control_out_queue); @@ -553,9 +579,11 @@ int main(void) rffc5071_lock_test(&mixer.rffc5071); #endif - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { fpga_if_xcvr_selftest(); - ) + } +#endif if (da7219_detect()) { operacake_skip_i2c_address(DA7219_ADDRESS); @@ -602,9 +630,11 @@ int main(void) sweep_mode(request.seq); break; case TRANSCEIVER_MODE_CPLD_UPDATE: - IF_NOT_PRALINE ( +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { cpld_update(); - ) + } +#endif break; default: break; diff --git a/firmware/hackrf_usb/usb_api_board_info.c b/firmware/hackrf_usb/usb_api_board_info.c index eb91e5c9..393b102d 100644 --- a/firmware/hackrf_usb/usb_api_board_info.c +++ b/firmware/hackrf_usb/usb_api_board_info.c @@ -131,7 +131,8 @@ usb_request_status_t usb_vendor_request_reset( if (stage == USB_TRANSFER_STAGE_SETUP) { pin_shutdown(); clock_gen_shutdown(); - IF_H1_R9 ( +#ifdef IS_H1_R9 + if (IS_H1_R9) { /* * Set boot pins as inputs so that the bootloader reads them * correctly after the reset. @@ -140,7 +141,8 @@ usb_request_status_t usb_vendor_request_reset( gpio_input(gpio->h1r9_mcu_clk_en); gpio_input(gpio->h1r9_clkout_en); gpio_input(gpio->h1r9_rx); - ) + } +#endif wwdt_reset(100000); diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index bf7e4985..d17a87d8 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -142,13 +142,16 @@ usb_request_status_t usb_vendor_request_write_rffc5071( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { (void) endpoint; (void) stage; return USB_REQUEST_STATUS_STALL; - ) + } +#endif - IF_NOT_RAD1O ( +#ifdef IS_NOT_RAD1O + if (IS_NOT_RAD1O) { if (stage == USB_TRANSFER_STAGE_SETUP) { if (endpoint->setup.index < RFFC5071_NUM_REGS) { rffc5071_reg_write( @@ -161,20 +164,24 @@ usb_request_status_t usb_vendor_request_write_rffc5071( return USB_REQUEST_STATUS_STALL; } return USB_REQUEST_STATUS_OK; - ) + } +#endif } usb_request_status_t usb_vendor_request_read_rffc5071( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { (void) endpoint; (void) stage; return USB_REQUEST_STATUS_STALL; - ) + } +#endif - IF_NOT_RAD1O ( +#ifdef IS_NOT_RAD1O + if (IS_NOT_RAD1O) { uint16_t value; if (stage == USB_TRANSFER_STAGE_SETUP) { if (endpoint->setup.index < RFFC5071_NUM_REGS) { @@ -195,7 +202,8 @@ usb_request_status_t usb_vendor_request_read_rffc5071( return USB_REQUEST_STATUS_STALL; } return USB_REQUEST_STATUS_OK; - ) + } +#endif } usb_request_status_t usb_vendor_request_set_clkout_enable( @@ -287,7 +295,8 @@ usb_request_status_t usb_vendor_request_write_fpga_reg( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { - IF_PRALINE ( + #ifdef IS_PRALINE + if (IS_PRALINE) { if (stage == USB_TRANSFER_STAGE_SETUP) { fpga_reg_write( &fpga, @@ -296,7 +305,8 @@ usb_request_status_t usb_vendor_request_write_fpga_reg( usb_transfer_schedule_ack(endpoint->in); } return USB_REQUEST_STATUS_OK; - ) + } + #endif return USB_REQUEST_STATUS_STALL; } @@ -305,7 +315,8 @@ usb_request_status_t usb_vendor_request_read_fpga_reg( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { - IF_PRALINE ( + #ifdef IS_PRALINE + if (IS_PRALINE) { if (stage == USB_TRANSFER_STAGE_SETUP) { const uint8_t value = fpga_reg_read(&fpga, endpoint->setup.index); endpoint->buffer[0] = value; @@ -318,7 +329,8 @@ usb_request_status_t usb_vendor_request_read_fpga_reg( usb_transfer_schedule_ack(endpoint->out); } return USB_REQUEST_STATUS_OK; - ) + } + #endif return USB_REQUEST_STATUS_STALL; } diff --git a/firmware/hackrf_usb/usb_api_selftest.c b/firmware/hackrf_usb/usb_api_selftest.c index e25f387a..403f3753 100644 --- a/firmware/hackrf_usb/usb_api_selftest.c +++ b/firmware/hackrf_usb/usb_api_selftest.c @@ -82,12 +82,15 @@ void generate_selftest_report(void) { char* s = &selftest.report.msg[0]; size_t c = sizeof(selftest.report.msg); - IF_RAD1O ( +#ifdef IS_RAD1O + if (IS_RAD1O) { append(&s, &c, "Mixer: MAX2871, ID: "); append(&s, &c, itoa(selftest.mixer_id, 10)); append(&s, &c, "\n"); - ) - IF_NOT_RAD1O ( + } +#endif +#ifdef IS_NOT_RAD1O + if (IS_NOT_RAD1O) { append(&s, &c, "Mixer: RFFC5072, ID: "); append(&s, &c, itoa(selftest.mixer_id >> 3, 10)); append(&s, &c, ", Rev: "); @@ -104,7 +107,8 @@ void generate_selftest_report(void) append(&s, &c, " (FAIL)"); } append(&s, &c, "\n"); - ) + } +#endif append(&s, &c, "Clock: Si5351"); append(&s, &c, ", Rev: "); @@ -113,19 +117,26 @@ void generate_selftest_report(void) append(&s, &c, selftest.si5351_readback_ok ? "OK" : "FAIL"); append(&s, &c, "\n"); - IF_PRALINE ( +#ifdef IS_PRALINE + if (IS_PRALINE) { append(&s, &c, "Transceiver: MAX2831, RSSI mux test: "); append(&s, &c, selftest.max2831_mux_test_ok ? "PASS" : "FAIL"); append(&s, &c, "\n"); - ) - IF_NOT_PRALINE ( + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { append(&s, &c, "Transceiver: "); - IF_H1_R9 ( + #ifdef IS_H1_R9 + if (IS_H1_R9) { append(&s, &c, "MAX2839"); - ) - IF_NOT_H1_R9 ( + } + #endif + #ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { append(&s, &c, "MAX2837"); - ) + } + #endif append(&s, &c, ", readback success: "); append(&s, &c, itoa(selftest.max283x_readback_register_count, 10)); append(&s, &c, "/"); @@ -140,8 +151,10 @@ void generate_selftest_report(void) itoa(selftest.max283x_readback_expected_value, 10)); } append(&s, &c, "\n"); - ) - IF_PRALINE ( + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { append(&s, &c, "FPGA configuration: "); append(&s, &c, test_result_to_str(selftest.fpga_image_load)); append(&s, &c, "\n"); @@ -173,7 +186,8 @@ void generate_selftest_report(void) append(&s, &c, itoa(m->avg_mag_sq_q, 10)); append(&s, &c, "\n"); } - ) + } +#endif } usb_request_status_t usb_vendor_request_read_selftest( From f7a3d434075d0fa5cdedcc546e2a426c3a628f30 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 14 Apr 2026 11:52:21 +0100 Subject: [PATCH 131/238] Use IS macros for all conditional compilation. --- firmware/common/cpld_jtag.c | 13 ++++---- firmware/common/cpld_jtag.h | 5 +-- firmware/common/hackrf_core.c | 32 ++++++++----------- firmware/common/hackrf_core.h | 13 ++++---- firmware/common/hackrf_ui.c | 8 ++--- firmware/common/max283x.c | 22 ++++++------- firmware/common/max283x.h | 20 ++++++------ firmware/common/max2871.c | 5 +-- firmware/common/mixer.c | 9 +++--- firmware/common/mixer.h | 13 +++++--- firmware/common/operacake_sctimer.c | 12 +++---- firmware/common/platform_gpio.h | 33 +++++++++---------- firmware/common/platform_scu.h | 40 +++++++++++++----------- firmware/common/radio.c | 6 ++-- firmware/common/rf_path.c | 21 +++++-------- firmware/common/rf_path.h | 12 ++++--- firmware/common/rffc5071.c | 9 ++---- firmware/common/rffc5071.h | 5 +-- firmware/common/selftest.h | 8 +++-- firmware/common/sgpio.c | 2 +- firmware/common/sgpio.h | 3 +- firmware/common/si5351c.c | 7 ++--- firmware/common/tune_config.h | 4 ++- firmware/hackrf_usb/hackrf_usb.c | 32 ++++++++++--------- firmware/hackrf_usb/usb_api_board_info.c | 3 +- firmware/hackrf_usb/usb_api_register.c | 7 ++--- firmware/hackrf_usb/usb_api_register.h | 4 ++- firmware/hackrf_usb/usb_api_selftest.c | 11 ++++--- firmware/hackrf_usb/usb_descriptor.c | 34 ++++++++------------ firmware/hackrf_usb/usb_descriptor.h | 16 +++++----- firmware/hackrf_usb/usb_device.c | 9 +++--- firmware/hackrf_usb/usb_device.h | 10 +++--- 32 files changed, 212 insertions(+), 216 deletions(-) diff --git a/firmware/common/cpld_jtag.c b/firmware/common/cpld_jtag.c index b277b462..034ba196 100644 --- a/firmware/common/cpld_jtag.c +++ b/firmware/common/cpld_jtag.c @@ -19,17 +19,16 @@ * Boston, MA 02110-1301, USA. */ -#if !defined(PRALINE) || defined(UNIVERSAL) - #include -#endif - #include "cpld_jtag.h" + #include "platform_detect.h" -#if !defined(PRALINE) || defined(UNIVERSAL) + +#ifdef IS_NOT_PRALINE + #include #include "xapp058/micro.h" #endif -#if !defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_NOT_PRALINE static refill_buffer_cb refill_buffer; static uint32_t xsvf_buffer_len, xsvf_pos; static unsigned char* xsvf_buffer; @@ -102,7 +101,7 @@ void cpld_jtag_release(jtag_t* const jtag) #endif } -#if !defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_NOT_PRALINE /* return 0 if success else return error code see xsvfExecute() */ int cpld_jtag_program( jtag_t* const jtag, diff --git a/firmware/common/cpld_jtag.h b/firmware/common/cpld_jtag.h index 939e5d94..0994c858 100644 --- a/firmware/common/cpld_jtag.h +++ b/firmware/common/cpld_jtag.h @@ -24,15 +24,16 @@ #include #include "gpio.h" +#include "platform_detect.h" typedef struct { gpio_t gpio_tck; -#if !defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_NOT_PRALINE gpio_t gpio_tms; gpio_t gpio_tdi; gpio_t gpio_tdo; #endif -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_EXPANSION_COMPATIBLE gpio_t gpio_pp_tms; gpio_t gpio_pp_tdo; #endif diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 0ac7ae65..d5679942 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -25,7 +25,10 @@ #include #include #include -#if !defined(RAD1O) + +#include "platform_detect.h" + +#ifdef IS_NOT_RAD1O #include #endif @@ -36,15 +39,14 @@ #include "i2c_lpc.h" #include "max283x.h" #include "max5864_target.h" -#include "platform_detect.h" #include "platform_gpio.h" #include "platform_scu.h" #include "spi_bus.h" #include "w25q80bv_target.h" -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_EXPANSION_COMPATIBLE #include "portapack.h" #endif -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE #include "ice40_spi.h" #endif @@ -142,7 +144,7 @@ sgpio_config_t sgpio_config = { .slice_mode_multislice = true, }; -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE static ssp_config_t ssp_config_ice40_fpga = { .data_bits = SSP_DATA_8BITS, .spi_mode = SSP_CPOL_1_CPHA_1, @@ -786,7 +788,7 @@ void ssp1_set_mode_max5864(void) spi_bus_start(max5864.bus, &ssp_config_max5864); } -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE void ssp1_set_mode_ice40(void) { spi_bus_start(&spi_bus_ssp1, &ssp_config_ice40_fpga); @@ -1124,41 +1126,33 @@ void pin_setup(void) sgpio_configure_pin_functions(&sgpio_config); } -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE void enable_1v2_power(void) { - #ifdef IS_PRALINE if (IS_PRALINE) { gpio_set(platform_gpio()->gpio_1v2_enable); } - #endif } void disable_1v2_power(void) { - #ifdef IS_PRALINE if (IS_PRALINE) { gpio_clear(platform_gpio()->gpio_1v2_enable); } - #endif } void enable_3v3aux_power(void) { - #ifdef IS_PRALINE if (IS_PRALINE) { gpio_clear(platform_gpio()->gpio_3v3aux_enable_n); } - #endif } void disable_3v3aux_power(void) { - #ifdef IS_PRALINE if (IS_PRALINE) { gpio_set(platform_gpio()->gpio_3v3aux_enable_n); } - #endif } #endif @@ -1198,7 +1192,7 @@ void disable_1v8_power(void) #endif } -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE static inline void enable_rf_power_hackrf_one(void) { const platform_gpio_t* gpio = platform_gpio(); @@ -1226,7 +1220,7 @@ static inline void disable_rf_power_hackrf_one(void) } #endif -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE static inline void enable_rf_power_praline(void) { gpio_clear(platform_gpio()->vaa_disable); @@ -1241,7 +1235,7 @@ static inline void disable_rf_power_praline(void) } #endif -#if defined(RAD1O) +#ifdef IS_RAD1O static inline void enable_rf_power_rad1o(void) { gpio_set(platform_gpio()->vaa_enable); @@ -1379,7 +1373,7 @@ void halt_and_flash(const uint32_t duration) } } -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE void p1_ctrl_set(const p1_ctrl_signal_t signal) { const platform_gpio_t* gpio = platform_gpio(); diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 93bc44c9..56221f6b 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -36,13 +36,14 @@ extern "C" { #include "max283x.h" #include "max5864.h" #include "mixer.h" +#include "platform_detect.h" // IWYU pragma: keep #include "radio.h" #include "rf_path.h" #include "sgpio.h" #include "si5351c.h" #include "spi_ssp.h" #include "w25q80bv.h" -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE #include "fpga.h" #include "ice40_spi.h" #endif @@ -52,7 +53,7 @@ extern si5351c_driver_t clock_gen; extern ssp_config_t ssp_config_w25q80bv; extern max283x_driver_t max283x; -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE extern ice40_spi_driver_t ice40; extern fpga_driver_t fpga; #endif @@ -71,14 +72,14 @@ void clock_gen_init(void); void clock_gen_shutdown(void); void ssp1_set_mode_max283x(void); void ssp1_set_mode_max5864(void); -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE void ssp1_set_mode_ice40(void); #endif void pin_shutdown(void); void pin_setup(void); -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE void enable_1v2_power(void); void disable_1v2_power(void); void enable_3v3aux_power(void); @@ -91,7 +92,7 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program); clock_source_t activate_best_clock_source(void); -#if defined(RAD1O) || defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) +#if defined(IS_RAD1O) || defined(IS_HACKRF_ONE) || defined(IS_PRALINE) void enable_rf_power(void); void disable_rf_power(void); #endif @@ -112,7 +113,7 @@ void trigger_enable(const bool enable); void halt_and_flash(const uint32_t duration); -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE typedef enum { P1_SIGNAL_TRIGGER_IN = 0, P1_SIGNAL_AUX_CLK1 = 1, diff --git a/firmware/common/hackrf_ui.c b/firmware/common/hackrf_ui.c index b90ccc14..4224d40f 100644 --- a/firmware/common/hackrf_ui.c +++ b/firmware/common/hackrf_ui.c @@ -23,14 +23,12 @@ #include #include "hackrf_ui.h" +#include "platform_detect.h" // IWYU pragma: keep #include "transceiver_mode.h" -#if !defined(JAWBREAKER) - #include "platform_detect.h" -#endif -#if defined(PRALINE) || defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_EXPANSION_COMPATIBLE #include "ui_portapack.h" #endif -#if defined(RAD1O) +#ifdef IS_RAD1O #include "ui_rad1o.h" #endif diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index 856c5d99..3b49ab6e 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -31,19 +31,19 @@ #include "platform_gpio.h" #include "spi_bus.h" -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE #include "max2831_target.h" #endif -#if !defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_NOT_PRALINE #include "max2837_target.h" #endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_H1_R9 #include "max2839_target.h" #endif extern spi_bus_t spi_bus_ssp1; -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE max2831_driver_t max2831 = { .bus = &spi_bus_ssp1, .target_init = max2831_target_init, @@ -51,7 +51,7 @@ max2831_driver_t max2831 = { }; #endif -#if !defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_NOT_PRALINE max2837_driver_t max2837 = { .bus = &spi_bus_ssp1, .target_init = max2837_target_init, @@ -59,7 +59,7 @@ max2837_driver_t max2837 = { }; #endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE max2839_driver_t max2839 = { .bus = &spi_bus_ssp1, .target_init = max2839_target_init, @@ -113,7 +113,7 @@ void max283x_setup(max283x_driver_t* const drv) /* clang-format off */ -#if defined(UNIVERSAL) +#if UNIVERSAL // UNIVERSAL: all variants #define DISPATCH(_drv, _max2831, _max2837, _max2839) \ if (_drv->type == MAX2831_VARIANT) { \ @@ -123,7 +123,7 @@ void max283x_setup(max283x_driver_t* const drv) } else { \ _max2839; \ } -#elif defined(HACKRF_ONE) +#elif HACKRF_ONE // HACKRF_ONE: MAX2837 and MAX2839 only #define DISPATCH(_drv, _max2831, _max2837, _max2839) \ if (_drv->type == MAX2837_VARIANT) { \ @@ -131,7 +131,7 @@ void max283x_setup(max283x_driver_t* const drv) } else { \ _max2839; \ } -#elif defined(PRALINE) +#elif PRALINE // PRALINE: MAX2831 only #define DISPATCH(_drv, _max2831, _max2837, _max2839) \ (void) drv; \ @@ -251,9 +251,7 @@ uint32_t max283x_set_lpf_bandwidth( const max283x_mode_t mode, const uint32_t bandwidth_hz) { -#if !defined(PRALINE) (void) mode; -#endif DISPATCH( drv, return max2831_set_lpf_bandwidth( @@ -294,9 +292,7 @@ void max283x_set_rx_hpf_frequency( max283x_driver_t* const drv, const max283x_rx_hpf_freq_t freq) { -#if !defined(PRALINE) && !defined(UNIVERSAL) (void) freq; -#endif PRALINE_ONLY( drv, max2831_set_rx_hpf_frequency( diff --git a/firmware/common/max283x.h b/firmware/common/max283x.h index bcafff06..01bb40b0 100644 --- a/firmware/common/max283x.h +++ b/firmware/common/max283x.h @@ -27,13 +27,15 @@ #include #include "fixed_point.h" -#if defined(PRALINE) || defined(UNIVERSAL) +#include "platform_detect.h" + +#ifdef IS_PRALINE #include "max2831.h" #endif -#if !defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_NOT_PRALINE #include "max2837.h" #endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_H1_R9 #include "max2839.h" #endif @@ -55,13 +57,13 @@ typedef enum { } max283x_rx_hpf_freq_t; typedef enum { -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE MAX2831_VARIANT, #endif -#if !defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_NOT_PRALINE MAX2837_VARIANT, #endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_H1_R9 MAX2839_VARIANT, #endif } max283x_variant_t; @@ -70,13 +72,13 @@ typedef struct { max283x_variant_t type; union { -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE max2831_driver_t max2831; #endif -#if !defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_NOT_PRALINE max2837_driver_t max2837; #endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_H1_R9 max2839_driver_t max2839; #endif } drv; diff --git a/firmware/common/max2871.c b/firmware/common/max2871.c index 4c5a94b2..05840678 100644 --- a/firmware/common/max2871.c +++ b/firmware/common/max2871.c @@ -24,17 +24,18 @@ #include #include +#include + #include "fixed_point.h" #include "max2871_regs.h" -#include "selftest.h" #include "platform_scu.h" +#include "selftest.h" #if (defined DEBUG) #include #define LOG printf #else #define LOG(x, ...) - #include #endif #define MIN(x, y) ((x) < (y) ? (x) : (y)) diff --git a/firmware/common/mixer.c b/firmware/common/mixer.c index fb921350..e38c28bf 100644 --- a/firmware/common/mixer.c +++ b/firmware/common/mixer.c @@ -26,15 +26,16 @@ #include "fixed_point.h" #include "platform_detect.h" #include "platform_gpio.h" -#if defined(RAD1O) +#ifdef IS_RAD1O #include "max2871.h" -#else +#endif +#ifdef IS_NOT_RAD1O #include "rffc5071.h" #include "rffc5071_spi.h" #include "spi_bus.h" #endif -#if !defined(RAD1O) +#ifdef IS_NOT_RAD1O static rffc5071_spi_config_t rffc5071_spi_config; static spi_bus_t spi_bus_rffc5071 = { @@ -47,7 +48,7 @@ static spi_bus_t spi_bus_rffc5071 = { #endif mixer_driver_t mixer = { -#if !defined(RAD1O) +#ifdef IS_NOT_RAD1O .rffc5071.bus = &spi_bus_rffc5071, #endif }; diff --git a/firmware/common/mixer.h b/firmware/common/mixer.h index 0afacb6b..f7861725 100644 --- a/firmware/common/mixer.h +++ b/firmware/common/mixer.h @@ -23,12 +23,15 @@ #pragma once #include +#include #include "fixed_point.h" +#include "platform_detect.h" -#if defined(RAD1O) +#ifdef IS_RAD1O #include "max2871.h" -#else +#endif +#ifdef IS_NOT_RAD1O #include "rffc5071.h" #endif @@ -41,15 +44,15 @@ typedef struct { mixer_variant_t type; union { -#if defined(RAD1O) +#ifdef IS_RAD1O max2871_driver_t max2871; -#else +#endif +#ifdef IS_NOT_RAD1O rffc5071_driver_t rffc5071; #endif }; } mixer_driver_t; -#include extern void mixer_bus_setup(mixer_driver_t* const mixer); extern void mixer_setup(mixer_driver_t* const mixer, mixer_variant_t type); diff --git a/firmware/common/operacake_sctimer.c b/firmware/common/operacake_sctimer.c index 2dbe07d9..3b95f6a1 100644 --- a/firmware/common/operacake_sctimer.c +++ b/firmware/common/operacake_sctimer.c @@ -25,16 +25,16 @@ #include #include #include -#if !defined(PRALINE) + +#include "delay.h" +#include "platform_detect.h" +#include "sct.h" + +#ifdef IS_NOT_PRALINE #include #include #endif -#include - -#include "delay.h" -#include "sct.h" - #define U1CTRL_SET SCT_OUT14_SET #define U1CTRL_CLR SCT_OUT14_CLR #define U2CTRL0_SET SCT_OUT13_SET diff --git a/firmware/common/platform_gpio.h b/firmware/common/platform_gpio.h index 16767136..eeb37b05 100644 --- a/firmware/common/platform_gpio.h +++ b/firmware/common/platform_gpio.h @@ -27,10 +27,11 @@ extern "C" { #include "gpio.h" #include "gpio_lpc.h" +#include "platform_detect.h" typedef struct { /* LEDs */ -#if defined(PRALINE) || defined(UNIVERSAL) || defined(RAD1O) +#ifdef IS_FOUR_LEDS gpio_t led[4]; #else gpio_t led[3]; @@ -38,7 +39,7 @@ typedef struct { /* Power Supply Control */ gpio_t gpio_1v8_enable; -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE gpio_t gpio_1v2_enable; gpio_t gpio_3v3aux_enable_n; #endif @@ -48,7 +49,7 @@ typedef struct { gpio_t max283x_enable; gpio_t max283x_rx_enable; gpio_t max283x_tx_enable; -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE gpio_t max2831_rxhp; gpio_t max2831_ld; #endif @@ -58,7 +59,7 @@ typedef struct { /* RF supply (VAA) control */ gpio_t vaa_disable; -#if defined(RAD1O) +#ifdef IS_RAD1O gpio_t vaa_enable; #endif @@ -68,7 +69,7 @@ typedef struct { gpio_t w25q80bv_select; /* RF switch control */ -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE gpio_t hp; gpio_t lp; gpio_t tx_mix_bp; @@ -85,7 +86,7 @@ typedef struct { gpio_t h1r9_no_ant_pwr; // HACKRF_ONE r9 gpio_t h1r9_rx; // HACKRF_ONE r9 #endif -#if defined(RAD1O) +#ifdef IS_RAD1O gpio_t tx_rx_n; gpio_t tx_rx; gpio_t by_mix; @@ -98,7 +99,7 @@ typedef struct { gpio_t tx_amp; gpio_t rx_lna; #endif -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE gpio_t tx_en; gpio_t mix_en_n; gpio_t mix_en_n_r1_0; @@ -109,23 +110,23 @@ typedef struct { /* CPLD JTAG interface GPIO pins, FPGA config pins in Praline */ gpio_t cpld_tck; -#if !defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_NOT_PRALINE + gpio_t cpld_tdo; gpio_t cpld_tms; gpio_t cpld_tdi; - gpio_t cpld_tdo; #endif -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_EXPANSION_COMPATIBLE gpio_t cpld_pp_tms; gpio_t cpld_pp_tdo; #endif -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE gpio_t fpga_cfg_creset; gpio_t fpga_cfg_cdone; gpio_t fpga_cfg_spi_cs; #endif /* Other CPLD interface GPIO pins */ -#if !defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_NOT_PRALINE gpio_t trigger_enable; #endif gpio_t q_invert; @@ -144,7 +145,7 @@ typedef struct { gpio_t synt_rfout_en; // RAD1O /* Praline */ -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE gpio_t p2_ctrl0; gpio_t p2_ctrl1; gpio_t p1_ctrl0; @@ -157,7 +158,7 @@ typedef struct { gpio_t pps_out; #endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE /* HackRF One r9 clock control */ gpio_t h1r9_clkin_en; gpio_t h1r9_clkout_en; @@ -169,14 +170,14 @@ typedef struct { #endif /* RAD1O */ -#if defined(RAD1O) +#ifdef IS_RAD1O gpio_t lcd_cs; gpio_t lcd_bl_en; gpio_t lcd_reset; #endif /* Portapack */ -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_EXPANSION_COMPATIBLE gpio_t io_stbx; gpio_t addr; gpio_t lcd_rdx; diff --git a/firmware/common/platform_scu.h b/firmware/common/platform_scu.h index 2c5365e3..1ffb224c 100644 --- a/firmware/common/platform_scu.h +++ b/firmware/common/platform_scu.h @@ -29,6 +29,8 @@ extern "C" { #include +#include "platform_detect.h" + /* * SCU PinMux */ @@ -38,13 +40,13 @@ typedef struct { scu_grp_pin_t PINMUX_LED1; scu_grp_pin_t PINMUX_LED2; scu_grp_pin_t PINMUX_LED3; -#if defined(RAD1O) || defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_FOUR_LEDS scu_grp_pin_t PINMUX_LED4; #endif scu_grp_pin_t PINMUX_EN1V8; scu_grp_pin_t PINMUX_EN1V2; -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE scu_grp_pin_t PINMUX_EN3V3_AUX_N; scu_grp_pin_t PINMUX_EN3V3_OC_N; #endif @@ -52,7 +54,7 @@ typedef struct { /* GPIO Input PinMux */ scu_grp_pin_t PINMUX_BOOT0; scu_grp_pin_t PINMUX_BOOT1; -#if !defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_NOT_HACKRF_ONE scu_grp_pin_t PINMUX_BOOT2; scu_grp_pin_t PINMUX_BOOT3; #endif @@ -63,7 +65,7 @@ typedef struct { scu_grp_pin_t PINMUX_PP_DIR; /* USB peripheral */ -#if defined(JAWBREAKER) +#ifdef IS_JAWBREAKER scu_grp_pin_t PINMUX_USB_LED0; scu_grp_pin_t PINMUX_USB_LED1; #endif @@ -75,7 +77,7 @@ typedef struct { scu_grp_pin_t SSP1_CS; /* CPLD JTAG interface */ -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE scu_grp_pin_t PINMUX_FPGA_CRESET; scu_grp_pin_t PINMUX_FPGA_CDONE; scu_grp_pin_t PINMUX_FPGA_SPI_CS; @@ -127,15 +129,15 @@ typedef struct { uint32_t XCVR_RXENABLE_PINCFG; uint32_t XCVR_TXENABLE_PINCFG; uint32_t XCVR_CS_PINCFG; -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE scu_grp_pin_t XCVR_LD; uint32_t XCVR_LD_PINCFG; uint32_t XCVR_RXHP_PINCFG; #endif -#if defined(RAD1O) || defined(PRALINE) || defined(UNIVERSAL) +#if defined(IS_RAD1O) || defined(IS_PRALINE) scu_grp_pin_t XCVR_RXHP; #endif -#if defined(RAD1O) +#ifdef IS_RAD1O scu_grp_pin_t XCVR_B6; scu_grp_pin_t XCVR_B7; #endif @@ -145,7 +147,7 @@ typedef struct { scu_grp_pin_t AD_CS_PINCFG; /* RFFC5071 GPIO serial interface PinMux */ -#if !defined(RAD1O) +#ifdef IS_NOT_RAD1O scu_grp_pin_t MIXER_ENX; scu_grp_pin_t MIXER_SCLK; scu_grp_pin_t MIXER_SDATA; @@ -153,11 +155,11 @@ typedef struct { uint32_t MIXER_SCLK_PINCFG; uint32_t MIXER_SDATA_PINCFG; #endif -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE scu_grp_pin_t MIXER_LD; uint32_t MIXER_LD_PINCFG; #endif -#if defined(RAD1O) +#ifdef IS_RAD1O scu_grp_pin_t VCO_CE; scu_grp_pin_t VCO_SCLK; scu_grp_pin_t VCO_SDATA; @@ -168,15 +170,15 @@ typedef struct { #endif /* RF LDO control */ -#if defined(JAWBREAKER) +#ifdef IS_JAWBREAKER scu_grp_pin_t RF_LDO_ENABLE; #endif /* RF supply (VAA) control */ -#if defined(PRALINE) || defined(HACKRF_ONE) || defined(UNIVERSAL) +#if defined(IS_PRALINE) || defined(IS_HACKRF_ONE) scu_grp_pin_t NO_VAA_ENABLE; #endif -#if defined(RAD1O) +#ifdef IS_RAD1O scu_grp_pin_t VAA_ENABLE; #endif @@ -189,7 +191,7 @@ typedef struct { scu_grp_pin_t FLASH_WP; /* RF switch control */ -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE scu_grp_pin_t TX_EN; scu_grp_pin_t MIX_EN_N; scu_grp_pin_t MIX_EN_N_R1_0; @@ -198,7 +200,7 @@ typedef struct { scu_grp_pin_t ANT_BIAS_EN_N; scu_grp_pin_t ANT_BIAS_OC_N; #endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE scu_grp_pin_t HP; scu_grp_pin_t LP; scu_grp_pin_t TX_MIX_BP; @@ -213,7 +215,7 @@ typedef struct { scu_grp_pin_t RX_AMP; scu_grp_pin_t NO_RX_AMP_PWR; #endif -#if defined(RAD1O) +#ifdef IS_RAD1O scu_grp_pin_t BY_AMP; scu_grp_pin_t BY_AMP_N; scu_grp_pin_t TX_RX; @@ -227,7 +229,7 @@ typedef struct { #endif /* Praline */ -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE scu_grp_pin_t P2_CTRL0; scu_grp_pin_t P2_CTRL1; scu_grp_pin_t P1_CTRL0; @@ -252,7 +254,7 @@ typedef struct { #endif /* HackRF One r9 */ -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE scu_grp_pin_t H1R9_CLKIN_EN; scu_grp_pin_t H1R9_CLKOUT_EN; scu_grp_pin_t H1R9_MCU_CLK_EN; diff --git a/firmware/common/radio.c b/firmware/common/radio.c index a98587f4..760351ac 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -33,7 +33,7 @@ #include "rf_path.h" #include "transceiver_mode.h" #include "tuning.h" -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE #include "fpga.h" #include "tune_config.h" #endif @@ -294,7 +294,7 @@ static fp_40_24_t digital_from_analog_rf( return drf; } -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE /* * Convert center frequency of digital baseband (as seen by MCU) to center * frequency of analog baseband (as seen by ADC/DAC). @@ -354,7 +354,7 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) const uint64_t requested_if = bank[RADIO_FREQUENCY_IF]; const uint64_t requested_lo = bank[RADIO_FREQUENCY_LO]; const uint64_t requested_img_reject = bank[RADIO_IMAGE_REJECT]; -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE const uint64_t requested_rotation = bank[RADIO_ROTATION]; #endif diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 5043bfe8..6a8e3caf 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -23,16 +23,13 @@ #include "rf_path.h" -#if !defined(JAWBREAKER) - #include -#endif - #include "hackrf_core.h" #include "max283x.h" #include "max5864.h" #include "mixer.h" #include "platform_detect.h" -#if !defined(JAWBREAKER) +#ifdef IS_NOT_JAWBREAKER + #include #include "platform_scu.h" #endif @@ -92,7 +89,7 @@ #define SWITCHCTRL_ANT_PWR (1 << 6) /* turn on antenna port power */ -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) { board_id_t board_id = detected_platform(); @@ -186,7 +183,7 @@ static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) } #endif -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE static void switchctrl_set_praline(rf_path_t* const rf_path, uint8_t ctrl) { if (ctrl & SWITCHCTRL_TX) { @@ -227,7 +224,7 @@ static void switchctrl_set_praline(rf_path_t* const rf_path, uint8_t ctrl) } #endif -#if defined(RAD1O) +#ifdef IS_RAD1O static void switchctrl_set_rad1o(rf_path_t* const rf_path, uint8_t ctrl) { if (ctrl & SWITCHCTRL_TX) { @@ -319,11 +316,9 @@ static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) void rf_path_pin_setup(rf_path_t* const rf_path) { -#if defined(JAWBREAKER) +#ifdef JAWBREAKER (void) rf_path; -#endif - -#if !defined(JAWBREAKER) +#else const platform_scu_t* scu = platform_scu(); #endif @@ -530,7 +525,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d max283x_rx(&max283x); break; -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE case RF_PATH_DIRECTION_TX_CALIBRATION: case RF_PATH_DIRECTION_RX_CALIBRATION: rf_path->switchctrl &= ~SWITCHCTRL_TX; diff --git a/firmware/common/rf_path.h b/firmware/common/rf_path.h index 64634b3d..42dd91cb 100644 --- a/firmware/common/rf_path.h +++ b/firmware/common/rf_path.h @@ -25,7 +25,9 @@ #include -#if !defined(JAWBREAKER) +#include "platform_detect.h" // IWYU pragma: keep + +#ifdef IS_NOT_JAWBREAKER #include "gpio.h" #endif @@ -33,7 +35,7 @@ typedef enum { RF_PATH_DIRECTION_OFF, RF_PATH_DIRECTION_RX, RF_PATH_DIRECTION_TX, -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE RF_PATH_DIRECTION_TX_CALIBRATION, RF_PATH_DIRECTION_RX_CALIBRATION, #endif @@ -49,7 +51,7 @@ typedef struct { uint8_t switchctrl; struct { -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE gpio_t gpio_hp; gpio_t gpio_lp; gpio_t gpio_tx_mix_bp; @@ -67,7 +69,7 @@ typedef struct { gpio_t gpio_h1r9_no_ant_pwr; #endif -#if defined(RAD1O) +#ifdef IS_RAD1O gpio_t gpio_tx_rx_n; gpio_t gpio_tx_rx; gpio_t gpio_by_mix; @@ -81,7 +83,7 @@ typedef struct { gpio_t gpio_rx_lna; #endif -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE gpio_t gpio_tx_en; gpio_t gpio_mix_en_n; gpio_t gpio_lpf_en; diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index ab0717ea..2a1866d2 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -35,17 +35,14 @@ #include #include -#if defined(PRALINE) || defined(UNIVERSAL) - #include -#endif - #include "delay.h" #include "fixed_point.h" #include "platform_detect.h" #include "rffc5071.h" #include "rffc5071_regs.def" // private register def macros #include "selftest.h" -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE + #include #include "platform_scu.h" #endif @@ -370,7 +367,7 @@ void rffc5071_set_gpo(rffc5071_driver_t* const drv, uint8_t gpo) rffc5071_regs_commit(drv); } -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE bool rffc5071_poll_ld(rffc5071_driver_t* const drv, uint8_t* prelock_state) { // This is only supported on Praline hardware. diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index 6a0c4ce2..c6b2c0c2 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -27,6 +27,7 @@ #include "fixed_point.h" #include "gpio.h" +#include "platform_detect.h" // IWYU pragma: keep #include "spi_bus.h" /* 31 registers, each containing 16 bits of data. */ @@ -35,7 +36,7 @@ typedef struct { spi_bus_t* const bus; gpio_t gpio_reset; -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE gpio_t gpio_ld; #endif uint16_t regs[RFFC5071_NUM_REGS]; @@ -70,7 +71,7 @@ extern void rffc5071_enable(rffc5071_driver_t* const drv); extern void rffc5071_disable(rffc5071_driver_t* const drv); extern void rffc5071_set_gpo(rffc5071_driver_t* const drv, uint8_t); -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE extern bool rffc5071_poll_ld(rffc5071_driver_t* const drv, uint8_t* prelock_state); #endif extern bool rffc5071_check_lock(rffc5071_driver_t* const drv); diff --git a/firmware/common/selftest.h b/firmware/common/selftest.h index 8223a582..9fca53a6 100644 --- a/firmware/common/selftest.h +++ b/firmware/common/selftest.h @@ -24,6 +24,8 @@ #include #include +#include "platform_detect.h" // IWYU pragma: keep + #define NUM_LOCK_ATTEMPTS 3 enum { @@ -37,10 +39,10 @@ typedef uint8_t test_result_t; typedef struct { uint16_t mixer_id; -#if !defined(RAD1O) +#ifdef IS_NOT_RAD1O bool mixer_locks[NUM_LOCK_ATTEMPTS]; #endif -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE uint16_t max2831_mux_rssi_1; uint16_t max2831_mux_temp; uint16_t max2831_mux_rssi_2; @@ -52,7 +54,7 @@ typedef struct { uint8_t max283x_readback_total_registers; uint8_t si5351_rev_id; bool si5351_readback_ok; -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE test_result_t fpga_image_load; test_result_t fpga_spi; test_result_t sgpio_rx; diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index 4aa98265..9d03924a 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -31,7 +31,7 @@ #include "platform_detect.h" #include "platform_scu.h" #include "sgpio.h" -#if !defined(PRALINE) +#ifdef IS_NOT_PRALINE #include "hackrf_core.h" #endif diff --git a/firmware/common/sgpio.h b/firmware/common/sgpio.h index f6fdf213..409cef0c 100644 --- a/firmware/common/sgpio.h +++ b/firmware/common/sgpio.h @@ -26,6 +26,7 @@ #include #include "gpio.h" +#include "platform_detect.h" // IWYU pragma: keep typedef enum { SGPIO_DIRECTION_RX, @@ -34,7 +35,7 @@ typedef enum { typedef struct { gpio_t gpio_q_invert; -#if !defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_NOT_PRALINE gpio_t gpio_trigger_enable; #endif bool slice_mode_multislice; diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index a1466393..0acff63e 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -23,16 +23,13 @@ #include #include -#if defined(HACKRF_ONE) || defined(UNIVERSAL) - #include -#endif - #include "clkin.h" #include "delay.h" #include "platform_detect.h" #include "selftest.h" #include "si5351c.h" -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE + #include #include "gpio.h" #include "platform_gpio.h" #include "platform_scu.h" diff --git a/firmware/common/tune_config.h b/firmware/common/tune_config.h index 34c692e6..dd81f62d 100644 --- a/firmware/common/tune_config.h +++ b/firmware/common/tune_config.h @@ -21,7 +21,9 @@ #pragma once -#if defined(PRALINE) || defined(UNIVERSAL) +#include "platform_detect.h" + +#ifdef IS_PRALINE #include "fpga.h" typedef struct { diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 653a477a..b79dcdec 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -48,14 +48,14 @@ #include #include #include -#if defined(PRALINE) || defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_EXPANSION_COMPATIBLE #include #endif -#if !defined(RAD1O) +#ifdef IS_NOT_RAD1O #include #include #endif -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE #include #if !(defined(DFU_MODE) || defined(RAM_MODE)) #include @@ -63,7 +63,7 @@ #include #endif #endif -#if !defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_NOT_PRALINE #include #include #endif @@ -81,10 +81,10 @@ #include "usb_descriptor.h" #include "usb_device.h" #include "usb_endpoint.h" -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE #include "usb_api_praline.h" #endif -#if !defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_NOT_PRALINE #include "usb_api_cpld.h" #endif @@ -102,7 +102,7 @@ static usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_read_si5351c, usb_vendor_request_set_sample_rate_frac, usb_vendor_request_set_baseband_filter_bandwidth, -#if !defined(RAD1O) +#ifdef IS_NOT_RAD1O usb_vendor_request_write_rffc5071, usb_vendor_request_read_rffc5071, #else @@ -122,7 +122,7 @@ static usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_set_vga_gain, usb_vendor_request_set_txvga_gain, NULL, // was set_if_freq -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) +#if defined(IS_HACKRF_ONE) || defined(IS_PRALINE) usb_vendor_request_set_antenna_enable, #else NULL, @@ -139,7 +139,7 @@ static usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_spiflash_status, usb_vendor_request_spiflash_clear_status, usb_vendor_request_operacake_gpio_test, -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE usb_vendor_request_cpld_checksum, #else NULL, @@ -156,7 +156,7 @@ static usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_read_supported_platform, usb_vendor_request_set_leds, usb_vendor_request_user_config_set_bias_t_opts, -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE usb_vendor_request_write_fpga_reg, usb_vendor_request_read_fpga_reg, usb_vendor_request_p2_ctrl, @@ -252,7 +252,7 @@ void usb_set_descriptor_by_serial_number(void) } } -#if !defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_NOT_PRALINE static bool cpld_jtag_sram_load(jtag_t* const jtag) { cpld_jtag_take(jtag); @@ -280,7 +280,7 @@ static void m0_rom_to_ram(void) memcpy(dest, (uint32_t*) (base + src), len); } -#if (defined(PRALINE) || defined(UNIVERSAL)) && !(defined(DFU_MODE) || defined(RAM_MODE)) +#if defined(IS_PRALINE) && !(defined(DFU_MODE) || defined(RAM_MODE)) extern uint32_t _binary_fpga_bin_start; void fpga_loader_setup(void) @@ -347,9 +347,11 @@ void radio_changed(const uint32_t changed) if (opmode != TRANSCEIVER_MODE_RX_SWEEP) { hackrf_ui()->set_frequency(freq / FP_ONE_HZ); } - IF_EXPANSION_COMPATIBLE ( +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { operacake_set_range(freq / FP_ONE_MHZ); - ) + } +#endif } if (changed & (1 << RADIO_IMAGE_REJECT)) { if (opmode != TRANSCEIVER_MODE_RX_SWEEP) { @@ -575,7 +577,7 @@ int main(void) rf_path_init(&rf_path); -#if !defined(RAD1O) +#ifdef IS_NOT_RAD1O rffc5071_lock_test(&mixer.rffc5071); #endif diff --git a/firmware/hackrf_usb/usb_api_board_info.c b/firmware/hackrf_usb/usb_api_board_info.c index 393b102d..920ad749 100644 --- a/firmware/hackrf_usb/usb_api_board_info.c +++ b/firmware/hackrf_usb/usb_api_board_info.c @@ -20,7 +20,6 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ - #include "usb_api_board_info.h" #include @@ -34,7 +33,7 @@ #include #include #include -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE #include #include #endif diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index d17a87d8..b9498dab 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -21,7 +21,6 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ - #include "usb_api_register.h" #include @@ -36,10 +35,10 @@ #include #include #include -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE #include #endif -#if !defined(RAD1O) +#ifdef IS_NOT_RAD1O #include #include #endif @@ -290,7 +289,7 @@ usb_request_status_t usb_vendor_request_user_config_set_bias_t_opts( return USB_REQUEST_STATUS_OK; } -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE usb_request_status_t usb_vendor_request_write_fpga_reg( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) diff --git a/firmware/hackrf_usb/usb_api_register.h b/firmware/hackrf_usb/usb_api_register.h index 58a84aff..aef02d03 100644 --- a/firmware/hackrf_usb/usb_api_register.h +++ b/firmware/hackrf_usb/usb_api_register.h @@ -23,6 +23,8 @@ #pragma once +#include "platform_detect.h" // IWYU pragma: keep + #include #include @@ -56,7 +58,7 @@ usb_request_status_t usb_vendor_request_set_leds( usb_request_status_t usb_vendor_request_user_config_set_bias_t_opts( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE usb_request_status_t usb_vendor_request_write_fpga_reg( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); diff --git a/firmware/hackrf_usb/usb_api_selftest.c b/firmware/hackrf_usb/usb_api_selftest.c index 403f3753..4c812366 100644 --- a/firmware/hackrf_usb/usb_api_selftest.c +++ b/firmware/hackrf_usb/usb_api_selftest.c @@ -19,11 +19,10 @@ * Boston, MA 02110-1301, USA. */ +#include "usb_api_selftest.h" + #include #include -#if !defined(RAD1O) - #include -#endif #include #include @@ -34,7 +33,9 @@ #include #include -#include "usb_api_selftest.h" +#ifdef IS_NOT_RAD1O + #include +#endif static char* itoa(int val, int base) { @@ -61,7 +62,7 @@ void append(char** dest, size_t* capacity, const char* str) } } -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE static const char* test_result_to_str(test_result_t result) { switch (result) { diff --git a/firmware/hackrf_usb/usb_descriptor.c b/firmware/hackrf_usb/usb_descriptor.c index f213f484..36531ebc 100644 --- a/firmware/hackrf_usb/usb_descriptor.c +++ b/firmware/hackrf_usb/usb_descriptor.c @@ -26,17 +26,9 @@ #include -#define USB_VENDOR_ID (0x1D50) +#include "platform_detect.h" -#if (defined HACKRF_ONE || defined PRALINE) - #define USB_PRODUCT_ID (0x6089) -#elif JAWBREAKER - #define USB_PRODUCT_ID (0x604B) -#elif RAD1O - #define USB_PRODUCT_ID (0xCC15) -#else - #define USB_PRODUCT_ID (0xFFFF) -#endif +#define USB_VENDOR_ID (0x1D50) #define USB_API_VERSION (0x0111) @@ -51,7 +43,7 @@ #define USB_STRING_LANGID (0x0409) -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) +#if defined(IS_HACKRF_ONE) || defined(IS_PRALINE) uint8_t usb_descriptor_device_hackrf[] = { 18, // bLength USB_DESCRIPTOR_TYPE_DEVICE, // bDescriptorType @@ -69,7 +61,7 @@ uint8_t usb_descriptor_device_hackrf[] = { 0x01 // bNumConfigurations }; #endif -#if defined(JAWBREAKER) +#ifdef IS_JAWBREAKER uint8_t usb_descriptor_device_jawbreaker[] = { 18, // bLength USB_DESCRIPTOR_TYPE_DEVICE, // bDescriptorType @@ -87,7 +79,7 @@ uint8_t usb_descriptor_device_jawbreaker[] = { 0x01 // bNumConfigurations }; #endif -#if defined(RAD1O) +#ifdef IS_RAD1O uint8_t usb_descriptor_device_rad1o[] = { 18, // bLength USB_DESCRIPTOR_TYPE_DEVICE, // bDescriptorType @@ -223,7 +215,7 @@ uint8_t usb_descriptor_string_manufacturer[] = { 's', 0x00, }; -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE uint8_t usb_descriptor_string_product_hackrf_one[] = { 22, // bLength USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType @@ -239,7 +231,7 @@ uint8_t usb_descriptor_string_product_hackrf_one[] = { 'e', 0x00, }; #endif -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE uint8_t usb_descriptor_string_product_praline[] = { 22, // bLength USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType @@ -255,7 +247,7 @@ uint8_t usb_descriptor_string_product_praline[] = { 'o', 0x00, }; #endif -#if defined(JAWBREAKER) +#ifdef IS_JAWBREAKER uint8_t usb_descriptor_string_product_jawbreaker[] = { 36, // bLength USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType @@ -278,7 +270,7 @@ uint8_t usb_descriptor_string_product_jawbreaker[] = { 'r', 0x00, }; #endif -#if defined(RAD1O) +#ifdef IS_RAD1O uint8_t usb_descriptor_string_product_rad1o[] = { 12, // bLength USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType @@ -329,7 +321,7 @@ uint8_t usb_descriptor_string_serial_number[] = { uint8_t usb_descriptor_string_serial_number[USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN]; #endif -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE uint8_t* usb_descriptor_strings_hackrf_one[] = { usb_descriptor_string_languages, usb_descriptor_string_manufacturer, @@ -339,7 +331,7 @@ uint8_t* usb_descriptor_strings_hackrf_one[] = { 0, // TERMINATOR }; #endif -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE uint8_t* usb_descriptor_strings_praline[] = { usb_descriptor_string_languages, usb_descriptor_string_manufacturer, @@ -349,7 +341,7 @@ uint8_t* usb_descriptor_strings_praline[] = { 0, // TERMINATOR }; #endif -#if defined(JAWBREAKER) +#ifdef IS_JAWBREAKER uint8_t* usb_descriptor_strings_jawbreaker[] = { usb_descriptor_string_languages, usb_descriptor_string_manufacturer, @@ -359,7 +351,7 @@ uint8_t* usb_descriptor_strings_jawbreaker[] = { 0, // TERMINATOR }; #endif -#if defined(RAD1O) +#ifdef IS_RAD1O uint8_t* usb_descriptor_strings_rad1o[] = { usb_descriptor_string_languages, usb_descriptor_string_manufacturer, diff --git a/firmware/hackrf_usb/usb_descriptor.h b/firmware/hackrf_usb/usb_descriptor.h index 93f3eb78..ef41d6ac 100644 --- a/firmware/hackrf_usb/usb_descriptor.h +++ b/firmware/hackrf_usb/usb_descriptor.h @@ -24,13 +24,15 @@ #include -#if defined(HACKRF_ONE) || defined(PRALINE) || defined(UNIVERSAL) +#include "platform_detect.h" + +#if defined(IS_HACKRF_ONE) || defined(IS_PRALINE) extern uint8_t usb_descriptor_device_hackrf[]; #endif -#if defined(JAWBREAKER) +#ifdef IS_JAWBREAKER extern uint8_t usb_descriptor_device_jawbreaker[]; #endif -#if defined(RAD1O) +#ifdef IS_RAD1O extern uint8_t usb_descriptor_device_rad1o[]; #endif extern uint8_t usb_descriptor_device_qualifier[]; @@ -38,16 +40,16 @@ extern uint8_t usb_descriptor_configuration_full_speed[]; extern uint8_t usb_descriptor_configuration_high_speed[]; extern uint8_t usb_descriptor_string_languages[]; extern uint8_t usb_descriptor_string_manufacturer[]; -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE extern uint8_t usb_descriptor_string_product_hackrf_one[]; #endif -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE extern uint8_t usb_descriptor_string_product_praline[]; #endif -#if defined(JAWBREAKER) +#ifdef IS_JAWBREAKER extern uint8_t usb_descriptor_string_product_jawbreaker[]; #endif -#if defined(RAD1O) +#ifdef IS_RAD1O extern uint8_t usb_descriptor_string_product_rad1o[]; #endif diff --git a/firmware/hackrf_usb/usb_device.c b/firmware/hackrf_usb/usb_device.c index 4ad46424..a2af1158 100644 --- a/firmware/hackrf_usb/usb_device.c +++ b/firmware/hackrf_usb/usb_device.c @@ -25,6 +25,7 @@ #include +#include "platform_detect.h" #include "usb_descriptor.h" usb_configuration_t usb_configuration_high_speed = { @@ -47,7 +48,7 @@ usb_configuration_t* usb_configurations[] = { usb_device_t usb_device; -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE const usb_device_t usb_device_hackrf_one = { .descriptor = usb_descriptor_device_hackrf, .descriptor_strings = usb_descriptor_strings_hackrf_one, @@ -58,7 +59,7 @@ const usb_device_t usb_device_hackrf_one = { .wcid_feature_descriptor = wcid_feature_descriptor, }; #endif -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE const usb_device_t usb_device_praline = { .descriptor = usb_descriptor_device_hackrf, .descriptor_strings = usb_descriptor_strings_praline, @@ -69,7 +70,7 @@ const usb_device_t usb_device_praline = { .wcid_feature_descriptor = wcid_feature_descriptor, }; #endif -#if defined(JAWBREAKER) +#ifdef IS_JAWBREAKER const usb_device_t usb_device_jawbreaker = { .descriptor = usb_descriptor_device_jawbreaker, .descriptor_strings = usb_descriptor_strings_jawbreaker, @@ -80,7 +81,7 @@ const usb_device_t usb_device_jawbreaker = { .wcid_feature_descriptor = wcid_feature_descriptor, }; #endif -#if defined(RAD1O) +#ifdef IS_RAD1O const usb_device_t usb_device_rad1o = { .descriptor = usb_descriptor_device_rad1o, .descriptor_strings = usb_descriptor_strings_rad1o, diff --git a/firmware/hackrf_usb/usb_device.h b/firmware/hackrf_usb/usb_device.h index 528d084d..f442db37 100644 --- a/firmware/hackrf_usb/usb_device.h +++ b/firmware/hackrf_usb/usb_device.h @@ -25,17 +25,19 @@ #include +#include "platform_detect.h" + extern usb_device_t usb_device; -#if defined(HACKRF_ONE) || defined(UNIVERSAL) +#ifdef IS_HACKRF_ONE extern const usb_device_t usb_device_hackrf_one; #endif -#if defined(PRALINE) || defined(UNIVERSAL) +#ifdef IS_PRALINE extern const usb_device_t usb_device_praline; #endif -#if defined(JAWBREAKER) +#ifdef IS_JAWBREAKER extern const usb_device_t usb_device_jawbreaker; #endif -#if defined(RAD1O) +#ifdef IS_RAD1O extern const usb_device_t usb_device_rad1o; #endif From f2962ce9b10e85d8d709aa05cd425bea48fd50c1 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 21 Apr 2026 14:24:41 -0400 Subject: [PATCH 132/238] By default, turn off bias tee when radio idle This matches the behavior before #1648. --- firmware/common/radio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 760351ac..a0aafb4c 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -53,6 +53,7 @@ void radio_init(radio_t* const radio) radio->config[RADIO_BANK_IDLE][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF; radio->config[RADIO_BANK_RX][RADIO_OPMODE] = TRANSCEIVER_MODE_RX; radio->config[RADIO_BANK_TX][RADIO_OPMODE] = TRANSCEIVER_MODE_TX; + radio->config[RADIO_BANK_IDLE][RADIO_BIAS_TEE] = false; radio->regs_dirty = 0; } From 4bd414194a5ead5b4adcec23afdcab2a0f33534b Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 21 Apr 2026 17:11:31 -0400 Subject: [PATCH 133/238] Fix explicit TX interpolation --- firmware/common/radio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 760351ac..6c932ec9 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -158,14 +158,13 @@ static inline uint8_t compute_resample_log( static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank) { fp_28_36_t rate, afe_rate, previous_rate, previous_afe_rate; - uint64_t previous_n; + uint64_t previous_n, requested_n; uint8_t n = 0; bool new_afe_rate = false; bool new_rate = false; bool new_n = false; const uint64_t requested_rate = bank[RADIO_SAMPLE_RATE]; - const uint64_t requested_n = bank[RADIO_RESAMPLE_RX]; if (requested_rate != RADIO_UNSET) { rate = MIN(requested_rate, MAX_MCU_RATE); @@ -193,6 +192,7 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank) switch (opmode) { case TRANSCEIVER_MODE_TX: case TRANSCEIVER_MODE_SS: + requested_n = bank[RADIO_RESAMPLE_TX]; n = compute_resample_log(rate / SR_FP_ONE_HZ, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX]) { #ifdef IS_PRALINE @@ -204,6 +204,7 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank) } break; default: + requested_n = bank[RADIO_RESAMPLE_RX]; n = compute_resample_log(rate / SR_FP_ONE_HZ, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX]) { #ifdef IS_PRALINE From 230bfbc36f16f15acb2a9380c9e7e814e490200f Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Wed, 22 Apr 2026 10:51:54 -0400 Subject: [PATCH 134/238] Allow explicit resampling ratio of 1 --- firmware/common/radio.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 6c932ec9..4f5eb683 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -127,26 +127,39 @@ static uint32_t radio_update_direction(radio_t* const radio, uint64_t* bank) return (1 << RADIO_OPMODE); } -#define MAX_AFE_RATE_HZ (40000000UL) +#define ABSOLUTE_MIN_AFE_RATE SR_FP_KHZ(200) +#define ABSOLUTE_MAX_AFE_RATE SR_FP_KHZ(43600) +#define MAX_SUPPORTED_AFE_RATE SR_FP_KHZ(40000) static inline uint8_t compute_resample_log( - const uint32_t sample_rate_hz, + const fp_28_36_t sample_rate, const uint64_t requested_n) { if (detected_platform() != BOARD_ID_PRALINE) { return 0; } - const uint8_t min_n = 1; - uint8_t max_n = 5; + uint8_t n = 0; // resampling ratio is 2**n + const uint8_t max_n = 5; + fp_28_36_t afe_rate = 0; - if (requested_n != RADIO_UNSET) { - max_n = MIN(max_n, requested_n); - } - uint8_t n = min_n; // resampling ratio is 2**n - uint32_t afe_rate_x2 = 4 * sample_rate_hz; - while ((afe_rate_x2 <= MAX_AFE_RATE_HZ) && (n < max_n)) { - afe_rate_x2 <<= 1; - n++; + if (requested_n == RADIO_UNSET) { + /* Find highest supported resampling ratio of at least 2 (n=1). */ + while (((afe_rate * 2) <= MAX_SUPPORTED_AFE_RATE) && (n < max_n)) { + n++; + afe_rate = sample_rate << n; + } + } else { + /* Restrict requested resampling ratio within allowable limits. */ + n = MIN(max_n, requested_n); + afe_rate = sample_rate << n; + while ((afe_rate < ABSOLUTE_MIN_AFE_RATE) && (n < max_n)) { + n++; + afe_rate <<= 1; + } + while ((afe_rate > ABSOLUTE_MAX_AFE_RATE) && (n > 0)) { + n--; + afe_rate >>= 1; + } } return n; } @@ -193,7 +206,7 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank) case TRANSCEIVER_MODE_TX: case TRANSCEIVER_MODE_SS: requested_n = bank[RADIO_RESAMPLE_TX]; - n = compute_resample_log(rate / SR_FP_ONE_HZ, requested_n); + n = compute_resample_log(rate, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_TX]) { #ifdef IS_PRALINE if (IS_PRALINE) { @@ -205,7 +218,7 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank) break; default: requested_n = bank[RADIO_RESAMPLE_RX]; - n = compute_resample_log(rate / SR_FP_ONE_HZ, requested_n); + n = compute_resample_log(rate, requested_n); if (n != radio->config[RADIO_BANK_APPLIED][RADIO_RESAMPLE_RX]) { #ifdef IS_PRALINE if (IS_PRALINE) { From 902ae831bfe5b93277a816d012b44e2d61e7b61c Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 19 Mar 2026 11:30:54 +0200 Subject: [PATCH 135/238] firmware: move cpu clock logic to cpu_clock.h|c --- firmware/common/cpu_clock.c | 252 +++++++++++++++++++++++++++++++ firmware/common/cpu_clock.h | 34 +++++ firmware/common/hackrf_core.c | 225 +-------------------------- firmware/common/hackrf_core.h | 3 +- firmware/hackrf-common.cmake | 1 + firmware/hackrf_usb/hackrf_usb.c | 1 + 6 files changed, 291 insertions(+), 225 deletions(-) create mode 100644 firmware/common/cpu_clock.c create mode 100644 firmware/common/cpu_clock.h diff --git a/firmware/common/cpu_clock.c b/firmware/common/cpu_clock.c new file mode 100644 index 00000000..1bbd9571 --- /dev/null +++ b/firmware/common/cpu_clock.c @@ -0,0 +1,252 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "cpu_clock.h" + +#include + +#include +#if defined(IS_JAWBREAKER) || defined(IS_HACKRF_ONE) || defined(IS_PRALINE) + #include +#endif + +#include "delay.h" +#include "hackrf_core.h" +#include "i2c_bus.h" +#ifdef IS_NOT_RAD1O + #include "platform_detect.h" +#endif + +/* +Configure PLL1 (Main MCU Clock) to max speed (204MHz). +Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. +This function shall be called after cpu_clock_init(). +*/ +static void cpu_clock_pll1_max_speed(void) +{ + uint32_t reg_val; + + /* This function implements the sequence recommended in: + * UM10503 Rev 2.4 (Aug 2018), section 13.2.1.1, page 167. */ + + /* 1. Select the IRC as BASE_M4_CLK source. */ + reg_val = CGU_BASE_M4_CLK; + reg_val &= ~CGU_BASE_M4_CLK_CLK_SEL_MASK; + reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_IRC) | CGU_BASE_M4_CLK_AUTOBLOCK(1); + CGU_BASE_M4_CLK = reg_val; + + /* 2. Enable the crystal oscillator. */ + CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_ENABLE_MASK; + + /* 3. Wait 250us. */ + delay_us_at_mhz(250, 12); + + /* 4. Set the AUTOBLOCK bit. */ + CGU_PLL1_CTRL |= CGU_PLL1_CTRL_AUTOBLOCK(1); + + /* 5. Reconfigure PLL1 to produce the final output frequency, with the + * crystal oscillator as clock source. */ + reg_val = CGU_PLL1_CTRL; + // clang-format off + reg_val &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | + CGU_PLL1_CTRL_PD_MASK | + CGU_PLL1_CTRL_FBSEL_MASK | + CGU_PLL1_CTRL_BYPASS_MASK | + CGU_PLL1_CTRL_DIRECT_MASK | + CGU_PLL1_CTRL_PSEL_MASK | + CGU_PLL1_CTRL_MSEL_MASK | + CGU_PLL1_CTRL_NSEL_MASK ); + /* Set PLL1 up to 12MHz * 17 = 204MHz. + * Direct mode: FCLKOUT = FCCO = M*(FCLKIN/N) */ + reg_val |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL) | + CGU_PLL1_CTRL_PSEL(0) | + CGU_PLL1_CTRL_NSEL(0) | + CGU_PLL1_CTRL_MSEL(16) | + CGU_PLL1_CTRL_FBSEL(0) | + CGU_PLL1_CTRL_DIRECT(1); + // clang-format on + CGU_PLL1_CTRL = reg_val; + + /* 6. Wait for PLL1 to lock. */ + while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK_MASK)) {} + + /* 7. Set the PLL1 P-divider to divide by 2 (DIRECT=0, PSEL=0). */ + CGU_PLL1_CTRL &= ~CGU_PLL1_CTRL_DIRECT_MASK; + + /* 8. Select PLL1 as BASE_M4_CLK source. */ + reg_val = CGU_BASE_M4_CLK; + reg_val &= ~CGU_BASE_M4_CLK_CLK_SEL_MASK; + reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_PLL1); + CGU_BASE_M4_CLK = reg_val; + + /* 9. Wait 50us. */ + delay_us_at_mhz(50, 102); + + /* 10. Set the PLL1 P-divider to direct output mode (DIRECT=1). */ + CGU_PLL1_CTRL |= CGU_PLL1_CTRL_DIRECT_MASK; +} + +/* clock startup for LPC4320 configure PLL1 to max speed (204MHz). +Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. */ +void cpu_clock_init(void) +{ + /* use IRC as clock source for APB1 (including I2C0) */ + CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_IRC); + + /* use IRC as clock source for APB3 */ + CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_IRC); + + //FIXME disable I2C + /* Kick I2C0 down to 400kHz when we switch over to APB1 clock = 204MHz */ + i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_fast_clock); + + /* + * 12MHz clock is entering LPC XTAL1/OSC input now. + * On HackRF One and Jawbreaker, there is a 12 MHz crystal at the LPC. + * Set up PLL1 to run from XTAL1 input. + */ + + //FIXME a lot of the details here should be in a CGU driver + + /* set xtal oscillator to low frequency mode */ + CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_HF_MASK; + + cpu_clock_pll1_max_speed(); + + /* use XTAL_OSC as clock source for APB1 */ + CGU_BASE_APB1_CLK = + CGU_BASE_APB1_CLK_AUTOBLOCK(1) | CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_XTAL); + + /* use XTAL_OSC as clock source for APB3 */ + CGU_BASE_APB3_CLK = + CGU_BASE_APB3_CLK_AUTOBLOCK(1) | CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_XTAL); + + /* use XTAL_OSC as clock source for PLL0USB */ + CGU_PLL0USB_CTRL = CGU_PLL0USB_CTRL_PD(1) | CGU_PLL0USB_CTRL_AUTOBLOCK(1) | + CGU_PLL0USB_CTRL_CLK_SEL(CGU_SRC_XTAL); + while (CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK) {} + + /* configure PLL0USB to produce 480 MHz clock from 12 MHz XTAL_OSC */ + /* Values from User Manual v1.4 Table 94, for 12MHz oscillator. */ + CGU_PLL0USB_MDIV = 0x06167FFA; + CGU_PLL0USB_NP_DIV = 0x00302062; + CGU_PLL0USB_CTRL |= + (CGU_PLL0USB_CTRL_PD(1) | CGU_PLL0USB_CTRL_DIRECTI(1) | + CGU_PLL0USB_CTRL_DIRECTO(1) | CGU_PLL0USB_CTRL_CLKEN(1)); + + /* power on PLL0USB and wait until stable */ + CGU_PLL0USB_CTRL &= ~CGU_PLL0USB_CTRL_PD_MASK; + while (!(CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK)) {} + + /* use PLL0USB as clock source for USB0 */ + CGU_BASE_USB0_CLK = CGU_BASE_USB0_CLK_AUTOBLOCK(1) | + CGU_BASE_USB0_CLK_CLK_SEL(CGU_SRC_PLL0USB); + + /* Switch peripheral clock over to use PLL1 (204MHz) */ + CGU_BASE_PERIPH_CLK = CGU_BASE_PERIPH_CLK_AUTOBLOCK(1) | + CGU_BASE_PERIPH_CLK_CLK_SEL(CGU_SRC_PLL1); + + /* Switch APB1 clock over to use PLL1 (204MHz) */ + CGU_BASE_APB1_CLK = + CGU_BASE_APB1_CLK_AUTOBLOCK(1) | CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_PLL1); + + /* Switch APB3 clock over to use PLL1 (204MHz) */ + CGU_BASE_APB3_CLK = + CGU_BASE_APB3_CLK_AUTOBLOCK(1) | CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_PLL1); + + CGU_BASE_SSP0_CLK = + CGU_BASE_SSP0_CLK_AUTOBLOCK(1) | CGU_BASE_SSP0_CLK_CLK_SEL(CGU_SRC_PLL1); + + CGU_BASE_SSP1_CLK = + CGU_BASE_SSP1_CLK_AUTOBLOCK(1) | CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1); + +#ifdef IS_NOT_RAD1O + if (IS_NOT_RAD1O) { + /* Disable unused clocks */ + /* Start with PLLs */ + CGU_PLL0AUDIO_CTRL = CGU_PLL0AUDIO_CTRL_PD(1); + + /* Dividers */ + CGU_IDIVA_CTRL = CGU_IDIVA_CTRL_PD(1); + CGU_IDIVB_CTRL = CGU_IDIVB_CTRL_PD(1); + CGU_IDIVC_CTRL = CGU_IDIVC_CTRL_PD(1); + CGU_IDIVD_CTRL = CGU_IDIVD_CTRL_PD(1); + CGU_IDIVE_CTRL = CGU_IDIVE_CTRL_PD(1); + + /* Base clocks */ + CGU_BASE_SPIFI_CLK = + CGU_BASE_SPIFI_CLK_PD(1); /* SPIFI is only used at boot */ + CGU_BASE_USB1_CLK = + CGU_BASE_USB1_CLK_PD(1); /* USB1 is not exposed on HackRF */ + CGU_BASE_PHY_RX_CLK = CGU_BASE_PHY_RX_CLK_PD(1); + CGU_BASE_PHY_TX_CLK = CGU_BASE_PHY_TX_CLK_PD(1); + CGU_BASE_LCD_CLK = CGU_BASE_LCD_CLK_PD(1); + CGU_BASE_VADC_CLK = CGU_BASE_VADC_CLK_PD(1); + CGU_BASE_SDIO_CLK = CGU_BASE_SDIO_CLK_PD(1); + CGU_BASE_UART0_CLK = CGU_BASE_UART0_CLK_PD(1); + CGU_BASE_UART1_CLK = CGU_BASE_UART1_CLK_PD(1); + CGU_BASE_UART2_CLK = CGU_BASE_UART2_CLK_PD(1); + CGU_BASE_UART3_CLK = CGU_BASE_UART3_CLK_PD(1); + CGU_BASE_OUT_CLK = CGU_BASE_OUT_CLK_PD(1); + CGU_BASE_AUDIO_CLK = CGU_BASE_AUDIO_CLK_PD(1); + CGU_BASE_CGU_OUT0_CLK = CGU_BASE_CGU_OUT0_CLK_PD(1); + CGU_BASE_CGU_OUT1_CLK = CGU_BASE_CGU_OUT1_CLK_PD(1); + + /* Disable unused peripheral clocks */ + CCU1_CLK_APB1_CAN1_CFG = 0; + CCU1_CLK_APB1_I2S_CFG = 0; + CCU1_CLK_APB1_MOTOCONPWM_CFG = 0; + //CCU1_CLK_APB3_ADC0_CFG = 0; + CCU1_CLK_APB3_ADC1_CFG = 0; + CCU1_CLK_APB3_CAN0_CFG = 0; + CCU1_CLK_APB3_DAC_CFG = 0; + //CCU1_CLK_M4_DMA_CFG = 0; + CCU1_CLK_M4_EMC_CFG = 0; + CCU1_CLK_M4_EMCDIV_CFG = 0; + CCU1_CLK_M4_ETHERNET_CFG = 0; + CCU1_CLK_M4_LCD_CFG = 0; + CCU1_CLK_M4_QEI_CFG = 0; + CCU1_CLK_M4_RITIMER_CFG = 0; + // CCU1_CLK_M4_SCT_CFG = 0; + CCU1_CLK_M4_SDIO_CFG = 0; + CCU1_CLK_M4_SPIFI_CFG = 0; + CCU1_CLK_M4_TIMER0_CFG = 0; + //CCU1_CLK_M4_TIMER1_CFG = 0; + //CCU1_CLK_M4_TIMER2_CFG = 0; + CCU1_CLK_M4_TIMER3_CFG = 0; + CCU1_CLK_M4_UART1_CFG = 0; + CCU1_CLK_M4_USART0_CFG = 0; + CCU1_CLK_M4_USART2_CFG = 0; + CCU1_CLK_M4_USART3_CFG = 0; + CCU1_CLK_M4_USB1_CFG = 0; + CCU1_CLK_M4_VADC_CFG = 0; + // CCU1_CLK_SPIFI_CFG = 0; + // CCU1_CLK_USB1_CFG = 0; + // CCU1_CLK_VADC_CFG = 0; + // CCU2_CLK_APB0_UART1_CFG = 0; + // CCU2_CLK_APB0_USART0_CFG = 0; + // CCU2_CLK_APB2_USART2_CFG = 0; + // CCU2_CLK_APB2_USART3_CFG = 0; + // CCU2_CLK_APLL_CFG = 0; + // CCU2_CLK_SDIO_CFG = 0; + } +#endif +} diff --git a/firmware/common/cpu_clock.h b/firmware/common/cpu_clock.h new file mode 100644 index 00000000..b0393081 --- /dev/null +++ b/firmware/common/cpu_clock.h @@ -0,0 +1,34 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "platform_detect.h" // IWYU pragma: keep + +void cpu_clock_init(void); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index d5679942..e9bc4c2e 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -21,17 +21,12 @@ * Boston, MA 02110-1301, USA. */ -#include #include #include #include #include "platform_detect.h" -#ifdef IS_NOT_RAD1O - #include -#endif - #include "delay.h" #include "gpio.h" #include "hackrf_core.h" @@ -44,14 +39,12 @@ #include "spi_bus.h" #include "w25q80bv_target.h" #ifdef IS_EXPANSION_COMPATIBLE - #include "portapack.h" + #include "portapack.h" #endif #ifdef IS_PRALINE #include "ice40_spi.h" #endif -#include - i2c_bus_t i2c0 = { .obj = (void*) I2C0_BASE, .start = i2c_lpc_start, @@ -428,222 +421,6 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) return resultant_rate; } -/* -Configure PLL1 (Main MCU Clock) to max speed (204MHz). -Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. -This function shall be called after cpu_clock_init(). -*/ -static void cpu_clock_pll1_max_speed(void) -{ - uint32_t reg_val; - - /* This function implements the sequence recommended in: - * UM10503 Rev 2.4 (Aug 2018), section 13.2.1.1, page 167. */ - - /* 1. Select the IRC as BASE_M4_CLK source. */ - reg_val = CGU_BASE_M4_CLK; - reg_val &= ~CGU_BASE_M4_CLK_CLK_SEL_MASK; - reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_IRC) | CGU_BASE_M4_CLK_AUTOBLOCK(1); - CGU_BASE_M4_CLK = reg_val; - - /* 2. Enable the crystal oscillator. */ - CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_ENABLE_MASK; - - /* 3. Wait 250us. */ - delay_us_at_mhz(250, 12); - - /* 4. Set the AUTOBLOCK bit. */ - CGU_PLL1_CTRL |= CGU_PLL1_CTRL_AUTOBLOCK(1); - - /* 5. Reconfigure PLL1 to produce the final output frequency, with the - * crystal oscillator as clock source. */ - reg_val = CGU_PLL1_CTRL; - // clang-format off - reg_val &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | - CGU_PLL1_CTRL_PD_MASK | - CGU_PLL1_CTRL_FBSEL_MASK | - CGU_PLL1_CTRL_BYPASS_MASK | - CGU_PLL1_CTRL_DIRECT_MASK | - CGU_PLL1_CTRL_PSEL_MASK | - CGU_PLL1_CTRL_MSEL_MASK | - CGU_PLL1_CTRL_NSEL_MASK ); - /* Set PLL1 up to 12MHz * 17 = 204MHz. - * Direct mode: FCLKOUT = FCCO = M*(FCLKIN/N) */ - reg_val |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL) | - CGU_PLL1_CTRL_PSEL(0) | - CGU_PLL1_CTRL_NSEL(0) | - CGU_PLL1_CTRL_MSEL(16) | - CGU_PLL1_CTRL_FBSEL(0) | - CGU_PLL1_CTRL_DIRECT(1); - // clang-format on - CGU_PLL1_CTRL = reg_val; - - /* 6. Wait for PLL1 to lock. */ - while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK_MASK)) {} - - /* 7. Set the PLL1 P-divider to divide by 2 (DIRECT=0, PSEL=0). */ - CGU_PLL1_CTRL &= ~CGU_PLL1_CTRL_DIRECT_MASK; - - /* 8. Select PLL1 as BASE_M4_CLK source. */ - reg_val = CGU_BASE_M4_CLK; - reg_val &= ~CGU_BASE_M4_CLK_CLK_SEL_MASK; - reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_PLL1); - CGU_BASE_M4_CLK = reg_val; - - /* 9. Wait 50us. */ - delay_us_at_mhz(50, 102); - - /* 10. Set the PLL1 P-divider to direct output mode (DIRECT=1). */ - CGU_PLL1_CTRL |= CGU_PLL1_CTRL_DIRECT_MASK; -} - -/* clock startup for LPC4320 configure PLL1 to max speed (204MHz). -Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. */ -void cpu_clock_init(void) -{ - /* use IRC as clock source for APB1 (including I2C0) */ - CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_IRC); - - /* use IRC as clock source for APB3 */ - CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_IRC); - - //FIXME disable I2C - /* Kick I2C0 down to 400kHz when we switch over to APB1 clock = 204MHz */ - i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_fast_clock); - - /* - * 12MHz clock is entering LPC XTAL1/OSC input now. - * On HackRF One and Jawbreaker, there is a 12 MHz crystal at the LPC. - * Set up PLL1 to run from XTAL1 input. - */ - - //FIXME a lot of the details here should be in a CGU driver - - /* set xtal oscillator to low frequency mode */ - CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_HF_MASK; - - cpu_clock_pll1_max_speed(); - - /* use XTAL_OSC as clock source for APB1 */ - CGU_BASE_APB1_CLK = - CGU_BASE_APB1_CLK_AUTOBLOCK(1) | CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_XTAL); - - /* use XTAL_OSC as clock source for APB3 */ - CGU_BASE_APB3_CLK = - CGU_BASE_APB3_CLK_AUTOBLOCK(1) | CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_XTAL); - - /* use XTAL_OSC as clock source for PLL0USB */ - CGU_PLL0USB_CTRL = CGU_PLL0USB_CTRL_PD(1) | CGU_PLL0USB_CTRL_AUTOBLOCK(1) | - CGU_PLL0USB_CTRL_CLK_SEL(CGU_SRC_XTAL); - while (CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK) {} - - /* configure PLL0USB to produce 480 MHz clock from 12 MHz XTAL_OSC */ - /* Values from User Manual v1.4 Table 94, for 12MHz oscillator. */ - CGU_PLL0USB_MDIV = 0x06167FFA; - CGU_PLL0USB_NP_DIV = 0x00302062; - CGU_PLL0USB_CTRL |= - (CGU_PLL0USB_CTRL_PD(1) | CGU_PLL0USB_CTRL_DIRECTI(1) | - CGU_PLL0USB_CTRL_DIRECTO(1) | CGU_PLL0USB_CTRL_CLKEN(1)); - - /* power on PLL0USB and wait until stable */ - CGU_PLL0USB_CTRL &= ~CGU_PLL0USB_CTRL_PD_MASK; - while (!(CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK)) {} - - /* use PLL0USB as clock source for USB0 */ - CGU_BASE_USB0_CLK = CGU_BASE_USB0_CLK_AUTOBLOCK(1) | - CGU_BASE_USB0_CLK_CLK_SEL(CGU_SRC_PLL0USB); - - /* Switch peripheral clock over to use PLL1 (204MHz) */ - CGU_BASE_PERIPH_CLK = CGU_BASE_PERIPH_CLK_AUTOBLOCK(1) | - CGU_BASE_PERIPH_CLK_CLK_SEL(CGU_SRC_PLL1); - - /* Switch APB1 clock over to use PLL1 (204MHz) */ - CGU_BASE_APB1_CLK = - CGU_BASE_APB1_CLK_AUTOBLOCK(1) | CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_PLL1); - - /* Switch APB3 clock over to use PLL1 (204MHz) */ - CGU_BASE_APB3_CLK = - CGU_BASE_APB3_CLK_AUTOBLOCK(1) | CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_PLL1); - - CGU_BASE_SSP0_CLK = - CGU_BASE_SSP0_CLK_AUTOBLOCK(1) | CGU_BASE_SSP0_CLK_CLK_SEL(CGU_SRC_PLL1); - - CGU_BASE_SSP1_CLK = - CGU_BASE_SSP1_CLK_AUTOBLOCK(1) | CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1); - -#ifdef IS_NOT_RAD1O - if (IS_NOT_RAD1O) { - /* Disable unused clocks */ - /* Start with PLLs */ - CGU_PLL0AUDIO_CTRL = CGU_PLL0AUDIO_CTRL_PD(1); - - /* Dividers */ - CGU_IDIVA_CTRL = CGU_IDIVA_CTRL_PD(1); - CGU_IDIVB_CTRL = CGU_IDIVB_CTRL_PD(1); - CGU_IDIVC_CTRL = CGU_IDIVC_CTRL_PD(1); - CGU_IDIVD_CTRL = CGU_IDIVD_CTRL_PD(1); - CGU_IDIVE_CTRL = CGU_IDIVE_CTRL_PD(1); - - /* Base clocks */ - CGU_BASE_SPIFI_CLK = - CGU_BASE_SPIFI_CLK_PD(1); /* SPIFI is only used at boot */ - CGU_BASE_USB1_CLK = - CGU_BASE_USB1_CLK_PD(1); /* USB1 is not exposed on HackRF */ - CGU_BASE_PHY_RX_CLK = CGU_BASE_PHY_RX_CLK_PD(1); - CGU_BASE_PHY_TX_CLK = CGU_BASE_PHY_TX_CLK_PD(1); - CGU_BASE_LCD_CLK = CGU_BASE_LCD_CLK_PD(1); - CGU_BASE_VADC_CLK = CGU_BASE_VADC_CLK_PD(1); - CGU_BASE_SDIO_CLK = CGU_BASE_SDIO_CLK_PD(1); - CGU_BASE_UART0_CLK = CGU_BASE_UART0_CLK_PD(1); - CGU_BASE_UART1_CLK = CGU_BASE_UART1_CLK_PD(1); - CGU_BASE_UART2_CLK = CGU_BASE_UART2_CLK_PD(1); - CGU_BASE_UART3_CLK = CGU_BASE_UART3_CLK_PD(1); - CGU_BASE_OUT_CLK = CGU_BASE_OUT_CLK_PD(1); - CGU_BASE_AUDIO_CLK = CGU_BASE_AUDIO_CLK_PD(1); - CGU_BASE_CGU_OUT0_CLK = CGU_BASE_CGU_OUT0_CLK_PD(1); - CGU_BASE_CGU_OUT1_CLK = CGU_BASE_CGU_OUT1_CLK_PD(1); - - /* Disable unused peripheral clocks */ - CCU1_CLK_APB1_CAN1_CFG = 0; - CCU1_CLK_APB1_I2S_CFG = 0; - CCU1_CLK_APB1_MOTOCONPWM_CFG = 0; - //CCU1_CLK_APB3_ADC0_CFG = 0; - CCU1_CLK_APB3_ADC1_CFG = 0; - CCU1_CLK_APB3_CAN0_CFG = 0; - CCU1_CLK_APB3_DAC_CFG = 0; - //CCU1_CLK_M4_DMA_CFG = 0; - CCU1_CLK_M4_EMC_CFG = 0; - CCU1_CLK_M4_EMCDIV_CFG = 0; - CCU1_CLK_M4_ETHERNET_CFG = 0; - CCU1_CLK_M4_LCD_CFG = 0; - CCU1_CLK_M4_QEI_CFG = 0; - CCU1_CLK_M4_RITIMER_CFG = 0; - // CCU1_CLK_M4_SCT_CFG = 0; - CCU1_CLK_M4_SDIO_CFG = 0; - CCU1_CLK_M4_SPIFI_CFG = 0; - CCU1_CLK_M4_TIMER0_CFG = 0; - //CCU1_CLK_M4_TIMER1_CFG = 0; - //CCU1_CLK_M4_TIMER2_CFG = 0; - CCU1_CLK_M4_TIMER3_CFG = 0; - CCU1_CLK_M4_UART1_CFG = 0; - CCU1_CLK_M4_USART0_CFG = 0; - CCU1_CLK_M4_USART2_CFG = 0; - CCU1_CLK_M4_USART3_CFG = 0; - CCU1_CLK_M4_USB1_CFG = 0; - CCU1_CLK_M4_VADC_CFG = 0; - // CCU1_CLK_SPIFI_CFG = 0; - // CCU1_CLK_USB1_CFG = 0; - // CCU1_CLK_VADC_CFG = 0; - // CCU2_CLK_APB0_UART1_CFG = 0; - // CCU2_CLK_APB0_USART0_CFG = 0; - // CCU2_CLK_APB2_USART2_CFG = 0; - // CCU2_CLK_APB2_USART3_CFG = 0; - // CCU2_CLK_APLL_CFG = 0; - // CCU2_CLK_SDIO_CFG = 0; - } -#endif -} - void clock_gen_init(void) { i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_fast_clock); diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 56221f6b..334d74a0 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -33,6 +33,7 @@ extern "C" { #include "cpld_jtag.h" #include "fixed_point.h" #include "i2c_bus.h" +#include "i2c_lpc.h" #include "max283x.h" #include "max5864.h" #include "mixer.h" @@ -49,6 +50,7 @@ extern "C" { #endif /* TODO: Hide these configurations */ +extern const i2c_lpc_config_t i2c_config_si5351c_fast_clock; extern si5351c_driver_t clock_gen; extern ssp_config_t ssp_config_w25q80bv; @@ -67,7 +69,6 @@ extern rf_path_t rf_path; extern jtag_t jtag_cpld; extern i2c_bus_t i2c0; -void cpu_clock_init(void); void clock_gen_init(void); void clock_gen_shutdown(void); void ssp1_set_mode_max283x(void); diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 9a349b1e..a2823405 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -168,6 +168,7 @@ endmacro() macro(DeclareTargets) SET(SRC_M4 ${SRC_M4} + ${PATH_HACKRF_FIRMWARE_COMMON}/cpu_clock.c ${PATH_HACKRF_FIRMWARE_COMMON}/delay.c ${PATH_HACKRF_FIRMWARE_COMMON}/hackrf_core.c ${PATH_HACKRF_FIRMWARE_COMMON}/sgpio.c diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index b79dcdec..dba9a39e 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include From b8cd1d51a7e3d605b238a68f6051c74c5e1bc8ca Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 19 Mar 2026 11:04:47 +0200 Subject: [PATCH 136/238] firmware: move clock generator logic to clock_gen.h|c --- firmware/common/clock_gen.c | 452 ++++++++++++++++++++++ firmware/common/clock_gen.h | 76 ++++ firmware/common/fpga_selftest.c | 1 + firmware/common/hackrf_core.c | 416 +------------------- firmware/common/hackrf_core.h | 27 -- firmware/common/hackrf_ui.h | 2 +- firmware/common/radio.h | 7 - firmware/common/ui_portapack.c | 2 +- firmware/common/ui_rad1o.c | 5 +- firmware/hackrf-common.cmake | 1 + firmware/hackrf_usb/hackrf_usb.c | 1 + firmware/hackrf_usb/usb_api_board_info.c | 1 + firmware/hackrf_usb/usb_api_praline.c | 1 + firmware/hackrf_usb/usb_api_transceiver.c | 1 + 14 files changed, 541 insertions(+), 452 deletions(-) create mode 100644 firmware/common/clock_gen.c create mode 100644 firmware/common/clock_gen.h diff --git a/firmware/common/clock_gen.c b/firmware/common/clock_gen.c new file mode 100644 index 00000000..e29e5a91 --- /dev/null +++ b/firmware/common/clock_gen.c @@ -0,0 +1,452 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "clock_gen.h" + +#include + +#include "hackrf_core.h" +#include "hackrf_ui.h" +#include "i2c_bus.h" +#include "platform_detect.h" +#include "sgpio.h" +#include "si5351c.h" +#if defined(IS_HACKRF_ONE) || defined(IS_PRALINE) + #include "delay.h" + #include "portapack.h" +#endif +#if defined(IS_PRALINE) + #include "gpio.h" + #include "platform_gpio.h" +#endif + +void clock_gen_init(void) +{ + i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_fast_clock); + + si5351c_init(&clock_gen); + si5351c_disable_all_outputs(&clock_gen); + si5351c_disable_oeb_pin_control(&clock_gen); + si5351c_power_down_all_clocks(&clock_gen); + si5351c_set_crystal_configuration(&clock_gen); + si5351c_enable_xo_and_ms_fanout(&clock_gen); + + /* + * Clocks on HackRF One r9: + * CLK0 -> MAX5864/CPLD/SGPIO (sample clocks) + * CLK1 -> RFFC5072/MAX2839 + * CLK2 -> External Clock Output/LPC43xx (power down at boot) + * + * Clocks on other platforms: + * CLK0 -> MAX5864/CPLD + * CLK1 -> CPLD + * CLK2 -> SGPIO + * CLK3 -> External Clock Output (power down at boot) + * CLK4 -> RFFC5072 (MAX2837 on rad1o) + * CLK5 -> MAX2837 (MAX2871 on rad1o) + * CLK6 -> none + * CLK7 -> LPC43xx (uses a 12MHz crystal by default) + * + * Clocks on Praline: + * CLK0 -> AFE_CLK (MAX5864/FPGA) + * CLK1 -> SCT_CLK + * CLK2 -> MCU_CLK (uses a 12MHz crystal by default) + * CLK3 -> External Clock Output (power down at boot) + * CLK4 -> XCVR_CLK (MAX2837) + * CLK5 -> MIX_CLK (RFFC5072) + * CLK6 -> AUX_CLK1 + * CLK7 -> AUX_CLK2 + */ + +#ifdef IS_H1_R9 + if (IS_H1_R9) { + /* MS0/CLK0 is the reference for both RFFC5071 and MAX2839. */ + si5351c_configure_multisynth( + &clock_gen, + 0, + 20 * 128 - 512, + 0, + 1, + 0); /* 800/20 = 40MHz */ + } +#endif +#ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { + /* MS4/CLK4 is the source for the RFFC5071 mixer (MAX2837 on rad1o). */ + si5351c_configure_multisynth( + &clock_gen, + 4, + 20 * 128 - 512, + 0, + 1, + 0); /* 800/20 = 40MHz */ + /* MS5/CLK5 is the source for the MAX2837 clock input (MAX2871 on rad1o). */ + si5351c_configure_multisynth( + &clock_gen, + 5, + 20 * 128 - 512, + 0, + 1, + 0); /* 800/20 = 40MHz */ + } +#endif + + /* MS6/CLK6 is unused. */ + /* MS7/CLK7 is unused. */ + + /* Set to 10 MHz, the common rate between Jawbreaker and HackRF One. */ + sample_rate_set(SR_FP_MHZ(10), true); + + si5351c_configure_clock_control(&clock_gen); + si5351c_set_clock_source(&clock_gen, PLL_SOURCE_XTAL); + // soft reset + si5351c_reset_pll(&clock_gen, SI5351C_PLL_BOTH); + si5351c_enable_clock_outputs(&clock_gen); +} + +void clock_gen_shutdown(void) +{ + i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_fast_clock); + si5351c_disable_all_outputs(&clock_gen); + si5351c_disable_oeb_pin_control(&clock_gen); + si5351c_power_down_all_clocks(&clock_gen); +} + +clock_source_t activate_best_clock_source(void) +{ +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { + /* Ensure PortaPack reference oscillator is off while checking for external clock input. */ + if (portapack_reference_oscillator && portapack()) { + portapack_reference_oscillator(false); + } + } +#endif + + clock_source_t source = CLOCK_SOURCE_HACKRF; + + /* Check for external clock input. */ + if (si5351c_clkin_signal_valid(&clock_gen)) { + source = CLOCK_SOURCE_EXTERNAL; + } else { +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { + /* Enable PortaPack reference oscillator (if present), and check for valid clock. */ + if (portapack_reference_oscillator && portapack()) { + portapack_reference_oscillator(true); + delay(510000); /* loop iterations @ 204MHz for >10ms for oscillator to enable. */ + if (si5351c_clkin_signal_valid(&clock_gen)) { + source = CLOCK_SOURCE_PORTAPACK; + } else { + portapack_reference_oscillator(false); + } + } + } +#endif + /* No external or PortaPack clock was found. Use HackRF Si5351C crystal. */ + } + + si5351c_set_clock_source( + &clock_gen, + (source == CLOCK_SOURCE_HACKRF) ? PLL_SOURCE_XTAL : PLL_SOURCE_CLKIN); + hackrf_ui()->set_clock_source(source); + + return source; +} + +/* + * Closest fraction to m/d with denominator <= max_den. + * Returns result in *r / *s with gcd(*r, *s) == 1 and 0 < *s <= max_den. + * Straight port from CPython's fractions, and better documented there. + */ +void limit_denominator( + uint64_t m, + uint64_t d, + const uint64_t max_den, + uint64_t* r, + uint64_t* s) +{ + if (d <= max_den) { + *r = m; + *s = d; + return; + } + + uint64_t p0 = 0, q0 = 1, p1 = 1, q1 = 0; + uint64_t n = m, orig_d = d; + uint64_t tmp; + + while (1) { + uint64_t a = n / d; + uint64_t q2 = q0 + a * q1; + + if (q2 > max_den) + break; + + tmp = p0 + a * p1; + p0 = p1; + q0 = q1; + p1 = tmp; + q1 = q2; + + tmp = n - a * d; + n = d; + d = tmp; + if (d == 0) + break; + } + + uint64_t k = (max_den - q0) / q1; + + /* Return closer candidate. */ + if (2 * d * (q0 + k * q1) <= orig_d) { + *r = p1; + *s = q1; + } else { + *r = p0 + k * p1; + *s = q0 + k * q1; + } +} + +/* + * Configure clock generator to produce sample clock in units of 1/(2**36) Hz. + * Can be called with program=false for a dry run that returns the resultant + * frequency without actually configuring the clock generator. + * + * The clock generator output frequency is: + * + * fs = 128 * vco / (512 + p1 + p2/p3)) + * + * where p1, p2, and p3 are register values. + * + * For more information see: + * https://www.pa3fwm.nl/technotes/tn42a-si5351-programming.html + */ +fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) +{ + const uint64_t vco_hz = 800 * 1000ULL * 1000ULL; + uint64_t p1, p2, p3; + uint64_t n, d, q1, q2, q3, r1, r2; + fp_28_36_t resultant_rate; + + /* + * First double the sample rate so that we can produce a clock at twice + * the intended sample rate. The 2x clock is sometimes used directly, + * and it is divided by two in an output divider to produce the actual + * AFE clock. + */ + fp_28_36_t rate = sample_rate * 2; + + /* + * Computes p1 = (N << 36) / rate - 512, where N = 128 * vco_hz. + * + * Full numerator (N << 36) is 73 bits, so we split the division: + * + * (N << 36) / rate = ((N << 27) / rate) << 9 + * + (((N << 27) % rate) << 9) / rate + * + * IMPORTANT: Assumes sample rate is in [200e3 << 36, 43.6e6 << 36]. + */ + const uint64_t A = (128 * vco_hz) << 27; + + q1 = A / rate; + r1 = A % rate; + + // Remaining 9 bits with long division. + q2 = 0; + r2 = r1; + for (int j = 0; j < 9; j++) { + uint64_t msb = r2 >> 63; + r2 <<= 1; + q2 <<= 1; + if (msb || r2 >= rate) { + r2 -= rate; + q2 |= 1; + } + } + + p1 = (q1 << 9) + q2 - 512; + + if (r2) { + /* Use the remainder for the fractional part. */ + n = r2; + d = rate; + + /* Reduce fraction. */ + const uint64_t p3_max = 0xfffff; + limit_denominator(n, d, p3_max, &p2, &p3); + + /* Roll over to next p1 to enable integer mode. */ + if (p2 >= p3) { + p1++; + p2 = 0; + } + } else { + p2 = 0; + } + + /* Maximum: (128 * 2048) - 512 */ + if (p1 > 0x3fe00) { + p1 = 0x3fe00; + p2 = 0; + } + + if (p2 == 0) { + /* Use unity denominator for integer mode. */ + p3 = 1; + n = (128 * vco_hz) << 18; + d = (p1 + 512); + q1 = n / d; + r1 = n % d; + q2 = ((r1 << 18) + (d / 2)) / d; + resultant_rate = (q1 << 18) + q2; + } else { + n = p3 * vco_hz * 128; + d = p3 * (p1 + 512) + p2; + q1 = n / d; + r1 = n % d; + q2 = (r1 << 18) / d; + r2 = (r1 << 18) % d; + q3 = ((r2 << 18) + (d / 2)) / d; + resultant_rate = (q1 << 36) + (q2 << 18) + q3; + } + + /* Return MCU sample rate, not AFE clock rate. */ + resultant_rate = (resultant_rate + 1) / 2; + + if (!program) { + return resultant_rate; + } + + bool streaming = sgpio_cpld_stream_is_enabled(&sgpio_config); + + if (streaming) { + sgpio_cpld_stream_disable(&sgpio_config); + } + +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { + /* Integer mode can be enabled if p1 is even and p2 is zero. */ + if (p1 & 0x1 || p2) { + si5351c_set_int_mode(&clock_gen, 0, 0); + } else { + si5351c_set_int_mode(&clock_gen, 0, 1); + } + + #ifdef IS_H1_R9 + if (IS_H1_R9) { + /* + * On HackRF One r9 all sample clocks are externally derived + * from MS1/CLK1 operating at twice the sample rate. + */ + si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 0); + } + #endif + #ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { + /* + * On other platforms the clock generator produces three + * different sample clocks, all derived from multisynth 0. + */ + /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ + si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); + + /* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ + si5351c_configure_multisynth( + &clock_gen, + 1, + 0, + 0, + 0, + 0); //p1 doesn't matter + + /* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */ + si5351c_configure_multisynth( + &clock_gen, + 2, + 0, + 0, + 0, + 0); //p1 doesn't matter + } + #endif + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { + /* MS0/CLK0 is the source for the MAX5864 (AFE_CLK). */ + si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); + + /* MS1/CLK1 is the source for the FPGA (FPGA_CLK and SCT_CLK). */ + si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 1); + + /* Delay FPGA_CLK relative to AFE_CLK. */ + uint8_t phase_offset = 0; + if (p1 < 2100) { + phase_offset = (p1 >> 4) - 6; + } + si5351c_set_phase(&clock_gen, 1, phase_offset); + + if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { + /* + * On older boards FPGA_CLK is on CLK2 while SCT_CLK is on + * CLK1. We configure both so that behavior is consistent with + * newer boards that use CLK1 for both FPGA_CLK and SCT_CLK. + */ + si5351c_configure_multisynth(&clock_gen, 2, p1, p2, p3, 1); + si5351c_set_phase(&clock_gen, 2, phase_offset); + } + + /* Reset PLL to synchronize output clock phase. */ + si5351c_reset_pll(&clock_gen, SI5351C_PLL_A); + } +#endif + + if (streaming) { + sgpio_cpld_stream_enable(&sgpio_config); + } + + return resultant_rate; +} + +#ifdef IS_PRALINE +void p1_ctrl_set(const p1_ctrl_signal_t signal) +{ + const platform_gpio_t* gpio = platform_gpio(); + + gpio_write(gpio->p1_ctrl0, signal & 1); + gpio_write(gpio->p1_ctrl1, (signal >> 1) & 1); + gpio_write(gpio->p1_ctrl2, (signal >> 2) & 1); +} + +void p2_ctrl_set(const p2_ctrl_signal_t signal) +{ + const platform_gpio_t* gpio = platform_gpio(); + + gpio_write(gpio->p2_ctrl0, signal & 1); + gpio_write(gpio->p2_ctrl1, (signal >> 1) & 1); +} + +void pps_out_set(const uint8_t value) +{ + gpio_write(platform_gpio()->pps_out, value & 1); +} +#endif diff --git a/firmware/common/clock_gen.h b/firmware/common/clock_gen.h new file mode 100644 index 00000000..48fb6f20 --- /dev/null +++ b/firmware/common/clock_gen.h @@ -0,0 +1,76 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "platform_detect.h" // IWYU pragma: keep + +#include +#ifdef IS_PRALINE + #include +#endif + +#include "fixed_point.h" + +typedef enum { + CLOCK_SOURCE_HACKRF = 0, + CLOCK_SOURCE_EXTERNAL = 1, + CLOCK_SOURCE_PORTAPACK = 2, +} clock_source_t; + +void clock_gen_init(void); +void clock_gen_shutdown(void); + +clock_source_t activate_best_clock_source(void); + +fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program); + +#ifdef IS_PRALINE +typedef enum { + P1_SIGNAL_TRIGGER_IN = 0, + P1_SIGNAL_AUX_CLK1 = 1, + P1_SIGNAL_CLKIN = 2, + P1_SIGNAL_TRIGGER_OUT = 3, + P1_SIGNAL_P22_CLKIN = 4, + P1_SIGNAL_P2_5 = 5, + P1_SIGNAL_NC = 6, + P1_SIGNAL_AUX_CLK2 = 7, +} p1_ctrl_signal_t; + +typedef enum { + P2_SIGNAL_CLK3 = 0, + P2_SIGNAL_TRIGGER_IN = 2, + P2_SIGNAL_TRIGGER_OUT = 3, +} p2_ctrl_signal_t; + +void p1_ctrl_set(const p1_ctrl_signal_t signal); +void p2_ctrl_set(const p2_ctrl_signal_t signal); + +void pps_out_set(const uint8_t value); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index 270d3ff4..fe0a96f9 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -23,6 +23,7 @@ #include #include +#include "clock_gen.h" #include "delay.h" #include "fixed_point.h" #include "fpga.h" diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index e9bc4c2e..c8b12842 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -27,10 +27,10 @@ #include "platform_detect.h" +#include "clock_gen.h" #include "delay.h" #include "gpio.h" #include "hackrf_core.h" -#include "hackrf_ui.h" #include "i2c_lpc.h" #include "max283x.h" #include "max5864_target.h" @@ -38,9 +38,6 @@ #include "platform_scu.h" #include "spi_bus.h" #include "w25q80bv_target.h" -#ifdef IS_EXPANSION_COMPATIBLE - #include "portapack.h" -#endif #ifdef IS_PRALINE #include "ice40_spi.h" #endif @@ -166,395 +163,6 @@ jtag_t jtag_cpld = { .gpio = &jtag_gpio_cpld, }; -/* - * Closest fraction to m/d with denominator <= max_den. - * Returns result in *r / *s with gcd(*r, *s) == 1 and 0 < *s <= max_den. - * Straight port from CPython's fractions, and better documented there. - */ -void limit_denominator( - uint64_t m, - uint64_t d, - const uint64_t max_den, - uint64_t* r, - uint64_t* s) -{ - if (d <= max_den) { - *r = m; - *s = d; - return; - } - - uint64_t p0 = 0, q0 = 1, p1 = 1, q1 = 0; - uint64_t n = m, orig_d = d; - uint64_t tmp; - - while (1) { - uint64_t a = n / d; - uint64_t q2 = q0 + a * q1; - - if (q2 > max_den) - break; - - tmp = p0 + a * p1; - p0 = p1; - q0 = q1; - p1 = tmp; - q1 = q2; - - tmp = n - a * d; - n = d; - d = tmp; - if (d == 0) - break; - } - - uint64_t k = (max_den - q0) / q1; - - /* Return closer candidate. */ - if (2 * d * (q0 + k * q1) <= orig_d) { - *r = p1; - *s = q1; - } else { - *r = p0 + k * p1; - *s = q0 + k * q1; - } -} - -/* - * Configure clock generator to produce sample clock in units of 1/(2**36) Hz. - * Can be called with program=false for a dry run that returns the resultant - * frequency without actually configuring the clock generator. - * - * The clock generator output frequency is: - * - * fs = 128 * vco / (512 + p1 + p2/p3)) - * - * where p1, p2, and p3 are register values. - * - * For more information see: - * https://www.pa3fwm.nl/technotes/tn42a-si5351-programming.html - */ -fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) -{ - const uint64_t vco_hz = 800 * 1000ULL * 1000ULL; - uint64_t p1, p2, p3; - uint64_t n, d, q1, q2, q3, r1, r2; - fp_28_36_t resultant_rate; - - /* - * First double the sample rate so that we can produce a clock at twice - * the intended sample rate. The 2x clock is sometimes used directly, - * and it is divided by two in an output divider to produce the actual - * AFE clock. - */ - fp_28_36_t rate = sample_rate * 2; - - /* - * Computes p1 = (N << 36) / rate - 512, where N = 128 * vco_hz. - * - * Full numerator (N << 36) is 73 bits, so we split the division: - * - * (N << 36) / rate = ((N << 27) / rate) << 9 - * + (((N << 27) % rate) << 9) / rate - * - * IMPORTANT: Assumes sample rate is in [200e3 << 36, 43.6e6 << 36]. - */ - const uint64_t A = (128 * vco_hz) << 27; - - q1 = A / rate; - r1 = A % rate; - - // Remaining 9 bits with long division. - q2 = 0; - r2 = r1; - for (int j = 0; j < 9; j++) { - uint64_t msb = r2 >> 63; - r2 <<= 1; - q2 <<= 1; - if (msb || r2 >= rate) { - r2 -= rate; - q2 |= 1; - } - } - - p1 = (q1 << 9) + q2 - 512; - - if (r2) { - /* Use the remainder for the fractional part. */ - n = r2; - d = rate; - - /* Reduce fraction. */ - const uint64_t p3_max = 0xfffff; - limit_denominator(n, d, p3_max, &p2, &p3); - - /* Roll over to next p1 to enable integer mode. */ - if (p2 >= p3) { - p1++; - p2 = 0; - } - } else { - p2 = 0; - } - - /* Maximum: (128 * 2048) - 512 */ - if (p1 > 0x3fe00) { - p1 = 0x3fe00; - p2 = 0; - } - - if (p2 == 0) { - /* Use unity denominator for integer mode. */ - p3 = 1; - n = (128 * vco_hz) << 18; - d = (p1 + 512); - q1 = n / d; - r1 = n % d; - q2 = ((r1 << 18) + (d / 2)) / d; - resultant_rate = (q1 << 18) + q2; - } else { - n = p3 * vco_hz * 128; - d = p3 * (p1 + 512) + p2; - q1 = n / d; - r1 = n % d; - q2 = (r1 << 18) / d; - r2 = (r1 << 18) % d; - q3 = ((r2 << 18) + (d / 2)) / d; - resultant_rate = (q1 << 36) + (q2 << 18) + q3; - } - - /* Return MCU sample rate, not AFE clock rate. */ - resultant_rate = (resultant_rate + 1) / 2; - - if (!program) { - return resultant_rate; - } - - bool streaming = sgpio_cpld_stream_is_enabled(&sgpio_config); - - if (streaming) { - sgpio_cpld_stream_disable(&sgpio_config); - } - -#ifdef IS_NOT_PRALINE - if (IS_NOT_PRALINE) { - /* Integer mode can be enabled if p1 is even and p2 is zero. */ - if (p1 & 0x1 || p2) { - si5351c_set_int_mode(&clock_gen, 0, 0); - } else { - si5351c_set_int_mode(&clock_gen, 0, 1); - } - - #ifdef IS_H1_R9 - if (IS_H1_R9) { - /* - * On HackRF One r9 all sample clocks are externally derived - * from MS1/CLK1 operating at twice the sample rate. - */ - si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 0); - } - #endif - #ifdef IS_NOT_H1_R9 - if (IS_NOT_H1_R9) { - /* - * On other platforms the clock generator produces three - * different sample clocks, all derived from multisynth 0. - */ - /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ - si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); - - /* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ - si5351c_configure_multisynth( - &clock_gen, - 1, - 0, - 0, - 0, - 0); //p1 doesn't matter - - /* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */ - si5351c_configure_multisynth( - &clock_gen, - 2, - 0, - 0, - 0, - 0); //p1 doesn't matter - } - #endif - } -#endif -#ifdef IS_PRALINE - if (IS_PRALINE) { - /* MS0/CLK0 is the source for the MAX5864 (AFE_CLK). */ - si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); - - /* MS1/CLK1 is the source for the FPGA (FPGA_CLK and SCT_CLK). */ - si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 1); - - /* Delay FPGA_CLK relative to AFE_CLK. */ - uint8_t phase_offset = 0; - if (p1 < 2100) { - phase_offset = (p1 >> 4) - 6; - } - si5351c_set_phase(&clock_gen, 1, phase_offset); - - if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { - /* - * On older boards FPGA_CLK is on CLK2 while SCT_CLK is on - * CLK1. We configure both so that behavior is consistent with - * newer boards that use CLK1 for both FPGA_CLK and SCT_CLK. - */ - si5351c_configure_multisynth(&clock_gen, 2, p1, p2, p3, 1); - si5351c_set_phase(&clock_gen, 2, phase_offset); - } - - /* Reset PLL to synchronize output clock phase. */ - si5351c_reset_pll(&clock_gen, SI5351C_PLL_A); - } -#endif - - if (streaming) { - sgpio_cpld_stream_enable(&sgpio_config); - } - - return resultant_rate; -} - -void clock_gen_init(void) -{ - i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_fast_clock); - - si5351c_init(&clock_gen); - si5351c_disable_all_outputs(&clock_gen); - si5351c_disable_oeb_pin_control(&clock_gen); - si5351c_power_down_all_clocks(&clock_gen); - si5351c_set_crystal_configuration(&clock_gen); - si5351c_enable_xo_and_ms_fanout(&clock_gen); - - /* - * Clocks on HackRF One r9: - * CLK0 -> MAX5864/CPLD/SGPIO (sample clocks) - * CLK1 -> RFFC5072/MAX2839 - * CLK2 -> External Clock Output/LPC43xx (power down at boot) - * - * Clocks on other platforms: - * CLK0 -> MAX5864/CPLD - * CLK1 -> CPLD - * CLK2 -> SGPIO - * CLK3 -> External Clock Output (power down at boot) - * CLK4 -> RFFC5072 (MAX2837 on rad1o) - * CLK5 -> MAX2837 (MAX2871 on rad1o) - * CLK6 -> none - * CLK7 -> LPC43xx (uses a 12MHz crystal by default) - * - * Clocks on Praline: - * CLK0 -> AFE_CLK (MAX5864/FPGA) - * CLK1 -> SCT_CLK - * CLK2 -> MCU_CLK (uses a 12MHz crystal by default) - * CLK3 -> External Clock Output (power down at boot) - * CLK4 -> XCVR_CLK (MAX2837) - * CLK5 -> MIX_CLK (RFFC5072) - * CLK6 -> AUX_CLK1 - * CLK7 -> AUX_CLK2 - */ - -#ifdef IS_H1_R9 - if (IS_H1_R9) { - /* MS0/CLK0 is the reference for both RFFC5071 and MAX2839. */ - si5351c_configure_multisynth( - &clock_gen, - 0, - 20 * 128 - 512, - 0, - 1, - 0); /* 800/20 = 40MHz */ - } -#endif -#ifdef IS_NOT_H1_R9 - if (IS_NOT_H1_R9) { - /* MS4/CLK4 is the source for the RFFC5071 mixer (MAX2837 on rad1o). */ - si5351c_configure_multisynth( - &clock_gen, - 4, - 20 * 128 - 512, - 0, - 1, - 0); /* 800/20 = 40MHz */ - /* MS5/CLK5 is the source for the MAX2837 clock input (MAX2871 on rad1o). */ - si5351c_configure_multisynth( - &clock_gen, - 5, - 20 * 128 - 512, - 0, - 1, - 0); /* 800/20 = 40MHz */ - } -#endif - - /* MS6/CLK6 is unused. */ - /* MS7/CLK7 is unused. */ - - /* Set to 10 MHz, the common rate between Jawbreaker and HackRF One. */ - sample_rate_set(SR_FP_MHZ(10), true); - - si5351c_configure_clock_control(&clock_gen); - si5351c_set_clock_source(&clock_gen, PLL_SOURCE_XTAL); - // soft reset - si5351c_reset_pll(&clock_gen, SI5351C_PLL_BOTH); - si5351c_enable_clock_outputs(&clock_gen); -} - -void clock_gen_shutdown(void) -{ - i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_fast_clock); - si5351c_disable_all_outputs(&clock_gen); - si5351c_disable_oeb_pin_control(&clock_gen); - si5351c_power_down_all_clocks(&clock_gen); -} - -clock_source_t activate_best_clock_source(void) -{ -#ifdef IS_EXPANSION_COMPATIBLE - if (IS_EXPANSION_COMPATIBLE) { - /* Ensure PortaPack reference oscillator is off while checking for external clock input. */ - if (portapack_reference_oscillator && portapack()) { - portapack_reference_oscillator(false); - } - } -#endif - - clock_source_t source = CLOCK_SOURCE_HACKRF; - - /* Check for external clock input. */ - if (si5351c_clkin_signal_valid(&clock_gen)) { - source = CLOCK_SOURCE_EXTERNAL; - } else { -#ifdef IS_EXPANSION_COMPATIBLE - if (IS_EXPANSION_COMPATIBLE) { - /* Enable PortaPack reference oscillator (if present), and check for valid clock. */ - if (portapack_reference_oscillator && portapack()) { - portapack_reference_oscillator(true); - delay(510000); /* loop iterations @ 204MHz for >10ms for oscillator to enable. */ - if (si5351c_clkin_signal_valid(&clock_gen)) { - source = CLOCK_SOURCE_PORTAPACK; - } else { - portapack_reference_oscillator(false); - } - } - } -#endif - /* No external or PortaPack clock was found. Use HackRF Si5351C crystal. */ - } - - si5351c_set_clock_source( - &clock_gen, - (source == CLOCK_SOURCE_HACKRF) ? PLL_SOURCE_XTAL : PLL_SOURCE_CLKIN); - hackrf_ui()->set_clock_source(source); - - return source; -} - void ssp1_set_mode_max283x(void) { spi_bus_start(&spi_bus_ssp1, &ssp_config_max283x); @@ -1151,33 +759,11 @@ void halt_and_flash(const uint32_t duration) } #ifdef IS_PRALINE -void p1_ctrl_set(const p1_ctrl_signal_t signal) -{ - const platform_gpio_t* gpio = platform_gpio(); - - gpio_write(gpio->p1_ctrl0, signal & 1); - gpio_write(gpio->p1_ctrl1, (signal >> 1) & 1); - gpio_write(gpio->p1_ctrl2, (signal >> 2) & 1); -} - -void p2_ctrl_set(const p2_ctrl_signal_t signal) -{ - const platform_gpio_t* gpio = platform_gpio(); - - gpio_write(gpio->p2_ctrl0, signal & 1); - gpio_write(gpio->p2_ctrl1, (signal >> 1) & 1); -} - void clkin_ctrl_set(const clkin_signal_t signal) { gpio_write(platform_gpio()->clkin_ctrl, signal & 1); } -void pps_out_set(const uint8_t value) -{ - gpio_write(platform_gpio()->pps_out, value & 1); -} - void narrowband_filter_set(const uint8_t value) { gpio_write(platform_gpio()->aa_en, value & 1); diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 334d74a0..d38ce387 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -31,7 +31,6 @@ extern "C" { #include #include "cpld_jtag.h" -#include "fixed_point.h" #include "i2c_bus.h" #include "i2c_lpc.h" #include "max283x.h" @@ -69,8 +68,6 @@ extern rf_path_t rf_path; extern jtag_t jtag_cpld; extern i2c_bus_t i2c0; -void clock_gen_init(void); -void clock_gen_shutdown(void); void ssp1_set_mode_max283x(void); void ssp1_set_mode_max5864(void); #ifdef IS_PRALINE @@ -89,10 +86,6 @@ void disable_3v3aux_power(void); void enable_1v8_power(void); void disable_1v8_power(void); -fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program); - -clock_source_t activate_best_clock_source(void); - #if defined(IS_RAD1O) || defined(IS_HACKRF_ONE) || defined(IS_PRALINE) void enable_rf_power(void); void disable_rf_power(void); @@ -115,33 +108,13 @@ void trigger_enable(const bool enable); void halt_and_flash(const uint32_t duration); #ifdef IS_PRALINE -typedef enum { - P1_SIGNAL_TRIGGER_IN = 0, - P1_SIGNAL_AUX_CLK1 = 1, - P1_SIGNAL_CLKIN = 2, - P1_SIGNAL_TRIGGER_OUT = 3, - P1_SIGNAL_P22_CLKIN = 4, - P1_SIGNAL_P2_5 = 5, - P1_SIGNAL_NC = 6, - P1_SIGNAL_AUX_CLK2 = 7, -} p1_ctrl_signal_t; - -typedef enum { - P2_SIGNAL_CLK3 = 0, - P2_SIGNAL_TRIGGER_IN = 2, - P2_SIGNAL_TRIGGER_OUT = 3, -} p2_ctrl_signal_t; - typedef enum { CLKIN_SIGNAL_P1 = 0, CLKIN_SIGNAL_P22 = 1, } clkin_signal_t; -void p1_ctrl_set(const p1_ctrl_signal_t signal); -void p2_ctrl_set(const p2_ctrl_signal_t signal); void narrowband_filter_set(const uint8_t value); void clkin_ctrl_set(const clkin_signal_t value); -void pps_out_set(const uint8_t value); #endif #ifdef __cplusplus diff --git a/firmware/common/hackrf_ui.h b/firmware/common/hackrf_ui.h index 1193d1c5..7b7d67e4 100644 --- a/firmware/common/hackrf_ui.h +++ b/firmware/common/hackrf_ui.h @@ -25,7 +25,7 @@ #include #include -#include "radio.h" +#include "clock_gen.h" #include "rf_path.h" #include "transceiver_mode.h" diff --git a/firmware/common/radio.h b/firmware/common/radio.h index 83f72441..7ab46c80 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -54,13 +54,6 @@ typedef struct { uint32_t hz; } radio_sample_rate_t; -// legacy type, moved from hackrf_core -typedef enum { - CLOCK_SOURCE_HACKRF = 0, - CLOCK_SOURCE_EXTERNAL = 1, - CLOCK_SOURCE_PORTAPACK = 2, -} clock_source_t; - /** * Configurable registers stored as uint64_t. Any register may be set to * RADIO_UNSET. When not RADIO_UNSET, some registers are read as a specific type diff --git a/firmware/common/ui_portapack.c b/firmware/common/ui_portapack.c index 8912777f..85ffa705 100644 --- a/firmware/common/ui_portapack.c +++ b/firmware/common/ui_portapack.c @@ -26,8 +26,8 @@ #include #include +#include "clock_gen.h" #include "portapack.h" -#include "radio.h" #include "rf_path.h" #include "transceiver_mode.h" diff --git a/firmware/common/ui_rad1o.c b/firmware/common/ui_rad1o.c index ce894cdf..878e9e74 100644 --- a/firmware/common/ui_rad1o.c +++ b/firmware/common/ui_rad1o.c @@ -26,10 +26,13 @@ #include #include +#include "clock_gen.h" #include "hackrf_core.h" -#include "radio.h" #include "rf_path.h" #include "transceiver_mode.h" +#ifdef IS_NOT_RAD1O + #include "radio.h" +#endif #include "rad1o/display.h" #include "rad1o/draw.h" diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index a2823405..0183948f 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -174,6 +174,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/sgpio.c ${PATH_HACKRF_FIRMWARE_COMMON}/rf_path.c ${PATH_HACKRF_FIRMWARE_COMMON}/si5351c.c + ${PATH_HACKRF_FIRMWARE_COMMON}/clock_gen.c ${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c ${PATH_HACKRF_FIRMWARE_COMMON}/max5864_target.c ${PATH_HACKRF_FIRMWARE_COMMON}/mixer.c diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index dba9a39e..661d6791 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_board_info.c b/firmware/hackrf_usb/usb_api_board_info.c index 920ad749..c4634605 100644 --- a/firmware/hackrf_usb/usb_api_board_info.c +++ b/firmware/hackrf_usb/usb_api_board_info.c @@ -26,6 +26,7 @@ #include +#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_praline.c b/firmware/hackrf_usb/usb_api_praline.c index 2a41b839..47b59446 100644 --- a/firmware/hackrf_usb/usb_api_praline.c +++ b/firmware/hackrf_usb/usb_api_praline.c @@ -23,6 +23,7 @@ #include "usb_api_praline.h" +#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index be16b1be..3d3ded45 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include From 92476260edde8dae7a1d9814c3a3acd10141501c Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Tue, 24 Mar 2026 11:00:56 +0200 Subject: [PATCH 137/238] firmware: move power logic to power.h|c --- firmware/blinky/blinky.c | 9 +- firmware/common/hackrf_core.c | 163 +------------------------ firmware/common/hackrf_core.h | 14 --- firmware/common/power.c | 197 +++++++++++++++++++++++++++++++ firmware/common/power.h | 46 ++++++++ firmware/hackrf-common.cmake | 1 + firmware/hackrf_usb/hackrf_usb.c | 1 + 7 files changed, 251 insertions(+), 180 deletions(-) create mode 100644 firmware/common/power.c create mode 100644 firmware/common/power.h diff --git a/firmware/blinky/blinky.c b/firmware/blinky/blinky.c index 6d071c97..e82f4007 100644 --- a/firmware/blinky/blinky.c +++ b/firmware/blinky/blinky.c @@ -19,9 +19,10 @@ * Boston, MA 02110-1301, USA. */ +#include "delay.h" #include "hackrf_core.h" #include "platform_detect.h" -#include "delay.h" +#include "power.h" int main(void) { @@ -37,18 +38,18 @@ int main(void) #endif /* Blink LED1/2/3 on the board. */ - while (1) + while (1) { led_on(LED1); led_on(LED2); led_on(LED3); delay(2000000); - + led_off(LED1); led_off(LED2); led_off(LED3); - + delay(2000000); } diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index c8b12842..b0b8a563 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -36,6 +36,7 @@ #include "max5864_target.h" #include "platform_gpio.h" #include "platform_scu.h" +#include "power.h" #include "spi_bus.h" #include "w25q80bv_target.h" #ifdef IS_PRALINE @@ -511,168 +512,6 @@ void pin_setup(void) sgpio_configure_pin_functions(&sgpio_config); } -#ifdef IS_PRALINE -void enable_1v2_power(void) -{ - if (IS_PRALINE) { - gpio_set(platform_gpio()->gpio_1v2_enable); - } -} - -void disable_1v2_power(void) -{ - if (IS_PRALINE) { - gpio_clear(platform_gpio()->gpio_1v2_enable); - } -} - -void enable_3v3aux_power(void) -{ - if (IS_PRALINE) { - gpio_clear(platform_gpio()->gpio_3v3aux_enable_n); - } -} - -void disable_3v3aux_power(void) -{ - if (IS_PRALINE) { - gpio_set(platform_gpio()->gpio_3v3aux_enable_n); - } -} -#endif - -void enable_1v8_power(void) -{ -#ifdef IS_NOT_PRALINE - if (IS_NOT_PRALINE) { - #ifdef IS_H1_R9 - if (IS_H1_R9) { - gpio_set(platform_gpio()->h1r9_1v8_enable); - } - #endif - #ifdef IS_NOT_H1_R9 - if (IS_NOT_H1_R9) { - gpio_set(platform_gpio()->gpio_1v8_enable); - } - #endif - } -#endif -} - -void disable_1v8_power(void) -{ -#ifdef IS_NOT_PRALINE - if (IS_NOT_PRALINE) { - #ifdef IS_H1_R9 - if (IS_H1_R9) { - gpio_clear(platform_gpio()->h1r9_1v8_enable); - } - #endif - #ifdef IS_NOT_H1_R9 - if (IS_NOT_H1_R9) { - gpio_clear(platform_gpio()->gpio_1v8_enable); - } - #endif - } -#endif -} - -#ifdef IS_HACKRF_ONE -static inline void enable_rf_power_hackrf_one(void) -{ - const platform_gpio_t* gpio = platform_gpio(); - uint32_t i; - - /* many short pulses to avoid one big voltage glitch */ - for (i = 0; i < 1000; i++) { - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - gpio_set(gpio->h1r9_vaa_disable); - gpio_clear(gpio->h1r9_vaa_disable); - } else { - gpio_set(gpio->vaa_disable); - gpio_clear(gpio->vaa_disable); - } - } -} - -static inline void disable_rf_power_hackrf_one(void) -{ - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - gpio_set(platform_gpio()->h1r9_vaa_disable); - } else { - gpio_set(platform_gpio()->vaa_disable); - } -} -#endif - -#ifdef IS_PRALINE -static inline void enable_rf_power_praline(void) -{ - gpio_clear(platform_gpio()->vaa_disable); - - /* Let the voltage stabilize */ - delay(1000000); -} - -static inline void disable_rf_power_praline(void) -{ - gpio_set(platform_gpio()->vaa_disable); -} -#endif - -#ifdef IS_RAD1O -static inline void enable_rf_power_rad1o(void) -{ - gpio_set(platform_gpio()->vaa_enable); - - /* Let the voltage stabilize */ - delay(1000000); -} - -static inline void disable_rf_power_rad1o(void) -{ - gpio_clear(platform_gpio()->vaa_enable); -} -#endif - -void enable_rf_power(void) -{ -#ifdef IS_HACKRF_ONE - if (IS_HACKRF_ONE) { - enable_rf_power_hackrf_one(); - } -#endif -#ifdef IS_PRALINE - if (IS_PRALINE) { - enable_rf_power_praline(); - } -#endif -#ifdef IS_RAD1O - if (IS_RAD1O) { - enable_rf_power_rad1o(); - } -#endif -} - -void disable_rf_power(void) -{ -#ifdef IS_HACKRF_ONE - if (IS_HACKRF_ONE) { - disable_rf_power_hackrf_one(); - } -#endif -#ifdef IS_PRALINE - if (IS_PRALINE) { - disable_rf_power_praline(); - } -#endif -#ifdef IS_RAD1O - if (IS_RAD1O) { - disable_rf_power_rad1o(); - } -#endif -} - void led_on(const led_t led) { #ifdef IS_PRALINE diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index d38ce387..1d783236 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -77,20 +77,6 @@ void ssp1_set_mode_ice40(void); void pin_shutdown(void); void pin_setup(void); -#ifdef IS_PRALINE -void enable_1v2_power(void); -void disable_1v2_power(void); -void enable_3v3aux_power(void); -void disable_3v3aux_power(void); -#endif -void enable_1v8_power(void); -void disable_1v8_power(void); - -#if defined(IS_RAD1O) || defined(IS_HACKRF_ONE) || defined(IS_PRALINE) -void enable_rf_power(void); -void disable_rf_power(void); -#endif - typedef enum { LED1 = 0, LED2 = 1, diff --git a/firmware/common/power.c b/firmware/common/power.c new file mode 100644 index 00000000..25424aab --- /dev/null +++ b/firmware/common/power.c @@ -0,0 +1,197 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "power.h" + +#if defined(IS_HACKRF_ONE) + #include +#endif +#if defined(IS_HACKRF_ONE) || defined(IS_RAD1O) || defined(IS_JAWBREAKER) + #include "platform_detect.h" +#endif +#if defined(IS_PRALINE) || defined(IS_RAD1O) + #include "delay.h" +#endif + +#include "gpio.h" +#include "platform_gpio.h" + +#ifdef IS_PRALINE +void enable_1v2_power(void) +{ + if (IS_PRALINE) { + gpio_set(platform_gpio()->gpio_1v2_enable); + } +} + +void disable_1v2_power(void) +{ + if (IS_PRALINE) { + gpio_clear(platform_gpio()->gpio_1v2_enable); + } +} + +void enable_3v3aux_power(void) +{ + if (IS_PRALINE) { + gpio_clear(platform_gpio()->gpio_3v3aux_enable_n); + } +} + +void disable_3v3aux_power(void) +{ + if (IS_PRALINE) { + gpio_set(platform_gpio()->gpio_3v3aux_enable_n); + } +} +#endif + +void enable_1v8_power(void) +{ +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { + #ifdef IS_H1_R9 + if (IS_H1_R9) { + gpio_set(platform_gpio()->h1r9_1v8_enable); + } + #endif + #ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { + gpio_set(platform_gpio()->gpio_1v8_enable); + } + #endif + } +#endif +} + +void disable_1v8_power(void) +{ +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { + #ifdef IS_H1_R9 + if (IS_H1_R9) { + gpio_clear(platform_gpio()->h1r9_1v8_enable); + } + #endif + #ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { + gpio_clear(platform_gpio()->gpio_1v8_enable); + } + #endif + } +#endif +} + +#ifdef IS_HACKRF_ONE +static inline void enable_rf_power_hackrf_one(void) +{ + const platform_gpio_t* gpio = platform_gpio(); + uint32_t i; + + /* many short pulses to avoid one big voltage glitch */ + for (i = 0; i < 1000; i++) { + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + gpio_set(gpio->h1r9_vaa_disable); + gpio_clear(gpio->h1r9_vaa_disable); + } else { + gpio_set(gpio->vaa_disable); + gpio_clear(gpio->vaa_disable); + } + } +} + +static inline void disable_rf_power_hackrf_one(void) +{ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + gpio_set(platform_gpio()->h1r9_vaa_disable); + } else { + gpio_set(platform_gpio()->vaa_disable); + } +} +#endif + +#ifdef IS_PRALINE +static inline void enable_rf_power_praline(void) +{ + gpio_clear(platform_gpio()->vaa_disable); + + /* Let the voltage stabilize */ + delay(1000000); +} + +static inline void disable_rf_power_praline(void) +{ + gpio_set(platform_gpio()->vaa_disable); +} +#endif + +#ifdef IS_RAD1O +static inline void enable_rf_power_rad1o(void) +{ + gpio_set(platform_gpio()->vaa_enable); + + /* Let the voltage stabilize */ + delay(1000000); +} + +static inline void disable_rf_power_rad1o(void) +{ + gpio_clear(platform_gpio()->vaa_enable); +} +#endif + +void enable_rf_power(void) +{ +#ifdef IS_HACKRF_ONE + if (IS_HACKRF_ONE) { + enable_rf_power_hackrf_one(); + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { + enable_rf_power_praline(); + } +#endif +#ifdef IS_RAD1O + if (IS_RAD1O) { + enable_rf_power_rad1o(); + } +#endif +} + +void disable_rf_power(void) +{ +#ifdef IS_HACKRF_ONE + if (IS_HACKRF_ONE) { + disable_rf_power_hackrf_one(); + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { + disable_rf_power_praline(); + } +#endif +#ifdef IS_RAD1O + if (IS_RAD1O) { + disable_rf_power_rad1o(); + } +#endif +} diff --git a/firmware/common/power.h b/firmware/common/power.h new file mode 100644 index 00000000..22b2345e --- /dev/null +++ b/firmware/common/power.h @@ -0,0 +1,46 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "platform_detect.h" // IWYU pragma: keep + +#ifdef IS_PRALINE +void enable_1v2_power(void); +void disable_1v2_power(void); +void enable_3v3aux_power(void); +void disable_3v3aux_power(void); +#endif +void enable_1v8_power(void); +void disable_1v8_power(void); + +#if defined(IS_RAD1O) || defined(IS_HACKRF_ONE) || defined(IS_PRALINE) +void enable_rf_power(void); +void disable_rf_power(void); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 0183948f..1a55400f 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -168,6 +168,7 @@ endmacro() macro(DeclareTargets) SET(SRC_M4 ${SRC_M4} + ${PATH_HACKRF_FIRMWARE_COMMON}/power.c ${PATH_HACKRF_FIRMWARE_COMMON}/cpu_clock.c ${PATH_HACKRF_FIRMWARE_COMMON}/delay.c ${PATH_HACKRF_FIRMWARE_COMMON}/hackrf_core.c diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 661d6791..eff69298 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include From 799af35b5fd7f94221e0d37db477bd5b3e0bbc1b Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Tue, 24 Mar 2026 14:03:55 +0200 Subject: [PATCH 138/238] firmware: move led logic to leds.h|c --- firmware/blinky/blinky.c | 1 + firmware/common/hackrf_core.c | 73 +--------------- firmware/common/hackrf_core.h | 18 +--- firmware/common/leds.c | 100 ++++++++++++++++++++++ firmware/common/leds.h | 46 ++++++++++ firmware/common/platform_detect.c | 2 +- firmware/hackrf-common.cmake | 1 + firmware/hackrf_usb/hackrf_usb.c | 1 + firmware/hackrf_usb/usb_api_cpld.c | 1 + firmware/hackrf_usb/usb_api_register.c | 1 + firmware/hackrf_usb/usb_api_transceiver.c | 1 + 11 files changed, 157 insertions(+), 88 deletions(-) create mode 100644 firmware/common/leds.c create mode 100644 firmware/common/leds.h diff --git a/firmware/blinky/blinky.c b/firmware/blinky/blinky.c index e82f4007..0bf89bf8 100644 --- a/firmware/blinky/blinky.c +++ b/firmware/blinky/blinky.c @@ -21,6 +21,7 @@ #include "delay.h" #include "hackrf_core.h" +#include "leds.h" #include "platform_detect.h" #include "power.h" diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index b0b8a563..c6429f6d 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -28,10 +28,10 @@ #include "platform_detect.h" #include "clock_gen.h" -#include "delay.h" #include "gpio.h" #include "hackrf_core.h" #include "i2c_lpc.h" +#include "leds.h" #include "max283x.h" #include "max5864_target.h" #include "platform_gpio.h" @@ -512,62 +512,6 @@ void pin_setup(void) sgpio_configure_pin_functions(&sgpio_config); } -void led_on(const led_t led) -{ -#ifdef IS_PRALINE - if (IS_PRALINE) { - gpio_clear(platform_gpio()->led[led]); - } -#endif -#ifdef IS_NOT_PRALINE - if (IS_NOT_PRALINE) { - gpio_set(platform_gpio()->led[led]); - } -#endif -} - -void led_off(const led_t led) -{ -#ifdef IS_PRALINE - if (IS_PRALINE) { - gpio_set(platform_gpio()->led[led]); - } -#endif -#ifdef IS_NOT_PRALINE - if (IS_NOT_PRALINE) { - gpio_clear(platform_gpio()->led[led]); - } -#endif -} - -void led_toggle(const led_t led) -{ - gpio_toggle(platform_gpio()->led[led]); -} - -void set_leds(const uint8_t state) -{ - int num_leds = 3; -#ifdef IS_FOUR_LEDS - if (IS_FOUR_LEDS) { - num_leds = 4; - } -#endif - - for (int i = 0; i < num_leds; i++) { -#ifdef IS_PRALINE - if (IS_PRALINE) { - gpio_write(platform_gpio()->led[i], ((state >> i) & 1) == 0); - } -#endif -#ifdef IS_NOT_PRALINE - if (IS_NOT_PRALINE) { - gpio_write(platform_gpio()->led[i], ((state >> i) & 1) == 1); - } -#endif - } -} - void trigger_enable(const bool enable) { #ifdef IS_NOT_PRALINE @@ -582,21 +526,6 @@ void trigger_enable(const bool enable) #endif } -void halt_and_flash(const uint32_t duration) -{ - /* blink LED1, LED2, and LED3 */ - while (1) { - led_on(LED1); - led_on(LED2); - led_on(LED3); - delay(duration); - led_off(LED1); - led_off(LED2); - led_off(LED3); - delay(duration); - } -} - #ifdef IS_PRALINE void clkin_ctrl_set(const clkin_signal_t signal) { diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 1d783236..7b6e1336 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -28,7 +28,9 @@ extern "C" { #endif #include -#include +#ifdef IS_PRALINE + #include +#endif #include "cpld_jtag.h" #include "i2c_bus.h" @@ -77,22 +79,8 @@ void ssp1_set_mode_ice40(void); void pin_shutdown(void); void pin_setup(void); -typedef enum { - LED1 = 0, - LED2 = 1, - LED3 = 2, - LED4 = 3, -} led_t; - -void led_on(const led_t led); -void led_off(const led_t led); -void led_toggle(const led_t led); -void set_leds(const uint8_t state); - void trigger_enable(const bool enable); -void halt_and_flash(const uint32_t duration); - #ifdef IS_PRALINE typedef enum { CLKIN_SIGNAL_P1 = 0, diff --git a/firmware/common/leds.c b/firmware/common/leds.c new file mode 100644 index 00000000..ab9b56fb --- /dev/null +++ b/firmware/common/leds.c @@ -0,0 +1,100 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "leds.h" + +#include + +#include "delay.h" +#include "gpio.h" +#include "platform_detect.h" +#include "platform_gpio.h" + +void led_on(const led_t led) +{ +#ifdef IS_PRALINE + if (IS_PRALINE) { + gpio_clear(platform_gpio()->led[led]); + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { + gpio_set(platform_gpio()->led[led]); + } +#endif +} + +void led_off(const led_t led) +{ +#ifdef IS_PRALINE + if (IS_PRALINE) { + gpio_set(platform_gpio()->led[led]); + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { + gpio_clear(platform_gpio()->led[led]); + } +#endif +} + +void led_toggle(const led_t led) +{ + gpio_toggle(platform_gpio()->led[led]); +} + +void set_leds(const uint8_t state) +{ + int num_leds = 3; +#ifdef IS_FOUR_LEDS + if (IS_FOUR_LEDS) { + num_leds = 4; + } +#endif + + for (int i = 0; i < num_leds; i++) { +#ifdef IS_PRALINE + if (IS_PRALINE) { + gpio_write(platform_gpio()->led[i], ((state >> i) & 1) == 0); + } +#endif +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { + gpio_write(platform_gpio()->led[i], ((state >> i) & 1) == 1); + } +#endif + } +} + +void halt_and_flash(const uint32_t duration) +{ + /* blink LED1, LED2, and LED3 */ + while (1) { + led_on(LED1); + led_on(LED2); + led_on(LED3); + delay(duration); + led_off(LED1); + led_off(LED2); + led_off(LED3); + delay(duration); + } +} diff --git a/firmware/common/leds.h b/firmware/common/leds.h new file mode 100644 index 00000000..a552dca6 --- /dev/null +++ b/firmware/common/leds.h @@ -0,0 +1,46 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef enum { + LED1 = 0, + LED2 = 1, + LED3 = 2, + LED4 = 3, +} led_t; + +void led_on(const led_t led); +void led_off(const led_t led); +void led_toggle(const led_t led); +void set_leds(const uint8_t state); + +void halt_and_flash(const uint32_t duration); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/common/platform_detect.c b/firmware/common/platform_detect.c index b3903035..7c9fb53d 100644 --- a/firmware/common/platform_detect.c +++ b/firmware/common/platform_detect.c @@ -26,7 +26,7 @@ #include "firmware_info.h" #include "gpio.h" #include "gpio_lpc.h" -#include "hackrf_core.h" +#include "leds.h" #include "platform_detect.h" #include "platform_scu.h" diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 1a55400f..92a905f4 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -172,6 +172,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/cpu_clock.c ${PATH_HACKRF_FIRMWARE_COMMON}/delay.c ${PATH_HACKRF_FIRMWARE_COMMON}/hackrf_core.c + ${PATH_HACKRF_FIRMWARE_COMMON}/leds.c ${PATH_HACKRF_FIRMWARE_COMMON}/sgpio.c ${PATH_HACKRF_FIRMWARE_COMMON}/rf_path.c ${PATH_HACKRF_FIRMWARE_COMMON}/si5351c.c diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index eff69298..4cd68852 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_cpld.c b/firmware/hackrf_usb/usb_api_cpld.c index 05636a0b..7381601d 100644 --- a/firmware/hackrf_usb/usb_api_cpld.c +++ b/firmware/hackrf_usb/usb_api_cpld.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index b9498dab..632ce0e5 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 3d3ded45..153b760b 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include From 634bd605b92770defb63959a5736682951ec8d05 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Wed, 25 Mar 2026 14:53:00 +0200 Subject: [PATCH 139/238] firmware: move clkin_ctrl_set to clkin.h|c --- firmware/common/clkin.c | 13 ++++++++++++- firmware/common/clkin.h | 11 +++++++++++ firmware/common/hackrf_core.c | 6 +----- firmware/common/hackrf_core.h | 6 ------ firmware/hackrf_usb/usb_api_praline.c | 1 + 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/firmware/common/clkin.c b/firmware/common/clkin.c index 9f63681c..f5af1723 100644 --- a/firmware/common/clkin.c +++ b/firmware/common/clkin.c @@ -30,6 +30,10 @@ #include #include "gpdma.h" +#ifdef IS_PRALINE + #include "gpio.h" + #include "platform_gpio.h" +#endif #define CLOCK_CYCLES_1_MS (204000) #define MEASUREMENT_WINDOW_MS (50) @@ -114,4 +118,11 @@ void clkin_detect_init(void) uint32_t clkin_frequency(void) { return TIMER2_CR3 * (1000 / MEASUREMENT_WINDOW_MS); -}; +} + +#ifdef IS_PRALINE +void clkin_ctrl_set(const clkin_signal_t signal) +{ + gpio_write(platform_gpio()->clkin_ctrl, signal & 1); +} +#endif diff --git a/firmware/common/clkin.h b/firmware/common/clkin.h index 2cef67cf..53379013 100644 --- a/firmware/common/clkin.h +++ b/firmware/common/clkin.h @@ -23,5 +23,16 @@ #include +#include "platform_detect.h" // IWYU pragma: keep + void clkin_detect_init(void); uint32_t clkin_frequency(void); + +#ifdef IS_PRALINE +typedef enum { + CLKIN_SIGNAL_P1 = 0, + CLKIN_SIGNAL_P22 = 1, +} clkin_signal_t; + +void clkin_ctrl_set(const clkin_signal_t value); +#endif diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index c6429f6d..29ca3820 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -40,6 +40,7 @@ #include "spi_bus.h" #include "w25q80bv_target.h" #ifdef IS_PRALINE + #include "clkin.h" #include "ice40_spi.h" #endif @@ -527,11 +528,6 @@ void trigger_enable(const bool enable) } #ifdef IS_PRALINE -void clkin_ctrl_set(const clkin_signal_t signal) -{ - gpio_write(platform_gpio()->clkin_ctrl, signal & 1); -} - void narrowband_filter_set(const uint8_t value) { gpio_write(platform_gpio()->aa_en, value & 1); diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 7b6e1336..e0253458 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -82,13 +82,7 @@ void pin_setup(void); void trigger_enable(const bool enable); #ifdef IS_PRALINE -typedef enum { - CLKIN_SIGNAL_P1 = 0, - CLKIN_SIGNAL_P22 = 1, -} clkin_signal_t; - void narrowband_filter_set(const uint8_t value); -void clkin_ctrl_set(const clkin_signal_t value); #endif #ifdef __cplusplus diff --git a/firmware/hackrf_usb/usb_api_praline.c b/firmware/hackrf_usb/usb_api_praline.c index 47b59446..434418a5 100644 --- a/firmware/hackrf_usb/usb_api_praline.c +++ b/firmware/hackrf_usb/usb_api_praline.c @@ -23,6 +23,7 @@ #include "usb_api_praline.h" +#include #include #include #include From e2741090ad36b9aac6243fa25abad5eed9404ddd Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Fri, 27 Mar 2026 14:46:12 +0200 Subject: [PATCH 140/238] firmware: move narrowband_filter_set to rf_path.h|c --- firmware/common/fpga.h | 2 ++ firmware/common/hackrf_core.c | 7 ------- firmware/common/hackrf_core.h | 7 ------- firmware/common/rf_path.c | 10 ++++++++++ firmware/common/rf_path.h | 4 ++++ firmware/hackrf_usb/usb_api_praline.c | 4 ++-- 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/firmware/common/fpga.h b/firmware/common/fpga.h index 4aa54239..65826b21 100644 --- a/firmware/common/fpga.h +++ b/firmware/common/fpga.h @@ -90,3 +90,5 @@ bool fpga_image_load(struct fpga_loader_t* loader, unsigned int index); bool fpga_spi_selftest(void); bool fpga_sgpio_selftest(void); bool fpga_if_xcvr_selftest(void); + +//void narrowband_filter_set(const uint8_t value); diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 29ca3820..58499442 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -526,10 +526,3 @@ void trigger_enable(const bool enable) } #endif } - -#ifdef IS_PRALINE -void narrowband_filter_set(const uint8_t value) -{ - gpio_write(platform_gpio()->aa_en, value & 1); -} -#endif diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index e0253458..3755ee2e 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -28,9 +28,6 @@ extern "C" { #endif #include -#ifdef IS_PRALINE - #include -#endif #include "cpld_jtag.h" #include "i2c_bus.h" @@ -81,10 +78,6 @@ void pin_setup(void); void trigger_enable(const bool enable); -#ifdef IS_PRALINE -void narrowband_filter_set(const uint8_t value); -#endif - #ifdef __cplusplus } #endif diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 6a8e3caf..6cadea1c 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -32,6 +32,9 @@ #include #include "platform_scu.h" #endif +#ifdef IS_PRALINE + #include "platform_gpio.h" +#endif /* * RF switches on Jawbreaker are controlled by General Purpose Outputs (GPO) on @@ -615,3 +618,10 @@ void rf_path_set_antenna(rf_path_t* const rf_path, const uint_fast8_t enable) switchctrl_set(rf_path, rf_path->switchctrl); } + +#ifdef IS_PRALINE +void narrowband_filter_set(const uint8_t value) +{ + gpio_write(platform_gpio()->aa_en, value & 1); +} +#endif diff --git a/firmware/common/rf_path.h b/firmware/common/rf_path.h index 42dd91cb..12f83b53 100644 --- a/firmware/common/rf_path.h +++ b/firmware/common/rf_path.h @@ -102,3 +102,7 @@ void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter) void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable); void rf_path_set_antenna(rf_path_t* const rf_path, const uint_fast8_t enable); + +#ifdef IS_PRALINE +void narrowband_filter_set(const uint8_t value); +#endif diff --git a/firmware/hackrf_usb/usb_api_praline.c b/firmware/hackrf_usb/usb_api_praline.c index 434418a5..262e66df 100644 --- a/firmware/hackrf_usb/usb_api_praline.c +++ b/firmware/hackrf_usb/usb_api_praline.c @@ -25,12 +25,12 @@ #include #include -#include #include +#include #include #include #include -#if !(defined(DFU_MODE) || defined(RAM_MODE)) +#if !defined(DFU_MODE) && !defined(RAM_MODE) #include #endif From 5672be9d00a67a5ad8c2488580325d686b8365ef Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Tue, 31 Mar 2026 11:25:14 +0200 Subject: [PATCH 141/238] firmware: move clock-associated gpio functions to clkin.x and rename to clock_io.h|c --- firmware/common/clock_gen.c | 28 --------------- firmware/common/clock_gen.h | 27 --------------- firmware/common/{clkin.c => clock_io.c} | 45 +++++++++++++++++++++++-- firmware/common/{clkin.h => clock_io.h} | 26 +++++++++++++- firmware/common/hackrf_core.c | 18 ++-------- firmware/common/hackrf_core.h | 4 --- firmware/common/radio.c | 1 + firmware/common/sgpio.c | 2 +- firmware/common/si5351c.c | 2 +- firmware/hackrf-common.cmake | 2 +- firmware/hackrf_usb/hackrf_usb.c | 2 +- firmware/hackrf_usb/usb_api_praline.c | 3 +- 12 files changed, 76 insertions(+), 84 deletions(-) rename firmware/common/{clkin.c => clock_io.c} (81%) rename firmware/common/{clkin.h => clock_io.h} (64%) diff --git a/firmware/common/clock_gen.c b/firmware/common/clock_gen.c index e29e5a91..3080c436 100644 --- a/firmware/common/clock_gen.c +++ b/firmware/common/clock_gen.c @@ -33,10 +33,6 @@ #include "delay.h" #include "portapack.h" #endif -#if defined(IS_PRALINE) - #include "gpio.h" - #include "platform_gpio.h" -#endif void clock_gen_init(void) { @@ -426,27 +422,3 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) return resultant_rate; } - -#ifdef IS_PRALINE -void p1_ctrl_set(const p1_ctrl_signal_t signal) -{ - const platform_gpio_t* gpio = platform_gpio(); - - gpio_write(gpio->p1_ctrl0, signal & 1); - gpio_write(gpio->p1_ctrl1, (signal >> 1) & 1); - gpio_write(gpio->p1_ctrl2, (signal >> 2) & 1); -} - -void p2_ctrl_set(const p2_ctrl_signal_t signal) -{ - const platform_gpio_t* gpio = platform_gpio(); - - gpio_write(gpio->p2_ctrl0, signal & 1); - gpio_write(gpio->p2_ctrl1, (signal >> 1) & 1); -} - -void pps_out_set(const uint8_t value) -{ - gpio_write(platform_gpio()->pps_out, value & 1); -} -#endif diff --git a/firmware/common/clock_gen.h b/firmware/common/clock_gen.h index 48fb6f20..0bc6439b 100644 --- a/firmware/common/clock_gen.h +++ b/firmware/common/clock_gen.h @@ -28,9 +28,6 @@ extern "C" { #include "platform_detect.h" // IWYU pragma: keep #include -#ifdef IS_PRALINE - #include -#endif #include "fixed_point.h" @@ -47,30 +44,6 @@ clock_source_t activate_best_clock_source(void); fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program); -#ifdef IS_PRALINE -typedef enum { - P1_SIGNAL_TRIGGER_IN = 0, - P1_SIGNAL_AUX_CLK1 = 1, - P1_SIGNAL_CLKIN = 2, - P1_SIGNAL_TRIGGER_OUT = 3, - P1_SIGNAL_P22_CLKIN = 4, - P1_SIGNAL_P2_5 = 5, - P1_SIGNAL_NC = 6, - P1_SIGNAL_AUX_CLK2 = 7, -} p1_ctrl_signal_t; - -typedef enum { - P2_SIGNAL_CLK3 = 0, - P2_SIGNAL_TRIGGER_IN = 2, - P2_SIGNAL_TRIGGER_OUT = 3, -} p2_ctrl_signal_t; - -void p1_ctrl_set(const p1_ctrl_signal_t signal); -void p2_ctrl_set(const p2_ctrl_signal_t signal); - -void pps_out_set(const uint8_t value); -#endif - #ifdef __cplusplus } #endif diff --git a/firmware/common/clkin.c b/firmware/common/clock_io.c similarity index 81% rename from firmware/common/clkin.c rename to firmware/common/clock_io.c index f5af1723..0a8b48d9 100644 --- a/firmware/common/clkin.c +++ b/firmware/common/clock_io.c @@ -1,5 +1,5 @@ /* - * Copyright 2022 Great Scott Gadgets + * Copyright 2022-2026 Great Scott Gadgets * * This file is part of HackRF. * @@ -19,8 +19,9 @@ * Boston, MA 02110-1301, USA. */ -#include "clkin.h" +#include "clock_io.h" +#include #include #include @@ -30,8 +31,10 @@ #include #include "gpdma.h" +#include "gpio.h" +#include "hackrf_core.h" #ifdef IS_PRALINE - #include "gpio.h" + #include "fpga.h" #include "platform_gpio.h" #endif @@ -120,9 +123,45 @@ uint32_t clkin_frequency(void) return TIMER2_CR3 * (1000 / MEASUREMENT_WINDOW_MS); } +void trigger_enable(const bool enable) +{ +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { + gpio_write(sgpio_config.gpio_trigger_enable, enable); + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { + fpga_set_trigger_enable(&fpga, enable); + } +#endif +} + #ifdef IS_PRALINE void clkin_ctrl_set(const clkin_signal_t signal) { gpio_write(platform_gpio()->clkin_ctrl, signal & 1); } + +void p1_ctrl_set(const p1_ctrl_signal_t signal) +{ + const platform_gpio_t* gpio = platform_gpio(); + + gpio_write(gpio->p1_ctrl0, signal & 1); + gpio_write(gpio->p1_ctrl1, (signal >> 1) & 1); + gpio_write(gpio->p1_ctrl2, (signal >> 2) & 1); +} + +void p2_ctrl_set(const p2_ctrl_signal_t signal) +{ + const platform_gpio_t* gpio = platform_gpio(); + + gpio_write(gpio->p2_ctrl0, signal & 1); + gpio_write(gpio->p2_ctrl1, (signal >> 1) & 1); +} + +void pps_out_set(const uint8_t value) +{ + gpio_write(platform_gpio()->pps_out, value & 1); +} #endif diff --git a/firmware/common/clkin.h b/firmware/common/clock_io.h similarity index 64% rename from firmware/common/clkin.h rename to firmware/common/clock_io.h index 53379013..df540022 100644 --- a/firmware/common/clkin.h +++ b/firmware/common/clock_io.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 Great Scott Gadgets + * Copyright 2022-2026 Great Scott Gadgets * * This file is part of HackRF. * @@ -21,6 +21,7 @@ #pragma once +#include #include #include "platform_detect.h" // IWYU pragma: keep @@ -28,11 +29,34 @@ void clkin_detect_init(void); uint32_t clkin_frequency(void); +void trigger_enable(const bool enable); + #ifdef IS_PRALINE typedef enum { CLKIN_SIGNAL_P1 = 0, CLKIN_SIGNAL_P22 = 1, } clkin_signal_t; +typedef enum { + P1_SIGNAL_TRIGGER_IN = 0, + P1_SIGNAL_AUX_CLK1 = 1, + P1_SIGNAL_CLKIN = 2, + P1_SIGNAL_TRIGGER_OUT = 3, + P1_SIGNAL_P22_CLKIN = 4, + P1_SIGNAL_P2_5 = 5, + P1_SIGNAL_NC = 6, + P1_SIGNAL_AUX_CLK2 = 7, +} p1_ctrl_signal_t; + +typedef enum { + P2_SIGNAL_CLK3 = 0, + P2_SIGNAL_TRIGGER_IN = 2, + P2_SIGNAL_TRIGGER_OUT = 3, +} p2_ctrl_signal_t; + void clkin_ctrl_set(const clkin_signal_t value); +void p1_ctrl_set(const p1_ctrl_signal_t signal); +void p2_ctrl_set(const p2_ctrl_signal_t signal); + +void pps_out_set(const uint8_t value); #endif diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 58499442..086e3961 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -21,6 +21,8 @@ * Boston, MA 02110-1301, USA. */ +#include + #include #include #include @@ -40,7 +42,7 @@ #include "spi_bus.h" #include "w25q80bv_target.h" #ifdef IS_PRALINE - #include "clkin.h" + #include "clock_io.h" #include "ice40_spi.h" #endif @@ -512,17 +514,3 @@ void pin_setup(void) sgpio_configure_pin_functions(&sgpio_config); } - -void trigger_enable(const bool enable) -{ -#ifdef IS_NOT_PRALINE - if (IS_NOT_PRALINE) { - gpio_write(sgpio_config.gpio_trigger_enable, enable); - } -#endif -#ifdef IS_PRALINE - if (IS_PRALINE) { - fpga_set_trigger_enable(&fpga, enable); - } -#endif -} diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 3755ee2e..6e0c1cc0 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -27,8 +27,6 @@ extern "C" { #endif -#include - #include "cpld_jtag.h" #include "i2c_bus.h" #include "i2c_lpc.h" @@ -76,8 +74,6 @@ void ssp1_set_mode_ice40(void); void pin_shutdown(void); void pin_setup(void); -void trigger_enable(const bool enable); - #ifdef __cplusplus } #endif diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 760351ac..7191f1ff 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -25,6 +25,7 @@ #include +#include "clock_io.h" #include "fixed_point.h" #include "hackrf_core.h" #include "mixer.h" diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index 9d03924a..568f1208 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -32,7 +32,7 @@ #include "platform_scu.h" #include "sgpio.h" #ifdef IS_NOT_PRALINE - #include "hackrf_core.h" + #include "clock_io.h" #endif static void update_q_invert(sgpio_config_t* const config); diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 0acff63e..c9767405 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -23,7 +23,7 @@ #include #include -#include "clkin.h" +#include "clock_io.h" #include "delay.h" #include "platform_detect.h" #include "selftest.h" diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 92a905f4..6384acdc 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -192,7 +192,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/platform_gpio.c ${PATH_HACKRF_FIRMWARE_COMMON}/platform_scu.c ${PATH_HACKRF_FIRMWARE_COMMON}/firmware_info.c - ${PATH_HACKRF_FIRMWARE_COMMON}/clkin.c + ${PATH_HACKRF_FIRMWARE_COMMON}/clock_io.c ${PATH_HACKRF_FIRMWARE_COMMON}/gpdma.c ${PATH_HACKRF_FIRMWARE_COMMON}/radio.c ${PATH_HACKRF_FIRMWARE_COMMON}/selftest.c diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 4cd68852..bd2c5964 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -28,8 +28,8 @@ #include #include -#include #include +#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_praline.c b/firmware/hackrf_usb/usb_api_praline.c index 262e66df..d889f5da 100644 --- a/firmware/hackrf_usb/usb_api_praline.c +++ b/firmware/hackrf_usb/usb_api_praline.c @@ -23,8 +23,7 @@ #include "usb_api_praline.h" -#include -#include +#include #include #include #include From adf83cbac2396c568145e28bad48549b4e89561a Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Tue, 31 Mar 2026 10:59:18 +0200 Subject: [PATCH 142/238] firmware: move hackrf_core drivers & configurations to drivers.h|c --- firmware/common/clock_gen.c | 2 +- firmware/common/clock_io.c | 2 +- firmware/common/cpu_clock.c | 2 +- firmware/common/da7219.c | 2 +- firmware/common/drivers.c | 178 ++++++++++++++++++++++ firmware/common/drivers.h | 77 ++++++++++ firmware/common/fpga.c | 4 +- firmware/common/fpga_image.c | 2 +- firmware/common/fpga_selftest.c | 2 +- firmware/common/hackrf_core.c | 158 +------------------ firmware/common/hackrf_core.h | 44 ------ firmware/common/operacake.c | 2 +- firmware/common/portapack.c | 2 +- firmware/common/radio.c | 4 +- firmware/common/rf_path.c | 2 +- firmware/common/rom_iap.c | 2 +- firmware/common/ui_rad1o.c | 2 +- firmware/hackrf-common.cmake | 1 + firmware/hackrf_usb/hackrf_usb.c | 1 + firmware/hackrf_usb/usb_api_cpld.c | 2 +- firmware/hackrf_usb/usb_api_register.c | 2 +- firmware/hackrf_usb/usb_api_spiflash.c | 2 +- firmware/hackrf_usb/usb_api_sweep.c | 2 +- firmware/hackrf_usb/usb_api_transceiver.c | 2 +- 24 files changed, 284 insertions(+), 215 deletions(-) create mode 100644 firmware/common/drivers.c create mode 100644 firmware/common/drivers.h diff --git a/firmware/common/clock_gen.c b/firmware/common/clock_gen.c index 3080c436..b62308ce 100644 --- a/firmware/common/clock_gen.c +++ b/firmware/common/clock_gen.c @@ -23,7 +23,7 @@ #include -#include "hackrf_core.h" +#include "drivers.h" #include "hackrf_ui.h" #include "i2c_bus.h" #include "platform_detect.h" diff --git a/firmware/common/clock_io.c b/firmware/common/clock_io.c index 0a8b48d9..279eb8c5 100644 --- a/firmware/common/clock_io.c +++ b/firmware/common/clock_io.c @@ -30,9 +30,9 @@ #include #include +#include "drivers.h" #include "gpdma.h" #include "gpio.h" -#include "hackrf_core.h" #ifdef IS_PRALINE #include "fpga.h" #include "platform_gpio.h" diff --git a/firmware/common/cpu_clock.c b/firmware/common/cpu_clock.c index 1bbd9571..b69f0773 100644 --- a/firmware/common/cpu_clock.c +++ b/firmware/common/cpu_clock.c @@ -29,7 +29,7 @@ #endif #include "delay.h" -#include "hackrf_core.h" +#include "drivers.h" #include "i2c_bus.h" #ifdef IS_NOT_RAD1O #include "platform_detect.h" diff --git a/firmware/common/da7219.c b/firmware/common/da7219.c index 376e04a5..5af022d2 100644 --- a/firmware/common/da7219.c +++ b/firmware/common/da7219.c @@ -22,7 +22,7 @@ #include #include "da7219.h" -#include "hackrf_core.h" +#include "drivers.h" #include "i2c_bus.h" #define DA7219_REG_CHIP_ID1 0x81 diff --git a/firmware/common/drivers.c b/firmware/common/drivers.c new file mode 100644 index 00000000..a6bd536a --- /dev/null +++ b/firmware/common/drivers.c @@ -0,0 +1,178 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "drivers.h" + +#include + +#include +#include + +#include "clock_gen.h" +#include "i2c_lpc.h" +#include "max283x.h" +#include "max5864_target.h" +#include "spi_bus.h" +#include "w25q80bv_target.h" +#if defined(IS_PRALINE) + #include "fpga.h" + #include "ice40_spi.h" +#endif + +i2c_bus_t i2c0 = { + .obj = (void*) I2C0_BASE, + .start = i2c_lpc_start, + .stop = i2c_lpc_stop, + .transfer = i2c_lpc_transfer, +}; + +i2c_bus_t i2c1 = { + .obj = (void*) I2C1_BASE, + .start = i2c_lpc_start, + .stop = i2c_lpc_stop, + .transfer = i2c_lpc_transfer, +}; + +// const i2c_lpc_config_t i2c_config_si5351c_slow_clock = { +// .duty_cycle_count = 15, +// }; + +const i2c_lpc_config_t i2c_config_si5351c_fast_clock = { + .duty_cycle_count = 255, +}; + +si5351c_driver_t clock_gen = { + .bus = &i2c0, + .i2c_address = 0x60, +}; + +ssp_config_t ssp_config_max283x = { + /* FIXME speed up once everything is working reliably */ + /* + // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + const uint8_t serial_clock_rate = 32; + const uint8_t clock_prescale_rate = 128; + */ + // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + .serial_clock_rate = 21, + .clock_prescale_rate = 2, +}; + +max283x_driver_t max283x = {}; + +ssp_config_t ssp_config_max5864 = { + /* FIXME speed up once everything is working reliably */ + /* + // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + const uint8_t serial_clock_rate = 32; + const uint8_t clock_prescale_rate = 128; + */ + // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + .data_bits = SSP_DATA_8BITS, + .serial_clock_rate = 21, + .clock_prescale_rate = 2, +}; + +spi_bus_t spi_bus_ssp1 = { + .obj = (void*) SSP1_BASE, + .config = &ssp_config_max5864, + .start = spi_ssp_start, + .stop = spi_ssp_stop, + .transfer = spi_ssp_transfer, + .transfer_gather = spi_ssp_transfer_gather, +}; + +max5864_driver_t max5864 = { + .bus = &spi_bus_ssp1, + .target_init = max5864_target_init, +}; + +ssp_config_t ssp_config_w25q80bv = { + .data_bits = SSP_DATA_8BITS, + .serial_clock_rate = 2, + .clock_prescale_rate = 2, +}; + +spi_bus_t spi_bus_ssp0 = { + .obj = (void*) SSP0_BASE, + .config = &ssp_config_w25q80bv, + .start = spi_ssp_start, + .stop = spi_ssp_stop, + .transfer = spi_ssp_transfer, + .transfer_gather = spi_ssp_transfer_gather, +}; + +w25q80bv_driver_t spi_flash = { + .bus = &spi_bus_ssp0, + .target_init = w25q80bv_target_init, +}; + +sgpio_config_t sgpio_config = { + .slice_mode_multislice = true, +}; + +#ifdef IS_PRALINE +ssp_config_t ssp_config_ice40_fpga = { + .data_bits = SSP_DATA_8BITS, + .spi_mode = SSP_CPOL_1_CPHA_1, + .serial_clock_rate = 21, + .clock_prescale_rate = 2, +}; + +ice40_spi_driver_t ice40 = { + .bus = &spi_bus_ssp1, +}; + +fpga_driver_t fpga = { + .bus = &ice40, +}; +#endif + +radio_t radio = { + .sample_rate_cb = sample_rate_set, +}; + +rf_path_t rf_path = { + .switchctrl = 0, +}; + +jtag_gpio_t jtag_gpio_cpld = {}; + +jtag_t jtag_cpld = { + .gpio = &jtag_gpio_cpld, +}; + +void ssp1_set_mode_max283x(void) +{ + spi_bus_start(&spi_bus_ssp1, &ssp_config_max283x); +} + +void ssp1_set_mode_max5864(void) +{ + spi_bus_start(max5864.bus, &ssp_config_max5864); +} + +#ifdef IS_PRALINE +void ssp1_set_mode_ice40(void) +{ + spi_bus_start(&spi_bus_ssp1, &ssp_config_ice40_fpga); +} +#endif diff --git a/firmware/common/drivers.h b/firmware/common/drivers.h new file mode 100644 index 00000000..6aa45f87 --- /dev/null +++ b/firmware/common/drivers.h @@ -0,0 +1,77 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpld_jtag.h" +#include "i2c_bus.h" +#include "i2c_lpc.h" +#include "max283x.h" +#include "max5864.h" +#include "mixer.h" +#include "platform_detect.h" // IWYU pragma: keep +#include "radio.h" +#include "rf_path.h" +#include "sgpio.h" +#include "si5351c.h" +#include "spi_ssp.h" +#include "w25q80bv.h" +#if defined(IS_PRALINE) + #include "fpga.h" + #include "ice40_spi.h" +#endif + +/* TODO: Hide these configurations */ +extern const i2c_lpc_config_t i2c_config_si5351c_fast_clock; +extern si5351c_driver_t clock_gen; +extern ssp_config_t ssp_config_max283x; +extern ssp_config_t ssp_config_max5864; +extern ssp_config_t ssp_config_w25q80bv; + +#if defined(IS_PRALINE) +extern ssp_config_t ssp_config_ice40_fpga; +extern ice40_spi_driver_t ice40; +extern fpga_driver_t fpga; +#endif +extern max283x_driver_t max283x; +extern max5864_driver_t max5864; +extern mixer_driver_t mixer; +extern w25q80bv_driver_t spi_flash; +extern sgpio_config_t sgpio_config; +extern radio_t radio; +extern rf_path_t rf_path; +extern jtag_gpio_t jtag_gpio_cpld; +extern jtag_t jtag_cpld; +extern i2c_bus_t i2c0; + +void ssp1_set_mode_max283x(void); +void ssp1_set_mode_max5864(void); +#if defined(IS_PRALINE) +void ssp1_set_mode_ice40(void); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/firmware/common/fpga.c b/firmware/common/fpga.c index 9c4d55f2..172810a8 100644 --- a/firmware/common/fpga.c +++ b/firmware/common/fpga.c @@ -20,11 +20,11 @@ */ #include "fpga.h" +#include "fpga_regs.def" #include -#include "fpga_regs.def" -#include "hackrf_core.h" +#include "drivers.h" #include "ice40_spi.h" /* Set up all registers according to the loaded bitstream's defaults. */ diff --git a/firmware/common/fpga_image.c b/firmware/common/fpga_image.c index dc88556b..989d16b2 100644 --- a/firmware/common/fpga_image.c +++ b/firmware/common/fpga_image.c @@ -23,8 +23,8 @@ #include #include +#include "drivers.h" #include "fpga.h" -#include "hackrf_core.h" #include "ice40_spi.h" #include "lz4_blk.h" #include "selftest.h" diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index fe0a96f9..30e70ea2 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -25,9 +25,9 @@ #include "clock_gen.h" #include "delay.h" +#include "drivers.h" #include "fixed_point.h" #include "fpga.h" -#include "hackrf_core.h" #include "ice40_spi.h" #include "m0_state.h" #include "max283x.h" diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 086e3961..2a7bc376 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -21,167 +21,23 @@ * Boston, MA 02110-1301, USA. */ -#include +#include "hackrf_core.h" -#include #include #include -#include "platform_detect.h" - -#include "clock_gen.h" +#include "drivers.h" #include "gpio.h" -#include "hackrf_core.h" -#include "i2c_lpc.h" #include "leds.h" -#include "max283x.h" -#include "max5864_target.h" +#include "mixer.h" +#include "platform_detect.h" #include "platform_gpio.h" #include "platform_scu.h" #include "power.h" -#include "spi_bus.h" -#include "w25q80bv_target.h" -#ifdef IS_PRALINE +#include "rf_path.h" +#include "sgpio.h" +#if defined(IS_PRALINE) #include "clock_io.h" - #include "ice40_spi.h" -#endif - -i2c_bus_t i2c0 = { - .obj = (void*) I2C0_BASE, - .start = i2c_lpc_start, - .stop = i2c_lpc_stop, - .transfer = i2c_lpc_transfer, -}; - -i2c_bus_t i2c1 = { - .obj = (void*) I2C1_BASE, - .start = i2c_lpc_start, - .stop = i2c_lpc_stop, - .transfer = i2c_lpc_transfer, -}; - -// const i2c_lpc_config_t i2c_config_si5351c_slow_clock = { -// .duty_cycle_count = 15, -// }; - -const i2c_lpc_config_t i2c_config_si5351c_fast_clock = { - .duty_cycle_count = 255, -}; - -si5351c_driver_t clock_gen = { - .bus = &i2c0, - .i2c_address = 0x60, -}; - -static ssp_config_t ssp_config_max283x = { - /* FIXME speed up once everything is working reliably */ - /* - // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - const uint8_t serial_clock_rate = 32; - const uint8_t clock_prescale_rate = 128; - */ - // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - .serial_clock_rate = 21, - .clock_prescale_rate = 2, -}; - -max283x_driver_t max283x = {}; - -static ssp_config_t ssp_config_max5864 = { - /* FIXME speed up once everything is working reliably */ - /* - // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - const uint8_t serial_clock_rate = 32; - const uint8_t clock_prescale_rate = 128; - */ - // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - .data_bits = SSP_DATA_8BITS, - .serial_clock_rate = 21, - .clock_prescale_rate = 2, -}; - -spi_bus_t spi_bus_ssp1 = { - .obj = (void*) SSP1_BASE, - .config = &ssp_config_max5864, - .start = spi_ssp_start, - .stop = spi_ssp_stop, - .transfer = spi_ssp_transfer, - .transfer_gather = spi_ssp_transfer_gather, -}; - -max5864_driver_t max5864 = { - .bus = &spi_bus_ssp1, - .target_init = max5864_target_init, -}; - -ssp_config_t ssp_config_w25q80bv = { - .data_bits = SSP_DATA_8BITS, - .serial_clock_rate = 2, - .clock_prescale_rate = 2, -}; - -static spi_bus_t spi_bus_ssp0 = { - .obj = (void*) SSP0_BASE, - .config = &ssp_config_w25q80bv, - .start = spi_ssp_start, - .stop = spi_ssp_stop, - .transfer = spi_ssp_transfer, - .transfer_gather = spi_ssp_transfer_gather, -}; - -w25q80bv_driver_t spi_flash = { - .bus = &spi_bus_ssp0, - .target_init = w25q80bv_target_init, -}; - -sgpio_config_t sgpio_config = { - .slice_mode_multislice = true, -}; - -#ifdef IS_PRALINE -static ssp_config_t ssp_config_ice40_fpga = { - .data_bits = SSP_DATA_8BITS, - .spi_mode = SSP_CPOL_1_CPHA_1, - .serial_clock_rate = 21, - .clock_prescale_rate = 2, -}; - -ice40_spi_driver_t ice40 = { - .bus = &spi_bus_ssp1, -}; - -fpga_driver_t fpga = { - .bus = &ice40, -}; -#endif - -radio_t radio = { - .sample_rate_cb = sample_rate_set, -}; - -rf_path_t rf_path; - -jtag_gpio_t jtag_gpio_cpld; - -jtag_t jtag_cpld = { - .gpio = &jtag_gpio_cpld, -}; - -void ssp1_set_mode_max283x(void) -{ - spi_bus_start(&spi_bus_ssp1, &ssp_config_max283x); -} - -void ssp1_set_mode_max5864(void) -{ - spi_bus_start(max5864.bus, &ssp_config_max5864); -} - -#ifdef IS_PRALINE -void ssp1_set_mode_ice40(void) -{ - spi_bus_start(&spi_bus_ssp1, &ssp_config_ice40_fpga); -} #endif void pin_shutdown(void) diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 6e0c1cc0..20ae76f0 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -27,50 +27,6 @@ extern "C" { #endif -#include "cpld_jtag.h" -#include "i2c_bus.h" -#include "i2c_lpc.h" -#include "max283x.h" -#include "max5864.h" -#include "mixer.h" -#include "platform_detect.h" // IWYU pragma: keep -#include "radio.h" -#include "rf_path.h" -#include "sgpio.h" -#include "si5351c.h" -#include "spi_ssp.h" -#include "w25q80bv.h" -#ifdef IS_PRALINE - #include "fpga.h" - #include "ice40_spi.h" -#endif - -/* TODO: Hide these configurations */ -extern const i2c_lpc_config_t i2c_config_si5351c_fast_clock; -extern si5351c_driver_t clock_gen; -extern ssp_config_t ssp_config_w25q80bv; - -extern max283x_driver_t max283x; -#ifdef IS_PRALINE -extern ice40_spi_driver_t ice40; -extern fpga_driver_t fpga; -#endif -extern max283x_driver_t max283x; -extern max5864_driver_t max5864; -extern mixer_driver_t mixer; -extern w25q80bv_driver_t spi_flash; -extern sgpio_config_t sgpio_config; -extern radio_t radio; -extern rf_path_t rf_path; -extern jtag_t jtag_cpld; -extern i2c_bus_t i2c0; - -void ssp1_set_mode_max283x(void); -void ssp1_set_mode_max5864(void); -#ifdef IS_PRALINE -void ssp1_set_mode_ice40(void); -#endif - void pin_shutdown(void); void pin_setup(void); diff --git a/firmware/common/operacake.c b/firmware/common/operacake.c index 61d78512..24ca6541 100644 --- a/firmware/common/operacake.c +++ b/firmware/common/operacake.c @@ -26,9 +26,9 @@ #include +#include "drivers.h" #include "gpio.h" #include "gpio_lpc.h" -#include "hackrf_core.h" #include "i2c_bus.h" #include "operacake_sctimer.h" #include "platform_scu.h" diff --git a/firmware/common/portapack.c b/firmware/common/portapack.c index 455df871..f25a4a6e 100644 --- a/firmware/common/portapack.c +++ b/firmware/common/portapack.c @@ -26,9 +26,9 @@ #include "cpld_jtag.h" #include "delay.h" +#include "drivers.h" #include "gpio.h" #include "gpio_lpc.h" -#include "hackrf_core.h" #include "platform_gpio.h" #include "platform_scu.h" diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 65412c4b..2d3ce8c3 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -26,10 +26,10 @@ #include #include "clock_io.h" +#include "drivers.h" #include "fixed_point.h" -#include "hackrf_core.h" -#include "mixer.h" #include "max283x.h" +#include "mixer.h" #include "platform_detect.h" #include "rf_path.h" #include "transceiver_mode.h" diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 6cadea1c..0506a3bf 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -23,7 +23,7 @@ #include "rf_path.h" -#include "hackrf_core.h" +#include "drivers.h" #include "max283x.h" #include "max5864.h" #include "mixer.h" diff --git a/firmware/common/rom_iap.c b/firmware/common/rom_iap.c index a8f185ad..09da0b7c 100644 --- a/firmware/common/rom_iap.c +++ b/firmware/common/rom_iap.c @@ -22,7 +22,7 @@ #include -#include "hackrf_core.h" +#include "drivers.h" #include "rom_iap.h" #include "spi_bus.h" #include "w25q80bv.h" diff --git a/firmware/common/ui_rad1o.c b/firmware/common/ui_rad1o.c index 878e9e74..757e11f1 100644 --- a/firmware/common/ui_rad1o.c +++ b/firmware/common/ui_rad1o.c @@ -27,7 +27,7 @@ #include #include "clock_gen.h" -#include "hackrf_core.h" +#include "drivers.h" #include "rf_path.h" #include "transceiver_mode.h" #ifdef IS_NOT_RAD1O diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 6384acdc..664f23f1 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -168,6 +168,7 @@ endmacro() macro(DeclareTargets) SET(SRC_M4 ${SRC_M4} + ${PATH_HACKRF_FIRMWARE_COMMON}/drivers.c ${PATH_HACKRF_FIRMWARE_COMMON}/power.c ${PATH_HACKRF_FIRMWARE_COMMON}/cpu_clock.c ${PATH_HACKRF_FIRMWARE_COMMON}/delay.c diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index bd2c5964..982a84bf 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_cpld.c b/firmware/hackrf_usb/usb_api_cpld.c index 7381601d..ed2beeda 100644 --- a/firmware/hackrf_usb/usb_api_cpld.c +++ b/firmware/hackrf_usb/usb_api_cpld.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index 632ce0e5..58c1684c 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_spiflash.c b/firmware/hackrf_usb/usb_api_spiflash.c index d422836e..2c944a10 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.c +++ b/firmware/hackrf_usb/usb_api_spiflash.c @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index 4f7d8e57..ae3b399d 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -25,8 +25,8 @@ #include +#include #include -#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 153b760b..b6c6782b 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -27,8 +27,8 @@ #include #include +#include #include -#include #include #include #include From 679179eb63976260389b98d958550608a52471fa Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Fri, 24 Apr 2026 09:03:47 +0200 Subject: [PATCH 143/238] firmware: rename hackrf_core.x to pins.x --- firmware/blinky/blinky.c | 4 ++-- firmware/common/{hackrf_core.c => pins.c} | 8 ++++---- firmware/common/{hackrf_core.h => pins.h} | 6 ++++-- firmware/common/rf_path.c | 2 +- firmware/hackrf-common.cmake | 2 +- firmware/hackrf_usb/hackrf_usb.c | 6 +++--- firmware/hackrf_usb/usb_api_board_info.c | 4 ++-- 7 files changed, 17 insertions(+), 15 deletions(-) rename firmware/common/{hackrf_core.c => pins.c} (98%) rename firmware/common/{hackrf_core.h => pins.h} (91%) diff --git a/firmware/blinky/blinky.c b/firmware/blinky/blinky.c index 0bf89bf8..fdaf3ef7 100644 --- a/firmware/blinky/blinky.c +++ b/firmware/blinky/blinky.c @@ -20,15 +20,15 @@ */ #include "delay.h" -#include "hackrf_core.h" #include "leds.h" +#include "pins.h" #include "platform_detect.h" #include "power.h" int main(void) { detect_hardware_platform(); - pin_setup(); + pins_setup(); #ifndef PRALINE /* enable 1V8 power supply so that the 1V8 LED lights up */ diff --git a/firmware/common/hackrf_core.c b/firmware/common/pins.c similarity index 98% rename from firmware/common/hackrf_core.c rename to firmware/common/pins.c index 2a7bc376..35b77838 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/pins.c @@ -21,7 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#include "hackrf_core.h" +#include "pins.h" #include #include @@ -40,7 +40,7 @@ #include "clock_io.h" #endif -void pin_shutdown(void) +void pins_shutdown(void) { /* Configure all GPIO as Input (safe state) */ gpio_init(); @@ -209,8 +209,8 @@ void pin_shutdown(void) SCU_SFSI2C0 = SCU_I2C0_NOMINAL; } -/* Run after pin_shutdown() and prior to enabling power supplies. */ -void pin_setup(void) +/* Run after pins_shutdown() and prior to enabling power supplies. */ +void pins_setup(void) { /* Detect Platform */ const platform_gpio_t* gpio = platform_gpio(); diff --git a/firmware/common/hackrf_core.h b/firmware/common/pins.h similarity index 91% rename from firmware/common/hackrf_core.h rename to firmware/common/pins.h index 20ae76f0..b9454d18 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/pins.h @@ -27,8 +27,10 @@ extern "C" { #endif -void pin_shutdown(void); -void pin_setup(void); +#include "platform_detect.h" // IWYU pragma: keep + +void pins_shutdown(void); +void pins_setup(void); #ifdef __cplusplus } diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 0506a3bf..ea1c0d45 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -319,7 +319,7 @@ static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) void rf_path_pin_setup(rf_path_t* const rf_path) { -#ifdef JAWBREAKER +#ifdef IS_JAWBREAKER (void) rf_path; #else const platform_scu_t* scu = platform_scu(); diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 664f23f1..04d8b1a3 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -172,7 +172,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/power.c ${PATH_HACKRF_FIRMWARE_COMMON}/cpu_clock.c ${PATH_HACKRF_FIRMWARE_COMMON}/delay.c - ${PATH_HACKRF_FIRMWARE_COMMON}/hackrf_core.c + ${PATH_HACKRF_FIRMWARE_COMMON}/pins.c ${PATH_HACKRF_FIRMWARE_COMMON}/leds.c ${PATH_HACKRF_FIRMWARE_COMMON}/sgpio.c ${PATH_HACKRF_FIRMWARE_COMMON}/rf_path.c diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 982a84bf..54431ff3 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -35,10 +35,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -444,12 +444,12 @@ int main(void) detect_hardware_platform(); board_id_t board_id = detected_platform(); - pin_shutdown(); + pins_shutdown(); if (board_id != BOARD_ID_RAD1O) { clock_gen_shutdown(); } delay_us_at_mhz(10000, 96); - pin_setup(); + pins_setup(); #ifdef IS_PRALINE if (IS_PRALINE) { enable_3v3aux_power(); diff --git a/firmware/hackrf_usb/usb_api_board_info.c b/firmware/hackrf_usb/usb_api_board_info.c index c4634605..2d017378 100644 --- a/firmware/hackrf_usb/usb_api_board_info.c +++ b/firmware/hackrf_usb/usb_api_board_info.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include #include @@ -129,7 +129,7 @@ usb_request_status_t usb_vendor_request_reset( const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { - pin_shutdown(); + pins_shutdown(); clock_gen_shutdown(); #ifdef IS_H1_R9 if (IS_H1_R9) { From db376ad1946b6f14b8c00bb5856d18869192f231 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 17 Mar 2026 17:08:49 -0400 Subject: [PATCH 144/238] Change Praline CLKIN default to P1_CLKIN Previously the CLKIN switch defaulted to P22_CLKIN, enabling usage of the clock input on pin header P22 but not on SMA port P1. This change enables use of clock input on P1 and disables P22_CLKIN by default. --- ci-scripts/hackrf_pro_test.py | 3 --- firmware/common/pins.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/ci-scripts/hackrf_pro_test.py b/ci-scripts/hackrf_pro_test.py index 3d0b1c63..44b6eb56 100644 --- a/ci-scripts/hackrf_pro_test.py +++ b/ci-scripts/hackrf_pro_test.py @@ -663,9 +663,6 @@ class HackRF: self.rf_test_cases = praline_r110_rf_test_cases def clkin(self): - if self.name == "EUT" and self.id == "5": - debug = subprocess.run([self.bin_dir + "/hackrf_debug", "-d", self.serial, - "-C", "0"]) command = subprocess.run([self.bin_dir + "/hackrf_clock", "-i", "-d", self.serial], capture_output=True, encoding="utf-8", timeout=TIMEOUT) diff --git a/firmware/common/pins.c b/firmware/common/pins.c index 35b77838..6f8123cb 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -185,7 +185,7 @@ void pins_shutdown(void) p2_ctrl_set(P2_SIGNAL_CLK3); p1_ctrl_set(P1_SIGNAL_CLKIN); narrowband_filter_set(0); - clkin_ctrl_set(CLKIN_SIGNAL_P22); + clkin_ctrl_set(CLKIN_SIGNAL_P1); gpio_output(gpio->p2_ctrl0); gpio_output(gpio->p2_ctrl1); From 3e1542261a64b333d246b5e162ed88fe15caa28c Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 21 Apr 2026 10:21:40 -0400 Subject: [PATCH 145/238] Add CLKIN control option to hackrf_clock --- host/hackrf-tools/src/hackrf_clock.c | 37 ++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_clock.c b/host/hackrf-tools/src/hackrf_clock.c index 36f066c1..01c2c800 100644 --- a/host/hackrf-tools/src/hackrf_clock.c +++ b/host/hackrf-tools/src/hackrf_clock.c @@ -103,6 +103,19 @@ int parse_p2_ctrl_signal(char* s, enum p2_ctrl_signal* const signal) return HACKRF_SUCCESS; } +int parse_clkin_ctrl_signal(char* s, enum clkin_ctrl_signal* const signal) +{ + if (strcasecmp("p1", s) == 0) { + *signal = CLKIN_SIGNAL_P1; + } else if (strcasecmp("p22", s) == 0) { + *signal = CLKIN_SIGNAL_P22; + } else { + fprintf(stderr, "Invalid signal '%s'\n", s); + return HACKRF_ERROR_INVALID_PARAM; + } + return HACKRF_SUCCESS; +} + int si5351c_read_register(hackrf_device* device, const uint16_t register_number) { uint16_t register_value; @@ -295,6 +308,8 @@ static void usage() printf("\tone of: clkin, trigger_in, trigger_out, p22_clkin, pps_out, aux_clk1, aux_clk2, off\n"); printf("\t-2, --p2 : select the signal for the HackRF Pro P2 SMA connector (default: clkout)\n"); printf("\tone of: clkout, trigger_in, trigger_out\n"); + printf("\t-c, --clkin-ctrl : select the HackRF Pro CLKIN signal (default: p1)\n"); + printf("\tone of: p1, p22\n"); printf("\t-d, --device : Serial number of desired HackRF.\n"); printf("\nExamples:\n"); printf("\thackrf_clock -r 3 : prints settings for CLKOUT\n"); @@ -308,6 +323,7 @@ static struct option long_options[] = { {"clkout", required_argument, 0, 'o'}, {"p1", required_argument, 0, '1'}, {"p2", required_argument, 0, '2'}, + {"clkin-ctrl", required_argument, 0, 'c'}, {"device", required_argument, 0, 'd'}, {0, 0, 0, 0}, }; @@ -324,8 +340,10 @@ int main(int argc, char** argv) uint8_t clkin_status; bool p1_ctrl = false; bool p2_ctrl = false; + bool clkin_ctrl = false; enum p1_ctrl_signal p1_signal = P1_SIGNAL_CLKIN; enum p2_ctrl_signal p2_signal = P2_SIGNAL_CLK3; + enum clkin_ctrl_signal clkin_signal = CLKIN_SIGNAL_P1; const char* serial_number = NULL; int result = hackrf_init(); @@ -339,7 +357,7 @@ int main(int argc, char** argv) while ((opt = getopt_long( argc, argv, - "r:aio:1:2:d:h?", + "r:aio:1:2:c:d:h?", long_options, &option_index)) != EOF) { switch (opt) { @@ -371,6 +389,11 @@ int main(int argc, char** argv) result = parse_p2_ctrl_signal(optarg, &p2_signal); break; + case 'c': + clkin_ctrl = true; + result = parse_clkin_ctrl_signal(optarg, &clkin_signal); + break; + case 'd': serial_number = optarg; break; @@ -394,7 +417,7 @@ int main(int argc, char** argv) } } - if (!clkin && !clkout && !read && !p1_ctrl && !p2_ctrl) { + if (!clkin && !clkout && !read && !p1_ctrl && !p2_ctrl && !clkin_ctrl) { fprintf(stderr, "An operation must be specified.\n"); usage(); return EXIT_FAILURE; @@ -460,6 +483,16 @@ int main(int argc, char** argv) } } + if (clkin_ctrl) { + result = hackrf_set_clkin_ctrl(device, clkin_signal); + if (result != HACKRF_SUCCESS) { + printf("hackrf_set_clkin_ctrl() failed: %s (%d)\n", + hackrf_error_name(result), + result); + return EXIT_FAILURE; + } + } + result = hackrf_close(device); if (result) { printf("hackrf_close() failed: %s (%d)\n", From fd0c7cc5f1f416f8097ede8e03790845086a1dfa Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 21 Apr 2026 13:01:58 -0400 Subject: [PATCH 146/238] Document Praline P1, P2, and CLKIN control --- docs/source/external_clock_interface.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/source/external_clock_interface.rst b/docs/source/external_clock_interface.rst index fc3f3b1d..9c09ca66 100644 --- a/docs/source/external_clock_interface.rst +++ b/docs/source/external_clock_interface.rst @@ -9,12 +9,18 @@ HackRF Pro HackRF Pro has two configurable SMA ports, P1 and P2. By default, P1 is configured as CLKIN and P2 as CLKOUT. The default behaviour of these signals is as described for HackRF One below. +A second CLKIN signal is available on header P22 pin 2. Unlike HackRF One, HackRF Pro's P22_CLKIN is a separate signal from P1_CLKIN. To enable P22_CLKIN instead of P1_CLKIN use ``hackrf_clock -c p22``. + +Various internal signals can be connected to P1 or P2 instead of the default CLKIN and CLKOUT signals. Use ``hackrf_clock -1`` or ``hackrf_clock -2`` to select a different signal. + HackRF One ~~~~~~~~~~ -HackRF One produces a 10 MHz clock signal on CLKOUT. The signal is a 3.3 V, 10 MHz square wave intended for a high impedance load. +HackRF One produces a 10 MHz clock signal on the CLKOUT SMA port. The signal is a 3.3 V, 10 MHz square wave intended for a high impedance load. -The CLKIN port on HackRF One is a high impedance input that expects 3.3 V square wave at 10 MHz. Do not exceed 3.3 V or drop below 0 V on this input. Do not connect a clock signal at a frequency other than 10 MHz (unless you modify the firmware to support this). You may directly connect the CLKOUT port of one HackRF One to the CLKIN port of another HackRF One. +The CLKIN SMA port on HackRF One is a high impedance input that expects 3.3 V square wave at 10 MHz. Do not exceed 3.3 V or drop below 0 V on this input. Do not connect a clock signal at a frequency other than 10 MHz (unless you modify the firmware to support this). You may directly connect the CLKOUT port of one HackRF One to the CLKIN port of another HackRF. + +The CLKIN signal is also connected to header P22 pin 2. Unlike HackRF Pro, HackRF One has only one CLKIN signal shared between P22 pin 2 and the CLKIN port. Do not connect input signals to both CLKIN and P22 pin 2 simultaneously. HackRF One uses CLKIN instead of the internal crystal when a clock signal is detected on CLKIN. The switch to or from CLKIN only happens when a transmit or receive operation begins. From ba5fe7f7daa9ee487df8950134896a8df35a54cb Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sat, 18 Oct 2025 23:08:12 +0100 Subject: [PATCH 147/238] Rename usb_bulk_buffer to usb_samp_buffer. --- firmware/common/LPC43xx_M4_memory.ld | 4 ++-- firmware/common/fpga_selftest.c | 20 +++++++++---------- firmware/hackrf_usb/usb_api_sweep.c | 4 ++-- firmware/hackrf_usb/usb_api_transceiver.c | 10 +++++----- .../{usb_bulk_buffer.h => usb_buffer.h} | 8 ++++---- 5 files changed, 23 insertions(+), 23 deletions(-) rename firmware/hackrf_usb/{usb_bulk_buffer.h => usb_buffer.h} (85%) diff --git a/firmware/common/LPC43xx_M4_memory.ld b/firmware/common/LPC43xx_M4_memory.ld index 933fa854..d37542f9 100644 --- a/firmware/common/LPC43xx_M4_memory.ld +++ b/firmware/common/LPC43xx_M4_memory.ld @@ -35,11 +35,11 @@ MEMORY * to get performance benefit of having two USB buffers addressable * simultaneously (on two different buses of the AHB multilayer matrix) */ - ram_usb (rwx) : ORIGIN = 0x20008000, LENGTH = 32K + ram_samp (rwx) : ORIGIN = 0x20008000, LENGTH = 32K } -usb_bulk_buffer = ORIGIN(ram_usb); lz4_in_buf = ORIGIN(ram_lz4_in); lz4_out_buf = ORIGIN(ram_lz4_out); +usb_samp_buffer = ORIGIN(ram_samp); m0_state = ORIGIN(ram_shared); PROVIDE(__ram_m0_start__ = ORIGIN(ram_m0)); diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index 30e70ea2..b23be525 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -37,8 +37,8 @@ #include "streaming.h" // USB buffer used during selftests. -#define USB_BULK_BUFFER_SIZE 0x8000 -extern uint8_t usb_bulk_buffer[USB_BULK_BUFFER_SIZE]; +#define USB_SAMP_BUFFER_SIZE 0x8000 +extern uint8_t usb_samp_buffer[USB_SAMP_BUFFER_SIZE]; static int rx_samples(const unsigned int num_samples, uint32_t max_cycles) { @@ -115,10 +115,10 @@ bool fpga_sgpio_selftest(void) fpga_set_prbs_enable(&fpga, false); // Generate sequence from first value and compare. - bool seq_in_sync = (usb_bulk_buffer[0] != 0); - uint8_t seq = lfsr_advance(usb_bulk_buffer[0]); + bool seq_in_sync = (usb_samp_buffer[0] != 0); + uint8_t seq = lfsr_advance(usb_samp_buffer[0]); for (int i = 1; i < 512; ++i) { - if (usb_bulk_buffer[i] != seq) { + if (usb_samp_buffer[i] != seq) { seq_in_sync = false; break; } @@ -189,7 +189,7 @@ bool fpga_if_xcvr_selftest(void) return false; } - const size_t num_samples = USB_BULK_BUFFER_SIZE / 2; + const size_t num_samples = USB_SAMP_BUFFER_SIZE / 2; // Set common RX path and gateware settings for the measurements. fpga_set_tx_nco_pstep(&fpga, 64); // NCO phase increment @@ -206,7 +206,7 @@ bool fpga_if_xcvr_selftest(void) timeout = true; } measure_tone( - (int8_t*) usb_bulk_buffer, + (int8_t*) usb_samp_buffer, num_samples, &selftest.xcvr_measurements[0]); @@ -217,7 +217,7 @@ bool fpga_if_xcvr_selftest(void) timeout = true; } measure_tone( - (int8_t*) usb_bulk_buffer, + (int8_t*) usb_samp_buffer, num_samples, &selftest.xcvr_measurements[1]); @@ -230,7 +230,7 @@ bool fpga_if_xcvr_selftest(void) timeout = true; } measure_tone( - (int8_t*) usb_bulk_buffer, + (int8_t*) usb_samp_buffer, num_samples, &selftest.xcvr_measurements[2]); @@ -241,7 +241,7 @@ bool fpga_if_xcvr_selftest(void) timeout = true; } measure_tone( - (int8_t*) usb_bulk_buffer, + (int8_t*) usb_samp_buffer, num_samples, &selftest.xcvr_measurements[3]); diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index ae3b399d..eee74228 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -40,7 +40,7 @@ #include "usb_api_sweep.h" #include "usb_api_transceiver.h" -#include "usb_bulk_buffer.h" +#include "usb_buffer.h" #include "usb_endpoint.h" #define MIN(x, y) ((x) < (y) ? (x) : (y)) @@ -207,7 +207,7 @@ void sweep_mode(uint32_t seq) m0_state.next_mode = M0_MODE_RX; // Write metadata to buffer. - buffer = &usb_bulk_buffer[phase * 0x4000]; + buffer = &usb_samp_buffer[phase * 0x4000]; *buffer = 0x7f; *(buffer + 1) = 0x7f; *(buffer + 2) = sweep_freq & 0xff; diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index b6c6782b..f272dac5 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -41,7 +41,7 @@ #include #include -#include "usb_bulk_buffer.h" +#include "usb_buffer.h" #include "usb_endpoint.h" #define USB_TRANSFER_SIZE 0x4000 @@ -442,7 +442,7 @@ void rx_mode(uint32_t seq) if ((m0_state.m0_count - usb_count) >= USB_TRANSFER_SIZE) { usb_transfer_schedule_block( &usb_endpoint_bulk_in, - &usb_bulk_buffer[usb_count & USB_BULK_BUFFER_MASK], + &usb_samp_buffer[usb_count & USB_SAMP_BUFFER_MASK], USB_TRANSFER_SIZE, transceiver_bulk_transfer_complete, NULL); @@ -464,14 +464,14 @@ void tx_mode(uint32_t seq) // Set up OUT transfer of buffer 0. usb_transfer_schedule_block( &usb_endpoint_bulk_out, - &usb_bulk_buffer[0x0000], + &usb_samp_buffer[0x0000], USB_TRANSFER_SIZE, transceiver_bulk_transfer_complete, NULL); usb_count += USB_TRANSFER_SIZE; while (transceiver_request.seq == seq) { - if (!started && (m0_state.m4_count == USB_BULK_BUFFER_SIZE)) { + if (!started && (m0_state.m4_count == USB_SAMP_BUFFER_SIZE)) { // Buffer is now full, start streaming. baseband_streaming_enable(&sgpio_config); started = true; @@ -479,7 +479,7 @@ void tx_mode(uint32_t seq) if ((usb_count - m0_state.m0_count) <= USB_TRANSFER_SIZE) { usb_transfer_schedule_block( &usb_endpoint_bulk_out, - &usb_bulk_buffer[usb_count & USB_BULK_BUFFER_MASK], + &usb_samp_buffer[usb_count & USB_SAMP_BUFFER_MASK], USB_TRANSFER_SIZE, transceiver_bulk_transfer_complete, NULL); diff --git a/firmware/hackrf_usb/usb_bulk_buffer.h b/firmware/hackrf_usb/usb_buffer.h similarity index 85% rename from firmware/hackrf_usb/usb_bulk_buffer.h rename to firmware/hackrf_usb/usb_buffer.h index e21a84ff..5aecdb67 100644 --- a/firmware/hackrf_usb/usb_bulk_buffer.h +++ b/firmware/hackrf_usb/usb_buffer.h @@ -25,11 +25,11 @@ #include -#define USB_BULK_BUFFER_SIZE 0x8000 -#define USB_BULK_BUFFER_MASK 0x7FFF +#define USB_SAMP_BUFFER_SIZE 0x8000 +#define USB_SAMP_BUFFER_MASK 0x7FFF -/* Address of usb_bulk_buffer is set in ldscripts. If you change the name of this +/* Address of usb_samp_buffer is set in ldscripts. If you change the name of this * variable, it won't be where it needs to be in the processor's address space, * unless you also adjust the ldscripts. */ -extern uint8_t usb_bulk_buffer[USB_BULK_BUFFER_SIZE]; +extern uint8_t usb_samp_buffer[USB_SAMP_BUFFER_SIZE]; From d222e0188e3bf0ecdcde15f30cc6fb0251ba8978 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sun, 19 Oct 2025 22:39:10 +0100 Subject: [PATCH 148/238] Add new usb_bulk_buffer. --- firmware/common/LPC4320_M4_memory.ld | 3 ++- firmware/common/LPC4330_M4_memory.ld | 3 ++- firmware/common/LPC43xx_M4_memory.ld | 1 + firmware/hackrf_usb/usb_buffer.h | 10 +++++++--- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/firmware/common/LPC4320_M4_memory.ld b/firmware/common/LPC4320_M4_memory.ld index a5997f32..48be94da 100644 --- a/firmware/common/LPC4320_M4_memory.ld +++ b/firmware/common/LPC4320_M4_memory.ld @@ -26,7 +26,8 @@ MEMORY { /* rom is really the shadow region that points to SPI flash or elsewhere */ rom (rx) : ORIGIN = 0x00000000, LENGTH = 1M - ram_local1 (rwx) : ORIGIN = 0x10000000, LENGTH = 96K + ram_local1 (rwx) : ORIGIN = 0x10000000, LENGTH = 64K + ram_usb (rw) : ORIGIN = 0x10010000, LENGTH = 32K ram_local2 (rwx) : ORIGIN = 0x10080000, LENGTH = 32K ram_sleep (rwx) : ORIGIN = 0x10088000, LENGTH = 8K } diff --git a/firmware/common/LPC4330_M4_memory.ld b/firmware/common/LPC4330_M4_memory.ld index 1e886d3a..1d42ebee 100644 --- a/firmware/common/LPC4330_M4_memory.ld +++ b/firmware/common/LPC4330_M4_memory.ld @@ -26,7 +26,8 @@ MEMORY { /* rom is really the shadow region that points to SPI flash or elsewhere */ rom (rx) : ORIGIN = 0x00000000, LENGTH = 128K - ram_local1 (rwx) : ORIGIN = 0x10000000, LENGTH = 128K + ram_local1 (rwx) : ORIGIN = 0x10000000, LENGTH = 96K + ram_usb(rw) : ORIGIN = 0x10018000, LENGTH = 32K ram_local2 (rwx) : ORIGIN = 0x10080000, LENGTH = 64K ram_sleep (rwx) : ORIGIN = 0x10090000, LENGTH = 8K } diff --git a/firmware/common/LPC43xx_M4_memory.ld b/firmware/common/LPC43xx_M4_memory.ld index d37542f9..fc7dcee7 100644 --- a/firmware/common/LPC43xx_M4_memory.ld +++ b/firmware/common/LPC43xx_M4_memory.ld @@ -41,5 +41,6 @@ MEMORY lz4_in_buf = ORIGIN(ram_lz4_in); lz4_out_buf = ORIGIN(ram_lz4_out); usb_samp_buffer = ORIGIN(ram_samp); +usb_bulk_buffer = ORIGIN(ram_usb); m0_state = ORIGIN(ram_shared); PROVIDE(__ram_m0_start__ = ORIGIN(ram_m0)); diff --git a/firmware/hackrf_usb/usb_buffer.h b/firmware/hackrf_usb/usb_buffer.h index 5aecdb67..07543025 100644 --- a/firmware/hackrf_usb/usb_buffer.h +++ b/firmware/hackrf_usb/usb_buffer.h @@ -28,8 +28,12 @@ #define USB_SAMP_BUFFER_SIZE 0x8000 #define USB_SAMP_BUFFER_MASK 0x7FFF -/* Address of usb_samp_buffer is set in ldscripts. If you change the name of this - * variable, it won't be where it needs to be in the processor's address space, - * unless you also adjust the ldscripts. +#define USB_BULK_BUFFER_SIZE 0x8000 +#define USB_BULK_BUFFER_MASK 0x7FFF + +/* Addresses of usb_samp_buffer and usb_bulk_buffer are set in ldscripts. If + * you change the name of these variables, they won't be where they need to + * be in the processor's address space, unless you also adjust the ldscripts. */ extern uint8_t usb_samp_buffer[USB_SAMP_BUFFER_SIZE]; +extern uint8_t usb_bulk_buffer[USB_BULK_BUFFER_SIZE]; From 40a8dc53dc9f0f7f858c911eac47186f16127ce8 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sun, 19 Oct 2025 22:39:23 +0100 Subject: [PATCH 149/238] Use both buffers, with memcpy in place of DMA for now. --- firmware/hackrf_usb/usb_api_transceiver.c | 179 +++++++++++++++++----- 1 file changed, 142 insertions(+), 37 deletions(-) diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index f272dac5..148741eb 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -45,6 +46,11 @@ #include "usb_endpoint.h" #define USB_TRANSFER_SIZE 0x4000 +#define DMA_TRANSFER_SIZE 0x4000 + +#define BUF_HALF_MASK (USB_SAMP_BUFFER_SIZE >> 1) + +volatile uint32_t dma_started, dma_pending, usb_started, usb_completed; typedef struct { uint32_t freq_mhz; @@ -68,6 +74,8 @@ typedef struct { set_sample_r_params_t set_sample_r_params; +void dma_isr(void); + usb_request_status_t usb_vendor_request_set_baseband_filter_bandwidth( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) @@ -340,6 +348,11 @@ void transceiver_shutdown(void) void transceiver_startup(const transceiver_mode_t mode) { + dma_started = 0; + dma_pending = 0; + usb_started = 0; + usb_completed = 0; + radio_switch_opmode(&radio, mode); switch (mode) { @@ -424,30 +437,115 @@ usb_request_status_t usb_vendor_request_set_rx_overrun_limit( return USB_REQUEST_STATUS_OK; } +void transceiver_start_dma(void* src, void* dest, size_t size) +{ + dma_pending = size; + memcpy(dest, src, size); + dma_isr(); +} + +void dma_isr(void) +{ + m0_state.m4_count += dma_pending; + dma_pending = 0; +} + void transceiver_bulk_transfer_complete(void* user_data, unsigned int bytes_transferred) { (void) user_data; - m0_state.m4_count += bytes_transferred; + usb_completed += bytes_transferred; +} + +typedef enum { + DIRECTION_RX, + DIRECTION_TX, +} direction_t; + +void start_dma_if_possible(direction_t direction, size_t size) +{ + if (dma_pending) { + return; + } + + uint32_t sampling_completed = m0_state.m0_count; + uint32_t dma_completed = m0_state.m4_count; + uint32_t samp_offset = dma_started & USB_SAMP_BUFFER_MASK; + uint32_t bulk_offset = dma_started & USB_BULK_BUFFER_MASK; + uint32_t data_available, space_in_use, space_available, samp_buf_margin; + uint8_t *dest, *src; + + if (direction == DIRECTION_RX) { + data_available = sampling_completed - dma_started; + space_in_use = usb_completed - dma_completed; + space_available = USB_BULK_BUFFER_SIZE - space_in_use; + samp_buf_margin = USB_SAMP_BUFFER_SIZE - data_available; + src = &usb_samp_buffer[samp_offset]; + dest = &usb_bulk_buffer[bulk_offset]; + } else { + data_available = usb_completed - dma_started; + space_in_use = dma_completed - sampling_completed; + space_available = USB_SAMP_BUFFER_SIZE - space_in_use; + samp_buf_margin = space_in_use; + src = &usb_bulk_buffer[bulk_offset]; + dest = &usb_samp_buffer[samp_offset]; + } + + if (data_available < size || size > space_available) { + return; + } + + uint32_t m0_buf_half = sampling_completed & BUF_HALF_MASK; + uint32_t dma_buf_half = dma_started & BUF_HALF_MASK; + bool same_buf_half = m0_buf_half == dma_buf_half; + + if (same_buf_half && samp_buf_margin >= (USB_SAMP_BUFFER_SIZE / 2)) { + return; + } + + transceiver_start_dma(src, dest, size); + + dma_started += size; +} + +void start_usb_if_possible(direction_t direction) +{ + uint32_t bulk_offset = usb_started & USB_BULK_BUFFER_MASK; + uint32_t dma_completed = m0_state.m4_count; + uint32_t bytes_available; + usb_endpoint_t* usb_endpoint; + + if (direction == DIRECTION_RX) { + bytes_available = dma_completed - usb_started; + usb_endpoint = &usb_endpoint_bulk_in; + } else { + uint32_t space_used = usb_started - dma_completed; + bytes_available = USB_BULK_BUFFER_SIZE - space_used; + usb_endpoint = &usb_endpoint_bulk_out; + } + + if (bytes_available < USB_TRANSFER_SIZE) { + return; + } + + usb_transfer_schedule_block( + usb_endpoint, + &usb_bulk_buffer[bulk_offset], + USB_TRANSFER_SIZE, + transceiver_bulk_transfer_complete, + NULL); + + usb_started += USB_TRANSFER_SIZE; } void rx_mode(uint32_t seq) { - uint32_t usb_count = 0; - transceiver_startup(TRANSCEIVER_MODE_RX); baseband_streaming_enable(&sgpio_config); while (transceiver_request.seq == seq) { - if ((m0_state.m0_count - usb_count) >= USB_TRANSFER_SIZE) { - usb_transfer_schedule_block( - &usb_endpoint_bulk_in, - &usb_samp_buffer[usb_count & USB_SAMP_BUFFER_MASK], - USB_TRANSFER_SIZE, - transceiver_bulk_transfer_complete, - NULL); - usb_count += USB_TRANSFER_SIZE; - } + start_dma_if_possible(DIRECTION_RX, DMA_TRANSFER_SIZE); + start_usb_if_possible(DIRECTION_RX); radio_update(&radio); } @@ -456,35 +554,42 @@ void rx_mode(uint32_t seq) void tx_mode(uint32_t seq) { - unsigned int usb_count = 0; - bool started = false; - transceiver_startup(TRANSCEIVER_MODE_TX); - // Set up OUT transfer of buffer 0. - usb_transfer_schedule_block( - &usb_endpoint_bulk_out, - &usb_samp_buffer[0x0000], - USB_TRANSFER_SIZE, - transceiver_bulk_transfer_complete, - NULL); - usb_count += USB_TRANSFER_SIZE; + // First, make transfers directly into the sample buffer to fill it. + for (int i = 0; i < (USB_SAMP_BUFFER_SIZE / USB_TRANSFER_SIZE); i++) { + // Set up transfer. + usb_transfer_schedule_block( + &usb_endpoint_bulk_out, + &usb_samp_buffer[usb_started], + USB_TRANSFER_SIZE, + transceiver_bulk_transfer_complete, + NULL); + usb_started += USB_TRANSFER_SIZE; + // Wait for the transfer to complete. + while (usb_completed < usb_started) { + // Handle the host switching modes before filling the buffer. + if (transceiver_request.seq != seq) { + transceiver_shutdown(); + return; + } + + radio_update(&radio); + } + } + + // Sample buffer is now full. Update DMA counters accordingly. + dma_started = USB_SAMP_BUFFER_SIZE; + m0_state.m4_count = USB_SAMP_BUFFER_SIZE; + + // Start transmitting samples. + baseband_streaming_enable(&sgpio_config); + + // Continue feeding samples to the sample buffer. while (transceiver_request.seq == seq) { - if (!started && (m0_state.m4_count == USB_SAMP_BUFFER_SIZE)) { - // Buffer is now full, start streaming. - baseband_streaming_enable(&sgpio_config); - started = true; - } - if ((usb_count - m0_state.m0_count) <= USB_TRANSFER_SIZE) { - usb_transfer_schedule_block( - &usb_endpoint_bulk_out, - &usb_samp_buffer[usb_count & USB_SAMP_BUFFER_MASK], - USB_TRANSFER_SIZE, - transceiver_bulk_transfer_complete, - NULL); - usb_count += USB_TRANSFER_SIZE; - } + start_dma_if_possible(DIRECTION_TX, DMA_TRANSFER_SIZE); + start_usb_if_possible(DIRECTION_TX); radio_update(&radio); } From 0fb7b1c8c0ecb7854fa2d8a5b45bda05b8a84040 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sun, 19 Oct 2025 19:40:28 +0100 Subject: [PATCH 150/238] Reduce memory transfer size to 8KB. --- firmware/hackrf_usb/usb_api_transceiver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 148741eb..32efbc71 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -46,7 +46,7 @@ #include "usb_endpoint.h" #define USB_TRANSFER_SIZE 0x4000 -#define DMA_TRANSFER_SIZE 0x4000 +#define DMA_TRANSFER_SIZE 0x2000 #define BUF_HALF_MASK (USB_SAMP_BUFFER_SIZE >> 1) From cebf0c7ce1ef4d2c1699408fc7723d883f2886e1 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 1 Dec 2025 23:24:34 +0000 Subject: [PATCH 151/238] Flush both buffers before leaving TX mode. --- firmware/common/usb.h | 2 + firmware/hackrf_usb/usb_api_transceiver.c | 58 +++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/firmware/common/usb.h b/firmware/common/usb.h index 9445728a..2b8c6c8c 100644 --- a/firmware/common/usb.h +++ b/firmware/common/usb.h @@ -31,6 +31,8 @@ #include "usb_type.h" +usb_queue_head_t* usb_queue_head(const uint_fast8_t endpoint_address); + void usb_peripheral_reset(void); void usb_phy_enable(void); diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 32efbc71..2112fe07 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -27,6 +27,8 @@ #include #include +#include + #include #include #include @@ -593,6 +595,62 @@ void tx_mode(uint32_t seq) radio_update(&radio); } + // Host has now requested to stop TX. We won't initiate any further USB + // transfers into the bulk buffer. However, we should make sure all + // data currently in the USB bulk buffer reaches the sample buffer. + + if ((usb_started - usb_completed) > 0) { + // We were part way through a 16KB firmware-side transfer when + // the transceiver mode change request to stop TX was received. + // + // We want to include the contents of that partial transfer in + // the data we move to the sample buffer. + // + // The transfer was already stopped by usb_endpoint_flush(), + // which was called from request_transceiver_mode(). + // + // We will not have had a callback, and the transfer descriptor + // (dTD) will not have been updated, since the transfer did not + // complete. + // + // However, as long as we haven't started a new transfer, we + // can retrieve the partial byte count from the transfer + // overlay in the endpoint queue head (dQH) (UM10503 25.9.1). + + usb_queue_head_t* const qh = + usb_queue_head(usb_endpoint_bulk_out.address); + unsigned int bytes_remaining = + (qh->total_bytes & USB_TD_DTD_TOKEN_TOTAL_BYTES_MASK) >> + USB_TD_DTD_TOKEN_TOTAL_BYTES_SHIFT; + unsigned int bytes_transferred = USB_TRANSFER_SIZE - bytes_remaining; + usb_completed += bytes_transferred; + } + + // Feed the remaining data from the bulk buffer to the sample buffer. + // At this point, we also need to handle the case where there is less data + // to be transferred to the sample buffer than a full-sized DMA transfer. + + // Any remainder of less than 4 bytes will be ignored; this is the chunk + // size of our DMA transfers. + while ((usb_completed - m0_state.m4_count) >= 4) { + uint32_t data_available = usb_completed - dma_started; + if (data_available > DMA_TRANSFER_SIZE) { + start_dma_if_possible(DIRECTION_TX, DMA_TRANSFER_SIZE); + } else { + start_dma_if_possible(DIRECTION_TX, data_available); + } + radio_update(&radio); + } + + // Wait for the data in the sample buffer to be transmitted. + + // Any remainder of less than 32 bytes will be ignored; this is + // the chunk size used by the M0 core to transfer samples to SGPIO. + while ((m0_state.m4_count - m0_state.m0_count) >= 32) { + radio_update(&radio); + } + + // All data received from the host has now been transmitted. transceiver_shutdown(); } From ebe5a5acdffbe8e2ec8a3a273bf4b7e87317ee25 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 8 Dec 2025 16:05:09 +0000 Subject: [PATCH 152/238] Read USB API version in hackrf_open() and cache it. --- host/libhackrf/src/hackrf.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 48a25868..14c34ab2 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -143,6 +143,7 @@ typedef enum { struct hackrf_device { libusb_device_handle* usb_device; + uint16_t usb_api_version; struct libusb_transfer** transfers; hackrf_sample_block_cb_fn callback; volatile bool @@ -187,10 +188,8 @@ static const max2837_ft_t max2837_ft[] = { {28000000}, {0}}; -#define USB_API_REQUIRED(device, version) \ - uint16_t usb_version = 0; \ - hackrf_usb_api_version_read(device, &usb_version); \ - if (usb_version < version) \ +#define USB_API_REQUIRED(device, version) \ + if (device->usb_api_version < version) \ return HACKRF_ERROR_USB_API_VERSION; static const uint16_t hackrf_usb_vid = 0x1d50; @@ -713,6 +712,13 @@ static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** d { int result; hackrf_device* lib_device; + struct libusb_device_descriptor device_descriptor; + libusb_device* dev = libusb_get_device(usb_device); + result = libusb_get_device_descriptor(dev, &device_descriptor); + if (result < 0) { + last_libusb_error = result; + return HACKRF_ERROR_LIBUSB; + } //int speed = libusb_get_device_speed(usb_device); // TODO: Error or warning if not high speed USB? @@ -746,6 +752,7 @@ static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** d #endif lib_device->usb_device = usb_device; + lib_device->usb_api_version = device_descriptor.bcdDevice; lib_device->transfers = NULL; lib_device->callback = NULL; lib_device->transfer_thread_started = false; @@ -1700,17 +1707,7 @@ extern ADDAPI int ADDCALL hackrf_usb_api_version_read( hackrf_device* device, uint16_t* version) { - int result; - libusb_device* dev; - struct libusb_device_descriptor desc; - dev = libusb_get_device(device->usb_device); - result = libusb_get_device_descriptor(dev, &desc); - if (result < 0) { - last_libusb_error = result; - return HACKRF_ERROR_LIBUSB; - } - - *version = desc.bcdDevice; + *version = device->usb_api_version; return HACKRF_SUCCESS; } From 3517d0adfc3bdb34f806a997a862d2d75e3508ff Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 9 Dec 2025 16:32:14 +0000 Subject: [PATCH 153/238] NAK the request that takes us out of TX mode until buffer flushed. --- firmware/hackrf_usb/usb_api_transceiver.c | 14 ++++++++++++++ firmware/hackrf_usb/usb_api_transceiver.h | 2 ++ firmware/hackrf_usb/usb_endpoint.c | 3 ++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 2112fe07..cad75cd3 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -324,6 +324,17 @@ volatile transceiver_request_t transceiver_request = { .seq = 0, }; +void transceiver_usb_setup_complete(usb_endpoint_t* const endpoint) +{ + if (transceiver_request.mode == TRANSCEIVER_MODE_TX && + endpoint->setup.request == 1) { + // This is a request to leave TX mode. Do so but NAK for now. + request_transceiver_mode(endpoint->setup.value); + } else { + usb_setup_complete(endpoint); + } +} + // Must be called from an atomic context (normally USB ISR) void request_transceiver_mode(transceiver_mode_t mode) { @@ -651,6 +662,9 @@ void tx_mode(uint32_t seq) } // All data received from the host has now been transmitted. + // Now we can ACK the control request that took us out of TX mode. + usb_transfer_schedule_ack(usb_endpoint_control_in.in); + transceiver_shutdown(); } diff --git a/firmware/hackrf_usb/usb_api_transceiver.h b/firmware/hackrf_usb/usb_api_transceiver.h index df981c1e..383be18c 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.h +++ b/firmware/hackrf_usb/usb_api_transceiver.h @@ -36,6 +36,8 @@ typedef struct { extern volatile transceiver_request_t transceiver_request; +void transceiver_usb_setup_complete(usb_endpoint_t* const endpoint); + usb_request_status_t usb_vendor_request_set_transceiver_mode( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); diff --git a/firmware/hackrf_usb/usb_endpoint.c b/firmware/hackrf_usb/usb_endpoint.c index a8a35f0d..81251f1e 100644 --- a/firmware/hackrf_usb/usb_endpoint.c +++ b/firmware/hackrf_usb/usb_endpoint.c @@ -28,13 +28,14 @@ #include #include "usb_device.h" +#include "usb_api_transceiver.h" usb_endpoint_t usb_endpoint_control_out = { .address = 0x00, .device = &usb_device, .in = &usb_endpoint_control_in, .out = &usb_endpoint_control_out, - .setup_complete = usb_setup_complete, + .setup_complete = transceiver_usb_setup_complete, .transfer_complete = usb_control_out_complete, }; USB_DEFINE_QUEUE(usb_endpoint_control_out, 4); From 9584416b49ecd5e3b792288d2ffd5a64f7cfc60f Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 18 Dec 2025 07:21:58 +0000 Subject: [PATCH 154/238] Add vendor request to retrieve buffer size. --- firmware/hackrf_usb/hackrf_usb.c | 1 + firmware/hackrf_usb/usb_api_transceiver.c | 22 ++++++++++++++++++++++ firmware/hackrf_usb/usb_api_transceiver.h | 3 +++ firmware/hackrf_usb/usb_descriptor.c | 2 +- 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 54431ff3..cabf0d11 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -183,6 +183,7 @@ static usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_test_rtc_osc, usb_vendor_request_write_radio_reg, usb_vendor_request_read_radio_reg, + usb_vendor_request_get_buffer_size, }; static const uint32_t vendor_request_handler_count = diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index cad75cd3..1aca654e 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -450,6 +450,28 @@ usb_request_status_t usb_vendor_request_set_rx_overrun_limit( return USB_REQUEST_STATUS_OK; } +usb_request_status_t usb_vendor_request_get_buffer_size( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage) +{ + if (stage == USB_TRANSFER_STAGE_SETUP) { + uint32_t value = USB_SAMP_BUFFER_SIZE + USB_BULK_BUFFER_SIZE; + endpoint->buffer[0] = value & 0xff; + endpoint->buffer[1] = (value & 0xff00) >> 8; + endpoint->buffer[2] = (value & 0xff0000) >> 16; + endpoint->buffer[3] = (value & 0xff000000) >> 24; + usb_transfer_schedule_block( + endpoint->in, + &endpoint->buffer, + 4, + NULL, + NULL); + usb_transfer_schedule_ack(endpoint->out); + return USB_REQUEST_STATUS_OK; + } + return USB_REQUEST_STATUS_OK; +} + void transceiver_start_dma(void* src, void* dest, size_t size) { dma_pending = size; diff --git a/firmware/hackrf_usb/usb_api_transceiver.h b/firmware/hackrf_usb/usb_api_transceiver.h index 383be18c..a29dec11 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.h +++ b/firmware/hackrf_usb/usb_api_transceiver.h @@ -77,6 +77,9 @@ usb_request_status_t usb_vendor_request_set_tx_underrun_limit( usb_request_status_t usb_vendor_request_set_rx_overrun_limit( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); +usb_request_status_t usb_vendor_request_get_buffer_size( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage); void request_transceiver_mode(transceiver_mode_t mode); void transceiver_startup(transceiver_mode_t mode); diff --git a/firmware/hackrf_usb/usb_descriptor.c b/firmware/hackrf_usb/usb_descriptor.c index 36531ebc..067317b3 100644 --- a/firmware/hackrf_usb/usb_descriptor.c +++ b/firmware/hackrf_usb/usb_descriptor.c @@ -30,7 +30,7 @@ #define USB_VENDOR_ID (0x1D50) -#define USB_API_VERSION (0x0111) +#define USB_API_VERSION (0x0112) #define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF) From 90625818adc367759a94e90a3007beecd91e64aa Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 18 Dec 2025 07:36:58 +0000 Subject: [PATCH 155/238] For API >= 1.12, get buffer size when opening device. --- host/libhackrf/src/hackrf.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 14c34ab2..da3c0f15 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -115,6 +115,7 @@ typedef enum { HACKRF_VENDOR_REQUEST_TEST_RTC_OSC = 58, HACKRF_VENDOR_REQUEST_RADIO_WRITE_REG = 59, HACKRF_VENDOR_REQUEST_RADIO_READ_REG = 60, + HACKRF_VENDOR_REQUEST_GET_BUFFER_SIZE = 61, } hackrf_vendor_request; #define USB_CONFIG_STANDARD 0x1 @@ -138,7 +139,6 @@ typedef enum { #define TRANSFER_COUNT 4 #define TRANSFER_BUFFER_SIZE 262144 -#define DEVICE_BUFFER_SIZE 32768 #define USB_MAX_SERIAL_LENGTH 32 struct hackrf_device { @@ -163,6 +163,7 @@ struct hackrf_device { hackrf_flush_cb_fn flush_callback; hackrf_tx_block_complete_cb_fn tx_completion_callback; void* flush_ctx; + uint32_t buffer_size; }; typedef struct { @@ -712,6 +713,7 @@ static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** d { int result; hackrf_device* lib_device; + uint32_t buffer_size; struct libusb_device_descriptor device_descriptor; libusb_device* dev = libusb_get_device(usb_device); result = libusb_get_device_descriptor(dev, &device_descriptor); @@ -765,6 +767,30 @@ static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** d lib_device->flush_ctx = NULL; lib_device->tx_completion_callback = NULL; + if (lib_device->usb_api_version >= 0x0112) { + // Fetch buffer size from device so we know how many bytes to flush TX with. + result = libusb_control_transfer( + lib_device->usb_device, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | + LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_GET_BUFFER_SIZE, + 0, + 0, + (unsigned char*) &buffer_size, + 4, + 0); + + if (result < 4) { + last_libusb_error = result; + return HACKRF_ERROR_LIBUSB; + } + + lib_device->buffer_size = FROM_LE32(buffer_size); + } else { + // All older firmware uses a fixed 32KB buffer size. + lib_device->buffer_size = 32768; + } + result = pthread_mutex_init(&lib_device->transfer_lock, NULL); if (result != 0) { free(lib_device); @@ -2371,8 +2397,8 @@ ADDAPI int ADDCALL hackrf_enable_tx_flush( device->flush_transfer, device->usb_device, TX_ENDPOINT_ADDRESS, - calloc(1, DEVICE_BUFFER_SIZE), - DEVICE_BUFFER_SIZE, + calloc(1, device->buffer_size), + device->buffer_size, hackrf_libusb_flush_callback, device, 0); From 5afdd6dfef9f7d83885e09750d3a46acab0e9e8a Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 18 Dec 2025 07:49:31 +0000 Subject: [PATCH 156/238] If the host knows our buffer size, don't auto-flush. --- firmware/hackrf_usb/usb_api_transceiver.c | 26 +++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 1aca654e..ca9445d1 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -52,6 +52,11 @@ #define BUF_HALF_MASK (USB_SAMP_BUFFER_SIZE >> 1) +// Unless we know the host knows our buffer size, we'll avoid leaving TX +// until we've transmitted all bytes sent by the host. This flag is cleared +// when the host requests our buffer size. +bool auto_tx_flush = true; + volatile uint32_t dma_started, dma_pending, usb_started, usb_completed; typedef struct { @@ -327,7 +332,7 @@ volatile transceiver_request_t transceiver_request = { void transceiver_usb_setup_complete(usb_endpoint_t* const endpoint) { if (transceiver_request.mode == TRANSCEIVER_MODE_TX && - endpoint->setup.request == 1) { + endpoint->setup.request == 1 && auto_tx_flush) { // This is a request to leave TX mode. Do so but NAK for now. request_transceiver_mode(endpoint->setup.value); } else { @@ -467,6 +472,11 @@ usb_request_status_t usb_vendor_request_get_buffer_size( NULL, NULL); usb_transfer_schedule_ack(endpoint->out); + + // We now know the host is aware of our buffer size, so it + // can make its own decisions about flushing the buffer. + auto_tx_flush = false; + return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_OK; @@ -628,9 +638,17 @@ void tx_mode(uint32_t seq) radio_update(&radio); } - // Host has now requested to stop TX. We won't initiate any further USB - // transfers into the bulk buffer. However, we should make sure all - // data currently in the USB bulk buffer reaches the sample buffer. + // Host has now requested to stop TX. If we're not auto-flushing, we + // should now stop TX immediately. + + if (!auto_tx_flush) { + transceiver_shutdown(); + return; + } + + // Otherwise, we should now ensure all bytes sent by the host are + // transmitted before we leave TX. First, we should make sure all data + // currently in the USB bulk buffer reaches the sample buffer. if ((usb_started - usb_completed) > 0) { // We were part way through a 16KB firmware-side transfer when From 03119000a4a8543f9f39f5727cad42ce32df6a61 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sun, 19 Oct 2025 16:41:34 +0100 Subject: [PATCH 157/238] Use DMA for transfers. --- firmware/hackrf_usb/usb_api_transceiver.c | 64 ++++++++++++++++++++--- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index ca9445d1..fe2b5405 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -25,13 +25,15 @@ #include #include -#include +#include +#include #include #include #include #include +#include #include #include #include @@ -81,7 +83,7 @@ typedef struct { set_sample_r_params_t set_sample_r_params; -void dma_isr(void); +void transceiver_dma_setup(void); usb_request_status_t usb_vendor_request_set_baseband_filter_bandwidth( usb_endpoint_t* const endpoint, @@ -371,6 +373,8 @@ void transceiver_startup(const transceiver_mode_t mode) usb_started = 0; usb_completed = 0; + transceiver_dma_setup(); + radio_switch_opmode(&radio, mode); switch (mode) { @@ -482,15 +486,63 @@ usb_request_status_t usb_vendor_request_get_buffer_size( return USB_REQUEST_STATUS_OK; } -void transceiver_start_dma(void* src, void* dest, size_t size) +/* clang-format off */ + +// Which GPDMA channel to use. +const uint32_t DMA_CHANNEL = 1; + +// GPDMA CCONFIG register setting. +const uint32_t DMA_CONFIG = + GPDMA_CCONFIG_FLOWCNTRL(0) // memory-to-memory + | GPDMA_CCONFIG_IE(0) // no error interrupt + | GPDMA_CCONFIG_ITC(1) // terminal count interrupt + | GPDMA_CCONFIG_L(0) // do not lock + | GPDMA_CCONFIG_H(0); // do not halt + +// GPDMA CCONTROL register setting (excluding TRANSFERSIZE field). +const uint32_t DMA_CONTROL = + GPDMA_CCONTROL_SBSIZE(7) // 256-transfer src bursts + | GPDMA_CCONTROL_DBSIZE(7) // 256-transfer dst bursts + | GPDMA_CCONTROL_SWIDTH(2) // 32-bit src transfers + | GPDMA_CCONTROL_DWIDTH(2) // 32-bit dst transfers + | GPDMA_CCONTROL_S(0) // AHB Master 0 + | GPDMA_CCONTROL_D(1) // AHB Master 1 + | GPDMA_CCONTROL_SI(1) // increment source + | GPDMA_CCONTROL_DI(1) // increment destination + | GPDMA_CCONTROL_PROT1(0) // user mode + | GPDMA_CCONTROL_PROT2(0) // not bufferable + | GPDMA_CCONTROL_PROT3(0) // not cacheable + | GPDMA_CCONTROL_I(1); // interrupt enabled + +/* clang-format on */ + +// Called before any sequence of DMA transfers. +void transceiver_dma_setup(void) { - dma_pending = size; - memcpy(dest, src, size); - dma_isr(); + gpdma_controller_enable(); + GPDMA_CCONFIG(DMA_CHANNEL) = DMA_CONFIG; + GPDMA_CCONTROL(DMA_CHANNEL) = DMA_CONTROL; + GPDMA_CLLI(DMA_CHANNEL) = 0; + GPDMA_INTTCCLEAR = (1 << DMA_CHANNEL); + nvic_enable_irq(NVIC_DMA_IRQ); } +// Called to start each DMA transfer. +void transceiver_start_dma(void* src, void* dest, size_t size) +{ + uint32_t num_transfers = size >> 2; + GPDMA_CCONTROL(DMA_CHANNEL) = DMA_CONTROL | num_transfers; + GPDMA_CSRCADDR(DMA_CHANNEL) = (uint32_t) src; + GPDMA_CDESTADDR(DMA_CHANNEL) = (uint32_t) dest; + dma_pending = size; + gpdma_channel_enable(DMA_CHANNEL); +} + +// Called when a DMA transfer completes. void dma_isr(void) { + gpdma_channel_disable(DMA_CHANNEL); + GPDMA_INTTCCLEAR = (1 << DMA_CHANNEL); m0_state.m4_count += dma_pending; dma_pending = 0; } From f1ece3769c30de6ef319ab640e1b0eaecd4c2208 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 30 Apr 2026 09:48:52 +0200 Subject: [PATCH 158/238] firmware: move radio_t object instance to hackrf_usb binary --- firmware/common/drivers.c | 5 ----- firmware/common/drivers.h | 2 -- firmware/common/radio.h | 8 ++++++++ firmware/hackrf_usb/hackrf_usb.c | 4 ++++ 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/firmware/common/drivers.c b/firmware/common/drivers.c index a6bd536a..a9f00509 100644 --- a/firmware/common/drivers.c +++ b/firmware/common/drivers.c @@ -26,7 +26,6 @@ #include #include -#include "clock_gen.h" #include "i2c_lpc.h" #include "max283x.h" #include "max5864_target.h" @@ -146,10 +145,6 @@ fpga_driver_t fpga = { }; #endif -radio_t radio = { - .sample_rate_cb = sample_rate_set, -}; - rf_path_t rf_path = { .switchctrl = 0, }; diff --git a/firmware/common/drivers.h b/firmware/common/drivers.h index 6aa45f87..b5fea0a5 100644 --- a/firmware/common/drivers.h +++ b/firmware/common/drivers.h @@ -32,7 +32,6 @@ extern "C" { #include "max5864.h" #include "mixer.h" #include "platform_detect.h" // IWYU pragma: keep -#include "radio.h" #include "rf_path.h" #include "sgpio.h" #include "si5351c.h" @@ -60,7 +59,6 @@ extern max5864_driver_t max5864; extern mixer_driver_t mixer; extern w25q80bv_driver_t spi_flash; extern sgpio_config_t sgpio_config; -extern radio_t radio; extern rf_path_t rf_path; extern jtag_gpio_t jtag_gpio_cpld; extern jtag_t jtag_cpld; diff --git a/firmware/common/radio.h b/firmware/common/radio.h index 7ab46c80..b785c281 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -260,3 +260,11 @@ bool radio_update(radio_t* const radio); * the request bank for the new mode. */ void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode); + +/** + * Driver instance. + * + * This needs to be configured and provided by the application + * binary. e.g. firmware/hackrf_usb/hackrf_usb.c + */ +extern radio_t radio; diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 54431ff3..d02ea279 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -98,6 +98,10 @@ extern uint32_t __m0_end__; extern uint32_t __ram_m0_start__; extern uint32_t _etext_ram, _text_ram, _etext_rom; +radio_t radio = { + .sample_rate_cb = sample_rate_set, +}; + static usb_request_handler_fn vendor_request_handler[] = { NULL, usb_vendor_request_set_transceiver_mode, From 1af5055720d454518b44ab262cb51526a69e5d27 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 30 Apr 2026 14:35:46 +0200 Subject: [PATCH 159/238] firmware: move spi_bus_ssp0, spi_bus_ssp1 driver instances to spi_bus.x --- firmware/common/drivers.c | 18 ------------------ firmware/common/spi_bus.c | 22 ++++++++++++++++++++++ firmware/common/spi_bus.h | 4 ++++ 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/firmware/common/drivers.c b/firmware/common/drivers.c index a9f00509..a5b568af 100644 --- a/firmware/common/drivers.c +++ b/firmware/common/drivers.c @@ -90,15 +90,6 @@ ssp_config_t ssp_config_max5864 = { .clock_prescale_rate = 2, }; -spi_bus_t spi_bus_ssp1 = { - .obj = (void*) SSP1_BASE, - .config = &ssp_config_max5864, - .start = spi_ssp_start, - .stop = spi_ssp_stop, - .transfer = spi_ssp_transfer, - .transfer_gather = spi_ssp_transfer_gather, -}; - max5864_driver_t max5864 = { .bus = &spi_bus_ssp1, .target_init = max5864_target_init, @@ -110,15 +101,6 @@ ssp_config_t ssp_config_w25q80bv = { .clock_prescale_rate = 2, }; -spi_bus_t spi_bus_ssp0 = { - .obj = (void*) SSP0_BASE, - .config = &ssp_config_w25q80bv, - .start = spi_ssp_start, - .stop = spi_ssp_stop, - .transfer = spi_ssp_transfer, - .transfer_gather = spi_ssp_transfer_gather, -}; - w25q80bv_driver_t spi_flash = { .bus = &spi_bus_ssp0, .target_init = w25q80bv_target_init, diff --git a/firmware/common/spi_bus.c b/firmware/common/spi_bus.c index a26b4bab..a5332699 100644 --- a/firmware/common/spi_bus.c +++ b/firmware/common/spi_bus.c @@ -22,8 +22,30 @@ #include "spi_bus.h" +#include + +#include "spi_ssp.h" + +/* Driver instances. */ +spi_bus_t spi_bus_ssp0 = { + .obj = (void*) SSP0_BASE, + .start = spi_ssp_start, + .stop = spi_ssp_stop, + .transfer = spi_ssp_transfer, + .transfer_gather = spi_ssp_transfer_gather, +}; + +spi_bus_t spi_bus_ssp1 = { + .obj = (void*) SSP1_BASE, + .start = spi_ssp_start, + .stop = spi_ssp_stop, + .transfer = spi_ssp_transfer, + .transfer_gather = spi_ssp_transfer_gather, +}; + void spi_bus_start(spi_bus_t* const bus, const void* const config) { + bus->config = config; bus->start(bus, config); } diff --git a/firmware/common/spi_bus.h b/firmware/common/spi_bus.h index 07d5787d..23b3107b 100644 --- a/firmware/common/spi_bus.h +++ b/firmware/common/spi_bus.h @@ -51,3 +51,7 @@ void spi_bus_transfer_gather( spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count); + +/* Driver instances. */ +extern spi_bus_t spi_bus_ssp0; +extern spi_bus_t spi_bus_ssp1; From 858ffd268a4cf3a6c4941fdacb6a252599adbd5e Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 30 Apr 2026 14:40:37 +0200 Subject: [PATCH 160/238] firmware: move i2c_bus0, i2c_bus1 driver instances to i2c_bus.x --- firmware/common/da7219.c | 1 - firmware/common/drivers.c | 16 +--------------- firmware/common/drivers.h | 2 -- firmware/common/i2c_bus.c | 19 +++++++++++++++++++ firmware/common/i2c_bus.h | 4 ++++ firmware/common/operacake.c | 1 - 6 files changed, 24 insertions(+), 19 deletions(-) diff --git a/firmware/common/da7219.c b/firmware/common/da7219.c index 5af022d2..7ae916cb 100644 --- a/firmware/common/da7219.c +++ b/firmware/common/da7219.c @@ -22,7 +22,6 @@ #include #include "da7219.h" -#include "drivers.h" #include "i2c_bus.h" #define DA7219_REG_CHIP_ID1 0x81 diff --git a/firmware/common/drivers.c b/firmware/common/drivers.c index a5b568af..9d42000b 100644 --- a/firmware/common/drivers.c +++ b/firmware/common/drivers.c @@ -23,9 +23,9 @@ #include -#include #include +#include "i2c_bus.h" #include "i2c_lpc.h" #include "max283x.h" #include "max5864_target.h" @@ -36,20 +36,6 @@ #include "ice40_spi.h" #endif -i2c_bus_t i2c0 = { - .obj = (void*) I2C0_BASE, - .start = i2c_lpc_start, - .stop = i2c_lpc_stop, - .transfer = i2c_lpc_transfer, -}; - -i2c_bus_t i2c1 = { - .obj = (void*) I2C1_BASE, - .start = i2c_lpc_start, - .stop = i2c_lpc_stop, - .transfer = i2c_lpc_transfer, -}; - // const i2c_lpc_config_t i2c_config_si5351c_slow_clock = { // .duty_cycle_count = 15, // }; diff --git a/firmware/common/drivers.h b/firmware/common/drivers.h index b5fea0a5..111c7103 100644 --- a/firmware/common/drivers.h +++ b/firmware/common/drivers.h @@ -26,7 +26,6 @@ extern "C" { #endif #include "cpld_jtag.h" -#include "i2c_bus.h" #include "i2c_lpc.h" #include "max283x.h" #include "max5864.h" @@ -62,7 +61,6 @@ extern sgpio_config_t sgpio_config; extern rf_path_t rf_path; extern jtag_gpio_t jtag_gpio_cpld; extern jtag_t jtag_cpld; -extern i2c_bus_t i2c0; void ssp1_set_mode_max283x(void); void ssp1_set_mode_max5864(void); diff --git a/firmware/common/i2c_bus.c b/firmware/common/i2c_bus.c index 6d8dcd25..c0d5b79d 100644 --- a/firmware/common/i2c_bus.c +++ b/firmware/common/i2c_bus.c @@ -22,6 +22,25 @@ #include "i2c_bus.h" +#include + +#include "i2c_lpc.h" + +/* Driver instances. */ +i2c_bus_t i2c0 = { + .obj = (void*) I2C0_BASE, + .start = i2c_lpc_start, + .stop = i2c_lpc_stop, + .transfer = i2c_lpc_transfer, +}; + +i2c_bus_t i2c1 = { + .obj = (void*) I2C1_BASE, + .start = i2c_lpc_start, + .stop = i2c_lpc_stop, + .transfer = i2c_lpc_transfer, +}; + void i2c_bus_start(i2c_bus_t* const bus, const void* const config) { bus->start(bus, config); diff --git a/firmware/common/i2c_bus.h b/firmware/common/i2c_bus.h index 7519ba14..fa1211c1 100644 --- a/firmware/common/i2c_bus.h +++ b/firmware/common/i2c_bus.h @@ -47,3 +47,7 @@ void i2c_bus_transfer( const size_t tx_count, uint8_t* const rx, const size_t rx_count); + +/* Driver instances. */ +extern i2c_bus_t i2c0; +extern i2c_bus_t i2c1; diff --git a/firmware/common/operacake.c b/firmware/common/operacake.c index 24ca6541..f50c4f7e 100644 --- a/firmware/common/operacake.c +++ b/firmware/common/operacake.c @@ -26,7 +26,6 @@ #include -#include "drivers.h" #include "gpio.h" #include "gpio_lpc.h" #include "i2c_bus.h" From 4f44917f685337cdccbe5fd6b930883c2ac503c2 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 30 Apr 2026 14:48:24 +0200 Subject: [PATCH 161/238] firmware: move w25q80vc driver instance to w25q80bv.x --- firmware/common/drivers.c | 12 ------------ firmware/common/drivers.h | 3 --- firmware/common/pins.c | 1 + firmware/common/rom_iap.c | 1 - firmware/common/w25q80bv.c | 18 +++++++++++++++++- firmware/common/w25q80bv.h | 5 +++++ firmware/hackrf_usb/usb_api_spiflash.c | 1 - 7 files changed, 23 insertions(+), 18 deletions(-) diff --git a/firmware/common/drivers.c b/firmware/common/drivers.c index 9d42000b..b83a1a80 100644 --- a/firmware/common/drivers.c +++ b/firmware/common/drivers.c @@ -30,7 +30,6 @@ #include "max283x.h" #include "max5864_target.h" #include "spi_bus.h" -#include "w25q80bv_target.h" #if defined(IS_PRALINE) #include "fpga.h" #include "ice40_spi.h" @@ -81,17 +80,6 @@ max5864_driver_t max5864 = { .target_init = max5864_target_init, }; -ssp_config_t ssp_config_w25q80bv = { - .data_bits = SSP_DATA_8BITS, - .serial_clock_rate = 2, - .clock_prescale_rate = 2, -}; - -w25q80bv_driver_t spi_flash = { - .bus = &spi_bus_ssp0, - .target_init = w25q80bv_target_init, -}; - sgpio_config_t sgpio_config = { .slice_mode_multislice = true, }; diff --git a/firmware/common/drivers.h b/firmware/common/drivers.h index 111c7103..5d903e5b 100644 --- a/firmware/common/drivers.h +++ b/firmware/common/drivers.h @@ -35,7 +35,6 @@ extern "C" { #include "sgpio.h" #include "si5351c.h" #include "spi_ssp.h" -#include "w25q80bv.h" #if defined(IS_PRALINE) #include "fpga.h" #include "ice40_spi.h" @@ -46,7 +45,6 @@ extern const i2c_lpc_config_t i2c_config_si5351c_fast_clock; extern si5351c_driver_t clock_gen; extern ssp_config_t ssp_config_max283x; extern ssp_config_t ssp_config_max5864; -extern ssp_config_t ssp_config_w25q80bv; #if defined(IS_PRALINE) extern ssp_config_t ssp_config_ice40_fpga; @@ -56,7 +54,6 @@ extern fpga_driver_t fpga; extern max283x_driver_t max283x; extern max5864_driver_t max5864; extern mixer_driver_t mixer; -extern w25q80bv_driver_t spi_flash; extern sgpio_config_t sgpio_config; extern rf_path_t rf_path; extern jtag_gpio_t jtag_gpio_cpld; diff --git a/firmware/common/pins.c b/firmware/common/pins.c index 6f8123cb..425d6d74 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -36,6 +36,7 @@ #include "power.h" #include "rf_path.h" #include "sgpio.h" +#include "w25q80bv.h" #if defined(IS_PRALINE) #include "clock_io.h" #endif diff --git a/firmware/common/rom_iap.c b/firmware/common/rom_iap.c index 09da0b7c..25dfa269 100644 --- a/firmware/common/rom_iap.c +++ b/firmware/common/rom_iap.c @@ -22,7 +22,6 @@ #include -#include "drivers.h" #include "rom_iap.h" #include "spi_bus.h" #include "w25q80bv.h" diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index f569bedf..11c6d5c0 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -27,11 +27,15 @@ * programming the flash. */ +#include "w25q80bv.h" + #include #include +#include + #include "platform_detect.h" -#include "w25q80bv.h" +#include "w25q80bv_target.h" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) @@ -51,6 +55,18 @@ #define W25Q80BV_DEVICE_ID_RES 0x13 /* Expected device_id for W25Q80BV */ +/* Driver instance. */ +ssp_config_t ssp_config_w25q80bv = { + .data_bits = SSP_DATA_8BITS, + .serial_clock_rate = 2, + .clock_prescale_rate = 2, +}; + +w25q80bv_driver_t spi_flash = { + .bus = &spi_bus_ssp0, + .target_init = w25q80bv_target_init, +}; + /* * Set up pins for GPIO and SPI control, configure SSP0 peripheral for SPI. * SSP0_CS is controlled by GPIO in order to handle various transfer lengths. diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index a43d6445..21d0814b 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -28,6 +28,7 @@ #include "gpio.h" #include "spi_bus.h" +#include "spi_ssp.h" #define W25Q80BV_DEVICE_ID_RES 0x13 /* Expected device_id for W25Q80BV */ #define W25Q16DV_DEVICE_ID_RES 0x14 /* Expected device_id for W25Q16DV */ @@ -65,3 +66,7 @@ void w25q80bv_read( uint32_t len, uint8_t* const data); void w25q80bv_clear_status(w25q80bv_driver_t* const drv); + +/* Driver instance. */ +extern ssp_config_t ssp_config_w25q80bv; +extern w25q80bv_driver_t spi_flash; diff --git a/firmware/hackrf_usb/usb_api_spiflash.c b/firmware/hackrf_usb/usb_api_spiflash.c index 2c944a10..d490eb0e 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.c +++ b/firmware/hackrf_usb/usb_api_spiflash.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include From e5c8dc235012cc44ee4e6eab813a267b43680c02 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 30 Apr 2026 14:54:22 +0200 Subject: [PATCH 162/238] firmware: move max283x driver instance to max283x.x --- firmware/common/drivers.c | 20 -------------------- firmware/common/drivers.h | 4 ---- firmware/common/fpga.c | 1 + firmware/common/fpga_image.c | 1 + firmware/common/max283x.c | 20 +++++++++++++++++++- firmware/common/max283x.h | 6 ++++++ firmware/common/pins.c | 1 + firmware/common/ui_rad1o.c | 2 +- 8 files changed, 29 insertions(+), 26 deletions(-) diff --git a/firmware/common/drivers.c b/firmware/common/drivers.c index b83a1a80..38f41a9d 100644 --- a/firmware/common/drivers.c +++ b/firmware/common/drivers.c @@ -27,7 +27,6 @@ #include "i2c_bus.h" #include "i2c_lpc.h" -#include "max283x.h" #include "max5864_target.h" #include "spi_bus.h" #if defined(IS_PRALINE) @@ -48,20 +47,6 @@ si5351c_driver_t clock_gen = { .i2c_address = 0x60, }; -ssp_config_t ssp_config_max283x = { - /* FIXME speed up once everything is working reliably */ - /* - // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - const uint8_t serial_clock_rate = 32; - const uint8_t clock_prescale_rate = 128; - */ - // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - .serial_clock_rate = 21, - .clock_prescale_rate = 2, -}; - -max283x_driver_t max283x = {}; - ssp_config_t ssp_config_max5864 = { /* FIXME speed up once everything is working reliably */ /* @@ -111,11 +96,6 @@ jtag_t jtag_cpld = { .gpio = &jtag_gpio_cpld, }; -void ssp1_set_mode_max283x(void) -{ - spi_bus_start(&spi_bus_ssp1, &ssp_config_max283x); -} - void ssp1_set_mode_max5864(void) { spi_bus_start(max5864.bus, &ssp_config_max5864); diff --git a/firmware/common/drivers.h b/firmware/common/drivers.h index 5d903e5b..d4792d75 100644 --- a/firmware/common/drivers.h +++ b/firmware/common/drivers.h @@ -27,7 +27,6 @@ extern "C" { #include "cpld_jtag.h" #include "i2c_lpc.h" -#include "max283x.h" #include "max5864.h" #include "mixer.h" #include "platform_detect.h" // IWYU pragma: keep @@ -43,7 +42,6 @@ extern "C" { /* TODO: Hide these configurations */ extern const i2c_lpc_config_t i2c_config_si5351c_fast_clock; extern si5351c_driver_t clock_gen; -extern ssp_config_t ssp_config_max283x; extern ssp_config_t ssp_config_max5864; #if defined(IS_PRALINE) @@ -51,7 +49,6 @@ extern ssp_config_t ssp_config_ice40_fpga; extern ice40_spi_driver_t ice40; extern fpga_driver_t fpga; #endif -extern max283x_driver_t max283x; extern max5864_driver_t max5864; extern mixer_driver_t mixer; extern sgpio_config_t sgpio_config; @@ -59,7 +56,6 @@ extern rf_path_t rf_path; extern jtag_gpio_t jtag_gpio_cpld; extern jtag_t jtag_cpld; -void ssp1_set_mode_max283x(void); void ssp1_set_mode_max5864(void); #if defined(IS_PRALINE) void ssp1_set_mode_ice40(void); diff --git a/firmware/common/fpga.c b/firmware/common/fpga.c index 172810a8..3bdd636e 100644 --- a/firmware/common/fpga.c +++ b/firmware/common/fpga.c @@ -26,6 +26,7 @@ #include "drivers.h" #include "ice40_spi.h" +#include "max283x.h" /* Set up all registers according to the loaded bitstream's defaults. */ void fpga_init(fpga_driver_t* const drv) diff --git a/firmware/common/fpga_image.c b/firmware/common/fpga_image.c index 989d16b2..a9f46aee 100644 --- a/firmware/common/fpga_image.c +++ b/firmware/common/fpga_image.c @@ -27,6 +27,7 @@ #include "fpga.h" #include "ice40_spi.h" #include "lz4_blk.h" +#include "max283x.h" #include "selftest.h" struct fpga_image_read_ctx { diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index 3b49ab6e..e7221bb0 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -41,7 +41,25 @@ #include "max2839_target.h" #endif -extern spi_bus_t spi_bus_ssp1; +/* Driver instance. */ +ssp_config_t ssp_config_max283x = { + /* FIXME speed up once everything is working reliably */ + /* + // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + const uint8_t serial_clock_rate = 32; + const uint8_t clock_prescale_rate = 128; + */ + // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + .serial_clock_rate = 21, + .clock_prescale_rate = 2, +}; + +max283x_driver_t max283x = {}; + +void ssp1_set_mode_max283x(void) +{ + spi_bus_start(&spi_bus_ssp1, &ssp_config_max283x); +} #ifdef IS_PRALINE max2831_driver_t max2831 = { diff --git a/firmware/common/max283x.h b/firmware/common/max283x.h index 01bb40b0..b4e44620 100644 --- a/firmware/common/max283x.h +++ b/firmware/common/max283x.h @@ -28,6 +28,7 @@ #include "fixed_point.h" #include "platform_detect.h" +#include "spi_ssp.h" #ifdef IS_PRALINE #include "max2831.h" @@ -139,3 +140,8 @@ void max283x_set_rx_hpf_frequency( /* Perform MAX2831 TX and RX calibration. */ void max283x_tx_calibration(max283x_driver_t* const drv); void max283x_rx_calibration(max283x_driver_t* const drv); + +/* Driver instance. */ +extern ssp_config_t ssp_config_max283x; +extern max283x_driver_t max283x; +void ssp1_set_mode_max283x(void); diff --git a/firmware/common/pins.c b/firmware/common/pins.c index 425d6d74..bced06d4 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -29,6 +29,7 @@ #include "drivers.h" #include "gpio.h" #include "leds.h" +#include "max283x.h" #include "mixer.h" #include "platform_detect.h" #include "platform_gpio.h" diff --git a/firmware/common/ui_rad1o.c b/firmware/common/ui_rad1o.c index 757e11f1..378798b0 100644 --- a/firmware/common/ui_rad1o.c +++ b/firmware/common/ui_rad1o.c @@ -27,7 +27,7 @@ #include #include "clock_gen.h" -#include "drivers.h" +#include "max283x.h" #include "rf_path.h" #include "transceiver_mode.h" #ifdef IS_NOT_RAD1O From ac93a68a028d7921aa6e37626f1b8d18be23ac80 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 30 Apr 2026 12:45:15 +0100 Subject: [PATCH 163/238] ui_rad1o: remove unnecessary include. --- firmware/common/ui_rad1o.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/firmware/common/ui_rad1o.c b/firmware/common/ui_rad1o.c index 757e11f1..4f0a3636 100644 --- a/firmware/common/ui_rad1o.c +++ b/firmware/common/ui_rad1o.c @@ -30,9 +30,6 @@ #include "drivers.h" #include "rf_path.h" #include "transceiver_mode.h" -#ifdef IS_NOT_RAD1O - #include "radio.h" -#endif #include "rad1o/display.h" #include "rad1o/draw.h" From f655bec11f3dad1ebf659bf2cd2e798fbf1f5202 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 30 Apr 2026 14:01:36 +0100 Subject: [PATCH 164/238] ui_rad1o: use a helper function for printing frequencies. --- firmware/common/ui_rad1o.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/firmware/common/ui_rad1o.c b/firmware/common/ui_rad1o.c index 4f0a3636..c1041fad 100644 --- a/firmware/common/ui_rad1o.c +++ b/firmware/common/ui_rad1o.c @@ -58,20 +58,21 @@ static bool enabled = false; #define WHITE 0b11111111 #define GREY 0b01001101 +static void print_hz(char* tmp, char* fmt, uint64_t hz) +{ + uint32_t mhz, khz; + mhz = hz / 1000000; + khz = (hz - mhz * 1000000) / 1000; + sprintf(tmp, fmt, (unsigned int) mhz, (unsigned int) khz); + rad1o_lcdPrint(tmp); +} + static void draw_frequency(void) { char tmp[100]; - uint32_t mhz; - uint32_t khz; - - mhz = freq / 1000000; - khz = (freq - mhz * 1000000) / 1000; - rad1o_setTextColor(BLACK, GREEN); rad1o_setIntFont(&Font_Ubuntu18pt); - sprintf(tmp, "%4u.%03u", (unsigned int) mhz, (unsigned int) khz); - rad1o_lcdPrint(tmp); - + print_hz(tmp, "%4u.%03u", freq); rad1o_setIntFont(&Font_7x8); rad1o_lcdMoveCrsr(1, 18 - 7); rad1o_lcdPrint("MHz"); @@ -112,8 +113,6 @@ static void draw_tx_rx(void) static void ui_update(void) { char tmp[100]; - uint32_t mhz; - uint32_t khz; if (!enabled) { return; @@ -154,18 +153,12 @@ static void ui_update(void) rad1o_setTextColor(BLACK, WHITE); rad1o_lcdSetCrsr(2, 71); rad1o_lcdPrint("Rate: "); - mhz = sample_rate / 1000000; - khz = (sample_rate - mhz * 1000000) / 1000; - sprintf(tmp, "%2u.%03u MHz", (unsigned int) mhz, (unsigned int) khz); - rad1o_lcdPrint(tmp); + print_hz(tmp, "%2u.%03u MHz", sample_rate); rad1o_lcdNl(); rad1o_lcdMoveCrsr(2, 0); rad1o_lcdPrint("Filter: "); - mhz = filter_bw / 1000000; - khz = (filter_bw - mhz * 1000000) / 1000; - sprintf(tmp, "%2u.%03u MHz", (unsigned int) mhz, (unsigned int) khz); - rad1o_lcdPrint(tmp); + print_hz(tmp, "%2u.%03u MHz", filter_bw); rad1o_lcdNl(); rad1o_drawHLine(88, 0, RESX - 1, WHITE); From 5d7b6c33cf199dc57a138b44e490b3caf2e5cc88 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 30 Apr 2026 14:02:33 +0100 Subject: [PATCH 165/238] ui_rad1o: Round displayed frequencies to nearest kHz. --- firmware/common/ui_rad1o.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/firmware/common/ui_rad1o.c b/firmware/common/ui_rad1o.c index c1041fad..8df630bd 100644 --- a/firmware/common/ui_rad1o.c +++ b/firmware/common/ui_rad1o.c @@ -58,11 +58,14 @@ static bool enabled = false; #define WHITE 0b11111111 #define GREY 0b01001101 +#define DIV_ROUND_CLOSEST(n, d) ((n + (d / 2)) / d) + static void print_hz(char* tmp, char* fmt, uint64_t hz) { uint32_t mhz, khz; - mhz = hz / 1000000; - khz = (hz - mhz * 1000000) / 1000; + mhz = DIV_ROUND_CLOSEST(hz, 1000000); + hz -= mhz * 1000000; + khz = DIV_ROUND_CLOSEST(hz, 1000); sprintf(tmp, fmt, (unsigned int) mhz, (unsigned int) khz); rad1o_lcdPrint(tmp); } From 01a3b345422c2102721c2c8e3e9a42beb55a92d9 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 30 Apr 2026 15:07:58 +0200 Subject: [PATCH 166/238] firmware: move si5351c driver instance 'clock_gen' to si5351c.x --- firmware/common/cpu_clock.c | 2 +- firmware/common/drivers.c | 11 ----------- firmware/common/drivers.h | 4 ---- firmware/common/si5351c.c | 13 +++++++++++++ firmware/common/si5351c.h | 5 +++++ 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/firmware/common/cpu_clock.c b/firmware/common/cpu_clock.c index b69f0773..5a4ab4f6 100644 --- a/firmware/common/cpu_clock.c +++ b/firmware/common/cpu_clock.c @@ -29,8 +29,8 @@ #endif #include "delay.h" -#include "drivers.h" #include "i2c_bus.h" +#include "si5351c.h" #ifdef IS_NOT_RAD1O #include "platform_detect.h" #endif diff --git a/firmware/common/drivers.c b/firmware/common/drivers.c index 38f41a9d..bd601a1c 100644 --- a/firmware/common/drivers.c +++ b/firmware/common/drivers.c @@ -25,8 +25,6 @@ #include -#include "i2c_bus.h" -#include "i2c_lpc.h" #include "max5864_target.h" #include "spi_bus.h" #if defined(IS_PRALINE) @@ -38,15 +36,6 @@ // .duty_cycle_count = 15, // }; -const i2c_lpc_config_t i2c_config_si5351c_fast_clock = { - .duty_cycle_count = 255, -}; - -si5351c_driver_t clock_gen = { - .bus = &i2c0, - .i2c_address = 0x60, -}; - ssp_config_t ssp_config_max5864 = { /* FIXME speed up once everything is working reliably */ /* diff --git a/firmware/common/drivers.h b/firmware/common/drivers.h index d4792d75..2bb8db8e 100644 --- a/firmware/common/drivers.h +++ b/firmware/common/drivers.h @@ -26,13 +26,11 @@ extern "C" { #endif #include "cpld_jtag.h" -#include "i2c_lpc.h" #include "max5864.h" #include "mixer.h" #include "platform_detect.h" // IWYU pragma: keep #include "rf_path.h" #include "sgpio.h" -#include "si5351c.h" #include "spi_ssp.h" #if defined(IS_PRALINE) #include "fpga.h" @@ -40,8 +38,6 @@ extern "C" { #endif /* TODO: Hide these configurations */ -extern const i2c_lpc_config_t i2c_config_si5351c_fast_clock; -extern si5351c_driver_t clock_gen; extern ssp_config_t ssp_config_max5864; #if defined(IS_PRALINE) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index c9767405..53b025d8 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -25,6 +25,7 @@ #include "clock_io.h" #include "delay.h" +#include "i2c_lpc.h" #include "platform_detect.h" #include "selftest.h" #include "si5351c.h" @@ -35,6 +36,18 @@ #include "platform_scu.h" #endif +/* Driver instance. */ +// const i2c_lpc_config_t i2c_config_si5351c_slow_clock = { +// .duty_cycle_count = 15, +// }; +const i2c_lpc_config_t i2c_config_si5351c_fast_clock = { + .duty_cycle_count = 255, +}; +si5351c_driver_t clock_gen = { + .bus = &i2c0, + .i2c_address = 0x60, +}; + static enum pll_sources active_clock_source = PLL_SOURCE_UNINITIALIZED; /* External clock output default is deactivated as it creates noise */ static bool clkout_enabled = false; diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index 9e6b9ab8..f7a7da90 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -31,6 +31,7 @@ extern "C" { #include #include "i2c_bus.h" +#include "i2c_lpc.h" #define SI_INTDIV(x) (x * 128 - 512) @@ -115,6 +116,10 @@ void si5351c_set_phase( const uint8_t ms_number, const uint8_t offset); +/* Driver Instance. */ +extern const i2c_lpc_config_t i2c_config_si5351c_fast_clock; +extern si5351c_driver_t clock_gen; + #ifdef __cplusplus } #endif From 76252016b6a813b7c4ad661d6a8820521965a4d8 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 30 Apr 2026 15:19:15 +0200 Subject: [PATCH 167/238] firmware: rename si5351c driver instance 'clock_gen' to 'si5351c' --- firmware/common/clock_gen.c | 66 +++++++++++++------------- firmware/common/cpu_clock.c | 2 +- firmware/common/si5351c.c | 2 +- firmware/common/si5351c.h | 2 +- firmware/hackrf_usb/usb_api_register.c | 10 ++-- 5 files changed, 41 insertions(+), 41 deletions(-) diff --git a/firmware/common/clock_gen.c b/firmware/common/clock_gen.c index b62308ce..642fc61b 100644 --- a/firmware/common/clock_gen.c +++ b/firmware/common/clock_gen.c @@ -36,14 +36,14 @@ void clock_gen_init(void) { - i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_fast_clock); + i2c_bus_start(si5351c.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); - si5351c_set_crystal_configuration(&clock_gen); - si5351c_enable_xo_and_ms_fanout(&clock_gen); + si5351c_init(&si5351c); + si5351c_disable_all_outputs(&si5351c); + si5351c_disable_oeb_pin_control(&si5351c); + si5351c_power_down_all_clocks(&si5351c); + si5351c_set_crystal_configuration(&si5351c); + si5351c_enable_xo_and_ms_fanout(&si5351c); /* * Clocks on HackRF One r9: @@ -76,7 +76,7 @@ void clock_gen_init(void) if (IS_H1_R9) { /* MS0/CLK0 is the reference for both RFFC5071 and MAX2839. */ si5351c_configure_multisynth( - &clock_gen, + &si5351c, 0, 20 * 128 - 512, 0, @@ -88,7 +88,7 @@ void clock_gen_init(void) if (IS_NOT_H1_R9) { /* MS4/CLK4 is the source for the RFFC5071 mixer (MAX2837 on rad1o). */ si5351c_configure_multisynth( - &clock_gen, + &si5351c, 4, 20 * 128 - 512, 0, @@ -96,7 +96,7 @@ void clock_gen_init(void) 0); /* 800/20 = 40MHz */ /* MS5/CLK5 is the source for the MAX2837 clock input (MAX2871 on rad1o). */ si5351c_configure_multisynth( - &clock_gen, + &si5351c, 5, 20 * 128 - 512, 0, @@ -111,19 +111,19 @@ void clock_gen_init(void) /* Set to 10 MHz, the common rate between Jawbreaker and HackRF One. */ sample_rate_set(SR_FP_MHZ(10), true); - si5351c_configure_clock_control(&clock_gen); - si5351c_set_clock_source(&clock_gen, PLL_SOURCE_XTAL); + si5351c_configure_clock_control(&si5351c); + si5351c_set_clock_source(&si5351c, PLL_SOURCE_XTAL); // soft reset - si5351c_reset_pll(&clock_gen, SI5351C_PLL_BOTH); - si5351c_enable_clock_outputs(&clock_gen); + si5351c_reset_pll(&si5351c, SI5351C_PLL_BOTH); + si5351c_enable_clock_outputs(&si5351c); } void clock_gen_shutdown(void) { - i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_fast_clock); - si5351c_disable_all_outputs(&clock_gen); - si5351c_disable_oeb_pin_control(&clock_gen); - si5351c_power_down_all_clocks(&clock_gen); + i2c_bus_start(si5351c.bus, &i2c_config_si5351c_fast_clock); + si5351c_disable_all_outputs(&si5351c); + si5351c_disable_oeb_pin_control(&si5351c); + si5351c_power_down_all_clocks(&si5351c); } clock_source_t activate_best_clock_source(void) @@ -140,7 +140,7 @@ clock_source_t activate_best_clock_source(void) clock_source_t source = CLOCK_SOURCE_HACKRF; /* Check for external clock input. */ - if (si5351c_clkin_signal_valid(&clock_gen)) { + if (si5351c_clkin_signal_valid(&si5351c)) { source = CLOCK_SOURCE_EXTERNAL; } else { #ifdef IS_EXPANSION_COMPATIBLE @@ -149,7 +149,7 @@ clock_source_t activate_best_clock_source(void) if (portapack_reference_oscillator && portapack()) { portapack_reference_oscillator(true); delay(510000); /* loop iterations @ 204MHz for >10ms for oscillator to enable. */ - if (si5351c_clkin_signal_valid(&clock_gen)) { + if (si5351c_clkin_signal_valid(&si5351c)) { source = CLOCK_SOURCE_PORTAPACK; } else { portapack_reference_oscillator(false); @@ -161,7 +161,7 @@ clock_source_t activate_best_clock_source(void) } si5351c_set_clock_source( - &clock_gen, + &si5351c, (source == CLOCK_SOURCE_HACKRF) ? PLL_SOURCE_XTAL : PLL_SOURCE_CLKIN); hackrf_ui()->set_clock_source(source); @@ -342,9 +342,9 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) if (IS_NOT_PRALINE) { /* Integer mode can be enabled if p1 is even and p2 is zero. */ if (p1 & 0x1 || p2) { - si5351c_set_int_mode(&clock_gen, 0, 0); + si5351c_set_int_mode(&si5351c, 0, 0); } else { - si5351c_set_int_mode(&clock_gen, 0, 1); + si5351c_set_int_mode(&si5351c, 0, 1); } #ifdef IS_H1_R9 @@ -353,7 +353,7 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) * On HackRF One r9 all sample clocks are externally derived * from MS1/CLK1 operating at twice the sample rate. */ - si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 0); + si5351c_configure_multisynth(&si5351c, 1, p1, p2, p3, 0); } #endif #ifdef IS_NOT_H1_R9 @@ -363,11 +363,11 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) * different sample clocks, all derived from multisynth 0. */ /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ - si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); + si5351c_configure_multisynth(&si5351c, 0, p1, p2, p3, 1); /* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ si5351c_configure_multisynth( - &clock_gen, + &si5351c, 1, 0, 0, @@ -376,7 +376,7 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) /* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */ si5351c_configure_multisynth( - &clock_gen, + &si5351c, 2, 0, 0, @@ -389,17 +389,17 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) #ifdef IS_PRALINE if (IS_PRALINE) { /* MS0/CLK0 is the source for the MAX5864 (AFE_CLK). */ - si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); + si5351c_configure_multisynth(&si5351c, 0, p1, p2, p3, 1); /* MS1/CLK1 is the source for the FPGA (FPGA_CLK and SCT_CLK). */ - si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 1); + si5351c_configure_multisynth(&si5351c, 1, p1, p2, p3, 1); /* Delay FPGA_CLK relative to AFE_CLK. */ uint8_t phase_offset = 0; if (p1 < 2100) { phase_offset = (p1 >> 4) - 6; } - si5351c_set_phase(&clock_gen, 1, phase_offset); + si5351c_set_phase(&si5351c, 1, phase_offset); if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { /* @@ -407,12 +407,12 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) * CLK1. We configure both so that behavior is consistent with * newer boards that use CLK1 for both FPGA_CLK and SCT_CLK. */ - si5351c_configure_multisynth(&clock_gen, 2, p1, p2, p3, 1); - si5351c_set_phase(&clock_gen, 2, phase_offset); + si5351c_configure_multisynth(&si5351c, 2, p1, p2, p3, 1); + si5351c_set_phase(&si5351c, 2, phase_offset); } /* Reset PLL to synchronize output clock phase. */ - si5351c_reset_pll(&clock_gen, SI5351C_PLL_A); + si5351c_reset_pll(&si5351c, SI5351C_PLL_A); } #endif diff --git a/firmware/common/cpu_clock.c b/firmware/common/cpu_clock.c index 5a4ab4f6..aa4ac910 100644 --- a/firmware/common/cpu_clock.c +++ b/firmware/common/cpu_clock.c @@ -116,7 +116,7 @@ void cpu_clock_init(void) //FIXME disable I2C /* Kick I2C0 down to 400kHz when we switch over to APB1 clock = 204MHz */ - i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_fast_clock); + i2c_bus_start(si5351c.bus, &i2c_config_si5351c_fast_clock); /* * 12MHz clock is entering LPC XTAL1/OSC input now. diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 53b025d8..a7b605f5 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -43,7 +43,7 @@ const i2c_lpc_config_t i2c_config_si5351c_fast_clock = { .duty_cycle_count = 255, }; -si5351c_driver_t clock_gen = { +si5351c_driver_t si5351c = { .bus = &i2c0, .i2c_address = 0x60, }; diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index f7a7da90..b38eac90 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -118,7 +118,7 @@ void si5351c_set_phase( /* Driver Instance. */ extern const i2c_lpc_config_t i2c_config_si5351c_fast_clock; -extern si5351c_driver_t clock_gen; +extern si5351c_driver_t si5351c; #ifdef __cplusplus } diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index 58c1684c..e88d0016 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -27,7 +27,6 @@ #include #include -#include #include #include #include @@ -40,6 +39,7 @@ #include #endif #ifdef IS_NOT_RAD1O + #include #include #include #endif @@ -101,7 +101,7 @@ usb_request_status_t usb_vendor_request_write_si5351c( if (endpoint->setup.index < 256) { if (endpoint->setup.value < 256) { si5351c_write_single( - &clock_gen, + &si5351c, endpoint->setup.index, endpoint->setup.value); usb_transfer_schedule_ack(endpoint->in); @@ -121,7 +121,7 @@ usb_request_status_t usb_vendor_request_read_si5351c( if (stage == USB_TRANSFER_STAGE_SETUP) { if (endpoint->setup.index < 256) { const uint8_t value = - si5351c_read_single(&clock_gen, endpoint->setup.index); + si5351c_read_single(&si5351c, endpoint->setup.index); endpoint->buffer[0] = value; usb_transfer_schedule_block( endpoint->in, @@ -211,7 +211,7 @@ usb_request_status_t usb_vendor_request_set_clkout_enable( const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { - si5351c_clkout_enable(&clock_gen, endpoint->setup.value); + si5351c_clkout_enable(&si5351c, endpoint->setup.value); usb_transfer_schedule_ack(endpoint->in); } return USB_REQUEST_STATUS_OK; @@ -222,7 +222,7 @@ usb_request_status_t usb_vendor_request_get_clkin_status( const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { - endpoint->buffer[0] = si5351c_clkin_signal_valid(&clock_gen); + endpoint->buffer[0] = si5351c_clkin_signal_valid(&si5351c); usb_transfer_schedule_block( endpoint->in, &endpoint->buffer, From 3efc8bdbb6a2ccee3bbccfb0f2f7443fd1b34b94 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 30 Apr 2026 15:30:00 +0200 Subject: [PATCH 168/238] firmware: move max5864 driver instance to max5864.x --- firmware/common/drivers.c | 33 ++------------------------------- firmware/common/drivers.h | 8 +------- firmware/common/max5864.c | 29 +++++++++++++++++++++++++++++ firmware/common/max5864.h | 6 ++++++ firmware/common/pins.c | 1 + 5 files changed, 39 insertions(+), 38 deletions(-) diff --git a/firmware/common/drivers.c b/firmware/common/drivers.c index bd601a1c..769013b0 100644 --- a/firmware/common/drivers.c +++ b/firmware/common/drivers.c @@ -23,37 +23,13 @@ #include -#include - -#include "max5864_target.h" -#include "spi_bus.h" #if defined(IS_PRALINE) + #include #include "fpga.h" #include "ice40_spi.h" + #include "spi_bus.h" #endif -// const i2c_lpc_config_t i2c_config_si5351c_slow_clock = { -// .duty_cycle_count = 15, -// }; - -ssp_config_t ssp_config_max5864 = { - /* FIXME speed up once everything is working reliably */ - /* - // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - const uint8_t serial_clock_rate = 32; - const uint8_t clock_prescale_rate = 128; - */ - // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - .data_bits = SSP_DATA_8BITS, - .serial_clock_rate = 21, - .clock_prescale_rate = 2, -}; - -max5864_driver_t max5864 = { - .bus = &spi_bus_ssp1, - .target_init = max5864_target_init, -}; - sgpio_config_t sgpio_config = { .slice_mode_multislice = true, }; @@ -85,11 +61,6 @@ jtag_t jtag_cpld = { .gpio = &jtag_gpio_cpld, }; -void ssp1_set_mode_max5864(void) -{ - spi_bus_start(max5864.bus, &ssp_config_max5864); -} - #ifdef IS_PRALINE void ssp1_set_mode_ice40(void) { diff --git a/firmware/common/drivers.h b/firmware/common/drivers.h index 2bb8db8e..423e46a8 100644 --- a/firmware/common/drivers.h +++ b/firmware/common/drivers.h @@ -26,33 +26,27 @@ extern "C" { #endif #include "cpld_jtag.h" -#include "max5864.h" #include "mixer.h" #include "platform_detect.h" // IWYU pragma: keep #include "rf_path.h" #include "sgpio.h" -#include "spi_ssp.h" #if defined(IS_PRALINE) #include "fpga.h" #include "ice40_spi.h" + #include "spi_ssp.h" #endif -/* TODO: Hide these configurations */ -extern ssp_config_t ssp_config_max5864; - #if defined(IS_PRALINE) extern ssp_config_t ssp_config_ice40_fpga; extern ice40_spi_driver_t ice40; extern fpga_driver_t fpga; #endif -extern max5864_driver_t max5864; extern mixer_driver_t mixer; extern sgpio_config_t sgpio_config; extern rf_path_t rf_path; extern jtag_gpio_t jtag_gpio_cpld; extern jtag_t jtag_cpld; -void ssp1_set_mode_max5864(void); #if defined(IS_PRALINE) void ssp1_set_mode_ice40(void); #endif diff --git a/firmware/common/max5864.c b/firmware/common/max5864.c index b91a1cd1..88d781b9 100644 --- a/firmware/common/max5864.c +++ b/firmware/common/max5864.c @@ -24,6 +24,35 @@ #include +#include + +#include "max5864_target.h" +#include "spi_bus.h" + +/* Driver instance. */ +ssp_config_t ssp_config_max5864 = { + /* FIXME speed up once everything is working reliably */ + /* + // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + const uint8_t serial_clock_rate = 32; + const uint8_t clock_prescale_rate = 128; + */ + // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + .data_bits = SSP_DATA_8BITS, + .serial_clock_rate = 21, + .clock_prescale_rate = 2, +}; + +max5864_driver_t max5864 = { + .bus = &spi_bus_ssp1, + .target_init = max5864_target_init, +}; + +void ssp1_set_mode_max5864(void) +{ + spi_bus_start(max5864.bus, &ssp_config_max5864); +} + static void max5864_write(max5864_driver_t* const drv, uint8_t value) { spi_bus_transfer(drv->bus, &value, 1); diff --git a/firmware/common/max5864.h b/firmware/common/max5864.h index 56d730cc..a617cdf0 100644 --- a/firmware/common/max5864.h +++ b/firmware/common/max5864.h @@ -23,6 +23,7 @@ #pragma once #include "spi_bus.h" +#include "spi_ssp.h" typedef struct _max5864_driver_t { spi_bus_t* const bus; @@ -37,3 +38,8 @@ void max5864_idle(max5864_driver_t* const drv); void max5864_rx(max5864_driver_t* const drv); void max5864_tx(max5864_driver_t* const drv); void max5864_xcvr(max5864_driver_t* const drv); + +/* Driver instance. */ +extern ssp_config_t ssp_config_max5864; +extern max5864_driver_t max5864; +void ssp1_set_mode_max5864(void); diff --git a/firmware/common/pins.c b/firmware/common/pins.c index bced06d4..24aeb033 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -30,6 +30,7 @@ #include "gpio.h" #include "leds.h" #include "max283x.h" +#include "max5864.h" #include "mixer.h" #include "platform_detect.h" #include "platform_gpio.h" From c8a0b02d85da760b7d87da0b382acc6ea2f90204 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 30 Apr 2026 15:37:23 +0200 Subject: [PATCH 169/238] firmware: move mixer object's extern instance to mixer.h --- firmware/common/drivers.h | 2 -- firmware/common/mixer.h | 3 +++ firmware/common/rf_path.c | 1 - firmware/hackrf_usb/usb_api_register.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/common/drivers.h b/firmware/common/drivers.h index 423e46a8..461ada2c 100644 --- a/firmware/common/drivers.h +++ b/firmware/common/drivers.h @@ -26,7 +26,6 @@ extern "C" { #endif #include "cpld_jtag.h" -#include "mixer.h" #include "platform_detect.h" // IWYU pragma: keep #include "rf_path.h" #include "sgpio.h" @@ -41,7 +40,6 @@ extern ssp_config_t ssp_config_ice40_fpga; extern ice40_spi_driver_t ice40; extern fpga_driver_t fpga; #endif -extern mixer_driver_t mixer; extern sgpio_config_t sgpio_config; extern rf_path_t rf_path; extern jtag_gpio_t jtag_gpio_cpld; diff --git a/firmware/common/mixer.h b/firmware/common/mixer.h index f7861725..35c0f047 100644 --- a/firmware/common/mixer.h +++ b/firmware/common/mixer.h @@ -65,3 +65,6 @@ extern fp_40_24_t mixer_set_frequency( extern void mixer_enable(mixer_driver_t* const mixer); extern void mixer_disable(mixer_driver_t* const mixer); extern void mixer_set_gpo(mixer_driver_t* const drv, uint8_t gpo); + +/* Mixer instance. */ +extern mixer_driver_t mixer; diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index ea1c0d45..721d647c 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -23,7 +23,6 @@ #include "rf_path.h" -#include "drivers.h" #include "max283x.h" #include "max5864.h" #include "mixer.h" diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index e88d0016..88a4de53 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -36,10 +36,10 @@ #include #include #ifdef IS_PRALINE + #include #include #endif #ifdef IS_NOT_RAD1O - #include #include #include #endif From 9a3abb6413912ab8fc55251e504421121f83e0a4 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 30 Apr 2026 15:40:48 +0200 Subject: [PATCH 170/238] firmware: move rf_path object instance to rf_path.x --- firmware/common/drivers.c | 4 ---- firmware/common/drivers.h | 2 -- firmware/common/radio.c | 2 +- firmware/common/rf_path.c | 5 +++++ firmware/common/rf_path.h | 3 +++ 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/firmware/common/drivers.c b/firmware/common/drivers.c index 769013b0..85a17746 100644 --- a/firmware/common/drivers.c +++ b/firmware/common/drivers.c @@ -51,10 +51,6 @@ fpga_driver_t fpga = { }; #endif -rf_path_t rf_path = { - .switchctrl = 0, -}; - jtag_gpio_t jtag_gpio_cpld = {}; jtag_t jtag_cpld = { diff --git a/firmware/common/drivers.h b/firmware/common/drivers.h index 461ada2c..11ec20a2 100644 --- a/firmware/common/drivers.h +++ b/firmware/common/drivers.h @@ -27,7 +27,6 @@ extern "C" { #include "cpld_jtag.h" #include "platform_detect.h" // IWYU pragma: keep -#include "rf_path.h" #include "sgpio.h" #if defined(IS_PRALINE) #include "fpga.h" @@ -41,7 +40,6 @@ extern ice40_spi_driver_t ice40; extern fpga_driver_t fpga; #endif extern sgpio_config_t sgpio_config; -extern rf_path_t rf_path; extern jtag_gpio_t jtag_gpio_cpld; extern jtag_t jtag_cpld; diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 8cf73cc8..17b7486c 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -26,7 +26,6 @@ #include #include "clock_io.h" -#include "drivers.h" #include "fixed_point.h" #include "max283x.h" #include "mixer.h" @@ -35,6 +34,7 @@ #include "transceiver_mode.h" #include "tuning.h" #ifdef IS_PRALINE + #include "drivers.h" #include "fpga.h" #include "tune_config.h" #endif diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 721d647c..e3292532 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -35,6 +35,11 @@ #include "platform_gpio.h" #endif +/* RF Path instance. */ +rf_path_t rf_path = { + .switchctrl = 0, +}; + /* * RF switches on Jawbreaker are controlled by General Purpose Outputs (GPO) on * the RFFC5072. diff --git a/firmware/common/rf_path.h b/firmware/common/rf_path.h index 12f83b53..ca7641e4 100644 --- a/firmware/common/rf_path.h +++ b/firmware/common/rf_path.h @@ -106,3 +106,6 @@ void rf_path_set_antenna(rf_path_t* const rf_path, const uint_fast8_t enable); #ifdef IS_PRALINE void narrowband_filter_set(const uint8_t value); #endif + +/* RF Path instance. */ +extern rf_path_t rf_path; From 47f91d29cf313c03ded1989498de7519f62d0a3f Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 30 Apr 2026 16:19:05 +0200 Subject: [PATCH 171/238] firmware: move sgpio_config configuration instance to sgpio.x --- firmware/common/clock_gen.c | 1 - firmware/common/clock_io.c | 5 ++++- firmware/common/drivers.c | 6 ------ firmware/common/drivers.h | 2 -- firmware/common/sgpio.c | 5 +++++ firmware/common/sgpio.h | 3 +++ firmware/hackrf_usb/hackrf_usb.c | 2 +- firmware/hackrf_usb/usb_api_sweep.c | 2 +- firmware/hackrf_usb/usb_api_transceiver.c | 2 +- 9 files changed, 15 insertions(+), 13 deletions(-) diff --git a/firmware/common/clock_gen.c b/firmware/common/clock_gen.c index 642fc61b..0f0085c2 100644 --- a/firmware/common/clock_gen.c +++ b/firmware/common/clock_gen.c @@ -23,7 +23,6 @@ #include -#include "drivers.h" #include "hackrf_ui.h" #include "i2c_bus.h" #include "platform_detect.h" diff --git a/firmware/common/clock_io.c b/firmware/common/clock_io.c index 279eb8c5..c68d470f 100644 --- a/firmware/common/clock_io.c +++ b/firmware/common/clock_io.c @@ -30,10 +30,13 @@ #include #include -#include "drivers.h" #include "gpdma.h" #include "gpio.h" +#ifdef IS_NOT_PRALINE + #include "sgpio.h" +#endif #ifdef IS_PRALINE + #include "drivers.h" #include "fpga.h" #include "platform_gpio.h" #endif diff --git a/firmware/common/drivers.c b/firmware/common/drivers.c index 85a17746..58b30cb2 100644 --- a/firmware/common/drivers.c +++ b/firmware/common/drivers.c @@ -21,8 +21,6 @@ #include "drivers.h" -#include - #if defined(IS_PRALINE) #include #include "fpga.h" @@ -30,10 +28,6 @@ #include "spi_bus.h" #endif -sgpio_config_t sgpio_config = { - .slice_mode_multislice = true, -}; - #ifdef IS_PRALINE ssp_config_t ssp_config_ice40_fpga = { .data_bits = SSP_DATA_8BITS, diff --git a/firmware/common/drivers.h b/firmware/common/drivers.h index 11ec20a2..d0427e93 100644 --- a/firmware/common/drivers.h +++ b/firmware/common/drivers.h @@ -27,7 +27,6 @@ extern "C" { #include "cpld_jtag.h" #include "platform_detect.h" // IWYU pragma: keep -#include "sgpio.h" #if defined(IS_PRALINE) #include "fpga.h" #include "ice40_spi.h" @@ -39,7 +38,6 @@ extern ssp_config_t ssp_config_ice40_fpga; extern ice40_spi_driver_t ice40; extern fpga_driver_t fpga; #endif -extern sgpio_config_t sgpio_config; extern jtag_gpio_t jtag_gpio_cpld; extern jtag_t jtag_cpld; diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index 568f1208..e6151e46 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -35,6 +35,11 @@ #include "clock_io.h" #endif +/* Driver configuration instance. */ +sgpio_config_t sgpio_config = { + .slice_mode_multislice = true, +}; + static void update_q_invert(sgpio_config_t* const config); void sgpio_configure_pin_functions(sgpio_config_t* const config) diff --git a/firmware/common/sgpio.h b/firmware/common/sgpio.h index 409cef0c..767d6f48 100644 --- a/firmware/common/sgpio.h +++ b/firmware/common/sgpio.h @@ -50,3 +50,6 @@ void sgpio_cpld_stream_disable(sgpio_config_t* const config); bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config); void sgpio_cpld_set_mixer_invert(sgpio_config_t* const config, uint_fast8_t invert); + +/* Driver configuration instance. */ +extern sgpio_config_t sgpio_config; diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index d02ea279..031f2001 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -71,6 +70,7 @@ #ifdef IS_NOT_PRALINE #include #include + #include #endif #include "usb_api_adc.h" diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index ae3b399d..72ff2467 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -25,13 +25,13 @@ #include -#include #include #include #include #include #include #include +#include #include #include #include diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index b6c6782b..7f6f9473 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -27,13 +27,13 @@ #include #include -#include #include #include #include #include #include #include +#include #include #include #include From a426b7518d5ebb267f7895ecbf41d009223725d0 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Mon, 27 Apr 2026 16:56:20 -0400 Subject: [PATCH 172/238] Improve pins_shutdown() --- firmware/common/operacake_sctimer.c | 27 ++++++----------- firmware/common/pins.c | 34 +++++++++++++++++++-- firmware/common/platform_gpio.c | 1 + firmware/common/platform_gpio.h | 1 + firmware/common/platform_scu.c | 12 ++++++++ firmware/common/platform_scu.h | 12 ++++++++ firmware/common/rf_path.c | 27 +++++++++++++++++ firmware/common/rf_path.h | 1 + firmware/common/sgpio.c | 47 +++++++++++++++++++++++++++++ firmware/common/sgpio.h | 1 + 10 files changed, 143 insertions(+), 20 deletions(-) diff --git a/firmware/common/operacake_sctimer.c b/firmware/common/operacake_sctimer.c index 3b95f6a1..1268114f 100644 --- a/firmware/common/operacake_sctimer.c +++ b/firmware/common/operacake_sctimer.c @@ -28,6 +28,7 @@ #include "delay.h" #include "platform_detect.h" +#include "platform_scu.h" #include "sct.h" #ifdef IS_NOT_PRALINE @@ -62,6 +63,8 @@ static uint32_t default_output = 0; */ void operacake_sctimer_init(void) { + const platform_scu_t* scu = platform_scu(); + // We start by resetting the SCTimer RESET_CTRL1 = RESET_CTRL1_SCT_RST; @@ -77,25 +80,15 @@ void operacake_sctimer_init(void) // Pin definitions for the HackRF // U2CTRL0 - scu_pinmux( - P7_4, - SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); + scu_pinmux(scu->CTOUT_13, scu->CTOUT_PINCFG); // U2CTRL1 - scu_pinmux( - P7_5, - SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); + scu_pinmux(scu->CTOUT_12, scu->CTOUT_PINCFG); // U3CTRL0 - scu_pinmux( - P7_6, - SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); + scu_pinmux(scu->CTOUT_11, scu->CTOUT_PINCFG); // U3CTRL1 - scu_pinmux( - P7_7, - SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); + scu_pinmux(scu->CTOUT_8, scu->CTOUT_PINCFG); // U1CTRL - scu_pinmux( - P7_0, - SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); + scu_pinmux(scu->CTOUT_14, scu->CTOUT_PINCFG); uint8_t sct_clock_input; #ifdef IS_NOT_PRALINE @@ -114,8 +107,8 @@ void operacake_sctimer_init(void) #endif #ifdef IS_PRALINE if (IS_PRALINE) { - // Configure pin P6_4 as SCT_IN_6 - scu_pinmux(P6_4, SCU_CLK_IN | SCU_CONF_FUNCTION1); + // Configure pin P6_4 as CTIN_6 + scu_pinmux(scu->SCT_CLK, scu->SCT_CLK_PINCFG); // Use the GIMA to connect MS0/CLK1 (SCT_CLK) on pin P6_4 to the SCTimer GIMA_CTIN_6_IN = 0x0 << 4; diff --git a/firmware/common/pins.c b/firmware/common/pins.c index 6f8123cb..eb445fc3 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -178,9 +178,30 @@ void pins_shutdown(void) scu_pinmux(scu->TRIGGER_IN, scu->TRIGGER_IN_PINCFG); scu_pinmux(scu->TRIGGER_OUT, scu->TRIGGER_OUT_PINCFG); scu_pinmux(scu->PPS_OUT, scu->PPS_OUT_PINCFG); - scu_pinmux(scu->PINMUX_FPGA_CRESET, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - scu_pinmux(scu->PINMUX_FPGA_CDONE, SCU_GPIO_PUP | SCU_CONF_FUNCTION4); - scu_pinmux(scu->PINMUX_FPGA_SPI_CS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(scu->SCT_CLK, scu->SCT_CLK_PINCFG); + + scu_pinmux(scu->PINMUX_FPGA_CRESET, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_FPGA_CDONE, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); + scu_pinmux(scu->PINMUX_FPGA_SPI_CS, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + + scu_pinmux(scu->SSP1_CIPO, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->SSP1_COPI, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->SSP1_SCK, SCU_GPIO_PDN | SCU_CONF_FUNCTION2); + + scu_pinmux(scu->XCVR_ENABLE, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); + scu_pinmux(scu->XCVR_RXENABLE, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); + scu_pinmux(scu->XCVR_CS, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); + scu_pinmux(scu->XCVR_RXHP, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); + scu_pinmux(scu->XCVR_LD, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + + scu_pinmux(scu->MIXER_LD, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); + scu_pinmux(scu->MIXER_SCLK, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); + scu_pinmux(scu->MIXER_SDATA, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->MIXER_ENX, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->MIXER_RESETX, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->MIXER_ENBL, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + + scu_pinmux(scu->AD_CS, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); p2_ctrl_set(P2_SIGNAL_CLK3); p1_ctrl_set(P1_SIGNAL_CLKIN); @@ -202,8 +223,12 @@ void pins_shutdown(void) gpio_clear(gpio->fpga_cfg_creset); gpio_output(gpio->fpga_cfg_creset); gpio_input(gpio->fpga_cfg_cdone); + gpio_input(gpio->max5864_select); + + rf_path_pin_shutdown(); } #endif + sgpio_pin_shutdown(&sgpio_config); /* enable input on SCL and SDA pins */ SCU_SFSI2C0 = SCU_I2C0_NOMINAL; @@ -360,6 +385,9 @@ void pins_setup(void) (detected_revision() == BOARD_REV_GSG_PRALINE_R1_0)) { rf_path.gpio_mix_en_n = gpio->mix_en_n_r1_0; } + scu_pinmux(scu->PINMUX_FPGA_CRESET, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_FPGA_CDONE, SCU_GPIO_PUP | SCU_CONF_FUNCTION4); + scu_pinmux(scu->PINMUX_FPGA_SPI_CS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); } #endif diff --git a/firmware/common/platform_gpio.c b/firmware/common/platform_gpio.c index a5b892e8..eeecd90e 100644 --- a/firmware/common/platform_gpio.c +++ b/firmware/common/platform_gpio.c @@ -234,6 +234,7 @@ const platform_gpio_t* platform_gpio(void) gpio.rffc5072_data = &GPIO4_14; gpio.rffc5072_reset = &GPIO2_14; gpio.rffc5072_ld = &GPIO6_25; + gpio.rffc5072_enbl = &GPIO4_12; } #endif diff --git a/firmware/common/platform_gpio.h b/firmware/common/platform_gpio.h index eeb37b05..a7e68bc9 100644 --- a/firmware/common/platform_gpio.h +++ b/firmware/common/platform_gpio.h @@ -137,6 +137,7 @@ typedef struct { gpio_t rffc5072_data; gpio_t rffc5072_reset; gpio_t rffc5072_ld; // PRALINE + gpio_t rffc5072_enbl; // PRALINE gpio_t vco_ce; // RAD1O gpio_t vco_sclk; // RAD1O gpio_t vco_sdata; // RAD1O diff --git a/firmware/common/platform_scu.c b/firmware/common/platform_scu.c index ef894745..c9e468e9 100644 --- a/firmware/common/platform_scu.c +++ b/firmware/common/platform_scu.c @@ -258,10 +258,12 @@ const platform_scu_t* platform_scu(void) scu.MIXER_SDATA = (P9_2); /* GPIO4[14] on P9_2 */ scu.MIXER_RESETX = (P5_5); /* GPIO2[14] on P5_5 */ scu.MIXER_LD = (PD_11); /* GPIO6[25] on PD_11 */ + scu.MIXER_ENBL = (P9_0); /* GPIO4[12] on P9_0 */ scu.MIXER_SCLK_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.MIXER_SDATA_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu.MIXER_LD_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.MIXER_ENBL_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0); } #endif #ifdef IS_RAD1O @@ -365,6 +367,7 @@ const platform_scu_t* platform_scu(void) scu.TRIGGER_IN = (PD_12); /* GPIO6[26] on PD_12 */ scu.TRIGGER_OUT = (P2_6); /* GPIO5[6] on P2_6 */ scu.PPS_OUT = (P2_5); /* GPIO5[5] on P2_5 */ + scu.SCT_CLK = (P6_4); /* CTIN_6 on P6_4 */ scu.P2_CTRL0_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.P2_CTRL1_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); @@ -376,6 +379,7 @@ const platform_scu_t* platform_scu(void) scu.TRIGGER_IN_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.TRIGGER_OUT_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu.PPS_OUT_PINCFG = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu.SCT_CLK_PINCFG = (SCU_CLK_IN | SCU_CONF_FUNCTION1); } #endif @@ -438,6 +442,14 @@ const platform_scu_t* platform_scu(void) } #endif + /* SCT */ + scu.CTOUT_8 = (P7_7); + scu.CTOUT_11 = (P7_6); + scu.CTOUT_12 = (P7_5); + scu.CTOUT_13 = (P7_4); + scu.CTOUT_14 = (P7_0); + scu.CTOUT_PINCFG = (SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); + scu.PINMUX_ISP = (P2_7); /* GPIO0[7] */ scu.PINMUX_GP_CLKIN = (P4_7); diff --git a/firmware/common/platform_scu.h b/firmware/common/platform_scu.h index 1ffb224c..71c0f742 100644 --- a/firmware/common/platform_scu.h +++ b/firmware/common/platform_scu.h @@ -157,7 +157,9 @@ typedef struct { #endif #ifdef IS_PRALINE scu_grp_pin_t MIXER_LD; + scu_grp_pin_t MIXER_ENBL; uint32_t MIXER_LD_PINCFG; + uint32_t MIXER_ENBL_PINCFG; #endif #ifdef IS_RAD1O scu_grp_pin_t VCO_CE; @@ -240,6 +242,7 @@ typedef struct { scu_grp_pin_t TRIGGER_IN; scu_grp_pin_t TRIGGER_OUT; scu_grp_pin_t PPS_OUT; + scu_grp_pin_t SCT_CLK; scu_grp_pin_t P2_CTRL0_PINCFG; scu_grp_pin_t P2_CTRL1_PINCFG; @@ -251,6 +254,7 @@ typedef struct { scu_grp_pin_t TRIGGER_IN_PINCFG; scu_grp_pin_t TRIGGER_OUT_PINCFG; scu_grp_pin_t PPS_OUT_PINCFG; + scu_grp_pin_t SCT_CLK_PINCFG; #endif /* HackRF One r9 */ @@ -300,6 +304,14 @@ typedef struct { scu_grp_pin_t PINMUX_U0_TXD; scu_grp_pin_t PINMUX_U0_RXD; + /* SCT */ + scu_grp_pin_t CTOUT_8; + scu_grp_pin_t CTOUT_11; + scu_grp_pin_t CTOUT_12; + scu_grp_pin_t CTOUT_13; + scu_grp_pin_t CTOUT_14; + scu_grp_pin_t CTOUT_PINCFG; + scu_grp_pin_t PINMUX_ISP; scu_grp_pin_t PINMUX_GP_CLKIN; diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index ea1c0d45..8fc071a7 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -317,6 +317,33 @@ static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) #endif } +void rf_path_pin_shutdown(void) +{ +#ifdef IS_PRALINE + if (IS_PRALINE) { + const platform_scu_t* scu = platform_scu(); + + /* Configure RF switch control signals */ + scu_pinmux(scu->TX_EN, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + board_rev_t rev = detected_revision(); + if ((rev == BOARD_REV_PRALINE_R1_0) || + (rev == BOARD_REV_GSG_PRALINE_R1_0)) { + scu_pinmux(scu->MIX_EN_N_R1_0, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); + } else { + scu_pinmux(scu->MIX_EN_N, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + } + scu_pinmux(scu->LPF_EN, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->RF_AMP_EN, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + + /* Configure antenna port power control signal */ + scu_pinmux(scu->ANT_BIAS_EN_N, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + + /* Configure RF power supply (VAA) switch */ + scu_pinmux(scu->NO_VAA_ENABLE, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + } +#endif +} + void rf_path_pin_setup(rf_path_t* const rf_path) { #ifdef IS_JAWBREAKER diff --git a/firmware/common/rf_path.h b/firmware/common/rf_path.h index 12f83b53..a1e91b4c 100644 --- a/firmware/common/rf_path.h +++ b/firmware/common/rf_path.h @@ -93,6 +93,7 @@ typedef struct { }; } rf_path_t; +void rf_path_pin_shutdown(void); void rf_path_pin_setup(rf_path_t* const rf_path); void rf_path_init(rf_path_t* const rf_path); diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index 568f1208..a88290db 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -37,6 +37,53 @@ static void update_q_invert(sgpio_config_t* const config); +void sgpio_pin_shutdown(sgpio_config_t* const config) +{ + const platform_scu_t* scu = platform_scu(); + +#ifdef IS_PRALINE + if (IS_PRALINE) { + scu_pinmux(scu->PINMUX_SGPIO0, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_SGPIO1, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_SGPIO2, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_SGPIO3, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_SGPIO4, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); + scu_pinmux(scu->PINMUX_SGPIO5, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_SGPIO6, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); + scu_pinmux(scu->PINMUX_SGPIO7, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_SGPIO8, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_SGPIO9, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_SGPIO10, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_SGPIO11, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_SGPIO12, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + } +#endif + +#ifdef IS_H1_R9 + if (IS_H1_R9) { + scu_pinmux( + scu->H1R9_TRIGGER_EN, + SCU_GPIO_PDN | SCU_CONF_FUNCTION4); /* GPIO5[5] */ + } +#endif +#ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { + scu_pinmux( + scu->TRIGGER_EN, + SCU_GPIO_PDN | SCU_CONF_FUNCTION4); /* GPIO5[12] */ + } +#endif + + gpio_input(config->gpio_q_invert); + +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { + trigger_enable(false); + gpio_output(config->gpio_trigger_enable); + } +#endif +} + void sgpio_configure_pin_functions(sgpio_config_t* const config) { const platform_scu_t* scu = platform_scu(); diff --git a/firmware/common/sgpio.h b/firmware/common/sgpio.h index 409cef0c..392209da 100644 --- a/firmware/common/sgpio.h +++ b/firmware/common/sgpio.h @@ -41,6 +41,7 @@ typedef struct { bool slice_mode_multislice; } sgpio_config_t; +void sgpio_pin_shutdown(sgpio_config_t* const config); void sgpio_configure_pin_functions(sgpio_config_t* const config); void sgpio_test_interface(sgpio_config_t* const config); void sgpio_set_slice_mode(sgpio_config_t* const config, const bool multi_slice); From e8cfb86e10bf06a2bd1d8a61f19747ccffaecc06 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 28 Apr 2026 14:52:13 +0100 Subject: [PATCH 173/238] Add picoprintf to RAD1O firmware build. Code taken from https://github.com/rom-p/picoprintf @ dfb7f93. --- firmware/common/picobool.h | 20 ++ firmware/common/picoprintf.c | 342 +++++++++++++++++++++++++++++ firmware/common/picoprintf.h | 43 ++++ firmware/hackrf_usb/CMakeLists.txt | 1 + 4 files changed, 406 insertions(+) create mode 100644 firmware/common/picobool.h create mode 100644 firmware/common/picoprintf.c create mode 100644 firmware/common/picoprintf.h diff --git a/firmware/common/picobool.h b/firmware/common/picobool.h new file mode 100644 index 00000000..3f0324c8 --- /dev/null +++ b/firmware/common/picobool.h @@ -0,0 +1,20 @@ +#ifndef __picobool_h_INCLUDED__ +#define __picobool_h_INCLUDED__ + +// this file provides a bool type which might or might not be available on your platform + +#ifndef __cplusplus // C++: use standard bool + #ifndef __STDC_VERSION__ // Pre-C99: define bool manually + typedef unsigned char bool; + #define true 1 + #define false 0 + #elif __STDC_VERSION__ < 199901L // C90/C95: define bool manually + typedef unsigned char bool; + #define true 1 + #define false 0 + #else // C99+: use standard bool + #include + #endif +#endif + +#endif // __picobool_h_INCLUDED__ diff --git a/firmware/common/picoprintf.c b/firmware/common/picoprintf.c new file mode 100644 index 00000000..18ef565c --- /dev/null +++ b/firmware/common/picoprintf.c @@ -0,0 +1,342 @@ +#include "picoprintf.h" +#include "picobool.h" + +#include // fabs() +#include // llabs() + + +static void flip(char *pLeft, char *pRight) { + pRight--; + while (pLeft < pRight) { + char tmp = *pLeft; + *pLeft = *pRight; + *pRight = tmp; + pLeft++; + pRight--; + } +} + +// using #define over `inline` for enabling porting to old C +#if !defined(MIN) +#define MIN(left, right) (((left) < (right)) ? (left) : (right)) +#endif +#if !defined(MAX) +#define MAX(left, right) (((left) > (right)) ? (left) : (right)) +#endif + + +// returns the pointer to the null-terminating character of the filled string +int pico_vsnprintf(char *pDest, size_t cbDest, const char *pFormat, va_list vl) { + const char *pLowercaseNumberDigits = "0123456789abcdef"; + const char *pUppercaseNumberDigits = "0123456789ABCDEF"; + const char *pOctalDigits = pLowercaseNumberDigits; + const char *pBinaryDigits = pLowercaseNumberDigits; + char *pStart = pDest; + for (char *pEnd = pDest + cbDest - 1; *pFormat && pDest < pEnd; ) { + if (*pFormat != '%') { + *pDest++ = *pFormat++; + } else { // format starts here + pFormat++; // skipping the '%' + if (*pFormat == '%') { // unless it's indeed a '%' + *pDest++ = *pFormat++; + } else { // first, collect the format + char format = '\0'; + int bits_per_digit = 0; // valid in 'b', 'o', 'p' and 'x'/'X' modes only + int whole_chars = 0; // number of chars in the whole part of the number + int decimal_chars = -1; // if not specified, %f are rendered with 6, while %g are rendered with 0 + #ifdef __aarch64__ // these platforms benefit from packing flags into a single variable + struct { + unsigned force_sign:1; + unsigned fill_zeros:1; + unsigned left_align:1; + unsigned seen_period:1; + unsigned seen_numbers:1; + unsigned treat_as_unsigned:1; + unsigned treat_as_long:1; + unsigned render_in_lowercase:1; + } flags = {0}; + #define FLAGS flags. + + #else // other platforms do not benefit from struct packing + unsigned force_sign = 0; + unsigned fill_zeros = 0; + unsigned left_align = 0; + unsigned seen_period = 0; + unsigned seen_numbers = 0; + unsigned treat_as_unsigned = 0; + unsigned treat_as_long = 0; + unsigned render_in_lowercase = 0; + #define FLAGS + #endif // struct packing platforms + for (; *pFormat && '\0' == format; pFormat++) { + switch (*pFormat) { + #ifdef PICOFORMAT_HANDLE_FORCEDSIGN + case '+': + FLAGS force_sign = 1; + break; + #endif // PICOFORMAT_HANDLE_FORCEDSIGN + #ifdef PICOFORMAT_HANDLE_FILL + case '-': // left-align flag + FLAGS left_align = 1; + break; + #endif // PICOFORMAT_HANDLE_FILL + case '0': + if (!FLAGS seen_numbers) { + FLAGS fill_zeros = 1; + break; + } + // fall through + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + *(FLAGS seen_period ? &decimal_chars : &whole_chars ) *= 10; + *(FLAGS seen_period ? &decimal_chars : &whole_chars) += *pFormat - '0'; + FLAGS seen_numbers = 1; + break; + case '.': + FLAGS seen_numbers = FLAGS seen_period = 1; + decimal_chars = 0; + break; + case '*': // dynamic width/precision: read value from arg list + *(FLAGS seen_period ? &decimal_chars : &whole_chars) = va_arg(vl, int); + FLAGS seen_numbers = 1; + break; + case 'l': // long modifier + FLAGS treat_as_long = 1; + break; + case 'u': // unsigned decimal integer + FLAGS treat_as_unsigned = 1; + format = 'd'; + break; + #ifdef PICOFORMAT_HANDLE_BIN + case 'b': + bits_per_digit = 0; + FLAGS treat_as_unsigned = 1; + format = 'b'; + break; + #endif // PICOFORMAT_HANDLE_BIN + #ifdef PICOFORMAT_HANDLE_OCT + case 'o': // octal integer + bits_per_digit = 3; + FLAGS treat_as_unsigned = 1; + format = 'b'; + break; + #endif // PICOFORMAT_HANDLE_OCT + #ifdef PICOFORMAT_HANDLE_HEX + case 'x': // hexadecimal integer + case 'p': // pointer + bits_per_digit = 4; + FLAGS treat_as_unsigned = 1; + FLAGS render_in_lowercase = 1; + format = 'b'; + break; + case 'X': // hexadecimal integer, uppercase + bits_per_digit = 4; + FLAGS treat_as_unsigned = 1; + format = 'b'; + break; + #endif // PICOFORMAT_HANDLE_HEX + #ifdef PICOFORMAT_HANDLE_FLOATS + case 'a': + #ifdef PICOFORMAT_HANDLE_EXPONENTS + case 'e': // floating point, exponent format + #endif // PICOFORMAT_HANDLE_EXPONENTS + case 'f': + FLAGS render_in_lowercase = 1; + // fall through + case 'F': + #endif // PICOFORMAT_HANDLE_FLOATS + case 'c': // single char: always supported + case 'd': // integer: always supported + case 'i': // integer: always supported + case 's': // string of native `char`s: always supported + format = *pFormat; + break; + default: + FORMAT_ERROR_DELEGATE("detected unhandled format specifier: %c", *pFormat); + break; + } + } + + // format is parsed, now render the value + char *pParamStarts = pDest; + switch (format) { + case 'c': // single char + *pDest++ = va_arg(vl, int) & 0xff; + break; + case 's': { // null-terminated string + #ifdef PICOFORMAT_HANDLE_FILL + int len = 0; // effective length, bounded by precision if set + const char *pStr = va_arg(vl, const char*); + for (; pStr[len] && (decimal_chars < 0 || len < decimal_chars); len++); + if (!FLAGS left_align) { // right-align: pad on the left + #ifdef PICOFORMAT_CLANG_QUIRK // clang's non-standard: '0' flag zero-pads strings + char chFill = FLAGS fill_zeros ? '0' : ' '; + #else // PICOFORMAT_CLANG_QUIRK // standard C: '0' flag is undefined for %s, use spaces + char chFill = ' '; + #endif // PICOFORMAT_CLANG_QUIRK + for (; pDest < pEnd && whole_chars > len; whole_chars--) { + *pDest++ = chFill; + } + } + for (int ii = 0; ii < len && pDest < pEnd; ii++) { + *pDest++ = pStr[ii]; + } + if (FLAGS left_align) { // left-align: pad on the right (always spaces; '-' flag overrides '0') + for (; pDest < pEnd && whole_chars > len; whole_chars--) { + *pDest++ = ' '; + } + } + #else // PICOFORMAT_HANDLE_FILL + for (const char *pStr = va_arg(vl, const char*); *pStr && pDest < pEnd; ) { + *pDest++ = *pStr++; + } + #endif // PICOFORMAT_HANDLE_FILL + } + break; + #if defined(PICOFORMAT_HANDLE_HEX) || defined(PICOFORMAT_HANDLE_OCT) || defined(PICOFORMAT_HANDLE_BIN) + case 'b': { // binary, oct, or hex integer, always unsigned + long long int val = 0; + if (FLAGS treat_as_long) { + val = va_arg(vl, unsigned long long int); + } else { + val = va_arg(vl, unsigned); + } + unsigned mask = bits_per_digit == 4 ? 0x0f : bits_per_digit == 3 ? 0x07 : 0x01; + #if defined(PICOFORMAT_HANDLE_HEX) + const char* chars = FLAGS render_in_lowercase ? pLowercaseNumberDigits : pUppercaseNumberDigits; + #elif defined(PICOFORMAT_HANDLE_OCT) + const char* chars = pOctalDigits; + #else + const char* chars = pBinaryDigits; + #endif // individual non-decimal formats + while (pDest < pEnd + && (pDest == pParamStarts + || val + || pDest - pParamStarts < whole_chars)) { + char ch; + if (pDest == pParamStarts || 0 != val) { // if first char or there's still meaningful digits + ch = chars[val & mask]; + val >>= bits_per_digit; + } else { + ch = FLAGS fill_zeros ? '0' : ' '; + } + *pDest++ = ch; + } + flip(pParamStarts, pDest); + } + break; + #endif // defined(PICOFORMAT_HANDLE_BIN) || defined(PICOFORMAT_HANDLE_OCT) || defined(PICOFORMAT_HANDLE_HEX) + case 'd': // decimal integer + case 'i': { + long long int val = 0; + if (FLAGS treat_as_long) { + if (FLAGS treat_as_unsigned) { + val = va_arg(vl, unsigned long long int); + } else { + val = va_arg(vl, long long int); + } + } else { + if (FLAGS treat_as_unsigned) { + val = va_arg(vl, unsigned); + } else { + val = va_arg(vl, int); + } + } + char chSign = '\0'; + if ((FLAGS force_sign || val < 0) && pDest < pEnd) { + chSign = val < 0 ? '-' : '+'; + val = llabs(val); + whole_chars--; + } + while (pDest < pEnd + && (pDest == pParamStarts + || val + || pDest - pParamStarts < whole_chars)) { + char ch; + if (pDest == pParamStarts || 0 != val) { // if first digit (i.e. zero) or there's still non-zero digits to write + ch = val % 10 + '0'; + val /= 10; + } else { + if ('\0' != chSign && !FLAGS fill_zeros) { // write a sign if filling with spaces, not with zeros + *pDest++ = chSign; + whole_chars++; + chSign = '\0'; // prevent the sign from being written twice + } + #ifdef PICOFORMAT_HANDLE_FILL + ch = FLAGS fill_zeros ? '0' : ' '; + #else // PICOFORMAT_HANDLE_FILL + break; + #endif // PICOFORMAT_HANDLE_FILL + } + *pDest++ = ch; + } + if ('\0' != chSign) { // write a sign if it wasn't written before + *pDest++ = chSign; + } + flip(pParamStarts, pDest); + } + break; + #ifdef PICOFORMAT_HANDLE_FLOATS + case 'f': case 'F': { + double val = va_arg(vl, double); + if (FLAGS force_sign || val < 0.f) { + *pDest++ = val < 0.f ? '-' : '+'; + val = fabs(val); + pParamStarts = pDest; + } + if (val == INFINITY || val == -INFINITY || isnan(val)) { + for (const char *pszVal = isnan(val) ? FLAGS render_in_lowercase ? "nan" : "NAN": FLAGS render_in_lowercase ? "inf" : "INF" + ; pDest < pEnd && *pszVal + ; *pDest++ = *pszVal++); + } else { + if (decimal_chars == -1) { + if (format == 'g') { + decimal_chars = 0; + } else { + decimal_chars = 6; + } + } + whole_chars = MAX(0, whole_chars - decimal_chars); + whole_chars = MAX(whole_chars, pDest - pParamStarts + 1); // at least sign (if present) and first char + for (float digit = 1.f + ; pDest < pEnd && (val >= digit || pDest - pParamStarts < whole_chars) + ; digit *= 10.f) { + char ch = (int)(val / digit) % 10 + '0'; + *pDest++ = ch; + } + flip(pParamStarts, pDest); + if (decimal_chars && pDest < pEnd) { + *pDest++ = '.'; + val += .5f * pow(10.f, -decimal_chars); // compensating for rounding error + for (size_t digit = 0; pDest < pEnd && digit < decimal_chars; digit++) { + val = (val - (int)(val)) * 10.f; + *pDest++ = (int)(val) + '0'; + } + } + } + } + break; + #endif // PICOFORMAT_HANDLE_FLOATS + } + } + } + } + *pDest = '\0'; + return pDest - pStart; +} + + +int pico_snprintf(char *pDest, size_t cbDest, const char *pFormat, ...) { + va_list vl; + va_start(vl, pFormat); + int result = pico_vsnprintf(pDest, cbDest, pFormat, vl); + va_end(vl); + return result; +} diff --git a/firmware/common/picoprintf.h b/firmware/common/picoprintf.h new file mode 100644 index 00000000..82796502 --- /dev/null +++ b/firmware/common/picoprintf.h @@ -0,0 +1,43 @@ +#ifndef __picoprintf_h_INCLUDED__ +#define __picoprintf_h_INCLUDED__ + +#include // size_t +#include // va_* + + +int pico_snprintf(char *pDest, size_t cbDest, const char *pFormat, ...); +int pico_vsnprintf(char *pDest, size_t cbDest, const char *pFormat, va_list vl); + +// PLEASE use `pico_snprintf()` instead!!! This function is vulnerable to buffer overflows +inline int pico_sprintf(char *pDest, const char *pFormat, ...) { + va_list vl; + va_start(vl, pFormat); + int result = pico_vsnprintf(pDest, -1, pFormat, vl); + va_end(vl); + return result; +} + + +// +// IMPORTANT!!! +// comment/uncomment the following lines corresponding to the features you need +// +// #define PICOFORMAT_HANDLE_FILL // uncomment this line to handle "%6i" and "%04d" -- the fill with zeroes or spaces +// #define PICOFORMAT_HANDLE_FORCEDSIGN // uncomment this line to handle "%+d" -- the forced sign placement +// #define PICOFORMAT_HANDLE_BIN // uncomment this line to handle "%b" -- binary representation +// #define PICOFORMAT_HANDLE_OCT // uncomment this line to handle "%o" +// #define PICOFORMAT_HANDLE_HEX // uncomment this line to handle "%x" and "%X" +// #define PICOFORMAT_HANDLE_FLOATS // uncomment this line to handle the "%f" +// #define PICOFORMAT_CLANG_QUIRK // uncomment this line to match clang's non-standard "%010s" behavior (zero-pad strings when both '0' flag and width are set) + + +// by default, the debug builds (determined by `#define _DEBUG`) will real-time print errors when a feature is used that is not enabled above +#ifndef FORMAT_ERROR_DELEGATE + #ifdef _DEBUG + #define FORMAT_ERROR_DELEGATE(__message, __arg) printf(__message, __arg); printf("\n"); + #else // _DEBUG + #define FORMAT_ERROR_DELEGATE(__message, __arg) + #endif // _DEBUG +#endif // FORMAT_ERROR_DELEGATE + +#endif // __picoprintf_h_INCLUDED__ diff --git a/firmware/hackrf_usb/CMakeLists.txt b/firmware/hackrf_usb/CMakeLists.txt index 3fd3ea87..dba0120e 100644 --- a/firmware/hackrf_usb/CMakeLists.txt +++ b/firmware/hackrf_usb/CMakeLists.txt @@ -136,6 +136,7 @@ if(BOARD STREQUAL "RAD1O") "${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/smallfonts.c" "${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/draw.c" "${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/ubuntu18.c" + "${PATH_HACKRF_FIRMWARE_COMMON}/picoprintf.c" "${PATH_HACKRF_FIRMWARE_COMMON}/ui_rad1o.c" ) endif() From 58334a565b2a93a5b33663732709512289f33471 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 28 Apr 2026 15:42:18 +0100 Subject: [PATCH 174/238] picoprintf: remove unnecessary picobool.h. We don't require workarounds for ancient C environments. --- firmware/common/picobool.h | 20 -------------------- firmware/common/picoprintf.c | 1 - 2 files changed, 21 deletions(-) delete mode 100644 firmware/common/picobool.h diff --git a/firmware/common/picobool.h b/firmware/common/picobool.h deleted file mode 100644 index 3f0324c8..00000000 --- a/firmware/common/picobool.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __picobool_h_INCLUDED__ -#define __picobool_h_INCLUDED__ - -// this file provides a bool type which might or might not be available on your platform - -#ifndef __cplusplus // C++: use standard bool - #ifndef __STDC_VERSION__ // Pre-C99: define bool manually - typedef unsigned char bool; - #define true 1 - #define false 0 - #elif __STDC_VERSION__ < 199901L // C90/C95: define bool manually - typedef unsigned char bool; - #define true 1 - #define false 0 - #else // C99+: use standard bool - #include - #endif -#endif - -#endif // __picobool_h_INCLUDED__ diff --git a/firmware/common/picoprintf.c b/firmware/common/picoprintf.c index 18ef565c..185ccdfb 100644 --- a/firmware/common/picoprintf.c +++ b/firmware/common/picoprintf.c @@ -1,5 +1,4 @@ #include "picoprintf.h" -#include "picobool.h" #include // fabs() #include // llabs() From 5b4392f609633877ac64b351a6aa362cf73cedb3 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 28 Apr 2026 15:44:09 +0100 Subject: [PATCH 175/238] picoprintf: add LICENSE text to source & header files. --- firmware/common/picoprintf.c | 23 +++++++++++++++++++++++ firmware/common/picoprintf.h | 22 ++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/firmware/common/picoprintf.c b/firmware/common/picoprintf.c index 185ccdfb..f71af487 100644 --- a/firmware/common/picoprintf.c +++ b/firmware/common/picoprintf.c @@ -1,3 +1,26 @@ +/* MIT License + * + * Copyright (c) 2023-2026 rom-p + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + #include "picoprintf.h" #include // fabs() diff --git a/firmware/common/picoprintf.h b/firmware/common/picoprintf.h index 82796502..96ac9b14 100644 --- a/firmware/common/picoprintf.h +++ b/firmware/common/picoprintf.h @@ -1,3 +1,25 @@ +/* + * Copyright (c) 2023-2026 rom-p + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + #ifndef __picoprintf_h_INCLUDED__ #define __picoprintf_h_INCLUDED__ From 83fd6a00a81dac8863423346788ecc35b848e725 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 28 Apr 2026 15:45:16 +0100 Subject: [PATCH 176/238] picoprintf: Fix unused variable warnings with GCC 15.2. --- firmware/common/picoprintf.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/firmware/common/picoprintf.c b/firmware/common/picoprintf.c index f71af487..64446c3c 100644 --- a/firmware/common/picoprintf.c +++ b/firmware/common/picoprintf.c @@ -23,9 +23,11 @@ #include "picoprintf.h" -#include // fabs() #include // llabs() +#ifdef PICOFORMAT_HANDLE_FLOATS + #include // fabs() +#endif static void flip(char *pLeft, char *pRight) { pRight--; @@ -49,10 +51,16 @@ static void flip(char *pLeft, char *pRight) { // returns the pointer to the null-terminating character of the filled string int pico_vsnprintf(char *pDest, size_t cbDest, const char *pFormat, va_list vl) { +#if defined(PICOFORMAT_HANDLE_BIN) || defined(PICOFORMAT_HANDLE_OCT) || defined(PICOFORMAT_HANDLE_HEX) const char *pLowercaseNumberDigits = "0123456789abcdef"; +#endif +#if defined(PICOFORMAT_HANDLE_HEX) const char *pUppercaseNumberDigits = "0123456789ABCDEF"; +#elif defined(PICOFORMAT_HANDLE_OCT) const char *pOctalDigits = pLowercaseNumberDigits; +#elif defined(PICOFORMAT_HANDLE_BIN) const char *pBinaryDigits = pLowercaseNumberDigits; +#endif char *pStart = pDest; for (char *pEnd = pDest + cbDest - 1; *pFormat && pDest < pEnd; ) { if (*pFormat != '%') { @@ -63,7 +71,9 @@ int pico_vsnprintf(char *pDest, size_t cbDest, const char *pFormat, va_list vl) *pDest++ = *pFormat++; } else { // first, collect the format char format = '\0'; + #if defined(PICOFORMAT_HANDLE_BIN) || defined(PICOFORMAT_HANDLE_OCT) || defined(PICOFORMAT_HANDLE_HEX) int bits_per_digit = 0; // valid in 'b', 'o', 'p' and 'x'/'X' modes only + #endif int whole_chars = 0; // number of chars in the whole part of the number int decimal_chars = -1; // if not specified, %f are rendered with 6, while %g are rendered with 0 #ifdef __aarch64__ // these platforms benefit from packing flags into a single variable @@ -82,12 +92,16 @@ int pico_vsnprintf(char *pDest, size_t cbDest, const char *pFormat, va_list vl) #else // other platforms do not benefit from struct packing unsigned force_sign = 0; unsigned fill_zeros = 0; + #ifdef PICOFORMAT_HANDLE_FILL unsigned left_align = 0; + #endif unsigned seen_period = 0; unsigned seen_numbers = 0; unsigned treat_as_unsigned = 0; unsigned treat_as_long = 0; + #if defined(PICOFORMAT_HANDLE_HEX) || defined(PICOFORMAT_HANDLE_FLOATS) unsigned render_in_lowercase = 0; + #endif #define FLAGS #endif // struct packing platforms for (; *pFormat && '\0' == format; pFormat++) { @@ -235,7 +249,7 @@ int pico_vsnprintf(char *pDest, size_t cbDest, const char *pFormat, va_list vl) const char* chars = FLAGS render_in_lowercase ? pLowercaseNumberDigits : pUppercaseNumberDigits; #elif defined(PICOFORMAT_HANDLE_OCT) const char* chars = pOctalDigits; - #else + #elif defined(PICOFORMAT_HANDLE_BIN) const char* chars = pBinaryDigits; #endif // individual non-decimal formats while (pDest < pEnd From a20da328ba03eb3f06aac33eda372f1e061e6d32 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 28 Apr 2026 15:45:57 +0100 Subject: [PATCH 177/238] picoprintf: use #pragma once. --- firmware/common/picoprintf.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/firmware/common/picoprintf.h b/firmware/common/picoprintf.h index 96ac9b14..0fb5438b 100644 --- a/firmware/common/picoprintf.h +++ b/firmware/common/picoprintf.h @@ -20,8 +20,7 @@ * SOFTWARE. */ -#ifndef __picoprintf_h_INCLUDED__ -#define __picoprintf_h_INCLUDED__ +#pragma once #include // size_t #include // va_* @@ -61,5 +60,3 @@ inline int pico_sprintf(char *pDest, const char *pFormat, ...) { #define FORMAT_ERROR_DELEGATE(__message, __arg) #endif // _DEBUG #endif // FORMAT_ERROR_DELEGATE - -#endif // __picoprintf_h_INCLUDED__ From f970722195856b5f910f393b8871becef6061d4f Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 28 Apr 2026 16:36:14 +0100 Subject: [PATCH 178/238] picoprintf: Standardize code style. --- firmware/common/picoprintf.c | 715 +++++++++++++++++++---------------- firmware/common/picoprintf.h | 38 +- 2 files changed, 404 insertions(+), 349 deletions(-) diff --git a/firmware/common/picoprintf.c b/firmware/common/picoprintf.c index 64446c3c..1959edb5 100644 --- a/firmware/common/picoprintf.c +++ b/firmware/common/picoprintf.c @@ -23,356 +23,411 @@ #include "picoprintf.h" -#include // llabs() +#include // llabs() #ifdef PICOFORMAT_HANDLE_FLOATS - #include // fabs() + #include // fabs() #endif -static void flip(char *pLeft, char *pRight) { - pRight--; - while (pLeft < pRight) { - char tmp = *pLeft; - *pLeft = *pRight; - *pRight = tmp; - pLeft++; - pRight--; - } +static void flip(char* pLeft, char* pRight) +{ + pRight--; + while (pLeft < pRight) { + char tmp = *pLeft; + *pLeft = *pRight; + *pRight = tmp; + pLeft++; + pRight--; + } } // using #define over `inline` for enabling porting to old C #if !defined(MIN) -#define MIN(left, right) (((left) < (right)) ? (left) : (right)) + #define MIN(left, right) (((left) < (right)) ? (left) : (right)) #endif #if !defined(MAX) -#define MAX(left, right) (((left) > (right)) ? (left) : (right)) + #define MAX(left, right) (((left) > (right)) ? (left) : (right)) #endif - // returns the pointer to the null-terminating character of the filled string -int pico_vsnprintf(char *pDest, size_t cbDest, const char *pFormat, va_list vl) { -#if defined(PICOFORMAT_HANDLE_BIN) || defined(PICOFORMAT_HANDLE_OCT) || defined(PICOFORMAT_HANDLE_HEX) - const char *pLowercaseNumberDigits = "0123456789abcdef"; +int pico_vsnprintf(char* pDest, size_t cbDest, const char* pFormat, va_list vl) +{ +#if defined(PICOFORMAT_HANDLE_BIN) || defined(PICOFORMAT_HANDLE_OCT) || \ + defined(PICOFORMAT_HANDLE_HEX) + const char* pLowercaseNumberDigits = "0123456789abcdef"; #endif #if defined(PICOFORMAT_HANDLE_HEX) - const char *pUppercaseNumberDigits = "0123456789ABCDEF"; + const char* pUppercaseNumberDigits = "0123456789ABCDEF"; #elif defined(PICOFORMAT_HANDLE_OCT) - const char *pOctalDigits = pLowercaseNumberDigits; + const char* pOctalDigits = pLowercaseNumberDigits; #elif defined(PICOFORMAT_HANDLE_BIN) - const char *pBinaryDigits = pLowercaseNumberDigits; + const char* pBinaryDigits = pLowercaseNumberDigits; #endif - char *pStart = pDest; - for (char *pEnd = pDest + cbDest - 1; *pFormat && pDest < pEnd; ) { - if (*pFormat != '%') { - *pDest++ = *pFormat++; - } else { // format starts here - pFormat++; // skipping the '%' - if (*pFormat == '%') { // unless it's indeed a '%' - *pDest++ = *pFormat++; - } else { // first, collect the format - char format = '\0'; - #if defined(PICOFORMAT_HANDLE_BIN) || defined(PICOFORMAT_HANDLE_OCT) || defined(PICOFORMAT_HANDLE_HEX) - int bits_per_digit = 0; // valid in 'b', 'o', 'p' and 'x'/'X' modes only - #endif - int whole_chars = 0; // number of chars in the whole part of the number - int decimal_chars = -1; // if not specified, %f are rendered with 6, while %g are rendered with 0 - #ifdef __aarch64__ // these platforms benefit from packing flags into a single variable - struct { - unsigned force_sign:1; - unsigned fill_zeros:1; - unsigned left_align:1; - unsigned seen_period:1; - unsigned seen_numbers:1; - unsigned treat_as_unsigned:1; - unsigned treat_as_long:1; - unsigned render_in_lowercase:1; - } flags = {0}; - #define FLAGS flags. + char* pStart = pDest; + for (char* pEnd = pDest + cbDest - 1; *pFormat && pDest < pEnd;) { + if (*pFormat != '%') { + *pDest++ = *pFormat++; + } else { // format starts here + pFormat++; // skipping the '%' + if (*pFormat == '%') { // unless it's indeed a '%' + *pDest++ = *pFormat++; + } else { // first, collect the format + char format = '\0'; +#if defined(PICOFORMAT_HANDLE_BIN) || defined(PICOFORMAT_HANDLE_OCT) || \ + defined(PICOFORMAT_HANDLE_HEX) + int bits_per_digit = + 0; // valid in 'b', 'o', 'p' and 'x'/'X' modes only +#endif + int whole_chars = + 0; // number of chars in the whole part of the number + int decimal_chars = + -1; // if not specified, %f are rendered with 6, while %g are rendered with 0 +#ifdef __aarch64__ // these platforms benefit from packing flags into a single variable + struct { + unsigned force_sign : 1; + unsigned fill_zeros : 1; + unsigned left_align : 1; + unsigned seen_period : 1; + unsigned seen_numbers : 1; + unsigned treat_as_unsigned : 1; + unsigned treat_as_long : 1; + unsigned render_in_lowercase : 1; + } flags = {0}; - #else // other platforms do not benefit from struct packing - unsigned force_sign = 0; - unsigned fill_zeros = 0; - #ifdef PICOFORMAT_HANDLE_FILL - unsigned left_align = 0; - #endif - unsigned seen_period = 0; - unsigned seen_numbers = 0; - unsigned treat_as_unsigned = 0; - unsigned treat_as_long = 0; - #if defined(PICOFORMAT_HANDLE_HEX) || defined(PICOFORMAT_HANDLE_FLOATS) - unsigned render_in_lowercase = 0; - #endif - #define FLAGS - #endif // struct packing platforms - for (; *pFormat && '\0' == format; pFormat++) { - switch (*pFormat) { - #ifdef PICOFORMAT_HANDLE_FORCEDSIGN - case '+': - FLAGS force_sign = 1; - break; - #endif // PICOFORMAT_HANDLE_FORCEDSIGN - #ifdef PICOFORMAT_HANDLE_FILL - case '-': // left-align flag - FLAGS left_align = 1; - break; - #endif // PICOFORMAT_HANDLE_FILL - case '0': - if (!FLAGS seen_numbers) { - FLAGS fill_zeros = 1; - break; - } - // fall through - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - *(FLAGS seen_period ? &decimal_chars : &whole_chars ) *= 10; - *(FLAGS seen_period ? &decimal_chars : &whole_chars) += *pFormat - '0'; - FLAGS seen_numbers = 1; - break; - case '.': - FLAGS seen_numbers = FLAGS seen_period = 1; - decimal_chars = 0; - break; - case '*': // dynamic width/precision: read value from arg list - *(FLAGS seen_period ? &decimal_chars : &whole_chars) = va_arg(vl, int); - FLAGS seen_numbers = 1; - break; - case 'l': // long modifier - FLAGS treat_as_long = 1; - break; - case 'u': // unsigned decimal integer - FLAGS treat_as_unsigned = 1; - format = 'd'; - break; - #ifdef PICOFORMAT_HANDLE_BIN - case 'b': - bits_per_digit = 0; - FLAGS treat_as_unsigned = 1; - format = 'b'; - break; - #endif // PICOFORMAT_HANDLE_BIN - #ifdef PICOFORMAT_HANDLE_OCT - case 'o': // octal integer - bits_per_digit = 3; - FLAGS treat_as_unsigned = 1; - format = 'b'; - break; - #endif // PICOFORMAT_HANDLE_OCT - #ifdef PICOFORMAT_HANDLE_HEX - case 'x': // hexadecimal integer - case 'p': // pointer - bits_per_digit = 4; - FLAGS treat_as_unsigned = 1; - FLAGS render_in_lowercase = 1; - format = 'b'; - break; - case 'X': // hexadecimal integer, uppercase - bits_per_digit = 4; - FLAGS treat_as_unsigned = 1; - format = 'b'; - break; - #endif // PICOFORMAT_HANDLE_HEX - #ifdef PICOFORMAT_HANDLE_FLOATS - case 'a': - #ifdef PICOFORMAT_HANDLE_EXPONENTS - case 'e': // floating point, exponent format - #endif // PICOFORMAT_HANDLE_EXPONENTS - case 'f': - FLAGS render_in_lowercase = 1; - // fall through - case 'F': - #endif // PICOFORMAT_HANDLE_FLOATS - case 'c': // single char: always supported - case 'd': // integer: always supported - case 'i': // integer: always supported - case 's': // string of native `char`s: always supported - format = *pFormat; - break; - default: - FORMAT_ERROR_DELEGATE("detected unhandled format specifier: %c", *pFormat); - break; - } - } + #define FLAGS flags. - // format is parsed, now render the value - char *pParamStarts = pDest; - switch (format) { - case 'c': // single char - *pDest++ = va_arg(vl, int) & 0xff; - break; - case 's': { // null-terminated string - #ifdef PICOFORMAT_HANDLE_FILL - int len = 0; // effective length, bounded by precision if set - const char *pStr = va_arg(vl, const char*); - for (; pStr[len] && (decimal_chars < 0 || len < decimal_chars); len++); - if (!FLAGS left_align) { // right-align: pad on the left - #ifdef PICOFORMAT_CLANG_QUIRK // clang's non-standard: '0' flag zero-pads strings - char chFill = FLAGS fill_zeros ? '0' : ' '; - #else // PICOFORMAT_CLANG_QUIRK // standard C: '0' flag is undefined for %s, use spaces - char chFill = ' '; - #endif // PICOFORMAT_CLANG_QUIRK - for (; pDest < pEnd && whole_chars > len; whole_chars--) { - *pDest++ = chFill; - } - } - for (int ii = 0; ii < len && pDest < pEnd; ii++) { - *pDest++ = pStr[ii]; - } - if (FLAGS left_align) { // left-align: pad on the right (always spaces; '-' flag overrides '0') - for (; pDest < pEnd && whole_chars > len; whole_chars--) { - *pDest++ = ' '; - } - } - #else // PICOFORMAT_HANDLE_FILL - for (const char *pStr = va_arg(vl, const char*); *pStr && pDest < pEnd; ) { - *pDest++ = *pStr++; - } - #endif // PICOFORMAT_HANDLE_FILL - } - break; - #if defined(PICOFORMAT_HANDLE_HEX) || defined(PICOFORMAT_HANDLE_OCT) || defined(PICOFORMAT_HANDLE_BIN) - case 'b': { // binary, oct, or hex integer, always unsigned - long long int val = 0; - if (FLAGS treat_as_long) { - val = va_arg(vl, unsigned long long int); - } else { - val = va_arg(vl, unsigned); - } - unsigned mask = bits_per_digit == 4 ? 0x0f : bits_per_digit == 3 ? 0x07 : 0x01; - #if defined(PICOFORMAT_HANDLE_HEX) - const char* chars = FLAGS render_in_lowercase ? pLowercaseNumberDigits : pUppercaseNumberDigits; - #elif defined(PICOFORMAT_HANDLE_OCT) - const char* chars = pOctalDigits; - #elif defined(PICOFORMAT_HANDLE_BIN) - const char* chars = pBinaryDigits; - #endif // individual non-decimal formats - while (pDest < pEnd - && (pDest == pParamStarts - || val - || pDest - pParamStarts < whole_chars)) { - char ch; - if (pDest == pParamStarts || 0 != val) { // if first char or there's still meaningful digits - ch = chars[val & mask]; - val >>= bits_per_digit; - } else { - ch = FLAGS fill_zeros ? '0' : ' '; - } - *pDest++ = ch; - } - flip(pParamStarts, pDest); - } - break; - #endif // defined(PICOFORMAT_HANDLE_BIN) || defined(PICOFORMAT_HANDLE_OCT) || defined(PICOFORMAT_HANDLE_HEX) - case 'd': // decimal integer - case 'i': { - long long int val = 0; - if (FLAGS treat_as_long) { - if (FLAGS treat_as_unsigned) { - val = va_arg(vl, unsigned long long int); - } else { - val = va_arg(vl, long long int); - } - } else { - if (FLAGS treat_as_unsigned) { - val = va_arg(vl, unsigned); - } else { - val = va_arg(vl, int); - } - } - char chSign = '\0'; - if ((FLAGS force_sign || val < 0) && pDest < pEnd) { - chSign = val < 0 ? '-' : '+'; - val = llabs(val); - whole_chars--; - } - while (pDest < pEnd - && (pDest == pParamStarts - || val - || pDest - pParamStarts < whole_chars)) { - char ch; - if (pDest == pParamStarts || 0 != val) { // if first digit (i.e. zero) or there's still non-zero digits to write - ch = val % 10 + '0'; - val /= 10; - } else { - if ('\0' != chSign && !FLAGS fill_zeros) { // write a sign if filling with spaces, not with zeros - *pDest++ = chSign; - whole_chars++; - chSign = '\0'; // prevent the sign from being written twice - } - #ifdef PICOFORMAT_HANDLE_FILL - ch = FLAGS fill_zeros ? '0' : ' '; - #else // PICOFORMAT_HANDLE_FILL - break; - #endif // PICOFORMAT_HANDLE_FILL - } - *pDest++ = ch; - } - if ('\0' != chSign) { // write a sign if it wasn't written before - *pDest++ = chSign; - } - flip(pParamStarts, pDest); - } - break; - #ifdef PICOFORMAT_HANDLE_FLOATS - case 'f': case 'F': { - double val = va_arg(vl, double); - if (FLAGS force_sign || val < 0.f) { - *pDest++ = val < 0.f ? '-' : '+'; - val = fabs(val); - pParamStarts = pDest; - } - if (val == INFINITY || val == -INFINITY || isnan(val)) { - for (const char *pszVal = isnan(val) ? FLAGS render_in_lowercase ? "nan" : "NAN": FLAGS render_in_lowercase ? "inf" : "INF" - ; pDest < pEnd && *pszVal - ; *pDest++ = *pszVal++); - } else { - if (decimal_chars == -1) { - if (format == 'g') { - decimal_chars = 0; - } else { - decimal_chars = 6; - } - } - whole_chars = MAX(0, whole_chars - decimal_chars); - whole_chars = MAX(whole_chars, pDest - pParamStarts + 1); // at least sign (if present) and first char - for (float digit = 1.f - ; pDest < pEnd && (val >= digit || pDest - pParamStarts < whole_chars) - ; digit *= 10.f) { - char ch = (int)(val / digit) % 10 + '0'; - *pDest++ = ch; - } - flip(pParamStarts, pDest); - if (decimal_chars && pDest < pEnd) { - *pDest++ = '.'; - val += .5f * pow(10.f, -decimal_chars); // compensating for rounding error - for (size_t digit = 0; pDest < pEnd && digit < decimal_chars; digit++) { - val = (val - (int)(val)) * 10.f; - *pDest++ = (int)(val) + '0'; - } - } - } - } - break; - #endif // PICOFORMAT_HANDLE_FLOATS - } - } - } - } - *pDest = '\0'; - return pDest - pStart; +#else // other platforms do not benefit from struct packing + unsigned force_sign = 0; + unsigned fill_zeros = 0; + #ifdef PICOFORMAT_HANDLE_FILL + unsigned left_align = 0; + #endif + unsigned seen_period = 0; + unsigned seen_numbers = 0; + unsigned treat_as_unsigned = 0; + unsigned treat_as_long = 0; + #if defined(PICOFORMAT_HANDLE_HEX) || defined(PICOFORMAT_HANDLE_FLOATS) + unsigned render_in_lowercase = 0; + #endif + #define FLAGS +#endif // struct packing platforms + for (; *pFormat && '\0' == format; pFormat++) { + switch (*pFormat) { +#ifdef PICOFORMAT_HANDLE_FORCEDSIGN + case '+': + FLAGS force_sign = 1; + break; +#endif // PICOFORMAT_HANDLE_FORCEDSIGN +#ifdef PICOFORMAT_HANDLE_FILL + case '-': // left-align flag + FLAGS left_align = 1; + break; +#endif // PICOFORMAT_HANDLE_FILL + case '0': + if (!FLAGS seen_numbers) { + FLAGS fill_zeros = 1; + break; + } + // fall through + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + *(FLAGS seen_period ? &decimal_chars : + &whole_chars) *= 10; + *(FLAGS seen_period ? &decimal_chars : + &whole_chars) += + *pFormat - '0'; + FLAGS seen_numbers = 1; + break; + case '.': + FLAGS seen_numbers = FLAGS seen_period = + 1; + decimal_chars = 0; + break; + case '*': // dynamic width/precision: read value from arg list + *(FLAGS seen_period ? &decimal_chars : + &whole_chars) = + va_arg(vl, int); + FLAGS seen_numbers = 1; + break; + case 'l': // long modifier + FLAGS treat_as_long = 1; + break; + case 'u': // unsigned decimal integer + FLAGS treat_as_unsigned = 1; + format = 'd'; + break; +#ifdef PICOFORMAT_HANDLE_BIN + case 'b': + bits_per_digit = 0; + FLAGS treat_as_unsigned = 1; + format = 'b'; + break; +#endif // PICOFORMAT_HANDLE_BIN +#ifdef PICOFORMAT_HANDLE_OCT + case 'o': // octal integer + bits_per_digit = 3; + FLAGS treat_as_unsigned = 1; + format = 'b'; + break; +#endif // PICOFORMAT_HANDLE_OCT +#ifdef PICOFORMAT_HANDLE_HEX + case 'x': // hexadecimal integer + case 'p': // pointer + bits_per_digit = 4; + FLAGS treat_as_unsigned = 1; + FLAGS render_in_lowercase = 1; + format = 'b'; + break; + case 'X': // hexadecimal integer, uppercase + bits_per_digit = 4; + FLAGS treat_as_unsigned = 1; + format = 'b'; + break; +#endif // PICOFORMAT_HANDLE_HEX +#ifdef PICOFORMAT_HANDLE_FLOATS + case 'a': + #ifdef PICOFORMAT_HANDLE_EXPONENTS + case 'e': // floating point, exponent format + #endif // PICOFORMAT_HANDLE_EXPONENTS + case 'f': + FLAGS render_in_lowercase = 1; + // fall through + case 'F': +#endif // PICOFORMAT_HANDLE_FLOATS + case 'c': // single char: always supported + case 'd': // integer: always supported + case 'i': // integer: always supported + case 's': // string of native `char`s: always supported + format = *pFormat; + break; + default: + FORMAT_ERROR_DELEGATE( + "detected unhandled format specifier: %c", + *pFormat); + break; + } + } + + // format is parsed, now render the value + char* pParamStarts = pDest; + switch (format) { + case 'c': // single char + *pDest++ = va_arg(vl, int) & 0xff; + break; + case 's': { // null-terminated string +#ifdef PICOFORMAT_HANDLE_FILL + int len = + 0; // effective length, bounded by precision if set + const char* pStr = va_arg(vl, const char*); + for (; pStr[len] && + (decimal_chars < 0 || len < decimal_chars); + len++) + ; + if (!FLAGS left_align) { // right-align: pad on the left + #ifdef PICOFORMAT_CLANG_QUIRK // clang's non-standard: '0' flag zero-pads strings + char chFill = + FLAGS fill_zeros ? '0' : ' '; + #else // PICOFORMAT_CLANG_QUIRK // standard C: '0' flag is undefined for %s, use spaces + char chFill = ' '; + #endif // PICOFORMAT_CLANG_QUIRK + for (; pDest < pEnd && whole_chars > len; + whole_chars--) { + *pDest++ = chFill; + } + } + for (int ii = 0; ii < len && pDest < pEnd; ii++) { + *pDest++ = pStr[ii]; + } + if (FLAGS left_align) { // left-align: pad on the right (always spaces; '-' flag overrides '0') + for (; pDest < pEnd && whole_chars > len; + whole_chars--) { + *pDest++ = ' '; + } + } +#else // PICOFORMAT_HANDLE_FILL + for (const char* pStr = va_arg(vl, const char*); + *pStr && pDest < pEnd;) { + *pDest++ = *pStr++; + } +#endif // PICOFORMAT_HANDLE_FILL + } break; +#if defined(PICOFORMAT_HANDLE_HEX) || defined(PICOFORMAT_HANDLE_OCT) || \ + defined(PICOFORMAT_HANDLE_BIN) + case 'b': { // binary, oct, or hex integer, always unsigned + long long int val = 0; + if (FLAGS treat_as_long) { + val = va_arg(vl, unsigned long long int); + } else { + val = va_arg(vl, unsigned); + } + unsigned mask = bits_per_digit == 4 ? 0x0f : + bits_per_digit == 3 ? 0x07 : + 0x01; + #if defined(PICOFORMAT_HANDLE_HEX) + const char* chars = FLAGS render_in_lowercase ? + pLowercaseNumberDigits : + pUppercaseNumberDigits; + #elif defined(PICOFORMAT_HANDLE_OCT) + const char* chars = pOctalDigits; + #elif defined(PICOFORMAT_HANDLE_BIN) + const char* chars = pBinaryDigits; + #endif // individual non-decimal formats + while (pDest < pEnd && + (pDest == pParamStarts || val || + pDest - pParamStarts < whole_chars)) { + char ch; + if (pDest == pParamStarts || + 0 != val) { // if first char or there's still meaningful digits + ch = chars[val & mask]; + val >>= bits_per_digit; + } else { + ch = FLAGS fill_zeros ? '0' : ' '; + } + *pDest++ = ch; + } + flip(pParamStarts, pDest); + } break; +#endif // defined(PICOFORMAT_HANDLE_BIN) || defined(PICOFORMAT_HANDLE_OCT) || defined(PICOFORMAT_HANDLE_HEX) + case 'd': // decimal integer + case 'i': { + long long int val = 0; + if (FLAGS treat_as_long) { + if (FLAGS treat_as_unsigned) { + val = va_arg( + vl, + unsigned long long int); + } else { + val = va_arg(vl, long long int); + } + } else { + if (FLAGS treat_as_unsigned) { + val = va_arg(vl, unsigned); + } else { + val = va_arg(vl, int); + } + } + char chSign = '\0'; + if ((FLAGS force_sign || val < 0) && + pDest < pEnd) { + chSign = val < 0 ? '-' : '+'; + val = llabs(val); + whole_chars--; + } + while (pDest < pEnd && + (pDest == pParamStarts || val || + pDest - pParamStarts < whole_chars)) { + char ch; + if (pDest == pParamStarts || + 0 != val) { // if first digit (i.e. zero) or there's still non-zero digits to write + ch = val % 10 + '0'; + val /= 10; + } else { + if ('\0' != chSign && + !FLAGS fill_zeros) { // write a sign if filling with spaces, not with zeros + *pDest++ = chSign; + whole_chars++; + chSign = + '\0'; // prevent the sign from being written twice + } +#ifdef PICOFORMAT_HANDLE_FILL + ch = FLAGS fill_zeros ? '0' : ' '; +#else // PICOFORMAT_HANDLE_FILL + break; +#endif // PICOFORMAT_HANDLE_FILL + } + *pDest++ = ch; + } + if ('\0' != + chSign) { // write a sign if it wasn't written before + *pDest++ = chSign; + } + flip(pParamStarts, pDest); + } break; +#ifdef PICOFORMAT_HANDLE_FLOATS + case 'f': + case 'F': { + double val = va_arg(vl, double); + if (FLAGS force_sign || val < 0.f) { + *pDest++ = val < 0.f ? '-' : '+'; + val = fabs(val); + pParamStarts = pDest; + } + if (val == INFINITY || val == -INFINITY || + isnan(val)) { + for (const char* pszVal = isnan(val) ? + FLAGS render_in_lowercase ? + "nan" : + "NAN" : + FLAGS render_in_lowercase ? + "inf" : + "INF"; + pDest < pEnd && *pszVal; + *pDest++ = *pszVal++) + ; + } else { + if (decimal_chars == -1) { + if (format == 'g') { + decimal_chars = 0; + } else { + decimal_chars = 6; + } + } + whole_chars = + MAX(0, + whole_chars - decimal_chars); + whole_chars = MAX( + whole_chars, + pDest - pParamStarts + + 1); // at least sign (if present) and first char + for (float digit = 1.f; pDest < pEnd && + (val >= digit || + pDest - pParamStarts < whole_chars); + digit *= 10.f) { + char ch = + (int) (val / digit) % 10 + + '0'; + *pDest++ = ch; + } + flip(pParamStarts, pDest); + if (decimal_chars && pDest < pEnd) { + *pDest++ = '.'; + val += .5f * + pow(10.f, + -decimal_chars); // compensating for rounding error + for (size_t digit = 0; + pDest < pEnd && + digit < decimal_chars; + digit++) { + val = (val - + (int) (val)) * + 10.f; + *pDest++ = + (int) (val) + '0'; + } + } + } + } break; +#endif // PICOFORMAT_HANDLE_FLOATS + } + } + } + } + *pDest = '\0'; + return pDest - pStart; } - -int pico_snprintf(char *pDest, size_t cbDest, const char *pFormat, ...) { - va_list vl; - va_start(vl, pFormat); - int result = pico_vsnprintf(pDest, cbDest, pFormat, vl); - va_end(vl); - return result; +int pico_snprintf(char* pDest, size_t cbDest, const char* pFormat, ...) +{ + va_list vl; + va_start(vl, pFormat); + int result = pico_vsnprintf(pDest, cbDest, pFormat, vl); + va_end(vl); + return result; } diff --git a/firmware/common/picoprintf.h b/firmware/common/picoprintf.h index 0fb5438b..aadb27ea 100644 --- a/firmware/common/picoprintf.h +++ b/firmware/common/picoprintf.h @@ -22,23 +22,22 @@ #pragma once -#include // size_t -#include // va_* +#include // size_t +#include // va_* - -int pico_snprintf(char *pDest, size_t cbDest, const char *pFormat, ...); -int pico_vsnprintf(char *pDest, size_t cbDest, const char *pFormat, va_list vl); +int pico_snprintf(char* pDest, size_t cbDest, const char* pFormat, ...); +int pico_vsnprintf(char* pDest, size_t cbDest, const char* pFormat, va_list vl); // PLEASE use `pico_snprintf()` instead!!! This function is vulnerable to buffer overflows -inline int pico_sprintf(char *pDest, const char *pFormat, ...) { - va_list vl; - va_start(vl, pFormat); - int result = pico_vsnprintf(pDest, -1, pFormat, vl); - va_end(vl); - return result; +inline int pico_sprintf(char* pDest, const char* pFormat, ...) +{ + va_list vl; + va_start(vl, pFormat); + int result = pico_vsnprintf(pDest, -1, pFormat, vl); + va_end(vl); + return result; } - // // IMPORTANT!!! // comment/uncomment the following lines corresponding to the features you need @@ -51,12 +50,13 @@ inline int pico_sprintf(char *pDest, const char *pFormat, ...) { // #define PICOFORMAT_HANDLE_FLOATS // uncomment this line to handle the "%f" // #define PICOFORMAT_CLANG_QUIRK // uncomment this line to match clang's non-standard "%010s" behavior (zero-pad strings when both '0' flag and width are set) - // by default, the debug builds (determined by `#define _DEBUG`) will real-time print errors when a feature is used that is not enabled above #ifndef FORMAT_ERROR_DELEGATE - #ifdef _DEBUG - #define FORMAT_ERROR_DELEGATE(__message, __arg) printf(__message, __arg); printf("\n"); - #else // _DEBUG - #define FORMAT_ERROR_DELEGATE(__message, __arg) - #endif // _DEBUG -#endif // FORMAT_ERROR_DELEGATE + #ifdef _DEBUG + #define FORMAT_ERROR_DELEGATE(__message, __arg) \ + printf(__message, __arg); \ + printf("\n"); + #else // _DEBUG + #define FORMAT_ERROR_DELEGATE(__message, __arg) + #endif // _DEBUG +#endif // FORMAT_ERROR_DELEGATE From ec1ff486b44e3c7f9a69aa293b0f5a6642047087 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 28 Apr 2026 15:22:06 +0100 Subject: [PATCH 179/238] picoprintf: Enable additional features. --- firmware/common/picoprintf.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/common/picoprintf.h b/firmware/common/picoprintf.h index aadb27ea..313ee91d 100644 --- a/firmware/common/picoprintf.h +++ b/firmware/common/picoprintf.h @@ -42,11 +42,11 @@ inline int pico_sprintf(char* pDest, const char* pFormat, ...) // IMPORTANT!!! // comment/uncomment the following lines corresponding to the features you need // -// #define PICOFORMAT_HANDLE_FILL // uncomment this line to handle "%6i" and "%04d" -- the fill with zeroes or spaces +#define PICOFORMAT_HANDLE_FILL // uncomment this line to handle "%6i" and "%04d" -- the fill with zeroes or spaces // #define PICOFORMAT_HANDLE_FORCEDSIGN // uncomment this line to handle "%+d" -- the forced sign placement // #define PICOFORMAT_HANDLE_BIN // uncomment this line to handle "%b" -- binary representation // #define PICOFORMAT_HANDLE_OCT // uncomment this line to handle "%o" -// #define PICOFORMAT_HANDLE_HEX // uncomment this line to handle "%x" and "%X" +#define PICOFORMAT_HANDLE_HEX // uncomment this line to handle "%x" and "%X" // #define PICOFORMAT_HANDLE_FLOATS // uncomment this line to handle the "%f" // #define PICOFORMAT_CLANG_QUIRK // uncomment this line to match clang's non-standard "%010s" behavior (zero-pad strings when both '0' flag and width are set) From f73c2b8e6a4ab1666fa387e82994fe24f2bfb842 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 30 Apr 2026 14:44:29 +0100 Subject: [PATCH 180/238] rad1o: Add formatting support to rad1o_lcdPrint. --- firmware/common/rad1o/print.c | 18 ++++++++++++++++-- firmware/common/rad1o/print.h | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/firmware/common/rad1o/print.c b/firmware/common/rad1o/print.c index d279f4e7..345af5e0 100644 --- a/firmware/common/rad1o/print.c +++ b/firmware/common/rad1o/print.c @@ -1,5 +1,11 @@ #include "print.h" +#include +#include +#include + +#include + #include "display.h" #include "render.h" #include "smallfonts.h" @@ -7,9 +13,17 @@ static int32_t x = 0; static int32_t y = 0; -void rad1o_lcdPrint(const char* string) +void rad1o_lcdPrint(const char* fmt, ...) { - x = rad1o_DoString(x, y, string); + va_list args1, args2; + va_start(args1, fmt); + va_copy(args2, args1); + int buflen = pico_vsnprintf(NULL, 0, fmt, args1) + 1; + va_end(args1); + char* buf = alloca(buflen); + pico_vsnprintf(buf, buflen, fmt, args2); + va_end(args2); + x = rad1o_DoString(x, y, buf); } void rad1o_lcdNl(void) diff --git a/firmware/common/rad1o/print.h b/firmware/common/rad1o/print.h index 8981da25..858f1b22 100644 --- a/firmware/common/rad1o/print.h +++ b/firmware/common/rad1o/print.h @@ -2,7 +2,7 @@ #include -void rad1o_lcdPrint(const char* string); +void rad1o_lcdPrint(const char* string, ...); void rad1o_lcdNl(void); void rad1o_lcdClear(void); void rad1o_lcdMoveCrsr(int32_t dx, int32_t dy); From 9688caaf1c3aa0de92d6bac6d611af46bbaa73ff Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 30 Apr 2026 14:45:27 +0100 Subject: [PATCH 181/238] ui_rad1o: Eliminate use of sprintf. --- firmware/common/ui_rad1o.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/firmware/common/ui_rad1o.c b/firmware/common/ui_rad1o.c index 8df630bd..a157b6ef 100644 --- a/firmware/common/ui_rad1o.c +++ b/firmware/common/ui_rad1o.c @@ -24,7 +24,6 @@ #include #include -#include #include "clock_gen.h" #include "drivers.h" @@ -60,22 +59,20 @@ static bool enabled = false; #define DIV_ROUND_CLOSEST(n, d) ((n + (d / 2)) / d) -static void print_hz(char* tmp, char* fmt, uint64_t hz) +static void print_hz(char* fmt, uint64_t hz) { uint32_t mhz, khz; mhz = DIV_ROUND_CLOSEST(hz, 1000000); hz -= mhz * 1000000; khz = DIV_ROUND_CLOSEST(hz, 1000); - sprintf(tmp, fmt, (unsigned int) mhz, (unsigned int) khz); - rad1o_lcdPrint(tmp); + rad1o_lcdPrint(fmt, (unsigned int) mhz, (unsigned int) khz); } static void draw_frequency(void) { - char tmp[100]; rad1o_setTextColor(BLACK, GREEN); rad1o_setIntFont(&Font_Ubuntu18pt); - print_hz(tmp, "%4u.%03u", freq); + print_hz("%4u.%03u", freq); rad1o_setIntFont(&Font_7x8); rad1o_lcdMoveCrsr(1, 18 - 7); rad1o_lcdPrint("MHz"); @@ -115,8 +112,6 @@ static void draw_tx_rx(void) static void ui_update(void) { - char tmp[100]; - if (!enabled) { return; } @@ -156,12 +151,12 @@ static void ui_update(void) rad1o_setTextColor(BLACK, WHITE); rad1o_lcdSetCrsr(2, 71); rad1o_lcdPrint("Rate: "); - print_hz(tmp, "%2u.%03u MHz", sample_rate); + print_hz("%2u.%03u MHz", sample_rate); rad1o_lcdNl(); rad1o_lcdMoveCrsr(2, 0); rad1o_lcdPrint("Filter: "); - print_hz(tmp, "%2u.%03u MHz", filter_bw); + print_hz("%2u.%03u MHz", filter_bw); rad1o_lcdNl(); rad1o_drawHLine(88, 0, RESX - 1, WHITE); @@ -185,8 +180,7 @@ static void ui_update(void) if (direction == RF_PATH_DIRECTION_TX) { rad1o_setTextColor(BLACK, RED); } - sprintf(tmp, " TX: %u dB", (unsigned int) bbtxvga_gain); - rad1o_lcdPrint(tmp); + rad1o_lcdPrint(" TX: %u dB", (unsigned int) bbtxvga_gain); rad1o_lcdNl(); rad1o_lcdMoveCrsr(2, 0); @@ -194,12 +188,10 @@ static void ui_update(void) if (direction == RF_PATH_DIRECTION_RX) { rad1o_setTextColor(BLACK, GREEN); } - sprintf(tmp, "LNA: %2u dB", (unsigned int) bblna_gain); - rad1o_lcdPrint(tmp); + rad1o_lcdPrint("LNA: %2u dB", (unsigned int) bblna_gain); rad1o_lcdNl(); rad1o_lcdMoveCrsr(2, 0); - sprintf(tmp, "VGA: %2u dB", (unsigned int) bbvga_gain); - rad1o_lcdPrint(tmp); + rad1o_lcdPrint("VGA: %2u dB", (unsigned int) bbvga_gain); rad1o_lcdNl(); rad1o_lcdDisplay(); From 90ab84ba28be0e32b99af42e663d78f0445ff1a8 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 30 Apr 2026 16:24:25 +0200 Subject: [PATCH 182/238] firmware: move jtag_cpld driver instance to cpld_jtag.x --- firmware/common/cpld_jtag.c | 7 +++++++ firmware/common/cpld_jtag.h | 4 ++++ firmware/common/drivers.c | 6 ------ firmware/common/drivers.h | 3 --- firmware/common/pins.c | 3 ++- firmware/common/portapack.c | 1 - firmware/hackrf-common.cmake | 1 + firmware/hackrf_usb/CMakeLists.txt | 1 - firmware/hackrf_usb/hackrf_usb.c | 1 - firmware/hackrf_usb/usb_api_cpld.c | 1 - 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/firmware/common/cpld_jtag.c b/firmware/common/cpld_jtag.c index 034ba196..92f89f27 100644 --- a/firmware/common/cpld_jtag.c +++ b/firmware/common/cpld_jtag.c @@ -34,6 +34,13 @@ static uint32_t xsvf_buffer_len, xsvf_pos; static unsigned char* xsvf_buffer; #endif +/* Driver instance. */ +jtag_gpio_t jtag_gpio_cpld = {}; + +jtag_t jtag_cpld = { + .gpio = &jtag_gpio_cpld, +}; + void cpld_jtag_take(jtag_t* const jtag) { const jtag_gpio_t* const gpio = jtag->gpio; diff --git a/firmware/common/cpld_jtag.h b/firmware/common/cpld_jtag.h index 0994c858..14f70437 100644 --- a/firmware/common/cpld_jtag.h +++ b/firmware/common/cpld_jtag.h @@ -59,3 +59,7 @@ int cpld_jtag_program( unsigned char* const buffer, refill_buffer_cb refill); unsigned char cpld_jtag_get_next_byte(void); + +/* Driver instance. */ +extern jtag_gpio_t jtag_gpio_cpld; +extern jtag_t jtag_cpld; diff --git a/firmware/common/drivers.c b/firmware/common/drivers.c index 58b30cb2..1444534c 100644 --- a/firmware/common/drivers.c +++ b/firmware/common/drivers.c @@ -45,12 +45,6 @@ fpga_driver_t fpga = { }; #endif -jtag_gpio_t jtag_gpio_cpld = {}; - -jtag_t jtag_cpld = { - .gpio = &jtag_gpio_cpld, -}; - #ifdef IS_PRALINE void ssp1_set_mode_ice40(void) { diff --git a/firmware/common/drivers.h b/firmware/common/drivers.h index d0427e93..1fe7d72c 100644 --- a/firmware/common/drivers.h +++ b/firmware/common/drivers.h @@ -25,7 +25,6 @@ extern "C" { #endif -#include "cpld_jtag.h" #include "platform_detect.h" // IWYU pragma: keep #if defined(IS_PRALINE) #include "fpga.h" @@ -38,8 +37,6 @@ extern ssp_config_t ssp_config_ice40_fpga; extern ice40_spi_driver_t ice40; extern fpga_driver_t fpga; #endif -extern jtag_gpio_t jtag_gpio_cpld; -extern jtag_t jtag_cpld; #if defined(IS_PRALINE) void ssp1_set_mode_ice40(void); diff --git a/firmware/common/pins.c b/firmware/common/pins.c index 24aeb033..f695d1ef 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -26,7 +26,7 @@ #include #include -#include "drivers.h" +#include "cpld_jtag.h" #include "gpio.h" #include "leds.h" #include "max283x.h" @@ -41,6 +41,7 @@ #include "w25q80bv.h" #if defined(IS_PRALINE) #include "clock_io.h" + #include "drivers.h" #endif void pins_shutdown(void) diff --git a/firmware/common/portapack.c b/firmware/common/portapack.c index f25a4a6e..d3d848fc 100644 --- a/firmware/common/portapack.c +++ b/firmware/common/portapack.c @@ -26,7 +26,6 @@ #include "cpld_jtag.h" #include "delay.h" -#include "drivers.h" #include "gpio.h" #include "gpio_lpc.h" #include "platform_gpio.h" diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 04d8b1a3..d31cd6c0 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -172,6 +172,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/power.c ${PATH_HACKRF_FIRMWARE_COMMON}/cpu_clock.c ${PATH_HACKRF_FIRMWARE_COMMON}/delay.c + ${PATH_HACKRF_FIRMWARE_COMMON}/cpld_jtag.c ${PATH_HACKRF_FIRMWARE_COMMON}/pins.c ${PATH_HACKRF_FIRMWARE_COMMON}/leds.c ${PATH_HACKRF_FIRMWARE_COMMON}/sgpio.c diff --git a/firmware/hackrf_usb/CMakeLists.txt b/firmware/hackrf_usb/CMakeLists.txt index 3fd3ea87..fe392f49 100644 --- a/firmware/hackrf_usb/CMakeLists.txt +++ b/firmware/hackrf_usb/CMakeLists.txt @@ -66,7 +66,6 @@ set(SRC_M4 usb_api_adc.c "${PATH_HACKRF_FIRMWARE_COMMON}/usb_queue.c" "${PATH_HACKRF_FIRMWARE_COMMON}/fault_handler.c" - "${PATH_HACKRF_FIRMWARE_COMMON}/cpld_jtag.c" "${PATH_HACKRF_FIRMWARE_COMMON}/crc.c" "${PATH_HACKRF_FIRMWARE_COMMON}/rom_iap.c" "${PATH_HACKRF_FIRMWARE_COMMON}/operacake.c" diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 031f2001..7419d063 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -70,7 +70,6 @@ #ifdef IS_NOT_PRALINE #include #include - #include #endif #include "usb_api_adc.h" diff --git a/firmware/hackrf_usb/usb_api_cpld.c b/firmware/hackrf_usb/usb_api_cpld.c index ed2beeda..391b9366 100644 --- a/firmware/hackrf_usb/usb_api_cpld.c +++ b/firmware/hackrf_usb/usb_api_cpld.c @@ -29,7 +29,6 @@ #include #include -#include #include #include #include From d0f61abcd791a792428b765a3c01540acc28ecbb Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 30 Apr 2026 16:31:14 +0200 Subject: [PATCH 183/238] firmware: move ice40 driver instance to ice40_spi.x --- firmware/common/drivers.c | 20 -------------------- firmware/common/drivers.h | 8 -------- firmware/common/fpga.c | 1 - firmware/common/fpga_image.c | 1 - firmware/common/ice40_spi.c | 17 +++++++++++++++++ firmware/common/ice40_spi.h | 6 ++++++ firmware/common/pins.c | 2 +- 7 files changed, 24 insertions(+), 31 deletions(-) diff --git a/firmware/common/drivers.c b/firmware/common/drivers.c index 1444534c..65ca10a9 100644 --- a/firmware/common/drivers.c +++ b/firmware/common/drivers.c @@ -22,32 +22,12 @@ #include "drivers.h" #if defined(IS_PRALINE) - #include #include "fpga.h" #include "ice40_spi.h" - #include "spi_bus.h" #endif #ifdef IS_PRALINE -ssp_config_t ssp_config_ice40_fpga = { - .data_bits = SSP_DATA_8BITS, - .spi_mode = SSP_CPOL_1_CPHA_1, - .serial_clock_rate = 21, - .clock_prescale_rate = 2, -}; - -ice40_spi_driver_t ice40 = { - .bus = &spi_bus_ssp1, -}; - fpga_driver_t fpga = { .bus = &ice40, }; #endif - -#ifdef IS_PRALINE -void ssp1_set_mode_ice40(void) -{ - spi_bus_start(&spi_bus_ssp1, &ssp_config_ice40_fpga); -} -#endif diff --git a/firmware/common/drivers.h b/firmware/common/drivers.h index 1fe7d72c..1128a2dc 100644 --- a/firmware/common/drivers.h +++ b/firmware/common/drivers.h @@ -28,20 +28,12 @@ extern "C" { #include "platform_detect.h" // IWYU pragma: keep #if defined(IS_PRALINE) #include "fpga.h" - #include "ice40_spi.h" - #include "spi_ssp.h" #endif #if defined(IS_PRALINE) -extern ssp_config_t ssp_config_ice40_fpga; -extern ice40_spi_driver_t ice40; extern fpga_driver_t fpga; #endif -#if defined(IS_PRALINE) -void ssp1_set_mode_ice40(void); -#endif - #ifdef __cplusplus } #endif diff --git a/firmware/common/fpga.c b/firmware/common/fpga.c index 3bdd636e..b339fc15 100644 --- a/firmware/common/fpga.c +++ b/firmware/common/fpga.c @@ -24,7 +24,6 @@ #include -#include "drivers.h" #include "ice40_spi.h" #include "max283x.h" diff --git a/firmware/common/fpga_image.c b/firmware/common/fpga_image.c index a9f46aee..3ebadad8 100644 --- a/firmware/common/fpga_image.c +++ b/firmware/common/fpga_image.c @@ -23,7 +23,6 @@ #include #include -#include "drivers.h" #include "fpga.h" #include "ice40_spi.h" #include "lz4_blk.h" diff --git a/firmware/common/ice40_spi.c b/firmware/common/ice40_spi.c index c8364b8a..2685092a 100644 --- a/firmware/common/ice40_spi.c +++ b/firmware/common/ice40_spi.c @@ -28,6 +28,23 @@ #include "delay.h" #include "platform_scu.h" +/* Driver instance. */ +ssp_config_t ssp_config_ice40_fpga = { + .data_bits = SSP_DATA_8BITS, + .spi_mode = SSP_CPOL_1_CPHA_1, + .serial_clock_rate = 21, + .clock_prescale_rate = 2, +}; + +ice40_spi_driver_t ice40 = { + .bus = &spi_bus_ssp1, +}; + +void ssp1_set_mode_ice40(void) +{ + spi_bus_start(&spi_bus_ssp1, &ssp_config_ice40_fpga); +} + void ice40_spi_target_init(ice40_spi_driver_t* const drv) { const platform_scu_t* scu = platform_scu(); diff --git a/firmware/common/ice40_spi.h b/firmware/common/ice40_spi.h index 4ceddffa..a1362033 100644 --- a/firmware/common/ice40_spi.h +++ b/firmware/common/ice40_spi.h @@ -27,6 +27,7 @@ #include "gpio.h" #include "spi_bus.h" +#include "spi_ssp.h" typedef struct { spi_bus_t* const bus; @@ -43,3 +44,8 @@ bool ice40_spi_syscfg_program( uint8_t* buf, size_t (*read_block_cb)(void* ctx), void* read_ctx); + +/* Driver instance. */ +extern ssp_config_t ssp_config_ice40_fpga; +extern ice40_spi_driver_t ice40; +void ssp1_set_mode_ice40(void); diff --git a/firmware/common/pins.c b/firmware/common/pins.c index f695d1ef..c51de383 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -41,7 +41,7 @@ #include "w25q80bv.h" #if defined(IS_PRALINE) #include "clock_io.h" - #include "drivers.h" + #include "ice40_spi.h" #endif void pins_shutdown(void) From 8569c1dfd26d55f4f2e6df6b4265ef11018c9e60 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 30 Apr 2026 16:35:44 +0200 Subject: [PATCH 184/238] firmware: move fpga object instance to fpga.x --- firmware/common/clock_io.c | 1 - firmware/common/drivers.c | 11 ----------- firmware/common/drivers.h | 9 --------- firmware/common/fpga.c | 5 +++++ firmware/common/fpga.h | 3 ++- firmware/common/fpga_selftest.c | 1 - firmware/common/radio.c | 1 - firmware/hackrf_usb/usb_api_register.c | 1 - 8 files changed, 7 insertions(+), 25 deletions(-) diff --git a/firmware/common/clock_io.c b/firmware/common/clock_io.c index c68d470f..b0904f89 100644 --- a/firmware/common/clock_io.c +++ b/firmware/common/clock_io.c @@ -36,7 +36,6 @@ #include "sgpio.h" #endif #ifdef IS_PRALINE - #include "drivers.h" #include "fpga.h" #include "platform_gpio.h" #endif diff --git a/firmware/common/drivers.c b/firmware/common/drivers.c index 65ca10a9..739f9b1f 100644 --- a/firmware/common/drivers.c +++ b/firmware/common/drivers.c @@ -20,14 +20,3 @@ */ #include "drivers.h" - -#if defined(IS_PRALINE) - #include "fpga.h" - #include "ice40_spi.h" -#endif - -#ifdef IS_PRALINE -fpga_driver_t fpga = { - .bus = &ice40, -}; -#endif diff --git a/firmware/common/drivers.h b/firmware/common/drivers.h index 1128a2dc..0071a0be 100644 --- a/firmware/common/drivers.h +++ b/firmware/common/drivers.h @@ -25,15 +25,6 @@ extern "C" { #endif -#include "platform_detect.h" // IWYU pragma: keep -#if defined(IS_PRALINE) - #include "fpga.h" -#endif - -#if defined(IS_PRALINE) -extern fpga_driver_t fpga; -#endif - #ifdef __cplusplus } #endif diff --git a/firmware/common/fpga.c b/firmware/common/fpga.c index b339fc15..f68b6525 100644 --- a/firmware/common/fpga.c +++ b/firmware/common/fpga.c @@ -27,6 +27,11 @@ #include "ice40_spi.h" #include "max283x.h" +/* Driver instance. */ +fpga_driver_t fpga = { + .bus = &ice40, +}; + /* Set up all registers according to the loaded bitstream's defaults. */ void fpga_init(fpga_driver_t* const drv) { diff --git a/firmware/common/fpga.h b/firmware/common/fpga.h index 65826b21..1765fcdd 100644 --- a/firmware/common/fpga.h +++ b/firmware/common/fpga.h @@ -91,4 +91,5 @@ bool fpga_spi_selftest(void); bool fpga_sgpio_selftest(void); bool fpga_if_xcvr_selftest(void); -//void narrowband_filter_set(const uint8_t value); +/* Driver instance. */ +extern fpga_driver_t fpga; diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index 30e70ea2..c51dd008 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -25,7 +25,6 @@ #include "clock_gen.h" #include "delay.h" -#include "drivers.h" #include "fixed_point.h" #include "fpga.h" #include "ice40_spi.h" diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 17b7486c..eb01b5de 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -34,7 +34,6 @@ #include "transceiver_mode.h" #include "tuning.h" #ifdef IS_PRALINE - #include "drivers.h" #include "fpga.h" #include "tune_config.h" #endif diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index 88a4de53..30d1d493 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -36,7 +36,6 @@ #include #include #ifdef IS_PRALINE - #include #include #endif #ifdef IS_NOT_RAD1O From 8bdefc2d899e4a26cca2c37b30faf0b454ad5f20 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 30 Apr 2026 16:38:10 +0200 Subject: [PATCH 185/238] firmware: remove drivers.x --- firmware/common/drivers.c | 22 ---------------------- firmware/common/drivers.h | 30 ------------------------------ firmware/hackrf-common.cmake | 1 - 3 files changed, 53 deletions(-) delete mode 100644 firmware/common/drivers.c delete mode 100644 firmware/common/drivers.h diff --git a/firmware/common/drivers.c b/firmware/common/drivers.c deleted file mode 100644 index 739f9b1f..00000000 --- a/firmware/common/drivers.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2026 Great Scott Gadgets - * - * This file is part of HackRF. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include "drivers.h" diff --git a/firmware/common/drivers.h b/firmware/common/drivers.h deleted file mode 100644 index 0071a0be..00000000 --- a/firmware/common/drivers.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2026 Great Scott Gadgets - * - * This file is part of HackRF. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index d31cd6c0..eb1d5716 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -168,7 +168,6 @@ endmacro() macro(DeclareTargets) SET(SRC_M4 ${SRC_M4} - ${PATH_HACKRF_FIRMWARE_COMMON}/drivers.c ${PATH_HACKRF_FIRMWARE_COMMON}/power.c ${PATH_HACKRF_FIRMWARE_COMMON}/cpu_clock.c ${PATH_HACKRF_FIRMWARE_COMMON}/delay.c From 9c81954b1b31cd7166f0d8df345c24803a9b4c06 Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Fri, 24 Apr 2026 10:43:00 +0200 Subject: [PATCH 186/238] firmware: move platform preprocessor definitions to cmake --- firmware/common/platform_detect.h | 62 ---------------------- firmware/hackrf-common.cmake | 2 + firmware/platform-detect.cmake | 87 +++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 62 deletions(-) create mode 100644 firmware/platform-detect.cmake diff --git a/firmware/common/platform_detect.h b/firmware/common/platform_detect.h index 0331fe9c..4f0f0f43 100644 --- a/firmware/common/platform_detect.h +++ b/firmware/common/platform_detect.h @@ -21,7 +21,6 @@ #pragma once -#include #include #define BOARD_REV_GSG (0x80) @@ -32,67 +31,6 @@ #define PLATFORM_HACKRF1_R9 (1 << 3) #define PLATFORM_PRALINE (1 << 4) -/* clang-format off */ - -/* Helper macros for platform-specific code. */ -#if defined(UNIVERSAL) - #define IS_PRALINE (detected_platform() == BOARD_ID_PRALINE) - #define IS_NOT_PRALINE (!IS_PRALINE) - #define IS_HACKRF_ONE ( \ - detected_platform() == BOARD_ID_HACKRF1_OG || \ - detected_platform() == BOARD_ID_HACKRF1_R9 \ - ) - #define IS_NOT_HACKRF_ONE (!IS_HACKRF_ONE) - #define IS_H1_R9 (detected_platform() == BOARD_ID_HACKRF1_R9) - #define IS_NOT_H1_R9 (!IS_H1_R9) - #define IS_NOT_RAD1O true - #define IS_NOT_JAWBREAKER true - #define IS_H1_OR_PRALINE true - #define IS_H1_OR_RAD1O IS_HACKRF_ONE - #define IS_H1_OR_JAWBREAKER IS_HACKRF_ONE - #define IS_FOUR_LEDS IS_PRALINE - #define IS_EXPANSION_COMPATIBLE true -#elif defined(HACKRF_ONE) - #define IS_NOT_PRALINE true - #define IS_HACKRF_ONE true - #define IS_H1_R9 (detected_platform() == BOARD_ID_HACKRF1_R9) - #define IS_NOT_H1_R9 (!IS_H1_R9) - #define IS_NOT_RAD1O true - #define IS_NOT_JAWBREAKER true - #define IS_H1_OR_PRALINE true - #define IS_H1_OR_RAD1O true - #define IS_H1_OR_JAWBREAKER true - #define IS_EXPANSION_COMPATIBLE true -#elif defined(PRALINE) - #define IS_PRALINE true - #define IS_NOT_HACKRF_ONE true - #define IS_NOT_H1_R9 true - #define IS_NOT_RAD1O true - #define IS_NOT_JAWBREAKER true - #define IS_H1_OR_PRALINE true - #define IS_FOUR_LEDS true - #define IS_EXPANSION_COMPATIBLE true -#elif defined(RAD1O) - #define IS_NOT_PRALINE true - #define IS_NOT_HACKRF_ONE true - #define IS_NOT_H1_R9 true - #define IS_RAD1O true - #define IS_NOT_JAWBREAKER true - #define IS_H1_OR_RAD1O true - #define IS_FOUR_LEDS true -#elif defined(JAWBREAKER) - #define IS_NOT_PRALINE true - #define IS_NOT_HACKRF_ONE true - #define IS_NOT_H1_R9 true - #define IS_NOT_RAD1O true - #define IS_JAWBREAKER true - #define IS_H1_OR_JAWBREAKER true -#else - #error "No recognised platform defined" -#endif - -/* clang-format on */ - typedef enum { BOARD_ID_JELLYBEAN = 0, BOARD_ID_JAWBREAKER = 1, diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index eb1d5716..dfc67d9e 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -74,6 +74,8 @@ if(NOT DEFINED BOARD) set(BOARD HACKRF_ONE) endif() +include(${PATH_HACKRF_FIRMWARE}/platform-detect.cmake) + if(BOARD STREQUAL "HACKRF_ONE" OR BOARD STREQUAL "PRALINE" OR BOARD STREQUAL "UNIVERSAL") set(MCU_PARTNO LPC4320) else() diff --git a/firmware/platform-detect.cmake b/firmware/platform-detect.cmake new file mode 100644 index 00000000..dcaeba58 --- /dev/null +++ b/firmware/platform-detect.cmake @@ -0,0 +1,87 @@ +# Copyright 2026 Great Scott Gadgets +# +# This file is part of HackRF. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +cmake_minimum_required(VERSION 3.12.0) + +if(BOARD STREQUAL "UNIVERSAL") + add_compile_definitions( + "IS_PRALINE=(detected_platform() == BOARD_ID_PRALINE)" + "IS_NOT_PRALINE=(!IS_PRALINE)" + "IS_HACKRF_ONE=( \ + detected_platform() == BOARD_ID_HACKRF1_OG || \ + detected_platform() == BOARD_ID_HACKRF1_R9 \ + )" + "IS_NOT_HACKRF_ONE=(!IS_HACKRF_ONE)" + "IS_H1_R9=(detected_platform() == BOARD_ID_HACKRF1_R9)" + "IS_NOT_H1_R9=(!IS_H1_R9)" + "IS_NOT_RAD1O=1" + "IS_NOT_JAWBREAKER=1" + "IS_H1_OR_PRALINE=1" + "IS_H1_OR_RAD1O=IS_HACKRF_ONE" + "IS_H1_OR_JAWBREAKER=IS_HACKRF_ONE" + "IS_FOUR_LEDS=IS_PRALINE" + "IS_EXPANSION_COMPATIBLE=1" + ) +elseif(BOARD STREQUAL "HACKRF_ONE") + add_compile_definitions( + "IS_NOT_PRALINE=1" + "IS_HACKRF_ONE=1" + "IS_H1_R9=(detected_platform() == BOARD_ID_HACKRF1_R9)" + "IS_NOT_H1_R9=(!IS_H1_R9)" + "IS_NOT_RAD1O=1" + "IS_NOT_JAWBREAKER=1" + "IS_H1_OR_PRALINE=1" + "IS_H1_OR_RAD1O=1" + "IS_H1_OR_JAWBREAKER=1" + "IS_EXPANSION_COMPATIBLE=1" + ) +elseif(BOARD STREQUAL "PRALINE") + add_compile_definitions( + "IS_PRALINE=1" + "IS_NOT_HACKRF_ONE=1" + "IS_NOT_H1_R9=1" + "IS_NOT_RAD1O=1" + "IS_NOT_JAWBREAKER=1" + "IS_H1_OR_PRALINE=1" + "IS_FOUR_LEDS=1" + "IS_EXPANSION_COMPATIBLE=1" + ) +elseif(BOARD STREQUAL "RAD1O") + add_compile_definitions( + "IS_NOT_PRALINE=1" + "IS_NOT_HACKRF_ONE=1" + "IS_NOT_H1_R9=1" + "IS_RAD1O=1" + "IS_NOT_JAWBREAKER=1" + "IS_H1_OR_RAD1O=1" + "IS_FOUR_LEDS=1" + ) +elseif(BOARD STREQUAL "JAWBREAKER") + add_compile_definitions( + "IS_NOT_PRALINE=1" + "IS_NOT_HACKRF_ONE=1" + "IS_NOT_H1_R9=1" + "IS_NOT_RAD1O=1" + "IS_JAWBREAKER=1" + "IS_H1_OR_JAWBREAKER=1" + ) +else() + message(FATAL_ERROR "No recognized platform defined: ${BOARD}") +endif() From 01ffff68eea4db1f39b76bff1ab64f1edeb11d6b Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Fri, 24 Apr 2026 11:55:25 +0200 Subject: [PATCH 187/238] firmware: remove spurious platform_detect.h includes --- firmware/common/clock_gen.h | 2 -- firmware/common/clock_io.c | 1 + firmware/common/clock_io.h | 2 -- firmware/common/cpld_jtag.c | 1 - firmware/common/cpld_jtag.h | 1 - firmware/common/cpu_clock.c | 3 --- firmware/common/cpu_clock.h | 2 -- firmware/common/hackrf_ui.c | 1 - firmware/common/max283x.h | 1 - firmware/common/mixer.h | 2 -- firmware/common/operacake_sctimer.c | 5 ++++- firmware/common/pins.c | 2 +- firmware/common/pins.h | 2 -- firmware/common/platform_gpio.h | 1 - firmware/common/platform_scu.h | 2 -- firmware/common/power.c | 10 ++++------ firmware/common/power.h | 2 -- firmware/common/rf_path.h | 2 -- firmware/common/rffc5071.h | 1 - firmware/common/selftest.h | 2 -- firmware/common/sgpio.h | 1 - firmware/hackrf_usb/usb_api_register.c | 1 + firmware/hackrf_usb/usb_api_register.h | 2 -- firmware/hackrf_usb/usb_api_selftest.c | 7 +++---- firmware/hackrf_usb/usb_descriptor.c | 2 -- firmware/hackrf_usb/usb_descriptor.h | 2 -- firmware/hackrf_usb/usb_device.c | 1 - firmware/hackrf_usb/usb_device.h | 2 -- firmware/include-what-you-use.cmake | 18 +++++++++++++++++- 29 files changed, 31 insertions(+), 50 deletions(-) diff --git a/firmware/common/clock_gen.h b/firmware/common/clock_gen.h index 0bc6439b..fa1d3da0 100644 --- a/firmware/common/clock_gen.h +++ b/firmware/common/clock_gen.h @@ -25,8 +25,6 @@ extern "C" { #endif -#include "platform_detect.h" // IWYU pragma: keep - #include #include "fixed_point.h" diff --git a/firmware/common/clock_io.c b/firmware/common/clock_io.c index b0904f89..d4d14af0 100644 --- a/firmware/common/clock_io.c +++ b/firmware/common/clock_io.c @@ -32,6 +32,7 @@ #include "gpdma.h" #include "gpio.h" +#include "platform_detect.h" #ifdef IS_NOT_PRALINE #include "sgpio.h" #endif diff --git a/firmware/common/clock_io.h b/firmware/common/clock_io.h index df540022..4868b2d9 100644 --- a/firmware/common/clock_io.h +++ b/firmware/common/clock_io.h @@ -24,8 +24,6 @@ #include #include -#include "platform_detect.h" // IWYU pragma: keep - void clkin_detect_init(void); uint32_t clkin_frequency(void); diff --git a/firmware/common/cpld_jtag.c b/firmware/common/cpld_jtag.c index 92f89f27..441fefe8 100644 --- a/firmware/common/cpld_jtag.c +++ b/firmware/common/cpld_jtag.c @@ -22,7 +22,6 @@ #include "cpld_jtag.h" #include "platform_detect.h" - #ifdef IS_NOT_PRALINE #include #include "xapp058/micro.h" diff --git a/firmware/common/cpld_jtag.h b/firmware/common/cpld_jtag.h index 14f70437..f49f1317 100644 --- a/firmware/common/cpld_jtag.h +++ b/firmware/common/cpld_jtag.h @@ -24,7 +24,6 @@ #include #include "gpio.h" -#include "platform_detect.h" typedef struct { gpio_t gpio_tck; diff --git a/firmware/common/cpu_clock.c b/firmware/common/cpu_clock.c index aa4ac910..37445e51 100644 --- a/firmware/common/cpu_clock.c +++ b/firmware/common/cpu_clock.c @@ -31,9 +31,6 @@ #include "delay.h" #include "i2c_bus.h" #include "si5351c.h" -#ifdef IS_NOT_RAD1O - #include "platform_detect.h" -#endif /* Configure PLL1 (Main MCU Clock) to max speed (204MHz). diff --git a/firmware/common/cpu_clock.h b/firmware/common/cpu_clock.h index b0393081..92ad6441 100644 --- a/firmware/common/cpu_clock.h +++ b/firmware/common/cpu_clock.h @@ -25,8 +25,6 @@ extern "C" { #endif -#include "platform_detect.h" // IWYU pragma: keep - void cpu_clock_init(void); #ifdef __cplusplus diff --git a/firmware/common/hackrf_ui.c b/firmware/common/hackrf_ui.c index 4224d40f..ac243890 100644 --- a/firmware/common/hackrf_ui.c +++ b/firmware/common/hackrf_ui.c @@ -23,7 +23,6 @@ #include #include "hackrf_ui.h" -#include "platform_detect.h" // IWYU pragma: keep #include "transceiver_mode.h" #ifdef IS_EXPANSION_COMPATIBLE #include "ui_portapack.h" diff --git a/firmware/common/max283x.h b/firmware/common/max283x.h index b4e44620..4db5edfe 100644 --- a/firmware/common/max283x.h +++ b/firmware/common/max283x.h @@ -27,7 +27,6 @@ #include #include "fixed_point.h" -#include "platform_detect.h" #include "spi_ssp.h" #ifdef IS_PRALINE diff --git a/firmware/common/mixer.h b/firmware/common/mixer.h index 35c0f047..15afe35e 100644 --- a/firmware/common/mixer.h +++ b/firmware/common/mixer.h @@ -26,8 +26,6 @@ #include #include "fixed_point.h" -#include "platform_detect.h" - #ifdef IS_RAD1O #include "max2871.h" #endif diff --git a/firmware/common/operacake_sctimer.c b/firmware/common/operacake_sctimer.c index 1268114f..9325f65d 100644 --- a/firmware/common/operacake_sctimer.c +++ b/firmware/common/operacake_sctimer.c @@ -30,12 +30,15 @@ #include "platform_detect.h" #include "platform_scu.h" #include "sct.h" - #ifdef IS_NOT_PRALINE #include #include #endif +#include "delay.h" +#include "platform_detect.h" +#include "sct.h" + #define U1CTRL_SET SCT_OUT14_SET #define U1CTRL_CLR SCT_OUT14_CLR #define U2CTRL0_SET SCT_OUT13_SET diff --git a/firmware/common/pins.c b/firmware/common/pins.c index 48479f95..3010cd9f 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -39,7 +39,7 @@ #include "rf_path.h" #include "sgpio.h" #include "w25q80bv.h" -#if defined(IS_PRALINE) +#ifdef IS_PRALINE #include "clock_io.h" #include "ice40_spi.h" #endif diff --git a/firmware/common/pins.h b/firmware/common/pins.h index b9454d18..bc109e5b 100644 --- a/firmware/common/pins.h +++ b/firmware/common/pins.h @@ -27,8 +27,6 @@ extern "C" { #endif -#include "platform_detect.h" // IWYU pragma: keep - void pins_shutdown(void); void pins_setup(void); diff --git a/firmware/common/platform_gpio.h b/firmware/common/platform_gpio.h index a7e68bc9..c57df96e 100644 --- a/firmware/common/platform_gpio.h +++ b/firmware/common/platform_gpio.h @@ -27,7 +27,6 @@ extern "C" { #include "gpio.h" #include "gpio_lpc.h" -#include "platform_detect.h" typedef struct { /* LEDs */ diff --git a/firmware/common/platform_scu.h b/firmware/common/platform_scu.h index 71c0f742..a3702bf7 100644 --- a/firmware/common/platform_scu.h +++ b/firmware/common/platform_scu.h @@ -29,8 +29,6 @@ extern "C" { #include -#include "platform_detect.h" - /* * SCU PinMux */ diff --git a/firmware/common/power.c b/firmware/common/power.c index 25424aab..1256e595 100644 --- a/firmware/common/power.c +++ b/firmware/common/power.c @@ -24,16 +24,14 @@ #if defined(IS_HACKRF_ONE) #include #endif -#if defined(IS_HACKRF_ONE) || defined(IS_RAD1O) || defined(IS_JAWBREAKER) - #include "platform_detect.h" -#endif + +#include "gpio.h" +#include "platform_detect.h" +#include "platform_gpio.h" #if defined(IS_PRALINE) || defined(IS_RAD1O) #include "delay.h" #endif -#include "gpio.h" -#include "platform_gpio.h" - #ifdef IS_PRALINE void enable_1v2_power(void) { diff --git a/firmware/common/power.h b/firmware/common/power.h index 22b2345e..fc8af67a 100644 --- a/firmware/common/power.h +++ b/firmware/common/power.h @@ -25,8 +25,6 @@ extern "C" { #endif -#include "platform_detect.h" // IWYU pragma: keep - #ifdef IS_PRALINE void enable_1v2_power(void); void disable_1v2_power(void); diff --git a/firmware/common/rf_path.h b/firmware/common/rf_path.h index 3b97ac62..a1796f13 100644 --- a/firmware/common/rf_path.h +++ b/firmware/common/rf_path.h @@ -25,8 +25,6 @@ #include -#include "platform_detect.h" // IWYU pragma: keep - #ifdef IS_NOT_JAWBREAKER #include "gpio.h" #endif diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index c6b2c0c2..40971061 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -27,7 +27,6 @@ #include "fixed_point.h" #include "gpio.h" -#include "platform_detect.h" // IWYU pragma: keep #include "spi_bus.h" /* 31 registers, each containing 16 bits of data. */ diff --git a/firmware/common/selftest.h b/firmware/common/selftest.h index 9fca53a6..cea60da2 100644 --- a/firmware/common/selftest.h +++ b/firmware/common/selftest.h @@ -24,8 +24,6 @@ #include #include -#include "platform_detect.h" // IWYU pragma: keep - #define NUM_LOCK_ATTEMPTS 3 enum { diff --git a/firmware/common/sgpio.h b/firmware/common/sgpio.h index 58a30c27..0aebdb5f 100644 --- a/firmware/common/sgpio.h +++ b/firmware/common/sgpio.h @@ -26,7 +26,6 @@ #include #include "gpio.h" -#include "platform_detect.h" // IWYU pragma: keep typedef enum { SGPIO_DIRECTION_RX, diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index 30d1d493..1a9f0238 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -21,6 +21,7 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ + #include "usb_api_register.h" #include diff --git a/firmware/hackrf_usb/usb_api_register.h b/firmware/hackrf_usb/usb_api_register.h index aef02d03..a5a36550 100644 --- a/firmware/hackrf_usb/usb_api_register.h +++ b/firmware/hackrf_usb/usb_api_register.h @@ -23,8 +23,6 @@ #pragma once -#include "platform_detect.h" // IWYU pragma: keep - #include #include diff --git a/firmware/hackrf_usb/usb_api_selftest.c b/firmware/hackrf_usb/usb_api_selftest.c index 4c812366..7fde6f68 100644 --- a/firmware/hackrf_usb/usb_api_selftest.c +++ b/firmware/hackrf_usb/usb_api_selftest.c @@ -23,6 +23,9 @@ #include #include +#ifdef IS_NOT_RAD1O + #include +#endif #include #include @@ -33,10 +36,6 @@ #include #include -#ifdef IS_NOT_RAD1O - #include -#endif - static char* itoa(int val, int base) { static char buf[32] = {0}; diff --git a/firmware/hackrf_usb/usb_descriptor.c b/firmware/hackrf_usb/usb_descriptor.c index 067317b3..005babb3 100644 --- a/firmware/hackrf_usb/usb_descriptor.c +++ b/firmware/hackrf_usb/usb_descriptor.c @@ -26,8 +26,6 @@ #include -#include "platform_detect.h" - #define USB_VENDOR_ID (0x1D50) #define USB_API_VERSION (0x0112) diff --git a/firmware/hackrf_usb/usb_descriptor.h b/firmware/hackrf_usb/usb_descriptor.h index ef41d6ac..bd43f4aa 100644 --- a/firmware/hackrf_usb/usb_descriptor.h +++ b/firmware/hackrf_usb/usb_descriptor.h @@ -24,8 +24,6 @@ #include -#include "platform_detect.h" - #if defined(IS_HACKRF_ONE) || defined(IS_PRALINE) extern uint8_t usb_descriptor_device_hackrf[]; #endif diff --git a/firmware/hackrf_usb/usb_device.c b/firmware/hackrf_usb/usb_device.c index a2af1158..90347e17 100644 --- a/firmware/hackrf_usb/usb_device.c +++ b/firmware/hackrf_usb/usb_device.c @@ -25,7 +25,6 @@ #include -#include "platform_detect.h" #include "usb_descriptor.h" usb_configuration_t usb_configuration_high_speed = { diff --git a/firmware/hackrf_usb/usb_device.h b/firmware/hackrf_usb/usb_device.h index f442db37..5ef53360 100644 --- a/firmware/hackrf_usb/usb_device.h +++ b/firmware/hackrf_usb/usb_device.h @@ -25,8 +25,6 @@ #include -#include "platform_detect.h" - extern usb_device_t usb_device; #ifdef IS_HACKRF_ONE diff --git a/firmware/include-what-you-use.cmake b/firmware/include-what-you-use.cmake index b5c1bc7e..291cfdab 100644 --- a/firmware/include-what-you-use.cmake +++ b/firmware/include-what-you-use.cmake @@ -28,11 +28,27 @@ endif() # include-what-you-use arguments: # # --no_fwd_decls - Disable forward declaration suggestions. +# --keep - Always keep the specified include. # --mapping_file - Specify mapping files for excluding suggestions. +# -w - Disable spurious clang warnings. +# +# NOTE: We specify '--keep platform_detect.h' due to iwyu 0.23 not +# being able to detect usage of symbols within preprocessor +# macros. This results in false positives for the removal of the +# include. +# +# The alternate solution is to use "// IWYU pragma: always-keep" +# within "platform_detect.h" itself but this triggers the +# angle-quote-curse on 0.23. (e.g. https://github.com/include-what-you-use/include-what-you-use/issues/1087) +# +# iwyu versions from at least 0.26 onwards do not suffer from these +# problems which will allow us to remove it in future. # list(APPEND IWYU_COMMAND -Xiwyu --no_fwd_decls - -Xiwyu --mapping_file=${CMAKE_SOURCE_DIR}/libopencm3.imp) + -Xiwyu --keep ${CMAKE_SOURCE_DIR}/common/platform_detect.h + -Xiwyu --mapping_file=${CMAKE_SOURCE_DIR}/libopencm3.imp + -w) set(CMAKE_C_INCLUDE_WHAT_YOU_USE ${IWYU_COMMAND}) set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${IWYU_COMMAND}) From 23104c7bd9fa4dddda0bc5c6db512679b5626cc7 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 28 Apr 2026 11:58:18 +0100 Subject: [PATCH 188/238] firmware: bump CMake requirement to 3.12. --- .github/workflows/build.yml | 4 ++-- .github/workflows/includes-check.yml | 2 +- firmware/CMakeLists.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a93a27c1..02239f82 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -160,10 +160,10 @@ jobs: matrix: os: ['macos', 'ubuntu', 'windows'] board: ['HACKRF_ONE', 'JAWBREAKER', 'RAD1O', 'PRALINE', 'UNIVERSAL'] - cmake: ['3.10.0', 'latest'] + cmake: ['3.12.0', 'latest'] exclude: - os: 'windows' - cmake: '3.10.0' + cmake: '3.12.0' # GitHub doesn't give us many macOS runners, so don't build for every board. # We just need to know that building firmware works on macOS. Use PRALINE # since that's the most complicated one due to FPGA bitstreams. diff --git a/.github/workflows/includes-check.yml b/.github/workflows/includes-check.yml index 11640069..f16800fe 100644 --- a/.github/workflows/includes-check.yml +++ b/.github/workflows/includes-check.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: board: ['HACKRF_ONE', 'JAWBREAKER', 'RAD1O', 'PRALINE', 'UNIVERSAL'] - cmake: ['3.10.0', 'latest'] + cmake: ['3.12.0', 'latest'] # Don't cancel all builds when one fails fail-fast: false diff --git a/firmware/CMakeLists.txt b/firmware/CMakeLists.txt index 611e7870..844ae708 100644 --- a/firmware/CMakeLists.txt +++ b/firmware/CMakeLists.txt @@ -23,7 +23,7 @@ option(CHECK_INCLUDES "Check firmware sources for unused includes and transitive dependencies. (Requires iwyu)" OFF) -cmake_minimum_required(VERSION 3.10.0) +cmake_minimum_required(VERSION 3.12.0) set(CMAKE_TOOLCHAIN_FILE toolchain-arm-cortex-m.cmake) project (hackrf_firmware_all C) From 6ff7f8ed6346a396e74d85ed7e7b5b9049052806 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 7 May 2026 18:56:53 -0400 Subject: [PATCH 189/238] Fix IWYU --keep syntax for compatibility with 0.22 --- firmware/include-what-you-use.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/include-what-you-use.cmake b/firmware/include-what-you-use.cmake index 291cfdab..37e2a2a6 100644 --- a/firmware/include-what-you-use.cmake +++ b/firmware/include-what-you-use.cmake @@ -46,7 +46,7 @@ endif() # list(APPEND IWYU_COMMAND -Xiwyu --no_fwd_decls - -Xiwyu --keep ${CMAKE_SOURCE_DIR}/common/platform_detect.h + -Xiwyu --keep=${CMAKE_SOURCE_DIR}/common/platform_detect.h -Xiwyu --mapping_file=${CMAKE_SOURCE_DIR}/libopencm3.imp -w) From db44436fda46150bc443b0c1f65b1e70803d7cb5 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 7 May 2026 19:30:30 -0400 Subject: [PATCH 190/238] Remove redundant includes --- firmware/common/operacake_sctimer.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/firmware/common/operacake_sctimer.c b/firmware/common/operacake_sctimer.c index 9325f65d..76453e57 100644 --- a/firmware/common/operacake_sctimer.c +++ b/firmware/common/operacake_sctimer.c @@ -35,10 +35,6 @@ #include #endif -#include "delay.h" -#include "platform_detect.h" -#include "sct.h" - #define U1CTRL_SET SCT_OUT14_SET #define U1CTRL_CLR SCT_OUT14_CLR #define U2CTRL0_SET SCT_OUT13_SET From fe060fd04b1c18a1755cd800632c45bcf9b5fa2b Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 11 May 2026 12:19:29 +0100 Subject: [PATCH 191/238] libhackrf: Set timeouts for all USB transfers. --- host/libhackrf/src/hackrf.c | 129 ++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 63 deletions(-) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index da3c0f15..7bafd5f3 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -54,6 +54,10 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI #define FROM_LE64(x) x #endif +#define DEFAULT_REQUEST_TIMEOUT 100 +#define CPLD_WRITE_TIMEOUT 10000 +#define SPIFLASH_WRITE_TIMEOUT 50000 // W25Q32JV max chip erase time + // TODO: Factor this into a shared #include so that firmware can use // the same values. typedef enum { @@ -778,7 +782,7 @@ static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** d 0, (unsigned char*) &buffer_size, 4, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 4) { last_libusb_error = result; @@ -948,7 +952,7 @@ int ADDCALL hackrf_set_transceiver_mode( 0, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -977,7 +981,7 @@ int ADDCALL hackrf_max2837_read( register_number, (unsigned char*) value, 2, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 2) { last_libusb_error = result; @@ -1006,7 +1010,7 @@ int ADDCALL hackrf_max2831_read( register_number, (unsigned char*) value, 2, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 2) { last_libusb_error = result; @@ -1039,7 +1043,7 @@ int ADDCALL hackrf_max2837_write( register_number, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -1072,7 +1076,7 @@ int ADDCALL hackrf_max2831_write( register_number, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -1103,7 +1107,7 @@ int ADDCALL hackrf_si5351c_read( register_number, (unsigned char*) &temp_value, 1, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 1) { last_libusb_error = result; @@ -1137,7 +1141,7 @@ int ADDCALL hackrf_si5351c_write( register_number, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -1161,7 +1165,7 @@ int ADDCALL hackrf_set_baseband_filter_bandwidth( bandwidth_hz >> 16, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -1190,7 +1194,7 @@ int ADDCALL hackrf_rffc5071_read( register_number, (unsigned char*) value, 2, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 2) { last_libusb_error = result; @@ -1220,7 +1224,7 @@ int ADDCALL hackrf_rffc5071_write( register_number, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -1246,7 +1250,7 @@ int ADDCALL hackrf_fpga_read_register( register_number, (unsigned char*) value, 1, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 1) { last_libusb_error = result; @@ -1273,7 +1277,7 @@ int ADDCALL hackrf_fpga_write_register( register_number, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -1297,7 +1301,7 @@ int ADDCALL hackrf_read_selftest(hackrf_device* device, hackrf_selftest* selftes 0, (unsigned char*) selftest, sizeof(hackrf_selftest), - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 2) { last_libusb_error = result; @@ -1429,7 +1433,7 @@ int ADDCALL hackrf_read_adc(hackrf_device* device, uint8_t adc_channel, uint16_t adc_channel, (unsigned char*) value, 2, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 2) { last_libusb_error = result; @@ -1453,7 +1457,7 @@ int ADDCALL hackrf_get_m0_state(hackrf_device* device, hackrf_m0_state* state) 0, (unsigned char*) state, sizeof(hackrf_m0_state), - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < sizeof(hackrf_m0_state)) { last_libusb_error = result; @@ -1488,7 +1492,7 @@ int ADDCALL hackrf_set_tx_underrun_limit(hackrf_device* device, uint32_t value) value >> 16, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -1512,7 +1516,7 @@ int ADDCALL hackrf_set_rx_overrun_limit(hackrf_device* device, uint32_t value) value >> 16, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -1534,7 +1538,7 @@ int ADDCALL hackrf_spiflash_erase(hackrf_device* device) 0, NULL, 0, - 0); + SPIFLASH_WRITE_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -1565,7 +1569,7 @@ int ADDCALL hackrf_spiflash_write( address & 0xFFFF, data, length, - 0); + SPIFLASH_WRITE_TIMEOUT); if (result < length) { last_libusb_error = result; @@ -1595,7 +1599,7 @@ int ADDCALL hackrf_spiflash_read( address & 0xFFFF, data, length, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < length) { last_libusb_error = result; @@ -1618,7 +1622,7 @@ int ADDCALL hackrf_spiflash_status(hackrf_device* device, uint8_t* data) 0, data, 2, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 1) { last_libusb_error = result; @@ -1641,7 +1645,7 @@ int ADDCALL hackrf_spiflash_clear_status(hackrf_device* device) 0, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -1671,8 +1675,7 @@ int ADDCALL hackrf_cpld_write( &data[i], chunk_size, &transferred, - 10000 // long timeout to allow for CPLD programming - ); + CPLD_WRITE_TIMEOUT); if (result != LIBUSB_SUCCESS) { last_libusb_error = result; @@ -1694,7 +1697,7 @@ int ADDCALL hackrf_board_id_read(hackrf_device* device, uint8_t* value) 0, value, 1, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 1) { last_libusb_error = result; @@ -1718,7 +1721,7 @@ int ADDCALL hackrf_version_string_read( 0, (unsigned char*) version, length, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 0) { last_libusb_error = result; @@ -1769,7 +1772,7 @@ int ADDCALL hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz) 0, (unsigned char*) &set_freq_params, length, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < length) { last_libusb_error = result; @@ -1829,7 +1832,7 @@ int ADDCALL hackrf_set_freq_explicit( 0, (unsigned char*) ¶ms, length, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < length) { last_libusb_error = result; @@ -1871,7 +1874,7 @@ int ADDCALL hackrf_set_sample_rate_manual( 0, (unsigned char*) &set_fracrate_params, length, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < length) { last_libusb_error = result; @@ -1943,7 +1946,7 @@ int ADDCALL hackrf_set_amp_enable(hackrf_device* device, const uint8_t value) 0, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -1969,7 +1972,7 @@ int ADDCALL hackrf_board_partid_serialno_read( 0, (unsigned char*) read_partid_serialno, length, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < length) { last_libusb_error = result; @@ -2010,7 +2013,7 @@ int ADDCALL hackrf_set_lna_gain(hackrf_device* device, uint32_t value) value, &retval, 1, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 1 || !retval) { return HACKRF_ERROR_INVALID_PARAM; @@ -2037,7 +2040,7 @@ int ADDCALL hackrf_set_vga_gain(hackrf_device* device, uint32_t value) value, &retval, 1, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 1 || !retval) { return HACKRF_ERROR_INVALID_PARAM; @@ -2063,7 +2066,7 @@ int ADDCALL hackrf_set_txvga_gain(hackrf_device* device, uint32_t value) value, &retval, 1, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 1 || !retval) { return HACKRF_ERROR_INVALID_PARAM; @@ -2084,7 +2087,7 @@ int ADDCALL hackrf_set_antenna_enable(hackrf_device* device, const uint8_t value 0, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -2401,7 +2404,7 @@ ADDAPI int ADDCALL hackrf_enable_tx_flush( device->buffer_size, hackrf_libusb_flush_callback, device, - 0); + DEFAULT_REQUEST_TIMEOUT); device->flush_transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER; @@ -2669,7 +2672,7 @@ int ADDCALL hackrf_set_hw_sync_mode(hackrf_device* device, const uint8_t value) 0, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -2750,7 +2753,7 @@ int ADDCALL hackrf_init_sweep( (num_bytes >> 16) & 0xffff, data, size, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < size) { last_libusb_error = result; @@ -2784,7 +2787,7 @@ int ADDCALL hackrf_get_operacake_boards(hackrf_device* device, uint8_t* boards) 0, boards, 8, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 8) { last_libusb_error = result; @@ -2823,7 +2826,7 @@ int ADDCALL hackrf_set_operacake_mode( (uint8_t) mode, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -2862,7 +2865,7 @@ int ADDCALL hackrf_get_operacake_mode( 0, &buf, 1, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 1) { last_libusb_error = result; @@ -2905,7 +2908,7 @@ int ADDCALL hackrf_set_operacake_ports( port_a | (port_b << 8), NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -2927,7 +2930,7 @@ int ADDCALL hackrf_reset(hackrf_device* device) 0, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -2957,7 +2960,7 @@ int ADDCALL hackrf_set_operacake_ranges( 0, ranges, len_ranges, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < len_ranges) { last_libusb_error = result; @@ -2998,7 +3001,7 @@ int ADDCALL hackrf_set_operacake_freq_ranges( 0, range_bytes, len_ranges, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < len_ranges) { last_libusb_error = result; @@ -3040,7 +3043,7 @@ int ADDCALL hackrf_set_operacake_dwell_times( 0, dwell_data, data_len, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < data_len) { last_libusb_error = result; @@ -3063,7 +3066,7 @@ int ADDCALL hackrf_set_clkout_enable(hackrf_device* device, const uint8_t value) 0, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -3085,7 +3088,7 @@ int ADDCALL hackrf_get_clkin_status(hackrf_device* device, uint8_t* status) 0, status, 1, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 1) { last_libusb_error = result; return HACKRF_ERROR_LIBUSB; @@ -3114,7 +3117,7 @@ int ADDCALL hackrf_operacake_gpio_test( 0, (unsigned char*) test_result, 2, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 1) { last_libusb_error = result; @@ -3140,7 +3143,7 @@ int ADDCALL hackrf_cpld_checksum(hackrf_device* device, uint32_t* crc) 0, (unsigned char*) crc, length, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < length) { last_libusb_error = result; @@ -3165,7 +3168,7 @@ int ADDCALL hackrf_set_ui_enable(hackrf_device* device, const uint8_t value) 0, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -3223,7 +3226,7 @@ int ADDCALL hackrf_board_rev_read(hackrf_device* device, uint8_t* value) 0, value, 1, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 1) { last_libusb_error = result; @@ -3307,7 +3310,7 @@ int ADDCALL hackrf_supported_platform_read(hackrf_device* device, uint32_t* valu 0, &data[0], 4, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 1) { last_libusb_error = result; @@ -3330,7 +3333,7 @@ int ADDCALL hackrf_set_leds(hackrf_device* device, const uint8_t state) 0, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -3376,7 +3379,7 @@ int ADDCALL hackrf_set_user_bias_t_opts( 0, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -3399,7 +3402,7 @@ int ADDCALL hackrf_set_p1_ctrl(hackrf_device* device, const enum p1_ctrl_signal 0, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -3422,7 +3425,7 @@ int ADDCALL hackrf_set_p2_ctrl(hackrf_device* device, const enum p2_ctrl_signal 0, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -3447,7 +3450,7 @@ int ADDCALL hackrf_set_clkin_ctrl( 0, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -3470,7 +3473,7 @@ int ADDCALL hackrf_set_narrowband_filter(hackrf_device* device, const uint8_t va 0, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -3493,7 +3496,7 @@ int ADDCALL hackrf_set_fpga_bitstream(hackrf_device* device, const uint8_t index 0, NULL, 0, - 0); + DEFAULT_REQUEST_TIMEOUT); if (result != 0) { last_libusb_error = result; @@ -3521,7 +3524,7 @@ int ADDCALL hackrf_radio_read_register( bank, (unsigned char*) value, length, - 0); + DEFAULT_REQUEST_TIMEOUT); *value = FROM_LE64(*value); if (result < length) { @@ -3561,7 +3564,7 @@ int ADDCALL hackrf_radio_write_register( bank, &data[0], sizeof(data), - 0); + DEFAULT_REQUEST_TIMEOUT); if (result < 9) { last_libusb_error = result; From b4600148116b0aaeb91291d3c8bd7c50977dbde2 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 13 May 2026 21:52:51 +0100 Subject: [PATCH 192/238] Move cpld_jtag_sram_load() into cpld_jtag.c. --- firmware/common/cpld_jtag.c | 13 +++++++++++++ firmware/common/cpld_jtag.h | 1 + firmware/hackrf_usb/hackrf_usb.c | 15 --------------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/firmware/common/cpld_jtag.c b/firmware/common/cpld_jtag.c index 441fefe8..4d313d01 100644 --- a/firmware/common/cpld_jtag.c +++ b/firmware/common/cpld_jtag.c @@ -21,6 +21,7 @@ #include "cpld_jtag.h" +#include "cpld_xc2c.h" #include "platform_detect.h" #ifdef IS_NOT_PRALINE #include @@ -138,4 +139,16 @@ unsigned char cpld_jtag_get_next_byte(void) xsvf_pos++; return byte; } + +bool cpld_jtag_sram_load(jtag_t* const jtag) +{ + cpld_jtag_take(jtag); + cpld_xc2c64a_jtag_sram_write(jtag, &cpld_hackrf_program_sram); + const bool success = cpld_xc2c64a_jtag_sram_verify( + jtag, + &cpld_hackrf_program_sram, + &cpld_hackrf_verify); + cpld_jtag_release(jtag); + return success; +} #endif diff --git a/firmware/common/cpld_jtag.h b/firmware/common/cpld_jtag.h index f49f1317..b9a4b52f 100644 --- a/firmware/common/cpld_jtag.h +++ b/firmware/common/cpld_jtag.h @@ -58,6 +58,7 @@ int cpld_jtag_program( unsigned char* const buffer, refill_buffer_cb refill); unsigned char cpld_jtag_get_next_byte(void); +bool cpld_jtag_sram_load(jtag_t* const jtag); /* Driver instance. */ extern jtag_gpio_t jtag_gpio_cpld; diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 97863876..eb7f85c5 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -69,7 +69,6 @@ #endif #ifdef IS_NOT_PRALINE #include - #include #endif #include "usb_api_adc.h" @@ -261,20 +260,6 @@ void usb_set_descriptor_by_serial_number(void) } } -#ifdef IS_NOT_PRALINE -static bool cpld_jtag_sram_load(jtag_t* const jtag) -{ - cpld_jtag_take(jtag); - cpld_xc2c64a_jtag_sram_write(jtag, &cpld_hackrf_program_sram); - const bool success = cpld_xc2c64a_jtag_sram_verify( - jtag, - &cpld_hackrf_program_sram, - &cpld_hackrf_verify); - cpld_jtag_release(jtag); - return success; -} -#endif - static void m0_rom_to_ram(void) { uint32_t* dest = &__ram_m0_start__; From d00dae3835f15a398915d764393a4c0b3e256ff0 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sun, 3 May 2026 09:03:37 +0100 Subject: [PATCH 193/238] si5351c: API: change terminology to refer to XTAL/CLKIN as "inputs". There are multiple similar but different things called a "source" or "clock source", or that are set in a register called "SRC", in the context of the Si5351 and its usage in HackRF. One place we can be unambiguous is that there are only two inputs to the Si5351C itself: XTAL and CLKIN. Let's have a type for that alone, and name it as such when we use it. There should be no functional changes in this commit. --- firmware/common/clock_gen.c | 9 +++++---- firmware/common/si5351c.c | 28 ++++++++++++++-------------- firmware/common/si5351c.h | 17 +++++++---------- 3 files changed, 26 insertions(+), 28 deletions(-) diff --git a/firmware/common/clock_gen.c b/firmware/common/clock_gen.c index 0f0085c2..f1f0bc60 100644 --- a/firmware/common/clock_gen.c +++ b/firmware/common/clock_gen.c @@ -111,7 +111,7 @@ void clock_gen_init(void) sample_rate_set(SR_FP_MHZ(10), true); si5351c_configure_clock_control(&si5351c); - si5351c_set_clock_source(&si5351c, PLL_SOURCE_XTAL); + si5351c_change_input(&si5351c, SI5351C_INPUT_XTAL); // soft reset si5351c_reset_pll(&si5351c, SI5351C_PLL_BOTH); si5351c_enable_clock_outputs(&si5351c); @@ -159,9 +159,10 @@ clock_source_t activate_best_clock_source(void) /* No external or PortaPack clock was found. Use HackRF Si5351C crystal. */ } - si5351c_set_clock_source( - &si5351c, - (source == CLOCK_SOURCE_HACKRF) ? PLL_SOURCE_XTAL : PLL_SOURCE_CLKIN); + si5351c_input_t input = (source == CLOCK_SOURCE_HACKRF) ? SI5351C_INPUT_XTAL : + SI5351C_INPUT_CLKIN; + si5351c_change_input(&si5351c, input); + hackrf_ui()->set_clock_source(source); return source; diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index a7b605f5..23d18e93 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -48,7 +48,8 @@ si5351c_driver_t si5351c = { .i2c_address = 0x60, }; -static enum pll_sources active_clock_source = PLL_SOURCE_UNINITIALIZED; +static bool input_initialized = false; +static si5351c_input_t active_input; /* External clock output default is deactivated as it creates noise */ static bool clkout_enabled = false; static uint8_t outputs_disabled = 0xff; @@ -160,13 +161,11 @@ void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv) * CLKIN_DIV=0 (Divide by 1) * Set both PLLA_SRC and PLLB_SRC */ -void si5351c_configure_pll_sources( - si5351c_driver_t* const drv, - const enum pll_sources source) +void si5351c_configure_inputs(si5351c_driver_t* const drv, const si5351c_input_t input) { uint8_t data[] = {15, 0x00}; - if (source == PLL_SOURCE_CLKIN) { + if (input == SI5351C_INPUT_CLKIN) { data[1] = 0x0c; } si5351c_write(drv, data, sizeof(data)); @@ -175,11 +174,11 @@ void si5351c_configure_pll_sources( /* MultiSynth NA (PLLA) and NB (PLLB) */ void si5351c_configure_pll_multisynth( si5351c_driver_t* const drv, - const enum pll_sources source) + const si5351c_input_t input) { /* XTAL: 25 MHz * (0x0e00 + 512) / 128 = 800 MHz, integer mode */ uint8_t data[] = {26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00}; - if (source == PLL_SOURCE_CLKIN) { + if (input == SI5351C_INPUT_CLKIN) { /* CLKIN: 10 MHz * (0x2600 + 512) / 128 = 800 MHz, integer mode */ data[4] = 0x26; } @@ -415,9 +414,9 @@ void si5351c_set_int_mode( } } -void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source) +void si5351c_change_input(si5351c_driver_t* const drv, si5351c_input_t input) { - if (source == active_clock_source) { + if (input_initialized && input == active_input) { return; } si5351c_disable_all_outputs(drv); @@ -427,8 +426,8 @@ void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_source * HackRF One r9 always uses PLL A on the XTAL input * but externally switches that input to CLKIN. */ - si5351c_configure_pll_sources(drv, PLL_SOURCE_XTAL); - if (source == PLL_SOURCE_CLKIN) { + si5351c_configure_inputs(drv, SI5351C_INPUT_XTAL); + if (input == SI5351C_INPUT_CLKIN) { gpio_set(platform_gpio()->h1r9_clkin_en); } else { gpio_clear(platform_gpio()->h1r9_clkin_en); @@ -437,11 +436,12 @@ void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_source #endif #ifdef IS_NOT_H1_R9 if (IS_NOT_H1_R9) { - si5351c_configure_pll_sources(drv, source); + si5351c_configure_inputs(drv, input); } #endif - si5351c_configure_pll_multisynth(drv, source); - active_clock_source = source; + si5351c_configure_pll_multisynth(drv, input); + active_input = input; + input_initialized = true; si5351c_reset_pll(drv, SI5351C_PLL_BOTH); } diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index b38eac90..aedc7d05 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -64,11 +64,10 @@ typedef enum { #define SI5351C_CLK_PLL_SRC(x) ((x & SI5351C_PLL_B) << 4) -enum pll_sources { - PLL_SOURCE_UNINITIALIZED = -1, - PLL_SOURCE_XTAL = 0, - PLL_SOURCE_CLKIN = 1, -}; +typedef enum { + SI5351C_INPUT_XTAL = 0, + SI5351C_INPUT_CLKIN = 1, +} si5351c_input_t; typedef struct { i2c_bus_t* const bus; @@ -80,12 +79,10 @@ void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv); void si5351c_power_down_all_clocks(si5351c_driver_t* const drv); void si5351c_set_crystal_configuration(si5351c_driver_t* const drv); void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv); -void si5351c_configure_pll_sources( - si5351c_driver_t* const drv, - const enum pll_sources source); +void si5351c_configure_inputs(si5351c_driver_t* const drv, const si5351c_input_t input); void si5351c_configure_pll_multisynth( si5351c_driver_t* const drv, - const enum pll_sources source); + const si5351c_input_t input); void si5351c_reset_pll(si5351c_driver_t* const drv, si5351c_pll_t pll); void si5351c_configure_multisynth( si5351c_driver_t* const drv, @@ -100,7 +97,7 @@ void si5351c_set_int_mode( si5351c_driver_t* const drv, const uint_fast8_t ms_number, const uint_fast8_t on); -void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source); +void si5351c_change_input(si5351c_driver_t* const drv, const si5351c_input_t input); bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv); void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val); From 098b9dd9f20fd971efbd84429a8904d633092d12 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sun, 3 May 2026 09:19:45 +0100 Subject: [PATCH 194/238] si5351c: API: distinguish between PLL IDs and PLL masks. We're going to want a type that just identifies one PLL, and is consistent with how the PLLs are numbered in register settings. The current si5351c_pll_t is a bitmask which allows referring to both PLLs. Let's make that a different type, and name things more clearly when using it. --- firmware/common/clock_gen.c | 4 ++-- firmware/common/si5351c.c | 16 ++++++++-------- firmware/common/si5351c.h | 15 ++++++++++----- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/firmware/common/clock_gen.c b/firmware/common/clock_gen.c index f1f0bc60..e91e3822 100644 --- a/firmware/common/clock_gen.c +++ b/firmware/common/clock_gen.c @@ -113,7 +113,7 @@ void clock_gen_init(void) si5351c_configure_clock_control(&si5351c); si5351c_change_input(&si5351c, SI5351C_INPUT_XTAL); // soft reset - si5351c_reset_pll(&si5351c, SI5351C_PLL_BOTH); + si5351c_reset_plls(&si5351c, SI5351C_PLL_MASK_BOTH); si5351c_enable_clock_outputs(&si5351c); } @@ -412,7 +412,7 @@ fp_28_36_t sample_rate_set(const fp_28_36_t sample_rate, const bool program) } /* Reset PLL to synchronize output clock phase. */ - si5351c_reset_pll(&si5351c, SI5351C_PLL_A); + si5351c_reset_plls(&si5351c, SI5351C_PLL_MASK_A); } #endif diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 23d18e93..30c23129 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -91,7 +91,7 @@ void si5351c_disable_all_outputs(si5351c_driver_t* const drv) } /* Disable all CLKx outputs using selected PLL. */ -void si5351c_disable_pll_outputs(si5351c_driver_t* const drv, si5351c_pll_t pll) +void si5351c_disable_pll_outputs(si5351c_driver_t* const drv, si5351c_pll_mask_t mask) { /* * Bitmask defines outputs using PLL B. Other outputs are assumed to @@ -102,10 +102,10 @@ void si5351c_disable_pll_outputs(si5351c_driver_t* const drv, si5351c_pll_t pll) pllb_outputs = 0x30; } - if (pll & SI5351C_PLL_A) { + if (mask & SI5351C_PLL_MASK_A) { outputs_disabled |= ~pllb_outputs; } - if (pll & SI5351C_PLL_B) { + if (mask & SI5351C_PLL_MASK_B) { outputs_disabled |= pllb_outputs; } uint8_t data[] = {3, outputs_disabled}; @@ -189,18 +189,18 @@ void si5351c_configure_pll_multisynth( si5351c_write(drv, data, sizeof(data)); } -void si5351c_reset_pll(si5351c_driver_t* const drv, si5351c_pll_t pll) +void si5351c_reset_plls(si5351c_driver_t* const drv, si5351c_pll_mask_t mask) { uint8_t value = 0; - if (pll & SI5351C_PLL_A) { + if (mask & SI5351C_PLL_MASK_A) { value |= 0x20; } - if (pll & SI5351C_PLL_B) { + if (mask & SI5351C_PLL_MASK_B) { value |= 0x80; } - si5351c_disable_pll_outputs(drv, pll); + si5351c_disable_pll_outputs(drv, mask); uint8_t data[] = {177, value}; si5351c_write(drv, data, sizeof(data)); delay_us_at_mhz(2000, 204); @@ -442,7 +442,7 @@ void si5351c_change_input(si5351c_driver_t* const drv, si5351c_input_t input) si5351c_configure_pll_multisynth(drv, input); active_input = input; input_initialized = true; - si5351c_reset_pll(drv, SI5351C_PLL_BOTH); + si5351c_reset_plls(drv, SI5351C_PLL_MASK_BOTH); } bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv) diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index aedc7d05..491266cf 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -57,12 +57,17 @@ extern "C" { #define SI5351C_REVID 0x03 typedef enum { - SI5351C_PLL_A = 1, - SI5351C_PLL_B = 2, - SI5351C_PLL_BOTH = 3, + SI5351C_PLL_A = 0, + SI5351C_PLL_B = 1, } si5351c_pll_t; -#define SI5351C_CLK_PLL_SRC(x) ((x & SI5351C_PLL_B) << 4) +#define SI5351C_CLK_PLL_SRC(x) ((x & SI5351C_PLL_B) << 5) + +typedef enum { + SI5351C_PLL_MASK_A = 1, + SI5351C_PLL_MASK_B = 2, + SI5351C_PLL_MASK_BOTH = 3, +} si5351c_pll_mask_t; typedef enum { SI5351C_INPUT_XTAL = 0, @@ -83,7 +88,7 @@ void si5351c_configure_inputs(si5351c_driver_t* const drv, const si5351c_input_t void si5351c_configure_pll_multisynth( si5351c_driver_t* const drv, const si5351c_input_t input); -void si5351c_reset_pll(si5351c_driver_t* const drv, si5351c_pll_t pll); +void si5351c_reset_plls(si5351c_driver_t* const drv, si5351c_pll_mask_t mask); void si5351c_configure_multisynth( si5351c_driver_t* const drv, const uint_fast8_t ms_number, From a1cdbaddbf3bf20d74a3da7819093826d6d2a475 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sun, 3 May 2026 09:32:03 +0100 Subject: [PATCH 195/238] si5351c: internal: Add register definitions and helpers. --- firmware/common/si5351c_regs.def | 494 +++++++++++++++++++++++++++++++ 1 file changed, 494 insertions(+) create mode 100644 firmware/common/si5351c_regs.def diff --git a/firmware/common/si5351c_regs.def b/firmware/common/si5351c_regs.def new file mode 100644 index 00000000..5c3a6774 --- /dev/null +++ b/firmware/common/si5351c_regs.def @@ -0,0 +1,494 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +static inline void si5351c_reg_set_clean(si5351c_driver_t* drv, int reg) +{ + drv->regs_dirty[reg / 32] &= ~(1 << (reg % 32)); +} + +static inline void si5351c_reg_set_dirty(si5351c_driver_t* drv, int reg) +{ + drv->regs_dirty[reg / 32] |= (1 << (reg % 32)); +} + +static inline bool si5351c_reg_is_dirty(si5351c_driver_t* drv, int reg) +{ + return (drv->regs_dirty[reg / 32] & (1 << (reg % 32))) ? true : false; +} + +/* Generate static inline accessors that operate on the global + * regs. Done this way to (1) allow defs to be scraped out and used + * elsewhere, e.g. in scripts, (2) to avoid dealing with endian + * (structs). This may be used in firmware, or on host predefined + * register loads. */ + +/* On set_, register is always set dirty, even if nothing + * changed. This makes sure that writes that have side effects, + * e.g. frequency setting, are not skipped. */ + +/* n=name, r=regnum, o=offset (bits from LSB) of LSB of field, + * l=length (bits) */ +#define __MREG__(n,r,o,l) \ +static inline uint8_t get_##n(si5351c_driver_t* const _d) { \ + return (_d->regs[r] >> o) & ((1L<regs[r] &= (uint8_t)(~(((1L<regs[r] |= (uint8_t)(((v&((1L<> 8); \ + set_##n##_BOT(_d, v); \ +} + +#define __3PART__(n) \ +static inline uint32_t get_##n(si5351c_driver_t* const _d) { \ + return (get_##n##_TOP(_d) << 16) | (get_##n##_MID(_d) << 8) | get_##n##_BOT(_d); \ +} \ +static inline void set_##n(si5351c_driver_t* const _d, uint32_t v) { \ + set_##n##_TOP(_d, v >> 16); \ + set_##n##_MID(_d, v >> 8); \ + set_##n##_BOT(_d, v); \ +} + +/* Generate accessors for per-PLL and per-multisynth registers */ +/* n=name, p=prefix, s=suffix */ + +#define __PER_PLL__(n, p, s) \ +static inline uint32_t get_##n(si5351c_driver_t* const _d, si5351c_pll_t pll) { \ + return (pll == SI5351C_PLL_A) ? get_##p##A##s(_d) : get_##p##B##s(_d); \ +} \ +static inline void set_##n(si5351c_driver_t* const _d, si5351c_pll_t pll, uint32_t v) { \ + if (pll == SI5351C_PLL_A) { \ + set_##p##A##s(_d, v); \ + } else { \ + set_##p##B##s(_d, v); \ + } \ +} + +#define __PER_MS__(n, p, s) \ +static inline uint32_t get_##n(si5351c_driver_t* const _d, uint8_t i) { \ + switch (i) { \ + case 0: return get_##p##0##s(_d); \ + case 1: return get_##p##1##s(_d); \ + case 2: return get_##p##2##s(_d); \ + case 3: return get_##p##3##s(_d); \ + case 4: return get_##p##4##s(_d); \ + case 5: return get_##p##5##s(_d); \ + case 6: return get_##p##6##s(_d); \ + case 7: return get_##p##7##s(_d); \ + default: return 0; \ + } \ +} \ +static inline void set_##n(si5351c_driver_t* const _d, uint8_t i, uint32_t v) { \ + switch (i) { \ + case 0: set_##p##0##s(_d, v); return; \ + case 1: set_##p##1##s(_d, v); return; \ + case 2: set_##p##2##s(_d, v); return; \ + case 3: set_##p##3##s(_d, v); return; \ + case 4: set_##p##4##s(_d, v); return; \ + case 5: set_##p##5##s(_d, v); return; \ + case 6: set_##p##6##s(_d, v); return; \ + case 7: set_##p##7##s(_d, v); return; \ + } \ +} \ +static inline void set_all_##n(si5351c_driver_t* const _d, uint32_t v) { \ + set_##p##0##s(_d, v); \ + set_##p##1##s(_d, v); \ + set_##p##2##s(_d, v); \ + set_##p##3##s(_d, v); \ + set_##p##4##s(_d, v); \ + set_##p##5##s(_d, v); \ + set_##p##6##s(_d, v); \ + set_##p##7##s(_d, v); \ +} + +#define __PER_FRAC_MS__(n, p, s) \ +static inline void set_##n(si5351c_driver_t* const _d, uint8_t i, uint32_t v) { \ + switch (i) { \ + case 0: set_##p##0##s(_d, v); return; \ + case 1: set_##p##1##s(_d, v); return; \ + case 2: set_##p##2##s(_d, v); return; \ + case 3: set_##p##3##s(_d, v); return; \ + case 4: set_##p##4##s(_d, v); return; \ + case 5: set_##p##5##s(_d, v); return; \ + } \ +} + +/* Register 0: Device Status */ +__MREG__(SYS_INIT, 0, 7, 1) +__MREG__(LOL_B, 0, 6, 1) +__MREG__(LOL_A, 0, 5, 1) +__MREG__(LOS_CLKIN, 0, 4, 1) +__MREG__(LOS_XTAL, 0, 3, 1) +__MREG__(REVID, 0, 0, 2) + +/* Register 1: Interrupt Status Sticky */ +__MREG__(SYS_INIT_STKY, 1, 7, 1) +__MREG__(LOL_B_STKY, 1, 6, 1) +__MREG__(LOL_A_STKY, 1, 5, 1) +__MREG__(LOS_CLKIN_STKY, 1, 4, 1) +__MREG__(LOS_XTAL_STKY, 1, 3, 1) + +/* Register 2: Interrupt Status Mask */ +__MREG__(SYS_INIT_MASK, 2, 7, 1) +__MREG__(LOL_B_MASK, 2, 6, 1) +__MREG__(LOL_A_MASK, 2, 5, 1) +__MREG__(LOS_CLKIN_MASK, 2, 4, 1) +__MREG__(LOS_XTAL_MASK, 2, 3, 1) + +/* Register 3: Output Enable Control */ +__MREG__(CLK7_OEB, 3, 7, 1) +__MREG__(CLK6_OEB, 3, 6, 1) +__MREG__(CLK5_OEB, 3, 5, 1) +__MREG__(CLK4_OEB, 3, 4, 1) +__MREG__(CLK3_OEB, 3, 3, 1) +__MREG__(CLK2_OEB, 3, 2, 1) +__MREG__(CLK1_OEB, 3, 1, 1) +__MREG__(CLK0_OEB, 3, 0, 1) + +/* Register 4: OEB Pin Enable Control */ +__MREG__(OEB_CLK7, 4, 7, 1) +__MREG__(OEB_CLK6, 4, 6, 1) +__MREG__(OEB_CLK5, 4, 5, 1) +__MREG__(OEB_CLK4, 4, 4, 1) +__MREG__(OEB_CLK3, 4, 3, 1) +__MREG__(OEB_CLK2, 4, 2, 1) +__MREG__(OEB_CLK1, 4, 1, 1) +__MREG__(OEB_CLK0, 4, 0, 1) + +/* Register 9: OEB Pin Enable Control Mask */ +__MREG__(OEB_MASK7, 9, 7, 1) +__MREG__(OEB_MASK6, 9, 6, 1) +__MREG__(OEB_MASK5, 9, 5, 1) +__MREG__(OEB_MASK4, 9, 4, 1) +__MREG__(OEB_MASK3, 9, 3, 1) +__MREG__(OEB_MASK2, 9, 2, 1) +__MREG__(OEB_MASK1, 9, 1, 1) +__MREG__(OEB_MASK0, 9, 0, 1) + +/* Register 15: PLL Input Source */ +__MREG__(CLKIN_DIV, 15, 6, 2) +__MREG__(PLLB_SRC, 15, 3, 1) +__MREG__(PLLA_SRC, 15, 2, 1) + +/* Register 16: CLK0 Control */ +__MREG__(CLK0_PDN, 16, 7, 1) +__MREG__(MS0_INT, 16, 6, 1) +__MREG__(MS0_SRC, 16, 5, 1) +__MREG__(CLK0_INV, 16, 4, 1) +__MREG__(CLK0_SRC, 16, 2, 2) +__MREG__(CLK0_IDRV, 16, 0, 2) + +/* Register 17: CLK1 Control */ +__MREG__(CLK1_PDN, 17, 7, 1) +__MREG__(MS1_INT, 17, 6, 1) +__MREG__(MS1_SRC, 17, 5, 1) +__MREG__(CLK1_INV, 17, 4, 1) +__MREG__(CLK1_SRC, 17, 2, 2) +__MREG__(CLK1_IDRV, 17, 0, 2) + +/* Register 18: CLK2 Control */ +__MREG__(CLK2_PDN, 18, 7, 1) +__MREG__(MS2_INT, 18, 6, 1) +__MREG__(MS2_SRC, 18, 5, 1) +__MREG__(CLK2_INV, 18, 4, 1) +__MREG__(CLK2_SRC, 18, 2, 2) +__MREG__(CLK2_IDRV, 18, 0, 2) + +/* Register 19: CLK3 Control */ +__MREG__(CLK3_PDN, 19, 7, 1) +__MREG__(MS3_INT, 19, 6, 1) +__MREG__(MS3_SRC, 19, 5, 1) +__MREG__(CLK3_INV, 19, 4, 1) +__MREG__(CLK3_SRC, 19, 2, 2) +__MREG__(CLK3_IDRV, 19, 0, 2) + +/* Register 20: CLK4 Control */ +__MREG__(CLK4_PDN, 20, 7, 1) +__MREG__(MS4_INT, 20, 6, 1) +__MREG__(MS4_SRC, 20, 5, 1) +__MREG__(CLK4_INV, 20, 4, 1) +__MREG__(CLK4_SRC, 20, 2, 2) +__MREG__(CLK4_IDRV, 20, 0, 2) + +/* Register 21: CLK5 Control */ +__MREG__(CLK5_PDN, 21, 7, 1) +__MREG__(MS5_INT, 21, 6, 1) +__MREG__(MS5_SRC, 21, 5, 1) +__MREG__(CLK5_INV, 21, 4, 1) +__MREG__(CLK5_SRC, 21, 2, 2) +__MREG__(CLK5_IDRV, 21, 0, 2) + +/* Register 22: CLK6 Control */ +__MREG__(CLK6_PDN, 22, 7, 1) +__MREG__(FBA_INT, 22, 6, 1) +__MREG__(MS6_SRC, 22, 5, 1) +__MREG__(CLK6_INV, 22, 4, 1) +__MREG__(CLK6_SRC, 22, 2, 2) +__MREG__(CLK6_IDRV, 22, 0, 2) + +/* Register 23: CLK7 Control */ +__MREG__(CLK7_PDN, 23, 7, 1) +__MREG__(FBB_INT, 23, 6, 1) +__MREG__(MS7_SRC, 23, 5, 1) +__MREG__(CLK7_INV, 23, 4, 1) +__MREG__(CLK7_SRC, 23, 2, 2) +__MREG__(CLK7_IDRV, 23, 0, 2) + +/* Register 24: CLK0-CLK3 Disable State */ +__MREG__(CLK3_DIS_STATE, 24, 6, 2) +__MREG__(CLK2_DIS_STATE, 24, 4, 2) +__MREG__(CLK1_DIS_STATE, 24, 2, 2) +__MREG__(CLK0_DIS_STATE, 24, 0, 2) + +/* Register 25: CLK4-CLK7 Disable State */ +__MREG__(CLK7_DIS_STATE, 25, 6, 2) +__MREG__(CLK6_DIS_STATE, 25, 4, 2) +__MREG__(CLK5_DIS_STATE, 25, 2, 2) +__MREG__(CLK4_DIS_STATE, 25, 0, 2) + +/* Registers 26-33: Multisynth NA Parameters */ +__MREG__(MSNA_P3_MID, 26, 0, 8) +__MREG__(MSNA_P3_BOT, 27, 0, 8) +__MREG__(MSNA_P1_TOP, 28, 0, 2) +__MREG__(MSNA_P1_MID, 29, 0, 8) +__MREG__(MSNA_P1_BOT, 30, 0, 8) +__MREG__(MSNA_P3_TOP, 31, 4, 4) +__MREG__(MSNA_P2_TOP, 31, 0, 4) +__MREG__(MSNA_P2_MID, 32, 0, 8) +__MREG__(MSNA_P2_BOT, 33, 0, 8) + +/* Registers 34-41: Multisynth NB Parameters */ +__MREG__(MSNB_P3_MID, 34, 0, 8) +__MREG__(MSNB_P3_BOT, 35, 0, 8) +__MREG__(MSNB_P1_TOP, 36, 0, 2) +__MREG__(MSNB_P1_MID, 37, 0, 8) +__MREG__(MSNB_P1_BOT, 38, 0, 8) +__MREG__(MSNB_P3_TOP, 39, 4, 4) +__MREG__(MSNB_P2_TOP, 39, 0, 4) +__MREG__(MSNB_P2_MID, 40, 0, 8) +__MREG__(MSNB_P2_BOT, 41, 0, 8) + +/* Registers 42-49: Multisynth 0 Parameters */ +__MREG__(MS0_P3_MID, 42, 0, 8) +__MREG__(MS0_P3_BOT, 43, 0, 8) +__MREG__(R0_DIV, 44, 4, 3) +__MREG__(MS0_DIVBY4, 44, 2, 2) +__MREG__(MS0_P1_TOP, 44, 0, 2) +__MREG__(MS0_P1_MID, 45, 0, 8) +__MREG__(MS0_P1_BOT, 46, 0, 8) +__MREG__(MS0_P3_TOP, 47, 4, 4) +__MREG__(MS0_P2_TOP, 47, 0, 4) +__MREG__(MS0_P2_MID, 48, 0, 8) +__MREG__(MS0_P2_BOT, 49, 0, 8) + +/* Registers 50-57: Multisynth 1 Parameters */ +__MREG__(MS1_P3_MID, 50, 0, 8) +__MREG__(MS1_P3_BOT, 51, 0, 8) +__MREG__(R1_DIV, 52, 4, 3) +__MREG__(MS1_DIVBY4, 52, 2, 2) +__MREG__(MS1_P1_TOP, 52, 0, 2) +__MREG__(MS1_P1_MID, 53, 0, 8) +__MREG__(MS1_P1_BOT, 54, 0, 8) +__MREG__(MS1_P3_TOP, 55, 4, 4) +__MREG__(MS1_P2_TOP, 55, 0, 4) +__MREG__(MS1_P2_MID, 56, 0, 8) +__MREG__(MS1_P2_BOT, 57, 0, 8) + +/* Registers 58-65: Multisynth 2 Parameters */ +__MREG__(MS2_P3_MID, 58, 0, 8) +__MREG__(MS2_P3_BOT, 59, 0, 8) +__MREG__(R2_DIV, 60, 4, 3) +__MREG__(MS2_DIVBY4, 60, 2, 2) +__MREG__(MS2_P1_TOP, 60, 0, 2) +__MREG__(MS2_P1_MID, 61, 0, 8) +__MREG__(MS2_P1_BOT, 62, 0, 8) +__MREG__(MS2_P3_TOP, 63, 4, 4) +__MREG__(MS2_P2_TOP, 63, 0, 4) +__MREG__(MS2_P2_MID, 64, 0, 8) +__MREG__(MS2_P2_BOT, 65, 0, 8) + +/* Registers 66-73: Multisynth 3 Parameters */ +__MREG__(MS3_P3_MID, 66, 0, 8) +__MREG__(MS3_P3_BOT, 67, 0, 8) +__MREG__(R3_DIV, 68, 4, 3) +__MREG__(MS3_DIVBY4, 68, 2, 2) +__MREG__(MS3_P1_TOP, 68, 0, 2) +__MREG__(MS3_P1_MID, 69, 0, 8) +__MREG__(MS3_P1_BOT, 70, 0, 8) +__MREG__(MS3_P3_TOP, 71, 4, 4) +__MREG__(MS3_P2_TOP, 71, 0, 4) +__MREG__(MS3_P2_MID, 72, 0, 8) +__MREG__(MS3_P2_BOT, 73, 0, 8) + +/* Registers 74-81: Multisynth 4 Parameters */ +__MREG__(MS4_P3_MID, 74, 0, 8) +__MREG__(MS4_P3_BOT, 75, 0, 8) +__MREG__(R4_DIV, 76, 4, 3) +__MREG__(MS4_DIVBY4, 76, 2, 2) +__MREG__(MS4_P1_TOP, 76, 0, 2) +__MREG__(MS4_P1_MID, 77, 0, 8) +__MREG__(MS4_P1_BOT, 78, 0, 8) +__MREG__(MS4_P3_TOP, 79, 4, 4) +__MREG__(MS4_P2_TOP, 79, 0, 4) +__MREG__(MS4_P2_MID, 80, 0, 8) +__MREG__(MS4_P2_BOT, 81, 0, 8) + +/* Registers 82-89: Multisynth 5 Parameters */ +__MREG__(MS5_P3_MID, 82, 0, 8) +__MREG__(MS5_P3_BOT, 83, 0, 8) +__MREG__(R5_DIV, 84, 4, 3) +__MREG__(MS5_DIVBY4, 84, 2, 2) +__MREG__(MS5_P1_TOP, 84, 0, 2) +__MREG__(MS5_P1_MID, 85, 0, 8) +__MREG__(MS5_P1_BOT, 86, 0, 8) +__MREG__(MS5_P3_TOP, 87, 4, 4) +__MREG__(MS5_P2_TOP, 87, 0, 4) +__MREG__(MS5_P2_MID, 88, 0, 8) +__MREG__(MS5_P2_BOT, 89, 0, 8) + +/* Register 90: Multisynth 6 Parameters */ +__MREG__(MS6_P1, 90, 0, 8) + +/* Register 91: Multisynth 7 Parameters */ +__MREG__(MS7_P1, 91, 0, 8) + +/* Register 92: Clock 6 and 7 Output Divider */ +__MREG__(R7_DIV, 92, 4, 3) +__MREG__(R6_DIV, 92, 0, 3) + +/* Registers 149-161: Spread Spectrum Parameters */ +__MREG__(SSC_EN, 149, 7, 1) +__MREG__(SSDN_P2_TOP, 149, 0, 7) +__MREG__(SSDN_P2_BOT, 150, 0, 8) +__MREG__(SSC_MODE, 151, 7, 1) +__MREG__(SSDN_P3_TOP, 151, 0, 7) +__MREG__(SSDN_P3_BOT, 152, 0, 8) +__MREG__(SSDN_P1_BOT, 153, 0, 8) +__MREG__(SSUDP_TOP, 154, 4, 4) +__MREG__(SSDN_P1_TOP, 154, 0, 4) +__MREG__(SSUDP_BOT, 155, 0, 8) +__MREG__(SSUP_P2_TOP, 156, 0, 7) +__MREG__(SSUP_P2_BOT, 157, 0, 8) +__MREG__(SSUP_P3_TOP, 158, 0, 8) +__MREG__(SSUP_P3_BOT, 159, 0, 8) +__MREG__(SSUP_P1_BOT, 160, 0, 8) +__MREG__(SS_NCLK, 161, 4, 4) +__MREG__(SSUP_P1_TOP, 161, 0, 4) + +/* Registers 162-163: VCXO Parameter */ +__MREG__(VCXO_PARAM_BOT, 162, 0, 8) +__MREG__(VCXO_PARAM_MID, 163, 0, 8) +__MREG__(VCXO_PARAM_TOP, 164, 0, 6) + +/* Registers 165-170: CLK0-CLK5 Initial Phase Offsets */ +__MREG__(CLK0_PHOFF, 165, 0, 7) +__MREG__(CLK1_PHOFF, 166, 0, 7) +__MREG__(CLK2_PHOFF, 167, 0, 7) +__MREG__(CLK3_PHOFF, 168, 0, 7) +__MREG__(CLK4_PHOFF, 169, 0, 7) +__MREG__(CLK5_PHOFF, 170, 0, 7) + +/* Register 177: PLL Reset */ +__MREG__(PLLB_RST, 177, 7, 1) +__MREG__(PLLA_RST, 177, 5, 1) + +/* Register 183: Crystal Internal Load Capacitance */ +__MREG__(XTAL_CL, 183, 6, 2) + +/* Register 187: Fanout Enable */ +__MREG__(CLKIN_FANOUT_EN, 187, 7, 1) +__MREG__(XO_FANOUT_EN, 187, 6, 1) +__MREG__(MS_FANOUT_EN, 187, 4, 1) + +/* 3-part parameters */ +__3PART__(MSNA_P1) +__3PART__(MSNA_P2) +__3PART__(MSNA_P3) +__3PART__(MSNB_P1) +__3PART__(MSNB_P2) +__3PART__(MSNB_P3) +__3PART__(MS0_P1) +__3PART__(MS0_P2) +__3PART__(MS0_P3) +__3PART__(MS1_P1) +__3PART__(MS1_P2) +__3PART__(MS1_P3) +__3PART__(MS2_P1) +__3PART__(MS2_P2) +__3PART__(MS2_P3) +__3PART__(MS3_P1) +__3PART__(MS3_P2) +__3PART__(MS3_P3) +__3PART__(MS4_P1) +__3PART__(MS4_P2) +__3PART__(MS4_P3) +__3PART__(MS5_P1) +__3PART__(MS5_P2) +__3PART__(MS5_P3) + +/* 2-part parameters */ +__2PART__(SSDN_P1) +__2PART__(SSDN_P2) +__2PART__(SSDN_P3) +__2PART__(SSUP_P1) +__2PART__(SSUP_P2) +__2PART__(SSUP_P3) +__2PART__(SSUDP) + +/* Per-PLL register groups */ +__PER_PLL__(LOL, LOL_, ) +__PER_PLL__(LOL_STKY, LOL_, _STKY) +__PER_PLL__(LOL_MASK, LOL_, _MASK) +__PER_PLL__(PLL_SRC, PLL, _SRC) +__PER_PLL__(MSN_P1, MSN, _P1) +__PER_PLL__(MSN_P2, MSN, _P2) +__PER_PLL__(MSN_P3, MSN, _P3) +__PER_PLL__(PLL_RST, PLL, _RST) + +/* Per-multisynth register groups */ +__PER_MS__(CLK_OEB, CLK, _OEB) +__PER_MS__(OEB_CLK, OEB_CLK, ) +__PER_MS__(OEB_MASK, OEB_MASK, ) +__PER_MS__(CLK_PDN, CLK, _PDN) +__PER_MS__(MS_SRC, MS, _SRC) +__PER_MS__(CLK_INV, CLK, _INV) +__PER_MS__(CLK_SRC, CLK, _SRC) +__PER_MS__(CLK_IDRV, CLK, _IDRV) +__PER_MS__(CLK_DIS_STATE, CLK, _DIS_STATE) +__PER_MS__(R_DIV, R, _DIV) +__PER_MS__(MS_P1, MS, _P1) +__PER_FRAC_MS__(MS_INT, MS, _INT) +__PER_FRAC_MS__(MS_P2, MS, _P2) +__PER_FRAC_MS__(MS_P3, MS, _P3) +__PER_FRAC_MS__(MS_DIVBY4, MS, _DIVBY4) +__PER_FRAC_MS__(CLK_PHOFF, CLK, _PHOFF) From 016910567bc236fcfb14ebb741185c468416cda8 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sun, 3 May 2026 09:32:58 +0100 Subject: [PATCH 196/238] si5351c: internal: reimplement using register helpers. --- firmware/common/si5351c.c | 480 +++++++++++++++++++++++--------------- firmware/common/si5351c.h | 72 ++++-- 2 files changed, 336 insertions(+), 216 deletions(-) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 30c23129..1f27d8db 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Jared Boone * * This file is part of HackRF. @@ -22,6 +22,7 @@ #include #include +#include #include "clock_io.h" #include "delay.h" @@ -36,6 +37,8 @@ #include "platform_scu.h" #endif +#include "si5351c_regs.def" + /* Driver instance. */ // const i2c_lpc_config_t i2c_config_si5351c_slow_clock = { // .duty_cycle_count = 15, @@ -52,13 +55,16 @@ static bool input_initialized = false; static si5351c_input_t active_input; /* External clock output default is deactivated as it creates noise */ static bool clkout_enabled = false; -static uint8_t outputs_disabled = 0xff; /* write to single register */ void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val) { const uint8_t data_tx[] = {reg, val}; - si5351c_write(drv, data_tx, 2); + i2c_bus_transfer(drv->bus, drv->i2c_address, data_tx, 2, NULL, 0); + if (reg < SI5351C_CACHED_REGS) { + drv->regs[reg] = val; + si5351c_reg_set_clean(drv, reg); + } } /* read single register */ @@ -67,72 +73,100 @@ uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg) const uint8_t data_tx[] = {reg}; uint8_t data_rx[] = {0x00}; i2c_bus_transfer(drv->bus, drv->i2c_address, data_tx, 1, data_rx, 1); - return data_rx[0]; + uint8_t val = data_rx[0]; + if (reg < SI5351C_CACHED_REGS) { + drv->regs[reg] = val; + si5351c_reg_set_clean(drv, reg); + } + return val; } -/* - * Write to one or more contiguous registers. data[0] should be the first - * register number, one or more values follow. - */ -void si5351c_write( - si5351c_driver_t* const drv, - const uint8_t* const data, - const size_t data_count) +/* Commit changes to register values. */ +void si5351c_regs_commit(si5351c_driver_t* drv) { - i2c_bus_transfer(drv->bus, drv->i2c_address, data, data_count, NULL, 0); + for (int start = 0; start < SI5351C_CACHED_REGS; start++) { + if (si5351c_reg_is_dirty(drv, start)) { + if (start == SI5351C_CACHED_REGS - 1) { + si5351c_write_single(drv, start, drv->regs[start]); + } else { + int end; + for (end = start + 1; end < 256; end++) { + if (!si5351c_reg_is_dirty(drv, end)) + break; + } + size_t len = 1 + (end - start); + uint8_t data_tx[len]; + data_tx[0] = start; + for (int i = 0; i < (end - start); i++) { + data_tx[1 + i] = drv->regs[start + i]; + } + i2c_bus_transfer( + drv->bus, + drv->i2c_address, + data_tx, + len, + NULL, + 0); + for (int i = start; i < end; i++) { + si5351c_reg_set_clean(drv, i); + } + start = end; + } + } + } + + /* Reset bits are self-clearing. */ + drv->regs[177] = 0; } /* Disable all CLKx outputs. */ void si5351c_disable_all_outputs(si5351c_driver_t* const drv) { - outputs_disabled = 0xff; - uint8_t data[] = {3, outputs_disabled}; - si5351c_write(drv, data, sizeof(data)); + set_all_CLK_OEB(drv, SI5351C_OUTPUT_DISABLE); + si5351c_regs_commit(drv); } /* Disable all CLKx outputs using selected PLL. */ void si5351c_disable_pll_outputs(si5351c_driver_t* const drv, si5351c_pll_mask_t mask) { - /* - * Bitmask defines outputs using PLL B. Other outputs are assumed to - * use PLL A. - */ - uint8_t pllb_outputs = 0x00; - if (detected_platform() == BOARD_ID_PRALINE) { - pllb_outputs = 0x30; + /* For each CLKx output, check if it is using the specified PLL. */ + for (int op = 0; op < 8; op++) { + int ms; + /* First check which multisynth is used by this output. */ + switch (get_CLK_SRC(drv, op)) { + case SI5351C_SRC_MULTISYNTH_SELF: + ms = op; + break; + case SI5351C_SRC_MULTISYNTH_0_4: + ms = (op < 4) ? 0 : 4; + break; + default: + /* This output is not using any PLL */ + continue; + } + /* Now check which PLL is used by that multisynth. */ + if (mask & (1 << get_MS_SRC(drv, ms))) { + /* This output depends on the specified PLL; disable it. */ + set_CLK_OEB(drv, op, SI5351C_OUTPUT_DISABLE); + } } - - if (mask & SI5351C_PLL_MASK_A) { - outputs_disabled |= ~pllb_outputs; - } - if (mask & SI5351C_PLL_MASK_B) { - outputs_disabled |= pllb_outputs; - } - uint8_t data[] = {3, outputs_disabled}; - si5351c_write(drv, data, sizeof(data)); + si5351c_regs_commit(drv); } /* Turn off OEB pin control for all CLKx */ void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv) { - uint8_t data[] = {9, 0xFF}; - si5351c_write(drv, data, sizeof(data)); + set_all_OEB_MASK(drv, true); + si5351c_regs_commit(drv); } /* Power down all CLKx */ void si5351c_power_down_all_clocks(si5351c_driver_t* const drv) { - uint8_t data[] = { - 16, - SI5351C_CLK_POWERDOWN, - SI5351C_CLK_POWERDOWN, - SI5351C_CLK_POWERDOWN, - SI5351C_CLK_POWERDOWN, - SI5351C_CLK_POWERDOWN, - SI5351C_CLK_POWERDOWN, - SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE, - SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE}; - si5351c_write(drv, data, sizeof(data)); + set_all_CLK_PDN(drv, true); + set_FBA_INT(drv, true); + set_FBB_INT(drv, true); + si5351c_regs_commit(drv); } /* @@ -142,8 +176,8 @@ void si5351c_power_down_all_clocks(si5351c_driver_t* const drv) */ void si5351c_set_crystal_configuration(si5351c_driver_t* const drv) { - uint8_t data[] = {183, 0x80}; - si5351c_write(drv, data, sizeof(data)); + set_XTAL_CL(drv, SI5351C_XTAL_8PF); + si5351c_regs_commit(drv); } /* @@ -152,8 +186,10 @@ void si5351c_set_crystal_configuration(si5351c_driver_t* const drv) */ void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv) { - uint8_t data[] = {187, 0xD0}; - si5351c_write(drv, data, sizeof(data)); + set_CLKIN_FANOUT_EN(drv, true); + set_XO_FANOUT_EN(drv, true); + set_MS_FANOUT_EN(drv, true); + si5351c_regs_commit(drv); } /* @@ -163,12 +199,10 @@ void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv) */ void si5351c_configure_inputs(si5351c_driver_t* const drv, const si5351c_input_t input) { - uint8_t data[] = {15, 0x00}; - - if (input == SI5351C_INPUT_CLKIN) { - data[1] = 0x0c; - } - si5351c_write(drv, data, sizeof(data)); + set_CLKIN_DIV(drv, SI5351C_DIV_1); + set_PLLA_SRC(drv, input); + set_PLLB_SRC(drv, input); + si5351c_regs_commit(drv); } /* MultiSynth NA (PLLA) and NB (PLLB) */ @@ -176,33 +210,26 @@ void si5351c_configure_pll_multisynth( si5351c_driver_t* const drv, const si5351c_input_t input) { - /* XTAL: 25 MHz * (0x0e00 + 512) / 128 = 800 MHz, integer mode */ - uint8_t data[] = {26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00}; - if (input == SI5351C_INPUT_CLKIN) { - /* CLKIN: 10 MHz * (0x2600 + 512) / 128 = 800 MHz, integer mode */ - data[4] = 0x26; + for (si5351c_pll_t pll = SI5351C_PLL_A; pll <= SI5351C_PLL_B; pll++) { + if (input == SI5351C_INPUT_CLKIN) { + /* CLKIN: 10 MHz * (0x2600 + 512) / 128 = 800 MHz, integer mode */ + set_MSN_P1(drv, pll, 0x2600); + } else { + /* XTAL: 25 MHz * (0x0e00 + 512) / 128 = 800 MHz, integer mode */ + set_MSN_P1(drv, pll, 0x0E00); + } + set_MSN_P2(drv, pll, 0); + set_MSN_P3(drv, pll, 1); } - si5351c_write(drv, data, sizeof(data)); - - /* Apply same configuration to PLL B. */ - data[0] = 34; - si5351c_write(drv, data, sizeof(data)); + si5351c_regs_commit(drv); } void si5351c_reset_plls(si5351c_driver_t* const drv, si5351c_pll_mask_t mask) { - uint8_t value = 0; - - if (mask & SI5351C_PLL_MASK_A) { - value |= 0x20; - } - if (mask & SI5351C_PLL_MASK_B) { - value |= 0x80; - } - si5351c_disable_pll_outputs(drv, mask); - uint8_t data[] = {177, value}; - si5351c_write(drv, data, sizeof(data)); + set_PLLA_RST(drv, (mask & SI5351C_PLL_MASK_A) ? true : false); + set_PLLB_RST(drv, (mask & SI5351C_PLL_MASK_B) ? true : false); + si5351c_regs_commit(drv); delay_us_at_mhz(2000, 204); si5351c_enable_clock_outputs(drv); } @@ -227,110 +254,166 @@ void si5351c_configure_multisynth( * ... * 7 means divide by 128 */ - const uint_fast8_t register_number = 42 + (ms_number * 8); - uint8_t data[] = { - register_number, - (p3 >> 8) & 0xFF, - (p3 >> 0) & 0xFF, - (r_div << 4) | (0 << 2) | ((p1 >> 16) & 0x3), - (p1 >> 8) & 0xFF, - (p1 >> 0) & 0xFF, - (((p3 >> 16) & 0xF) << 4) | (((p2 >> 16) & 0xF) << 0), - (p2 >> 8) & 0xFF, - (p2 >> 0) & 0xFF}; - si5351c_write(drv, data, sizeof(data)); + set_MS_P1(drv, ms_number, p1); + set_MS_P2(drv, ms_number, p2); + set_MS_P3(drv, ms_number, p3); + set_R_DIV(drv, ms_number, r_div); + si5351c_regs_commit(drv); } void si5351c_configure_clock_control(si5351c_driver_t* const drv) { - uint8_t clkout_ctrl; + si5351c_clk_ctrl_t clkout = { + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_8MA, + }; - if (clkout_enabled) { - clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA); - } else { - clkout_ctrl = SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE; + si5351c_clk_ctrl_t powered_down = { + .power_down = true, + .mode = SI5351C_MODE_INT, + }; + + if (!clkout_enabled) { + clkout = powered_down; } + si5351c_clk_ctrl_t clk[8]; + /* Clock to CPU is deactivated as it is not used and creates noise */ /* External clock output is kept in current state */ - uint8_t data[] = { - 16, - SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA), - SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA) | SI5351C_CLK_INV, - SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA), - clkout_ctrl, - SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA) | SI5351C_CLK_INV, - SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA), - SI5351C_CLK_POWERDOWN | - SI5351C_CLK_INT_MODE, /* not connected, but: PLL A int mode */ - SI5351C_CLK_POWERDOWN | - SI5351C_CLK_INT_MODE /* not connected, but: PLL B int mode */ + + /* CLK0: MAX5864/CPLD */ + clk[0] = (si5351c_clk_ctrl_t){ + .mode = SI5351C_MODE_FRAC, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_8MA, }; + /* CLK1: CPLD */ + clk[1] = (si5351c_clk_ctrl_t){ + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_0_4, + .drive = SI5351C_DRIVE_2MA, + .invert = true, + }; + /* CLK2: SGPIO */ + clk[2] = (si5351c_clk_ctrl_t){ + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_0_4, + .drive = SI5351C_DRIVE_2MA, + }; + /* CLK3: CLKOUT */ + clk[3] = clkout; + /* CLK4: RFFC5072 (MAX2837 on rad1o) */ + clk[4] = (si5351c_clk_ctrl_t){ + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_6MA, + .invert = true, + }; + /* CLK5: MAX2837 (MAX2871 on rad1o) */ + clk[5] = (si5351c_clk_ctrl_t){ + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_4MA, + }; + /* CLK6: none */ + clk[6] = powered_down; + /* CLK7: LPC43xx */ + clk[7] = powered_down; + #ifdef IS_H1_R9 if (IS_H1_R9) { - data[1] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA); - data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA); - data[3] = clkout_ctrl; - data[4] = SI5351C_CLK_POWERDOWN; - data[5] = SI5351C_CLK_POWERDOWN; - data[6] = SI5351C_CLK_POWERDOWN; + /* CLK0: MAX5864/CPLD/SGPIO (sample clocks) */ + clk[0] = (si5351c_clk_ctrl_t){ + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_6MA, + }; + /* CLK1: RFFC5072/MAX2839 */ + clk[1] = (si5351c_clk_ctrl_t){ + .mode = SI5351C_MODE_FRAC, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_4MA, + }; + /* CLK2: CLKOUT/LPC4320 */ + clk[2] = clkout; + /* Other outputs not present on Si5351A */ + clk[3] = powered_down; + clk[4] = powered_down; + clk[5] = powered_down; + clk[6] = powered_down; + clk[7] = powered_down; } #endif #ifdef IS_PRALINE if (IS_PRALINE) { /* CLK0: AFE_CLK */ - data[1] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA); + clk[0] = (si5351c_clk_ctrl_t){ + .mode = SI5351C_MODE_FRAC, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_4MA, + }; /* CLK1: SCT_CLK and FPGA_CLK */ - data[2] = SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA); + clk[1] = (si5351c_clk_ctrl_t){ + .mode = SI5351C_MODE_FRAC, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_2MA, + }; /* CLK3: CLKOUT */ - clkout_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA); + clkout.pll = SI5351C_PLL_B; + clk[3] = clkout; /* CLK4: XCVR_CLK */ - data[5] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA) | SI5351C_CLK_INV; - data[6] = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_PLL_B) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA); + clk[4] = (si5351c_clk_ctrl_t){ + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_B, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_4MA, + .invert = true, + }; + /* CLK5: MIX_CLK */ + clk[5] = (si5351c_clk_ctrl_t){ + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_B, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_4MA, + }; if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { /* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */ - data[3] = SI5351C_CLK_FRAC_MODE | - SI5351C_CLK_PLL_SRC(SI5351C_PLL_A) | - SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | - SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA); + clk[2] = (si5351c_clk_ctrl_t){ + .mode = SI5351C_MODE_FRAC, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_2MA, + }; } else { /* CLK2: MCU_CLK */ - data[3] = SI5351C_CLK_POWERDOWN; + clk[2] = powered_down; } } #endif - si5351c_write(drv, data, sizeof(data)); -} -#define SI5351C_CLK_ENABLE(x) (0 << x) -#define SI5351C_CLK_DISABLE(x) (1 << x) -#define SI5351C_REG_OUTPUT_EN (3) + for (int i = 0; i < 8; i++) { + set_CLK_PDN(drv, i, clk[i].power_down); + set_MS_INT(drv, i, clk[i].mode); + set_MS_SRC(drv, i, clk[i].pll); + set_CLK_SRC(drv, i, clk[i].source); + set_CLK_IDRV(drv, i, clk[i].drive); + set_CLK_INV(drv, i, clk[i].invert); + } + + si5351c_regs_commit(drv); +} void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) { @@ -340,46 +423,61 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) /* 3: External clock output is deactivated by default */ uint8_t clkout = 3; - uint8_t value = 0; + + bool enable[8]; #ifdef IS_PRALINE if (IS_PRALINE) { - value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | - SI5351C_CLK_ENABLE(4) | SI5351C_CLK_ENABLE(5) | - SI5351C_CLK_DISABLE(6) | SI5351C_CLK_DISABLE(7); + enable[0] = true; + enable[1] = true; if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { /* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */ - value |= SI5351C_CLK_ENABLE(2); + enable[2] = true; } else { - value |= SI5351C_CLK_DISABLE(2); + enable[2] = false; } + enable[3] = false; + enable[4] = true; + enable[5] = true; + enable[6] = false; + enable[7] = false; } #endif #ifdef IS_NOT_PRALINE if (IS_NOT_PRALINE) { - value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | - SI5351C_CLK_ENABLE(2) | SI5351C_CLK_ENABLE(4) | - SI5351C_CLK_ENABLE(5) | SI5351C_CLK_DISABLE(6) | - SI5351C_CLK_DISABLE(7); + enable[0] = true; + enable[1] = true; + enable[2] = true; + enable[3] = false; + enable[4] = true; + enable[5] = true; + enable[6] = false; + enable[7] = false; /* HackRF One r9 has only three clock generator outputs. */ #ifdef IS_H1_R9 if (IS_H1_R9) { clkout = 2; - value = SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | - SI5351C_CLK_DISABLE(3) | SI5351C_CLK_DISABLE(4) | - SI5351C_CLK_DISABLE(5) | SI5351C_CLK_DISABLE(6) | - SI5351C_CLK_DISABLE(7); + enable[0] = true; + enable[1] = true; + enable[3] = false; + enable[4] = false; + enable[5] = false; + enable[6] = false; + enable[7] = false; } #endif } #endif + enable[clkout] = clkout_enabled; - value |= (clkout_enabled) ? SI5351C_CLK_ENABLE(clkout) : - SI5351C_CLK_DISABLE(clkout); - uint8_t data[] = {SI5351C_REG_OUTPUT_EN, value}; - si5351c_write(drv, data, sizeof(data)); - outputs_disabled = value; + for (int i = 0; i < 8; i++) { + set_CLK_OEB( + drv, + i, + enable[i] ? SI5351C_OUTPUT_ENABLE : SI5351C_OUTPUT_DISABLE); + } + si5351c_regs_commit(drv); #ifdef IS_H1_R9 if (IS_H1_R9) { @@ -398,20 +496,8 @@ void si5351c_set_int_mode( const uint_fast8_t ms_number, const uint_fast8_t on) { - uint8_t data[] = {16, 0}; - - if (ms_number < 8) { - data[0] = 16 + ms_number; - data[1] = si5351c_read_single(drv, data[0]); - - if (on) { - data[1] |= SI5351C_CLK_INT_MODE; - } else { - data[1] &= ~(SI5351C_CLK_INT_MODE); - } - - si5351c_write(drv, data, 2); - } + set_MS_INT(drv, ms_number, on); + si5351c_regs_commit(drv); } void si5351c_change_input(si5351c_driver_t* const drv, si5351c_input_t input) @@ -451,7 +537,9 @@ bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv) uint32_t f = clkin_frequency(); return (f > 9000000) && (f < 11000000); } else { - return (si5351c_read_single(drv, 0) & SI5351C_LOS) == 0; + si5351c_read_single(drv, LOS_CLKIN); + bool los_clkin = get_LOS_CLKIN(drv); + return !los_clkin; } } @@ -475,7 +563,8 @@ void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable) void si5351c_init(si5351c_driver_t* const drv) { /* Read revision ID */ - selftest.si5351_rev_id = si5351c_read_single(drv, 0) & SI5351C_REVID; + si5351c_read_single(drv, REVID); + selftest.si5351_rev_id = get_REVID(drv); /* Read back interrupt status mask register, flip the mask bits and verify. */ uint8_t int_mask = si5351c_read_single(drv, 2); @@ -494,6 +583,17 @@ void si5351c_init(si5351c_driver_t* const drv) selftest.report.pass = false; } + /* Cache all current register values. */ + uint8_t data_tx[] = {0}; + i2c_bus_transfer( + drv->bus, + drv->i2c_address, + data_tx, + 1, + drv->regs, + sizeof(drv->regs)); + memset(drv->regs_dirty, 0, sizeof(drv->regs_dirty)); + #ifdef IS_H1_R9 if (IS_H1_R9) { const platform_gpio_t* gpio = platform_gpio(); @@ -529,8 +629,6 @@ void si5351c_set_phase( const uint8_t ms_number, const uint8_t offset) { - const uint8_t address = 165 + ms_number; - if (ms_number < 8) { - si5351c_write_single(drv, address, offset & 0x7f); - } + set_CLK_PHOFF(drv, ms_number, offset); + si5351c_regs_commit(drv); } diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index 491266cf..5be31788 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012-2026 Great Scott Gadgets * Copyright 2012 Jared Boone * * This file is part of HackRF. @@ -28,47 +28,62 @@ extern "C" { #include #include -#include #include "i2c_bus.h" #include "i2c_lpc.h" #define SI_INTDIV(x) (x * 128 - 512) -#define SI5351C_CLK_POWERDOWN (1 << 7) -#define SI5351C_CLK_INT_MODE (1 << 6) -#define SI5351C_CLK_FRAC_MODE (0 << 6) +#define SI5351C_CACHED_REGS 188 -#define SI5351C_CLK_INV (1 << 4) +typedef enum { + SI5351C_MODE_FRAC = 0, + SI5351C_MODE_INT = 1, +} si5351c_mode_t; -#define SI5351C_CLK_SRC(x) (x << 2) -#define SI5351C_CLK_SRC_XTAL 0 -#define SI5351C_CLK_SRC_CLKIN 1 -#define SI5351C_CLK_SRC_MULTISYNTH_0_4 2 -#define SI5351C_CLK_SRC_MULTISYNTH_SELF 3 +typedef enum { + SI5351C_SRC_XTAL = 0, + SI5351C_SRC_CLKIN = 1, + SI5351C_SRC_MULTISYNTH_0_4 = 2, + SI5351C_SRC_MULTISYNTH_SELF = 3, +} si5351c_src_t; -#define SI5351C_CLK_IDRV(x) (x << 0) -#define SI5351C_CLK_IDRV_2MA 0 -#define SI5351C_CLK_IDRV_4MA 1 -#define SI5351C_CLK_IDRV_6MA 2 -#define SI5351C_CLK_IDRV_8MA 3 - -#define SI5351C_LOS (1 << 4) -#define SI5351C_REVID 0x03 +typedef enum { + SI5351C_DRIVE_2MA = 0, + SI5351C_DRIVE_4MA = 1, + SI5351C_DRIVE_6MA = 2, + SI5351C_DRIVE_8MA = 3, +} si5351c_drive_t; typedef enum { SI5351C_PLL_A = 0, SI5351C_PLL_B = 1, } si5351c_pll_t; -#define SI5351C_CLK_PLL_SRC(x) ((x & SI5351C_PLL_B) << 5) - typedef enum { SI5351C_PLL_MASK_A = 1, SI5351C_PLL_MASK_B = 2, SI5351C_PLL_MASK_BOTH = 3, } si5351c_pll_mask_t; +typedef enum { + SI5351C_XTAL_6PF = 1, + SI5351C_XTAL_8PF = 2, + SI5351C_XTAL_10PF = 3, +} si5351c_xtal_t; + +typedef enum { + SI5351C_OUTPUT_ENABLE = 0, + SI5351C_OUTPUT_DISABLE = 1, +} si5351c_output_t; + +typedef enum { + SI5351C_DIV_1 = 0, + SI5351C_DIV_2 = 1, + SI5351C_DIV_4 = 2, + SI5351C_DIV_8 = 3, +} si5351c_div_t; + typedef enum { SI5351C_INPUT_XTAL = 0, SI5351C_INPUT_CLKIN = 1, @@ -77,8 +92,19 @@ typedef enum { typedef struct { i2c_bus_t* const bus; uint8_t i2c_address; + uint8_t regs[SI5351C_CACHED_REGS]; + uint32_t regs_dirty[(SI5351C_CACHED_REGS + 31) / 32]; } si5351c_driver_t; +typedef struct { + bool power_down; + si5351c_mode_t mode; + si5351c_pll_t pll; + si5351c_src_t source; + si5351c_drive_t drive; + bool invert; +} si5351c_clk_ctrl_t; + void si5351c_disable_all_outputs(si5351c_driver_t* const drv); void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv); void si5351c_power_down_all_clocks(si5351c_driver_t* const drv); @@ -107,10 +133,6 @@ bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv); void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val); uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg); -void si5351c_write( - si5351c_driver_t* const drv, - const uint8_t* const data, - const size_t data_count); void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable); void si5351c_init(si5351c_driver_t* const drv); void si5351c_set_phase( From 478a520d65f2f822bac6baf9a7387c19720e3c12 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 18 May 2026 14:42:16 +0100 Subject: [PATCH 197/238] Add script to extract font data to an image file for editing. --- firmware/tools/edit-font.py | 107 ++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 firmware/tools/edit-font.py diff --git a/firmware/tools/edit-font.py b/firmware/tools/edit-font.py new file mode 100644 index 00000000..9e03467a --- /dev/null +++ b/firmware/tools/edit-font.py @@ -0,0 +1,107 @@ +# Tool to extract font data, save to bitmap file, and apply modifications +# to source code after editing the bitmap. + +from __future__ import print_function +from matplotlib.pyplot import imread, imsave, imshow, show +import numpy as np +import sys +import re + +if len(sys.argv) != 3: + print("Usage: %s { show | extract | insert}" % sys.argv[0]) + sys.exit(1) + +font_name = sys.argv[1] +mode = sys.argv[2] + +# Where to find the font data - may need updated if code has changed. +source_file = 'firmware/common/ui_portapack.c' +data_marker = f'static const uint8_t {font_name}_glyph_data[] = {{' +data_offset = 1 # Data starts this number of lines after start marker. +end_pattern = '(.*)};$' # Indicates end of font data. +def_marker = f'static const ui_font_t {font_name} =' +def_offset = 1 +def_pattern = '^\t{{(?P\\d+), (?P\\d+)}' + +# Image filename used in extract and insert modes. +image_file = f'{font_name}.png' + +# Get the literals used to populate the font array in the source file +lines = [line.rstrip() for line in open(source_file).readlines()] +try: + start = lines.index(data_marker) + data_offset +except ValueError: + print(f"Could not find glyph data for font '{font_name}'") + sys.exit(1) + +data = str() +for line in lines[start:]: + if match := re.match(end_pattern, line): + data += match.group(1) + break + else: + data += line + +# Get the width and height from the font definition. +try: + def_start = lines.index(def_marker) +except ValueError: + print(f"Could not find definition for font '{font_name}'") + sys.exit(1) + +def_match = re.match(def_pattern, lines[def_start + def_offset]) + +if def_match is None: + print(f"Failed to parse definition of '{font_name}'") + +width = int(def_match.group('width')) +height = int(def_match.group('height')) + +# Eval the literals to get the values into a numpy array +packed = eval("np.array([%s], np.uint8)" % data) + +# Reorganise into a monochrome image. +chars_per_row = 5 +unpacked = np.unpackbits(packed) +bitmaps = (unpacked + .reshape(-1, height, width // 8, 8)[:,:,::-1,:] + .reshape(-1, height, width)[:,:,::-1] +) +indices = np.arange(len(bitmaps)).reshape(-1, chars_per_row) +image = np.block([[bitmaps[idx] for idx in row] for row in indices]) + +if mode == 'show': + # Display font image + imshow(image, cmap='binary') + show() + +elif mode == 'extract': + # Save font image + imsave(image_file, image, format='png', cmap='binary') + +elif mode == 'insert': + # Read in modified font image + image = imread(image_file)[:,:,0].astype(bool) + + # Reorganise back to original order + rows = image.reshape(-1, height, image.shape[1]) + single_row_image = np.hstack(rows) + num_chars = single_row_image.shape[1] // width + bitmaps = np.array(np.split(single_row_image, num_chars, 1)) + unpacked = (bitmaps + [:,:,::-1].reshape(-1, height, width // 8, 8) + [:,:,::-1,:].reshape(-1) + ) + packed = ~np.packbits(unpacked) + + # Replace lines of file in same format as used before + bytes_per_row = 13 + split_indices = np.arange(bytes_per_row, len(packed), bytes_per_row) + for i, group in enumerate(np.split(packed, split_indices)): + line = ("\t0x%02x," + " 0x%02x," * (len(group) - 1)) % tuple(group) + if len(group) < bytes_per_row: + line = line[:-1] + "};" + lines[start + i] = line + + # Write out modified source file + open(source_file, 'w').writelines([line + "\n" for line in lines]) From dc255468b1ecaf8141d68067addb1e5c03f452ce Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 18 May 2026 17:26:27 +0100 Subject: [PATCH 198/238] Fix up IWYU issues in cpld_jtag.{c,h}. --- firmware/common/cpld_jtag.c | 3 ++- firmware/common/cpld_jtag.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/firmware/common/cpld_jtag.c b/firmware/common/cpld_jtag.c index 4d313d01..e6413ba4 100644 --- a/firmware/common/cpld_jtag.c +++ b/firmware/common/cpld_jtag.c @@ -21,11 +21,12 @@ #include "cpld_jtag.h" -#include "cpld_xc2c.h" #include "platform_detect.h" #ifdef IS_NOT_PRALINE + #include #include #include "xapp058/micro.h" + #include "cpld_xc2c.h" #endif #ifdef IS_NOT_PRALINE diff --git a/firmware/common/cpld_jtag.h b/firmware/common/cpld_jtag.h index b9a4b52f..c1f707d4 100644 --- a/firmware/common/cpld_jtag.h +++ b/firmware/common/cpld_jtag.h @@ -21,6 +21,7 @@ #pragma once +#include #include #include "gpio.h" From 50ce90908f6a6cbbe03778b21f9c0a564242bf09 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Sat, 9 May 2026 06:21:44 +0100 Subject: [PATCH 199/238] si5351c: Wait for SYS_INIT flag to clear during startup. --- firmware/common/si5351c.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 1f27d8db..f356f320 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -583,6 +583,11 @@ void si5351c_init(si5351c_driver_t* const drv) selftest.report.pass = false; } + /* Wait for on-chip initialization to complete. */ + while (get_SYS_INIT(drv)) { + si5351c_read_single(drv, SYS_INIT); + } + /* Cache all current register values. */ uint8_t data_tx[] = {0}; i2c_bus_transfer( From 4c69adb9dab1f0df34d93a6ea2a4715fb92f1ec1 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 8 May 2026 14:54:03 +0100 Subject: [PATCH 200/238] si5351c: API: change argument of si5351c_clkout_enable to bool. --- firmware/common/si5351c.c | 4 ++-- firmware/common/si5351c.h | 2 +- firmware/hackrf_usb/usb_api_register.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index f356f320..d053d601 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -543,9 +543,9 @@ bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv) } } -void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable) +void si5351c_clkout_enable(si5351c_driver_t* const drv, bool enable) { - clkout_enabled = (enable > 0); + clkout_enabled = enable; uint8_t clkout = 3; diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index 5be31788..c357442f 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -133,7 +133,7 @@ bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv); void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val); uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg); -void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable); +void si5351c_clkout_enable(si5351c_driver_t* const drv, bool enable); void si5351c_init(si5351c_driver_t* const drv); void si5351c_set_phase( si5351c_driver_t* const drv, diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index 1a9f0238..626c7508 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -211,7 +211,7 @@ usb_request_status_t usb_vendor_request_set_clkout_enable( const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { - si5351c_clkout_enable(&si5351c, endpoint->setup.value); + si5351c_clkout_enable(&si5351c, endpoint->setup.value > 0); usb_transfer_schedule_ack(endpoint->in); } return USB_REQUEST_STATUS_OK; From 9423133c4b94957665991c3dfa30c93ed474e045 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 8 May 2026 14:40:28 +0100 Subject: [PATCH 201/238] si5351c: Make clk array persistent, setup in init, include OE flags. --- firmware/common/si5351c.c | 365 +++++++++++++++++--------------------- firmware/common/si5351c.h | 3 +- 2 files changed, 161 insertions(+), 207 deletions(-) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index d053d601..50d39583 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -51,10 +51,12 @@ si5351c_driver_t si5351c = { .i2c_address = 0x60, }; +si5351c_clk_t clk[8]; + +uint8_t clkout_id; + static bool input_initialized = false; static si5351c_input_t active_input; -/* External clock output default is deactivated as it creates noise */ -static bool clkout_enabled = false; /* write to single register */ void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val) @@ -263,146 +265,6 @@ void si5351c_configure_multisynth( void si5351c_configure_clock_control(si5351c_driver_t* const drv) { - si5351c_clk_ctrl_t clkout = { - .mode = SI5351C_MODE_INT, - .pll = SI5351C_PLL_A, - .source = SI5351C_SRC_MULTISYNTH_SELF, - .drive = SI5351C_DRIVE_8MA, - }; - - si5351c_clk_ctrl_t powered_down = { - .power_down = true, - .mode = SI5351C_MODE_INT, - }; - - if (!clkout_enabled) { - clkout = powered_down; - } - - si5351c_clk_ctrl_t clk[8]; - - /* Clock to CPU is deactivated as it is not used and creates noise */ - /* External clock output is kept in current state */ - - /* CLK0: MAX5864/CPLD */ - clk[0] = (si5351c_clk_ctrl_t){ - .mode = SI5351C_MODE_FRAC, - .pll = SI5351C_PLL_A, - .source = SI5351C_SRC_MULTISYNTH_SELF, - .drive = SI5351C_DRIVE_8MA, - }; - /* CLK1: CPLD */ - clk[1] = (si5351c_clk_ctrl_t){ - .mode = SI5351C_MODE_INT, - .pll = SI5351C_PLL_A, - .source = SI5351C_SRC_MULTISYNTH_0_4, - .drive = SI5351C_DRIVE_2MA, - .invert = true, - }; - /* CLK2: SGPIO */ - clk[2] = (si5351c_clk_ctrl_t){ - .mode = SI5351C_MODE_INT, - .pll = SI5351C_PLL_A, - .source = SI5351C_SRC_MULTISYNTH_0_4, - .drive = SI5351C_DRIVE_2MA, - }; - /* CLK3: CLKOUT */ - clk[3] = clkout; - /* CLK4: RFFC5072 (MAX2837 on rad1o) */ - clk[4] = (si5351c_clk_ctrl_t){ - .mode = SI5351C_MODE_INT, - .pll = SI5351C_PLL_A, - .source = SI5351C_SRC_MULTISYNTH_SELF, - .drive = SI5351C_DRIVE_6MA, - .invert = true, - }; - /* CLK5: MAX2837 (MAX2871 on rad1o) */ - clk[5] = (si5351c_clk_ctrl_t){ - .mode = SI5351C_MODE_INT, - .pll = SI5351C_PLL_A, - .source = SI5351C_SRC_MULTISYNTH_SELF, - .drive = SI5351C_DRIVE_4MA, - }; - /* CLK6: none */ - clk[6] = powered_down; - /* CLK7: LPC43xx */ - clk[7] = powered_down; - -#ifdef IS_H1_R9 - if (IS_H1_R9) { - /* CLK0: MAX5864/CPLD/SGPIO (sample clocks) */ - clk[0] = (si5351c_clk_ctrl_t){ - .mode = SI5351C_MODE_INT, - .pll = SI5351C_PLL_A, - .source = SI5351C_SRC_MULTISYNTH_SELF, - .drive = SI5351C_DRIVE_6MA, - }; - /* CLK1: RFFC5072/MAX2839 */ - clk[1] = (si5351c_clk_ctrl_t){ - .mode = SI5351C_MODE_FRAC, - .pll = SI5351C_PLL_A, - .source = SI5351C_SRC_MULTISYNTH_SELF, - .drive = SI5351C_DRIVE_4MA, - }; - /* CLK2: CLKOUT/LPC4320 */ - clk[2] = clkout; - /* Other outputs not present on Si5351A */ - clk[3] = powered_down; - clk[4] = powered_down; - clk[5] = powered_down; - clk[6] = powered_down; - clk[7] = powered_down; - } -#endif -#ifdef IS_PRALINE - if (IS_PRALINE) { - /* CLK0: AFE_CLK */ - clk[0] = (si5351c_clk_ctrl_t){ - .mode = SI5351C_MODE_FRAC, - .pll = SI5351C_PLL_A, - .source = SI5351C_SRC_MULTISYNTH_SELF, - .drive = SI5351C_DRIVE_4MA, - }; - /* CLK1: SCT_CLK and FPGA_CLK */ - clk[1] = (si5351c_clk_ctrl_t){ - .mode = SI5351C_MODE_FRAC, - .pll = SI5351C_PLL_A, - .source = SI5351C_SRC_MULTISYNTH_SELF, - .drive = SI5351C_DRIVE_2MA, - }; - /* CLK3: CLKOUT */ - clkout.pll = SI5351C_PLL_B; - clk[3] = clkout; - /* CLK4: XCVR_CLK */ - clk[4] = (si5351c_clk_ctrl_t){ - .mode = SI5351C_MODE_INT, - .pll = SI5351C_PLL_B, - .source = SI5351C_SRC_MULTISYNTH_SELF, - .drive = SI5351C_DRIVE_4MA, - .invert = true, - }; - /* CLK5: MIX_CLK */ - clk[5] = (si5351c_clk_ctrl_t){ - .mode = SI5351C_MODE_INT, - .pll = SI5351C_PLL_B, - .source = SI5351C_SRC_MULTISYNTH_SELF, - .drive = SI5351C_DRIVE_4MA, - }; - if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { - /* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */ - clk[2] = (si5351c_clk_ctrl_t){ - .mode = SI5351C_MODE_FRAC, - .pll = SI5351C_PLL_A, - .source = SI5351C_SRC_MULTISYNTH_SELF, - .drive = SI5351C_DRIVE_2MA, - }; - } else { - /* CLK2: MCU_CLK */ - clk[2] = powered_down; - } - } -#endif - for (int i = 0; i < 8; i++) { set_CLK_PDN(drv, i, clk[i].power_down); set_MS_INT(drv, i, clk[i].mode); @@ -417,72 +279,19 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv) void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) { - /* Enable CLK outputs 0, 1, 2, 4, 5 only. */ - /* Praline: enable 0, 1, 4, 5 only. */ - /* 7: Clock to CPU is deactivated as it is not used and creates noise */ - /* 3: External clock output is deactivated by default */ - - uint8_t clkout = 3; - - bool enable[8]; - -#ifdef IS_PRALINE - if (IS_PRALINE) { - enable[0] = true; - enable[1] = true; - if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { - /* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */ - enable[2] = true; - } else { - enable[2] = false; - } - enable[3] = false; - enable[4] = true; - enable[5] = true; - enable[6] = false; - enable[7] = false; - } -#endif -#ifdef IS_NOT_PRALINE - if (IS_NOT_PRALINE) { - enable[0] = true; - enable[1] = true; - enable[2] = true; - enable[3] = false; - enable[4] = true; - enable[5] = true; - enable[6] = false; - enable[7] = false; - - /* HackRF One r9 has only three clock generator outputs. */ - #ifdef IS_H1_R9 - if (IS_H1_R9) { - clkout = 2; - enable[0] = true; - enable[1] = true; - enable[3] = false; - enable[4] = false; - enable[5] = false; - enable[6] = false; - enable[7] = false; - } - #endif - } -#endif - enable[clkout] = clkout_enabled; - for (int i = 0; i < 8; i++) { set_CLK_OEB( drv, i, - enable[i] ? SI5351C_OUTPUT_ENABLE : SI5351C_OUTPUT_DISABLE); + clk[i].output_enable ? SI5351C_OUTPUT_ENABLE : + SI5351C_OUTPUT_DISABLE); } si5351c_regs_commit(drv); #ifdef IS_H1_R9 if (IS_H1_R9) { const platform_gpio_t* gpio = platform_gpio(); - if (clkout_enabled) { + if (clk[clkout_id].output_enable) { gpio_set(gpio->h1r9_clkout_en); } else { gpio_clear(gpio->h1r9_clkout_en); @@ -545,16 +354,11 @@ bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv) void si5351c_clkout_enable(si5351c_driver_t* const drv, bool enable) { - clkout_enabled = enable; + clk[clkout_id].output_enable = enable; + clk[clkout_id].power_down = !enable; - uint8_t clkout = 3; - - /* HackRF One r9 has only three clock generator outputs. */ - if (detected_platform() == BOARD_ID_HACKRF1_R9) { - clkout = 2; - } /* Configure clock to 10MHz */ - si5351c_configure_multisynth(drv, clkout, 80 * 128 - 512, 0, 1, 0); + si5351c_configure_multisynth(drv, clkout_id, 80 * 128 - 512, 0, 1, 0); si5351c_configure_clock_control(drv); si5351c_enable_clock_outputs(drv); @@ -620,6 +424,155 @@ void si5351c_init(si5351c_driver_t* const drv) gpio_output(gpio->h1r9_mcu_clk_en); } #endif + + si5351c_clk_t clkout = { + .output_enable = false, + .power_down = true, + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_8MA, + }; + + si5351c_clk_t powered_down = { + .output_enable = false, + .power_down = true, + .mode = SI5351C_MODE_INT, + }; + + /* CLK0: MAX5864/CPLD */ + clk[0] = (si5351c_clk_t){ + .output_enable = true, + .mode = SI5351C_MODE_FRAC, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_8MA, + }; + /* CLK1: CPLD */ + clk[1] = (si5351c_clk_t){ + .output_enable = true, + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_0_4, + .drive = SI5351C_DRIVE_2MA, + .invert = true, + }; + /* CLK2: SGPIO */ + clk[2] = (si5351c_clk_t){ + .output_enable = true, + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_0_4, + .drive = SI5351C_DRIVE_2MA, + }; + /* CLK3: CLKOUT */ + clk[3] = clkout; + clkout_id = 3; + /* CLK4: RFFC5072 (MAX2837 on rad1o) */ + clk[4] = (si5351c_clk_t){ + .output_enable = true, + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_6MA, + .invert = true, + }; + /* CLK5: MAX2837 (MAX2871 on rad1o) */ + clk[5] = (si5351c_clk_t){ + .output_enable = true, + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_4MA, + }; + /* CLK6: none */ + clk[6] = powered_down; + /* CLK7: LPC43xx */ + clk[7] = powered_down; + +#ifdef IS_H1_R9 + if (IS_H1_R9) { + /* CLK0: MAX5864/CPLD/SGPIO (sample clocks) */ + clk[0] = (si5351c_clk_t){ + .output_enable = true, + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_6MA, + }; + /* CLK1: RFFC5072/MAX2839 */ + clk[1] = (si5351c_clk_t){ + .output_enable = true, + .mode = SI5351C_MODE_FRAC, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_4MA, + }; + /* CLK2: CLKOUT/LPC4320 */ + clk[2] = clkout; + clkout_id = 2; + /* Other outputs not present on Si5351A */ + clk[3] = powered_down; + clk[4] = powered_down; + clk[5] = powered_down; + clk[6] = powered_down; + clk[7] = powered_down; + } +#endif +#ifdef IS_PRALINE + if (IS_PRALINE) { + /* CLK0: AFE_CLK */ + clk[0] = (si5351c_clk_t){ + .output_enable = true, + .mode = SI5351C_MODE_FRAC, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_4MA, + }; + /* CLK1: SCT_CLK and FPGA_CLK */ + clk[1] = (si5351c_clk_t){ + .output_enable = true, + .mode = SI5351C_MODE_FRAC, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_2MA, + }; + /* CLK3: CLKOUT */ + clkout.pll = SI5351C_PLL_B; + clk[3] = clkout; + clkout_id = 3; + /* CLK4: XCVR_CLK */ + clk[4] = (si5351c_clk_t){ + .output_enable = true, + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_B, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_4MA, + .invert = true, + }; + /* CLK5: MIX_CLK */ + clk[5] = (si5351c_clk_t){ + .output_enable = true, + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_B, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_4MA, + }; + if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { + /* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */ + clk[2] = (si5351c_clk_t){ + .output_enable = true, + .mode = SI5351C_MODE_FRAC, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_2MA, + }; + } else { + /* CLK2: MCU_CLK */ + clk[2] = powered_down; + } + } +#endif } /* diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index c357442f..9691b896 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -97,13 +97,14 @@ typedef struct { } si5351c_driver_t; typedef struct { + bool output_enable; bool power_down; si5351c_mode_t mode; si5351c_pll_t pll; si5351c_src_t source; si5351c_drive_t drive; bool invert; -} si5351c_clk_ctrl_t; +} si5351c_clk_t; void si5351c_disable_all_outputs(si5351c_driver_t* const drv); void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv); From 835e7b618a55865aeeb7846d00b3f378b74ff3d5 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 19 May 2026 06:47:45 +0100 Subject: [PATCH 202/238] Move LPC43xx I2C instances and configs to ipc_lpc.{c,h}. --- firmware/common/clock_gen.c | 5 +++-- firmware/common/cpu_clock.c | 3 ++- firmware/common/da7219.c | 1 + firmware/common/i2c_bus.c | 19 ------------------- firmware/common/i2c_bus.h | 4 ---- firmware/common/i2c_lpc.c | 20 ++++++++++++++++++++ firmware/common/i2c_lpc.h | 5 +++++ firmware/common/operacake.c | 1 + firmware/common/si5351c.c | 6 ------ firmware/common/si5351c.h | 2 -- 10 files changed, 32 insertions(+), 34 deletions(-) diff --git a/firmware/common/clock_gen.c b/firmware/common/clock_gen.c index e91e3822..22f461c2 100644 --- a/firmware/common/clock_gen.c +++ b/firmware/common/clock_gen.c @@ -25,6 +25,7 @@ #include "hackrf_ui.h" #include "i2c_bus.h" +#include "i2c_lpc.h" #include "platform_detect.h" #include "sgpio.h" #include "si5351c.h" @@ -35,7 +36,7 @@ void clock_gen_init(void) { - i2c_bus_start(si5351c.bus, &i2c_config_si5351c_fast_clock); + i2c_bus_start(si5351c.bus, &i2c_config_fast_clock); si5351c_init(&si5351c); si5351c_disable_all_outputs(&si5351c); @@ -119,7 +120,7 @@ void clock_gen_init(void) void clock_gen_shutdown(void) { - i2c_bus_start(si5351c.bus, &i2c_config_si5351c_fast_clock); + i2c_bus_start(si5351c.bus, &i2c_config_fast_clock); si5351c_disable_all_outputs(&si5351c); si5351c_disable_oeb_pin_control(&si5351c); si5351c_power_down_all_clocks(&si5351c); diff --git a/firmware/common/cpu_clock.c b/firmware/common/cpu_clock.c index 37445e51..325de76f 100644 --- a/firmware/common/cpu_clock.c +++ b/firmware/common/cpu_clock.c @@ -30,6 +30,7 @@ #include "delay.h" #include "i2c_bus.h" +#include "i2c_lpc.h" #include "si5351c.h" /* @@ -113,7 +114,7 @@ void cpu_clock_init(void) //FIXME disable I2C /* Kick I2C0 down to 400kHz when we switch over to APB1 clock = 204MHz */ - i2c_bus_start(si5351c.bus, &i2c_config_si5351c_fast_clock); + i2c_bus_start(si5351c.bus, &i2c_config_fast_clock); /* * 12MHz clock is entering LPC XTAL1/OSC input now. diff --git a/firmware/common/da7219.c b/firmware/common/da7219.c index 7ae916cb..de85d2b8 100644 --- a/firmware/common/da7219.c +++ b/firmware/common/da7219.c @@ -23,6 +23,7 @@ #include "da7219.h" #include "i2c_bus.h" +#include "i2c_lpc.h" #define DA7219_REG_CHIP_ID1 0x81 #define DA7219_REG_CHIP_ID2 0x82 diff --git a/firmware/common/i2c_bus.c b/firmware/common/i2c_bus.c index c0d5b79d..6d8dcd25 100644 --- a/firmware/common/i2c_bus.c +++ b/firmware/common/i2c_bus.c @@ -22,25 +22,6 @@ #include "i2c_bus.h" -#include - -#include "i2c_lpc.h" - -/* Driver instances. */ -i2c_bus_t i2c0 = { - .obj = (void*) I2C0_BASE, - .start = i2c_lpc_start, - .stop = i2c_lpc_stop, - .transfer = i2c_lpc_transfer, -}; - -i2c_bus_t i2c1 = { - .obj = (void*) I2C1_BASE, - .start = i2c_lpc_start, - .stop = i2c_lpc_stop, - .transfer = i2c_lpc_transfer, -}; - void i2c_bus_start(i2c_bus_t* const bus, const void* const config) { bus->start(bus, config); diff --git a/firmware/common/i2c_bus.h b/firmware/common/i2c_bus.h index fa1211c1..7519ba14 100644 --- a/firmware/common/i2c_bus.h +++ b/firmware/common/i2c_bus.h @@ -47,7 +47,3 @@ void i2c_bus_transfer( const size_t tx_count, uint8_t* const rx, const size_t rx_count); - -/* Driver instances. */ -extern i2c_bus_t i2c0; -extern i2c_bus_t i2c1; diff --git a/firmware/common/i2c_lpc.c b/firmware/common/i2c_lpc.c index 05631f05..9d6499fa 100644 --- a/firmware/common/i2c_lpc.c +++ b/firmware/common/i2c_lpc.c @@ -23,6 +23,26 @@ #include "i2c_lpc.h" #include +#include + +/* Driver instances. */ +i2c_bus_t i2c0 = { + .obj = (void*) I2C0_BASE, + .start = i2c_lpc_start, + .stop = i2c_lpc_stop, + .transfer = i2c_lpc_transfer, +}; + +i2c_bus_t i2c1 = { + .obj = (void*) I2C1_BASE, + .start = i2c_lpc_start, + .stop = i2c_lpc_stop, + .transfer = i2c_lpc_transfer, +}; + +const i2c_lpc_config_t i2c_config_fast_clock = { + .duty_cycle_count = 255, +}; /* FIXME return i2c0 status from each function */ diff --git a/firmware/common/i2c_lpc.h b/firmware/common/i2c_lpc.h index f5b8230e..e71cb362 100644 --- a/firmware/common/i2c_lpc.h +++ b/firmware/common/i2c_lpc.h @@ -42,3 +42,8 @@ void i2c_lpc_transfer( uint8_t* const data_rx, const size_t count_rx); bool i2c_probe(i2c_bus_t* const bus, const uint_fast8_t device_address); + +/* Driver instances. */ +extern const i2c_lpc_config_t i2c_config_fast_clock; +extern i2c_bus_t i2c0; +extern i2c_bus_t i2c1; diff --git a/firmware/common/operacake.c b/firmware/common/operacake.c index f50c4f7e..bce51b76 100644 --- a/firmware/common/operacake.c +++ b/firmware/common/operacake.c @@ -29,6 +29,7 @@ #include "gpio.h" #include "gpio_lpc.h" #include "i2c_bus.h" +#include "i2c_lpc.h" #include "operacake_sctimer.h" #include "platform_scu.h" diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 1f27d8db..77d77703 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -40,12 +40,6 @@ #include "si5351c_regs.def" /* Driver instance. */ -// const i2c_lpc_config_t i2c_config_si5351c_slow_clock = { -// .duty_cycle_count = 15, -// }; -const i2c_lpc_config_t i2c_config_si5351c_fast_clock = { - .duty_cycle_count = 255, -}; si5351c_driver_t si5351c = { .bus = &i2c0, .i2c_address = 0x60, diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index 5be31788..b99bec14 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -30,7 +30,6 @@ extern "C" { #include #include "i2c_bus.h" -#include "i2c_lpc.h" #define SI_INTDIV(x) (x * 128 - 512) @@ -141,7 +140,6 @@ void si5351c_set_phase( const uint8_t offset); /* Driver Instance. */ -extern const i2c_lpc_config_t i2c_config_si5351c_fast_clock; extern si5351c_driver_t si5351c; #ifdef __cplusplus From 62cdff34483c34dadabae43850f8b99577444820 Mon Sep 17 00:00:00 2001 From: grvvy Date: Fri, 24 Apr 2026 10:58:55 -0600 Subject: [PATCH 203/238] Jenkinsfile: add resource locks to HIL USB hubs to allow for concurrent builds --- Jenkinsfile | 160 +++++++++++++++++++++++++++------------------------- 1 file changed, 84 insertions(+), 76 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index b41d6714..2d856531 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -41,29 +41,31 @@ pipeline { steps { sh './ci-scripts/install_host.sh' sh './ci-scripts/build_firmware.sh HACKRF_ONE' - script { - allOff() - reset('h1_eut') - } - sh 'sleep 1s' - retry(3) { - sh './ci-scripts/test_host.sh' - } - script { - reset('h1_tester h1_eut') - } - sh 'sleep 1s' - script { - // Allow up to 3 retries 5 minutes each for the HIL test - runCommand(3, 5, 'MINUTES', "HackRF One Test", h1_test) - } - script { - allOff() - reset('h1_eut') - } - sh 'sleep 1s' - retry(3) { - sh 'python3 ci-scripts/test_sgpio_debug.py' + lock('HIL_hubs') { + script { + allOff() + reset('h1_eut') + } + sh 'sleep 1s' + retry(3) { + sh './ci-scripts/test_host.sh' + } + script { + reset('h1_tester h1_eut') + } + sh 'sleep 1s' + script { + // Allow up to 3 retries 5 minutes each for the HIL test + runCommand(3, 5, 'MINUTES', "HackRF One Test", h1_test) + } + script { + allOff() + reset('h1_eut') + } + sh 'sleep 1s' + retry(3) { + sh 'python3 ci-scripts/test_sgpio_debug.py' + } } } } @@ -81,29 +83,31 @@ pipeline { steps { sh './ci-scripts/install_host.sh' sh './ci-scripts/build_firmware.sh UNIVERSAL' - script { - allOff() - reset('h1_eut') - } - sh 'sleep 1s' - retry(3) { - sh './ci-scripts/test_host.sh' - } - script { - reset('h1_tester h1_eut') - } - sh 'sleep 1s' - script { - // Allow up to 3 retries 5 minutes each for the HIL test - runCommand(3, 5, 'MINUTES', "HackRF One Test", h1_test) - } - script { - allOff() - reset('h1_eut') - } - sh 'sleep 1s' - retry(3) { - sh 'python3 ci-scripts/test_sgpio_debug.py' + lock('HIL_hubs') { + script { + allOff() + reset('h1_eut') + } + sh 'sleep 1s' + retry(3) { + sh './ci-scripts/test_host.sh' + } + script { + reset('h1_tester h1_eut') + } + sh 'sleep 1s' + script { + // Allow up to 3 retries 5 minutes each for the HIL test + runCommand(3, 5, 'MINUTES', "HackRF One Test", h1_test) + } + script { + allOff() + reset('h1_eut') + } + sh 'sleep 1s' + retry(3) { + sh 'python3 ci-scripts/test_sgpio_debug.py' + } } } } @@ -121,21 +125,23 @@ pipeline { steps { sh './ci-scripts/install_host.sh' sh './ci-scripts/build_firmware.sh PRALINE' - script { - allOff() - reset('hpro_eut') - } - sh 'sleep 1s' - retry(3) { - sh './ci-scripts/test_host.sh' - } - script { - reset('hpro_tester hpro_eut') - } - sh 'sleep 1s' - script { - // Allow up to 3 retries 5 minutes each for the HIL test - runCommand(3, 5, 'MINUTES', "HackRF Pro Test", hpro_test) + lock('HIL_hubs') { + script { + allOff() + reset('hpro_eut') + } + sh 'sleep 1s' + retry(3) { + sh './ci-scripts/test_host.sh' + } + script { + reset('hpro_tester hpro_eut') + } + sh 'sleep 1s' + script { + // Allow up to 3 retries 5 minutes each for the HIL test + runCommand(3, 5, 'MINUTES', "HackRF Pro Test", hpro_test) + } } } } @@ -153,21 +159,23 @@ pipeline { steps { sh './ci-scripts/install_host.sh' sh './ci-scripts/build_firmware.sh UNIVERSAL' - script { - allOff() - reset('hpro_eut') - } - sh 'sleep 1s' - retry(3) { - sh './ci-scripts/test_host.sh' - } - script { - reset('hpro_tester hpro_eut') - } - sh 'sleep 1s' - script { - // Allow up to 3 retries 5 minutes each for the HIL test - runCommand(3, 5, 'MINUTES', "HackRF Pro Test", hpro_test) + lock('HIL_hubs') { + script { + allOff() + reset('hpro_eut') + } + sh 'sleep 1s' + retry(3) { + sh './ci-scripts/test_host.sh' + } + script { + reset('hpro_tester hpro_eut') + } + sh 'sleep 1s' + script { + // Allow up to 3 retries 5 minutes each for the HIL test + runCommand(3, 5, 'MINUTES', "HackRF Pro Test", hpro_test) + } } } } From 6c01a078d52c76d58619881669d84c94ad4c5194 Mon Sep 17 00:00:00 2001 From: grvvy Date: Tue, 19 May 2026 14:44:37 -0600 Subject: [PATCH 204/238] Jenkinsfile: ensure device resets occur between test runs --- Jenkinsfile | 111 +++++++++++++++------------------------------------- 1 file changed, 32 insertions(+), 79 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 2d856531..dcfd9ad8 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -39,32 +39,14 @@ pipeline { timeout(time: 20, unit: 'MINUTES') } steps { - sh './ci-scripts/install_host.sh' - sh './ci-scripts/build_firmware.sh HACKRF_ONE' + runCommand("Install Host Tools", './ci-scripts/install_host.sh', 3, 1, 'MINUTES') + runCommand("Build HackRF One Firmware", './ci-scripts/build_firmware.sh HACKRF_ONE', 3, 1, 'MINUTES') lock('HIL_hubs') { script { allOff() - reset('h1_eut') - } - sh 'sleep 1s' - retry(3) { - sh './ci-scripts/test_host.sh' - } - script { - reset('h1_tester h1_eut') - } - sh 'sleep 1s' - script { - // Allow up to 3 retries 5 minutes each for the HIL test - runCommand(3, 5, 'MINUTES', "HackRF One Test", h1_test) - } - script { - allOff() - reset('h1_eut') - } - sh 'sleep 1s' - retry(3) { - sh 'python3 ci-scripts/test_sgpio_debug.py' + runTest("Check Host", 'h1_eut', './ci-scripts/test_host.sh') + runTest("HackRF One HIL Test", 'h1_tester h1_eut', h1_test) + runTest("SGPIO Debug Test", 'h1_eut', 'python3 ci-scripts/test_sgpio_debug.py') } } } @@ -81,34 +63,17 @@ pipeline { timeout(time: 20, unit: 'MINUTES') } steps { - sh './ci-scripts/install_host.sh' - sh './ci-scripts/build_firmware.sh UNIVERSAL' + runCommand("Install Host Tools", './ci-scripts/install_host.sh', 3, 1, 'MINUTES') + runCommand("Build Universal Firmware", './ci-scripts/build_firmware.sh UNIVERSAL', 3, 1, 'MINUTES') lock('HIL_hubs') { script { allOff() - reset('h1_eut') - } - sh 'sleep 1s' - retry(3) { - sh './ci-scripts/test_host.sh' - } - script { - reset('h1_tester h1_eut') - } - sh 'sleep 1s' - script { - // Allow up to 3 retries 5 minutes each for the HIL test - runCommand(3, 5, 'MINUTES', "HackRF One Test", h1_test) - } - script { - allOff() - reset('h1_eut') - } - sh 'sleep 1s' - retry(3) { - sh 'python3 ci-scripts/test_sgpio_debug.py' + runTest("Check Host", 'h1_eut', './ci-scripts/test_host.sh') + runTest("HackRF One HIL Test", 'h1_tester h1_eut', h1_test) + runTest("SGPIO Debug Test", 'h1_eut', 'python3 ci-scripts/test_sgpio_debug.py') } } + } } stage('Test HackRF Pro with BOARD=PRALINE') { @@ -123,24 +88,13 @@ pipeline { timeout(time: 20, unit: 'MINUTES') } steps { - sh './ci-scripts/install_host.sh' - sh './ci-scripts/build_firmware.sh PRALINE' + runCommand("Install Host Tools", './ci-scripts/install_host.sh', 3, 1, 'MINUTES') + runCommand("Build Praline Firmware", './ci-scripts/build_firmware.sh PRALINE', 3, 1, 'MINUTES') lock('HIL_hubs') { script { allOff() - reset('hpro_eut') - } - sh 'sleep 1s' - retry(3) { - sh './ci-scripts/test_host.sh' - } - script { - reset('hpro_tester hpro_eut') - } - sh 'sleep 1s' - script { - // Allow up to 3 retries 5 minutes each for the HIL test - runCommand(3, 5, 'MINUTES', "HackRF Pro Test", hpro_test) + runTest("Check Host", 'hpro_eut', './ci-scripts/test_host.sh') + runTest("HackRF Pro HIL Test", 'hpro_tester hpro_eut', hpro_test) } } } @@ -157,24 +111,13 @@ pipeline { timeout(time: 20, unit: 'MINUTES') } steps { - sh './ci-scripts/install_host.sh' - sh './ci-scripts/build_firmware.sh UNIVERSAL' + runCommand("Install Host Tools", './ci-scripts/install_host.sh', 3, 1, 'MINUTES') + runCommand("Build Universal Firmware", './ci-scripts/build_firmware.sh UNIVERSAL', 3, 1, 'MINUTES') lock('HIL_hubs') { script { allOff() - reset('hpro_eut') - } - sh 'sleep 1s' - retry(3) { - sh './ci-scripts/test_host.sh' - } - script { - reset('hpro_tester hpro_eut') - } - sh 'sleep 1s' - script { - // Allow up to 3 retries 5 minutes each for the HIL test - runCommand(3, 5, 'MINUTES', "HackRF Pro Test", hpro_test) + runTest("Check Host", 'hpro_eut', './ci-scripts/test_host.sh') + runTest("HackRF Pro HIL Test", 'hpro_tester hpro_eut', hpro_test) } } } @@ -192,15 +135,15 @@ pipeline { def allOff() { // Allow up to 3 retries, 20 seconds each, for the USB hub port power server to respond appropriately - runCommand(3, 20, 'SECONDS', 'USB hub port power server command', "hubs all off") + runCommand('USB hub port power server command', "hubs all off", 3, 20, 'SECONDS') } def reset(devices) { // Allow up to 3 retries, 20 seconds each, for the USB hub port power server to respond appropriately - runCommand(3, 20, 'SECONDS', 'USB hub port power server command', "hubs ${devices} reset") + runCommand('USB hub port power server command', "hubs ${devices} reset", 3, 20, 'SECONDS') } -def runCommand(retries, time, unit, title, cmd) { +def runCommand(title, cmd, retries, time, unit) { retry(retries) { try { timeout(time: time, unit: unit) { @@ -222,3 +165,13 @@ def runCommand(retries, time, unit, title, cmd) { } } } + +def runTest(title, devices, cmd) { + retry(3) { + // reset() retains it's own internal retries + reset(devices) + sh 'sleep 1s' + // run the test with 0 internal retries and 3 external retries to ensure resets between runs + runCommand(title, cmd, 0, 5, 'MINUTES') + } +} From c2262ccda1a73e00e153e35f5bb0b2902d0de92d Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 19 May 2026 16:57:30 +0100 Subject: [PATCH 205/238] si5351c: Add control of MCU_CLKIN output. --- firmware/common/si5351c.c | 51 +++++++++++++++++++++++++++++++++++++-- firmware/common/si5351c.h | 1 + 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 50d39583..353a4d2e 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -54,6 +54,7 @@ si5351c_driver_t si5351c = { si5351c_clk_t clk[8]; uint8_t clkout_id; +uint8_t mcu_clkin_id; static bool input_initialized = false; static si5351c_input_t active_input; @@ -364,6 +365,40 @@ void si5351c_clkout_enable(si5351c_driver_t* const drv, bool enable) si5351c_enable_clock_outputs(drv); } +void si5351c_mcu_clkin_enable(si5351c_driver_t* const drv, bool enable) +{ +#ifdef IS_H1_R9 + if (IS_H1_R9) { + /* MCU clock is shared with CLKOUT. */ + si5351c_clkout_enable(drv, enable); + } +#endif +#ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { + clk[mcu_clkin_id].output_enable = enable; + clk[mcu_clkin_id].power_down = !enable; + + /* Configure clock to 40MHz */ + if (mcu_clkin_id >= 6) { + // MCU_CLKIN on CLK6 or CLK7, integer only MS. + si5351c_configure_multisynth(drv, mcu_clkin_id, 20, 0, 0, 0); + } else { + // MCU_CLKIN on CLK0 to CLK5, fractional-capable MS. + si5351c_configure_multisynth( + drv, + mcu_clkin_id, + 20 * 128 - 512, + 0, + 1, + 0); + } + + si5351c_configure_clock_control(drv); + si5351c_enable_clock_outputs(drv); + } +#endif +} + void si5351c_init(si5351c_driver_t* const drv) { /* Read revision ID */ @@ -434,6 +469,15 @@ void si5351c_init(si5351c_driver_t* const drv) .drive = SI5351C_DRIVE_8MA, }; + si5351c_clk_t mcu_clkin = { + .output_enable = false, + .power_down = true, + .mode = SI5351C_MODE_INT, + .pll = SI5351C_PLL_A, + .source = SI5351C_SRC_MULTISYNTH_SELF, + .drive = SI5351C_DRIVE_2MA, + }; + si5351c_clk_t powered_down = { .output_enable = false, .power_down = true, @@ -488,7 +532,8 @@ void si5351c_init(si5351c_driver_t* const drv) /* CLK6: none */ clk[6] = powered_down; /* CLK7: LPC43xx */ - clk[7] = powered_down; + clk[7] = mcu_clkin; + mcu_clkin_id = 7; #ifdef IS_H1_R9 if (IS_H1_R9) { @@ -511,6 +556,7 @@ void si5351c_init(si5351c_driver_t* const drv) /* CLK2: CLKOUT/LPC4320 */ clk[2] = clkout; clkout_id = 2; + mcu_clkin_id = 2; /* Other outputs not present on Si5351A */ clk[3] = powered_down; clk[4] = powered_down; @@ -569,7 +615,8 @@ void si5351c_init(si5351c_driver_t* const drv) }; } else { /* CLK2: MCU_CLK */ - clk[2] = powered_down; + clk[2] = mcu_clkin; + mcu_clkin_id = 2; } } #endif diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index 9691b896..dad74a17 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -135,6 +135,7 @@ bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv); void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val); uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg); void si5351c_clkout_enable(si5351c_driver_t* const drv, bool enable); +void si5351c_mcu_clkin_enable(si5351c_driver_t* const drv, bool enable); void si5351c_init(si5351c_driver_t* const drv); void si5351c_set_phase( si5351c_driver_t* const drv, From 62229fdf73e96943f95c623144258d9708982beb Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 21 May 2026 18:40:44 +0100 Subject: [PATCH 206/238] Remove sample rate callback, move radio instance to radio.c. --- firmware/common/radio.c | 29 +++++++++++++++-------------- firmware/common/radio.h | 4 ---- firmware/hackrf_usb/hackrf_usb.c | 4 ---- 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index eb01b5de..f8b2e514 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -25,6 +25,7 @@ #include +#include "clock_gen.h" #include "clock_io.h" #include "fixed_point.h" #include "max283x.h" @@ -41,6 +42,9 @@ #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define MAX(x, y) ((x) > (y) ? (x) : (y)) +/* Driver instance. */ +radio_t radio; + void radio_init(radio_t* const radio) { for (uint8_t bank = 0; bank < RADIO_NUM_BANKS; bank++) { @@ -231,22 +235,19 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank) } new_n = (n != previous_n); - if (radio->sample_rate_cb) { - afe_rate = rate << n; - afe_rate = radio->sample_rate_cb(afe_rate, false); - previous_rate = radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE]; - if ((previous_n == RADIO_UNSET) || previous_rate == RADIO_UNSET) { - previous_afe_rate = RADIO_UNSET; - } else { - previous_afe_rate = previous_rate << previous_n; - } - new_afe_rate = (afe_rate != previous_afe_rate); - if (new_afe_rate) { - afe_rate = radio->sample_rate_cb(afe_rate, true); - } + afe_rate = rate << n; + afe_rate = sample_rate_set(afe_rate, false); + previous_rate = radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE]; + if ((previous_n == RADIO_UNSET) || previous_rate == RADIO_UNSET) { + previous_afe_rate = RADIO_UNSET; } else { - return 0; + previous_afe_rate = previous_rate << previous_n; } + new_afe_rate = (afe_rate != previous_afe_rate); + if (new_afe_rate) { + afe_rate = sample_rate_set(afe_rate, true); + } + rate = afe_rate >> n; new_rate = (rate != previous_rate); if (new_rate) { diff --git a/firmware/common/radio.h b/firmware/common/radio.h index b785c281..821c7fea 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -225,7 +225,6 @@ typedef struct { radio_config_mode_t config_mode; uint64_t config[RADIO_NUM_BANKS][RADIO_NUM_REGS]; volatile uint32_t regs_dirty; - sample_rate_fn sample_rate_cb; update_fn update_cb; } radio_t; @@ -263,8 +262,5 @@ void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode); /** * Driver instance. - * - * This needs to be configured and provided by the application - * binary. e.g. firmware/hackrf_usb/hackrf_usb.c */ extern radio_t radio; diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index eb7f85c5..5d71fa80 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -96,10 +96,6 @@ extern uint32_t __m0_end__; extern uint32_t __ram_m0_start__; extern uint32_t _etext_ram, _text_ram, _etext_rom; -radio_t radio = { - .sample_rate_cb = sample_rate_set, -}; - static usb_request_handler_fn vendor_request_handler[] = { NULL, usb_vendor_request_set_transceiver_mode, From 7cce66a7fa8449a3c64e55d62ba1bda8005d5c63 Mon Sep 17 00:00:00 2001 From: mndza Date: Fri, 22 May 2026 08:18:17 +0200 Subject: [PATCH 207/238] Fix reads with hackrf_spiflash when size is a multiple of 64 bytes. --- firmware/hackrf_usb/usb_api_spiflash.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/firmware/hackrf_usb/usb_api_spiflash.c b/firmware/hackrf_usb/usb_api_spiflash.c index d490eb0e..c698d599 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.c +++ b/firmware/hackrf_usb/usb_api_spiflash.c @@ -111,6 +111,7 @@ usb_request_status_t usb_vendor_request_read_spiflash( len, NULL, NULL); + usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } } else if (stage == USB_TRANSFER_STAGE_DATA) { @@ -121,7 +122,6 @@ usb_request_status_t usb_vendor_request_read_spiflash( ((addr + len) > spi_flash.num_bytes)) { return USB_REQUEST_STATUS_STALL; } else { - usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } } else { @@ -141,13 +141,9 @@ usb_request_status_t usb_vendor_request_spiflash_status( 2, NULL, NULL); - return USB_REQUEST_STATUS_OK; - } else if (stage == USB_TRANSFER_STAGE_DATA) { usb_transfer_schedule_ack(endpoint->out); - return USB_REQUEST_STATUS_OK; - } else { - return USB_REQUEST_STATUS_OK; } + return USB_REQUEST_STATUS_OK; } usb_request_status_t usb_vendor_request_spiflash_clear_status( From eb2e6a1c05a2a2080bec6964242c7e00c0734e24 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 28 May 2026 16:37:18 +0100 Subject: [PATCH 208/238] Move SSP0 and SSP1 bus instances to spi_ssp.{c,h}. --- firmware/common/spi_bus.c | 21 --------------------- firmware/common/spi_bus.h | 4 ---- firmware/common/spi_ssp.c | 17 +++++++++++++++++ firmware/common/spi_ssp.h | 4 ++++ 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/firmware/common/spi_bus.c b/firmware/common/spi_bus.c index a5332699..1b05c298 100644 --- a/firmware/common/spi_bus.c +++ b/firmware/common/spi_bus.c @@ -22,27 +22,6 @@ #include "spi_bus.h" -#include - -#include "spi_ssp.h" - -/* Driver instances. */ -spi_bus_t spi_bus_ssp0 = { - .obj = (void*) SSP0_BASE, - .start = spi_ssp_start, - .stop = spi_ssp_stop, - .transfer = spi_ssp_transfer, - .transfer_gather = spi_ssp_transfer_gather, -}; - -spi_bus_t spi_bus_ssp1 = { - .obj = (void*) SSP1_BASE, - .start = spi_ssp_start, - .stop = spi_ssp_stop, - .transfer = spi_ssp_transfer, - .transfer_gather = spi_ssp_transfer_gather, -}; - void spi_bus_start(spi_bus_t* const bus, const void* const config) { bus->config = config; diff --git a/firmware/common/spi_bus.h b/firmware/common/spi_bus.h index 23b3107b..07d5787d 100644 --- a/firmware/common/spi_bus.h +++ b/firmware/common/spi_bus.h @@ -51,7 +51,3 @@ void spi_bus_transfer_gather( spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count); - -/* Driver instances. */ -extern spi_bus_t spi_bus_ssp0; -extern spi_bus_t spi_bus_ssp1; diff --git a/firmware/common/spi_ssp.c b/firmware/common/spi_ssp.c index 7c288d51..868556be 100644 --- a/firmware/common/spi_ssp.c +++ b/firmware/common/spi_ssp.c @@ -28,6 +28,23 @@ #include #include +/* Driver instances. */ +spi_bus_t spi_bus_ssp0 = { + .obj = (void*) SSP0_BASE, + .start = spi_ssp_start, + .stop = spi_ssp_stop, + .transfer = spi_ssp_transfer, + .transfer_gather = spi_ssp_transfer_gather, +}; + +spi_bus_t spi_bus_ssp1 = { + .obj = (void*) SSP1_BASE, + .start = spi_ssp_start, + .stop = spi_ssp_stop, + .transfer = spi_ssp_transfer, + .transfer_gather = spi_ssp_transfer_gather, +}; + void spi_ssp_start(spi_bus_t* const bus, const void* const _config) { const ssp_config_t* const config = _config; diff --git a/firmware/common/spi_ssp.h b/firmware/common/spi_ssp.h index 822772b5..5e754dc4 100644 --- a/firmware/common/spi_ssp.h +++ b/firmware/common/spi_ssp.h @@ -45,3 +45,7 @@ void spi_ssp_transfer_gather( spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count); + +/* Driver instances. */ +extern spi_bus_t spi_bus_ssp0; +extern spi_bus_t spi_bus_ssp1; From b86b13930574a1ff97d82901bb8d55d489783404 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 29 May 2026 09:02:01 +0100 Subject: [PATCH 209/238] Express all delays as delay_us() or delay_ms(). --- firmware/blinky/blinky.c | 4 ++-- firmware/common/clock_gen.c | 2 +- firmware/common/cpu_clock.c | 16 ++++++++++++++-- firmware/common/cpu_clock.h | 3 +++ firmware/common/delay.c | 21 ++++++++++++--------- firmware/common/delay.h | 4 ++-- firmware/common/fpga_selftest.c | 8 ++++---- firmware/common/ice40_spi.c | 4 ++-- firmware/common/leds.c | 6 +++--- firmware/common/operacake_sctimer.c | 2 +- firmware/common/platform_detect.c | 20 ++++++++++---------- firmware/common/portapack.c | 14 ++++---------- firmware/common/power.c | 4 ++-- firmware/common/rad1o/display.c | 12 +++--------- firmware/common/rffc5071.c | 4 ++-- firmware/common/si5351c.c | 2 +- firmware/hackrf_usb/hackrf_usb.c | 6 +++--- firmware/hackrf_usb/usb_api_cpld.c | 2 +- 18 files changed, 70 insertions(+), 64 deletions(-) diff --git a/firmware/blinky/blinky.c b/firmware/blinky/blinky.c index fdaf3ef7..4bd11106 100644 --- a/firmware/blinky/blinky.c +++ b/firmware/blinky/blinky.c @@ -45,13 +45,13 @@ int main(void) led_on(LED2); led_on(LED3); - delay(2000000); + delay_ms(150); led_off(LED1); led_off(LED2); led_off(LED3); - delay(2000000); + delay_ms(150); } return 0; diff --git a/firmware/common/clock_gen.c b/firmware/common/clock_gen.c index 22f461c2..8a75074f 100644 --- a/firmware/common/clock_gen.c +++ b/firmware/common/clock_gen.c @@ -148,7 +148,7 @@ clock_source_t activate_best_clock_source(void) /* Enable PortaPack reference oscillator (if present), and check for valid clock. */ if (portapack_reference_oscillator && portapack()) { portapack_reference_oscillator(true); - delay(510000); /* loop iterations @ 204MHz for >10ms for oscillator to enable. */ + delay_ms(18); // for oscillator to enable. if (si5351c_clkin_signal_valid(&si5351c)) { source = CLOCK_SOURCE_PORTAPACK; } else { diff --git a/firmware/common/cpu_clock.c b/firmware/common/cpu_clock.c index 325de76f..32fd012c 100644 --- a/firmware/common/cpu_clock.c +++ b/firmware/common/cpu_clock.c @@ -33,6 +33,9 @@ #include "i2c_lpc.h" #include "si5351c.h" +/* We start with the CPU clock at 96MHz */ +unsigned int cpu_clock_mhz = 96; + /* Configure PLL1 (Main MCU Clock) to max speed (204MHz). Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. @@ -51,11 +54,14 @@ static void cpu_clock_pll1_max_speed(void) reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_IRC) | CGU_BASE_M4_CLK_AUTOBLOCK(1); CGU_BASE_M4_CLK = reg_val; + /* CPU is now at 12MHz */ + cpu_clock_mhz = 12; + /* 2. Enable the crystal oscillator. */ CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_ENABLE_MASK; /* 3. Wait 250us. */ - delay_us_at_mhz(250, 12); + delay_us(250); /* 4. Set the AUTOBLOCK bit. */ CGU_PLL1_CTRL |= CGU_PLL1_CTRL_AUTOBLOCK(1); @@ -95,11 +101,17 @@ static void cpu_clock_pll1_max_speed(void) reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_PLL1); CGU_BASE_M4_CLK = reg_val; + /* CPU is now at 102MHz */ + cpu_clock_mhz = 102; + /* 9. Wait 50us. */ - delay_us_at_mhz(50, 102); + delay_us(50); /* 10. Set the PLL1 P-divider to direct output mode (DIRECT=1). */ CGU_PLL1_CTRL |= CGU_PLL1_CTRL_DIRECT_MASK; + + /* CPU is now at 204MHz */ + cpu_clock_mhz = 204; } /* clock startup for LPC4320 configure PLL1 to max speed (204MHz). diff --git a/firmware/common/cpu_clock.h b/firmware/common/cpu_clock.h index 92ad6441..04929643 100644 --- a/firmware/common/cpu_clock.h +++ b/firmware/common/cpu_clock.h @@ -27,6 +27,9 @@ extern "C" { void cpu_clock_init(void); +// Current clock speed in MHz, updated on clock changes. +extern unsigned int cpu_clock_mhz; + #ifdef __cplusplus } #endif diff --git a/firmware/common/delay.c b/firmware/common/delay.c index ceb7693e..b74389b2 100644 --- a/firmware/common/delay.c +++ b/firmware/common/delay.c @@ -21,16 +21,9 @@ #include "delay.h" -void delay(uint32_t duration) -{ - uint32_t i; +#include "cpu_clock.h" - for (i = 0; i < duration; i++) { - __asm__("nop"); - } -} - -void delay_us_at_mhz(uint32_t us, uint32_t mhz) +static void delay_us_at_mhz(uint32_t us, uint32_t mhz) { #if defined(LPC43XX_M4) // The loop below takes 3 cycles per iteration. @@ -52,3 +45,13 @@ void delay_us_at_mhz(uint32_t us, uint32_t mhz) #error "No delay loop implementation" #endif } + +void delay_us(uint32_t us) +{ + delay_us_at_mhz(us, cpu_clock_mhz); +} + +void delay_ms(uint32_t ms) +{ + delay_us_at_mhz(ms * 1000, cpu_clock_mhz); +} diff --git a/firmware/common/delay.h b/firmware/common/delay.h index 870ba39e..eed806bb 100644 --- a/firmware/common/delay.h +++ b/firmware/common/delay.h @@ -27,8 +27,8 @@ extern "C" { #include -void delay(uint32_t duration); -void delay_us_at_mhz(uint32_t us, uint32_t mhz); +void delay_us(uint32_t us); +void delay_ms(uint32_t ms); #ifdef __cplusplus } diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index 06f2e8ee..7170422c 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -200,7 +200,7 @@ bool fpga_if_xcvr_selftest(void) // Capture 1: 4 Msps, tone at 0.5 MHz, narrowband filter OFF sample_rate_set(SR_FP_MHZ(4), true); - delay_us_at_mhz(1000, 204); + delay_ms(1); if (rx_samples(num_samples, 2000000) == -1) { timeout = true; } @@ -211,7 +211,7 @@ bool fpga_if_xcvr_selftest(void) // Capture 2: 4 Msps, tone at 0.5 MHz, narrowband filter ON narrowband_filter_set(1); - delay_us_at_mhz(1000, 204); + delay_ms(1); if (rx_samples(num_samples, 2000000) == -1) { timeout = true; } @@ -224,7 +224,7 @@ bool fpga_if_xcvr_selftest(void) fpga_set_tx_nco_pstep(&fpga, 255); sample_rate_set(SR_FP_MHZ(20), true); narrowband_filter_set(0); - delay_us_at_mhz(1000, 204); + delay_ms(1); if (rx_samples(num_samples, 2000000) == -1) { timeout = true; } @@ -235,7 +235,7 @@ bool fpga_if_xcvr_selftest(void) // Capture 4: 20 Msps, tone at 5 MHz, narrowband filter ON narrowband_filter_set(1); - delay_us_at_mhz(1000, 204); + delay_ms(1); if (rx_samples(num_samples, 2000000) == -1) { timeout = true; } diff --git a/firmware/common/ice40_spi.c b/firmware/common/ice40_spi.c index 2685092a..880e0be2 100644 --- a/firmware/common/ice40_spi.c +++ b/firmware/common/ice40_spi.c @@ -112,14 +112,14 @@ bool ice40_spi_syscfg_program( gpio_clear(drv->gpio_select); // Wait a minimum of 200 ns. - delay_us_at_mhz(1, 204 / 4); // 250 ns. + delay_us(1); // Release CRESET_B or drive CRESET_B = 1. gpio_set(drv->gpio_creset); // Wait a minimum of 1200 μs to clear internal configuration memory. // Testing showed us that we need to wait longer. Let's wait 1800 μs. - delay_us_at_mhz(1800, 204); + delay_us(1800); // Set SPI_SS = 1, Send 8 dummy clocks. gpio_set(drv->gpio_select); diff --git a/firmware/common/leds.c b/firmware/common/leds.c index ab9b56fb..e1fd507b 100644 --- a/firmware/common/leds.c +++ b/firmware/common/leds.c @@ -84,17 +84,17 @@ void set_leds(const uint8_t state) } } -void halt_and_flash(const uint32_t duration) +void halt_and_flash(const uint32_t period_ms) { /* blink LED1, LED2, and LED3 */ while (1) { led_on(LED1); led_on(LED2); led_on(LED3); - delay(duration); + delay_ms(period_ms / 2); led_off(LED1); led_off(LED2); led_off(LED3); - delay(duration); + delay_ms(period_ms / 2); } } diff --git a/firmware/common/operacake_sctimer.c b/firmware/common/operacake_sctimer.c index 76453e57..c5ec8a3b 100644 --- a/firmware/common/operacake_sctimer.c +++ b/firmware/common/operacake_sctimer.c @@ -75,7 +75,7 @@ void operacake_sctimer_init(void) // there are additional instructions that fill the time. If the duration of // the actions from here to the first access to the SCTimer is changed, then // this delay may need to be increased. - delay(8); + delay_us(1); // Pin definitions for the HackRF // U2CTRL0 diff --git a/firmware/common/platform_detect.c b/firmware/common/platform_detect.c index 7c9fb53d..475ad1e1 100644 --- a/firmware/common/platform_detect.c +++ b/firmware/common/platform_detect.c @@ -194,11 +194,11 @@ void detect_hardware_platform(void) /* activate internal pull-down */ scu_pinmux(P5_0, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); scu_pinmux(P6_10, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); - delay_us_at_mhz(4, 96); + delay_us(4); /* tri-state for a moment before testing input */ scu_pinmux(P5_0, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); scu_pinmux(P6_10, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - delay_us_at_mhz(4, 96); + delay_us(4); /* if input rose quickly, there must be an external pull-up */ detected_resistors |= (gpio_read(&gpio2_9_on_P5_0)) ? P5_0_PUP : 0; detected_resistors |= (gpio_read(&gpio3_6_on_P6_10)) ? P6_10_PUP : 0; @@ -207,12 +207,12 @@ void detect_hardware_platform(void) scu_pinmux(P5_0, SCU_GPIO_PUP | SCU_CONF_FUNCTION0); scu_pinmux(P6_10, SCU_GPIO_PUP | SCU_CONF_FUNCTION0); scu_pinmux(P6_5, SCU_GPIO_PUP | SCU_CONF_FUNCTION0); - delay_us_at_mhz(4, 96); + delay_us(4); /* tri-state for a moment before testing input */ scu_pinmux(P5_0, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); scu_pinmux(P6_10, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); scu_pinmux(P6_5, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - delay_us_at_mhz(4, 96); + delay_us(4); /* if input fell quickly, there must be an external pull-down */ detected_resistors |= (gpio_read(&gpio2_9_on_P5_0)) ? 0 : P5_0_PDN; detected_resistors |= (gpio_read(&gpio3_6_on_P6_10)) ? 0 : P6_10_PDN; @@ -221,37 +221,37 @@ void detect_hardware_platform(void) switch (detected_resistors) { case JAWBREAKER_RESISTORS: if (!(supported_platform() & PLATFORM_JAWBREAKER)) { - halt_and_flash(3000000); + halt_and_flash(500); } platform = BOARD_ID_JAWBREAKER; return; case RAD1O_RESISTORS: if (!(supported_platform() & PLATFORM_RAD1O)) { - halt_and_flash(3000000); + halt_and_flash(500); } platform = BOARD_ID_RAD1O; return; case HACKRF1_OG_RESISTORS: if (!(supported_platform() & PLATFORM_HACKRF1_OG)) { - halt_and_flash(3000000); + halt_and_flash(500); } platform = BOARD_ID_HACKRF1_OG; break; case HACKRF1_R9_RESISTORS: if (!(supported_platform() & PLATFORM_HACKRF1_R9)) { - halt_and_flash(3000000); + halt_and_flash(500); } platform = BOARD_ID_HACKRF1_R9; break; case PRALINE_RESISTORS: if (!(supported_platform() & PLATFORM_PRALINE)) { - halt_and_flash(3000000); + halt_and_flash(500); } platform = BOARD_ID_PRALINE; break; default: platform = BOARD_ID_UNRECOGNIZED; - halt_and_flash(1000000); + halt_and_flash(150); } uint32_t adc0_3 = check_pin_strap(3); diff --git a/firmware/common/portapack.c b/firmware/common/portapack.c index d3d848fc..0c3cbce2 100644 --- a/firmware/common/portapack.c +++ b/firmware/common/portapack.c @@ -31,12 +31,6 @@ #include "platform_gpio.h" #include "platform_scu.h" -static void portapack_sleep_milliseconds(const uint32_t milliseconds) -{ - /* NOTE: Naively assumes 204 MHz instruction cycle clock and five instructions per count */ - delay(milliseconds * 40800); -} - typedef struct { gpio_t gpio_dir; gpio_t gpio_lcd_rdx; @@ -244,7 +238,7 @@ static void portapack_lcd_sleep_out(void) // "It will be necessary to wait 120msec after sending Sleep Out // command (when in Sleep In Mode) before Sleep In command can be // sent." - portapack_sleep_milliseconds(120); + delay_ms(120); } static void portapack_lcd_display_on(void) @@ -310,11 +304,11 @@ static void portapack_lcd_wake(void) static void portapack_lcd_reset(void) { portapack_lcd_reset_state(false); - portapack_sleep_milliseconds(1); + delay_ms(1); portapack_lcd_reset_state(true); - portapack_sleep_milliseconds(10); + delay_ms(10); portapack_lcd_reset_state(false); - portapack_sleep_milliseconds(120); + delay_ms(120); } static void portapack_lcd_init(void) diff --git a/firmware/common/power.c b/firmware/common/power.c index 1256e595..70c8c0f1 100644 --- a/firmware/common/power.c +++ b/firmware/common/power.c @@ -132,7 +132,7 @@ static inline void enable_rf_power_praline(void) gpio_clear(platform_gpio()->vaa_disable); /* Let the voltage stabilize */ - delay(1000000); + delay_ms(35); } static inline void disable_rf_power_praline(void) @@ -147,7 +147,7 @@ static inline void enable_rf_power_rad1o(void) gpio_set(platform_gpio()->vaa_enable); /* Let the voltage stabilize */ - delay(1000000); + delay_ms(35); } static inline void disable_rf_power_rad1o(void) diff --git a/firmware/common/rad1o/display.c b/firmware/common/rad1o/display.c index 91813aab..c0c090b3 100644 --- a/firmware/common/rad1o/display.c +++ b/firmware/common/rad1o/display.c @@ -10,12 +10,6 @@ #include "gpio_lpc.h" #include "delay.h" -static void delayms(const uint32_t milliseconds) -{ - /* NOTE: Naively assumes 204 MHz instruction cycle clock and five instructions per count */ - delay(milliseconds * 40800); -} - static struct gpio gpio_lcd_cs = GPIO(4, 12); /* P9_0 */ static struct gpio gpio_lcd_bl_en = GPIO(0, 8); /* P1_1 */ static struct gpio gpio_lcd_reset = GPIO(5, 17); /* P9_4 */ @@ -85,9 +79,9 @@ void rad1o_lcdInit(void) // Reset the display gpio_clear(&gpio_lcd_reset); - delayms(100); + delay_ms(100); gpio_set(&gpio_lcd_reset); - delayms(100); + delay_ms(100); select(); @@ -115,7 +109,7 @@ void rad1o_lcdInit(void) (1 << 12) | (0 << 13) | (0 << 14) | 0); write(0, 0x01); /* most color displays need the pause */ - delayms(10); + delay_ms(10); size_t i = 0; while (i < sizeof(initseq_d)) { diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 2a1866d2..df25987c 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -163,13 +163,13 @@ void rffc5071_lock_test(rffc5071_driver_t* const drv) rffc5071_enable(drv); // Wait 1ms. - delay_us_at_mhz(1000, 204); + delay_ms(1); // Check for lock. lock = rffc5071_check_lock(drv); rffc5071_disable(drv); - delay_us_at_mhz(100, 204); + delay_us(100); selftest.mixer_locks[i] = lock; } diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 77d77703..6672b3b0 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -224,7 +224,7 @@ void si5351c_reset_plls(si5351c_driver_t* const drv, si5351c_pll_mask_t mask) set_PLLA_RST(drv, (mask & SI5351C_PLL_MASK_A) ? true : false); set_PLLB_RST(drv, (mask & SI5351C_PLL_MASK_B) ? true : false); si5351c_regs_commit(drv); - delay_us_at_mhz(2000, 204); + delay_ms(2); si5351c_enable_clock_outputs(drv); } diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 5d71fa80..f9a4e40b 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -433,7 +433,7 @@ int main(void) if (board_id != BOARD_ID_RAD1O) { clock_gen_shutdown(); } - delay_us_at_mhz(10000, 96); + delay_ms(10); pins_setup(); #ifdef IS_PRALINE if (IS_PRALINE) { @@ -491,7 +491,7 @@ int main(void) #ifdef IS_NOT_PRALINE if (IS_NOT_PRALINE) { if (!cpld_jtag_sram_load(&jtag_cpld)) { - halt_and_flash(6000000); + halt_and_flash(1000); } } #endif @@ -503,7 +503,7 @@ int main(void) #else fpga_image_load(&fpga_loader, 0); #endif - delay_us_at_mhz(100, 204); + delay_us(100); fpga_spi_selftest(); fpga_sgpio_selftest(); } diff --git a/firmware/hackrf_usb/usb_api_cpld.c b/firmware/hackrf_usb/usb_api_cpld.c index 391b9366..38103c81 100644 --- a/firmware/hackrf_usb/usb_api_cpld.c +++ b/firmware/hackrf_usb/usb_api_cpld.c @@ -76,7 +76,7 @@ void cpld_update(void) cpld_xsvf_buffer, refill_cpld_buffer); if (error == 0) { - halt_and_flash(6000000); + halt_and_flash(1000); } else { /* LED3 (Red) steady on error */ led_on(LED3); From 4f9f6a4c7425144ea43348f424c52d150ec67fa3 Mon Sep 17 00:00:00 2001 From: Dreg Date: Wed, 3 Jun 2026 02:41:37 +0200 Subject: [PATCH 210/238] Add SigDigger support information to documentation --- docs/source/software_support.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/source/software_support.rst b/docs/source/software_support.rst index e8487652..66594e6b 100644 --- a/docs/source/software_support.rst +++ b/docs/source/software_support.rst @@ -43,6 +43,11 @@ Software That Has Direct Support For HackRF * `https://xakcop.com/aprs-sdr `__ +* SigDigger (Windows/Linux/macOS) + + * `https://github.com/BatchDrake/SigDigger `__ + * Supports HackRF through SoapySDR / SoapyHackRF + Software That Can Use Data From HackRF @@ -74,4 +79,4 @@ Troubleshooting Recommendations Many of these tools require libhackrf and at times HackRF Tools. It may help you to have updated libhackrf and HackRF Tools when troubleshooting these applications. -It is also strongly suggested, and usually required, that your HackRF Tools and HackRF firmware match. \ No newline at end of file +It is also strongly suggested, and usually required, that your HackRF Tools and HackRF firmware match. From 5d9b6bf4119228c65ea2b72991926e956bca5c4c Mon Sep 17 00:00:00 2001 From: mndza Date: Thu, 28 May 2026 14:05:13 +0200 Subject: [PATCH 211/238] add gateware documentation --- docs/images/gateware-basic-block-diagram.png | Bin 0 -> 195902 bytes docs/images/gateware-basic-block-diagram.svg | 4 + .../images/gateware-ext-prec-rx-dsp-chain.png | Bin 0 -> 70790 bytes .../images/gateware-ext-prec-rx-dsp-chain.svg | 4 + .../images/gateware-ext-prec-tx-dsp-chain.png | Bin 0 -> 51198 bytes .../images/gateware-ext-prec-tx-dsp-chain.svg | 4 + docs/images/gateware-halfprec-dsp-chain.png | Bin 0 -> 79385 bytes docs/images/gateware-halfprec-dsp-chain.svg | 4 + .../gateware-rx-only-basic-block-diagram.png | Bin 0 -> 138600 bytes .../gateware-rx-only-basic-block-diagram.svg | 4 + docs/images/gateware-standard-dsp-chain.png | Bin 0 -> 130043 bytes docs/images/gateware-standard-dsp-chain.svg | 4 + .../gateware-tx-only-basic-block-diagram.png | Bin 0 -> 137152 bytes .../gateware-tx-only-basic-block-diagram.svg | 4 + docs/source/gateware.rst | 118 ++++++++++++++++++ docs/source/hackrf_pro.rst | 2 + docs/source/index.rst | 7 ++ 17 files changed, 155 insertions(+) create mode 100644 docs/images/gateware-basic-block-diagram.png create mode 100644 docs/images/gateware-basic-block-diagram.svg create mode 100644 docs/images/gateware-ext-prec-rx-dsp-chain.png create mode 100644 docs/images/gateware-ext-prec-rx-dsp-chain.svg create mode 100644 docs/images/gateware-ext-prec-tx-dsp-chain.png create mode 100644 docs/images/gateware-ext-prec-tx-dsp-chain.svg create mode 100644 docs/images/gateware-halfprec-dsp-chain.png create mode 100644 docs/images/gateware-halfprec-dsp-chain.svg create mode 100644 docs/images/gateware-rx-only-basic-block-diagram.png create mode 100644 docs/images/gateware-rx-only-basic-block-diagram.svg create mode 100644 docs/images/gateware-standard-dsp-chain.png create mode 100644 docs/images/gateware-standard-dsp-chain.svg create mode 100644 docs/images/gateware-tx-only-basic-block-diagram.png create mode 100644 docs/images/gateware-tx-only-basic-block-diagram.svg create mode 100644 docs/source/gateware.rst diff --git a/docs/images/gateware-basic-block-diagram.png b/docs/images/gateware-basic-block-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..58f99e7c6a7622edbb820923cbd6d4834d2190e9 GIT binary patch literal 195902 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%0DQwoE@m47=`rp~=S*1%crihTn3-FbFJmlvKOR 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/h8H1cdTAwMWR0qrL284aN9729+/ZcdFx1MDAwN1x1MDAwNrG02VxmeD0x//1kyTaS0Fx1MDAwMrLFmPbAxHR0I6moUuXyfVWZWf/9Y2lpefjcc5f/vbTsPlXKrWa1X35cXP7Tfv/g9lx1MDAwN81uXHUwMDA3L4H370H3vl/x7mxcZoe9wb//9S//XHSn0m2/PuW23LbbXHUwMDE5XHUwMDBl8L7/x38vLf3X+1x1MDAxM680q/bZy8Y57Dw/XFzXXG6lm63rWsttNODMe9S76b0zfbcyLHfqLde/9ITfXHUwMDBiplx1MDAxZC6lJpRcdTAwMWJQIOTo6jNeLVxi4kiqqZLMXGIpXHUwMDA1gdHlx2Z12MBbuGGOJMZQwyhhyojRXHUwMDFkXHK3WW9cZu0tXHUwMDAyb9GMXHSuXHJlknM+uue1R/9eXCKjb1x1MDAwNsN+99Zd7ba6fdvt/6Ou/c/v9E25clvvd+87Vf+emvfx76k1W63j4bPXMr5lfKPLY+2fv/VcdTAwMWXGvk96XG5/sN7ouINBqK/dXrnSXHUwMDFj2lx1MDAxN0WJ/63tXW+r6k3Yf/w+9cttd8vOWOe+1Vx1MDAxYX3d7FRdO1x1MDAwZstXw9Cvdapvv1x1MDAxNrp74LpV74Vcblx0kjL/PfqiRSnR41/vdzuenFx1MDAwMVGMXHUwMDEzQYnxf39QQlx1MDAwMVx1MDAxYnrN1sqtgeu/aNuJtYDw+WO571XLr49QpYxWlFBcclKNrreandvxrre6lVv/V7xv//ozTp77va6QzeKPYbn93H/aboq7X5t3U8szyrCjXHUwMDE4MYJzqViiPFx1MDAwYq1cdTAwMDRII6iIXGI0UOJwbjTBh1x1MDAxNSdU6DiJXHUwMDA2x1DBOGgjlFxuXGZ9IdAjgX6cXqCpJGiCXHUwMDE4XHUwMDFholx1MDAxOInWPFwi5+9cdTAwMDJNJTVAgc2xON+d3pTkbu38+fjxeO30x+GAtqE2tThcdTAwMWKiXHUwMDFkTZRcdTAwMDLzKs5cIizOlDl4UVx1MDAxOM5cdFx1MDAwMEHZ11x1MDAxMXGmXHUwMDAwjqZCXHUwMDFhRjRcdTAwMTeKU1x1MDAxYVx1MDAxNWctUZpcdTAwMDHbodaQa5m3fS6Lqv7txflpY3p5NtpcdTAwMTBuqDIx4mxcdTAwMDLiOi7OIIxC4aNcdTAwMWZcdTAwMTLot1x1MDAwYr5cdTAwMDRcdTAwMDaksLr1dFN5Wi109tpnJXq4Uz68a5vReEKSWO73u4/Loyt//ZnWLu+drJUu9tdXKrtcdTAwMWJseHhr9lZcdTAwMGZcdTAwMGbj21x1MDAxZLpPw0Czb3+bpIU6XHUwMDFmLUzvZ7iPYVx1MDAwNWTEUVx1MDAxYYBTKVxmXHRaXHUwMDA1K1bCYUorjW5cdTAwMDS1XHUwMDA3b4jCI4X6K/GjcV6pojrGmVxikq+6XHL75c6gV+6jXFz87ip3lsGFIPrU+Js8ol3WwIlEXHUwMDE3gu7DoFx1MDAxN6FCfUTn8lx1MDAxNF9fXHUwMDFhrVx1MDAxNOL4i6XVn51mZ+j2a+VKYM5r3c7wuPnyiuhC366X282Wffky1Fix1azb17BcXHFta8vBdzFsXCLlXHUwMDE43dBuVqtBXHUwMDFmVMFGy82O29+axpl1+816s1NunfhcdTAwMDNYiul/+X7Y/eFcdTAwMGVeRzDs37vBl+RuvutcdTAwMDV1QKSo9EGZXGbW9eXOpTxfLz5fXHUwMDFmXFxcdTAwMGW2V1x1MDAxZad2rIiSlcNcdTAwMTVcdTAwMTNcdTAwMDIo/i+1b6rDQFx1MDAxMalcdTAwMGZcdTAwMTGKcP+NRoBcIpNEMJzwWOrzXHUwMDBlXHUwMDE0lWZCcl+5XHUwMDE2QHGk5s/Ta7lcdTAwMTTANVx1MDAxMTpcdTAwMGUnUqLE+Ncjz6qRMFmOO8/Mxz0s3Ynmw01p0NpbP+akqzZLMUz+1UGHpFlcdTAwMWHuXGJASSaaIezgYZjIqEZcdTAwMWZmXHUwMDE0gJJSXHRCorKMJN6qXHUwMDAxXHUwMDE4fFxcXCKLZ1FRXHUwMDA2plx1MDAxZKRVQiiNnJ+agG2bLMtaatfIL3Fb1fKg4f69XHUwMDAy/TK9QKNcdTAwMTFcdTAwMTFaK4g6KG9WXCJcdTAwMDAyXHUwMDAwXHUwMDE1XHUwMDA1XGL0a7NcdTAwMTBoTTNcYvTo6163OY5E/b8t+e/a+8fo7//5M/ZuLlx1MDAxZMlQmNF4Wsn1efznny5cdTAwMDA1XHUwMDBlRUhGXHUwMDE5YUC5MJOaS9SOmTRcdTAwMTfRM7+9XGJoXHUwMDFlXGbL/eFcbkpes1PHN+8j9Pdlw1e/Te7Of1xmLnuuu71XP9m5X19bXHUwMDFmnq5cdTAwMDVg+nK7W/WUpdu/aVx1MDAwZYNcdTAwMTdqzSe3emhnNjSxS+idXHQzdj1cdTAwMGZcdTAwMTiSSuIvOtlcdTAwMGY6RqNcdTAwMTFcdTAwMTbjXHUwMDFmXHUwMDFh/1BcdTAwMTJcImNcdTAwMTjximW3U508guur45dcdTAwMWQlXHUwMDBipdvqxd7dkOzp9lnxcyOwnTSMXHTKuUTYSKVSf4ZcdTAwMDcosftEKoJcZpyjXHUwMDBmT1x1MDAxOYM3XHUwMDBmRWuYXHUwMDFibjliXHUwMDE5cITBa2jqmmOQxG3ddFx1MDAxZj2dXG7hIa/vx259XHUwMDEyx3uzPFx1MDAxMOz/a5/GxjxBNYKqXHUwMDE1XHUwMDEy39dBZG0sRTX8l5hCMd+GxT4/rPSeTFx1MDAxY2eqxk4/znj13Vx1MDAxYVx1MDAxY/fcSrPcilhU7ErkYlxufrgvXHUwMDBmyo9rZ5f9XHUwMDBlb/bO13ZcdTAwMGau8P6pXHUwMDExMaJYh0lBJOfK4IBYmOratSaDKFxu2SxeQs5rokun/lpcdTAwMTPlaFx1MDAxZGhcdTAwMDBU+zBcdTAwMDK0Q6lWyvcx+UDhXHUwMDFiqMHNze9ccoXLXHUwMDA30yNcdTAwMDfFXGZcdTAwMDGUd/83g0umdPxbXHUwMDFmOFx1MDAxOFBcdTAwMDKn5kPAIUFRPfHbXFzbKdS7e9Qt1I6u3EpVN0QhjzWmo+Lx1UOrddXacMU+2dgtdfZXrqZaY0ptdqUn6V79cqO92qn1n1bbJ7/Ory+n625Ej2e6dpU+/pS1K9RAR1x1MDAxMlx0XFxgd1x1MDAwNKNhVoD8V9idXHUwMDEy6+KQOlx1MDAwNCTmXZ2tQbBcdTAwMWYgkiokXHUwMDBlMWtXIPLV4m+zdlU+nF6TcXKEZuhX4jiANMmkXHUwMDE2XGYxYDjMglx1MDAwMyiSQXp9YXxb+TneONxcbtiyr1uxmuBcdTAwMTPHV6zG+p3PSlU6dp3kl1x1MDAxNVx1MDAwNU9RhUK3ySlcdTAwMWJbqEK3XGZcblxiIYogV5CBvbKRV1x1MDAxNoh0iZZcdTAwMWPVXHUwMDFjXbuKW6dCY0CJolJIdPxIOfJep/pcdTAwMGU7QOWjXGbOWUlGXHRcdTAwMDdcYlxu7ptGM1x1MDAxNXHZ71x1MDAxYc3RXHUwMDE2U5wkf4Zy8s3pS0shMczkm2HlobHdbFx1MDAxZWzxl5PTx3Jzc/C0df553zyr7arS3p5unD5etEFcdTAwMGWO+Fx1MDAxMWlcXD33e/Po89Pfa4rPR+rjXGKJqoxcdTAwMDZDIFx1MDAwMVx1MDAwZvt8qlx1MDAxY4VcdTAwMDBdXHUwMDAzKrti1PhcdTAwMTDfh/Dc4dbpcyaIQJTv25OF059sITJsWGmpXHUwMDA1XHUwMDEwXHUwMDA1cUvZLFx1MDAxOb8rbXcluJrFdtXnfP6Pi6XS8eFSpYHud1x1MDAxZVxc/1x1MDAwNLc77vrju59cdTAwMGZcdTAwMDJwz55qvc06O+a7l8eX5uCktlH8kVx0XHUwMDAxKIluXHUwMDFjfbNgwMZ0XHUwMDFhlENcdTAwMDDhvaHUbjLFbELPXHUwMDAzXHUwMDAyqNUqpmJ+c/0+nl69mdSccFx1MDAxZavegieG6EkphcZZyFx1MDAxYlx1MDAwMNBcdTAwMTV1uK86xeLwR+vxviV27s9rjVx1MDAxYzzqzWDQ6pdZof1jyG/qLWJWSi/Dz1x1MDAwM4Dn/e1cbu3tt3bL7ZWD+52Dx63CeUKzmbq7/oOd9n+121x1MDAxN6o9XHUwMDFjlipcdTAwMDf7dyu7c0n6099rKlx1MDAwMJBcdTAwMGWzLp5cdEC+wHzt8XRAaIcobdCUgFx1MDAxMujk/Y0+XHUwMDFmXHUwMDAxMIchnyCIIOz+t45cdFx1MDAxOFsggCRcdTAwMGJxkiFIXGZsXHUwMDE4qlFcdTAwMTFbYIlANHTMj3m0XHUwMDBitERcdTAwMDUgwrwggJM5Q1x1MDAwMFx1MDAxM9zuOFx1MDAwMojvfk7RKpX2rSno2/XLwu456TUua7Xn8keiVSxcdTAwMDQggcjv90VcdTAwMDDNXHUwMDEx9nN0XHUwMDFk2saDxsSBToNcdTAwMDFcdTAwMTZxoJM1/CaDhlx1MDAxYuBGiyjft3aaJ2u4UZJ7QUV5o4DaRfual3a2iqq1Vzu77lV/XGZkZypv/fd6v/R+png/Sjl1UIS1kppcdTAwMTLJXHUwMDAzkbRv/Jda6ouqpIlmLMp/OXNQ9o3RXHUwMDFjXHIs0uRcdTAwMDX/zaJcdTAwMWKVXGaL3lxcMMNcdTAwMTTEXHUwMDAyZClcdTAwMTOVgyM5YYhs5s/7XHUwMDE1S6vz4PQmeJqYXHUwMDE4zbx9XePm/PHa7PRKtfvhk7o5XZVX3Ytsvk4hXHUwMDE1RXCE2qzHXHUwMDExLOJbg1x1MDAxN1xyXHUwMDAz0IIyXHUwMDE23bfKRHdtXHUwMDAyT5BSL9juSJur02sz4ERcdTAwMTh847FhbGhLk8EssSSEm9xd3Uuh9munXFzefNp7pCuVlave3vlqwor3l7q69H5OcnVcdTAwMTI05YZgh1x1MDAxNFx1MDAwZqe6eUxcdTAwMGaQwdm9W6ZETNAnXHUwMDA3R9jcXHUwMDA0IbnhlFx1MDAwN+5YuLqJyuFmcHVUXHUwMDFhZG3BXHL0XHUwMDAwXHUwMDBlVFx1MDAxMVx1MDAwN/iuXHUwMDFjTFBE9EzNJL3tU5lcdKXiXFy4ulx0jmbc1YV6nZOr2yj21l+u6NMludx+qOtOsdIoTaO9fp4q06ihvlx1MDAxM/P4nPVOQmj0dYpcdTAwMWFcdTAwMDJcdTAwMTBccrXiwlx1MDAwMYtTXHIwRZAqxLi4he4m6W4zg+6i4WSII2TcTi5Pic9W0jCNNOTLc1Mjyru3epqH8rbc2jBFdYfdXpLehjo7rqSh3uWjpMVCf3ejfK97PXq2s3lz8uNwcPWUKS5SU2RcdTAwMWRcXFxuXHUwMDBlJLBcXGdfXHUwMDBlaONIw7lcdTAwMDaG01wilIqJv1x1MDAwMPTTXHUwMDAyXHUwMDA0wk1OhM1cdTAwMTiP6qowjkJnTYBLyuxeTt6A9FtER/6aXm+5VNJcdTAwMTKIuKVcdTAwMTdk9Ynbq1xiZJFeasHyXHUwMDBmj9zYPN1erz5t9y/JVePlWP56gFx1MDAxY3ZK+Fx1MDAwNdTF2epq79I9JSdrXHUwMDA3zy/P9Vp8s1+7o5E+/lx1MDAxNFeJwPR17ZOCje/mYT7IiHJsglx1MDAxZcNcdTAwMWJcdTAwMTS3YVx1MDAwYlx1MDAxMVx1MDAwNWRvcYyow1x1MDAwNrFcdTAwMTgsNjQy6Nzt9DonKFVM0Vx1MDAwNJ1jiXGMgFx1MDAxNFx1MDAxZDWOzGJJ53M49/hwa1x1MDAxZXDuXHUwMDA0XHUwMDA3XHUwMDE2XHRiXGb2Olx1MDAxZlx1MDAxN5qeQDRNkSGKfo2gd+NMqfCiLCiB+ol+z1x1MDAxONRjQaNEdVx1MDAxZeJcdTAwMTe+hVx1MDAwM+1kXHUwMDAwvlx1MDAxMnDahGJxpFXqxFx1MDAxNVx1MDAxZCFcYlx1MDAwNfPBXHUwMDEyQ2mO7nCvWd+H++NVpuBcdTAwMDW2f1x1MDAxZLfbv3hcdTAwMGUhXHUwMDAxs4qMmFXI5dlFvchcdTAwMWae6XqtWNi/b9bldVx1MDAxMe7/QThcIn38KThCSOZozblhTKGRXGLbIGOvjVKkI1x1MDAxNsgsynh83Op0p7c6klx1MDAxOC5s2FSc0ZHJy8goXlx1MDAxMslcdTAwMTWbXHUwMDA121aQQXDjIMSSdef9butnp+/Wm1x1MDAwM4RcdTAwMDKDeUBcdTAwMTVcdTAwMTN8elxmqnhcdTAwMWbIUsw48sFcdTAwMTnpxnjWJVx1MDAxMJA9SIVcdTAwMWNfXHUwMDBirnjMxi9aXHUwMDAxaXeLNFx1MDAwMSNcdTAwMTDrZomP+EdVQLghJMtOsLSp5ELE8Vx1MDAwNkheXHUwMDFlp1RcdTAwMTjgdEbpTyYov19SXHUwMDAyIVEgP/90IVwiyX5zXHUwMDExb/6PqTGQXHUwMDFlLvahXHUwMDExRGpcZvxcdTAwMTlcdTAwMWVeuMJA2lxi/qZcblx1MDAwM2FcdTAwMDVcdTAwMWRPT1x1MDAxZv/N8Wspln3/8mFtX93frJpB8aBeLojn1pqJWvaJXGZcdTAwMTLtO1qKaPybl1x1MDAwNEdBXHUwMDEyKVx1MDAxOYnZMMmWm1x1MDAwZVx1MDAxYWFcdTAwMWWhi1XYONvOp7ftRmgk5Do2xlx1MDAxNbuSuH2CRJ5cdTAwMTG0TrmHXHUwMDA1zIpFvlx1MDAxNFx1MDAwZlulW1a7u9u/bT+QXHUwMDAzXtzY2P88K/tEknpqu59IhEtt97eJr0+frzRcdTAwMTbJuWNQMqkhVFx1MDAxYaXDVTKUQJipmOZMXHUwMDE5XHUwMDAzXHUwMDEwXHUwMDAzMynxSoUgXaHAXHUwMDA0XHUwMDBiLnctqORk2yOy4Epcbmh6XGKLw5WGJlfIIHYhkbM5rFxi6aWnL5U71Z+dWqv7+M7H5oFNTvDvsYn2diRL8Vx1MDAwM8mHTqabzzQ6yTWqKaIyYZeKJKVcdTAwMTCOrjLGwW+1QCShXHUwMDE0XHUwMDA0QrlcdTAwMDOxVYaB4lx1MDAxNuDZqkExe07EQSlcdTAwMDNEM4pcdMlcdTAwMDSC9YXWJ2i9zKD1OCH4SmVsJFwiqJRIRFx1MDAwZcBQ9WdcdTAwMTJY/CGtz7egXpJAek9HRNFvLuKXp+SD6ZU3PspcdTAwMDc5Uj5mw+nAmLGigJZq2T1iXHUwMDAwjuPkRIrIIDJcdTAwMTLCdJv2oSFcdTAwMTTI2Fx1MDAxOFx1MDAwNKFcdTAwMWZcdTAwMWZFhFx1MDAxNMZcdTAwMTG/XGbUMCx/+XLD0bV298Hda76+ncF5c9h4U6QpUFv6JkW6PffOOeGKKsNcdTAwMTWTMmzPXHUwMDE5NfjiLcFcdTAwMDQ0XHUwMDA0jETzpzhz8GnCkFx1MDAxOVx1MDAxYYnTomP2IIkjwFJQramWXHUwMDA2mM5SXCL1n2XRi1x1MDAxOSw6cnWlNfC4TFx1MDAxMZqyKVx1MDAwMIpSbmZcdTAwMTNXoD+UKpKvRU+USPspRIXx8zY9PVx1MDAxMOFDXHUwMDA2kThm7Fx1MDAxMzaHglx1MDAxMPpZOz6DpUmSqZeztdOfMKjpyyGp+y12zY0qxDZcbqRcbsa2e/up0kyK6WCOQrFVaJNfXHUwMDE3oWNcdTAwMTAyV462K6eCI9RG6rSoOJ1oT1cy2FOcNqS3sYl3QJKrzTHEj0ZcdTAwMGI6XHUwMDBiWjxcdTAwMDfmNHR3XHUwMDAxuFx1MDAwMyh5mttQXCJcdTAwMDVcdTAwMDBi0vOFZImeUYtcdTAwMTH1+LyBn4WlTNtcdTAwMDKxcHisynKUenw9avfGgC9ZKWortEk/JMB+kJaAsTtcdTAwMGZInFx1MDAwNFx1MDAxMqjvvI2z/djZfJG7W1x1MDAwN72Ty5eSXFw3m/x5Olx1MDAwNE5cdJNcdTAwMGVRXvo157ZKc8hjUPRcdTAwMThGS+RENl3NXHUwMDA0XHUwMDE3yt5dhiBcdTAwMGVFZ8KVRoxcdTAwMWVKXGZcciBwXCKNd9iD5lx1MDAwNEGjWUDwRJexkXCgVUCv3qZcdTAwMTOiYvxW5lAghZWxeW1cXKfkxtiUJ1x1MDAwMfpDVY5mssCaqydJlFPv6aiETm+2x1x1MDAxNTfhSn5GJjeguXVx+HJ5Vjhw60ebp1x1MDAxN9u6eqzPnqe0XHUwMDFiSN3tijzRRkJwXHUwMDA17zVwz+FcdTAwMWPdXG4om2KJnnWi2YhLlbOVz1x1MDAxNTf2hD2cXHUwMDE1rSDnXHUwMDAzXHUwMDFkv5PVSChxmMFq2FO68IO8Po7Qq+TzS5HOS4pOQs9PRmyuhqOQKKre1aiU/lx1MDAxMyxHei3YNMthXGKEXHUwMDBlz1xmXHUwMDA3jdisIMWVrZJcdTAwMDaKXHUwMDEzo6OZe4w5KFx1MDAxN1x1MDAwNGxNXpQ9XHUwMDFlXHUwMDEzMkIspFGIbilcYiDYXHUwMDFjyblo0jcyXHUwMDFkm1x1MDAxOeKAQTGrXHUwMDAzcXHAMcdq+shC2JM3P1Y4af73cFxuiVx1MDAwMuldjZHF6VxyRFx1MDAxMptKP/LvY2wqjIfyWOGbwfFANFMv59BwptfQTDOcXHUwMDFhuZhccn+z5eRcYoWxaDu8YuuOXGK7X8pcclx1MDAxOFx1MDAxMa2ihXKqXHUwMDE46lwiNSijwCiLXHRyIY7dbuXcxnba80jEYvs7yXBuT284XHUwMDExXHUwMDFmW1x1MDAwM1x1MDAxMLv5nVxmrHCmOMOpmMne99dHUieLo/d4RFx1MDAxMD9vNWdcdTAwMTBKnM1cdTAwMWX9Vlx1MDAxMC89XHUwMDFhMc1SKVwiU1x1MDAwZcdAiFx1MDAwN4JcYips4mgoXHUwMDAzeWSojCM5s2XupeE26DTeUKG5XHUwMDAzyoRWqFqC6Vx1MDAwNTtMslQ7XHUwMDE5LFx1MDAxNTFEXGJcdTAwMTmbX1xuJFx1MDAwMvz84pj4kFx1MDAxNCC/adZHIVkkvcsx0vh5czWL01x1MDAxNfNcdTAwMDd5M1nY14iW0V96tetsenm421RrZZNMmEBSgaz890KA6dHYqbu7UjpcYu28SrTaXHUwMDA0z7F5RYDUwUtWXGKptPWpokdcdTAwMGWgXHUwMDE0a4Z+lYNGXHUwMDE1x1x1MDAxN5xcdTAwMTAuY5SR9qBTZY/IXtjVJLu6m2F7V9pVZUhcYpdJrnxDXHUwMDEx61x1MDAxM2aPt5yBYZ2D/d1kibSfQlRcdTAwMTg/b1ZnZLBcYpNApFeYzOixcJnwVVx1MDAxM1x1MDAxOcNcdTAwMWOkxP3uvPqsdCbg4Gylen3SfKhXXHUwMDFlz39cdTAwMWScvUStanJ5W+lwavNdgVxigLHAXHUwMDE5zsBcdTAwMTGM2NPDXGLYglx1MDAwM1x1MDAxMctcbsi+KVx1MDAxMlx1MDAxNkWEttluMYaVKsfYwDBAeGWDXHUwMDFhM1x1MDAxY7VcdTAwMWFrM79rLfdcdTAwMWJyOb1d5UZcImJlJra6XHUwMDExXHJcdTAwMTSwjYQhXCLx1kLCl6eTpMj0odxs883DXfLyfFC63ylcdTAwMWT1e49TXHUwMDE156KUolx1MDAwZSvQiuAwXHUwMDExXHUwMDE0hFx1MDAxOVx1MDAxOFx1MDAxYVtHeWdcdTAwMTLYXHUwMDE1XHUwMDA2Q2Kq49mzlW3YXHUwMDFmol1cckGkMVx1MDAxMme1KM6VJL/1LGG00mLZuFx1MDAxNXVtXHUwMDEy6Vx1MDAxNlBg6DbFXHUwMDFjXHUwMDE25yqWVpcq9p6larddbnZ+dkrF8W+2bFJTp9xcbn2dR7rUjKpf5jCmfDKnXGZpbm1dXHUwMDBmfvXPa/fd44vtl6Z4gGlcZoLN1LZ1OIywXHUwMDAxXHUwMDBlJlx1MDAxY2Y/KmzLiJdcdTAwMWbJosRBwGulXHUwMDFkrpGSKS5cdTAwMTfF+rLYg0ZcdTAwMDZ7YJhBXHUwMDA0XHUwMDExXHUwMDFmXHUwMDA3ynXiWrGHkdlcdTAwMDfPXHUwMDBmn6lBWD/cKM6xboe7l4+a7lZa5cpg82b7onL1eFcv6MrBVUy9nFx1MDAxOL/tR9VQXHUwMDAzXFyIXHUwMDA0RVx1MDAwNcmNlzBcdTAwMTN13Fx1MDAwNFx1MDAxY7Cng1x1MDAxYm+H3cR57oWmJmpqllx1MDAxYdRcdTAwMTZcdTAwMWFcdTAwMTlccrFcdTAwMDVyZDSKxkeejFx1MDAwYjs1c6epJ3ZcdTAwMWUrbvMhmHE8d1xuXHUwMDFi28ucXHUwMDBlXHUwMDA0vT0o7Jw97YrCY6l+L3dcdTAwMTivXHUwMDE0N6J6m8AhXHLRjrEn+FwiIbF+NKS6o/NAcaao3fGKOVx1MDAwZnRUXHUwMDBihWguXHUwMDE0j8u9mPVZYN/hhJRcdTAwMWKa4bxfJrVdkolcdTAwMWX75XVFJfJHe667srvxXHUwMDFm0eK3XHUwMDBisbU6NrZ3bju1lcu14+vm1vUjOT+UVb9wbEhcdTAwMGW/9ISU9H6m+DhcdTAwMTRvXHUwMDA3XHRcdTAwMGZw1Fx1MDAxM2NcdTAwMGL/hPWEXHUwMDBix1x1MDAwNjhcdTAwMThbO5CK4DFcdTAwMWLveqJcdTAwMTZVXHUwMDFmP6FcdTAwMWLn0+uGXHUwMDAxZcNcdTAwMWVlZHF6Ob1MXHUwMDEwTlx1MDAxYlx1MDAxMEQgM8lJ+vRcdTAwMTEpPztNS9Vq5Yqbh5f79GmY6T4n5rSUpZj+5+P/XHUwMDFlaiedo6fHw1bhrrzz3KtcXJfPiyeZ/Fx1MDAxZqNSXG5qfZfSY9hcdTAwMTXVnlx1MDAwMOFGSiOIXHKjjTvm3lx1MDAxZXIrUepcdTAwMTRIyoMxxz54lcRRjNlcdTAwMTRcdTAwMDdGSDBbYaHpYU2/yIBl0Vx1MDAxNiOxMFx1MDAxMMkztC6SJFx1MDAxN3tEsmqPdfzYYUhpbnBzbadQ7+5Rt1A7unIrVd1cdTAwMTBcdTAwMDVcdTAwMTPvXHUwMDA2M5XCOrr/Je5uh8f99v7m1uauW6qyJzmH7jW9n2nuXHUwMDE1jENcdTAwMTQh9uBcdTAwMDV7SlVcdTAwMTiGauIwbrNcXEBcdTAwMWGjILrwq6mjJ1x1MDAxYzPNXHUwMDE3zjVR5TIgT1x1MDAxMIYjXHUwMDAy4rHeNaqIvsrZwzKk/tCGcKhcdTAwMWazZZA/O+1u9b5cdTAwMTXvY1x1MDAwM5nnf4ePneDXUlx1MDAxOObS+CDycbTp1i21Yoo9tkghtqLEXHUwMDFlXHUwMDBmKGDs1Fx1MDAwNiC2XCIn2mUuJFM05iR5wbVcclx1MDAxM7FFKFx1MDAwNFx1MDAwZorRSMGZxJ/QNqLLxt4gzcy5ojKyTPvJVdm/ILufZtimtCVS7SuNi1x1MDAwMFx1MDAxNjKygjTa5/GssJjJWYOBPae5SO6PSt2kx5MkOf/WqHSEMdowZZNkkd5Eyz/NQyWu8YR4qUKBczYjXlx1MDAwMlVeqI1cdTAwMTEmXHUwMDFhS5MxXHUwMDBlJd2ufmZcYoZQLkBcdTAwMDD4SYXvI2A298FcIlx1MDAxNMGViqbS/O1J/Ukw9s1OhNKMX/s0NuQxPUiV3ZD0vo5cItJamiBPajxcdTAwMDXuRupcdTAwMTWEXHLDWMGCSfh2cEsutsrlo9OXe1edNjZpoSdcdTAwMDdRXHUwMDBmmFx1MDAxNq5cdTAwMDPcXHUwMDAyITBcXGkxXHUwMDE23yCUXHUwMDAzzNZTQSaqKYkyzTlcdNf5XHUwMDFly61XXHUwMDE5QC+1oas0elCRXHUwMDA3emky0SRcbmVZqC+Pd0hcdTAwMTHpXHUwMDE3/VLq9s5cdTAwMWFcdTAwMGZ8d4dcZpvq7rh2dPdcdTAwMDGRXHUwMDE2ilj9XHUwMDFji0BDYmYrRVx1MDAxYeWleFGIXHUwMDAyuzmR6W9RTZ2WM8i04XZeoqfOvrK15Fx1MDAxMDRCXGYxTMCXXHUwMDE33HhcdTAwMTXqP96s/XK51ztcdTAwMWVikyPPv/zQdFx1MDAxZleSgfxcdTAwMWZvKmHn2vXKXHUwMDBl/PXHX/9cdTAwMDPhIXiWIn0=ADCinterfaceSGPIORX DSP chainTX DSP chainADCDACMCUSPISPI controlregistersSGPIO andflow controlADC clock domainDAC clock domainInternal clock domainFPGATransceiverDACinterfaceTransceivermodule \ No newline at end of file diff --git a/docs/images/gateware-ext-prec-rx-dsp-chain.png b/docs/images/gateware-ext-prec-rx-dsp-chain.png new file mode 100644 index 0000000000000000000000000000000000000000..6dc4833047e0d36ad14078439d60bc4cde95db25 GIT binary patch literal 70790 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 IWBcI$1SF;TBme*a literal 0 HcmV?d00001 diff --git a/docs/images/gateware-ext-prec-rx-dsp-chain.svg b/docs/images/gateware-ext-prec-rx-dsp-chain.svg new file mode 100644 index 00000000..af05bf82 --- /dev/null +++ b/docs/images/gateware-ext-prec-rx-dsp-chain.svg @@ -0,0 +1,4 @@ + + +eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO1cXGtX2tpcdTAwMTb93l/h8H6tOfv96DdcdTAwMTRbrbVS0YLee8ZcdTAwMTlcdTAwMDFcdTAwMDJEIGBcYr7O6H+/K1x1MDAxMUnIi6Dx0XOkY3RAnjt7rznnmnuv+PeHjY1N73ZibX7a2LRu2ubQ7rjm9eZHf/uV5U7tsVx1MDAwM7tI8Hs6nrnt4Mi+502mn/74IzzDaI9H92dZQ2tkOd5cdTAwMTSO+y/83tj4O/hcdTAwMWb22Fx1MDAxZP/cXHUwMDAxXHUwMDFi1UjnR52cWiNcdTAwMTfzztGX47NqcGpw0ENjXFyr7ZlOb2iFu25gO1XIUIJhJTinVCC92HtcdTAwMGJ7XHUwMDA1XHUwMDE2hmSUK0RcdTAwMTknSMvF3mu74/X9I6Q2JMaUI6mJxpoujuhbdq/vwSGYcINIjCjVcFx1MDAxNVxuX1x1MDAxNsfcN+jTXHUwMDA2WmyZeu54YO2Mh2PXb/V/sOX/XHUwMDBi29wy24OeO545nfBcdTAwMTiTd1S3XHUwMDFiXHUwMDFl07WHw7p3XHUwMDFiXFxcdTAwMTk6XHUwMDE5OnQzdv3GvPUktj3rLLhhr+9Y0+lSW8dcdTAwMTOzbXt+P2FcdTAwMTRu9Vs32e9cdTAwMDTj9WfYJtdcdTAwMWNZ+/6AObPhcLHZdjqWP1xmmy28fDunM7/d0uFTy/IvgSXCkispwvaHscVcdTAwMTCOb/0+doI4w0RKIbnkLGzAtFxuXHUwMDAx5lx1MDAwNZftmsOpXHUwMDE19rTfiN1I8IVcdTAwMGYzm3RMb95cdTAwMTKFkIBBZUiEXHUwMDE3XHUwMDFk2s4g3vThuD1cYu9cdTAwMTJs/fUxLZ57s9aoWzl1XHUwMDFiqGI3XHUwMDFid1edm+Z1L1x1MDAxOc+edeNlhTLTXHUwMDFjIyaWQlx1MDAxOWLYkJxzLVx1MDAxNYFwXHUwMDE2XCJcdTAwMTHKmDCDUfhAwCOuuGbJWCa83Nj1XFzTmU5MXHUwMDE3+vh3j9/RXHUwMDFh8UuEkppTiVLiVyiaXHUwMDE1v5Ip4Fx1MDAxOVx1MDAxZVx0+1dcbt8wXHUwMDFh/SiExz9ublTrtY1237SdyECOXHUwMDFkr27f+U0naGnrZ3NkXHUwMDBmXHUwMDAzhl26VGVo9/w+2Fx1MDAxY1rdSEBAN3g2KMNitzeehHvbcD24reUmh2fs2j3bMYcnuc00Z9742JreN9RzZ1a0J6y9XHUwMDA1j1x1MDAxYoTn4PZscHg7Q9VcdTAwMTG9uFx1MDAxZTc+XHUwMDFm1Vpm87BZWIc0Jlx1MDAwNlwimkqCKVxmXHUwMDA2XHUwMDBmh9jvJSmlIbVcdTAwMTZUXHUwMDEzXHUwMDA0YYPDvVx1MDAwZuBV2Fx1MDAxMIJcYo65XHUwMDEyRFx1MDAwYlx1MDAxZPbrXHUwMDAyu1x1MDAxNFx1MDAxOVxiXHUwMDAxNSDKXHUwMDE5QJxHWHA1lpVQllx1MDAxNvk61FxyPr87jq/Tcfww2uFQ0vmWX3F4c4A2YErJaFx1MDAwMD+gm2SiXHUwMDFiXHUwMDEzXCKVxlH8r1x1MDAwMe9F88KGZqlFJGhcdTAwMWLt4/rB972qvVe56Fx1MDAxZrpH9i69+2tzcdyvj+mXvT+ZnDZPyOi0zr7efLeOr26mXYYry3d5uL/puuPryHXn37I4iVx0TVx1MDAxNWZcdTAwMTF+fJKkpj9lXHUwMDAxSdVEXHUwMDFhWjNEIcOD9FxysWVUKmIoRDBmVFx1MDAxMa50XHUwMDAylFxmckNfUKmfqzDBVJqiondcdTAwMTSmoPCmuJpcbn9kqMA6XHUwMDA1bkwlti7ghlx1MDAxMFChZlx1MDAxYT9cdTAwMDZuZUZuQk13XHUwMDFks1x1MDAxNVx1MDAxNYiIjmKxtHWVjrahvZabo6Qju9OJ3mpZTFeJWlxcX+Ncci9HWe2rs7Z73WPfKLOP7trbtdu2OCmsrEoxcGhaXHRcZiktwTrm8LgwYKNQioA3k1wiXGaGRVpMOXBA5Fx1MDAxM9L6XHUwMDAyxFx1MDAwMHRcdTAwMTY9RIXDUY7F+2eA+naNXHUwMDE0WSsmMWRDaahcdTAwMDanknB+XHUwMDBmsOaQ43Ck9Fx1MDAwYopos950K4NWt1t1rratXHUwMDFmg8Fs0Jq8gIjmXrd+cHgzkzY7bc+8Kq3v3V5cdTAwMWXJy1x1MDAxMq77rXV8e3nuNr80rquN8eR0cnP4xStL9Fx1MDAxOVwiiNEoSTxe9NNHpYjoY5xHXHUwMDE4Qlx1MDAxOdDSXHUwMDFjwlBhbP6TfHP4oOWSwl1xUoBUXHUwMDBiLDBcdTAwMDbrnEZcbogkNi+0nvpcdTAwMTTPXHUwMDExXHS5u1x1MDAxY61nXGJcdTAwMTH2JOdcXN3ZaPmHlOGan6r2K4Q2rvbJppej907vroKtXHUwMDFkfjGhSDly9HnQ/bZXWO+Fkr6iz+FLYjn7g95rVKbeh4e8y/1cdTAwMDLZXHUwMDA0rYFs5HtmjlGaZ4ZdmcDmgGtcdEP5cmo/aX5v91x1MDAxYs27Rnt/n8krp7ZdZWdF1bN71G25jVx1MDAwYqfDL6fyYLfROoFcdTAwMTF6XbVfrcpUc0jEylHl9N4roMqSXCJcdTAwMDODXHUwMDEx19yfsNRcdTAwMTIvw3quytmw5sggK734u0pnYVx1MDAxOa+RumPEgXlcdTAwMTlPrMNsXHUwMDA2M5mZWNbUXHUwMDFmXypcdTAwMWWVuj+rIT+0b6K6+npcbr1CXHUwMDFh41xuXHUwMDFka3c58jz7flBxZ5XmUbd/dT447rZofeBcdTAwMTSWZ0ZQJLsmkcXQYnacIG6g6CdMz7Pt+Ls8p0CarDHFxqnyeTfVjDOWWMZ6gDSBMSScs/C8Z5fnqz103t/+2mh1f17QqkNqfFTfem15lmdnPycnP05ml1x1MDAwN9Ci3Z81+vlgtzzTrJSQUSg/Xp7Te6+APDOq82C90jRjkZJmv+txJnjpOqvNjFx1MDAxMK0pTdNjTJKL0OGCXHUwMDE0435dXHUwMDBiKts1P12Qq1bbXHUwMDFlmVx1MDAxZTR2Y+qZPWv6XHUwMDE2xHmFMCbsc/YzlCPU+VOLMcZZQrPmxFBcXHJNsUIkOt9yv1x1MDAxYY2XVqOTaIZUXHUwMDFkXHUwMDEzJVx1MDAxMCQpWlxiIWlEglx1MDAxN+hcdTAwMTbIgOCCfF5z0OiIRrzZdbCOOe1bL6zSbFx1MDAxZKBcdTAwMDOsqNJpOGfJrYtcdTAwMTlzzZRmUXEvcW6MRyO3KMonYzueXHUwMDAzhN82wq5cdTAwMGV+LL7/+TH16K2cYFxm9sfjMLxgQntcdTAwMDGnrrdccqNjO73NpZqAeZVikVUzOHo07lx1MDAwNFx1MDAwMTV2W3Y0v4AgvbE6Nf/xl55cdTAwMWVcdTAwMWXT4CgsbIs9+PxbWIhgOZ3Vrcyf7SuplXg5WYeQyGl20L1cdTAwMTWfjvqWmVx1MDAwMFx1MDAwNTxUdFx1MDAxZqi5XHUwMDFk81x1MDAxN9awNb5OiaegvXWr91x1MDAxMLXL4PFvuj+tT4COzWHKTTP3jcZX1qF931x1MDAxMdOG7fXnwCiQZ+1/nX3bObn2zveG28dfL88vqtK9TFJzhoeSSFx1MDAxOJhLTSSFeCZ6udLPL1x1MDAxNlx1MDAwMlx1MDAwMHKNKGVcZstcdTAwMTCCXHUwMDBm9KyZoZHiXHUwMDE4ICE5XHUwMDExJLVY6O3T8St4Jv7k4iDFKVFKpk50YsQyZ0eIX/cnMX1BK3Xa3MV1tFO7MpuXuq/GX4Zd77So5dlcdTAwMTlhd3+G735sfz2vkcb0wu10XHUwMDBm3mJxUPpTXHUwMDE2sDwwXHUwMDE4hoJcZlx1MDAxOVx1MDAwYoxcdTAwMTRcZkysZC8oXHUwMDBlykOh1Fx1MDAwNvcnJFx0mFwiiFx1MDAwN5RSOv5eXHUwMDFjlIpCUTwnooQz8KXpcCNUZcFccmNIXHUwMDE4YGRKXzF8uvep9c2pXHUwMDA1lsGKrGa/XoXQXG4li5uetMaX43byXHQnz+1ITlxySUBcdTAwMGKl0r5PTrqdfCBDjoM51YJpKZAmNGKI4maHaUjPpcJ8nZmNf5HbkcWRzVx1MDAwNEHCdzwpyFY5NfSKXHUwMDBiTVx1MDAwNH47VX+lup3sWPQ/W4kwTGTja5udfFx1MDAwMnhps5NM7f9cdTAwMTV+Yq/RPN5pnHi1o2mjentTV2fbzXHxNVx1MDAxOaZcciRcdTAwMTBTWEmCo4XroZ/QnFx1MDAwNS9cdTAwMGZA8pokQMZccq6IYEiAq1x1MDAxMJHpolx1MDAwNf/x90wmje/Uk/1cdTAwMDRcdTAwMTZcblx1MDAxMc2oTJv10dlLM5hcYimYovxcdTAwMDVLJyr7jf3rn6je2Fx1MDAxN5O9mTPtXHUwMDFkkT1eeFxypfZcdTAwMDVXd2rNu8pgq+38PK//dXzlvEVDkf6UXHUwMDA1XGZcdTAwMDVcdTAwMTNcdTAwMDKA5s+4alx0Y0NTXzfIxSFcdTAwMDZ6XHUwMDBmXHUwMDE2PJlkmKTlIexcdTAwMWSHaTjUa8yySjB8XHUwMDFhYiZ1OVx1MDAwNdHsXHUwMDE3XHUwMDBlqNBAkoi/ndTjwVJ8Ntve2J1++p9cdTAwMDPuXHUwMDAxPNPHXHLBPlx1MDAwMkWot+AwVmhb3GFcdTAwMTR4lnJcZkc+IeVcdTAwMTlcdTAwMGVOsKFcdTAwMTnnXGa0UlxuLmI4XHUwMDBmXGZHiPPkm7rI8F82p0RcdTAwMTDwI5gqnlJx7Gd6imnIXHUwMDA2NXhcdTAwMWKy1kvn/1wiw1FZXHUwMDAz+FpcYlxuakvTqo+5znRcdTAwMWMwxkpcdTAwMTCFy15feSOOIztcdTAwMTj9z1ZcIlx1MDAwZVx1MDAxM5n82o4jn1x1MDAxMN5cdTAwMWTHiziO/FKZPPZcdTAwMTNcbudcdTAwMTVoK2RoycBLICA/zpKvOoNZSTFcdTAwMTjofqFcdIPrlVxc+G/RXHUwMDAyWOU6rzhcdTAwMTer/Grrtv7ds53tNUiPXHUwMDAyov0107Rkh2TnOkQyf4qBPWb6dKlcdTAwMWQp1ch+Pcur095WNFxmg1xyXHUwMDE5XHUwMDEx+HS+yy/6fFx1MDAxY98tPWtAfkX5LquV+dUvj2RlXHUwMDFk+6zV7JLJOIdcZvPL7/PIUEmV97LZnFxmqWJ+NqiSlTaxUlfOVlIj4lxmnD9cdTAwMDTnOzemceNOcW6UfsVcYqMsjVx1MDAxYiPKk1hZ4lx1MDAwNJJ6Rlx1MDAxZjPxkk+Nb6XiJjsog/MzwvHpRPlcdTAwMWNcdTAwMTUt5Vx1MDAxM+Uz0HmyyuY1ibKM9DL/NeM8RsWIiGgpclx1MDAwNqFmXHUwMDE1XCJLf1Ffcq7nPZnGp+/EmUKcu8WJU1x1MDAwMN6ha5OvXHUwMDAy+YKY89fbuO9cbtSzXHUwMDEwp4j+yaXXXCLOzNiLnf2G+PGJzLOGk07jnWVmWmatwslb/stcdTAwMTl5VMMwy3vpYTXXMFx1MDAwM8KOMTzvupRXXHUwMDEy37kmjWs+r2FgfTj5r0CkOlic/SdcdTAwMDNcdTAwMDQlkj+HgWWYM1x1MDAxYy7evFqWllx1MDAxOX2x01x1MDAxZss2z2FcYp+LXFzKcIZcdTAwMWbmfbRpTiZ1XHUwMDBmxnzRN5tXtnW9nT2J/mHealx1MDAxZo1WsP7768Ov/1x1MDAwM1x1MDAxNahInyJ9RX DSP chainEnableDC blockMixerDecimation stagesPhase stepFactors:16, 32, 64, 128 \ No newline at end of file diff --git a/docs/images/gateware-ext-prec-tx-dsp-chain.png b/docs/images/gateware-ext-prec-tx-dsp-chain.png new file mode 100644 index 0000000000000000000000000000000000000000..d0a971902e8a42668aa4f1a0fa997d104a26b6e3 GIT binary patch literal 51198 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/yxjrxXGaLwVAwSyolW42tIEtGkiFL8e9zWzZabNlcdTAwMTiGQCZcdTAwMTNRRcm93r59zrm3W1/XXHUwMDFhjWb6eWSab1x1MDAxYk3zqedcdTAwMDa+XHUwMDE3u7fNdVt+Y+LEj0KoXCLZ7yRcdTAwMWHHvazlIE1Hyds3b4pcdTAwMWVOL1x1MDAxYU56mcBcZk2YJtDuL/jdaHzN/kON79m+p8zEvJNcdTAwMWOP37VGZ6fB2a3Z+bibdc1cdTAwMWHdXHUwMDFiXHUwMDEzm17qhv3AXHUwMDE0VZ+gnFHqaMFcdTAwMTjHSHHKXHUwMDE5y2s/Q60m2sFcdTAwMTRrLrDgnGic1976XjqAXHUwMDE2QmpHYkw5ktBcdTAwMThrmrdcdTAwMThcdTAwMTi/P0ihXHQm3CFcdTAwMTIjSjVlnMJL3mZi0NtcdTAwMDbKS5I0jq7Mdlx1MDAxNESxtfpcdTAwMTds7F9hc9ftXfXjaFx1MDAxY3pFm8vLnu7pos2lXHUwMDFmXHUwMDA0nfRzNjI4XHUwMDE5XHUwMDFj2pxcdTAwMTn/fGo9mSlf1Fx1MDAwYibsXHUwMDBmQpMkXHUwMDE1W6OR2/NT6yeMilJr3ajlZfv1vrApdoemZTcsXHUwMDFjXHUwMDA3QV7sh56x29Ds4s3KdKE3na7SPDHGXHUwMDBlgaVcdTAwMTaKXHStZV5TYItcdTAwMTEyW3pcdTAwMTiFXHUwMDE5zjChkjKCS/38ZFx1MDAwN1x1MDAwMJZmw166QWJcbk9bI3ZL4CtcdTAwMTYzXHUwMDFleW46tURqhYTmXHUwMDFjoWLQwFx1MDAwZq9mTVx1MDAwZqLeVTFLVnq3Xofnrcs+v1x0qdy49kLe0ofph/Pj7sp4tnhcdTAwMDSEcSVcdTAwMDRRiGNRxbOQXHUwMDBl4JAjzlx1MDAxNEWU6Tk8XHUwMDEzxFx1MDAxZFR+9DygmXaYLj3q2fFsn/86nvdcdTAwMWWBZ4awJKRcdTAwMWXPXHUwMDE49nEhoCVTXHUwMDE20SXZeVx1MDAwNKCnXHUwMDE1XHUwMDA1XHUwMDAyK1x1MDAwMEvNpzRfQlx0n2r3ZGe/e8A628Ptsf6yd9GSO2Ezb3e3Xj/spPPg3UmqWu3u79t70YfBvt44P9w/r85yP79cdTAwMWLH0e2q435s6+OtUXRxe33UPVx1MDAxZW7GbX1w/G61cadvL8Tueu/Nsbvi/Fx0sTV2iCU2RCpcdTAwMDJokVViXHUwMDAz7YlaRmyskKMsoSmoguRSzfOa8Oclclx1MDAxYbthMnJjwNtLkVx1MDAxOX8jMv/6XGIyXHUwMDBixJGGXHUwMDEwVUtmTOaK78lMXHUwMDEwg1RcdTAwMDNpwZ9C5ufEb1x1MDAwMUdcdTAwMGJDcEArTE08ilx1MDAwMjdcdTAwMDV7XHUwMDFiSer2TVLa0ihMO/6XyVx1MDAxYSqle+7QXHUwMDBm7Fx1MDAxZYjKkJuB37feaPaMXHUwMDFkuFn2SOpDXG6YN1x1MDAxOPqeV1x1MDAwZXE9XHUwMDE41PVDXHUwMDEzt1aJlVHs9/3QXHJOV1qGO06jXHUwMDEzk0xcdTAwMTaSxmNT9ph5l6dzXHUwMDBl4UtcYv6ZXGbD06M/bvg1XHUwMDFhjLzNXHUwMDEzwlx1MDAwZY9OVyF4KVx1MDAxMyVcdTAwMTJpVcDfOlBp6mBGtaRcdTAwMDJcdTAwMTjORVGbXHUwMDEznFCHllx0XnDhR2L4t1xu1789guFEMK0gXHUwMDA15WXgTlx1MDAxOS5L6f1stFx1MDAwNiaCRENa9t1cdTAwMTH89KKx02k3elx1MDAwMyDXc1x1MDAxMDswl+lcdTAwMTJap9FoXHUwMDExpytWz1x1MDAxMrjezOchbnt89Sc6iL4kvyc4XHUwMDE4dM8vTkQsV867JVKOwoRcYiFcdTAwMTjSxVx1MDAwNk/gqSA6cySYkJRcYlWKvTl5XHUwMDE5d7hcdTAwMDJcXCFAlcXJPHd5sVx1MDAwM1x1MDAwZnNXXHRltPg/pNnH9bwtcsT7naPTkrvC+Hs6w2FJg/d1XHUwMDE5sFM6g9YuojOnQlx1MDAwMp/Jk9j8tNw7PPvY9sjw7GDbhF2yMVx1MDAxNPu7x19WzZHjLd7ekPuD8Ijs6tPt3vl1lOx9jzly/SpXXGKhklxih8OWKCmZYJKRXHUwMDE5XHUwMDFhavZcdTAwMTBccjFyUHakhd6Y4JpcdTAwMTDKftKwjoYnq4dPgimmXGLcX8c3jcRcIr5cdFwiJIYkmTyFb/XQhVx1MDAwM5FcdTAwMDBcdTAwMDJDykRcdTAwMWVcdTAwMDHduei55/bSKE7e/lx1MDAxZGKx3qBkvSHYutWV2lBaupN5iVx1MDAxY/mBuDZcdTAwMWJiV1jL88Tb5XI0I0VVmivsXGJtOcwg2ipZ4GhcdTAwMWFt6Vx1MDAwMzRHjr2shUrCsMSIlSCV81xcgFx1MDAxMiimXHUwMDEx5lpcdTAwMTJKXHUwMDFldWn7SrT33GRgXpj3nUfwXnFifVl3LubzpXnWrCiVXHUwMDEyjjWvfmmbXHUwMDE3j1wifzaMXHUwMDE3b43C19mP/P39en3rhWC0z8ZcdTAwMWNcdTAwMGWL8eaiMpxo43RcdTAwMGJ2x1x1MDAwZvvVXHUwMDFjaPpcdTAwMTFlXHUwMDE1RYDWw8jLXHUwMDAwXHUwMDE1xV2/nIdcdTAwMDBIP1x1MDAxOa9tV19ZvF1cdTAwMDT4XHUwMDEyL1j3XFziZUKvsLJcblx1MDAxNbuCTUv5gXHncFx1MDAwN/3KdXD89GdScVx1MDAxM3Sj25pcdTAwMWTLXGbvmP49LuYnbSWdken5blAz6cK6YXRjXHUwMDBl/IlHknM/XHUwMDFkTKG3QpKz/CZ0mfyBrFWu+GduXHUwMDAyNXZAIC2WtMKKXHUwMDE1upVf8UvhXGJE4PyqkKZKXHUwMDE1/XPxQ1x1MDAwZSWMXHTFYFx1MDAxY8GZZj8/WdWJ3+nq4lx1MDAwNykl4japrFx1MDAxMT86f/LIxY9Km6Dw0oXuMyQ9TGjYUy6LjOO1xG9jIVx1MDAxOLPaeVx1MDAxY/579Vt+Z/g09ausOZPC51G/OoWramBVqqrqt0R9ln8vWaY+XHUwMDE4c+5cdTAwMTBFJLdwXHUwMDA2LapRXHUwMDFmxfjkO0RxNM7FR3BcdTAwMDdLjWG/IXmDo0Dxwb1Qn59iUyM2Z4/ItFx1MDAxMFdYXHUwMDEwKetOWISw2dJ7tbE5NaGodOz9wcRmIfhm+j+kLbNcdMKrqFx1MDAwZa5+qEeokjg+KEPfRGzWpk5ruqNRJ1x1MDAwNVx1MDAxNOQuad745nZr8UFobWqbZafJbvDu1u7+XHUwMDAxkVx1MDAxMOB/In0=Interpolation stagesTX DSP chainFactors:16, 32, 64, 128 \ No newline at end of file diff --git a/docs/images/gateware-halfprec-dsp-chain.png b/docs/images/gateware-halfprec-dsp-chain.png new file mode 100644 index 0000000000000000000000000000000000000000..a0b6c5ed1feaf3eb37319391ca81f6e431238458 GIT binary patch literal 79385 zcmeFZc|4T;|2ACqB_vWLq%4&s*^2BTB&4z%k}>vu4^2X)QfTaZ_HD|(Q%Pd%41*Eb zx3Q0HW}eUVyT7mB{kvbT=lTD+uRpH2RCAur^Rv9)@8ftM$LE#)JxwMCE{0>rjxlN7 zxqbiGF&dF$$0)PuXu#hPq21lbj`1DSx~=lS&vJR3wtDdP6mi`^Bv07K!iYMy!rH{- z>dvo%YMJF~hMfxE)~|X-&6eo!lGo>3Ytvu8X7IVK&U#wC75jmopYG7Vj5LO7N8J=^ z*Ydb7G~v&~yN!KveXp}-E>+$Y3QfJ~8JWTN>=*^zKYe(!$44}0zS}qFI!<*``Pk7P z+{Y;xE$RO89&~*AzQ-vdYkiM1{nH)Dw+8p1{P!OJJ<9)%$NyY#|BlBI;T}hd zKH5%w7_qLFJuw1{{<%qEGG3n3IJ(ugc9knkLHS@WRM-pxB`PL?6%)Kqa!e>Mv z3gzU`ABbzP;|V!*m$d#$Rkl53mXzXyX%{K)QLS;2e5-a;IBV7bf#_Ty3O&mxUf(nJ zbQAR%cRO@cA#g`3gs=qZ=%QJJ{7DaGzP@idaNVl;nCJdNu53!>uPcS|c4bd;6EwPD2 zz~wwFd}OO<5CTKqav5=NJD;L_=ZF904UF42CRCIXab9YHC1f|$e{UwvX2i~2&oJk% z#5vdc&*0CHL@{)gE5x(;IPDX6{}T97(Ofx$icW+pz0UFcun+x^nX7_lzpm`f(4Rz) zi6Hzfz6u*FN2-K<=b*U?^0gEWQk$wBZQQ1h}59ALTKl)ut zMr!7n)G^XRZdzih3rnpxN~(IPr0#Achp2XAu@K64*qU~ey!wJHC|C6q_db=CKd87K zwC`1Ruv#aZB$1x&Q+~^EEc$`*A4{d>{!LQ~ZAr=05aM2QPKUS%GHoWP?C?du732Y~UD&IaW zp#(O)TN2Bnp4>+#)EDf0NILqDbKed_cM=6MN;W9;hN_x~T`k2FivxjDIc?4{)+o*nmQVG^fw4 z9J2$4dd@>l+fp-_BQv(t>tk?r%B?5EDhKIigKX1@Hz!vw|K{0j7fL(pJiRQ=Rjoie z+|+4&+9}Z%yR0**GzVV6rE>X$j9BAj_&Ep5oIFGzubfw2nSZtK(92Pum5R^pf=N`3 za?cTteLrRh``e5aknab$CfD-hp{yvy#eq_jD~?5{VZI7j_tjF}7{t8EQ^ufR~rSp#!anIRK z2~BSI7rjvy7SY?urm~P@8*|idHk%}*Grp-wIIW5vWJmAA0e#uHd{bEUjLQ>I~RU5knXBbya;up@x(CCoQQi^K@&$^2=Hl9hyZ zy2)5Ug7;=9P}_ zts}OutnzvIaby_ueYQ+0x@P7zMvNBKwcefB+bB`nh~SNhS?qN;z?`i8%>DAHmwuK_ zLB)aaNv;~vI)TA~!4r@?@zv>8G1I4mofR{Fznu{~c^!?0z1bubRLH4`u+tUZqY`NI zeI@+T>UhHrSecHi)qmba=hUzNIHysjSwHifQS2Ith;K@2{Pgyx^b&u2^lhsQPBBxO zUuHZ3^A|SbnhvvPa~w!asMubOWgwD{NPSkioAT_ z$K6N@`UVc^LiL$0d7PIFgalGp3Tfz#0BLqd?p{aspx!SE8DGrH*dG*N>?Ck_3Ox#4W&29Oq6WB2;h!1 z#f=A|(oHzHl85*zs>VFK6=sXdx~}XcuIiq16?zy=Cn9(^{`ZN*z(~a0{vTe_*}8

    5c`^?!9B)kj6=8~j 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/hRd+CTs3DuVx1MDAwM8yUwzyEoftfLNmWsYItXHUwMDE5WYbAv3Lzv0a/XT9J73KIJWsoPIhAcnBWsohKkmvY37eH2rv491x1MDAxZrXaUvzY95b+qi15X5tu129F7sPSsrl+70VcdTAwMDM/XGagiYz+P1xih1FzdGcnjvuDv/78M3nCaYa97095Xa/nXHUwMDA18Vx1MDAwMO77b/h/rfbv0b/Q4rfMs6fMi/jJ4Gi4vdM/O+2ePXj1L1x1MDAxYqNHRzf96EzkNWM3uOl6SdNXuM4odbRgjGOkOOWMjVtcdTAwMWahVVx1MDAxM+1gijVcdTAwMTdYcE40XHUwMDFltz74rbhcdTAwMDN3XGKpXHUwMDFkiTHlSMLNWNPxXHUwMDFkXHUwMDFkz7/pxHBcdTAwMGIm3CFcdTAwMTIjSjVlnMJcdTAwMGbje7536K9cdTAwMWFcdTAwMWFfXHUwMDE5xFF4662H3TAyvf4v7Jk/SZ9cdTAwMWJu8/YmXG6HQSu5p91u6qZO7mn73e5J/Dh6M0wyTOhS5v3nz70nmetlT8FcdTAwMTfedFx1MDAwMm8wmOhr2HebfmzmXHSj5KrpXX+nNVqvfyV9ityet2NcdTAwMTYsXHUwMDE4drvjy37Q8swyLDXw6sTXXHUwMDA1reevm7h94HnmXHUwMDE1WGqhmNBajltcdTAwMTLZYoRlr+6HwUjOMMZSaiZZso7+oFx1MDAwZVx1MDAwMlx1MDAxNo9e23a7XHUwMDAzL5lp04mNlPAlg1x1MDAxOfZbbvzcXHUwMDEzqZVEmktcdTAwMTCfcXvXXHUwMDBmbrNd74bN2+RbRle/LVx1MDAxN8nzWvuG31x1MDAwN1Su3LVcdTAwMDK+o/fj6/OjxtTybORcdTAwMTEkjCshiEJcdTAwMWOLSXlcdTAwMTbSXHUwMDAxOeSIM0VcdTAwMTFlOifPXHUwMDA0cVx1MDAwN6U/Oi/QTDtMpz6qcnk2n19dnjdnkGeGsCSkWJ4xUaRMoFx1MDAxNVx1MDAxMrCKSuh55Pm5IVx1MDAxMcCUXHUwMDEwqo3j+m5jj52s99aH+mnzYkfWg/GAJlx1MDAwNDH2vsZL44Zvy7bXdraPY7Vz2Ph7fTO87uzqlfP93fPi17pRXHUwMDE0Pkz73i+H+mitXHUwMDFmXjzcXHUwMDFkNI56q9Gh3jvanu69zz/9JHDb53VyTidxrbFDXGauQVFcdTAwMTFcdTAwMTBcdTAwMTY5iWtAPVE2XFxjhVx1MDAxY2XwTIFcdTAwMTQklypcdTAwMGZrwqvFcVx1MDAxY7nBoO9GIG8/XHUwMDBiy/iVsLw1XHUwMDAzllx1MDAwNeJIg4YqxDImulxmy1xcaIWVlPNAuUrpTYTRXGIhXGZ/J4i9qFx1MDAxZnbdXHUwMDE4eltcdTAwMWLE7o03SC1oXHUwMDE4xCf+kzfSXHUwMDFkXHUwMDEzVzfdnt81KyAmXrna9W/MXFwsNT3z4qX0fMQ+2H/jXHUwMDFien6rldZvTXip61x1MDAwN160M42iXGYj/8ZcdTAwMGbc7ulUw3CHcXjsXHK+XHUwMDBmJI6GXnrGvO2xLedcdTAwMTBugfcj6Vx1MDAwNadcdTAwMDeX9/xcdTAwMGV1+q3VY8L2XHUwMDBmTqeBd8pcZiWwZinGN1x1MDAxM6g0dTCjWlJcdTAwMDH45lwiaVx1MDAxZMObUIem4Z0g4XfC92vp6k8z4JtcYqZcdTAwMTXYnzwtuM/4lih3dWx7XCIw/Vx1MDAwNVx1MDAxMjS5471cdTAwMDD89KJWPzmsNTtcdTAwMDCuKoDd9dqxXHUwMDA11nHYL8P0RK+zXHUwMDAwLu5mNcA9XHUwMDFj3l6hvfBp8PdcdTAwMDB3O43zi2NcdTAwMTHJqY1uWFx1MDAwMEdhQoRcdTAwMTBcZtZjXHUwMDAyu+BXgm7mSDAhKVx1MDAxMSqlecfgZdzhXG7kXG6BVGGResFcdTAwMTi7PFmBl7GrhPK0+CfY2EfFuE0sxFx1MDAxZitHn698Szr/XHUwMDAzzuApaZj9nF42vEtzSnxcZmdcdNa6UmQ+fW2zZYOzL4ct0jvbW/eCXHUwMDA2WemJ3Y2jp8VN72iNXHUwMDFmrsjdTnBANvTpevP8Llx1MDAxY2y+R1x1MDAxM9k+fotcdTAwMGWVoFx1MDAwM1x1MDAxOTcmMuNScK4zONTsJVx1MDAxY2Lxolx1MDAxMmVcdTAwMWZALFx1MDAwMuLx9FxulGCKKYL5L0RcXCrElkVcdTAwMWPhsG6a8/dnIW+6zTiMXHUwMDA2f/1PgJdhWWpsuaaWwVx1MDAxM1iuUVKoUFNhmZ9hKb+g3bKKdrrhVKN47bSUoaRJuCvsXGJtsMxA7abx/Kx26Vx1MDAwYnBHjlx02UIjYVhiXFzoXHUwMDEzXHUwMDBi5CDFNMJcXFx1MDAwM72QmUK3b4T+ljvoeD9cdTAwMTn+JzPAX3Fi5rLIPeYpds2gX1xiglx1MDAxOWbiNVwit3ou8PdDP6vNk59qyVSP/jP++V/LxXeXyqL5rOTEMHlfTjmDZ1x1MDAxYsVrsDh+cDNpXHUwMDBiPe+kTMNcdHB3L2yN5CmMXHUwMDFhfpxuaPtfvdahXHUwMDE5/cTgzSA4Qrhk3DlcdTAwMDPMXHUwMDBiWkkvJyXFjGDVIL7juTmxg+fSbeCG+lx1MDAxOZPc6zbCh4JcdTAwMTVcdTAwMWJ1/MS7+SFcdTAwMTf5L91cdTAwMTmc9L2m73ZcdTAwMGK+tLStXHUwMDE33nt7/vdcdTAwMTlcdTAwMTmc+3HnWfSmsHXs8VBcdTAwMWL7XHUwMDAxq9ni/Fx1MDAxYTvAj0aWTFAptas1jvNL4VxiRMCPVUhTpZLnx9yHXHUwMDFjSlx1MDAxOFx1MDAxM1xuYIdcdTAwMDVcdTAwMTeo+jD/77BtdTo99Wlccis1sfuUUFx1MDAxZqWlQX4wS5HkYDQlymdh7lNcYlx1MDAxNlYzmtaLb8V9K6WyOGrNieHi3GePXHUwMDFjzsd9XHUwMDEzQ1x1MDAxZVx1MDAxMWE13FfEb5NcZjhJVCXct1x1MDAwMEnZN1dsJFx1MDAwNYqMO1x1MDAwNJxkbsRcdTAwMWUoq4CkXHUwMDE04983LVx1MDAxMiU85ijBXHUwMDFk8LMxyFx1MDAwNTP6P0FIwlFcdTAwMWacVMBJZzOYY4grLFxiXHUwMDE4Q1x1MDAwNaRESGn8Q2IlXGJcdTAwMDVe+l05qUz2Mo+/REFZK+JNyFx0T27pIzQ5mpfY6lx1MDAxZHLS7Tq5XHUwMDE41Fl8NVx1MDAxY6qDcO3pcvUpKNhoKYnXgqZxXHUwMDE4xVx1MDAwNHxcdTAwMDBcdTAwMGVOXHUwMDAwy+y2YPBZJUNcdTAwMTgxijjIeI6YjOcpQEIwmF+gtnSB8UTBYkdMc2RyiihcdTAwMDeOe/+e41x1MDAxYjDV54VcdTAwMDO4RIF1ZPbEXHUwMDBi+Fx1MDAwYlxm5PJwXHUwMDEyo0A1Ku2IVlx1MDAxNMDtKD+6blx1MDAxY1x1MDAwN4/bW9dbu7c7X/Vnd23xXHUwMDAwrvs5OOycrq9tnZBe/bS+XHUwMDFl99TaVvFrZ1xu4Fx1MDAxYdrVwPRcdTAwMTQnKmChXHUwMDAwrn38llx1MDAwMK5WzKGaKylcdTAwMDCWWGuWgaVcdTAwMDBYXG6mwFx1MDAwNpSSqbxPw7QjqfmYVzCRviXZXHUwMDA0/YjfXHUwMDE24fB8eotBwdowpFx1MDAwYr1cdTAwMTiVz3pcdTAwMTjjTYNcdTAwMTmPXHUwMDE4mStVqUrJTVx1MDAwNPE53LlcdTAwMTG4jbSGeLs47Vx1MDAwYlotXHUwMDFip812vJqI7Omd6oDBs7Xh9tXjdeess3Z54s+eT1x1MDAwYlx1MDAxMkJoemVG88aRI8Gs4lx1MDAwNINiJTqP4feQT+vylvr1IX0xi1x1MDAxM1x1MDAwMI6aJunko1x1MDAwNNNC0ezVZEtGgzFcdJZSxZGJXHUwMDExqFNMvdh+4uOOwndt9Zntb39cIlx1MDAxN+7R6lE0nN5UZNgxhlwiXHUwMDAyjcNcdTAwMTHJiLPSjtBcZnHNJDLZ4zlxXHUwMDA2QXbSqbIpfixPp1x1MDAxNVx1MDAxNcvz76GiLmfJwdOMM5DNolx1MDAxY1x1MDAxZFxmdnuZQFx1MDAxM1xmsmzqXHUwMDAwKjdcbsVcdTAwMDV5XHUwMDFhbqjO5sHaIKQqfFqNXHUwMDA2f7+pUWh975eocbZ23FhZP4zu7878XHUwMDBidiGu9qs0NqtCt31ebcYm+IClwJZcYjua2YCtXG6CUb9Bgt1rJdBeTVx1MDAwZl7gQi4oxoX5s6w8TFx1MDAwZUyNtEjn5b2RLspcdTAwMTmY9fVaw9zyXHUwMDFlkmZf0IZZXHUwMDEzM9/1aozMvZZUXHUwMDE3+nz1VNdcdTAwMDP/PNLxlUc70+fbMepcYoNd9Vx1MDAxZLuJ1P7Qylx1MDAwNrXoXHUwMDE5vIlxsohWTm75UMpcdK7dXHUwMDE5lLJSXHUwMDAyLHtVXHUwMDE4qFx1MDAxMaxcdTAwMTTXYJxcbsxcdTAwMTWuXidcdTAwMGauVp+6nd7h54N24+q6fbPbXHUwMDFjXHUwMDA07cV18lx1MDAwMrrT+t6bu83Nk0/tLbGFVm56+497V+crjVxudTKZKe5uXHUwMDAxt31ebVx1MDAxOXySOoQqKimVmCM6WeQyUsrchmspXHUwMDFjKYSQXGJGg8CD/ChymVx1MDAwNcuNXHUwMDE5sIw0kuD6XHUwMDE1OoyYcVx1MDAwYpjhISTFa4SBZpPfnJZu/99//vdPVlx1MDAxYnT8dPb622nqXHUwMDE3VGRWU1x1MDAxN3e/XHUwMDFhbb3d7O5ds6143+1cZleaq2ir8XnFnVpbMyknLO1MrkrWic7D+qMmtSqIN6eHONec4lx0rZtCuCYqezlcdTAwMWRcdTAwMTNcdTAwMTJEcl29ut5e94afXHUwMDFlb3tbjYvL/fud/kEjOlhcXF0voFat763rXnSng/teXHUwMDE339w/tL8+tHdcdTAwMWb33qNcdTAwMGJtn1db0ZpcdTAwMTY2YGed6Fx1MDAwMjtcXFx1MDAxNFx1MDAxON5cdTAwMWZcdTAwMWG6XHUwMDE0vq1cdTAwMTk0NEVcdTAwMDLULCneXHUwMDE3leUhMKwolpKQ+WrKX9eP9pp+771Vob6gXHUwMDFic1x1MDAwZXX5XHUwMDE4qtHVvZOzzue7/k33cmd3Z79/XHUwMDExn8SbfCo0U+IgwUA2lGJIcj5ZxyYwc8xcdTAwMTFcdTAwMDVCXHUwMDBiU2IjXG5i3YQ5zGy/MlOIrrgu2n799cH9Wrr5Zlx1MDAwNt3MYY1Eusw/wbampVx1MDAxNeagzFx1MDAwNVZcdTAwMTN+VUXQxohcIpZcdTAwMTbXWaF9/GuUoFx1MDAxNnezXHUwMDFh4NpD+dY0S7CI4d0mdc5cdTAwMWNcYpJO5lx1MDAxZSVOIP5CPlx1MDAxM3KwqYOERVRaXGKNMC3IaDI1XGJSa440XHUwMDA3+5pcdTAwMTP2XHUwMDBiZDS9RS3Ml1n2qThlSqNCXHUwMDFjI8sxRlxmXHUwMDAxiLV4P6HuapMvLfI4as+LYvLKnO08ZU64Pfei9pPrYcp6aVx1MDAwZt9X1Mt8uqil2/+cYp2jT+s+2vXq3Wh4dsc+3fH11bDAsio9I4CZ2KY2me5cdTAwMTRcdTAwMDPuJzna5Jxqjlx1MDAwNdZaUc5cdTAwMTP+XHUwMDFkXHUwMDA3QcD+MlXNnCmEwfxcdTAwMTJcdTAwMDWZMVx1MDAxZqdcdTAwMDRcdTAwMTQy8m0xI89ySlx1MDAwMMVmd5FcdTAwMTduXlx1MDAxMExLqVphXHUwMDA15DWnMzXuX0F0YYWc7+1cdTAwMWNHT/XHK1x1MDAxMoWXfuvk6SxNV1lTf9xgXHUwMDBmWlx1MDAxY7VcdTAwMDdb267Hn64/0/OGqp/fXHUwMDA3XHUwMDE36j3uMdjHb9tjwMSh0lx1MDAwNC0kpzqd6TFOMrXiXHUwMDEwa+VcdTAwMTRcdTAwMWPQ8XEuQCH0utNcdTAwMWJD4FmC36h0LtvMXGYpjaDsuVmKw3yiKlx1MDAwZs6qaEdhXHUwMDBmdLGpol977LuDwfL32Hxt2P/xUyt8KHZ2fnLa6Vx1MDAwYoot61x1MDAwNM02rGqcIzsv2Zwjo1lcdTAwMTlh5rRcdTAwMTYhKUZcdTAwMTm9a3wju951sGJwh2ImNX1cIvCROyWAUHCwXHUwMDA0YrNcdTAwMDQ5/kGeUW+GJCBcdTAwMDGeqix0jLBkpVx0qdRcdTAwMWPlIVx1MDAwNHpcdTAwMDXHiMi5kswrrkorXHUwMDE1xlFzTlx1MDAwZXN2+8xukZ1cdTAwMWJ+tlv0XHUwMDBmPSagcY3r9Vhuy8ujrcbGWexdf5LTXHUwMDFmXHTMgeOYIJRIpqUmkmfCQ1x1MDAxOI3OXG5cdTAwMDDsXHUwMDEwhNXH8WTVXHUwMDExXlCB46E4XHUwMDAzNFx1MDAxN2cyp8srcuVthFHCOa58XHUwMDFi1ttcdTAwMTen3FtcdTAwMGKlqIefLlx1MDAxYfuPO/Hd+uKeR/9cdTAwMTI3TlZ2j46C/WPqtY+e3G1cdTAwMTlX6HnQ1E7YQp6HffxcdTAwMTbPg1x1MDAxM2SO7DCuO4a/uVxiXHUwMDAwf1x1MDAwMYZcdTAwMWank82Lw3CWLEVEwPJghcd7YipLM5ukyXug88HtVSyPX+Vwslx1MDAxN5TbW1x1MDAxZU5m5ySb11x1MDAwMfB0sJFcIqE1XHUwMDE2XFxlvVx1MDAwZWbHOnI0ZVxuXHUwMDEzxFx1MDAxOFwiWOmiYF/mTCj84XRcdTAwMTRivz899lx0XHUwMDA1L1HwwpQnbUG+xliZqqHqoT+b0nolp6NcXFx1MDAxOEfNOTnMXHUwMDE58zM7XHUwMDFkdkr4cDp+itPRf1x1MDAxNP2VePf0yX98Wlx0XHUwMDA2N5u0j6Y7mVx1MDAxMSNcdTAwMDXESkyxXHUwMDBlXHUwMDE3xnGYZD+JmcNMXHUwMDFltzJcdTAwMGWJkoV53FgrRTHlXHUwMDFhcEVcdTAwMGLYb3S8XHUwMDA2Zlx1MDAxOFMwpaSpXHUwMDA0Rlx1MDAxNVdo/EapJXfT+iEkh4Txb9xcdTAwMDHvXHUwMDBmVlx1MDAxM1x1MDAxNUVnYaFF9vLYXHUwMDBmMedzmi2vytlx7pyTStmxVFRHT1x1MDAxN1xi6fTsWH500Ls/McxaXHUwMDAxY6NcdTAwMGVNuaUqXHUwMDEziINaqzJ/ZIGr5yTwgkRxWFx1MDAxM4zJOFdcdTAwMWMx/vH7uFxuSSOa3nDS5uQuc+pKXHUwMDAxOVx1MDAxMFp6pivmmChN6Fxc3DDRj3ebyVIqkKPHXHUwMDBiRHFx4+lcdTAwMTVSRMBcdTAwMDRcdTAwMDTjXHUwMDBmYylcZvDMoUmcTVx1MDAwZcREXHUwMDE2U3/yLDdjnou9+GWuQeDsXHUwMDE4lHVcYvljJl8j52XCNa3WXHUwMDA2tPCzveTBeug2lZbK21x1MDAxMUFbK/RcdTAwMDBcdTAwMGb8e1x0z+gjeOG5s1x1MDAwNlx1MDAxNvxH8lx1MDAxMVapKOdcdTAwMDdBJ1x1MDAwNFx1MDAxZM9A0NpQbXpjMkXQurSWR4HZXHUwMDA3xs1cXMV6v1xmP5fI46i5QFx1MDAxNFx1MDAxNyfoV+C2mVx02sZuU1x1MDAxMbS97GFegiaagMP4/E9ytmjRXHUwMDEwVH4lflx1MDAxZoK2147ZXGKaSWytyTK+tzlcdTAwMTmnlKFcdTAwMTVytPltlIhQsOlAklxuXGL6g45cdTAwMGLo+H6WTVx1MDAwNkaEQMWJ3+lcdTAwMDT9XGZcdTAwMWYzs2RIonl+XHTCr8HHpdKXeXxe7n1cdTAwMDXaerWTvyuKLE7nx//xPJlLbr9/XHUwMDEyg3CMJ3Hp3vdcdTAwMWXWyjdcYv54XHUwMDFlnoGtN1xuK33749v/XHUwMDAzf9FPsyJ9Interpolation stagesTX DSP chainFactors:1, 2, 4, 8, 16, 32EnableDC blockfâ‚›/4 shiftDecimation stagesRX DSP chainModes:Bypass, shift up, shift downFactors:1, 2, 4, 8, 16, 32 \ No newline at end of file diff --git a/docs/images/gateware-tx-only-basic-block-diagram.png b/docs/images/gateware-tx-only-basic-block-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..fbd1639cb80bcd1972f0980927a186a5711fcd7e GIT binary patch literal 137152 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 OhulR)>1@f{?*9jG19NNu literal 0 HcmV?d00001 diff --git a/docs/images/gateware-tx-only-basic-block-diagram.svg b/docs/images/gateware-tx-only-basic-block-diagram.svg new file mode 100644 index 00000000..61aea1e2 --- /dev/null +++ b/docs/images/gateware-tx-only-basic-block-diagram.svg @@ -0,0 +1,4 @@ + + +eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO1dWVfbyFx1MDAxMn7Pr+BwX2NNV+89b1x1MDAwZWZcdTAwMGbgXHUwMDA0wnbnXHUwMDFljrBlW8FcdTAwMWK2WefMf7/VYpFkLVi2SFx1MDAxOFx1MDAwZc5cdTAwMTlcdTAwMDYsud0tVdX31db6+9PS0vLkbugt/7m07N023K7fXHUwMDFjuTfLn+37195o7Fx1MDAwZvp4iFx1MDAwNn+PXHUwMDA3V6NGcGZnMlx1MDAxOY7//OOP8Fx1MDAxM05j0Hv4lNf1el5/Msbz/ot/Ly39XHUwMDFk/MQjftN+9qRzRLfvrs9aldr55lmr63U69DD4aHDS02RGXmPi9ttdLzx0i+9cdTAwMGKmXHUwMDFkLqUmwFxyVVTI56N3eLTCtUOEMvjPXHUwMDFl44w+XHUwMDFmvvGbk1x1MDAwZZ7CXHJzJDFcdTAwMDZcZlx1MDAwM8KUXHUwMDExz2d0PL/dmdjVanBcdTAwMDRcdTAwMTBgYLTSXFzw51NcdTAwMWUm9OdcdTAwMTJ5fmc8XHUwMDE5XHIuvJVBdzCys/5cdTAwMGZ49l8453O3cdFcdTAwMWVccq76zfCcVvBcbs9p+d3u/uQuXHUwMDE4XHUwMDE5LzJe0OWp8Y9cdTAwMWUnT6fez/pcdTAwMTR+YbvT98bj2FxcXHUwMDA3Q7fhT+x1XHUwMDAyXHUwMDEyvmtnN9xsXHUwMDA29+t/4ZxGbs/btDesf9XtPr/t95uevVxyy6eT2Lf1m4/fXHUwMDE2O3vseXZcdTAwMDQuhKRcdTAwMTJYeFx1MDAxZEPJXHUwMDAyzlx1MDAxM2/vXHUwMDBl+oGYUaY5lYqFc/XHNVx1MDAxNK9JMGrL7Y698DrbOaxGRC9cXMrVsOk+fFx1MDAwNJQmRHIuNZXht3b9/sX0zLuDxkX4LcG7/3xOk+bRcCCkX/0+cXt3o9stX1xc/ty4nFmaUYJcdTAwMWRcXJ9cdTAwMTE4J8VcdTAwMTLSLIgjQYNcdTAwMTJaXHQqjVx1MDAwMJFcdTAwMTBnXG7E4dxoglx1MDAxZlacgNBp8sxcdTAwMWSiXGKj6nGcXHUwMDBmeU7K883s8lxmkqBcdTAwMDFiaIZSXHUwMDA0WmuWJc/AlVJGXHUwMDEySstcdTAwMTZohWpcdTAwMDTlXGL05Y/zmvzaOrrbv9lf/fG9PoZcdTAwMWVtzSzQhmhHXHUwMDEzNL7mQaBFXFyggaEgKmE4x4tAUPp1QqCBUkeDkIZcdTAwMTE0vYpcdTAwMDMkXHUwMDA1WkvHXHUwMDAwxXHAXHUwMDFhci3LN9BcctMw/3KBvl2fXaKNNoRcdTAwMWJQJkWgXHUwMDExZjNccrRCRbDGdFx1MDAxZXl+PFx1MDAxMFxuYERcYpubt+eN25VKf6d3WIP6tlu/7IX3IyaI7mg0uFl+PvLP57xx+fBgtXa8u/al8XWdTepcdTAwMTdmZ6VeT1x1MDAxZnfi3U5mXHUwMDFkdmN1u9JcdTAwMWXsgFdpfTv1XHUwMDFhTd1cdTAwMTGVXHUwMDE5p/v4W45yS1xuXHUwMDAwpFx1MDAxY+XOX3987XG9ZsRRmlJcdTAwMGVSXHUwMDE4gqBcdTAwMWPTa+EwhFx1MDAxNo34hEqJJyRZl0KzIPGlXHUwMDE1XHUwMDAxUKBTUEqQcrV4MnL746E7Qnn7t2vyYVx1MDAwMWxCUqvxO3lcdTAwMDKFXHUwMDAyu1x0WapcZlx1MDAwNJmEQcqr59HlPPFFaKJFxDeURiuFuP5adeWvvt+feKOW24jc89agP9n371x1MDAwM0NEYu+uuT2/ay++jFxyVu36bXtcdTAwMTmWXHUwMDFinlx1MDAxZG05ei0mPnoyzyf0/GYzXG5tXHJcdTAwMWPU9fveaHNcdTAwMTaMXHUwMDFjjPy233e7XHUwMDA34Vx1MDAwMpZS5u9eTVx1MDAwNt+98cNcbiajKy96kbyNJ71cdTAwMDCHilx1MDAxY5Xec8l4TZ9sn8ijterd2d7JeOvLzcx4XHJEK4crJlx1MDAwNFx1MDAwNfxP6lx1MDAxMFx1MDAwMeJcZlRJho5cdTAwMTXh4Vx1MDAxNU0wUCaJYFxuSKpH9cRAn8b5oKBJPb+bXc2loFxcXHUwMDEzodNcdTAwMTgoRKcypeZcZum/Mni3SmegPDroQiDl1WuXwr8+r427O2v7nFxm1EYtJUDwgKQxaZbGilx1MDAxOaM4XHUwMDE1hmyGx9knopOD+IRXTkmpXHUwMDA0ISohy0FsgFx1MDAwMyP4ccmUSeGe6LEhe2XCaG5cdTAwMThcdTAwMThpXG5IMnIlz8jfglpNd9zxfq04388uzmhDhNaKitRcdTAwMTBcdTAwMDFVmbBlPyiFQlwiWrZAS4hqV1x1MDAwMdhcdTAwMWFcdTAwMGX8aYZcdTAwMWL+tlx1MDAxNF7s4I/n3//3OfXsTIFcXPzTlYQkh8MlWOl44o4mX/De+v02Li3kwE/hvlx1MDAwN2Akl0ffxydDz9vaaVx1MDAxZmxfra2uTX6sRojwcm/QXGbEcTA69yfRXHUwMDAzLf/Wa9btpYtduSWEP5y9RmZCXHUwMDE5OoOE6NhcdTAwMTVwUNWRd+JcdTAwMGZtg3WSJtbwzNyXvX7z5Vx1MDAxNZyd7t9vK1mpXTSPdy4nZEf3XHUwMDBlq4utwE7SMCaQXGLh3WAglfpcdTAwMWNfoMTpXHUwMDEzqVxies5cXDCes4bgPlSt5et4bkL3cIXRY2hM/CnM97rng5tAaGOEI5j7vtd+0oy4jtrv3Fx1MDAxY+9cdTAwMGa9hu92U75z+liObb9yx+7N6uHJqM/94dHq171TVJ2Z2VxuMlxmh0lcdTAwMTHgjaFgWNxccrHhXHUwMDA1oyVFT1x1MDAwM1x1MDAwZqE/YpLxsjC8XHUwMDAw3KpFhPCE4Vx1MDAwNeVoXG5cXMDDMKFcdTAwMTUoh6uc01x1MDAxNj0//3dzXHUwMDE1d292465cdTAwMTh6jMZAgpRcdTAwMDRcdTAwMWWJnn732SNcdTAwMTFcdTAwMDSdTaUjYeOSolx1MDAwYt+q+6fX3e5pd91cdTAwMTO7ZP1rrb/75XTxKMCXoYSd9sl6b6XfXHUwMDFh3a70XHUwMDBlflx1MDAxZZ2dlFx1MDAxMLR41ehcdTAwMDLapWhcdTAwMGVkIeKWf11zolx1MDAwYqiHXGJUknK85VowmOJt6KFQzvEkPFx1MDAwNCTqPDxptbVcdTAwMGL2RYlcdTAwMDSF3C4tXGJectT73YRcdTAwMTfc+uyqjHdHaIZUXCKNpymaXHUwMDFkXWBKU/wknytSWKb4htL46Jzvr9c3I8bs91x1MDAwNVx1MDAxNV6AxumgwtS8y1x0JuSzn5fgWVx1MDAwMXWEsv49gEbaOVx1MDAxNUtAdKaKXHUwMDEy9LtcYrJNyZNqjCbf4UTbmCc6aUalhVx1MDAxMlx1MDAxMJzRXHUwMDA2IDJIxH8jdahIXHUwMDFmsf9nlf5WXHUwMDAwnZVkQHgkJ1x1MDAxNWp0ip6H8UK0tpJxKFx1MDAxZJ3pl+vOlu/vbfL7g1x1MDAxZjeuvzG+3TxaXHUwMDFjnV8rpVDb2dGdXHUwMDFmN8c9Ksff+DfSOb1cdTAwMWJccktcdTAwMTg3P1xukjvuy6hfZk4h/37loL6i0kHf3qZcdTAwMGVcYnqgLJ78RtRXSNSRiFx1MDAxM6XQPU1cdTAwMDZrgDKHoTkhaHFshFKnRGs+UD/TRFx1MDAxNEgqIEtcdTAwMTeUKJpcdTAwMTZtZJEo27SN0Fx1MDAxY1x1MDAxMVx1MDAxYUWuZNCXXHUwMDAwplC6O1x1MDAwMfpcdTAwMDfHS7X9+lKjg/j7XHUwMDE2sP9cdTAwMDXcncb+9OmXlE9o9C5MRV+snVS+XHUwMDFlkWHnpNW6c4vlXHUwMDEzmKRcYiqGXHRGWLJcdTAwMDBcdTAwMDCUhXZcclLbQoCUXHUwMDAygFlIwEdcdTAwMDHAy1x1MDAxYX4+u4JcdTAwMWJjY+ZCpbnoSmXm/1x1MDAwMZDOqVfgXHUwMDAwrePeXHUwMDE5r21vVlV3p3V4Nmx+XHUwMDFmy/5MXHUwMDFjYFx1MDAxNuwzlJWUqsifZ1x1MDAwZfZcdTAwMDFw1EPNlEDmRY1JeLxcdTAwMDH2gWKaaMaS2MeRadt8upBcdTAwMWNNIScyqSNcdTAwMWbQl6VcdTAwMTiNXHUwMDAyXHUwMDBlL1x1MDAxN2jIXHUwMDE0TYU+aVx1MDAxMvUyYalcdTAwMTf6J8Bp6bWLhaU3gX216spbgLxcdTAwMTdwJiWHXjbSddarw7X7U7g9ISdb123drzY6tVmUN6zaZFpCJDlcdTAwMTVAnHVQXHUwMDA16i6VXG5cZqE0XHUwMDE5g+bCQZXHXHUwMDE3ZYpIXCLSXHUwMDEy5lx1MDAxZsqbobx+XHUwMDAx5Vx1MDAxNURcIlx1MDAxN6EyzbeNXHUwMDE2TCaiVUYh9aCR9O/CyquMkYZwXHUwMDFkLVx1MDAwZp1DeXdWfpShvF2vNclR3clgmKW3sclOK2lsduUoabUy+rruXunhXHUwMDEwXHUwMDBltzfOXHUwMDBmvtfHp7fFXHUwMDEzRviDo1x1MDAwN1x1MDAxM1x1MDAxYc5AXHUwMDFh0YFcdTAwMDRNqOZcZpVVKJVcdTAwMTKRouBIQVx1MDAwNVFcYrKC6rR2XHUwMDAxYVx1MDAxY0VcdTAwMDVcdTAwMTCKjlx0cl4ovb76XSSMfs6ut1xcKim0Sk1cdTAwMThBNFx1MDAxMjCtt9JmWVx1MDAxMSfnqq/O46NcdTAwMWLrXHUwMDFiP7bWmrdbo1x1MDAxM3Laud+XP6/pZCY++jlvWH5M2+JwZWV44v0gXHUwMDA3q3t393ftVvqwxWM83FxubEldXHUwMDBl+evPgUpkpo5VXGZBKENPjdO4XHUwMDAycuKgXmomhFCcccZcdTAwMTJcbshcdTAwMWUzO1xmzSeApFx1MDAxZjGeXHUwMDAyOncxu85cdEBnQ0GGzrFcdTAwMDSCPumcsE4+46JsnovSi+Z5XHUwMDExqNyvb75cdTAwMDWe+1x1MDAwMoAl0jrRWZdcdTAwMDOh+UU5LzfcKUei30GYXHUwMDA0zqJcdTAwMTj5IKTa1kqgXHUwMDBmaoRcIlx1MDAwMmSy9PstJHXeXHUwMDA1gvZcdTAwMGIwX0lcdTAwMDXTQrFEdYW92FwiU5tcdTAwMDG5kP3ofFx1MDAxZEp5UHd43K7y6ztYa1Uru1d+W55V6dXiXGK6QJbktZA5d1xctbk7+tm567fO6u6WafRcdTAwMDa1853GW0T8/PuVg/hCMocjoFvnXHUwMDE2tXmKcCuHRStwk3hvPlx1MDAxYUXmt1x1MDAxMINcdTAwMDJcdTAwMDXkxCBoc57mXHUwMDFha8h2jVx1MDAwNUXfWMvS20RcbstuXHUwMDFh3i9Z7Fx1MDAxZFxyun/1R17bXHUwMDFmI26P31x1MDAwMlx1MDAwNXhcdTAwMDGAUyjA00KWUtZRXHUwMDBlKdg9uV7dVVfnK2ZcXN1ru1x1MDAxNXHXXTVcdTAwMDVIgXaQXHUwMDE1olx1MDAwMFx0ooUgcVLwXFzpXHUwMDAxVFx1MDAxMilcdTAwMTlJiYHNWIdcdTAwMTmwXHUwMDAy+ThM2Vme98Bcbs5cdC+Q5lx1MDAxMVx1MDAxYVx1MDAxOZZWaawgr2tcdTAwMDTQgdNcZq136Yme+2q9W7tgrcvL3YveNdnj1fX13bdbivlaxVx1MDAxZa9KXHUwMDBiXHUwMDE43vBIw+ZCtCD/fuXRXHUwMDAyzlx1MDAxZMM0XHUwMDAxQ0BcdTAwMWGlp1x1MDAxYkhpkO/S0iD0c5PkXHUwMDA1QIxcdTAwMDOWXHUwMDE4cHRcdTAwMGJcdTAwMDVDT+ODXHUwMDE4XHUwMDE0MFx1MDAxMqJIylx1MDAwYijaXGLC0kJcdTAwMDHGZFeESVx1MDAxYlx1MDAwN2DczGUkcms8XHREMtPz1nguuf3mX/1Wd3DzhK5vgVx1MDAxYryAw6lVn3YlS+lcdTAwMGIph1x1MDAxY+Sbz7xcdTAwMGU8ro1ccqnbflEwXHUwMDEygMaLuqhxtFx1MDAwNlx0RFx1MDAxMqJcdTAwMTghPFx1MDAxOS7gXHUwMDE07Vx1MDAwNFwije2JMUhcZlJcdTAwMDJ+xGFCcVx1MDAwM0QowZlBb6JkZvCOXHUwMDE0X1x1MDAxNlB8o9A3UzK1XHSPmeyeUlx1MDAwNYozWXpcdTAwMGKe3SbEzFx1MDAxNVx1MDAwMiy1XHUwMDA1L1Mgg08nRTFcdTAwMWMvXHUwMDAxzTN20eVXgi/N2UXHtVx1MDAxNkxcdTAwMWGQttxExlx1MDAxN8HxLcRVSjkulFx1MDAxMylcdTAwMTKLKNhGl2/W5lpChUytQVx1MDAxMJh/XHUwMDE15TXSxUWv3E6652O9wbW34z9cXJfxkT/pPOrQXGaULT+UlW/MtUNsZS1Rhismp7KnXHUwMDAyXHUwMDE1Qyn8XHUwMDFmXHUwMDA1XHUwMDA0aZKs5OPMkdx2/WvEXHUwMDAy9O9Dzlx1MDAxNzHlglovUVx1MDAwN9xcdTAwMGaoXGLN/Yclj1vyalx1MDAwMUuO7rTSmvLUgl3I3KBKck1RwUTZXGZu/mROuZY8S1x1MDAxZe2rklx1MDAxNMXFLXl+8mcuM0hcdTAwMWMz9YpcdTAwMWJBQUhy4lx1MDAwNa33K7Rxk0KzTFjnNFx1MDAwYjy3jV7AmG5cdTAwMWXX709cdTAwMGUre17728aP4y3d3NeHdzNcdTAwMTlTQMFcbsJZRFx1MDAxYkmpijvASIxRSTjyXGZcdTAwMDQ3uz9h0ppcbuKgXHUwMDFiJLgtnea2XHUwMDExL5VcdTAwMThLZCN24zXNiVaRnbs+rGncmq5ntD9EVOLxZtKkdD5aWfRf8Fx1MDAwNZBcdTAwMWFOU5CdZbNmUUP5SXM0XqDnXG6il2pnK5miXHUwMDFhXHUwMDFjTUrp7IZ2mjBlXHUwMDFjmcN+xEcu33Lk95/lWVx1MDAwZUNobE/FeLDdXHUwMDE2yCiuXHUwMDEwuzSyXmJ0soiNMUcjsFFcdFx1MDAxNKVcdTAwMTWdqjTLgZZJMYFcdTAwMWW7oFx1MDAwNIcrO9j+jkzHRoEsXHUwMDFiVczqQFqWXHJyNlxu1XaLPVx1MDAxNt0y4X1cdTAwMTmITIlcZo6mXGLj4lQsf8+2X8Bpftf2M1Bolm/QcuYnXfIsp1wiMtqQnjCc1G5MgpRLWv812WTDjGOzJ1x1MDAwMu0u+r+gU1JcdTAwMGVg5dgoqShcdTAwMTAweKJX+eBcXFmGc3t2w0mJIULI1PolJjI7TjXj2lD5bolVpkRcdTAwMDZH04RxccP5XHUwMDFhO2KVbzhfIeD4rzech7VDQfdcdTAwMGW/NM9cdTAwMGX863bj5ujn3uF90nBmt/Liolx1MDAxNWF2/1ZBpzenp1x1MDAwMl1Wg/ydXHUwMDEyxHEpk1x1MDAwZSu1e4dcdTAwMDa5O6FtXHUwMDAxR4rDXG7KMTYgg4Mj22FFon+pdvG99vKek5PZbSc3XHUwMDEyrWdKwsZOJVx1MDAxYadNsE6Bt5lqVnq/PouFXCJcdTAwMTYqQKjLjVx1MDAxZd+ofyX3d3u1q+3at9HwZqZOXHUwMDA0XHUwMDAwwlx1MDAxZEVcdTAwMTlcdTAwMTOGojU301x1MDAwMVx1MDAxOIFUgTMpKDrmeO1SWoFcZnPAxtvQ9GpcdTAwMWHdMOWjXHUwMDAw4WX5bVx1MDAxN4leS22j1ynia0y29FL7XHUwMDEwhPkqlHJlV5DFNpiyuz837DlLzUHP9ft/9TdtyUDf7cbeLqNcdTAwMTjhldr6XG6voJwqXHUwMDA0Q/zNzbPxz9FR62qwf7x174trOlOtXHUwMDEx047NSlx1MDAxOSE1J2bqoSpP/bnI+I2hNOVcdTAwMTFBgj7UIHOtJUqU/Og5KqLpnVwiXHUwMDE1XHUwMDA3zCA3YKnd9Ty74lx1MDAwMFDZXHSa8TfYoLtWX6++YVWOT69cdTAwMWM9/drouo3xxvnWceP05rJd0Y29085MkFx1MDAxY6ZEwFD7lKh0TaWSmyBcdTAwMDGdxGRCXHUwMDFkavd9NEF41KSB8oeqZqpqkV56y3qMplwijVVKmq2qXHUwMDAy7EbalIZB57eiqlx1MDAwN/ZGNjz/Olq/9+Y0NnWW5Shu/sayuZUhti3ebpCApNpwXHUwMDEwkeS+vUJKOsCUJFx1MDAwMlx1MDAwNEHf0SRcdTAwMTVXcO2gX4lcdTAwMTiLzlxukvE0iGVcdTAwMGXRyNaNsU+mYEZcdTAwMTZpXG6cYaf913hmxK/fZf9cdTAwMWNcbniGtl9DaZO+yz4kg23PSqzwXHUwMDE2oN9UOrvmaFx1MDAxZFwi24T+rrha7Oyk3L308UxhfoXhmCONwnshhELHXHUwMDA0UVGGw32aXHUwMDFh9jfWXHUwMDFiXHUwMDA2xXighVKgiVx1MDAwNClD0bEvcFxilVx1MDAxNGwnXHUwMDE5Q3k0yTBlwfDfa2R3okuwu1xmi6lcdTAwMTUgXHUwMDA2MXRcdTAwMGZcdTAwMTgwQDeR5SzhXHUwMDE37dqf1WnzaCtodP5cdTAwMGZzmlrylCbkXG5vTHxcdTAwMWZWkVx1MDAxOC1Xkl9cdTAwMWH9+fdki0uijjJuXHUwMDFiplxuKV/sadH3tcHwsHPNv26Tia8u91vfZn+EZ1x1MDAxOCZliqAsTz3y0D75SNoqXGKl7VZvkNJcbvdG4qTvolx1MDAxYlx1MDAwZdzZ0Vx1MDAxMFx1MDAxZFx1MDAwNqqMYmlcdTAwMGY9RI3O3NtNMmmE3Wq+ZDBcdTAwMTTAlSmpfTu/oazIM5Sm9nuYfoZSSpyUSUdcbtD2cSyE23BqUp6fXHUwMDFmPfM4StnU7lx1MDAxNWT5d1C7XHUwMDAyO3hcdTAwMDJcdTAwMTgpiEhNmNLszk6BUkeUnOtcdJ6xaaQ2dLPfnzLldIHTK1x1MDAwMlx1MDAxMUpwu/s0XHUwMDAx9GTgRe5WQe1JXHUwMDE3/ldcdTAwMTkvoUeLk8Ff8FxiJ1x1MDAxNb8nU89wQlx1MDAxMFxclFxyvkIyeJrQxtdcdTAwMTB5hlx1MDAxMyOESfX22SCLzj+DXHLGtSFXfmehg/nC/NLwr8FcdTAwMDc/PY6y7Fx1MDAwZYf7XHUwMDEzNGDPQrV87Xs3X7KjXHUwMDA2n1x1MDAxZe+ohVx1MDAxNi8oXHUwMDFj/ufTP/9cdTAwMDf5elfzIn0=DACinterfaceSGPIOTX DSP chainDACMCUSPISPI controlregistersSGPIO andflow controlDAC clock domainInternal clock domainFPGATransceiver \ No newline at end of file diff --git a/docs/source/gateware.rst b/docs/source/gateware.rst new file mode 100644 index 00000000..f560b583 --- /dev/null +++ b/docs/source/gateware.rst @@ -0,0 +1,118 @@ +================================================ +Gateware +================================================ + +One of the significant hardware changes in :ref:`HackRF Pro ` is the replacement of the CPLD with a FPGA. While the older CPLD primarily provided glue logic between the MCU and RF front end, the FPGA in HackRF Pro introduces more logic and DSP capability. This enables offloading digital signal processing tasks from the MCU. + +FPGAs are highly flexible devices whose behavior is defined by *gateware*: hardware descriptions that configure the internal logic fabric. HackRF Pro gateware is written in `Amaranth HDL `__, a Python-based hardware description language. + +The specific FPGA device used in HackRF Pro is the Lattice iCE40UP5K, which features +5280 LUT4s and 8 dedicated DSP (multiply-accumulate) blocks. We rely on the `open-source iCE40 FPGA toolchain `__ to build the required bitstreams that are bundled in the firmware. + +All gateware source code lives under `firmware/fpga/` in the HackRF repository. Top-level designs reside in `firmware/fpga/top/` and are the primary entry points for different operational modes. + +By default, a standard gateware configuration is loaded at boot. However, the firmware can dynamically reconfigure the FPGA at runtime to switch between different gateware variants. + + +Standard gateware +~~~~~~~~~~~~~~~~~ + +The standard gateware is used by default when the firmware has not requested an alternative bitstream. + +The standard gateware provides a balanced configuration optimized for general-purpose operation. It implements configurable digital signal processing paths for the reception and transmission paths, capable of (limited) frequency translation and supporting a wide range of sample rates. + +Block diagram +^^^^^^^^^^^^^ + +.. image:: ../images/gateware-basic-block-diagram.png + :align: center + +.. image:: ../images/gateware-standard-dsp-chain.png + :align: center + :width: 75% + +Features +^^^^^^^^ +* 8-bit I, 8-bit Q data format +* Receiver signal chain: + * Optional DC offset removal (DC blocker) + * Configurable fs/4 shifter (quarter sample rate): bypass, shift up or shift down + * Configurable decimation rates: 1x, 2x, 4x, 8x, 16x, 32x +* Transmitter signal chain: + * Configurable interpolation rates: 1x, 2x, 4x, 8x, 16x, 32x +* SPI control interface for register configuration +* Double data rate (DDR) interface to RF transceiver +* Interface to MCU (SGPIO) + + +Half-precision gateware +~~~~~~~~~~~~~~~~~~~~~~~ + +The half-precision gateware reduces sample width to 4 bits per I/Q component, enabling higher throughput within the constraints of the USB interface (up to 40 Msps). + +This configuration is intended for applications where bandwidth is more critical than dynamic range, such as wideband spectrum monitoring. + +Block diagram +^^^^^^^^^^^^^ + +.. image:: ../images/gateware-basic-block-diagram.png + :align: center + +.. image:: ../images/gateware-halfprec-dsp-chain.png + :align: center + :width: 75% + +Features +^^^^^^^^ +* 4-bit I, 4-bit Q data format +* Receiver signal chain: + * Optional DC offset removal (DC blocker) + * Round to 4-bit I/Q +* Transmitter signal chain: + * Extend width to 8-bit I/Q +* SPI control interface for register configuration +* Double data rate (DDR) interface to RF transceiver +* Interface to MCU (SGPIO) + +Extended-precision gateware (RX and TX) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The extended-precision gateware increases internal signal processing precision and output sample width to improve signal quality. The main drawback is that the minimum decimation or interpolation factor is 16x. Due to increased logic requirements, this gateware is split in two top-level designs (RX and TX). + +Samples are 16-bit I/Q, while the effective number of bits (ENOB) depends on the selected configuration and typically ranges between 9 and 11 bits. + +The increased dynamic range of the output makes it particularly useful for weak and/or narrowband signals. + +Block diagram (RX) +^^^^^^^^^^^^^^^^^^ + +.. image:: ../images/gateware-rx-only-basic-block-diagram.png + :align: center + +.. image:: ../images/gateware-ext-prec-rx-dsp-chain.png + :align: center + :width: 75% + +Block diagram (TX) +^^^^^^^^^^^^^^^^^^ + +.. image:: ../images/gateware-tx-only-basic-block-diagram.png + :align: center + +.. image:: ../images/gateware-ext-prec-tx-dsp-chain.png + :align: center + :width: 75% + +Features +^^^^^^^^ +* 16-bit I, 16-bit Q data format +* Receiver signal chain (RX extended-precision gateware): + * Optional DC offset removal (DC blocker) + * Configurable mixer (in fs/128 steps) + * Configurable decimation rates: 16x, 32x, 64x, 128x +* Transmitter signal chain (TX extended-precision gateware): + * Configurable interpolation rates: 16x, 32x, 64x, 128x +* SPI control interface for register configuration +* Double data rate (DDR) interface to RF transceiver +* Interface to MCU (SGPIO) + diff --git a/docs/source/hackrf_pro.rst b/docs/source/hackrf_pro.rst index 18e4a151..e47dbb0b 100644 --- a/docs/source/hackrf_pro.rst +++ b/docs/source/hackrf_pro.rst @@ -2,6 +2,8 @@ HackRF Pro ================================================ +.. _hackrf_pro: + .. image:: ../images/hackrf-pro-preliminary-photo.jpg :alt: HackRF Pro diff --git a/docs/source/index.rst b/docs/source/index.rst index ce845e66..401fbb3b 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -57,6 +57,13 @@ Welcome to HackRF's documentation! setting_gain virtual_machines + +.. toctree:: + :maxdepth: 2 + :caption: Gateware + + gateware + .. toctree:: :maxdepth: 2 :caption: Opera Cake Documentation From e32695e24fde864b46a9664ccddf42a2b91594d0 Mon Sep 17 00:00:00 2001 From: mndza Date: Wed, 3 Jun 2026 10:12:36 +0200 Subject: [PATCH 212/238] gateware: CIC defaults to the minimum resampling factor --- firmware/fpga/build/praline_fpga.bin | Bin 204769 -> 204382 bytes firmware/fpga/dsp/cic.py | 5 ++++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/firmware/fpga/build/praline_fpga.bin b/firmware/fpga/build/praline_fpga.bin index a6b024858f10f08f84cbc6cffa578935c0ae469a..64dd9b4b9bc6f457a2d440b385132e270e0e864b 100644 GIT binary patch literal 204382 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

    8B0P02b};H!|8ra@ zj&qgkNI;oQ?O!umM{E=?E$ix+M;Y;xTxKZk$uL9BWH#OFE~V#MaJTSKt*}7f7Q|mm zw6OXXI3kzR;3~UMn`|(9EcXXM;b<5ZoncUf_~rCAlMTMEyRHe+ zPj#ayN?exWK{}s0hN}LS;KE>yS5pE?a`V$FHo%z>aQ2u6*2G06pxCGK-rQL+m{3Gd z^81LBQmI}A4qg)FD5!gJNzGgktM0J10%mp}*{@Nm3Oh8+n%<+@Sqd1K`H)k#43Gz| z#i5}IYqy+n@E<(sViY7w{>y?RTd*#-TMSQRS}%zAFeT0!r8;g|X}cx*i5K*ExmhW1 zuPQ#m>i4~9_cJM;TV7-XQ~n@wj*`FqQ>Cvnq9q^?l{X{AM8GcS6*!UCp}CWl#iqH# z&FHc(CE4b`EstQgm^HLHKxk|{UPO{l3F_ga!g{c%F>fCyt(w^(GTy_;r+I7j=|A20Y&CL>6k^xB}mmFj?Lly zu~n9;)GObEInfb(c|txbtE9paMyMt2S6oD1M@vL+lv}3FJq{7~&3B!0VgfPXMYv28 z1fC=m61n(*9gp1PQj*FsNs_7OMK?AeI%d^0E7S?O*#8a6LYfhB6E<)zl5>Xl$A^^g zE*MXBN>NgK)D@Jf{~@#WuH$&k3>4#Doz4Uz zO$IiRE>ki#&f{D7GY3g#*q6v0R4|{kS3Sc7oYFNS@~2bEVoVefHp?^7W+lUTk@d23 z9z++Yp8rlsFgRhwOL&=}51&DlVY3CsD>xk~-p+Rs_$xE1yiuBF>2X5kaKwNlQ|x(6 z@g?h$@m;9w0%`gdX61xjt|G9DlosUnmSe2|?Gjj69b6&P_-<1l0uMv@r${%=rYD#L zLw3>mc^Y~QKc(bk44oG$pJ*lV|N4mY>MsxZSt|k;G|}t6_|X5pQ}KU)=d%BOW#a#H z)YA|7`JbPD!mBvnJ_oYQ#f!K8zfU#$|L;W7|8t^?7q9)_ck=&ts@wiQCyErT`4>}h z1HY&j(=HNSy!+WrcTXawtRZ7Ie+fr&hA%pH69l3x-9rYLopd$z!X0A)t8GaiNdtO_ zwKU8GbaBxgl?J4iat1Nq4(g+u3f-*0dJtK_M_#HPKs}~Y?{vupZnQ#9iI1*%2**iW zPQCS*0`42PP%9bBq5g77U+SSWQbBjiM?H*BSTUc#{L&OuQZ}%Oa5r%YclOY6bp^t; zhxI7`f)6N%-?WWc2yV3B%<~fxV?CVl&c1%ETMxBO8lcM@6;71*Af-J`zRA41pADsK z>q82J#vn6}DGf+M$)i9W>P2qDYaZdHcW=jxw+!n7qqDR&3Ux>{DAUS7p^wNRqlmJk zM`)bp5-m5&>HF3w>4DQyUm+i*%c;F)DqF+o5?Wb~vVQ~0FG*t)q_?8)bx?f5YV&j} z$6zH;;p3=GxzAjV>D1`mK^ktENU{N2KBIPT9Q`A7?6#a=uSSXAUQxn(TCr}*{)OHo$PO5_ zWSRG6%QvTC1ci0ULe}>C{HOqRoG!0Z70q4%5^B8|0boMRog% z4M=!p@P}D>&K07I`MV)IXmlg@e%Bx{gEly0w(EQgcUeEFsa0yP6107U8Y$Rp-9jl< zyfjJH*HoCmoz@m2tT;uZrdGdSlMK6vWsQ%OSzd(@|&^=c-333U=Fls*Pf_`)Dv&|yyY(L zm+$9Wi+yt-#^DD}?CxNVLNavFqEcS-H3^Bhuh$1tZl?y!8-o*sm2L9JUc#L`LVM}7t7j8Uh=Hm}a>jn*+ zH-I8a%4cwres)4jbs>u8m7#4jikLk{JFPbZ$8e1=FNe87P4sWX{z>NhH&$gxe&Y+& zdw*(v0(kkMGT57xe_)yHGxk!?N79{%_jGM@8J2V`E%31=vc>G-v|6Y0l8v|eHY-ym zJ+nK>T4=ORMP^Zozun6-iWj=|GHgeXGvQnHlH@2ecYiH1)vfzh9GHv;?O9uuOM~4D zy>H0c3(N#@F-)V4+s8iKC~5ahp5T9LeqqZo^$CiCDg#J7yLhWn9ybK}Qr=e6E4O&ll?Sxp1Kn|?v*4U% z9~Zyz^sH=_+4ZhF5++w$7a^;8k!@7NTDNd->t*V76#`EF*k7oSTZI&qi!rx{lpEjH-nmc&`&%EIe*1dQH zuW6_G-fO7WhY%Wn-WT!*hWc3o7G#J(pG&rkRB)(Y5vvUx2?(UDW_y zP$YNw@DF|LPP&Qqk%8TWAF;Q#$2kHv!}da`o?d_~fHo9QLM1S|LSJ#giKv>Gi{hdq zCUi7{dV*-6?{qgho8>hPd_2dnkm_o-XbczZaI1n(9e)fD5S#JtDjfzh)_sG(1R?3p zS@)9Pe-8y!fdor8Y&{LcR1THBdLNF{l6X=^#_z0Z;pAzP1ukVI`w0(}7Qbv)JxWKC zp4~V-8U0%mRNO^nf?w1K|b7;svzR84lH9FpH9j@A4 z$=NBF2u}Q-w&e*gyCBY0!t-m?maLt$=8xviEH$9)t|bWL4on zXjS>e)2HY)B%KiUbGgISU8@|M&Rzokpz@EcI{WV zDt-q3=-yUv&866;4HL0GRg$IkuAwXNEE#Zk*K0(Z7_DUHi(|&P$%t(2K}TGnr2<%* z<4!bm26GlYr#r=s`HYVtniTy{1=Y-6_Ux8yRt^jE9omg=KuSnW&`^GJc4!iwX5vLu zLXGN05tvuYDdlPhwG4q3XyjV)4#Y+05nK$=^|QUH07RWisSgFJx z<(c_W^6x_zi{d;oEb%@qjN`29C}k+G4JC!UFHLKS;&Bh54EF`9wKWp!L74uOU|Z^R z^zwuOzL(4go{a)62k&iiQQg8!%W9PBdn~T*3iHz3=-lBFJ5R>K;u&BpqC^_LHqtRA zHkH@&pl9mq2)8!OW$i3fGj)_?wyY2}R3O>cqEXxwDFazJ){{o7<56@gm(HM^Ws;5x z=-5qj@pLTt-li&P@(lQdwL{UYCraJ0F8R<_79>EF(tWZn<5Z$vS6QGIWD34P&Y%X? zAqjeY?nsoH73ZzT{Jb3-<6y!B2Q{rDf8w8V!Ravcu51V_Xskb#_1ldAfxmDQ*D+6h zL3iE4rd41?Al4z!s~%w`BB%0aw0roz`*~tFP+bVvzE#Rte2!7GvcQB5Ge|6Edh0Rf zj|VuPs$@U3i(8U(!FX00-IhclHP12%oR&H53VoV|yD*sb<^w!Vw@=0YM2bF2{DA^R zu>WfmlH^@{7~5pklhP)+cJZ3x8E*+)HtD&pC&>)=5qGjDe;lA=f#O0RB{3X#9KX~m z|2Q(5@&Otm!R^4Nppcz$DV@(+P)2M2-2uNs-5HGoL_CNt3lw5{8=~$jrBDui#mm_- zc?NT6=70#|x}+_DdEBRwY{{>Z4m$L}FRO8jNtbjX8kZ)KRJ+}%C6B~1#Ss-@rFdpe zR+mj|1OY^zm45X-vl!XL>qJ(B$ns=-9eYwS#XWtH-E4k>q1_EG($Z4qd;fv*TKQvq z$R&oZu)Lh=4sJppsL=N_>gB7usC7GbdP+Cs#z5!zJd?>GZmw!vyp-*I5UP?Z?u@E* zlK;&N-}GjsCa?ICvY%*#oMODna7`6&Cg>ZfhS7T0P!_y>fJ^CVSCz7o70tU*1oKtN zUfx5zL{d6#Iw^+)N*z!R_M zVM0!z3{mg-3SCCM4O~H34$}uW&DWB0BytgIPh`CQ3`tU?@c=%&&!M!eNfG>hn{-2t zaD8P!<6}uW;xy@qTagfZj&ag7GXg!k&S*(GfSIl$5P+>?Vl-Vbv29>(aq5}mbw{W=QT>wopND7 z{xHRu{ftVbm%T6dh4VO7cDa@3r8}l!uSYIFVa`{iJWaYxg~~soc&29JHuB06K0*ee zP9%L5WwC}Xk&4UsrMDa6eSRg%}0#y;nG)1G=cVMT?ehi{7e2-yW zRH{SsyPehR~Cb=3yz)Fi_~(*Oe=DizEw^`=~pVGZf|R2*Ie=LLnbtwi9+m>sD5k zljEM|yKm65u|3}Yf(qTpot6|kolMgUen3Oi4>t)^PGT0)W-9r~sw(8VHiy^j-EPs- z?lP3oTQqKfrLj9XhQgFEMjt@$C1?%vyK>2z{osMA)1f4k*q7W zy)xr3?#ZEl3zAp3fvZ`ihr+44RY2y(>VtK%VNN?K)oiM>(d?LtsBrK0?lM@_G0#@) z72>mA&ZSG@Z^&3)K;tZji+o1)NWUX&@J(oIf@D~9E2cxnFPA56Bq*Juz%#YvpViad z1AQb^z!Mry{!h`uwRYAex5)l};E~C1Ys^bi5Nolt#xw+=JwB*h9S@D2S7N}qWaa4d zuE25zo^zjNyz^6CcOt}c5RV@xQ(j_M&K&EQe7l;5LPF}xnNa<#3@f?t^D(3^ zg@-+rf7Bl7#NM^aiEdB&f-3x#n)AB_qIIm6axKI$3*~SVY!1g4U5!(5OuE%~_Gro} zmo5hdMAM6)M}z>eu6!FZi(?(HouMy0fSih5kC&0DBB#Zb<)RwkU<;57&xT0gYVjKq zq6f0^x|T~HbN~l_i(Rw=T_17!xNNyUoat-?V=Ad={1wLz0tlW+FiFr;9bm^%thok9 zQ?GiaDGMU+?7d-RV<}q3Ctw{hh9`qYWy*4;JO#L7A7Qs~o!RwmyBu(3Np*d+wTejwO0V))FQb3A> z5)cH@ffNzzN=3%O_4|Z^;VhxPVioF5@^OGZS3VVKk`Y#Tk_Q zK6UQ*-rw(^`}gJbqD`8dbDrh%eD=@#bBq#)ajd0#1_&hCaFu;F_4sU*aT``QB?dMd zZ+*&os0Ih0U~)~ZJ^!SBr!%b{UG_+&QwWa{A?hgca zhE6*fouG9e@7eJRlG@VdyAm6!a44n!ayqu@HSaUNMH?yjiJQJcT2_GvQHXWQGI6!zj7|KEfMl61m*S87KI#%W#ax zu&f+PzAYi>hw(Zr69=`P_5D?9LZ3vxT>TIxGl%GSe&jZFS%#i5En-JmJt9~Lq-N3S zSVI{*g44fsA?g>@r%-IFolu5WA}slkMpuJPf)rAN1wP384tMWmb^GW=(g$WqA$NiY zYjSMt<@szY-Ln(7PFUbQkKqdX#O3I7h3L(iY*@a(*+$mD7qhE~Wwj|uEotrIR@toS zNA^mEzK2ymqoFC-g@r)XoXHniKKnu`S!96(J6-e)D;fD2RgE{FbINv=X|AJ$=ncHD zGSu7fynYJm_o_v$Q<400Z|GsQ5G_Pa>8ro2XRWl;Je#I1u}DP%^l?=M!9#oN1If(G zK4$(884G4<=d2P;uJZu2q^0do88B_5^Hnypp~u~98_Z~fgTVL=Je);X53?YRCQd~a zSs4Q!tu8#_7^IzY2b{=9u@#ct#e>`NRbv;&(mwMw1u#Uf}smmg`C zneP4zRh{+frw*3WCS^_8^drQbC@NA|bm-M}wb+S9om}gvum*)d+(uRqz{yHRYM!dG zCRfTtmlWpht_ZBUhPl{9| zS~W9vIf)a$Y_%$nhzvm$4Z-X@tZo5}U6p=2MYi+D3x#0%KuFbQnsB2*|Ii1%!02i@-eA~ll#QPN)k6{K3w_H)MV5QC_4 zhWUH7FXjy$+2G4yTZt`NRhp@B6{CZTUI}ys@TGGPx>&Wx{abPj!2-o%wiOpxN zHG~9107ZG2ghk56amp0gXKKZw+>0y2?n)mEYsM4ie@UfKAS#WsNCJK|e6`9%*=U{u z!=fZ7YL##vC}#IBOS9AEh@N_s15wtXNDe$aD$!AwIriB#WfVFmMkC`U`XCjlF4WeA z=6|KIj)LBq+rYAjNDiD#YrlUnfG$uU@<)AJ*!$8}E=xChV< zBi1BpsKKRM_7U++w%x1(Xh6d4?in_QV>3q>i{re1v1>JY$y8SP)zS@i3%F_aVAD z{Uh92j=ob!;>kze!Yp39b0f{spgHA7p@w)F9>NHkTqi#I{G$yBJ2-x+Jg-CC8^stu z>A2h-_!eWN4UiG=Y*w54C=~aY&a@cS!azShT+C-4u-6nPLpge5A;N9j3@BrO@bWKr z^fzGSCIukhe08*4jl7Mawg!6d`vsNb=zXIP z*@r;_#W;zVLG?6g`b!4Kl9i>bx#)s`bsmShdH9Xk>g;^hZBMy1EJJ)+EWK=c9VP0C zcRtGE3_1dr}3fHXuM&F7ZB%B?OuxK`7DwOao?DN^OP*6 zh;D6i%3@yO>R;U%Sf$>Tz5zIWA}gVCA*L14eJL~;- z;|s}u;4sHr?Z6Y*gZ1)*2L#7~;ap^ID6YLVkH_Qrh~~=hE1D#cSg9 zUl^&3q$fNKYe4PDj^}3~E863QP?mU%5F#5z;gNT+DDDw7%D|he!idpq-dqDJk*qNu z$eW@WXCV8fXB@Xsz4=doHSBplJ)ad|3T(anq(a_iOmGaHcK3QJs^7$`^z3Bmfzb;7 zSfJ|@{j%2t#1)2U+{$B_htb3=RlL8)Q6FqnOu0pJF2#oZ^&>f&b#cF*1zZwBPSoi2 z0(z=y#Et)EMQwT1njUN!hLacv8-AXT+;)R;BE{F@WcXQxAN;Y zqpBV{+z2uinqNl?i!YwO4ci|;2Z;`Buh@#b3}wNEAYtdseL!(DM(wqf2iIw&NRwZV z$e&BGQ^jULM^iCIWOzbrq=jwW7wyvga>*RxyGh*0Lmj9dN^axp!}KyrB21j6j=jIP zuvjtA)d?jCmE`$kT^U%3&5goV2P2`@Kb9hPPkh8*@n_JyjS=9i-YRnZNhe@~u&YE^G6*$%a2 zE?GUfX7gQ&JD@OyRbt*mSxYD#)|G)gMDm(lytZumovtXJ9QH62%^TKCcQ_4l)z(Ns z`rv0GYAg_-w^J`n&8K^mQL#7flY`5UF3MJb_l63StF_Tw$$qB&q5^0u*#CSsj=>gq zl2Bbrl83ZvXg5^84Fn)<0yWOy1vg^bYAEI|-;NxdA83nN#pA2`Fnd0g0*9D?V%ayo zx8=Z6mm9iGXd!d;nxQ%h#2m7R_7GkGD+guD3c9JsJ>qeSgp9Ei_$}8w1D>ccj9f#k zv%KmTDl(&W+@S;$3H*+EOG7S>xBdn2x>MvM**8Rvv(wN{I5wc1N&d$uDj(3Kz&t9N zh}<8v$eqvPaiRN_AYPTxSrjh@Iq6Xdfr<_{Uk?BqhaCsn4ab774eVE?q!YKI5@a|a zt5VM?RF5zjMa6KW7ePMEp`t=IiB20{d9zhULy+$q--mAwSs)i}?SUPD*f|E+jyw%7 zGNlXfJMJ9gvCz{4*OMMeJq`f?h7o0Fp|%%q>d&OM5c(fS5!mkt{D!%sp!$v|&ifgG z9xB7Qhel!b48w`3kL&cjG!cKQh(b9*vLhbkxGP6iT4&2pjye!-pM^(W9mO(Fih{F# zjd#C{<{qbuqY(Fb2RvX$6ii}L6i%r;K0G;rWa<}Qlvt3u)9 z&u{U?-SDg8OrNC9_^IPR-ePNY7X>Yqko^I72bA~!^D2bqoF%(~{82pPatDvaSyd~# zZw@7#HyHX!D~@a+-VvKDoW(ec#>4#x6EKYFZS51g!bvbWgP2`Jlc_ zniP%r<(nNOBvL|AO2$NRACr2r67&r2gcrQ6{R7ry5WO{*@0>2A|>R3jb>^ z&UdCpF^!YoIWN1M9X{F6?ke7aafh%BQF$nN;ugkk%}{gETTth`6ufL7iMcc}{yFkn z6YXk^>HKmLF0z3BgD)pa2;{VY#zCQu!rEz#vmJiy@_aTa&ThfyaRXmS%;2=6sau(h z-A_c1y0|E3uX`Ayr4ah;mPV*|w2az&DAcV)ajmz+Smh9DS+pO`C8BJMRuP4lbBuk=lIh96_LYIl^SE6WeaB(t& zi!*j9%ds7%QAO^!f*Be!V9|q`yiu(WX*IsVBhnb%Hd82RDcMQ zaIer^G_J9a7HbrjGMIVT`i27Kq+n1r@aZ5Fjd%{js*K4*7AgsiqJquVkidGwH;NS9a zDIg8W-$7BfO^TJvXGibZJ}j~GJO z6$M4c2YE!?g%fN=jbnfnLY@qE#xKv00!(I7TsJWKxFwv<+^}KWQ-oTRlh?<&1& z4*c++cjSFqiq*`35Xgw`8-t4&6!B=>XOIazK?@E{x^I1A)0_T;BdN~feOtzbx%ZLTfT|I?Y#LZiX$*7ioD9_ zexBDWgRDe#78EW{-0dt%I3qi`yA}!6^xwz-l=cB9>&9wl9DMbd!vgMb28KOAH_=}e z^1m^M4Pn8Zxqz{ZFNWtG>+4*DXw@$MV6+u=B2nP9EQkWv?)j)ZMD;n>R7bNWDV3hT zDH!Ba&J(9a^&<6J$MWcKL<|q4xyxCP`lxci(~1Qg8C4#0dojVgle7=I@;!s+#fM`I z5%T|^3-Xx#gA-X6)uv)i@qp5h0%ih&SssOxWPTKJ&q@B-68Pk+&I2boTybN(qQ@^! ziUJ&BQq*?dGbHI=9oP%T_&8Gg1}6%K!O8paHXC(bUE@q=%2FpQk+Xj=c@_)|GUs^< zA^C!nk=9{SkyJ;JsTIq$Ge9!FSumnnTp_buDY5GmWWi8r)j6)f9mFcuYy)~2V3l0H zA>s{QQfg6HTuKr95*G5GLedQs%%!Nr^`0_O67&yGuunyPySRpm5ics09wm5IBQ6^K z0WFWgGkT}@RBlkVjtb4)8kEA30Wp&)-=WMi$8uFvXS*8UzcQ(*oOEOjw%$zTzH2<* zu}odXstmNZs4&(b#gT5IXcfR*D)_~|u>K@fvYUMkGOaI&GxN&=9!U-3LHl9~A-|!= z5p(!=sxs8!Fc|?W1nMbjJy7f)h93n)Tjy+89DWyKaRcaTu(~xF6mbT4;8_MH1w7plQbj9=)RBKK2-y6A z$jv)ndyk_JYP(H)Cb{7XQ+a=sJO0u40GbG@@PGMe9gR9n9{VkP8E~1Y0 zDV~}p@ly$@+g7)`yP_Ofd%lq5f1jxUA+mY^#l?zYa%jI{lLYceDwTG2I*OPhQzc5X zde6LesS=Xc?{jc8D(XAgJZ3RX9s{O|ivkjpJnwPYPZjV@179t$QgTQ6UnMC@j-w~S zcriZ{p`Z7tLY(37r`T-78mP5J2|)st!^FkkqS`T%p5p4iSO;2r)m{W;cRm~9|BBpq z@L;N#D#0`gCi9AH1S-;s5TT$7UIj?GK$N|#D3vuM2q~{i)6@cE&~XjJZ6KgLgjZZZ zQ5$w?d0wZedlb0=Wad1upaceMQFy>*G*wQf*vQwPSHhVRdcr|X(PBB+UND!U+6Ba7 zz8|OXWdCuZSRsXzS4mY#hTgSstnjDEO1aGWzvH`%UO}k65eNfzE0?8$KpgAqRsz3q zxs@~|ko}fa>(y8B8Niao5|tNYcFQc*M>PE5`&q|XInBzsq$*c5+$9y2S~idQjxIw- zFRxg}Csmz3puGd(N$}t`qP7Rn$Uq6lP7UAk>|Qoy*xa@0zpi?jfvUf0Gs1Gfp!JE5XTMZN~)!CpC_(5(dtzW&1xF5tKK zLe-(*oIUW)D35x~sq-u}XSaQ{Y}+~SwNgr})D{_}Sfmcq5dLh}bWdqfo%OZtF9Z94Bb({mcqg7P>Lyx--5D?RH1RRL(Bf)@S3-&2|vWUOWn^D(`( zH`dW{c-$U1cB2I_NO4GN5B+sfJX4on)JZjphsEwWc4 zOcWNtGzG-QFmf!nA`H#&YBO2&eXVUQM%h<@+|K%0heZOiwVgIw(0U8`547Pfh)=rt zdvReI#R>}Vqp=wSf&hlDUzv;WIo2{YOafPgu`sFGq$7fq0BI^RCo}#qBX+dKFQstdoIZNTU z6U2{>o@zC>w${~C=hxAeZOyA%apkYy($8~LcVkjt1^408 z&=PG6vxcAFt@cn$?cDdj2vSginnZChI7Y9yFI4qG-EW zI|JnisSBvs8U7hIHp@ZLSK5(($%>1fB!$c?$ziOT~ClS$m(8=x&v*ft{*t^>{FnlGZ-kkQL9_ig)****QbH z%_;tDr`e#fZlyhb^QLQo%vT2f;4lb!V$d!K#`WW9`xVpJD1>Tk%rhK!W?Rxe$V4n> z{i4|+a1#hDR9r(Nu}OuxhS|+$<0`dhojRL%J7;}vUK~ZrSY+XcxIZ+4_BcU5*@%yw z5~7p&D3))~(Q>Y%R;+ha|Awdm)jV(+NztTVK56~8FXnT{>>Co*?x#A(G4YzixQNn& zyuy>(QIlOtdnf@ewB z!j_p!g;DuR_esZU%C&Pho;fLs#P7+`R=5qE3y=Nxi0=J)2pb32jLrDDw_S168cxOk zd!fo4-{Q&dqQ-vcWslP+$2B#0_ml7Av2ZbkvJwV_!w^S!jJ}WRb7@js;N{5+q_JA5 z_JlS>{A~9r_*F%LD5xP4cXAp>M^`$w71T7pW6&IQZgW2RxS!ne^T@s&9N8)V8JUHn z4KoiE=#)4)h|7-92nxW9{Cs~fNqnV>3cw>AJ9F?EC;tue=pI?mL z-Y!thlqeiI$Adc9K2F;NM?e0!l3(YITGx5!J@B*d1?604Q*oY6rxamDbQ~ndxu?EN z=Qxtvtfv{Wa3S@xB;;;kv07?IMzzdN=RGt4>9^@NR#CY8Y#!zJc%l1t6-4S?$Xytm z6xu~hC(7Y2g9K6Ppk@EWID8(MFa(r^UnBA949!+8fM$pMtI31{?xOo`7@Zi21B^N2 zT3U=RRW=zc0}=UxLqsfYbNDe3g((Laz>bLOGGlR)k!MmR%(EzDjYnYbd1{d1X`R6! zU$8$RpNpgoES|xereNPRxO#A4y`->q)s~$5xsd6_L#?~mgd7u-sd+2O2c7u*__)h5 zsoW`f9~&U!G^rtnob71$`BG`fm_`xtTOQQ}=lJT>sQF7)_P|Ty#kH708F)BMC5LiL z&ANBx<7`IyegTi)DgLPrn`!i%iRnWeAm^->o9k!>ide8$%?&IymE#Ky?TU2ErQjx@ zr(p|+yLL(9T1jd)-i1r-n8p21^U6VWeI z3tjZ zd6Gk`@UKpG$m|D)%bh&+KL-Sysnem$B}s<|(@TS-JTY$C?KC{9!aDkS0fxuR=A0`T3_-|)t>YN`Ph0wYj zSMyhuVnD^WM!09np{xtq16F7pxWv~14+}U4e^}Il!_IPEPHcw^g^q~5y4(@dV}9mF zNbWc}b8tKY+6BhJewJjzqZ+i$|BP+K&ptT98dhd29ku30XF1k}`EkgCIdCdi^VzEi z`p%Gavhb{hI!zGjEQv>fgL<+N7kt&OOZdccHguCSi;4fm>BT!>5#wdtb)-xB&Y9~( zx?hbVSany_1u6gaGL-GoN}~TyQSL)OFW>*Wb-SJoOa=Yk;QGJT?ba;?lO)Hjnus&~ z3_2y|5-tk2z+aGRB0o5ktILq_6>SU)Zv?0xNTiTYAk<%31WRHX{g;hT8)(Qes%xwu zNux2AMq8K;Cs%t;>N$-KL#QPP(Kw8d)jcHWlKm$8D86cwFJfg#25 zT|~31Y`qR4=-E`KNxw!71&e_@@TmPTZz!|=M#%1uw!!HEIY8w_IDO}>pgi1rmpZCj zU<>m?5vtUN!qo7~!-M)t;LH?A^=%dogmD&YKsuYmf9d#!R_AC?vOmsO2Km z1wTP*QXY-K$ena5Tga^atcmTBKVU=jKXYKQeB*{;n?PpEskMQ;Om$)~XRqa=#J;yF zvTq#{?e%+DsMSRk&#b30Qpa}}(+`TQatqP|)Zegp6{Qx9{MHsQx72#}$mV~nAhesU zAh`g^BB*)xxY&<=^gp5=tS~Ht)CJ#wiEAi-0iar#rIrvp|BPNLD1U#dMb-{Txi6XP z0u~ec0{$;v^(AtEC<#N(g5kiwPa(|&@K9Z5{GyIDd0)P-nv z+Ygrxx>MU^q3lPK#65hWWNX8cm#CZ%r_BK_AXh6$-(Ezq-V>{+B9A6H$ksSSA#npu zOr+&K{PK)Wa6rIiD@?2qr-BVvFsp3ATyZWR1*iysU$ipB=6_HtVtFZu+{&2UcRdx# zLu4JbbFIC*mLKBS{^C?#X%srrCAuF|UZy;lOvYp-|-aG^57XjEO0Y z#Z#?U`3z_e^;=x5gk7LCg~=Mr5I8@9{(8M80_v`F_-5rYW+mx^62V+*Q(7)9r-Ew~ z`UTyDTt)^*L+U-6(Br-n+5CKE7R#@AZUerI95vomJYCQ$4761sbRjyW;09PXi=Z-8 z)9RAz=Pz<$E^sJe!<_#mMr

    @%VooWG4f0hp{QeBplF`~^9y^RSu%*P<1Rsjzsig00zX63fBSXH)8=H{||; z?Jg!S2&6UXo!GWWo-B6Q@|SY5ZDjot?FrsEVdJVYsR&pyNTHKf>Cdu7m9?EHu=$ud z?IV!mLhFV(_(*k>w1$1rEIw0AzF6#Ju|ux}S*%1{ExS+&(6`z>P3_;DsdZDWHjWLo zlJ2Ct!`fm0Ma?v$bb`xN+J8TWYCMZ0c0DUY%mgS1Y#C2@pVf^M(hW$Ib_=suEKve%b&U{FoS(@iL|bSj{QKWVz}$AWY9f~xO~bC@_` zBU_#%>m_CmpT1x&vrZ=mI z8`GWe!qrcMbA5omQ2z&0|MEr_B<#Ju2!u{OWiD<#M?yaZY40B%>toeO@%QT5VK#L5 ziDwndYt@S`$G=>KR-CfgYHWX%#%0s9m%0XG_276;Nvcd2Yfqz6s?YJDrHZ~u-bO>8 zx)Vt!JHLknmTtKG!WG6gjQxF|i;j6$I>tsdp2-2jVW1@5;yY}RHnROFR6mNge7qdQm@?Ww z&Oc6~N=V|@@bvZphY4qXo|_$WqwDwAZv%Nj+Jvh-l!Z(Xz%@9xg}w`5(dr}f2z)3@ zDfY%z{s`8#RCvfwf4|d$778q}+|>>)Z7|@awIf^pv;a48XQC`?w-KhnKCx*S>)ByD z9$E;_@8nu;&B2h_%e9N~CxhSA1%r5~Mem^Xq(cg&-?x!Xsu9t>1Y2HTaW18Q<7_Fl zU5G#_6$yqWA%?oR7o+{aM^hS*dEyXim8i!d6m)?lauU*9da~GR*ptQhn0fXGRO`WPru4X~H^D6rk9Sz3OyGMwHwAC^ z0SZ}Rn&lkdp||q^IrdXKvB*H?$&IV%53C5@9yo}*{IyCBes88HbZT6>`tTJzfk#?( z3_u}QmLenZ2+Xf6>KBjkxu`%is7&2pSrAeFX3N7=8E<2{M zZV;6VIhaIiB9$crq|&koExVEn3p;_zV$k1lwj_NEhCv16UIY1tM=pRTcL8eh+Wy6j z%&=>jCC%tC=2K7NS^}@|MaU9%y*P*E38xt2(-;CT0A=bwESrxlKk+q161c;u(lOaU zhN*>Tvr9CnY)k&@SQatBBm`HMUqy{&&%eBjs-`uskoaw~aadkQjqjf-rclY<*iLXC zYldWKf4pC^_~jS2`$_x}D{@+R@1YC_PIn#&e!&wiR4qYwDmZc?#9A(SD1}{ctW{LC z!M;7;Znp94r|ID5$k>#t)m7K=K9&~Ew+Y;77;ck?9x3PJ1 zkjr=#GxBX-vN}+mI)ztB&6i1q+D%lmnhBmSeD;Vzn_uCF_E?mRUVZjT#K=ZQ-T@&c zw^%s5?nM?h65SDxg-{e2hqxz(B7}MpMaDte`e=s$$X#2MCZJ@(PQoE z1|zFS#7QvPn&aX{V`T>IBDQ59j7E0nfoh^P(GUO13zBS{MMoQwnn~Z>VVzEkL^7N1 zPQ1(dP$u@>D~q+ubNm*_N%tj+m2J87z+a_x^EO|&6_1kQCpqGEc@C93gZ(?@NVBcW zf7)Oie3_-vX_@K+zf(iL!>Vccub3h?6?acVI{Pw>ecucDKZ*vbW!E2cqDBiGi05G94So9nI5Dp=SaY2&Y_TBN_D zB*{v$ZO5eKB5W)|7du@Wk`xTnmt_RLYjpHHsmx^3KKsx#Ff#tGj->xK4YOAOyHcfr zxtPn}U^7)EOY#{|E+y!)A6t1he}ucqDET-K&m%X;UqcDFS8?R^A`D1_?skLIQ(CXk zQQGL02^r72tdpFGK&|+IjZ0&5NUkuKDf@2xGy_q`>250x?#gbZL~w8|bh!GBMr#g7 zPm_eu)x$etXqCcTdU3a5zd(x<;dAuwNDih=Hoj zH3hWpkZqywCR!b%f4T*1{ielxP$atkdd=K(tvy#h=KpptPW=$Cz}nGBZ$F3D7&v7k zhCXcMJ+iUl@fz+)+8W2gRI64D7UG&%h) z&Ic7tTGiXi1=zbe;H3(b{(vppNYBs4%}$qdXMlwh#1^uWXh^eR5d|LII1<%9zeH!| zK6AMsL2aHqQLo!;57YLH9NrJ-uI|l3Wq45vqrl}@p?l-9>3O&;*@0%;jNJV+#%8UQ z?9H-pG9;}`4HA@BjuIyY_GxxIGcqMNyN@$z(hcj-g27d~@KaD$Y~N$1SmDVX zvLzJFf-j(Lv#EdW%kv1hbK1(uJ{;_1zzPdg0kyM6?=8I4+epLuo7A1#=V2A6T3E#( zsxb-})+^=Gk0AFsjo_h%{EW@8#I!4lfEqWZTd{6_p;%l@8BMpCLWluuQqEUA#7nD~q3=2XM9xCGx8taU zTx#?cN`dV&`UuaK*_y}LqM$WCw+}G4Y_lqwO#$i=hadz2>%scQP+*C{?L3X9J4Pe= zNgc;;8hN)ovyY+Nb)0vmKGE{@d)#{cKTyBZ&})N<T=?02?uzIWb1+s%^7S#VLXUa%Q?E|}n2Wt;Y=*U~QF`|{X z;6}W8xnwa*(1#XJd10QKmyOwTKF)UBRCWAY4=5(?E;V7la@ypq&OQ56Cb%ak> zCy37mR+he+!UUL#y8m8o0Lv=16K6v=}nd z&)@(Oowr_sz$BLR<;nj$O6u-PAQu94q~5~ZDPOdTgE)cXUuhYQ3Dt$ zUN8m*a>52L_n?3uvV*++g_O*Xz#<=oycEx7ZORWiav*@DTO`~DtK;v-3MI3!(Dv@# z709mwy)EoFt1h9uAN=cQMJo+$26o}T_j}v8Q0`p@)@B&=P31;~uDm7Z=^)AxG_B)7 z!RZmnB0JB8B(R$B%+T~X8s;?;rV)&ai~~;s4OePzVle~Jlaz>?tOnIAS&Y8gv=B_- z<-nWkz13?Gb>e^oaCH)^$cNH0C5Z@qE(+rDf{kL}*L8x2(L5K%_saIqE7r9!Ivoc< zwmK=#>RlC~={Xp#ryNVANfUglE=wp4-qE}zUrdYW5G=Ar0YzZ-p z%MsZcREGiVsiSsj+$!iN)K@(Q&o_Xb7!u@YBz2-f#KDtxMjz=0O z4kVKG{CED2<7hb*oo{3AZb$xPYiMMDm{QG<<&r%VKHP!FOniv%*^+QX6cjFt=GUUb z*-$CTN8OOYZo>{STwvNYT?e4G;8>`Y>)IkLd^MzrW>M3ykH|W|d*S{P22S3XA|)ne z?<^5GD^hMBoY#dY=m@vLnROL6nrWPb5v>KC#i156zz!T^?#I_dpQK($X`E@Qad9w82$#DN(G1H9?-^vE65LY9Fk*{9Aq@0@%6BJ;C`a_`FpN0q z(7P$!A*h+M#sP+mj!B5)XRDTf|4Xjdq0W5f#$*LIly11E(W3e(mkg5CljRW0^8v8z z#1|p~mORBKdV3e|;%tdQ@(*%)25uU@jNLs>ZnpOsBaos3ZrKlc6lD*N1ZxqW1f8dXDNL%%M~9rV*(wY!DduC|3J55 z{ApXalB3Uy!GAUu-4lZF$$kTXGX9_(f%3FM%L~*i=L@qMRl3(hfAY}TP_m2(=iKQC zKGOFQe^$?*XHu(b?zZU-70TUKr_BvuS5R4gH46{8sVTs*KI{P3@9tK!k2Wj@yXaVX zcS=+9>J3McqTT5zDPTHRb;HD?v;PS@jy|7_;T7D5^J8Iiq;~eUm4Rqj5jn$vl9xxf z^K#XqT4F+*KUd&P^f-_%08GM|8jZZ@HNkac$QKFz2(-r{13bqh9mTWc*#OKsQ@@;A zAbhgwua1NK+_yL_8@v5G$-FVY{8EWMCS%Z`hqV#Z(BjGL092^Eka4~p!;{?UZly@O z0ag*}m4DwLOSw0}O>@^jog+gkf9kHQ8HVZNGhw{$qx1Q%Ot2|wayk=MZ9PD;Z?*^C@HX%^fhzggk>o}I=Fa>LU2}^5234cf4Kud!z;8& z1JIssaT#mrx3Dn4E51)Hq^fuBLsQWCRc!X=n&m`GG$Gx&!!$U9)|hY^>@ts)xJ~OI84W`fOG7N~CM}dZ2YM3r{SJ!lw_v7OC^iXM z722XzI%JdeHtYOmV-475oWV?W+3Cu=6W6w_W*gWm&DXZW4xDi(r;YKCPV z!cw6&e23Y{vtT2{PUY@qOV<7=W#43)wxkm0S~F0IohQ#zoPD9>{r-SXTnBC8$|aT) z_|Piv|0AZXQup@d3`|yM4K5TvP^@LsBxY`Grfo{H0et4U{WKc<(j!&X&~^qWi5`n% zEey{mnw3q!j5py8-rK;DmH>>ESgZaOr8DVnY#~p-fir6$=}GrI?a6}?UX9__Gx~JJTTpOb zFCOsBst3g_*&h%4QTKtV+IZn;skn_sJh@>K60&t{9-+-+Eeo`JK~NgchO2XUri z@Ul1|?z1(T?faJBn0u{sJ=#rK+1iwOij)EvhgzpD63BjSaD>LQM zukSrNotE`+GKjan$;I1<=|FvK+r*&4Y=(A#LU+oNIw1G0U>J)hoLbP^Hj#H-4XJI3 zjC@Qk8waZHP!)^?E21fy?5~tMAcrfCxF*ZAgu0~7WzZm@H3_NWVlsua6Ky(Ly;J)gh==F^-@&tvrj z1t#K}8A)chnCEzm9rl@00)o;w#(8N$BZ7j{co-~mB};z;8WyMSM+$=^n2ek@2$lhl zp@8`{$_A<)V|xA?6xUUIQWj)>zkRw?ZJmU^^eHpaM>78645X{!Fd1Mn@G{a^Qw*Veh+|h@Fa@xF9D~d&=-cX57zT6*nh73Sv%H34 zlo{!qq%Pzl!_BNYJ;8g9K~5j$)%{t4&8q%rh_?ookM78%Iv}>IM>O%+a-u?&5_1h5cIxGk3 zgh|uSHVov14sBx}o))V{-Nbip7+5LBtw!KOV>p(_;W!dNvm7;^+#A7g7!~<1Eh| zmF8hn><>=@*P-g$??-21)xWAbmBgO9sSYd~>G;nNIF+Ht-1URrd}3CLxJ3-o!YznC zuW<1*)3c`MgI}}nJZu)uy-Gu|dz`NbZUuMBOWAez;|6-oCP+y*K&lv&BSV8(*T=FX zSr96m>VYGf1ZWU~QSgd6P6+DSi(n<_ ztsbgR^s#l59Se%3ub#e(+d5j*z>+-UAw*6yl34`6Gj6r4J`wJ~LP=<9f>>Aw-OSgI zcNm(r28kFSve?M}NBGPUCZp5@>6kl7kXrn6n|9mK75!k_GnzqBz&k`fsJl3_4Di)CktoBMU5oo(*`u4O2_U8DpxMi#b#nQve=*%x3_=!?K8S zG5(b+1=T#wv#amJ8qf~83&GJwy*G;~8@-!ELZWA+DL*biw;BdGn<6H? z$_&XKE5#)EvM0N(u+X@Xeff33xA7CmfYcm6ki1GdeGEHIrg7Brz{(s9$HKuRtgmUN zTh>J?NF^ITpv?t9r8!QX+8A`+nSdK{n(-zP>7=C0Mi<9&Eyt zo+{B7EPcpEzdiEq97Un&(ET)q~OnUgAP`HRb6MN)CoYpev zQ%ztRRlB=j17N9PxqZuvQnOc|kUWd-`C&X(h z1m&&=iY@%(7R)4>WgH|BF(#FSx=ruP9qA4sZsG)AFN6OiKpr>>E^M~D1s(2I5L^b* zB44wJp5&W<)=$V-46iP`{BvjwS%c_yuup{n(h|niM#kwSeiKQ+$m{bK) z#c~`?SU+adJSo^Si()E$qGTe=Ko=;)=yWXne{Owi2Z9$zm+?l={OKrcNH{T!nxSl2 z_1;4`yn&@eUnn6OrOF|6`h=|kRn9`(yfNTuMgrUXy$5+O%rVX^sMM^d$$+gwfpz2* zq@ynZs#L_#*EzWrA9Gp`je7^>uvyR z=1Cql_@O!`y)NlB7g1V)b7j5d3BM_49EFzri#vD&H&EUxcTA_cH{(<{*4*MiQCTQ> zTjgP0vCifkU%d+kB~1c$3SB9)rXamUReB4xbw{tYp2!i(nYBm)*uKcAX1YE{z@Ph@tM}-2gj6^>I-KdMaWn@IGr> zyKaE4F1x$gEZ~lk{{mLb2O#Ny^s$qmbn%lb1? zS7-B{4uXY1zvEK3i+o;=E}!%Npc$$Y2-5W4F3FOXB=*duwH0MJlFU-T5(}N(8cVT{ zEWbRH32tfsrqaL$wTDA6zhD~pXp{XK)2|rCV~h0@Y;9&ICfnK30sO02OFyiSE@_h5 zu(%t5HTipJd05GU0@xoBYoTMlWl(fP_WWs}e#Rcl!f&YZRT5-`O8}zQSe}}}su&op zZd^wXzAiTHnGA_61x$~auS4UoYiO3ro|Q8B@n(pM_KDq%(q{bw_;G1HHS|YW`WaJ) zEhmKLN>#u=`$*sp`d0I#FQe|}Ts^fGv2Myz%22Xg7-xA&VzGp94(4E(r(S0_f{|r$ zqI%noNUO(9&v_9Gg}IxB0wbU?$zS447s5EeGW(Tl$u>NUkkO|MfcbJO(LWdnNw!QD zX)h^_vrX+1DV4{=W$QE2VIHNBTk{HmSycI@Ph2@a>fUL9wwM-JC;tt<0`9IIO-B8y zg2Wi=Y#z&vRN^MKD3Q&>x%i;QfA7-EF&=1kqk&)*AtON^na=1v%@bONDZp{!X{#|C z{n-50894G>-d%B&-(@t`cS4d`gJi{HmnqoliZ5Oks{=OK@ORZ zX?p5&DJWL?=`&__*xHNQnfa0VRY=`3HunO0DgC%WK$?<~@uTx{%5MxE4JE{9|7e#fGFu$UtBZT3`9ea#by%tzK!b+UEv;Co&9> z$95bqWEx`P#4RunO|#tOFlq=8MtT5-Bm;ZUvq(kr$Q=X`f}`W)dil8pFaqe}Afci3 zZN(eq-~p8#uD<=&PU z{S%5-4)CIG2D1U&R0>QqOeU^4idcS5(34PDzoe0=DzzbItUd7 zDk&&a5ikdgOFPS{i#l?k+}*@Zq4e%ON$2r13eeW0U!@|bD)b8$G`7>Rl70-^y>ZY< zzZFj;xt_p#b)vn(XIqaJ)6^YimH3`=zzkE4G~16D4$;uP%v{&D64mX$Vr)9oJD-DD z`lLi zlE~_!<(2R{m~b+t3Xxn0OFD!9EB{V=h@hAfNjdV_6DhgFtkyb@vSZMV#|(vxF=74! zN7ja=6zqj4bHuL?tB!ay!{o8Fm+yDdaR@=~4gf!^FNX2A2(T}Sjgeuw-yu2u7)Z02gH@IZv2qlix{%!iuYL~6}-KPr5?rz z-II3l9>%2`Z!wL3G0L%-l~;kRBo@qf(z@O@p~rqBir09g!psuz9fbb&W1J;eGLL5o z0BV|&?4BQyOW$l=OvsTolK(i$Qea*EcGvn z2=^3I2vGM%4fRPv-kWo{7%+$ONS1aU3hsuM&-t2U@@ZKdsjprVZutMyj31E^?A>i}B) zytMy&`2WApqeYULv(MgZugkmMwU&5Yi`#E#iwv+}hi<`~7X-|=qc5~wg-8*?uO6xo z4_j36B{dNhmT}iAq4$_dVaF7}_ET;38b-)bc3Q+*3smG?*bhrGt>1%EgP*#0Gt2cN zyyxco{j*wFtI_XW$fAfEo7%2Kn%#Gz5-j5rFj?5V`|9`K*3lFFz$EJs`E2S zHoDI60jifBzkq>NHgAY}Q~r`Iznf&64th=ZdgSZk7lY1C@B>}#?PWKkc`CLmK@Fp**MpjK z9Q&X8h}?J$`RON^tse0ev3j^Bo#5NSmxiN_j;oG**S`}@6@3Nhwy^7j{HY{fwKx-} z??U(kl+?C7)edD8X#Vxce!R7oJ?69ChxX!oEAwEFk){r!_K;F>CYQcJMA`N@&G%!%dmAuYw;pL|JYqnc%JI;apmbOPT}7Ii zH?)s%T!(odJWK4TPok+qxmnUOfBp>|zvtKr9ru@`Sy5J5+DT}=#y<-e!gD%5H|B92 zo_)HGn9_ufYXn)$(K9J>{L2OJySbt*cRrm6u?-BgHRuo>mm3WhP3((=wjMxLEJi*i zzw^xi;(NHEbPtEWp&s+lmQuNV2XpJE4$lzooi~2dCulu$i-pERgn^##dI1NJMWvW- z?k4Vm^7S&zPaIzt5gweDe2pLH^o_&bNu<^wp5t=>0*>=}Ragm;aVaz$ibc%&XGQ)Z z5<*T;%VwtMu@z`+MN%Qw>7^TaHnRdoQB2JDQ+lBBk}1O@R_BWlPE^()NtNj3%e7>h zLMIQ40Rnex3>-))f6OY1$nJo6Jy!cH&@(J0Wj8A(AtV()G`BEq~DZI&PamVKp$*G91gqtr^aR{0`)4nphvZJoG-)U?S^XWq(;moHC3j+ z`>!ikLV=Ld%ME_F#Wv~52wDj~uVWu=d`A&h4*GNuS{@mTiFk(&H?+@KGzeM>|4d{V zvBa0$66MBX#z^y#z7P5GR>BjV#byi(X>uZTU7#7=X?L4;;7bvE7Z?Z5Al*Suo+`O3 z+g8G>oy687Yf+%R20-BJS|LLYA!I=H>%|JK^{ozpm%ni~ZF5SV4=hst9M-cTC8OO0kX=`88eFC+cC2h5Et-}`q=?p+#tI}v7 zTV`Fx9LxE{NHA2^ex_SHDY+?c!F9cGW*WRFCsGQ(v9{gb2_WY+eMgx>bf#?QnvU~B zNt2v@1s96hw`q=b2$Xuua*zshXUWg6XB$c(4vKqFCHy&-s#x_>DPu^YHq~rx9~Fw1 z*06*`IUUpmexpfq4&Fn(h0mZ2?if81tk3f~Aym*u8{Nl}M7|H$bNfj%Ech3W11 zF=6^G#-!Nu%Z<7gwjg}CPu-0!q!xW35>tuXuyP^_x z9dGJpRTBs<`AD#t*w9FDfW7RHjsBi^wr0Y~;JqGoK=wOfE=^ir#l3aZ*4Q}w$1u~Z zMN1%x4qiTVRUmrx4lVK5Ll2Vkb9X!I64Ynm{<3U=Wt=IidRjbC2my6DeB0Lch32?( z5Hf)_9G(B~aBMwTR?b_!*z*5{>-8_*R_#|59U5tbrrYt64=a-28(y|vQ8MfrK{!I~n6?2eAeFo0g% zFvkhOs;3Cq1;*-vF0wSp@nf{fyK9Kcw^W@=<}0DN^4%BupO9^XF}asK`o3uWjvtmV?Z+V}V6{MJb%;TYA_^!6 zOvnkG)!wOClFZ$|#vyH?iE@lQbUfS$3#8Sj`QB0SNyFcTCJoSJcQmyW{R+NBIjt;7 z`1nte%PM3N@TF#rzoygv_vC+-4C1wHNDv98f^#2u85HtH&z=dV4qmq1fu&jQ%G1^@&p0dtl5z5U-;YCs zcwE=xR@f%)-y-S9UDzE?d4K`r&H;Xu)+z#5CxfsBTXY3gcGMo(aSAj zG<8cPS*^*4aXr?9^E*)jZ^UAepbx7E8NP>5@=-*We7xWL&zz4CF6`EBfJqg0FtKnA z7T6%@i~K>47O_H+?-~cFhvoe&44p%xBu+ouP(?nsH}CLb5I-1&fHH`-cVPhKI59ay z+4kPT7*rc+FL*#Um{Ssb3R?h*Rw*{6Oj?w401}^)w>w$U@VPxqVzyC~EY!GS+eq7s z-IkCvyAI37pMib2Fm;2de#{?K5@3<$X=I{h0o#pa902S^#uh|Dm(FiF0Mwf~2T|>{ z%>o6|yw}7av{lz<@I0dn0R^-LVl?C#fQfJjCkww)6R6N~>ZIN5lp{ zg*i|2L70di{KY~7pX7X`S~*DsE6vUbD!@>lnx8cjeo?=m2X`J+NZ1&>i>OmQ$~5?7 z6DThY_}vHaiqKXcNS+-K2or)o`L7X2zU8~ARE9lhE#fmrQyV?yP6!5{LWIjZhp(cz zwG8cwDW7k|&kKGS7Nr$_Zj0itYuP~Q1K(h`_+Nc-b>kLVR~|0`Ja$bL*K_feK8zQ}}lL4gWZqFoJA z)D)2Bp*+}+f#DG5-^E9$?c@FcuyU-qi{S0z&I zO#ig*8=MJ3-6FE<-3k(o%dQ`|g$gF>6j=F3ROX@Q8@f=G4Q>FrTvhauJw5?FCMC<( zAB@w0^V?SJ3H44*N14&1pD61ga*Lc{X3Vg+RxofDQ999=33ZSmf#L(gxlB{N5A$u1 zeKb;tdj9(wt7q5)wxtG%8dMyNZDhE!_@2o^#b#TgJ8n|FHGYa$W)Gw+D1c zHzCe=B$%mce*jKdjCI2&bFvYEI3>|Q_pv6YC$flKFb|$H6O{d4$o+Mtx<#|!8U@Dq z)BJ>`bE0eybdI3Myf`65hK9)lvX8=S#Oy?%8O~;}ZXZ7i6m||P!@h1_cgZu*N&9Ag zd=)%_$KbhFwJ=!$7Utpd)|DE6>gFV{U@TvXlC8v-Nc7xE!_*7gu^04{x1?6i9YX zn5A&j%{z#40`6aiBwXV_&k(807WB8{@>v&IiHC1~7H{1Mqw7{77ynt1w2#!Vhuw&1 zC#^W~`cp((OJPz-A65aS?TN$T-BEfnhm#$D$>ibpf(3*rD!RfWDWU)wfky-*dF%z2 zrReP;Lw}=zkf#D>UaR|0MC`{BFh*LDyC*VV>Dt@A9D& zdo1P+QvC!n6;pSo{^DDZCj8ijvaaa4e6L z;$usSya6l0`BN+Y4ckn8CM`!`>(KR82v7+35eG`y=jsn?;b6ho8lhFyP_6_B2K7HW z9gj+E7tcsy3QjQ9o~i=EJHm$1-h%$(vPpEj6haME<3|{Tl^*dBa@nDi(6tryjl&JK z6vMZ<(Dx>YeE6L_;hjkH&@#9?@3-F2tPINhxUbDh7E?YZbvNs%!kfF zNh1|LQ<&nM^xQN(XTMQ>n7wZsNr-Pf$r(| zNDC?WrS4B?_b~M-oTEcRJV6|pB3%(6FX+n%$DhXaPTaU122KpE2B7my}ijoGjj5N&u0a0|2oK8`O8;(FfgL5`vt`dT6MrEZ&c*2rTLv zNKGPzo(I}Y40p9q;pwXh-W?IjUR$C7EFiE zW%g4Qs0@Ml;NW8&OWE#b?Ns_3-|yW=?0o=x4%MGN>@eOAgo;$$!JflQmR3X|hB|5X zpiKbeeD4FujMzuRzJ9W*(r^(VtRQ3tnaU94eoYl!NRF`(q^t7~?0<|^th^9n4s*D&=z)7*>Gwj|>~HyG{{+2k@?WuZakgs^8tacd2}!%D5zNPj{X(~3xW29x8k`1b*fV} zVv=q^_ou%Lo1Wwjm^O&PQ?a;)BcK;u>xb?)lc%d-t!`2BZT@6c&jX@5)OAHmk zmnP#epzlztGB=qes_iNU3WRGs=+_rT@oZr~z+LP@o{mReUWVwKLTex{(aRL>7+Jy9 zI1Z|rde+yl7cM-ec3>&9(fx81cc%>38@it7HYB!p3;e40P8_zW`S%A8+=>hvO1D>m zh+&g<@q6$0D!kS9VYl`>gvjW7R4W_ioB2E)xvRg!P@0M|hsjP>j7Xo~7tGV71#ONsx`sc z2qGrJiXfS1WR^y$So!xxq7<2g-+`@J6fT74{rjem9iUd!4s+!ayB!}nW@ZYcfzEsl zu#65^bZR1dP(IFzwJ!SoJnJSsO>%t)dqWLZ$C45RK9VZ^xtT%H6LiX%dYyIv{gzC)_&ndUbQ$q`*MLJYmYTru>DP;KoSf{q zdFiJTXkjbDsB9JaalL&F{L4IagW}$^Y(;MnK83iBmF0W%+*EfhC;sxQuTH>%D^w+M zIlnbMTw8XomZLRE#LX1x2M~Y+D&Jz|&I$M&ba_WZ51{HZ zyeoVVg>QtwX?ZX=JPOXD?=O2a&?#vM)n}xWv(q9P2SK6jNmXjd1$aWfe_HQhCxa2s%b^9@-O!DxeS!PtJ)Vp;*B)H0?LD6ggmSep! zlSVBl${!ffrH+=!?A=Jq`#bE(mi4XZ>KOmY*LePN5pBH$H3U?gAu!U@QPum5N(qu< zkW?=BteeHntPf%kAY50Zys4u-0G`|Cyu1Sl#lmD)1jUqKF;M!m6VP{E)E*vYNkr6Zp1}gU+IB8s%46_xV5qBD zbl^B;7`!Pr`3c*$achSS)k)_($p%Zon*I`gK!a6UZ!{^lKu(YA!m#)6Aka2=%Y1zstA&AiTokn$1_04l`M6dzFEv z)R-qeg?KGxG*^p`gu-h}f%wyda6fcfqub{U5hkYDUmhWMdCP$_4FHqwz`S8_5VSig zexfM2{fwu19OKDigFoZ2s|lMP3GOzkW#e#ts-KGW7;MbwP>Y);p#kZ#xo!8pY8ClS zG+YiyThCvkY|;7hlZEZ(@fbVSl-Mx82GkzRL|s)_YBfOmp;dP9%i+fGyXgZfnt+f~ zsam?A7{uONKCW{QAdX#2nZt7vs4oWR5{Xu6@>iWKyoPL#5LP|cztAYDuaG6((;s?&xZ!nv<4;o~eMGfxV9%?7Mv|9mpG@7F0^ z?LxoN{{)NW;QX_i4lENWE!^VSY`OHARx9TkMcsj-e3Zdsfo=sx*Hu1}w?Ed~ zhMSyAEvKsV*7JWPpBO`LmNo1q}-vQwIqNtXO~$i z=3IPW5I$+O)eI7Ej+#!OAjqN@1q#CY4gF=dT$slTv)%Q2H~LMv_Fs6EEzzD5jZ^^h zfqM3jn@{H+YjPUoBCAh~g3PL>oE9!~FkqoVjRexA+i{P(`Em=;u~J#|axi~+d<);X z2r^66PK})bmNE(#f~J|U>NFoxTC{;4`tdBnUk~>Wt~TGM1iU|V6xfZNk)#Gm-*~>} z;F2VC@?T~<__cwaXB0|}SOZ-P4TejNPaJ2EL0Ep(fLl+RB2i9hnIlpG#9Zd~8?Zg( zC3;Zoqx)>5apu`-+4bMBG#zxX%8&od7Da!5x9uT2*&?C?t)HoIaeE`-P-^=}z zasdDGtH9Wj1QDBr!-5`2?n_Se+wX_n#5C$oWMJYDwg}9z*f*C1Zagi)znp84t6RMQ zoerj9r_i^T&%(`K3k26$arUy!e%`1F&Bw-3^WlB_&PNAXo5~!Gb>pL=02a(Wg%&qJ zF31wy#7<-US_aJG5Str5T*&^v&BGb{n$RhwMtZo){S=S<*#FPASQq9L<<6z{3i$zx zU_ydgLK9-W-_pziA>JO_UIpq__%|3e#dPp_FtDrTdUSne6y~pzHlJ5or%~)CG!-x2 zMkfB+It@*ZwTA`J z_d9+*)t;uENtm`K{z>gqY_4INNiWSpKlm-Y^f^{u-grbe$FQ;T5t<0-<%}#-_n>Pv zb^KP;1&(QzYp}#6K>NmFaGI7J&ldh?42!BoGzWwP>(9D)g4b9N^U@gO(V^>z#ZBo= zTmSiAsjTV|iY@JCl>xN+4M>`@Jad7cmT5v?v$q-Al$5@}n%9wYu2I(+zKqx87vqqc zL?=&?gbj0Mnw3ZtIyORN_oHn74v{Q{;@ORqMp9a4w$D0gYb2mrRzVl&h}di+&s$8ASO@?nMeU^7&2zB z2(+N-s~ryV9T8$b_z&UvIg{VX^}K?>TI@wl{DGvj&PZKr_B)u^atShyPqOR6P6tOX ztfkDYRBS4_jlcL%YOyuHr@P=Uk;rL^oy{P_&G2;J^HX)T}pA$HrA%w0f_y;|- zjYe-roI#dT--FJ{3{qkvOw4lJiSbuh9V-YltBZ^)ikgja)~_3iGh92DP~-K-17s-F zo@3X!LR#CUg~4o!9hREcPY00Qr!}KWt(e;Enf%+*_9V1`gr^C1+jg7?)JO+jCZ@hu zpn&7kY^qqYen#OxAr^1lDQa>p%=ooYrbE*`wjmG`*J$O)ox5p?O_Y0=6aw5D%BgZ9B)%V{S)W>B_zDeSmqClj<1;?A;`(7oEd#@{rsvNgV~g25p8RG*Ym(bpTk;SL?G}rlgUi+G*pE?b zL(%yngn4CU$+M`l$bGVOSwn}BHd4nt1)OvXt1Nk(WHv9*StXhrt3}y79&;Y2dCY51 zz8$DwWm?Qy$D@~+yv%Mhr=v+ixlud9FJSC^8qhcpAm+jU8^y<`bgFY!5Pg<3te_(PAi%yMoHl84Ndn zdZgb))TV8Mz7N0bmlo6$ods`{l-3a5Nl2b?B)=qKs)rfIS55jct_sGTyX3((9rHjq zqZsf8cZjbzh+z0k?4hGD|z!X9d-`>od{Apycyuv z)Skq*8xbF-!mftPFp$bO)J9_xU5#9D^R6OCo=j1_1>|g^uY?8%36VX=Waf=tDOJKc z*#1B0z`*=k_1S&Mc(*v^JVTIyp^<8xVeluAxc0YY6lLHg zpbh{vKE~Iy9?S8Vce?iod00L+WN8@gkTHcPC0&2y0-Bfs=*Hq?9A{|O9;^QmC35^* zWQQ@E395V&vz=yI4LS`fsQ0!~ZSX0Rbg)CqRfPhJQ1dpzu|#}Q&5h3~C7cnsNUW5S zuoyl~pV83*QA62ApGlzVFCj325$*P1RwN4kF~Ne%4CAtgB{Io2ZhKn@?F|&gfu7_w zmRPi4jbHw?t15?17!V1g3!Rcxn%_g-2%<*^OXno%eSY;ONFFkrV~NVi4R%1%$35#- zYsr$0p{vJGC9bQzWH+OawdkS$hWhHqx!rYY9+y<239*hVb z#6dJ-^!~=xQpzGkqK@xC5iQsF?R@!7u5wE0bvTP%e)C<41_;<@j+`5*yF?;*^(vng z>>wy*du^je&y#~Q(Dwa<2zqr5yMTI+zUi?BvR;MCy^L;s=uKv0sCP6z1@rCGr?6`# zL6z~7UKS2Nj6HFdQjVyIYv%o%YNa1rj@9dI?H7Dda+GpA?yj^qp+_GuRDq(vYqXZJ zR1ThP238SG@4v@-4L#2Yk-ff`q=Osbg8ZS_9$uSof>};M{mV%6=f~|Vh|g&El&G*rqnHQ=v4!12T_T zHxY*r+)YP;nRACQ-M}faW@w2i^bc*brNE59j<9cd%mRJgv45x!Qa!MkdPy`=zmk2y z_y>?_O>XcT^-#QFlF74vnHd6wLXSUY)4qgUCsTb?t5ujP-O2LQx0|QuVlU`)wul_E z)EG^sS^dGNzGy+&3?HS4iT8NQ78I-pTuM*rj@iA37lZI#s8?W!7qOrV4xlsaa7l>j zN{pzt)?ASTdn0VmgByn?cJh09w*!Te1e4oI^)mOc=14$s$BiWNc6o@E4vri+fNuct z(b;Md13h!~lIxG)GIUO0#^VGJpvi7)#I0h8rJaYh-Xb!BWBI|c99VvuDk=Q0AA2}O zAN7WSH|xyXp}RT$)I&4}?kiSdv!sqvrXwEg2a?)LDt?C}ETvMz5yc;qoq)Idliz%+ zna);ZRlW|uG*QlJ_hTTr25c5Wh9O({7qpr~2~a%c;Ira04ZLH(FPLu%UTz7eP{Uw94 zXh~}9w_KFcA7Piu?&C-@ZMQgjc{x{^D$+udTZ33jHiHxh?op_lIrp_!YROIQv%PBT zNk{`0uen0lcbQ4ORJ*#`YW*+eEZ34ctyf=j72m#}oKCgm0=NSIF=7hUW9H$mypP7P zm11?^Nr(bJ519H0NIYh@tu*K0b~FAuJSUAV2^@#1Z$zCXbBP{M!%AwY*O81t)E2FO zLnKiVgn^X34Nw-gKO&}SKTs$AIsI0Y>4(AW@rJ=CD8}KTcaYSEw)(X|mp)3~gg^yh&~93(G;Kep@HQ>udTe5#vU9idK z@`!Men){_$)MvZh`21st{Q$@Z!CtaE+M8I*ImX7fgZp5>2aEk~97eP8X909?n%m$I zf6Djx@f z(Qpd$qC`#<;ouY6-PO{mz9fV2^tK7F_b3=#Ns<)>DeLuKg{18Jdj2+OzToG&orj+e zko~kgVZ1;sfrYaccjRFM{EoIOfL7yf<$i%PUHN!8QyRJ&OuetPUcnGk?8E3mc<%o& z?5WT)=r3&v{S7h7_tL74YFTaGLMTU{hMkT&=mPRbD+(=NnEQm6@|4|xdkm-IuC z?&nadCj-0eV7MIX1!)N@dcp#<$5Lx?9zxsh_wcbH_xu*x>oX*w+2hy{V8&_6pvdM~ zR4IT6XNU}7qh|B?;uTam{&7+x93Hl8JRSc1i2Au357@0>#hK`QLceFtuF~%mg&NTS ziYv__g%%g=dfqJ+U`k;|`&Mawtql4F2lgS${Cn2x*Xmb07)^d6cBXo8=Ru(Zk@WCU z^hl==H})2aB+&a1&f^47~h_GWi`AD}BD?PFIi^-})I@|1N25L$*{L4{+74-~p2;_DZosJWgqMbVcZ1uyKIBN&Zf#h4&?ZRuad-n z(Fr-k5m2nd@kpsbw`i7r?+vF?LK&a{QBDwMC1bL}i>c@cyx+4H&m*s>QNn`5Et1O^ z#K@*>0YCDu?&EZ_HXe3iYpvo$JZBH;FdZVl`w$*4fDB^MHj?9H;o2(rWALN^weu`7 zTya7CgYoE*i}0qBid~I1;logKL%f0Rw&CDF0MSIoCkVy-J~qZ0*hS>!Ux3ojLz5O7 z*b-<*%HvaePx&)Yf+!WeI`g3HiQ&CsqIDbPC3rLJbobz08i)_*(zVeWSJ|wKb-rVVj8T=s+ zDn|n+S(pXN3ZjI%xl-W)*I)FiT&}Hx{NYJSM0u$p9}Uc*l*k5;`QmQW2xQS*>DAIm z5Q|g1V?>b&SjCg_yR(Cozi03oMcUE5PsmD2_i~c?G9aC7^|*J2I1;m60CmJ}Ks*RMt_Gr9MJMwI576HGJT{5`@5(g_Kj^@k1L~by zHsCb%g?UN-bXyxU8R!yTYouU(j%o?j@Hq9QeFy;e2%aC@QA=_z-Mz@nA8a6JqW3)( z{qnEKc53_M|L(;BsGRROwKh27*Q|Es`^z=dK?05#dShz`N_^F+E-7?V%~J4XHb1xX zV3w?uC_wL)KizYM-%~h!p)%LT9$~ANXR)DYc%Ra~%v_L*pru&Y)ey)a%?@EJDSH&LV!C1g?)(aIo;#AZQ!(0^gWk$lMVQcDeSBu)l)$G>TLP z7Fo-nK_T4908k3(Q1EMz2v`FKJoD(I?VfF?asP7B&g>zBB&jZ;1%&+%?YN*X-IVzEyQq&|n#1|XQ!3V+|87-!OL7_R>gbD`0mK)1A~ zJRCkKcnGY}@=V#z9o8=x`$o9y$xCV7l|y?<^Bufsl8~g@tNYsV%KUFbK}Z+!c$3Lq z_^jxD5Y17GH=rkR4LZcsAI!$Iryq+UPK%Jy}9!B&JKpa-J3JZ;jCG`U8^{_iQXyyF)d`m3$t z1YH5^hJfmdAuh)deM7I#g|7om3L6CV(#RK=D8LcZcv4wz`$?^AXmJabTegh@fSloX$B4-nVXMAo-&;&u9(GK(cX}`p^qsyypKF^G* zOU&quKjNC0-4JZkdBOML!|p3A2Ng&I0Ai3`r5CL~QKv_G9!j7TH*Xfp*rmZ4o2)aT zxL|h_$FDjZctbs@>k%#e0i8hKGVGi1N~gW1cjKI@x2|Q;8_@0}<1Hs7I};%GbG2tDOtprcSdabaf3S zf%?Dyi@?B)_hypFmjjYhZZa?R@_hQ;QY;U7QHw0Y47NYVb znmqu~liWbxaE(qi1`HbtP$OWV|AV`tJ|OSwONjPgVd~H2O`6V&l&dDuYqjKU`|XGE z;V`Q|gw~7+uAb%@dZK;GuyebHMw@E0X{$>`%CBi#0;w&%qwSyvJu_=`sPLN)i#>?z%<{am zMd@%~H4rDRo&Wz0xf!ONWai=Kpi|K=3GhVPXss&cr<2>$Vc8aa%T^~qAn{ZwV6+fF z2eRHchGqKj!peR?+l(!eL>orS8U^(B@7u1$e(UOHW@%m&EO zlc88)ni$xo=ZPtBWbH@HT@FS4&P=M-wls0$`_$>|4R@-5IuSZA2molf#FCTUk-5FlQGH?ygquNs>j+ZP%KzkT=n>}I0f@kYV#7^!6 zy4bN=l;okn1h0A|n8?zka7zSCw{X1Yb7J3NI!Yic>x52cg|wFpSSSDv2%y$c1y~R< zIVrr{)-piur((#xs-ae}^gghh0!`DSRVzZdf~LF^@L{%Z;8#P)u+4H#cp92i1A?;3 z;Et$Mi33OIWe+X_&*WaJP4j&g>oCB+)DmvVuk_kL-8+VQ%u{epY~Ds)DID{gVNYSd z;EN+1(eq#H9Mw7*_5x{pboL;#bHBmC1nl}cYT*k;fKh|R zF9!V6k0RkASbS9gz}Q754v4{1Q~)o~B^JxH6?;xGc$nO!Zl67~k1&w|%45#G&{0V4 zfV`ukxK9WbAo&$r+aIKh{aDLpACm28Fe!Lb>;PqcM|}iSkN*xXA;-2Rp_K@Fw*$}s zB#u6Zo{&1l5J382WQb0dK{KdlPNi$&1fC>UQPu9Z6P-dC@Sd$T7F~-8OARJFq8RN0 z%hr#<$`v&2awK0)X^Ctedz`1sK|@AXgtb~e83Jbk?M)`_)cUY<*tT8{Iz~8Pk2*;B zZ907z8`Pbj?ZUnf`E`&s91MOVHBBClN6`Pcjhr>fe^Em2{SkAKo!-MT9^8R-`0j*l z?Pez;?5N7HI3ikj1Z0g}w4lhSRUB%`lltCsuT#^)t?kXc+Yd<*L3Ib$l3jY2zqHjt z0!2Y6z&S(e+ebwMl$bPp87UB-sezxrCq<6R-AD3QjgyC4dBTP1_^ibCLwa!Y^F=}3 z%Fm65^XLWPiz14&knUqI!3|FNt*{*e!?Xy;@!GTYf*_k^Zn;FO1{>K|WPG6PnlK&( zjwOoXuoO5lHl0sf>;Se7_!;;TgPTzoPQ04NhrKbl2OciwbudpTzgWx>8V+rNBmX(= zLp38lEzp92K-01d7_b3V1S}9(kMt`5kPQNH8BpATmL$EvvIv$ArS9u*pHHV~Qr2vS z1eIfT%%X=9KoJQ~`FQ4aKG6{A!FH_2#muk6Ga#y$!i#yNmAxrwOtu z0sU4m8)C=qfr!xw6DAK!w+c8A-!gCad~YA26px6q9<%}Y84V2pAZPcUQaj=@+?<}| zJ%TO*CSekLTkAzYNmc^+iM*m-JUm6rdsejBgurZ^rXJ<&FCrR3mdAOB%`wCL;B_GI zwEXII)H)59!2QN_4zXj%ucW~}c~^@Eo)u+$Bc(8`Rh8k&enQ=Gpw{v$Y6c-0MC9uW zmv7#W3f<*eLeGMV;E0vTNVcm7wC?PR=eN#SfVe{!OL*FGpj6J(UUhIUaIR8A^u~LL zH;Q5)&FLByZ-+jy+Xp>}fX7nmU5~HuA@9_-hT!m5dI~vW23(agUFdK_1t=1Pi1;e$ z+BA4O=VRFlr0PJML@S<2B|lvRG}u}^ab?RgZlfzp6U!`%h*eq&H=|5F$D+XxSOvR; z+4%&WYvm?N`y!r)_KMgbku?rKsyW`zpXRH~)Vo+L!13lt9G7UhUKrw&fXWE8yEs^e8cH$vg1Rn z;>1ir-xmoJjk|KU@OR*RKTIXh^X%(H$2_toTw-o{@ZUFjP!du>3$k@kG^xlBfDQP( zC8i{WOBbWE6!`_Yj1DWL8G)6~n>vsuJF@{uiCd9N!C2r))*Aq+3Y!}q5v*MESIuk@-maa6t2{F zWMR01bosbHAHGYh$dMB5^8r}6SvDut_FMtq?rh-+C!AuKYv^hcy@(PrFo2~xfkc@4 z0)69NlnyrdP&=ZYW1ekk_TW>7q^1j}1WfoUF>$s&z_H2oa2u6+RQEfPtm0K*Whg$I z(t}j4*g;lzcJ50v?MI?eaLr0>c#EBP)rSRt$8GTBZLyHz$*as}PWc&Br=g2}S?G53 zi$tR^)d@)Zn+g^PuG(s$2*nct=zh7#1) zLII42Xj<<1A;)%0Si!Xq5u^Rd4Ah`zT@n1+u!WR<163Qdx`^c^Ch&Y-Sgw^BrC`d` z1!F2g6(j3JE_iYy?m2fck;As8(l(Lk^d7_Cl+;oEU&o+xK*=OsF~!)fILSkB7|`Yw zoh^_6L>jW;7>`3I`6HnET#RgF^j)pE4d9oIu@Czc0yZVS8f(j_W*VfHTBbglaPtz@3@{wGjd< zSQQvQMA@GJF@!+Nx}ZZ#lEKzC{Sf-v)CaxH!W3P$nx&(hUFh#I-5R8u&1hGJ?*jBL zpf%8*2qn;gHu4>`0}0iHD*@5cJ&Y~HENo;>TuT`d6j#A~G_DDU8J)HPMO=!F$EEqH z76CC*RgzXyRY^u)xT59^s^^)E&!QYp#v@^4TWDYTrZHFHr^@ zoMvuBdXden#rQ`Sxs!?OLr56cD%w%1PvfGFDyx>T8Yklukmwc~@6nG+pfl;z|9%)~ zh3qh2Sv2A=xZLaE|B$wB0+>6RCOG)nREB>=#&hbT1_J|dqK#?LJMhZRJam)sG;cX+ zZ5<>_koEMQr!l3_cxy4MvYcii)zD9Pxp`7k;R8KDZcp*E3bDY^s!ENpx%W71fA z9;+7RY^-V}7B>QP8mf`Y^I!SDAS%^v8Y`}$lGFIvG}@WMN;9bG0=e&NhWwrpL<>+{ zI@?7f8P0albd2j6OHR%iMV;L0tv;V!&N)=3b2iyMzo#uZvPR_zKluYWtamqHb=C}8 z^y@Ufl-&WA9H+nYm_3TkV^rU@lgh*oc*2Gtrnm%knNP6Yo!m_au$Gwm5ADou^7p7p zxJv|YVqDtj8JNgSK#^q0GkO7PsL$^tP{F0DfM%FL-_1%b{4_Th(i+Dl6|funLOzbm zK{lw4ZskY`5IN~zQ4-3#;R~wpFCx9IO>mHr{gcL=%DwmEpg>t)b2-|By}^xVxziV! z$)d*hH0fB5w+d=4d_T9H)3s@W3R9@lCHmv1XhrDB=Xn|0Toud_Lz(0z;?$_6{S2VbCS~*!q_*qX4 z)2>n48Th_uG+V6VmnxeOj>c$az7#~B7Vv?DhJeV?$Bw2}PQ6dCz#?BMqo+(2A!;F6 zMs4WAh;<;mIRnJEzlxX|AYKn=>uFwvEd@mhwpxySB1UMv!E=UnjJvA^nE5saehONE+I|0}4YM$a5O8;3iu4FMZ@`2NS#zdK0 zu2qh|O*HkBTuzCSTMtmoG1vuG7RT{xO?#T=C^n$dLflMM;oHP?L0%I!FSv?+#mbNp zf~s$9buKdM9rX$;?|em=5fRIbp$tyA-s11l{F*%2gm37c-VTH`wMYJuK2I-;KThMAC^7VnOgocbBTt2&Fao2tNNQHsQCMxw7K1+vK+hf-9D%9DG-*HcQ79{&7FbDe}I<`^$} zKhl~Y*RLX$+)CZT)>LCy#ERF^okI#S#JgyMw3O|QzH>_hWlUG%*S^&MBn_HfG6Jbb zpE~&?c#co=qygzZEC8cF*-K8j%sG&H%zeBxZ8k5x2hPQAk=$i?c=)>%KvPpy539Fg zL5g)-CBNI})sy2nALKm-;7Co_x=9-ZJ<3Wu&|FqxE@)>)GgL%edp^iXQyFs1<^}0z#lLKgT{+joYk6>A z!mytYT|#c+Pya?ZtRx`tNBFp`2N+WvJqg3mU?7(S$D{3a=2u1?+p_rk;0wsRS8{hD zp%S6)mdsoq5YAFYA=JoxIZf0yWcF$arVa~4gwrlcV`HSX_ZcU`tA>AP?QCddBe=U~ z|Bv^8R>m(g9j?!(gd^@ZEZWWiA?h=-d`$bo;6TM@SMw>0Dbx`CS#7{;vavi2Hq^!nuRkzT%UVb7-*Xhx~7o1vH_OkUP z`@$t??7S;39EkjqCAR&nSZq6RzLy!9X#mucKMd0N6wTJ7tXz|Q6gDe)+|B}Z>l1g5 zOW^_G4+)omJ~s!ifzl0mP&Zy6J{Dt}=0#9l<&+` ziiq*#PmT5dVv-Dboa=PV{LL6rJIzao z|J*#kviU3m7o+xbx2%M*l9t;p?AoiZ64DB7YS7LxRumo5TI3lv5+0a*L zLY8sJLAC`te?t|;v%y>greeCwC=Yj*LaasH`141Ct+xvKiYaB_?j2>+oAMl_Y}gl8 zbmmtj?#zw?D$!7)H7FIWg1rNJD*r`o$4W*+sMfZ5!LT#^s}Fc$s(BA9hAT?Gz+%Oc zuitH;hMJe}Rbg$o;`eLN7#XErPTm>IZGK&VMfLSYd^M&oG%o=}Tk`iuf{D8CZ(_M3 zs0HNKotXa(`%Ei6IK4pUA^}Ta?7E!=(%uM8aKszo7+-D83-2$1&^yyFYt>iJ{U?=s zG}R8cV~j7SkaO~_udE%B2k%9wHe4}Fd=czD1WCzKVKT`4w`b1^x~k{@;pkf6o2at) zxp!ugNt(9P2cP^d|;35ILitiwz zxUL!$6<1fMyjcqd7oQ*mWCc;zw4kCQ`~ODww=Hdx$$gxA?m6H2&N+0Ahc*QO(r?_q zzD9w$GU#WM#(86<`*w#gh3rvhObJsveaLWXp-EezwXFcB)0ycDLD7J|fsY)*?sKY^ z_$hDz2+kii48C!*Veni$gczvLG$_u#UPuIm3Y9=+LdVzQb$%4D>&jEPBt+OlcF?2? zDcb5W@LU{WdRDWq$caPD1NfnvT5ph0C!`49)@iK+>7?I*(j#?A92=~Id7V$LyucKI zl~<9#aJ?F>~Owx$dXW1ZHTwSpp(;7Zh z^%brcKf|N+;!d~1BAjvAhhy3#Ur2mS(Lb89)PSO02uN*xcFj1k3p9dc{pCY9feVBz^y_1J@bHFi_1(m&3rT!hVwSY#8HY~rTny76V zG3?o-S7^%mJuD7GWrIQgtWlU)mw{|Cb`Fylf6<2;zy~C*K><*zj%#-HR?l}Zu{QB} znnAS333+*>s?;IRpQ7VjVm+!GC0%KSjUd_Ks0!MY?(d<}!K(`;a6yiVhO!+-`C3=3 zxEU1}!F(Y@3dG~2K}|-ghW45bgjca|uBfzp5K@7XoqSf=AErw-<=C4^)Ghdm@eC~r zflcB>l#gdMt_`)1R-S{mcHwtZ8d$4F)V~V5>)xK@*u4Bd0U#bBQMq+d3XKB(`s&l! zZcEHHG~?wcHIJ zaUbHX&S4(nUaz8cs3qJ=xX-)~QgJ)WMH_(0?NC~NQ%h?g*vAwGbR2h!KFy;Vp&!cC z8i7-vp$n)9aKPNVF4d1iSQ1qd>Q82@)7Ka;*gS@}#$s#W6?1+HQ%|1IdUX0wu2h1? z$7>`hyz?Em^?2F~=?yMW%PD z<5Y{%;j5_xpNKRZWBI$_Rq@S^lhqOE-tZf>SIJ%|8eRo$33&4ocEt7G zV8i!Swr4Nu(Ci$*1N3Txq;^nK z-cMVFL<~#%NeLTi&r12q^erWv9Ws2mz=y;P$QjbQ2RquipRUBt2bzmf`KgUYaWjW)Cf0hO=SxlO#i) zEm11;&$wUct|v4pv>pXlcinu9Lew;9XBLB?b66i!-qBNv$$^1k=`?gvXn}Z@C5!|n zW_|Wi4f>gSfo6aJls;KA*}Jzn2I%|eTenDJfinYnnpK3d7U)E~WdbLum1-~0DZ_`w zQwQPNi9sG_y z?;ALQ9<%uoU5M0oJk7Cq2rGi-f(VIZqV9zzUCh)bc!hP+FeW<^-Q53XCgI>_uGO}Z zCIZ`xzTB?ZSM(TNxhGl4X{ML`=!TD1ZeQ^Phep1x2(_pBsx-v;&|>ob=tcgseT+NH zypbi)*!=!CKQg*??}$r7umOrX=hR>an+6>&1}A%RGf-(h%GYfU3|Ntb6h`_KHiH$Y zx8S_1Nf*55mQR6%=%(4v=8hX$!1_)2{Q_t_75I`NvrE{)C=2aL`ch7jS%L(*PMuf=^oqD;?p>r;dstidF#%|Mx=-pXNBhQ)F)qK8k^*Gbt$h z@W}0*iUOyaGh!8J=Fm*^VKNA(fZ1hAFs8V$>@T;h)?VRO-MQZCnoC^eQ^GrYc^t|G z?Q}_esL4I?3O${7cG_)JkDF)`WdV`fC8!L!7K3*)E`iO!QY3Sen@%<-V0Xi~G2-*@ z(Q`(3fUs|IIUlo;nI;L!e4}!UqbOSk%$)tgy)~rZQ6_G8fi}sL1W$ju&NB`Uc3G=6%-iZ zW4c}ZTyiIF>j+|LxP*)bj36%{C@m=KzPlaaa9=OK7JBSTd~~jv?q||SVT4L+q@s*M ziqmD?>o3N)z;0hG*P)6IoiNkG_e9d-H+`N5Dol4nfnv9EytZ}n=w^=-ZER4223;1G zmb%$U2McS6SDr6H%kd`6X9N7#yMV#KU6?_qgo*7<4Pgx*>kz5z_bWLTG_a3QdMW{!zyvGg11$AK zG_bqDZ{^pJ>}7wFx{-^TwhpiCbKfDF84x=ghw|$61&h=(ne41T#t8rGLhjhlegtgX zBKJuSbEJu-ilhtitub7aXACG#Ru--teV}|=JITwS_~BDm#3&dcu53D+kyrPLr^f`6 zqe=LBzh^^0MMbQtilIG|^y;OGp4aI$vh6)P*Roj65>-jm=brs%j8Ii)83}B6KV{}$ zpPAOe6zZ=?<+HAbi%@M8&K`)7MZ3yV(t{)W1A^5av#^+BcS{@){D5Uz=``-+66wLu zqtB-9(W@)aTM+fAPA?&Lt~t+2caYFV?a)gC2Vgr?bQFyQnTTD0sNFKo51ZYZ>SceL zqR}oz3W|{W-F*;!LOUT_1JRuqPLRZ<%C={y0ca1@wJMHi-OA}uj|%D+Y#{j`8%BV1-Gfi>r0*L{OK-WALs+bSF z4Ot~LCO|_nwC}T|{mBkjr+QSCAj-I{FQrISbyms{R-SG3qxkAxlw~i9XGzYw9(`y& z#1VzCIU7&0Ce(X~E00vAJW)@7{HF!P>Ab9TUaE}R2aMi~NftbrcK=fG$DQH2g3xKu zq`(ou8t}VTs)Ru*0$=`79?wWr4aJ0Es&2(`^^sNseb^U7)ExWZhffvalpp#@0BybL z5aGR5yYO0~^=I=|LyB;ybi6vdol&&w(c$>FHev?qWNLxVh{qD5N$>1~50+HqnNG-s zOlSYGr51E>I)yL&&c<=YnH7nmAbg?AznM!h@?viUiFw0OmTMH4AyCBM5&hl0Ux$X3 zYg3nl(H14{;IoG!p-b&>7zPnUf=M^|uD%@ypQ<_$M72s{ue-|cq!7gVI{@Vvd`H3I zj)j}?BqLgtlI~@(>j@^gM34&SqC^(9La*Q!V-MOe(`4|UDcB8W1>Vj*mTPz~rgR^? zk1`_)!Z$`rlDMCJnHcz)u?Y5=FxnnVm>~3%7!H^R^^xH$bnRGyVP?%#_*%ICAPkCW ztj&w*E9z7)vmV^y0V|71j1lXIcwCVU1?+t}ezBLRzHaH$7$cD+f#(;&aEee0V)~ot zCTGwi-B4*}MG^ynocxao0tGki&17ge09llIcpyUo7@|!h6m+Fox@R@!1Q!>-azh9z zANaub<0#$dZz#sc_ZhPv=&$QOrCkgOyb;$q$5HPep9D5j-b1ti0_^&RG~@*!?p!nt za8aJApb1<~1#5QXV-N&EJq!%SOt%9;4 zBMEe@uDk+5SKkr-$~0VbVqZ&QO-2-lMl4p#cskogph;0}U?_GL^IU-83G6R^Dyv9C z#LJ~GaXm>jc%OZUk~+sGhj9i0^8Muo>K+iu4`LF#lc!S<_%RZmiXQmh!29#<11Zq$ zTp*mOWFZw-a+l9)8NIM@H32-dsZCnOU8E8119`-YZ zLooD`oA7Aug4$Yz0e%eZ7i)OX!8Ea%7-3nN2p3Yjs_JAZgVPF;K{U|=l0)^^T(rZb z={8Vg0p>x}Atq?Hx0U0tq)K_39)$x7!=XW8fCB^8Lj>0Wa@pfuT|*T~PEiP%EMz7I zj1p$n82+qw0l^=4&Ang12+uEL@Y$1CB~^Pqt5qQu*r)lyhCbvF|2NB(J6+kchjxxR zrd5k@94dcQQ6(hOQZ-yGylxd$*9|%a!cLmMkR8Rje&iM4zgWyz92^;1Le)Dk&Q4zGVBu16H zkoN=2z1Rp{1^X_I`m8jcG{JR%1=phXZ-Il_(+*gN$jf9OkZe1@IyFy^?SqR8g2l{R zs<`;@QrlBfJ8lpw4SbB?_wFB_f_)YAB3B?qeuZ-sxOO4-SExyJhvJfu)}aBckxE1$ zRwE`dXFc#FUL)ZEy|R)q2wv`B>PO}EWNpMwG&?xkSID_!DHG5y5&i2V7h{?0H0Sqb zL4kb;W%I2TAqm0diISx~Hy`u==wGXG`n3yq_)Cv{h7d`VUw-wB7|iUW!syVu5y@*8 zSB!yECm>T6Lb9!>aXE9Ahh&0$LL09fBvJ z-N&+0h@B;yq1cHqr0$XSM(MwYo~B6LTyD+_l!&;6SHEk6;aR^&vcM zZu+!iE)HPNHwoIQFfvaFTINSzZ%@oVw1nYh(IrV3`k2#kNEwxlrs^hgvJkbCec^Go zX|ZEV77}WnkC?tqbG+-;?a;$i{M0vQd;#L1E#N?nn8v=)VgFjxof4VvK#?K5g>0y+ zF$F!?X_kMO1no6=uH)m8`T;@cC6MyEbCsm|7ZJx9OHMznP_LkZO5vIzdJT8LWnQ{NFVF4ofH`jM`Qgc4)vig+s0=^{*BvF=6a`A5HXSM%N)=_L5Q%Q{ z;M0G&sfZ-hD?yPXcwF&AOCJ10FL|2vBecJmH83E?FbPU*K!{v}4KgEDxGHHkvXSUG zBvjHDXgSF;7OlBaX%zS_+lPw^;BgS!oVsVV!lqs*OT%!iv0}RYY1`9RQD_tHZT&fo zT}wGggDN#rdyRqND)=JQQgOC(@Y2Z5y z;uA&teQ7_gQxB{d$E{-;#J{oCO~&_6OqO>dL*fm24atW6b(Kkfw>43%frfZh)Z9cU z{;D!?Zn_GdE<;q)o=yvQ-tOg}m~0aI@p3~T!wnH9Ty$bjGW4vo3+9j|{-N8u8xh+V z-)UKtn4hcWhe_-HbNa8VGggvko20-t0A7La+%Y8Bi5Zjz z)rngC_VqE}0$W=S7Dm*)g0z+BZ=4ghA*g%<0) zfF%*CEX0LQY}O=KO~?OnvBKGU^WmtNV+aA{a-QQR7HNT3c#V-B=bUBqbcT&O8B*K2 zJL!^ zQTHx_g`}sb5DsK-8U}7w+AM$#mGN}3IsrBE;&HEp3VP_R73>=iG#rKQ@s4m@4=+UR zZ@g3YB#N(kC>)?J-)p$+bu7aLQd>V2`9E1{bD%?P%y;N94I#Mu-MLUfhcElQvwoS^ z^8C%nhj<}1XV$uVpI(4MLRlqJA(--_e@&br_pWPIK1rn4M)?B>dy0Bw2z9p8kmF*u zqfx;{PLTv6T4ZoU8gW^W(gO4Rp=I$~hP0s;l=q1MJR=wzvjR%HkjYGL>7fkGHhO#s z7-Z)C9ngoi)>EHMz*}sa%T2i~(^42uHctm8BqbwNC{loDEwKc;nxv}^C1XElriXMD zbTkw82(!V~6%AIDar|^4_yuGPbIqLM74H|}wlZxUFENEviEkQ8k!=7Aev^9{;Cv#g z4SNK~A8rk_6jUE*!}x8te;}^oi`u}WlIppZqh;LWhcAgF@TV4d6%_V?1z|e@D)Gw- zI_0~BLvZRz(5#DUH5$NF z!C~(~G!ah#(1-s^Q{WY3(w?1(JqT@Ih-+cGLRJ#8cOZ`lO zZ+?lY^Xb7j9_CO__K;7ZiNG{r3Jw>p3c8g@vHvIxwChoI1%+WRkw^I`HhU-LPeXo2 z1@cq8c+nz!Izsx7;FZ`@$U;w!B+SB7=gQR&CX*Otl^rIjaE-YTMfEEnDc!@A^i&uhl{^uNW8xD|4}>E@`I)XTRJXzg&0rCfMODyH5+WQ!u0P1Zz3H5t z46PVu1D?UqzhHLW-;dz;OWu02AFX5&++%Q|uv{sKT9m3J77(6Zb~!*K;M$gRGhL~b z!~09J$;gTZ0SW$kBE!K)=PquX1;cI+!=NIdYxSdnZiTBz4P*y3hu>r+*6M$-BM#=S zsMk_~?RzBuB@%JAir7BjD2M2X>?bB{u~_l)IJT%2i-vqzfE}6mKq57;8t*NlXLP~^ z$7wbvndM7ts31xrslEQA#8JDZ&G`k+M zQ|6f>P|6>x$8&K9rw!u7=3+9)hhBGOBE zXsE6czlEX_U?nnT7Y)~%66A-k0xo!5V3}&-F!{!<<1$7EUzv)a7yp5s^; zCZUa~u33Z|k!fl+vmbYcHu7$Eq7U0i87to20_h1H&CJGx*Y|JbHCZr?wy`kat=VCT zYGfA4r7p-sVGo-pjjl%?ArwDMpHEi%pI!*3L=9Y5Cxb~YDXYu@$~i3r!va2OA_?=A z%1DD{gw+2cvMQ{>K}e1aP&<^wI4MY*N|Bue*{`X_l$bB8FiL+jN7L*wJNE|`FXa~d z95&d;=&=>C549sE;i=Y72EZG^#82Rmci!}MBc!MxyHGK#qML>i20oHMoQ7aeT^K?3 zdAUXjW)1kTeU_%mu(>1PH6vf&PI$Sr9WVV8Y$kL>PV)b|gsjsGSZEAsD)bOyg%T>G z`i6xBi~y-b`1Ui$Tr|4P-pZ;oNOJ%UK8~#H0}m<`ElwK|8zzW^NQPdEr*LiRb7tX}0xkzw?sZ5XdsSyHZ za~>Fw@NciQBiJnTPN}_+KGC|fxmVROi)J_iU^hS1kd_vlX^zR}4qb%Udn67^2?w*# zaPWyP5>vFx_QF1DjYG?zQNUb;{YqSS&qujfczaM>e@v6_zxAX4TxQQ04kcq>O6y;y zYNS}GD|Nn0n}tuHiqMPtU*T9TG-=rtBVPvJa}+Wd;>(#>$CpvLcIJ{Xv~pMpK7j>x zyW+pwK^9ONs-==ciArJ}*tq6z__K=QxSKrw1__^aBbH|sOkUeyb9H+~DblTNRCN8L za^=hP+{6Z4ytM(rQdcs%8^uYeq$2h*wv#oX3t%WH&AVB8Q0+K;tYA9*jKO zx`~T$C{AT^{0SUkRs8(NE6&yJytybQQ$C#_J0l5QOSp#Gq7^`!Z(@t!@_80Le?)@O zA-g@@Sy0U?pB_J2jSV^ctuKzNG~>nD3L5+r0o2GzEv9lFFB_}bU}A0riGyuu)itwH z5PM+8MgOE&Hx}m+)F?KOz)RXn)*?z24EgGbxXgvDmO%_JeF`Q(;Jn4?M|MFq$afQX ztpl?u0ATJZCf6RjadQ?;&V16Zjrqn{NmX8dh$JQdX2_GDt&VlDcy%4d6!7Lz1}bkF!t?nVW28AJY{8&+5hGK zWZPzE)bjsR*ZQnt-a8f4ke_q-Lm5HXKRJVbtm1#6Y$UJ&uqd`x36Sd{F z6BP9INQYk0)1Vn+J9*oEZ{t*CED3Y`6gZO+1CnsSp;FLG@)NAvG@El&tf;fnvl!`# zqu!3%Ak*~=FUV!-!q{en67(S4r;-%3M|45wxhdlG%qQl9a>zR#9$IU59l&w&Cf9pYvYje)4;gmOFSjIA1$SD* z79{>C!B2v9sx%3O)Nzh|yEg_+i?er6SZZul??Qgg^Ovt)t67zEv~qoMeT9Y~<%ULTJD=6G6Vb?4t%p}6gTWBgM|K}STte^bTVS8w z?maB|R#M}NK7~_46P83kUatwwqH(wy}RtF{~52w2p{4z^X) zgvV-V97dQ`g;xQ{)W)A6L%~|vRO@VDv#7p$=vMwee>cExhgvRBI0JcS_MBGtWyFpw z!rk*9Z+}ph%G(~2V>NNZomcqq5XTaWlsw~m?Nx=@P|J0%%!g-Yg9ka#7uPz&g*c@{ zcdJ6J`W)bRP!U4U@Clc`-A(rC9z|`Vq(?&kQ*1fUG2fe9(E6Ebvk$7T;TWaP-_ zJ+@xO$NJ>LuFBx8f$~|0`t;*hwr-K6*Ln8>O5Otfz)EuI2Kl2GR+c5`<`f*GHqK_645a-cb~$yx+gKf}WLwH!IiS-vxst z_QMK^{aZDdj`>4<6}mY8imaAio(-=eGQjuqU?u1lne?lHJn=Lu0xV5pNvo$FZK4hQg+{M=&|W#T-1OUAsC(x#M1AXdIo~x)bDUR`PI`u0rMx z7Va;LI{$nz2;A?*GUOC)MDCjZqOrF`0^)vz2%Lbv%_|J6(hb5WG(3^t;_*fOnn(XP_)#n8ILHmrcx)AH6Uxb`GG6Mg3W zRB4Ek#(<($Rn&P0;XQJ|>JoFMPq6SWS>4df$yV?vU?jjpWm}wunMjK3)}{^=_)Br^gDhbc>jg|m%wrY!qViZt9c zj}q*DQ=}A3S;Sv&*n&TjgJMfOs`M6IZ`d;~N#NJK?bpXJ*Zid|2p<*z$c@57>Uy}N z%#9VogLCnJfryfcjnyRNf@hyYp$f#0=^9$&QgQS_l>=h}y^0Iq{xb*fF!Mj`i*F@O z7%a|$Fq2@2p3mlDyfhMphWq8%2i6aW1CM&tJstr2T)(uab6)uW;2BmSX&JBl^tKYr zsRC`$S~1y5*B2^$Ou3r4%mdjRUJ&n#g)DibLq}j)M_E)jwpRBkY}*A|Z4I=E8{dEk zo`RiC+R5EHCl(6INPX@5JFa^SBnayg%GQVDqdGFk4aeYOzz;c>$Cy?Qx#JRNbX^ObTLY!^H z?22}c*&MT|wb;ODSjnUL?f|j-Zji@J0Y}?*;aBR<6n!1Z(D0aeJ#}76s-3)-ADz%C zX(>foF|#ruqo{49U0`MAhH-IpG@J<+V7{qo09YUJd{VW>L|fD69pjva|gc_}H+= z>_ge$^ykpUw8qckP-G9jSL@8+No7STI7bSUCU9c#9e8^5aHX^dC#JDpK!LcUyGxWj zw3F6gV_FODh;s8A>hWM~yKYLANfi@b1pr~4ruf2*yxZhwUoW_*l^2#swebMf?Vc2t zwzarF;*TY{@P!Fd+YB}igf4M3?t&A#QN`lV0M!r`2_h6wiktp+Qgo9;VhlvIU1b0E zz?SbJbzJi+DJtd<{$ArButZ(7xzuqTJU5TlKCq&wkcm7b_w{6a^8=i232PhTLB)$d z&PK74Md!l}3RO|!?CRTYK``j1o5wgqP>rUM#|&z9$=6Vyt2&??-3k&poi(s4%V)7Q zqgb5*(+uX@SWp_DqSrq9Wpxtb)N}^*PIWX*`!w;DgpG1>8fgO~i)w;e+B^&+Z)q7; zl|fu^h2+~Gsv?CP+%(iP&MofMdNsYXkut7Cs+za>xpuClsdCXZKpda z*rIPJ1q<(MsZmt#23*mVOGBX-h*`R+pbF<<%ZbOb^k{Z32;N5GPr=jTVTCES5YgBa+=m+-hlN#BRUY=Z#Jz5&@JYxYum zH4Mq&@ay$dI^WXln~y@T=(Im$BbWQyo}|HsLt&&4e7oQE&B9MIdcwonw7TbJPFk4e z-E{U>F&YzO->^8b(mSuBISSgH$-g1BW)(WSX(?YfOvnqQ?!|B}Om3&~mNpk_Q|rH8 zlx9HwvVZw*OOM{|(G|inR=+3YP=55`}K-a?*jvJ!Sz9;~= z2;~W#ZjI9v$-6HQrHiKFq-_=OPDD7tuJ(>E^LmG)7=|VqLD`r<8xSG;1(*}iXT5?& zQcL3u@i7hiq8*?%NKU`Dt*}03|7;UNoG93-YF0Hfv#j-?A}v!G{Q9Ky3FH6Tmx z^xOiGpMB7N7A)KsJ;?fTvk0sEEoh-n*sNTB_BTDakjL&x6P4{<=+!=DR~Euz<2NuH zTH&7*$^#YU6le`JSONsU@NnPBR1)F0YOli@Q%rwg!LcL^H~9mWbQQ(oI9b-DCpLyB zu~2p-MeIvY*lR)`WKQ&kY==k;&}wIpP!-5bF&>=HA!|)y-4jw;Egx+}5p1>{>c!Hl<5>e^aRzAhg96G>ZZS0XD%pzmS+YYMP zSHs1hNdpTN_s{_v5r=!u=TJ@;e5xAQTl`d(azlnC^0e-gg7g%$Qj_uGG6*tpYDTfw z$9Oz+iHjxost=l<6X?1}`a)-cZHPB!+?EN=%zEkaeDXReSZo=poZ(_~Hvwz`q^ntw zN3QdI9t|0$9lkN-qRrIf8+Fd~=U_(^NVLJ8aaqn6ItC2P7%YV_Xv|e|bsgyx| zpUf=Kc*3O$HVZ7I|EVue(`j=SP^${*y`8MbEV4H}vDr&+?g^#W zNLUa5x7`aI19d)_{~0JHnPHjb)aHz$@f#Ecrm^rU4439 z8oAgj8LF=I0+u|7N@Uh>vb~xUq@eoYY6`8Dh~PPHmyK=|`NZkbQlt>rT8H(ghWCGJ zURvtMHeDHLG?6FC!eS9~bhrhmsLL(y90X*ycBYrGwBdTncG(svEgiN8hmuO>$GC$e z0*cd$&U<&XslRd=7G&i4E&X-mfrL%|77wMFV66{&{!g*0hdzJkS5)Mz)N*&;1C=fa zFTS`;fwr%x01|kBl=Vgfxo{3ut&rS-|fB+X^9PB#QlI10dLF zF{B_u^8msKOYEgs3KMR^F8&3i)c^4ZZ+)=iuWE- zSlCKXA*{=1#s2I=Ppnj>MSRs~kPKc68!^UX%ipVc1=he(;~M0oRD?JLc1`I_v`!*vUUYD%P6ynK#`(mtfc;a8i4HD9!*< zRn3D08Oz0xdVKWvJ~dgw`bT+8mlD6!sPn$`E@~}?qOc@GP`*B2JbIHSS6;?*VxMI( zKNG=i`&mzcy#py{oZ@#c#MuJcOia=AU9-Q295v}%9)h6xt*O82-DWR{mIi?qz3mw+ zMigFzA8OPNPud4{(?DSgx)$ylslZ=84GM>!p3UkmWHnHDf!~>5!O)3ZR84Mj)5?^E znfzUN1b!qu2Qmki<;RGY;|1nO*JS`>M=zkBV00(O0C)#qbL=mjEDWq=#QpdQG?vNA z^`mBUi74TqAKK$M&(q#p;64nG^ePTu$DYwg5u2MwhXFrPZyYAPU+@UnQ}`FGZAQ2d zmOpT0G4yU1vtW``#DYPLZ?}`~mUJm?-V&Nh4s^DJMus2|Jc@2+jYPo)c%`SgB`7Z? z2cckdA4(V6TU9Z~dNz@$2YNpPOd*)lNCZez#h~w3V1?KK-Qz>{mj0ULU}-c`lx{Y$?u=jKBjQF>$W~;ky&o zcAWIli9R&B;pb0;*}x(Kqn;$-Ac_VH*HR_?wqd@XQDFe9tf6oVk^G!uSO$PY$m9Ui zO?oiQuFM$TSTT}@XJXcukr8IuooQWD7^hZ>b7Ti$7zVy4KiqktC*WN_6S1ITT1zRN zlSF)S1GIr{A3XL9R@5bvWMV(3QKx`}-n^JP%ZirJKS*zxxiyR=1{@^%iK_L*lRj%; z18;(%8pQx5uIHuO8P?Xzy9-RLl@TAQ;R**|nA$MBDI=+oN|i|O6y&{PJ=PKm>00Js z5A|H*ub7=BuIGobjFNQt)&?Pb;N!{Huz)+_pm(Fs&ejy`$*`w`!~$`&xr$NoBk?RQ zbEPWwv=Lor7RNiqwArumna~F=>p+X$O@1O*+_2Sl{SQta3UxXhT8mQGmcE) z$4m^To9`Pb+le3koer15V%CnVtYk;xFe^uri5G1(sAdO`;ik|W8*);~drHA9#Gx@c zjOZ_uEGEgR)SGcA?1_+YNaTnky=+qS13rYmFw+?utwX1D-QPqE1TDLMi~@<2U6Gcftn*$6Hu|j8=)m8u*^6I7kok12vOhXKR}Y{==w|dT)qfPW&CD z&;+(-1Du3=P4_D*x%_zKE&zW0(g^)P!MU~nK-F!pK*+hNna1!CmPnm^N*3*kkYP~4 zfWynCckr15gl@mBrM>j^@R;l=aTBGPCVG4*iJ-b^Ra#iB~C%A77o0u2#5qn zw)wb9U0CS(o1G&eiX&O4mj2B2TeK*C!4~> zqnv(E95+%#iV(1eM?ayfjN*$bk>zT)T=#UNF>Aym=sR4aH6i%=ZN`-}l}6C{NEp;< z9yyAow9S&ByeU7$s6WXP-fU)gYC_dtsaivdj0ex0q)=chJ=A{)i4%rq@3p$GRGuI2I!Ff4g3Nm2zdlemZy}Ub14~J) z8qO{d2r!0p+tWR8G=sk*92S>QhJUDcwkTMO%RA8daaJ|9)&?mSbglc7E2mI4z55lv zj?@3NZa#nT#X{M^!!RIKMY4!TZ`E^RA8R#^SGI0KVM=hEmpp0WPPnRojey74;yR_? zb*H^ip%gio48JZNt~v%NmH+(y^z)HL8(=B2kPPBcZYgZQ<|t*Rb9Yx@$ocN}q_stF z&N*%o4Sq2oLBBa$M<|%|EPlcKcb>P!!OIf-&n-2zP#viJj@m5i8GWi-`91)gK!Fx( ziF|v{3l!({YQe(AB)|O^nK!a9r(VR=^IDU%8phrh{OC5XZCvF!tvMYt?s3qvv z{nauw6|G6*KtRT-`ZC)WGp}HFsZ-kDO#7e}a9sDTXLc(+_zzWynyvr)tyyh-!AL{i zuwMa&loh_H_`j7O*^*M#eE$*&XQGzG>lFTV#fK~n1%;z#h6?9fpqNgWzDc%H=B)_P0z zTZ}=Qc(xI)Bt?jgbuC$pF?;QzK7Zr5+0IMo^%~V_d%-w+E6W7~=hHcp+YMpH!dRZ( zu(7&*lFWY1d>^q9Z$6qKm4MD`CR3^vTDJ#e=(&W`)J4mrfKqOY^8D6L&}u{M#H3`5 z$^7VzH|!u_TG+OHF2{M@&f7Xth(sfWsMmidJ4|AaHAO~@J+0idBLzSqbm?SxbzUBJ z$_NaGMY_{}@as=8gg36)HsCT7h|YA3*eF0jULNy97%XiR zljrEGKBm4YXu3l?_CjxyhXk8*+FG;FfsN&fA^#NaK|QD?+-)P6*3wOSNgI;y{1I>` zs&+Al&GW`BR^RUO*(m(GE+(%=wKM^h3o0L0cAUPvU$kBU${HI+9u;k9_ub^nje_^QUI$zcxM6$QO2`X7>6@NGD$VD1L#zP910;87MrDs3+3fT zccGhY))<9mSaSieMs$EgFpi>PEdd~B zRJt|ClBGZWa)@G+_J2(aae+AR6BsM9E~E4S>O@;RC+LX>KXWZhHtXh`RFP?iIdG}9 znJSJe1C;X6!c2Mpl?rjpcoAWf{G%32T%W09cmX0JqD;AI9H>{U*9Jrqq!+y@;e~jN z8yz!cd6qp=0$F@GqC>(bfQf%C8)2-7Z1Y=MhgN>o7vFU-;TFQR%WEX6I&Q_OgZD)F zk{^2K%wXb@f2cswff?d)>sbujh7(Jy<+d;`qQdz`1oTih%(>Yg646!~*2^r2vKKeOuk)rYjND* z4MB@q>N(xc)h=8Zu>FDWUN3!UTOPqzIq$3f_HylLTSBc+a+0^5^1 z+#I~qB86w?S8L@ME<@&`dmq9bTl*w_edwp65(Fc+oeANUMZ4~G@nlh*n`C z6%oeOnaFEI4=yPiczg`iI9R)x)C${ejU-B7BQhynX6h^E;^Rba;5XcxHtvOGRKx$* zk1F%2Z|R3gGeCh|$fF9e)&c{K4pAZE5k21xn_=bP(+}*!W*0*72`I{*b3qH=gcxYv zBVl-r_T_9RJ`)Bo*2{Q*Z4F-3|2*tAG+QJ9M}zNp#_XpL~u&G2> zaG}W@ernXuRve>E=VK>e)`ch^>rR>_m`?8#3Cnh%h$XEneox?J&Z++_ju+yFHt9JU zz5|mhkif_$3;MBd98PyO{8XGF=g+cEB2&EG4*_U7G~*5h&!|`-UyLD==<~cJSyp3o;+%zHVk50@5nC1HyR zJ-TwXH9*jz;EMOgnZ)4Gx)yalS3|==>=mgQZnw>8Br1&%8o-e?9%@qDAO+yIb=g1h zXYW2+dNk$IX5)BZf|ah>cn1>dvPq5Dn z7^T}~=840Ey3ajk#kHU=k}kXTizwR!U|^VqRSc2-jMyif`p=c zf`*p9=}hd@CuV?QSoWd@9WKSz0%z zdz@UTCyX5c6&Qc%UhIIt(>9}LC&UIikWRicg|3DJ^nD0gshWmrjwLb7DL8ow^JinW z9wVu~@j!@v)IXFqZbV2<5Q7OE^-;A1$bOw8dFB#!5FV{=yY8aww z`Ooheg3J^5yZw+^Z;u45Y;NTCxC765c?B?AEDIhomj-JkHzv;-Z<@i%t971xCKQ#X zo23=sFK3q#%YsjeliUG9Lg;$>$UEL1T#Y3<1#lL~LMM*jh~g6BlzmI#Wjua=7-Pq| zD&D%Dmx##YC?eR)lN4U^59?Hx%i{gh?UZN=Die2R%hWnZP{G8FJY*T6Ms2Op%{mfL zx`F?B7jgwD@UivYir`lIFETEx$<|?@<$Sj!3;(VN_40__a)I{dk}FPQTNvPCIJco8 zc{;Iw8&>ljlvp#^Gg%XGkQ7c{g+PNPzB0IY3iO}vzF%PTbT-0eX&SWEv##ZtR|FR@ z&0Mg=;!R2b*8`lE)K6-grs+emCDKPe2OG+_sA=rAW!E>CVtnUF*L{cMi>}*nKXvco zH*NsB6F30Fy2sOsd?L-DoNq2uX=v{y0MAhJ-<<4m@za17D|7Ac(L{*#s1!8ru30HO z?I*UT5BMWhppys%X$~!$r3q5Mb2)tQx0y9;phs&9{*s1;cDbyqa|f!XoFJ z`fC-bAkh&B(@UQuvqt);<==9_6=ru4ZZ2aq7T-pd+X&7J`2Aj7Hck3Yc%al$uzfx< zx$XL#=SV@S%i+Mj&9GXFvQSzod9}8;?A!?GrrygMJ=M7&Cyel?(@3Fx5PG?yV<;M3 zp45^NQuP^26LSa|k^7iZ0WbeKFINJhBvjcUQpznz6&?s^%#;00A&Bprz$ClEMlm4!)DdqlPesOn>RH;ADAqTVo;9t85Up869-M}P z{*V4;j(1=da_ejaf~FAMqtwxS62w!`00mWTDobDYro@2QtevMJ*3uup1?&khzw+3N zdbM`)KxnIfl$e9+5Vq9hhXJLsgwieEg?eWv52R7KWz&Q}?YNQK@FaSgl_P+2OcN~r zw%@vA6>U?9dK5`&c=!_nf|-*A8sYLl*t>SD)^6S8?_q_oYg!&(cte=_9sF-(l?8R- zuv$N|f{=x@3!Y2nPZU-mnORP#l(=PM={dNa!}$V3PPCGof7kTdJeK2xJg;4{9xF*z z+tbC@gGg{ZBi93#g&&3|W_vS0p0!i0pU7@`=gfT0cj)x37afg(Ry*|SKi}*{<;ClE zq4?WtH9!`u<2MqL0xUU8lQl5%&-g5s2*jkcsHAc?vE@A2vgHlVdS_HyohD83*+0H_ zMzZ)vr){ii#_~-yPqC5}PyLBjK)dB=4Bj0;z@w(+e4z63$0$yR8E1pWq^{DotvxQwpA$%1#&J2z_)+2hFXrKcsp8W`d! zb`Fg@L-SvC`#++2j*TKCh=piFP)>>UN5KPBlgw%M&_yhcrw@Q7Tv(1w`e|&iguq-R zbTmR7$J_#%efsOUG=Tj;+5mx{U`5$!O8Hr?vyBa-j4~RR;pkJTFgJj|;LhC0aw|8o z3!y7EGSpJ5q?x=>KTWxbe{#^Niu-)dvN!U+#tSUhKbGY-_hN$-M{(~$9}Sp4i}x8X zBq80XHwU*11LGTc5qO`ytndg8#FWb|`0r2SHlp~|e4s$-!aE^UP^Kg2GX5TAAZN^5 z-w!BTiuDh^L-3VySsNd9?^kLCw?=%!-*sVZgmTU1g2t<~y0@JKL2K2aQu|O1rKF|$ zqbMeOl?p`;pU6oLJjv#2x9y4%@-!!kDECaI+0ca8f}dDE)}ypJ3@%#V$62xVmS)Fi zwSUZlwlh}i4}NoQKET4{Gc*D<47a=8Cajuwct3GKyIN*ex>bFL;ZoKStL;Yxo^Q0= z%B^U^qF$!qq#x3Hqde$E>oiq_vQe5K>rPf+pzVp^(8n|z_m8IJ5ZcagY87rEzP=y& zj}IRdf0^_(l+(7D<77f>A{r1o#fMDQH=v2c9W>#^342$2vEC1Gi8aigNTc|>7d7fj zLivIdP`;!-#KbYV*pk`sCO}9*nTuQ$%gnR#(B%GQR&Eh&$!dg|Jwr&(6BVMt zxu=%*H8*+6O^RHv(L_Kxlv5U)dSCe(l?2V7 zIIDG?g+@2YD-6dSY=*H^=Hn~*TvV~aa=%OirhQ--S6e9d?c{rGOWVBBK!~81>d*3E zB#mLKul4dv8gZ$HC@*xWZi&ZuzVV1&txGbz{2Gy;Yet3;^U@-NUJSqfWFcDW47P{H zsg?mae29vRHX9ncjsHJcUmh4mk^TRw`k0={BeAz%nSVSs=!b`CILfSTbjuAsvq zAPPDv7k{0!_ zBwx(BTfeClwlkLL7R`kR!2m%nP^@I}M{Zrzjr9a?Z&VO7faM<42;UcKrlW&e0AaTk z36;Tge)n{UD$$dp{qO{*W>n)^W+ z2Uq%5XVVqLdy%-iY6Z*$a4n-2;pBsSau_@){IOz+1baxs37T?jU)i_1mQwn{Ma#d~Ip(Mn!ZDNA-k`{AcvSH2a?v$LOX^Pq3@ zn>_xY;qk{9haY4Gd`moksK0mI;1y|2vfsM0}L@M?2gUn)1qjmvHL-)n><@voAdMmw5 zl(M-Jx`$1m^*&URFj!Xhg%lX|ChrC4H)~*m3o3k_-J3%P0Agut9;;1QB6SkYSrLRJ zKtdM)HZfAUK=u%T-p;}}C|#$Ud^unoHvBAW)XNPh)3rI!w@r>nrCYa9ZZ zf@it(giHr01&!xa;(D6AT70imU>bcczD zA>9;i1kZ&I8idom;7;iHQ?MKytl(3#C&jsr=Ouw*2JOTMy1g@qz|XU79M-hWFbCk; zdKbwsZn8rdrYRIHCA<&(6v^Nl6cmcXll`A{R!hg;JmmEl^BCWdD`Kk9#tyTr4;{ z5bprZB(qXvRM+qY3M*BuPsk>RA%s@_D4jw<<17;w?YMFbU>cS%Y%tTXPBHo9cc*(k z$Kn)^16O}DEDJVpcGQ7w?v@|1EvyFvN8X=Y=cl`3KpJEH=a(SQNYY~rE|XB5c{PQE zZ#wK+srL_X<6Vl6bb&Uk8lg%Q1cR^Hg2?K+D{ykRfO{1D%gy!6mMVI)Az`ir8)m82(rC7gtWsLWYa5+b}CrCvP zU6n!1(Y3V=HzB|P02i$>P~k(IthX~?6V|8LiKnTw5>~GpH(L-#9EI(;O@NZjvL9M; zRJlNGqzPz~iL5UgtH5s(SnOlg+Yg`NaRd}=R9JS4WGjew_q=vQzdSG0vXyM$8EIis z=|KdS>*=Y!Y=or6kAna4YKAfRkf(1jIAWWBvn-Uy;#QPjP5f_&ZG*)WV$nvV(tK-{?5Mm@e8Z9-!*qhQgTk@xWi~&!W(gVekK~E0JI8x>k*GTy> zcjtK%3CY;NXA)oo^DjU}0rbt(M5{%f4R7f?CHm$;0_v!metsR1v0R=}1%?ZesO3Oe z!B7=c4@e1`joKS-IReEo-eAXl3UQHQ0H^qIHDIFXS`zpVvnp<#|LPXFu@NhkZnzjB zOM?OppITVqO{2*aOT&cbP1FPlQv?_53#`dSa7|C7exS$@UCM=;hNl3dR@ZDqwARy3 z7_0AmH=|67_Z12$!B$l8>57jB+j{Alks^C6dT1pCe+DFm<9R zr~|goTkwHaN3Uv@)Id0$Yb6_1N*Ep8DQ8drNmv{Lwiq+wiPmwUGQ&e=;$7*84 zo_&k{OruQ($cNq}YRJWluje)=FRj#}=ydmvY!%L1V| zhpNkojpj;&LPy!`i_p^B!e4Qvx2NxWN+4zHd@hFxVa+sH6WR5n9tw~><*j`Uim0mZ zF8h%=Ag;`8fq!YD>wEp9mO%@|2c7UE2_&Ro2LWy zy+IsaWv3GY*5P)loRcq#Inu^M5~GlT14kGjP%*2@swZRchmM>HzzJM34uP4VB$p56 zQK1@DS{}PhX}ai{H+WeTjw8K5w|}oKA4IW^7{WZ4@;v1tTK!-IbHOIAj!;8$=D)_q zb%4^};5$v^>E>iduDV*bB?0>A=uY!#R_)NQD9&l;B9{-!t2a7#yZ#BS#_it@2q z9}X9RHv&MV- z7NxA-yP2R=gA%a&(S$z0cESlW9=>OmhG^S_%6djFkRo~^oF0J=nfOc#K#j+KL zWS5f20e_hD_X_J?GViUSE5#|Pt5yXo3Qn*ix$f@o{X|YQa%2E?T3Uejov18<6FIQiW`t)DadGn{B2ni@CtJ z5YxJQ%;YBuO;-|5m?_!sQM#I~@?g^57TzRF=6a=pd1+9(>@TdwV`d_5)$9Zdt@qu- zV6xI!3Y8h3axBfpVUdmf!i>%Q?!vcsRhG6>&mzRLQ=%IcAG<*J>~eYsy6`>hx*(t z7Wvzdz3Duv9Lx5%g`rp=U;~AW)TmVTrSJt_EWu2|X)R+s^?RD0BFo;H3w6tMV&yZ* z4Pm{^6Im-#;M&rt;MCg}u?iuV{g16`~CAvFe**s`bZrxYS0 zX$+8L=|wDLw>=F810xs9?8Hj4M%vVy75Zi%CyuIYgFjV05jMO{A2@K%G=wpx{;z>i zjj5fca_--VWJK}r&!n;9`dBRnqTbr$7K3%qwjm$)(YWHa!H)6059^*JYttIX+)w39 zBB8IVMYtEoj?q2<+R3 zS2=OkTjZhw8kYDgOiaiLS0^iT+JFrS_JweXrmuvoHp>FJF(^^A5(^7rO{l2$Nz-<2 z&8m&&^fs;cJq5*Gw9DHFvErsa+~6hvx3)E2q^PKJwv@@ou}DF^F|z8aDe7Od$I+{8 zn<4#7&(na1zEf0g0YcjKiP@>bcU##mP3kWWPzP#roOI)`Mo;{@x5PIX{rU7GkeQTen|jDjp2xSs_jP5A|&Z^PS2iKRqW zwUt4-xuE)`7&qYS1er@-ajlst{}Sj$V5wu^`PO1eWBepJJ?|4_w|R1*5v9s;ndQ2S zja(?3r2@M_W`GA)1KgxFJNpmF+(vlI|+RHF1OaUpXC<{|o1+NH0X9fx4g{MCOVNrwz zIuPN;Z<>kEIcEqarb_&m{f2>NexJD>3kB5@yhmwS0@gPF@59PfFwUZ8%)>o{qjEAa zSG!bU-#q`5l*DUX!0ha)a$xZM@D*)tJ*HTe@b73uYdSeh`IhS!vvrfhV;#HL8}aG1E~-n{pafmu}UySD?(8>^`zz;2?N!5%A)HJ7@K z0UYeGa0P@@Y=noj1mSk*#FmSXSi#3BQ16)lAv`n$7W2nB?oP!|2nwxd@h z=Iorlt{G?63}Bgn()CjYB$BmavnPcP{7nOOEOkuRp&xk!Y#i@YKWWCyQp?CA0k*gB z?LqbxZ-X{S-KAH!Af@vZme0+3Z}ZN=o=f3aN2u4C2@Q(JF)95Tu*@0Xvyp9*f*9V; z6_fx`^EzleRSv0}m?gxs%6dN$cyVlSPTRUNz<<-%q!+l|F@NGxMOBKyE5EUHmJ8?UlXL&^8oV+fH~aU{NyG9_C+ zEUxpRa5KWd&>Fl=7**Y76% zF}v*nW@Sp=Mk+*i80RqIqh9rSa_2Z;D=2WVPVn2!P|O$MSp=zIDiAP7~4vv?Zr- z5xxCpin$&qZpAq_{zU0G8ZJRzZ1*{qYiGtSG9LMhSPoc4LEP2a{F>x4_LQ!6;T?#0 z$i@U1+6TVcttIa-L+|8T6<8gJqPO*o-i*^NlKLgg(;bCQ);f4u_7 zon{rpVlIU(7Kg?&*$T`Xt-Pq+chkF)LTX`AQE$$ADJjdDg4u@ke2_E}(V=vJo&kxC z0*|^2Bf!`AT_Z-z92n7tMviLN#5=%kRckiDZB@Ei*`UNP32YOLjaTSOPzEfxO_b@w zV(7`77~2QdH=hmy5i%hag-ZFbEP^y7?aouP2)U#;!$o5FuiTu@70ekzj~Ah>%{aZFFNPmi_d%*)i)F#CoVcn1~8Z6hJ7vTYf8$ZqL)x2mKJ`; zz-st91UmA69W!sIUYX6r^YCCzW!0Vd07xg^bxvc~Aqz7@Ms>lrsi|TRZU=aG9P&3! zY>|nK$hffC-L>p6@6=Nm)#WdsxAKIn=4SmP41sWyUqfa~rw49*6G?p;ZM;L;Q}GUy zP*X~=N!iJtX5T0o{~}|~@MV^16Wtdw=*-o!4$SS?l^-7zW&z9d5R$JwO-&g3AnL5J zj2#)_pDF_uM*K*WvH;RMuoe{sTz4>8WWp;Jl%5w}P78%O^I9o={^13RgD`Z(k|!{1 zLJmO9?NAy7x-@K%4nl-Ejqg$H_S{|=-AlLax?Ny_E{J@C7NVJ*m>c)e`eldnB&M0- zg{GDo)C@Lr=H{+6UBbLmO^>c9i$5_aWj(z4HjvCU96#`(tenb@LXFe!GbE8f|?eX3x*|Oi^PJey>mrA zJTv;v#oQw2R;_8FJ;Di*wVcms1*D^stTeNKeKh=$GTXekl6Ddw0oRHe@HJ{S!nK&!mXPDto=(lLHKBGCmDBjXS{J48Q46sIg#`)sOGDG; z3KYPRAE?Q+%KDvY5)pdbo5W0pc8qVj7^pn@iktd0iX&tT$=m5`$|*yt%dO6Hs>PiK zPe>WQ)fcN;^P!Y0Fu(tZ5`4M%?%3NK!f(LGeW+hSNJBj=-!0s;o_2CcAo|zZQ5~2O{EiQ6lkm7=7@ux*0bmO>z;7a~+ZsUdL-C)MKORBAvrAtRBe+)>kTWQhavsqo-+mi7G0YbS zamr7cV%nX^j?p3d@&rFa)gcU%vXp1@H$rb zGIxv@6-DH%FqTmwpEKx9a*PtFJdXl@7zcK`?B8B28kkXhUmy*uEkFBcvnI)ZxlU%O z7lpC9SU$KB^u4TKuJ|}ZPQS6ALCRn38kH)2Y@dWkjq%iv8cr~*}*pXU)B=EZ@_kQ>aS>*^SLBy8Ie`j^sF+vyZF}lu= zQD}iRd$nLAvTtmLWZ}1;ChCLrET||unBP$dw{a}c^AE3fvUr^42`DDJd74EAu#JkN zTN6Es=d9KRem$emm+JPe>}3R@wB|14F_SOoi@>UE#SB5p&#v>lsqdf7wlJQiT33*L z42GXjA2}s!aR^X6&C%8IfauVd`-na15#H&57U<@JeIEL=W@?o=nV?Z5DZk@hiHXgM zomc8M{d(aCq6(hn5-SB%yfSW zItiHCXUV1L^**oE)hs6EjMw0*@t5#=vPAZy6kw<5xHg&!GUzPm_Mi?beexFXE{O4z z5x(oiG`T6Mi&3}hKM!~b)rF35|6txfWXVhmr6loYssi`%<7KQ`+$i^z$gI zDN)_UZ87WE8{9Ojm99cgO57qUh`eo*q^*Td2v^C)9C3k5b@*y&#?(Pn=zEa89KArG zXOtg4Mf{0(6(Il=S2R_!6nt5$NMAz~^F8z*mJSH^`SF8NV+-(|;s<^_sNu&EN(Hh0 zqP~b?>RCf4B2W$jHqDziJp;tenmAehIgFM~>A2K((dBkiCzC0V*7(57@yJp~JIdXq-JiZ)5aEO@44KMEDVU&LJgLx}> zMm3E{u6SLAlVC7Van{SqX)oNtL>0NorA182ZQsmKb0xF4v(;$88aRz$V1Cwv2~d_E zm*g#OW9cY@i~L@bK8~3%gRT)Hw$iC=FPus?R0(27c7t0Y8FtB64q8)}@}ZcH#Bd7FSuLo=EVkdyVx$B%RpX%EchaxGPF zM&iF3m!`=_*7i{|&>7B#JMuPFPzjr_i?Sz7i?ts;P7Oo?KE8D|wE%=>|Lx+5m zReiz^R&dnm$>`8qVUbVCDN~7EbMbx&+{Kx<%4kx_b#nqE)o&|Qe&QLAP-zwNlf|5^rPHV&WrIC@nRNZ!hVs?J!D8NRE0=)}-Gt~fd z7u8>ih=bddH&C0D7WH?^xcCHqX8djh){G^s+l_$XVaK&ge)_FD8YC7jN~>5)qSxtM z@?-cLwLGid!w?+*kt%q9nR6nmk5&ID7LQ$}5wbMOrr0MvZ(0fq*S++w~6adR0Zv^Ov^%}fLS z;qnCgu-CH1_hCZ3z3u6l8GaK(#4exp)k<6RHEM|TV&j-{KpujNY9T1n5_?_eW&8^* z-U1y~z_{tsc$~VQ8QYmbEd9&ZW^4wNWeMoRw*vL}qJ|jTlML>np_jvhN)?kQ2Wi;l zw}W1g$InXc2vWuE?x8y_$DxY<9j~~9QdDs@2DoCHd;BiAw zfqUX^oG7^)Kc-C#Qm?D=+=@x=wR3Sr$y^*?a5;|S0#-5EJ${FK{B|6_Y8sADcaKm1 z@3YT7@$9p4b~;{Fg0mHO-Gm0-a}z{u#XIi%-UWZg1{WW~#{G_pZ`?zF#inEzE|~K* zo{JZ=lEc`W_yKO8)Zt!#)V=+Cx4GZr$F-m1vg_U3zjR;!yW6baaeVAPY%X&*m;MX4 zj``6&aT32~?Zf>g|HO%#-OWwzYi@DxKTMy|IeP;x@2AT;wkbW`t{!_7w_N(2d&>{F zdY0Rao84xV;6%k;zhHBZyZOgBocNcUu2wQ0yZdg#=AW~1?8LbL9XsWoIN5;L{ph~# z8oaLJ575La>fOx^xUAxj?y(!OTT+i(4`1QldL@2+J>Pv}Gk$fPecS~6+B@Do)`VXl zG`QDYgZsaWV)KK*v7`SxHthQu?hv@o`*fOn9fo$;#|zwh7vSPg?!o4?J3v2Qg%dyB zoj!Z) z6n4MDxD9K2-@Rlnc6Yj6=X{43pB=%ogV*&bjve3cUh)Yp$)G2P9XpK@Y87obR?$v# zd5ME#`wzIgU(pl1O|IkFYt?g=7EDxW|rRch4Sd{k;gJ`8GDcJ%P=cb=ds=B+mZ&mP<8Tac|ET@&QV}T*sM78a5Nd*o?XWn~Mfwb8Qft zncZ;9bwT%*KJM%K;n?-KZrI3dcQ*&WCU*xaxdN-5vWg3-oK*~VPYl6zw`XB&t8aQWAkwA(f}^5$a6_Mgx$+5_g8NmnuX)T?ksR0RfyerHP|$}O`AUm zC$9M4%PXd4ft}JnY_BPJ)%VFCUl0Cbk;K z#;%v`c3@Kj8mJiL{_6K7Hhq4_C4GN$@4&B$Yeex`=Ud9m3a`(?1TM>ZV z#|=;VHFy7{d)Jw{|Glm1|8AS{-@8EJ|96*r<(VH>1eE{13%l3;_nwmf-gC$Q_o8@d zXdi=cp+9=ge*c*NsjCk`8 zRNc$!N#0&!IECg}Dk2sJi&8IhKJ_$!OfoNJc7mMCkXn%sxGw}&?g%!3d$8uwGfeZ- zWr|SJlc|56IgQw9>Xs~`^VPs498f)o?fNNaG(+XSa6s9_`Z?x{?0i4_fGg;a;k}Fs z>XDV?d7fO>tL}B)8@{Z8&E&sXL7X<365VZ$ z{Y4bPWsk?FUUX%?!I}qm;zXQr0mZ6-5-Dg3Z7P?gl&8N86A%wz>4DIw)2jL?fJ+u^ z-vJ8EWRa$i&of@5@tp(&?Dg(Q>G!ajFtu!@G%3b~$XZPm-guQ1t&NP`Mm_4jMa6l| z-Z8JUn{r!`88?ZgW^0vZSXrcc-`6VJ$v!}fX_qqcJW0wW>VxoAKm~aQt;tX* zTXKHBqJP8H=X3dH3!TAynfo+ECI;T2?i(v%$ zx3gkTITf~Nk=Rw&8QV&^qcvTAzdWqf!!L6vtj?1;%yh;Uzqrt0@_M? zpEKv8QVjj4T z6&5wp*$T+kLRPDc>imONW9G6r%Qw!j(&v_~=bX=1TbOZ2tTea7pmvW9jRegbcfmZdl(p*Cji zQcdfxtX0_#LsjuU;oGL3VODv^F}A%Gfo)JBv}WL#%n9(b=_BDILAhqca_(%WjqnA1 zU&>Rk;O_7O?ILv5^iAh94Q}<9!+Svw#S3fCp?hoHA_pmgF;vN$=|K(Pnv)tg0p(Mi zB3W1GJ4hkknd`1(Zl{Rf%}xJ#l=gUi)gYa|RDq~7yN{(XCQ$#;9L$tJ@5891l|=oI za2nRDoC0tp;s_s7H?t9#{b|pstvdbw8WCNw-rD;rMG9BfD${wXsrFYDP!L>bR2DOS z;>x~{1T(X#wHnyzkrl!?tV9C5In|Fz>h%~FWyu9|>O|-u8}TIx+uAsph?-;%nZ-`7`fvDjUMXMJDQV14Rc5xNif-nR>9Uje9X|4?euG_C}`Ws0E-Q zG2}%OgVY2s`5gE|>91#Tzli-z>}D3WMzxYi!{gc4OBd3%SS~+~PbnmCM@YRxV%8T^ z3mlh4rAow_`AO3{KJ-MLJfzY_J<9TS8m}O~J;Gp!T6lVT3VXKRV>hs zKu+!TloB;xG+`Q<{9=fda^Eu)PNw>L@`_%iXsT3Zb{OWiQCekLPRAj(TA~vnZYa8) z2d#C=XiKU8eHdL!;T^WSU@p1Qjow@oUVGOUrG^Ou$yP?}L&{IFk%x2#z!UOY_iF=l zA6ow(ic00`_Hx$Ex=uAqL5t^oabSTbaT|uIcurQwNeWAIxE@4I3tpmFFh$Ckz1~n! zDoWO9EHE{}VohZ3F(MwCe#aLIABu&RQhSRKejL3T1kTnfDhQ+y93mnGee91AwWD>5 z(SBfZJKcuDnj1eDlgJ_JA!3K2Sr0PLjac{o%4Xdu`NT8 z$H}FWUiCl%!a*91LEMD`A=uG;$$1XMQ|&cK1!R0O+1f@Zx0NNUYvE@2QG&s#C5Xtl zQ|44Y8-RU4V_~Q6M_WBqgO}r_79K|*XTPPgb~qZ)Cb;AIbgU|PTX#xVbl?WcJw6AQ zj%cePxLmvPLl9@uls$-Q{YWs;sQWehD5ZLek-v(sPZlmkeW3y_m%?-*pN}d)%YYF4 zY2#k-0X=7REnZw=gDuF-6csWD(?Mo_90X3YVdPNC^o0DH13-&kHhPIHNIeDIHjQ>b zCQ?~O0)qOzmO`s@__jXG!Mrdb$Xn5ci-xdL0aQe1vy983m(UU5x5UtY9>9xov#OB+jA>j94+C=Nt{}{R z0TFciSH3FDf18f?F}ami-SQlo>XEhm%Ngvxk$jPfWuyh$u(4w{tJ<>A{?YZ*6V@w} zXh$m|(~bDzbji-N>q~3qyGmm&ZUBUVk6WzdiP>Z&`P1A|j=x8(JPkJDE^lPfdrU`x zL42UeW|l2bUS#R!2tHwS-@NEprZVbn^#K#Q`S;)9hV6DoGl)H&^D}&<-Jz!~Q1}!E z2SuRikMxx9-DT85$|gc6X3&4gd`W?Vcp||6^hp}zZM=2oBDfe~`e4d6IW_p}VDJP| z(QRd^r>7bcd<)pz;8YV{Z^bWbwcs)7aVhOI1b(r&vybwT7d)PX zkkEBvNImtd{TTZz3oTVwlNIiMLg~&n6Yb*T9L`S%ij}1BSyZgt=&q)>MuJ2+njukK z4kctBTmrvyDtPNXJ<@WQ}Jke3dfuj*==;9B!rj{T<^&vN~m! zb{lH)OT$e{$t!wWv-x+Q+^-!|3T(VT&%@TEC0^EawG>xSELMb0zZR3k6g)`<>fWu~ z4i;?OM@_l{Vn`vQG!IgtvaIvjRdkS#dM>826(~m;C0f)$Gn+G;PCJ;5Bg3>v?WUZ_ z@+r4L>kXd!?WY)_*(Bh4*4lSM6$0BmhFHiVQwL8eHtPX~>UHB9L|(o}dPou0n6r2a z364-C)R{QFk#!MfYl^jh{Xv>1P}5eu3}9gwP&!1hT17vyc1BiFL(HffAdO}QUK~u{ z$6gF^y3d85P+zf8N#|y51N0y`;LJ3TWz%zP1k_#s-HTt$|F zzkMSG~ zrk{%Y?>>x~Y-;z6M0kX4R-+UqHdhf^j&Iw&yt?%Jo)A7!b>K*sNJ5&oL&+P|pu|`1 zK~JcYmqX^|Hc7i!! zl2Tc+_QU{5sXEG?rU5?(Jb#{2!OiG}K(^;(Z7U$V|L332;}LJ)net~PB1~qXri~iQ zQDOkWmZ6?WThYQ>l7zPhAB_bs;dyJfv5@B6gBpJ$;|`QBrwRH-xz=#$Zy9(RqSSB- zjD<%k$ZS6Vo>V)8*6h^~#Wr*0Rwkna%?hMD(UU<1J~*hixz)+) zZh9OOwiA73F_plOA>RccKa&p9OXZYf3IWyHid;-1!lr8N&}bxLz@KurE(Nh?fJ%pM zO8Q-!p2pl~>zIw6Ifp_fFw*HLY2_+sbdZs&_oC!|td;Ij!V!~m_A=5Gm4NSOEfzNY zN;R~Z>*FVj5Nw6vh6hq7uW(U_d03jrrXfxjLJX-!^cHGCvWA>V_tjegIO#oLs!4DZ zGmd=EXTUkQ{=<`*jFxBaBM+d-S~Z)4H5Rp$5qw_Hv)9vP8DG=F{sWwhf|{uCwALd_cFiK;QyLjr2>4r}2Knem868%3om0;Jpzcvll)Q7(CF!(qrQ z+1qC`9-Ybxf`HSb&9HP@qqMjJmIA?DK9nr4dI?J9uBQSE#uB3k4XhWU>QBNQ^Z@y` z5t-rMnUi2$whlJ7A%*#ixw*x*mKb6*sqwkWNj~M}B^W7&g@6PpSUG;pje3jE9Fs=h z#-|&=KJNWS;UCd#Ma{!JDC_jaG4b1NnQ~KBLYzMa0c#vf*MkOX&kch$bp3X>Prbu4 z?sXfLGEkcbYgc4#dxG-IpFl$E)vQ#o;?NZm zTskb-D@l`K7cOQ~{b`@NG0%`?l=vzI&T$!q!u$$1huqXniko5TY`3SO21a~KR)+jw znVLV@Utmlro3g!;ulufHSQ#aY)y6ujZ7K1RR`OZhP31T^tw0R?kRF#x`*vzstjeAp zRiQvK=gzI_3E#cVMzv$pxEHrrP&2s2qflFW<~><-0gW$0yUGXn582dxHIyR<@^-zx z5X|qdni*$CSI}w))uPaVP#smJbq+IQzJC(3E$Z0cipaK`GvB_c@)vmMeEU7!#8MOX zTIIHE>SvjChN%`~$+LpPYdWfs@Y0|-W2`bX1%^+n_DFB!v}-gWx0k+pzvHpJ_xC_1 z(Z;M9oJ$toJD!>0YAxo$cwz2!){|Hy%yx?xwJxV!{(~dwGl%G*CtvzT*cSuhHnRES z`E?Ia>)O=$Hh?rjCHWfJS+`*Z7UVn!4jJTpmeS?_>WiZ`{FBIKB@q)1jcANui93E> z#DasAhGHsinbcXWz?7VQs~;+(1&CjqeU<8f*2yB^t29`_qM;dYc#eg}2vo*Ebqs?r zT;%b3AAb9vs-uWaCMJdV#&v4e6y!npqr+{ayrKSqMQdMItA+^!N(68Pro?1s>7HAv zEZypfG9d6CYDdtbk+f-kg0XiLD+Zi@)sv?A4NF}?Q^%x550orq#>)N6wV#MF$G?^I z6gHCDQYKNnb=3sh-(sV#I%RPus9aD^RhM++p zk~j$(`SF2gZ@60pbi%FcGP}IaZZ~B+6rC(rS6dad=wT^A5`WRVtwq*aEY%NrLgTW& z3978eRYQd^RgM}$3pE6iGb~8i%WSxHsAUZ%|Gf=UnNv@R*9#~Ta3XDL%%AB+cPn>@$2PgHrkRh<&xFoK975+rb^MuJDL_tcqZY z-Xun}EOQ3Y$-GHmOE8d{yl2@G+EhdzxBu`fZOlvKDO_d`2fJgy*i@lG>veRSD04wC zR;mYbFS!iU$#a5gBU+S0HPnvxHKpw&z6M?be4l0(-XrVfunUDj@z9RRbRwI>^RdmA zOX22(AjX)qawOmYUIuVozRN<8jO~mLxOv3fJ2=VvS#b{h`m}Rw>eacSe%AhLnX`eX^;l~(P z$M|JkHfRS)@wg3mpbL=RNk5Zi$yvaJP#>q01!N~u92|bsG0}iY%WMmbr=;8d1uTVz z5&iTbG3#8KYxX7Mq9>XFxb#(xNspsE=T~N_-r2}W^OGtGHq|27q0e7?Lv;$6G22A- zJ0;^J7LaSlf=!vdvtgSJfgMt|oGX{ps-CFU4Y5M%309fIoo;BBig}k$#gGy# z5~jxLY$ok?TS>uYL@|I;zyFUY#5&~LkyT{hu)yd|1?5xN>evRwMl;*_C8%TrVGOSc zma|TB}rbX;7l&YJGJPy!a)|u5}{;=HHhp!hHQF2fD{3s$tc$8rWCk zKKObL87Yn_WDnMC>4KC%E+cMVp-Q7%1CAj8v8 z)2l+)U|ZA$cm9$=TSSg6t!?n z<`W?i{SE~Kv_Se*c3m$w1)l@T;h}1naTp&TEZ#PDAN-&eQM|D_Rm>ypFjW7g(p@y} zkR?l>9iqH!P@Mxlnuuj;|4bK|ncj9OvbOzzJbQRmm#i&Tj_GeWM4g@|J8UZ}0kcAa zg^=&Cl5iavIu$;Dof^LKsK&-;CFX<0YYNsl)MGr*R%l>Y#;KN4j}?R+XbcR`8HfyF zzD5%$GLu_|Uf*Y3c(9IYZrT0d_^HrPKP*84rLrW1$Wsl)ajfaV3tM>p4sHii?!?qAo8VnRKnZnrxdict+uxrVj->6~{+Qqzj(XR^tzA=nSoH^Aq5dmHo=F@Tt| zUxq%t>|IQ+5g#nG`Ef1BO#yo*hy5GGr6#E?LT-)W0=z}A?_?FcPQkJw^EEG4x0p%# zKA7rA%l}PTQUbbgoo4>NazX=NaHKD|t*-+hAwnQpRub#Qd(zc%LqS zJFAqh%mE!(xpMC2@!)8Qr?7-ES!TG==u4N)^#*Q*LdMcm4=Fy8hZHAcSSAfr$AS8a z57okh-i{tIza6pf0$r$GE&itr{+b^0q0nyMy39nSdbn*r#6k=;7OVAQ`kQAZh8g4Q zU%v1O??*@NQaRbzQs(Gb!uM;B{5sJ{sqT&y(fSa3T8S+s*2CYZHPsfG^#iCGc&tY4 zK)6K`gS*-Xo;~GYPxeu)ol^AEPj`(0YmYw;o$=TUqMkT%4f=qd^;8Iacbl!s{<~(< zi>CP?<~(S&7I6kkibd?0&e>a~z@CcYEjI4x**bVXdgzQEm)WP*(5~euAIV1Kd{RcY zc*H0gG6rC!rbexX9l;y&JeVA8j~+XO?w#47tb$JRc&Um$sdmwhUr6C+zj|*sCChF< zBLA$y>2LFq{`U6pGh^_o-Gcoj4dulr` z?D0H{dWvox^O6E77C17ORbCfa{|^Q6Wb-_)P@!j)(ZKZ^X07##tYtC&D2f^T>44Ua z7W(tv)_EXx9z`;o%xOOAu1x5J5^9Xia_I2#EszRKcHV#>dY^e4)_Nn}cj>_6N_58{ z#~iCq(&T)wF$F2ob|V&BRL;@!p5BcWsOrr22UtzpM0Sh^lcTB74@C-J5+sDozi_m_ktV*oA zbbnct##8aLEK*1dkpO|06v1yHxgh*B+iemnA`@9DB~y7WGkh#1LP$b~HiGkV5*_oD z(Q?c%@;R;|z+6W=q#2EYZKI$|kqDi^0f>(0D9gmwx&}m;0vZa*`KcL=$%6Q^sq$o%noTG5PCPY>Cd_p#3cFc_Bs1<3%<@u5-{W-JAG&Jbo_Bmk?DdyUJn5q56>t1>p(q?DnPTRy??jn$6)!mLdvk z8#xj;Cn6IKe|^ws0jY(mEX(jV_`OpFBIo~NHq^)otK)?Iw8*6*iB8FWco2@% zo$C-;-w=C%P`1!4FJn#DwXAdUOhA0>dK%P|@~l1#kGJ6NHPd*I79zxh2-dna zlw@NhMHBlXz6Q@&hAB7?8ZntQw7xoJXE%Te)swPjwTnDO3Kq zsL~|KpMxx*cihBZBybQs*kA93%<;B&BDXhSSzCa44R3E&Z2w+}L+5lB8#&DlY zV|4Q4i`Q#gcQAAnw8JujhXdhDP)t)4iz~q27>h|rDMcJc@sHdk>+Z$cO9;48@4U@R zcpSkGP{7la=Q=ATOY#ZioKVZgl6CJ5{ndPbgR;Jfh8hxeC+jvMnA#%^sRgT#D+=lp z^8#i9z%T;IgBX>9+;jP46^4ZX&^o1xrXo`;Mpvg&x zCOBAan#EW=;v74dq6;62(K8x*TGYYT|)Qt1$zJ!9%giv&ha*pwEFxY)U! z_Wu(-p3+oj=6&CsAXGr2I@_JS~+%0RTvtpvTQKr#dFy) zRYNE*t$-6_GC$rlcsKcFOtDrE1-hUPX3ka?VAE8#3g=wQP&9qPfh1ZVU?Qa_oX?yX_)PMQ8Y=VWDuL7_C^dE8u9^?X zZ~0O1VGp7)OChqG85d=Yy(=?(TN-A&8)em-<+Ui>kvR6F(~r!Hv4Dw(Ek+MM=Yj?h zlI>SK_f3I&hM{t%Ft`hp=+3z38&>XWT&yT2O1CD(b9|QpwIjMU@J-`EWKqZIVtM-g~dpFTv^y@ zPEh0A$enzF9HwN>1<$dm2|Nelg61p_;*|zMn{ZOFPY*%MfLEryOt9u3%Hpa6qIy~}0Y=mfpGSBk%)W3kL zU*75;B?e)pLxSo^HbQOI=@w**D4maT6o$)b?6mcI4@HC^iLe_XJGh)Tx-LZ9LhH5AWXsO6QN@9XlsQwbTSoK=}5>3&eSr8Pvq z(*m>ev<;I$ObS}`s#&M4^cG#c1@oaVe8GhIoS}Ge5R!?tF)8?<`2K^4(kZgt!i&>o z4suJxuF!C*TvMj5K!IP4YGiftH+^N%|0C&30Hdg~wa>k`s;hcQy1LV80)(VG2}xM( zEI@z=)lFCwga#3qxOD(AxCT%M8PwYen~D+y6*X$JDWc2-!EIcoNN_|an($=Y$7xX? z>Yz3t4le)9|CMhXlq8*6?mhP`-}%ltwB)cwEXjXR(oUpHl7?5tp^e36ca_b)ORDX? zC#!Jb!bIW|E}rtxHicaaTJuS)D76L zwIilR#1YMmt=F6$d$wU3eXvY!i=(RrYk0MF51*;kWY3wq6{Vfi9>w@?2@kppb#X+^ zvf_=^CN~&BQastx9`yoBso!h`gxV!Ftzkg*Q`TW^PC@j_c3P{ke>0ppt9$#WRyAw6 zV;SCS0x6muB+=4sQe{gY8IPfAj%L5EMeFk8H@Wyu*QlrCdoNZujI~WA}B;m3X1$E(eZ*GxDLLg?6Wp+m#rUtX_6fHhag2S6?R!v74*G3{O zF9;~$=s);Y=qmIc%!(n>>(+HoEx+#|BSu(?VA zN8w~ORT<-r#y(RTcnzUJ;FC>EDU?77 z@xeu@Z&5r(ERnP>q|O&-LF5RQFe&}i1pQ&StlKG`n+Uff4{4D_Fg#Ep0CL7dizji0 z$T-gc>xbCzNf#VP$@HTWJ0S5@G$)Z$bK-W_oob&+iko{ogw#bL>H`Qd75>;zX|{$xva%>s$9~0 z2dx=NrPjUQ#KeW{aH7Mpth)A>3st9c<#ZGN`+|SG}5W zi@6p0@5^n_CzJwhyR~~McXFDi^xF}+QqeWZ-4-&KtErnLmdC0Dim=5dN|0!m|Kx`E zCz{i_HZIwIc9W!>+kYi}DKn{KAn&BQx8umPw`9h&*V5tKACnO3jDjbkjhNMS?X>NT zN*L%%xJ`x~QXrwlx1*G~k`0*nU|%;ytR=5v(aXtNxV<%T2lch!D`wtQupbYEmcu1d z8AF|E-tWsDWG0{)I^e7SM78gB$-nbNU?*#~+L-x3axY>NipKvrK%;aPHih)==iV?2 zmF4*-@hFlDdpd04@DcJrg7dxp1y`) z7I6j@_Y~!p6CH++t(V=@|A@YR zq^*G>D!={Ei6p%wW_OcG(bu7j{<_pl{93yr(K40ro^bYpfwul z;b~D?sY*s&6@<)@%t~2{knHTH+qEjFt@FVT_V9(IU;PpJzks=1cN>c1=aB{SXyE`8cLGG?_CbIc_C1~FI2c9v}W|}E6?I7SJE{b zrH38AhxbE0{8c)wo7ac-Bg@^XbHoj;T;DDo#EI4{{NU^<4Gx9)rxN2``Kl(O?}qGL zJ>b2N&>Lh<`@WJ6YpM>rly*NnWC~f*g5uK*Yz0K3VWLW;81X?66@&oSQm4ZEe}RN> zfl(LRsReUGZ1iKTuqXj~R$X*WCw4tCPE^s!Y#7DIib0lT79EA)mL+j?EI8}t0g9UW z_dF=rbt2JZ0kryz<=uaUi*|@$+D#2zAJc|jWm&yd*bB#cASL0DU-wXwy^^CqnzY(UMotXR0ZE8Q`3dSxav*5}<)6NYg2wF%Be?PATXOx${byfrJv>$pm zqXw-MwJ)!hh{^^he%?X-*-HS(snb?GXExw{pZ`R@Op#1Fg(j?n=-rVjhdl6$pvr{2 z4=M)GQFP_Y%EHtVdekt$pQ~~uRq5K4zzVYcYT(E#U^Ab0;k2GsGr%KnXu;CZU*pubGHREX)Q0wh6Pg`KQ;Z zp)U2=wV~w#S2mfPriIg&0ZGnbDJXcS{rxi&JwK4ZdV>=3%YF;Ss2&e%uvN74l>{f%dlqDzi*<({;ak&aI3&JIqJgVae5>;&J&KdvtYBv(_hj%a2l-3|6_LO zWgowKqZU*T@`$Wl0r>z&wS`8{^afCy{}JJe%xCMC-9v1&M$dWr zLZtVZ&1f^{0w48P%&BB@vV8GY+r#yse?En}xAHuBLL}~#dX2uyx9f%_Wby^?Ut1|J zLWBnkXl@{L)MG%=r01g#&mk&4s>gD6D10Z&JB{w=5g{|oTxP!m(qY{eJcY%kxPFe} zr0eVUCkC>tN5Ju!_}~$YSF1mH)@tFKC9uc~`PFdG^D4f!kNNy9357m0j&*%MTbEA57ov{M$t*m4X3A?p?)YK3VaoTLGO_p%gN#sbz9mc(rr z5PKoFd}S81&R~$Y=r1gFyVu*36k-+8!#yURRoc~0g&5-Rccu5xx!bI zy&7?5Ui>S!WexYwuAr(9D(QANC^kkWP8B9@TdK*$V6H5hra~zZGjVHorVy^9wt*i1 zi#MAOb%OJQ69kJv?PP?L=h6h7<)C@c&gfM^ib(`+#7gbAW6)jV9Hvt_SQZsZ7g`5f zk3N2EdK~dV%PC=V7NMkt+yh70oA5YYRH`BMF#bxMST6i@8s&?c*W#2HFc9MeXuRac zeGqhjC*=CcX*m%SJ}res33LBWs{)u9@E_ECmc=PQdV$lkCqZTDNCCP8@)|TST1_*T z;IUh@^O7WLDY}ySDkyn@HR{W#JVr4nbz?R~s^dVp)iebG@t*e5GzV&+cOGcY;Dw{o zIgnU|TF>0uNUQ|m7Qxqy41vdW-EO=N+CFwr3@#125mJG1t8GD93@2w0yvdO#wmbm~ zKuova58^xmj0wFDnKQBdS5oHbD1tq!LQN<*SU;nw;G=|!iKzEArIMArLLvHhzz0l( zP~Qc!UdaA%oSNy@3<&3YME9d_DO?hxe+RY4o$NlD*9_QiRnoFM*Fir}rs+G=)hbCM zG#O4M-L!>h30WM&9Xn{x3J7|~u*}c8iDs-G?7e_-XOnu~H-jkVdH6#KKOuU>QOp9; z9QYf&oW4>sft74m$Q(H{eVBFqpN6oeexnHbngwTq{UN#UD<6%%j-mmHwyTy+T4*~9 zO?}EK0tj@6_>W+nAcGNq-aiKmhjy@}SfPpbS*jvRqxMF3xOP^`n#8IrH3RNv@=@O3 z^F9+A->jt&Wf8k+6^>fpfhYbkoo?Rx&0H+tBUr_K^phWZVvQa)YgE!AV>jf2+$U0> zVl(st#}>eV{Eg@r;1sMu!KyGVca_o#XK-ZSUK1Zm&lXBGeO3|0j}D)=lR@lrX|Y&7 z>BtAz>g;M}+L*egHVJb9{RzUkFqQ%&nmY0H-?0Z;7-K&Q1kVVdO`D6jFM~&2oP!iG z4D(4*Wl`A%@x(#!veCN7us|Pgmv|Rp*Zybu1$4A9m4CYWp*lrjaskXBiW9^cZPX`e%9no650)9OA93kh#9Jumx`muxLNmT7 zxMJr$!;00d2@c&B0-Nr88rwe!*NJ^ii9(aS`%6%Q>D3-(jPuKiKp-Dn6iuS;9Sd#D z0Qb$6Jd(DkfjK6^&FRLw<^Z*lPf)GxWNJdqsIgRDC~-!7{yAgelH>n|^=v>NJg`m7 zis&33?dMPbk<;HrYeI=+E+NM(2c*P^02oZvSOEU6y|2V z5Y++4lNNR#J^>5F;Xy-(=oc@W*1>YYKG$y+Uz+}NICh}u4>?K{8_pQUM3sUbKVqLj zAgk~VE*i~^71wh0Md4)o4R3T1rCcj@+!TNWS(y{B=~dJ);DcKM{GM`e1C0{*TQz8> zMQf-ac@s{1eEpwmAEHXDeXEK~EIx{;kkL6FD0b1|+DU)=n4mNKyLIIikckPm0Mh*B zZpgFgx#ez&FU%1;jm0cbTS^7>&FUl!-m)r{a*6v|RC^))`CEVxvB%;7mn&d(0q+O-~d3^INGArr- zwH-s&i8iv#m?*WfMF&%ov%#dit;9msg-Zs~k}`s-=+1Y6c%?33mbonB3;@ks-9WZ+ z{J|P9hc+y@Qo49l5C&c)LEvPKXTQZE;VqWIQ-7{yNv8^85*6H~NTMg*(?$Y0isxGFqo(#z&=1rH`x7un0QtCcAdh%!^Hgy(h>tU!lSGqj7x5 zc#xNYm8dS$xp=-eK_B8)}nqspkZ@jpKYTc`kopEJF!QbydIla#JJr`BTqE%_@6D|wBAm|*byM#tt z{H;b7N`N$2Xjsov;;_a?yFh!JnVAZ9T(Le(Yu{)O%Uo5ph&m#gUD@9sn|mdlQjTYc64b(5A@b22tTMSPs8q(Gdf(KQ3s8@*mU_UU zMpokf`1QNfj!{KYNqu;KBPS!hWX zQ-<~Jok7Y2ZqV`CpEzv6qz`|rCBxY_?pW@S3r~FEz?GLInxF9l0s9LKxk%zL zarkX~1>W*9Ys5&30I-J%MB1et6_g&T0PVxjZaSflX&!Mr=+*i>r#$4pclnI0f_U0; zYJsHyLDtr-3F_Zm)!{1ZS$@iA0-y0^0SPJ)f+&5^Sr@~dEZVM!y{fm%)fT05*_~0c zN#E}$4B+*#%h=K-5i}EC$2zO%Cy@6P+b2>zYSdq#G%%xlGRM@ca9Nit2wLQR-8%s5 zz78AA@8Jv0ULrd)lqMH)#drpt4ET&JwtMvzX(-Ok4xp#!zwzGNZ+fO6SmaG&?&d5i zbqd)fsuVSfWc}F1-p*`x7=jpm(m{XXPecd#JXvdwJNj>5$U>lekf#P<<#EzE!psGR z+50$)=H|9UX!N#X`Jpg<=k8Y6D8*uH7vJ;>8=d?mcv95SKOD_5KFT0#)6owNDj?3U zNg*J0;TAA&N5=cMx!yq9rm$rC^1bTdSJ8-Jxen%k*0P=zwpvGJy%INF`>HWesr~U) z>m#R-3w=N%N6y}od*31$a_$2(~&pRrV@;J6V zFcDJ&M*)8}@k^&HM4i9$E@FvGAkK`cx$J|)!>=a)VJ zMmJqx1tI1|4B#4rpU{+lJZ$50#f}GoT&`yTm8^};B5fa-BdNw2Sqs-gOdo)6X%Pyz zFdG^kGec;!KZM=4EJB9oCYS-E>_XzDg#H?^XMc+3kZIEgWa>2uYJ`p?>ls8cDEPs% z!i$9DNSf!Bjtsdk1*wYy$4gP-;cN>`#vHgt=52>+Y$zNp-Mfb(^GL8!|LJGXr@)*P zi&SQYu~zjD?O02mMt$imf9Yeei=B=S+-0zl{5~)PqA! zW4Y_#8+ zX~ZqBQ-ki|8Ixz>QP}XQ@$(@1ibFzl8fm#-CzB{cgad8^xq*^%ns%1Lr)zYMHdCk7 z*an?z!*c-@3%8-CIu$QSfgywj6$g2XFKrGvQe%HjM}Ir~+V=0vHYfkW^TTWCOkOud z>1d`R%4~8tG$2ZC(4hw`QC`G>wd6^Cq=a2^s3{u5R4m}%Tu7^WFmV} zx-jp7Yx^j@!RfqnCU9#8i-b;rt{oIAD_ofjCDMvHqz55t#(G!@7&nXi6gH{r87#NBo~q`S zSwlJBrG!MnAp)Ch04kcxXc`8(-YvFpHxpAb~eA|3Wwj*P&%^Ux(9vLOYtyu+?T$Q#%=lv$me)3fZ-y$}s}5V%!V=pXs| zuthD+I2i_g#g#P&m7!behrwUnkNc4_=zQu-E7bSJFvu5nWk1pYovP7=~!Dabga1*FAi;NT5T7jE+>)mlZ2#=nvTH z;4|$iE9TJ>TkobRqU{(0wMpS;qUO(PE$TN=Rk+SE5%itn^)i7X0PpgxFH>;JQ#>N+ z3Z)ADDXO`OF?VP`VRzVA3{T%U@$~AU=*vZPCz(kwVTApP-GDDY$cMBP)|z|J6sm%P ztc%S2XPQ;;Jm6*{2$&XA(@?Dh8(r8|9}<{N8AYP78n}ngq-I!O_P1y6ub|k~y$Swb zqy#i`Y;rsJjQCs{SPUI%Cn0gJP13U*_0jHTRs7;qgj-}t+QZIri=MGD(bPCNv=#d} zswIJ%?L210f|yxUcoIo)Oc!@}O^SNKZv|HE#8x2M!T4I$6VWGYuNfaw84qehn-F0Cy#nVCt1fWFaR~E zhyyRmG6IEPq3B34n?#0f1V}v#Fo3Ciong^}-Et5eNK#v^lLMR6X>C$stmD%?i&?e1 z#_H7Q2MS;~ojE`pR}!uk#L4U7Pjv@a^m{S^>*1U{sT!=DnWDEzOm0zc^gSS|yluz+ zB`)s45z;Oa!LctZ>QtS2c=~hc&a6O$sy0_tdry45IZ>rPQ=d-@>?e0H}hdc_cH6BD<% zaRo8Py_nbjY7>S7R`Hg-7Iq|&!6ggK?A7l(Q=XCBrOtq`W=zZNjlF;9W)r^Y<4Q}MZsZ$}nU z2}_M9^g_dzd7T+{hpK+!dH_xpsYTHl+3jSKaTys+*enzZ^m)V^r0#-!dniH1AC*yd zjji#y2T{JNRtWwm%AJXZ^#q{Kvxr!g(aexL)pi`7L)a84Mv#sC({60>Lmy zZAsFor#k%#MG-KkQTqU&d)X%7c$bP5ZD6qTbOdXNL{k4~*{SCGpTHdHh|Cb4gD zI(Q2btF$>v@U-I4nYr{btP_5MwRddA4qqD9_a870&+flW%!EEQ>w!z+)!ub7+KfyGeOkc zH#(+u3ID|2;@Eyv?as*Hl2G_owS>iDc;4g;JWFMQmOIY*V41*w!phQ`dJw=B*5Z=? z!oFBXXrYe|4*9xfzC-zr)I?VyHo$_BiY4%1EwDi&so+n@I~Z+LC10^;umH~^^Md6! zv;Vr>crIxy>FTgmG=IeC3x;z7Eo;~_u~Fg$!a|P^e(@G7ZXb{C5O-5J$4ey^{go8~ z+b_1}k-yR@{sf^7xIW^CK&FL(4_b`YLb;_r`j-3dqLN(uJ9ZwSC^N#(N6pp_KA3#{ zs5(olHCEIz4s-CBA$keq@BaRE@Me5e}eA0F%Rlfg5O%6@T;N%Jgb9jN_j& zL}!%l=Gbi~Lu-Feo67|D3zo)rj#XIEgNpFcO}6ebb6foDm61|e?;Jnv_ljxwp8*nq zhLEg`Zz`r0fYN??hpfF!@v95NzAk8XAC=cbd{i$QjifS1SYH1c8V9)Z6ShcdqC?TU znX-!A7Wt~i0zT5nv|G`ftNsnjt6W7BBpIhgaE6zM3Wi&Vs zT?#k4I3AXhd`p=M6104lgG&ehgocu4(r9IW8oDSqi&NUq{Uk3`nt7RNhN#5fbDfLt zVk4iiU*nK9#7IBr={EqbK|4sXCd5jT1&yqHWeh)asyjx7x71FgnJ%@t<_@Q4zY+R> zD!t2sl{;u_AHmXi5<{#qZ0ik5#fYBqd>r4{b=u`cyBtnv0fr`*76jS4*cFonta%w} z5ApJ%wkdp+$>5F$?VFui+JWqH?LZNQ$oP^OP-MXjWx-7!BkNglb}G$Tt!nhyVDj2PMgokx7kDFHlp>A>F!q z?w0zOL=vbH(P)U_%Syy3`L7r8YpG9}3JY=28&&z%W_4QYuQu;iW`p)|-~i~jLr_oN zCtr?Mp#N9LAy)^B6_)hIy%ZSGtY*1viDAi;MNWjE>M|^^<<`;~%ebG)m^|iA6_mY= zpDzJ(>i`4N07L1R@C%%7=>-szl6L+D1^iq!pN>v;1_tk>4eE%h~IG~y!VtRbh$-MUp3qrZ1T z!;((ks2YtmSUzMIuTmmC_6-c-*HEQO_vb=16bAm6`WK2DUcAOhJJS7TV zv>KJMc!Uo71y8=-;*N+FCs|}f&s`LF0ZC{S(BGv6(Hw$}fH#hFUe{0JmOlJVldHyw z2pw5Rqqj@;DrzdRpvK&0HR9g3H#ahRDPnJ#0`YC9E8|060R=!3d_^C(#%eZ3IYsF$ za>Zfl&Umw+%y}HUnFX1GA%rn(%B7*dI33MThq^i3 zMG3gYMlk0{mL|sm4Yk7cPE1S-KxZ66r}~4fln-RY7E3zX>S3?sa)2gQ`O+i!PyrY! zG2GR@^8U;S`XT6pCqUFUWE!3(iW6oMrE8)jiNh9x7V4RY2@6m-B+kHYZ>{vMgQyQ3;bFitndd4|i_IfCcN`$0%nE7-nx01F2 z-lKHhl4EVal!)d4ZbI4z$GZ{$b5ojY>z~WCk?D(GO|1?@wH@Yl8=dBV!MSGf){QvZ zPO`-T^Ab2GH7tpAx(^K)xl@LYW#qD_%L2g2VDCmEGVTT&RO=^!2kJ@72@+_)Z)e`T z?nonRNTn-dHDpQ6?1i$J+g6{UBvy?)kf>4QynlH)0%S`MZ_ry<3tStFir!hno+JK@ z4OCi(vV+^^U4b@x=mLuHpcC?Bc61ff)(5>3Wf9|NjnsGwya5%EZ+eb;@DM(Ol!+EWs!$f26xqchn2&(wpd zU=NErXkx^U zep&$Uque6;8X_`I5>PXsPSO5Y-Hv({w_@`EOpFnkQVU1bQUj^M-9NQbny%_nM68mu;eKN`p(OTRT`)%-f zDB$BY$B>G2t`1Ew31|07j6vQ213W zwd!O33wJcJHI5yr-|9G=VQ!(cjtVC+bXNevR{M&rFK7Jsz~DUx?x5<*Aw979fMF21#XyO>E$!d5rvoHwqXjlG>ItA=tLIzq-`xXmZw;x z{Q3>zz{<9lAP?fi$w3F9t8jLO?8NB+}Mvg`88~c+-Q3QR9>^1 z#)PN?ga(0_BB*J|vc$uCr-c5fVMbdl{^Z=3u zkGRl7JLqjfCZs2i1vAYmR=VeqMI`61$G`3Rx3SBrWEu8@2DO9;=CMEYK;~+PUxS^d zlr%LCmDU0un=Lse04brt=xH?!t(9SQb?od)>?aisI!KU`mLD^7%~=RRyCPkb*>Em6fXm4-HW1eA*J0 zJ_nxR)<8guxW9G1NF5@Vle9t?FAG0ZH>nA0cH0llAiRXW-Q@&53NvmHvjHnuyEXlD z_;^forGOPH2u%Q(q6aF}xF60O!L!Dv0MG$vjsyQu*xjrCCdrtg!g5EnSK8n^YhEVINIKyg#Hy zOIRdR%>yZlLW}{TGyx~{DkX>Do55xnvJ|L7v-+MA@_SEjLey0_dipGAqe8tJV*Y2y zZ{mE!ao14eVkZxVUp5!WuU&c2UlAP=4$*qvCh==CJjGa$_bm{RY0j}Xp?KATQmHm(tGG)Cs9*5Tb2l2uelMGrET@4~v} z6(GBxV)+m4qyIrFjJCh(Bf(ua*ppP(n|jFlRSjkzrKWmNz9{E4HOLAnyx}c12;zxB zr5_qz_`PY}!xmgCGE^xIl7)_n&Lxt(5JDjPr0eg~O zsv7@dQwmG$M&PUw7Q@*+5f`0$!Mr*>1TwtOznGM}G$^yawUR-A7TIWY?=aG~ql;k# zj}Vn?uR4z}S^NDiAjKX&3rD(^P~K976`tjWa9rbdVcrkBNS%!3)tgl`*@?@Ihg|Sz z9)@&NIO+WecYoG1DNAWuttSc~W}c7S(MGDgl2oUq%{#6@`a6no$+qEmmqU_XUJ$5- z&mgAGe;fCur*v9NqqDO1Uu;yukDN=jmP41h3C9I(`XYgNq5ixvppPpSqN{HQX_#EF z_C5-fFQhW7eV}&~FUaC5s})oiqpjtITgG=j2d8WT>&pXM}9Ck*hN< z^vp*M&PDNDB`=UxB(xhIV&0Hz)U{$-I$~MNjsPJ(u0W2WWo@Q3ZU{9k*6A%#Ozv|D&P=dj*viuWwt%P>NW(P&o8a@O^vE85H2~3V4xtJa_hFBD) z(wWEr%~lc3Ft3{i9GQ)>vC{OQ+FS32T4H6?L^uXjU^&QF!Jg_$YLQ z@>6UcPm;Q$NnGsE5R7pmK~ed1w1Y|}WZu{GOI2D1NBp{>JvmC~p6|fq0_PoSvfNBJ ziTLb8>E83%=UJdt8wUIaPYr8Ih20_fi7U%A$OOng;WiZ0uoO~6-cv3tZxLm1><9%+ zG2-lhw>njdr*eM_7bNUwA$|lu93PaWQEsy?;5sD^lT4%21q{9s;s3SP&>l(`M{ zXh?E567IAPVgrD{N9}tJ*VZi)aF^)_@NrMuVV*1)#un{>Vr+w-2NPN4S>e8omcdd{ zl!k9Xs+=Oi#*Y9t7cF5;;kw)&r8SJlLhc!b8|0P#PCk$(SqK-v2*n1yfu-8YBAM)$ zRBD-zI=2tGf&KMAG#`wg&(~~0Iocgga}7yswgs=OeIPZQ*xFX#$TH}^1V_67EAqRp zA;^Y5V47GIc7Qww9lnGqm76Ikho9F&$(7We#U(faNGQfxKTi2W8(CjencZ#n^0$a$ zuLQg31&M%@C|MAt=zPjV@r2DWvO!(iQV%P$c@~axXescmGPXX86>*{j+(#Th&#&2R zv^z)6pgPnL?57~e`9{wG^cP8&WwAVQe$obf2g89KLfsYu8e=;s9Txq*3=T=*ryPuM zbg9ndh+rm?ip8i+1*m#~L!QWrI<2g?6|ZMPbPYzl-h6~glBu2GTV4XAwc(@# zTg4zT;qiPj9C0Lw!pI%1FhLlAj+(|}I_6QFWr^~8Tcmj>&yxX1xh-pj+feK42|^O< z>7UHpXx}QLC}aOrkXu6`l656kIu-XJ%lx zO`MT7o6_)AYV3^)Eq1yP&xXO}XDr^53*Bk5&g)ssEIqjXNj6w#FSE$D#1z3#vVQ|B z!D=Jb)`it(C?c|PRu%NzWzocT6FbELXrj2txSMu|1auVwcPA>2+?xG`=A7{1_6K=_ z%%Wvq?W5-;ioDER_E)56F|A`Z+UB)bo_a{S8=Gg1RWBh?nJ`e-`z7LiTfwL?Xa|c> z&D&?$PH>7x^X2spsiFFDX*E)yWw#P7^YrNSd1o!e z-QA5?$s$xE@-Ry36Vb8VzxKWkSw5uTIhS1EM5!QqL;EcBN{v+2~;*~l7-+imFErxYseTM>sb)PEErqDUzg@{Kk( zKITg}-kU~%g+-}!xk`7TgECrK-9a;cb_MDeQ)#juVaIqfnlDoO*k_9PKb{j#H`0_r zx?40NuqJexDxc+PrTg6c6%!Vse8(IJm5BKL8X56~O8YtdZHwd-`t@@cd?boHt4zDe zIJKK1vD6K$Wqm&^#9{GA9;}P0dFcPhu4U~@Kt(3Lfub)f%R`lj2}!@5#wd#pOUM7oU+(p3w3jB!7-ZW za#-XsmF2MNyUn-%#LO~GN~l zz=HDdkcfZcG}CTmm5Q0~n)JK$%KAUK*l02)-lIg4z~x4%=G(tR{wv+f-k>D#1fAe+ zO}3~EtzE_t2X|3LcMWR>v*66g5Z~HK1P7g;K`(y#+7&kbDuQ(zD22nykx8|VGSGUs z?y*xuS34d4`Fc+xgJ9ojgw&9F&g{kdWWhUpgyntqkGWE2|nEXVl-pc#`i;UCgH{o7r8i zNU8jY4u@{dG?F3D<(Ks$QpjpzS1&B8W}^o!Uwf}a+z3^KJm-TS?jdI4@Pa)dW&?a2 z1MQ@;bQv5NY16+v)t(hNrY(kF0?Dfz_LDc@iv6;>tP8tz=rmDfFV~A&j4xl$_#tX zg~gqQKl!_Q{mN)qj*ro2v;vLL3&);>z((POFxayUvZJL!rZDEr+THE4WXwWKx`4;4 z*LZ7ifZ`hFjNFFMyN~kaXph0)MC15@)Ne?$nnXK#D7}5mNWZCDqqh=d%4ke_M=`Va zMy(xQih6`xYp}VI6nawz!4rypE*Yk}p#_v`>2x=(_F5G)AMHfR=RwYR&YV&|-t@2% ztiMFbHot1kG}V8z87fO3;onLwTIiXsOPiy{_x*8^K0-YV>?pM4Ul*Z20qCdG*`y`)|4t zi$dB=17&qpJQ)Tx26RSys}e2FjaBpfG_(ZVYW5hb${^$CTLvKxH#2~qNTJ6OJ{0P; zbgt$K4_vYLN~36Yau{>J5TCXKm(l#9hA#95d@Z8-GoZ5S!Yt&V9RYP1YiCR8O~37; zB;o7?SUVa?TNb`*oW({VFEEiAfjrJ<`{F1FlQ3Ze0<3DR9Yx|L-*pH)do)6~C^rd| zmM@za1t7t@uH}=lp!(-Ii{WS)zR>@;e$Sxrn!4mU6|~|6P-jXF_M8s(e-MX*cAS_8 z#YSr3Dmdj9naM^7P->^yDhlUTw}Bt1_-REnEO8R+2GQn~F@hTi=qZ;@( z$*+;@C{1>bHIy$WI6-H8P|8`w#Ko_UqFR8bJ`N%i>*HrmIkiKly&7Oi#~&3CPLs6| zlrkPW{J=s!-htzwWcJaSKqU;?Z^xK$&Rbz{SHS}ZU~oC=vkaLJ+;=v5mmDa=YLRo! z*U^0_&LEM5xt>mw)AYYU#&KP*;Xxwj1fBB0D`3a65(+rYpZoH_M)Ka{KY))|NDW|g zzzT$3p*rjgm-P9Ezfp;wqYL1QLU5L0gFZ8R%^RsHOIRJSx6-cMC&$LT_zdIKiQ_U_Ah_ zjk29wK~}FLiN{79fFBy$YDkYAD}6f-ZE!ljz{y%KfDkEm*oE>zhF^dm0@GnyWJU3L z#XXrGz+b4vag-2tw!>3j2E> zs|edfY)jc{G3DyVzrpfVk#|KY1@#-4yMxNP6`%@kAyw`EwP83_Z4fI~v4#b253%;q z90LgsYG*D14F)#hL{jo-D%vf&=TrG3I{-?(cy?FsD|q3P#|!Hn%0vpQYGBuLccSE0 z13?mZ$4)AEmp-hZPYf>Udy?oFS=pRt6{c9QxrLi4P=oA8vM0j>&ETEi`Xr!kZkLfR zskIfaZzfNp)Q`geD*q$4V>m+$Ynr6I8(Eeua2u8c2}U(zRPb3@Z$vaa(N?Picvanq zI}GUE*@mH#34iJ~D6xJ_O|TTl$)9Z3`f_O5Ph{e#cfCo6G{W&Dj7=TV!`}G~;ScQU z{XH`?*QY|VqSMMYlX>yK)W75t`lzSGPgJY z(ZR9=FqqG<^O$J~FO`O+%1x#pVKj=f@w6~UeD%3a2ZaSEcE!~!h?O_VZdSJ&XK=(D z=<}3BUgIt`U^j_LNJ9fevGR z0AtNWJ5nA{FeD8!ab|gU2;>*zdtQ~u1>r4JU#aB-1b#h*j106cB)tc-{G{yHiG5)?e6ij}ew|hAt)J+~b+;#JE$bcIf@u|TKJ%lL}%6v;j&8kPE)H)?biQ!ux} ziF2rv1waS#M!%$jg|D+CY@-{h${OBQi)g0h1c31=$e)2^Y?)MH|5piT^IcVvw3wD0-u*7}dY&(FD?S^-6?t2J@LXqtwnapj{*1~@>egmaJXo&n=+X2$0s4U9PPd&Pjd zi=IgL-pt@ZM~oVH9sVaMU``WjeYOH?<5}?l2qUW~KBIPc&weFr?gu%>dyK$hxlwCL zgAu25=wvodVP1h6i4LOg)V$y}irOu)W>Gz3OMR~h8!z$T+7v4&?DNbiKoxH27B^qY z*ptc{pRHlElsJR003|E;ky1hIBJ?U&uSUud$u_jj0si$_`kg+{XfS2QiQk)FIV}}a zeds6a_~{KBQ8BPpqef~$Kal?G&E8pV9nR-+ZcO_E%>hTU#3QhsYX;I>FeAy2Un*gn zTe#vRxQ6#gPktT5QK7&YCxGlR`#hUztc{vyc*Re7eh@5$y+8;{xGh+lU#5E@9s`tx zX^)fLYE>fbo_hrt>`PRrmpvd_z$u8K4}rVSqpxN6b6?jq(u(;Ca3gZXS(?1MvPT)p z2A6_*jB>69Ur(8-@mO8HiSo6I&y?eQt<#v1&V9BEvrfBFAyS#a9zn)+|XKXto4WZD>)>vDHcUZ#1WO`-}5M)!$+@*LdG z5g4&1Tob)MP~A4t@HL9ESM}GC$V>jhasldQF~f}V%w0-ul7Q8hYjy?UCXoz1$Fvr- z@_CAs5DS{7Yt#{{i%{^`YEgjpMPe}(*l=~c6}i6E(2=0NWl!;bt|$m`@>d2nzW9!L z9%uQ#{!7dG5A?B~N7`u$Y#0fi;^)K$yYfmOb-9naa{kKH{a_887GZ4^A7Cd?+P@D| zmtSEyL8#>to%N#@1zH{d^SB4Y7o&C=b-uyL&Y_4~Vhm)t?iolGP!x1t3jbn*>VvST zm@6YJd|9#-ssQjx9=R^0>NwS?_+Q(iHU zq6&f^ia?geN=GgW3`|$fT~7Wth!r!=a!dW_Q_8keQKp0ea1EL%h7f0DmVTxI!(SnH zJ^31$auY@D_6n*H_C-`|zQ_XFbQ&RK5#Bq%a5-%j19K;r4EGo;`9bh$lR%rHYPr60 z6WgD6``5@-Qsnv)*ZDwTb%s&Sw^|9#%jFg^$oElr({fDxaYA#Mjes zlaz3DxW@A2hXn6v5MJ481|92<)Rb(KM6Nv4f)Au;7Z+uUX#m$3m^6XUHkceaslxHJ z4B*9FKgRD&xUqzoceIb{G4|*^77Pt#2@|*NyP4Id;9Co8%?D_8LFJa$$>p8EU$BkA zqLpy+c$vBWT~goV9cHd73w&Hp`~xvATnh$eQbFixOE_~<_dh0rrPgmoI+0`>{tnqu5jfie1LU@*iw|nP$I4ugwiZOJ%Z6%IC>g4P3#t% z!g3nf5J`LZz|ec5P<|<9bFw^`^$o*2g(=hr<^Lhw1&5o;h$UAFQLIenmPAi2%e+c0 zbFoCL3l1lS`;KmgYs%?GaJKeS9qh(oDr#A!-0#a~A&p*U-$;Y?-7hL9f5ydB7MGB` z;Y@<@ypByzaZt;}&Bc#6>16${c+xL~*>1i;e{=G@_say1y zj#=;^r1dz@D@5}kjO4Jh3)!7qQkuB;9yl^}*Ag2})7xm$+Cwxo*YFsllsvW^jeS=$ ztghr8xIP~Qmo|?-OoITwgmd<)qiiZHWfC5M<)aMtiGNCkcCK=bsYfy-o8a<`FrKRg zLVnguzIE1GQQ-#KbkuCkbxXX0g;19_2yY`R7PqLZWNcTG-8V?@)7$aZ_Iy_0&9Fer zJE)Fx;_5<=20Ff(Oc?8!*_`|*-Os*+c%xlq5t4i#quoJd!RZ0~Vsp?^3w1QJ8S809 zcsbtZ1etm2!&;T8@I@$`{@`LgpdaCuMfcwJxT|WCfB0lp!&>-4M>+%J5Ap>FNsKg_ zZ0KAj0VbuMN=b7qB)y!v-+6(of)~_ubMb~^D!^~dg_j#ix_OPMoorTDAZ@^Ug5l}v zPzKIj3>j z2N9MY&30yp(+c%(+Xw@vwuM;HZ(v9mFhd1OEL^O~!+IX59Ui9(`gamUzN}T*B;ZWO zdT{Li&9-tIfvme-m+!km^<$VZViR0Wu$U&|UN0*n(s#nhQ&BT-%0SEQINUB$Iy$!s zrRYgS0t+V8E9fDV4JFBpLkL@K$hg|`0QK@hiMhPf)l?Fyto$dFWyUvp2&SVlo2+7F;1jH~| zfS>_R5(L~}P*jQ(CqQjfs)L{+Qauy4xS#_ff}##86}K7`D^}DSz=AbORNRWy!KHw8 z85Wf)%J*D9e}E)2_nzflpLgSm`}h`P3+(oPIMi2y4jyEiKsyRk#XqKmYnPwC^bU%a zdP(Bt`OCkf@knb2f_@b!(_9mr~WH?>4a5ba;=e%DNbnRJ9_04;QZL)atA+P=f6Wbq*NX+U{+gU|RYB7Hozy_6|2iq9%#I4Hz{9di(MUGYg@nA75-M~Rk@VC$x{ zg<%Cp*@q(tsoV9+rMhE;yE1`VLHfgxg`&m`<^8Hj^RHIlrD#+T2#aO@TCEoKb~Oz- z?Z#PfKasK8@_77K<F8ks% z!ijy?8x3>z7hPu^^$C?1g%EG1kuH%OyC7prxDD^1NuWq%k-@}UWScfL3;AID-8yC@ zE_d)Tf!u5|?V=KBAZzp6NPyz@U+u6M!?w()N0gMT=iapx@YPV}8VkLow(3nN+9EDl z+RcYg0L0=|lgfynjRvp7b5`w*(GwKbhNEdwDUdUEr~Yn=mLGi1yu&<{e~v%VWcCvN`zr8D z-X=|X|J&1>NaKN{q`*JC7Sa=81iE0PEX&K*;AiZ`>obH@6f#HCM(az3Pkn!hWR=v0 zD@Wsb%&lYdtGc0vRZpP=RUt%NLp56PVv^2uYpG4CA#dQ50?HE;Y1Ny(@JC6DE`Sv?v>)LZYmv~p!ZTOndl9r4uKd+REeaH-_xWBuMg{Sw>7;)^ zy4u8p=j$0f9|p)ktg?u5Kg7XH9Tr(7ImLUC!b1FaDNjx23mvCgT1jjWgK<_d9oj1z zBlZ(*=x|Arjp)GB(8d({Lz<$myh4|;M?dJ4@H20ad}$eN6m(i#BOLk0r|GW_g5|)Q z$m1Ra?9xG+R_56Q8zoJFunJJ%P8p`e4VGybL25e~? zREG$xu<9ml!<|+l4(J&xdW6uRAY29xar3ebT(2ZiL=ecZQ$5gz=iEO{Iwvpr9-)Tb z;j|a`#c}?@_X2lD;K!AVWydMH+Q>Y~QpqJ5aGbS~wQIssHxMmj374vfEEn|(2a-#) zbxi`FSUzbKwo;|J&-1WCB6D*^Y>oa-&hw*MakI{e6j29m<9x$GU$JBGB{`=z5iEv+ zC&CR=c)+Fyw{pF|#_AEB70U_9&qq%)Cw*A-u%eYt+~`jcMQC(j#{_y~f$mX)g>`V= ztUN&lQ(Lz$h=XGK)J-oUfqNArct}0Wfw^~53Y{u7R{T~>uVVVa?Je;%ok7Rr==us> zL_-brhW@KB5sX%&JT^C>V@Gd}c1cn2Yf{Joh!I{UCK<;x#nzM^xQ~+_i-P6JOy!}$ zr`bsC(4Q$HFdL}La&esG7HJ2yb@9d=5bDJBIGQ@mRhMfCLP{5>iTT>X0)@fM}f z(JiwNxIgRauOALp5N*4xVb0|y`-fhUq^D^@k1qv>BOmK%@e2~8=?5Bt%ZD1>WPXel zM^@|uF3%2qqyS$F%!0!EQ^G3Y)A?iLa3WUp9OOaab_AZ*)#-2-KdgN4bwq#@e@tlI zX|$y$hpsYumEM2EJ%0S&(axi3=5a0=Krgs2gof9_@6m+`f&-U`Iko&NWNNK6j_?_5 zU8_y6{n((R%|#ce=w_OSvWUaKXDQ(3v(VEWjr&2)cC-fK%Bq_V_IK>_4Yrz>Th3SH zG%Y9Be=fWT3SQRIBGqxdLcn(J6*UFR@^BiI8dGf-^XMw{-qPX{7Z&^;5!yDb+(%z< z51SqfN%h(d`hiV#H6XG{NoXp%y?3W2>ui=@L&Av9Abtjm+6n5^&aFESE#*z@ESOh9 z^56(X8@vpg)JuBr6+2uBp~~W<&wr|#DuT!VX(6R&HEV`SlAp2L(YH3ZkNShWutyiy zt}e8XhD@c#->r&@D7i#60!M%SR!E3V7ymkk;#S=`3PL?C4a{QI6vDtOQKsE)oCCpt z0$JhZM`$^e7U6U4G!WzY(F*&B?cA7#tC#-IK}FcC;Thi!m(`2yU$_l91&W1YRKc$e zEImp?-Dn7&q#SpMUls5MRPFuxq>JtU@ z>`5S`&DdeBlB*wBTv57uT=lP&XsTEX*%_8-6tED=)OUIm#u#$dqtjwfX-@JHM*Emx$j=GM3Vz;9mU2q$ zP-LeWJ+g?_nzb@7bsAmR0dXO!xo8lpsrKJFw>juucs8({v`tB>Y%s6H>6Z{(h^Q^( zcq@u3=-2#?dXlmRr`s?dxg8TiOPcyvP(Zs~~OWFTE$1-C15Vrl&UOHWZ+x5pblYZAqUxGrM5805moJ_oS8 z7dM^*f^?;#j-a(#&)WMt#9Z4hb^Ty-;{q3As!!ddbqG9{Cy=zj@8!~iF~-r*A~0i} z?n$OvUR`tr#UXXhe;J=iL6brqW#cUXs(;aLg;9l%3NBj+9eHk2p0-yW0_x+CYPLT% z>W>rgdQ(est|u-mjN6oVFIFAZX>?kbPRd(#(t%Wh)y>Pi()^)*Jh2wR$O1FA{*tW= z7Zy>s(+rB=k$&N-b=?sgT zuL$A9A_@v+#GagrIoApyhp5Z^H9Ud4z<#4=`_P^W2`h&0Ew}<5h4zp7JmVGxM$JQH zVdW3_CG3owebJIVL)x@oS?OPYd=NYWUmPrJ)fN9a;9FpXMUNpVCiS5~x{+sd?T@79 zQfKgMb|;*TdN0qD%6s=anC+pBY(eNr9|=eCX*B=6TF;``i8>^n z?tC*Fh+CMh^+ZyZygt7LdnsM|zdJ?5=n1ch@1ZlM^=1&Db^^3&XmuF;CMf$~-LWEi zbX&^(H@c46{^a*?-*i>)Jd=Bhzx{3E3zAx`cKLEr!EbzOX^x4q>I^P1B{cNz($ldB zR+^i^iP7!TZYIx3ji*VKyxw>|ib&YN73jN#%W)ti>i5xL=!Da*T&E+MYk2ec@qz`9)19bIy+FTl8*l@oF0RZO zhPrGwZItxdeUtQPpSqb5U)CvkeUyZCyjJzW*6~)VQF!ajzAh~4Ai~!`H_>UynUM8S z(xp8S{A*|dohr9=)O1{$+(D9py8<~Nf%@Zw{?vSpZR3O5NYcP6!5#yT{ePFh$mXP= zOGr`A{VoB>T!~-70wVmWMSq8bWhLDZKFG(b`5!FcWY4`3dd7+($?dnbc#tu1*tH;9 z4JRmVC)SGlP^d}|x)}@l1@$vg?byvT=~Zo1GhVNP?-2|uUlz;>k>Hu1r+8ZLrLyFG zq7Ti}@iw5BNH1is&mZ57+_{zCJp`fMvlim^vbyQ(m5XnG&xQ12z_yXT0s_wNzfdnm zTPB<3&^V&{hN`MKvA2KzT^f~DwZ$;|gRl8gNKA;Ec)X&gfN4>(L*iw5*}m|FY&52+ zD31e8MBA*c(x*Ceo8j9QdOCjWq@;`5V+S8T;(^0N=f5Ph<)jB#3f-{y0u}>eb00Hbs>`XGLMy7XiJX=YE+eGi#^40-KNeHo$sdcgtJF^v983G93Sm4hii4LCx0s+JCQbT z<^FMwqQpx6tRRuVb+W!^y0f{;vvHqmO61jCi4^G^9`0@$8~hmQF#e;4!4z{#Z4Wh5 z6m2g&2uQ7%M9jAfJ}8qV-B_WgvW*R12dHO$v-PLJyO+3@M;u4NC~~A0y`HW1pb64k zi(SW0<>)ApX~M>_lp{xET&r!}si3I8fvy2TSVthF71~GOAbY|CheSb%r2u%pZ$qkD{^1J!UW?!It_m*puL40y`Z;LP&6tf43>Erh;+~9-i+K=8%=%^ z!}X9vQOfXEIanX|1)8?o)XBoBYq;ofhS7n-bde(SwG)Ckoz2^MSIO%YU_Y=&zXxl0 z_}(^c>`Ykp+}F&d=2qY&qOh_hjubvd@aYD*SgUBTU<5>>%lUVKk5bt9=vLqsD){fM z+>k=7;4Ms5zlUX!DbHsP?KZY_n0Bp>?5C_p?80Qx1Cv41uhJp%xZblnSn!)sWf*03W8)S zT>E}>H=PXwj#D;`gL@`xNwDP0FJL|JIax9G$CXnkj|X@IoW+=XAzCB~+lK*meDqw(%5!0L6Hn}h@+ zcOR<|7^;|;tJ_C>meO!In?WLGPeK?Z3bTkJak)dQ?8}F03LB7A`nP4bS^7|8Y>DF( zm_7$7l^Y=@g1e~&DWKPz6@(<}@}RMgr8OmpSTD*IU@=DjZ4M=X@L`*ARJOb;@)Uf) zn!lj|Iu(`@-(f1(gPDyLuk_V_(mG6xpy4!a#J7!j#_WlWT~8C8#;UsLX9NBwcTb@F z^SK3rVi>OXB@er!%r;4M^4QSZj8jaUfT+)VQ~U=%8f&E=f-O+aB#HtD*Kj zR7SB<7YQeY60781#HI+190grD!8JhSk9E>iT@`2MQa>8T+;)R&x-E;OCZ8~~%-;DF zR;5G!+n`>!pk8CJz{jXysaXhWQM8_HsSh}@Q#MOplLvZg#k?8!IVL(v?q}uP{+pe( zfWh?!3yEX}q(JCoBgn(JYi=H$&`XzYN-8+yRI&g`Hh5D88E*O3Tr2;M*%}X+&Ypa7 ztRU?ONS6^t9`2)WvLW+g0my5W?qO7Cz5k1TJ zgt5n~iIpCLf(Zk`tkgI192JseJ@%PIj%ZFEwz23Pc{U%G3+q>p-{xpU@$)#Qx7yLe zr)MUx(5f%}^cNm$5x@Tc`Ihp99uDk0H6;rpVDi^3%XKy^fLI34hfs)?r$ny*9lrF} z%;GwUtqYeo`of{GA+1ewTHd2mY~-o?ab1g6BUOyptbcZS)W!aY8s`Jl{rQQV6eHmz zH?ZWb0cnW2Uk*h6%z~HJ$|y3=ZgM`0P+&=V1dSbQF1y}mu3n-{DPSSn+bJ=AL5#{? z*belDk6|(-KZ&7N>BhxK5FvJY<~}nY+>CVpQfaVgqi(-!)8B}?%&4soZRA=R!gn^U z+V+!Yb5OzgcW?>bM$TfX$D2W*$jn)>Mi+m%tdQpAY8w!Sl-Hp--{G6yz*LMCPfHW_ z*@lgG;meDz740;}pF1Szdk%RfPSN?cxO*#lK%Pzv4>e}+ET@_g%Er;3{CQ0|*7we& zM4&FP@`;%|x6<#wm|`6;65Tg~^F$mz&yO4GskTJN`6eC(PP61@bDQBrl5IlcHqg@x3Q~x?@mJM-g5s2@bJWP_rtAxz>;pR z1^4I|>CIQ|Xn#*eT)SG%b7gqh-Fw0{{NHqFI7c5fLj-Uv?Wq94Ox? zGNz)TgsAT4friL+eEk4GffX1Jm?48o?|BFjC-dh^CoQ1fi6Vn)1%rlIj(-eVlOQvJ zE9V)Sde$>LQd61&0LP97hTfdXRaH3kfz_Bt`uTU!3}P3*tC>yA@*x3Va;j2Wf_2s9 zE}q<)+w&n3g zI9A4WY$ZgL#!D?^II<1Dyl>eNGPpxa;r*;$B<)|+>4 z%;}qVd*0|0O8k|@uvC0*t#f$&R!5)d_jKadI9!X*g^I5S8cWG=_jLd~BdkClcUn0HXtQ5Y7- z1yB;?Yw--FJ~ReHAM)ru#z=4%jY}Qi%8RJBh2$-OX!-x}1p0N_n1%RD=4D%G$3HY^?Ih@Q~{+Y&!h{mY`rQ#9Vs@I^7<^<`B$%B;-u>u1~GT+H@zwB=BGs)8j-R3 zITlG1CJRfEfTo0g*-I11`dDmY><4;Iu?$1|xgzTm;~Icn)N|QT7_k2B(-l+pfah+x zTqW5m)*s??(GBm9LOCuBf_i^!=oA`|N6*8^Mt6AIIvlO+tRj~Plz?NV({>n*XwGoz zCcg7xXIm5({=3CdEI;=`?K|)1nf!QQznl=8}tXaq11t zU_>)HzTfmVSS|Y2!43UsK3|%s<0$0O!?Rw{);y+)h|(9p*`@(TagA0)qk$gtHmry9 zVKeov`k?b6@K}FrpnMkt)>3OJx=EXHGv}9RXBlba_nMV4wVU*?SL8pX3v`qhga;hj z<@$=K7Vq@qBwP5)Mik+&6?EZ{dE4L;nR681bgkQXg9-7|z}L+EmGY}wboMI%(W_C9 z|1JED{Gj+~t3(TsW*3i`xWJIge(dCpv{T4D@{Ob0(g|H#NAwL{uEkh^O#edsI!{|` zyn;)cF$eXrdk>YuoMxp>EL(_ogo!P?bKIYgzzn${##CY4zG)TvSKSAG=5={ zGFm)DY;f}`JeO};aYElxXl;P!zNuqGdtxd(_W;5*e&&eNnS3zgDe4Z}mu(<_tZ6R` zr{5?$^F-o4pes5Dap}ylT$hSP7eh#L=~uG(WiqQYgzm&Ja@1rh|TCo{1g< z9Cy?_gPZ|s%g3_OWP{9uslLC=g|(S~5^Upi`c^H5Lr7v_z7eCr zlC;%y#$9w?sWvM~<-1_-^F+{zev-jKF=x&qJ%*vRTPF50XZ&FLAv6{JMTr~N$K!vX z-yc*!IbLg&iy@>%9AwR^wrQ12?ng`8>%DZ*tQJjxEB!H;Ad<=+P3MrDXthb5Q*{lx zb7V)hv_HscvHzl{w_AH+-`NF;C#k^h)S^Sl*~)A8?NsA9`tuQb$!6bG}7Se$spw-GE!oxtXr1l)f0dz{6eDOG=dwl_ll^bZHMy3-h2 zNqy$#Thtd=lFZu?6qV==5i5v(eDHzkL9t@P`>;^kZh`PkCL0aqyX^B@`{Mu~)f0A! zTcmgLxq5>`z9;pTMsmbo;I?qI?Qs0}kyGEMbt7(j8blugv@+GM@g+Pq`>>sg1eue$ zE_gTd>k3Y!6w`7XR;LZ%%_HsV9DKk0({wy1G;O_4KHjd<@9@x-l>zyyQg{mUz877Bz$1(uqOHqVe{ssX8rXh+sL6Djb>&oOcdl-_M zDMy>*#1KK&T>t{mX0dV%iM@k8hFAW7Z>`YAQdXedfdhZC8?!lwuh?Ipis$mLHej>pyS;(lS5j%==JC z{ZA+B?D8g~14ePe2O#CMj4SbLE<@PP8YzQu#ztVZEy#y%(r&Zp8Kzp7!1!hXg#y^O z9%DD^$8^|*(Li^+FDS31dlB>;r55I-3)kSsrlpqcL5sPCPna9CiWCf*7FF>Sm2a?H zAbb3e#3@Z~We^qT5wuXHCSH;kMYcD_LoxS#)~!XWMD>LvXiZSHBVFjzU;>^BnRE1l z;E^0b_|H@de+sIEgeJsSAg&%!UMW}>L<{o_nw^HM9};Ky3j>c7FzwtqfDsOs5Tn(N z4t`&pNUA&v36o-J++>lDo`qQs?t_CDO$f@gNZ7*+I04a>ea3|;CgHd0m(jdI;2b1$ z45AclkcWLnMm6Wq_y$Vi+5h31z;DxKjOImmyVqkxS$Itj+o)(r?c*(-=%+IYDhq$9 zi?MPY-5Gp9%~2+0(1K~`N=Yh(q5{D?zN7NrL4Igg(vg}S@Epdv8Nz}d**bzNs@RVB zGKr-FqL81!Xqk(LNexmR;2u_?uV4EV{vts0sTR1s^e4!kJbcuN{`>O>@tpL?G*~*W zHi8wcf%qkR^38joDrx5hgyxcF?dSd*H2L zMZ0(3nPz7C*E{hwDDQ8CM?PTK>>jyDS+$$tSd zz7WOY55CSeg1GU$^4!zDM)rW^SrY0u@Tx^GFWYm(ua}=!`{-b59?JB{UGz3lw`d?+ z;`N%`!$P7z=dVz+`My{BIPV|^WTA83VoDV*R*%BLeqiYf?1C4&Q?%gUBx7Wz|HMs( zh#{!JnL~po5j&e#4*DCkKmu5ARM;5|7fZUh4z{;@5N%ys?1}_05A2OSbsPI5j?_k0 zEaLwiw7<{=*g`nh*%E#fB8sm$1GXb7xFsKkj5FZ7>iy5}!b`MilBs-& zWktGWUYX z9W7F+P#As1v`1F>DP0(nEBIQ)M^5pf=E zPr`<-*SpG)xsNr#5VA58we+@iGjQ@y`D&|{w%HDaqnVMDM4nmr@7k7#o4{tUqIvFF zoZYR_E|>|=u+OUnQvOi&3hO#H0Io}%S*=gDWc=t!f|6?I_eOHa>kx3HMW?ez>b7^K z;3-8vICLq`Z#&MZg`5gZff_poNy!xk<(pkUl^!43h9ti3g-#y=&?IkP`}AGNs>@G{ z4VYdEs0k^JmjF^lW@I`_OR5O6;Akd$zLu}O&v)HMqjq46H6~8!k7i74OC&M~wKKO- zJIW&PYGgF}i3>-WOGW3JA%=l~EQ+l#kK!uq~k(4n78Ptr&ouLV_joeuTII8?Xay8 zyZsPV`$pbUEV+E%m86hDU$5-|=C6l*FX{6h^Ez`rbE(PXQCQ*`CP=PAYwaxr@!IpD z86S=q4>eD}^y2mhELo%!nO2eukj?Hpfop^SI*X)RV15Q`7q3rm1|92p4RIFEeqsD* zT;V|=cf6*^0;|4_Pb`axS9Fla0miktZ}vhcXlH6Wm;Jzn1Fc+nJ2<^gkNPg>yTl5T zrX}eI$R_J)VOwqV>LYs%q%<1u(@lCo zLzrL3b#4K@m|-NE?02ZsNEewGu>1`v-zl9IYhv8FU$a(iENfj(1Df6EJ--(PDHK)F z5sz9bY)`A9IOXQC0WbwnTQ-m#P!QtCxkdoGCl!I`7g83l@$?U(nQ^<7XGpE*p^htP zb(bHTM<9XFSv8IF&C}tO^g`2)B=cIWIPV;qrNg-)=zfP^#It^dBP@!9vFFD3V*Oo` z5v}K@G~~;84S88iRuS`1Q#*+7AmW(+gmJ^f)kTQu%8#tJBqA`B{)A|q9xl$(yoqFR z*I|lX8$+J6E7&YMj0(mshg!bs>arzV{3@YQgus__T~^CFN?N&?u5G7G zuB8y%?Fj==fy7v3*QzS}a{HYW*?pmMdmOzQz4lqK6U!kq0Mo*})kp)5G`FPj^l{Z; z-go5zhsvWkhG$(zLAKOtJCfQjdc;26H{G6A%0xQ=e?XIj)F!^^45=Gb;!f5up>X(F z&YgnZv1&)V9J&K?v%-J( zT^Xp!7*E-@?X~bd`Cv#`|5|8c{T;-kP!CSy8L`QkM*PLGQ#e@^)z=7oeJpv7P~I>s+N12K-lEJ+XG&_P{_pj-h-U$t_Ognw&{?b(fDT(5IJ@RY zp|?;Tl4HWYUA|13jF{jpDLOryt`;}2@^Bgr&063r`^S3y)LUUP?QEewULH@7R{3ie zvUs!Mk}6jy$l=ssNB>66x$tf*UJxeDi$!igu_SW z%=eNEo)z}T+{xXfU4Y223#-rRXfhpsrGLj2(_%O#w!cf0YJ32LAbB&_aWG2V$$9}f zA#L8~C0!+E@UU4C&pDun1k5T!dzO~0gTwpO8LAp}-dJybN5arwVRbU6_f`!QplEE2 zW!xdbDoce-=hWWcWPV;ds7q)$)9!h+R+LDZsoB9`38x;BOPAbgJH}_M4 zbDMV7i`{SLo{3Ua5%-dO=vT%m7-7}gU-E|{eoxU=DxS3mQgBdiojGaSqZD>ytisD; zDs~D@+1#{ybGwl`W)hQY!gk`1e20GEA((>lUI`pxAn`bjGw6v8%W~)m<4@%hU_G+$ z;PI5#+h3B?a~i9V>Id!ls12}zhCKzWPTK5TE^4PPH$(D9Oy8l$a=dhWCe_exB(aL; z^cl#0G$olh)q-cBi=9D*YxQqXK-z9>d1UH0NHC|(d50xrrlF9@PN*uNiDYe;IkSy1(!~sYm(l8r#12AN*|1eD*O2kSL~yz4i^Ji*Ih>c zO&=uK5$HvMJb1k_CGy!kSi7v?pn8KRaP=4j_+~L(khAjV9egz<(-LHW{_y{#nviPK zEJlxLk}?rW(kQu?3BlKMB*~rD?S?4!;Wkso`%ySCjF#+h6HF(Cez*N#Q)l~D{Fy9e z;3S}KBK)9*fvN4DF-Hjq~9sovk>T!8!%=;H-Q~9Z|CLqmeDUSq_cO^P0%%8RmjU z6x#!Yh#xc$;U&nu4f2nuTLd=rjWOj4s?QA6=q%$}o`#;H=m}PagVX47jvQ`9Ti(*5 zeQ$8LQ`UbX<*H^H%89s`>w?cnz%YT^d#$lVsk_p1HKjeq^DG{4SexglLgwUV`X?oq zs-~Edv;43!guSKP5Q8T?z-DoOabySzc_9EzlQAC?L>~Zg=1Yi>zk{dez%W2g=F5-r z)P(zvH!0$qOLORgW!W#PoHMBmu?tgJDy;z(cKM(Ws^-9kNyCKs$(X+o*ZSar7r*Cy zi$+ic*8tt4(>fLfG}UN6*Kt#FyuxdoH2qJ%h?_k>rr!08oq_x1Kw}JG0(^Rh&L?sg zoU1=k^v^|HFMzBVfOgSHJiUqG8FS$Ms4W3_22S0-Vu~rPno&Lx{(Z(T3tG z>k(c#Bk;ialD0)gQzSNufmXfLoHp!BrKVauv#FyH_D{h*x1qhF9ZR6SvYF##j!=C& z=@amvj(^^}^cMq*56~Y?VSi;&^dDC>{7e6ghUfXUxfx=6xV(q&TJuZdSDns!;{=!DGd)!WS_FBDcnzV&sV`g1U0gad zvL{G5gtQ9X1+YTH&_g--X^vDh1ML8&KytZz=$6~xtHPH7A_g>M!~t9gZ=~|coqy6C zbslThW*>lDIAzVx;K&Nq38dSx9!==Dm~H>u=6$KzC|ABKv{U_}SrX;gfu^vXNYcR) zgx-W>X6vRM`2uen+qx554cud3ZkCfefV_bM)VJfb9^9BLikK3#;>1E%Ttf~#SxmEn z5Icq2fHm0%*cJtDjVs;DEb;%A`4?hzhJdo4FEEgPaG+vmHz8XwtTfmyQ;Q zYt3X{(QsHxf(!A60d6^}BA+$nwneVkXeR<664c)4r%=VCk41=MI`f4(#%SU2dQFt= z$;Chm3^8HjwYH_OGd3koauvB-;kbKJ@9UTGm-qZHjZ`$r1&L4eXp)+`jpitvujlVo{Nk8Q#Dz+FK=OtKQjuO6XRIxJuvG7QnA5q0O_JZat z97M4)yaybh6(e?wos^UMhLYp2xY0#ziI@o%7)s_kZFo1yTwS#78R(m-4W~+E-UOaN z5+zdYil6hUjHWER%^*I}Y@_@`s5<$NU$y8+1W6}xJWl>jJ|@r^e@TbURL@=ZwXquL z!jQK!HZ@OWtEzdIUrD%tT~xmM4YVVOzRYi-hO6OxfT{wa^h{c1s&?4IhtMnqQ9$E^ zU?_p{-1=He*~JKY!H^%$C$G7*m!?A^=CivyNVb4q&YW_c=2U+Wth8?1hZe*S_#EeK z3f105V+&fp%+>PkT!Wo+;&m$)qjncB6tiX)-c}}ka4KEbmW&-d4bx-ob((nHZzx3 zS_@9+9iKVEeFH7JLVSf{Zg?ZV92_4RVb7ok5Mcn1cyR(mK1zk}-&yTwrv6 z_0Uz5LaB9h#Ogq(8J4tpz{Z;o@})Qy*4_`0rh$?%z|W&H9{_mcmv^{rxYaMbcbj}E zh2?FKKvys)`YL68cEKE+C_GMu;EsoIN<76knOW?iDebKpYC+3Qd=D^k2EXVinF`3> zPDH4@@DYs9C|t@rZo(*f3BA+CpD3P0i2y2!VLjStQd8xps??qmaz-08+do`M2WG?^ zz3AwpRYn7$vs_aE+zOvf+HulnkW{3KEzInW!q+3K7owGK;vgOJ*$leIez|S{dpP$m zEASIO=~;Cj4eJYLMQ3SES(LBtB?muq#^&IjZ(TnZq>ZQu(Ktr87ZsLK*CA=|BU*Yu zbK$8B>-7>*rx^dxNnA=tHC(c}JVA6xvV?MRk;so_EuRxrz05C25mRC$-HbaV4E4gb zP1oS`jrLmABlm%EjM;RCLXm(elr!I0`q>)H#`PN0nmjk>Aq1~sMypq6jLD3(i6yC0^i@QzzHpD zOB6BbKQ_lCW4Ip4{R7E3BICOEgs4sj=hJibXp@1xzST?VZba;^2Unt?UULETKfem3 z>an2*y-IsI)9Uz@AX9K3aIK;`)~z_`CDt0Zd&DP56_pRj3Z^?yphhEj>a&>37~L?w`u5 zv9h;h0{9%_f5%yQQ(y`&>$(KWNT3+hw%4=f8Lv0uvx5$(I5ByRS161WTqiPuYWKzZiKje3 zwQwn5>BB$IGb7>|1n{5YS4Uyq6@d?Fj`joB>lfgLkUl0;DVsV-cCyg$AjSI^9=MHI zlUXjr%QPUVX0W^xTN5mU>75CzUe2%ja>F1RC~th_}@gR=CnZUBgF@7kL0~?3wvRKHVJYagV@4VZJHDP zGfDB5w0BY@FJ^(?kN8_>xky{w^^Gk%!5ELiXlivu5xA?>p31pSnO=XNpvgo6@TF6| zpRSufU=Jzc-x^s`3NMm_~>v&hPvG4uZZ!h5g77`DheGWC}y!hu#3q>;Mu&iuOJ;=;~ga~#g zxQpvDUU56MHfsLorc zabCuP{<_!zCl|u1FVE!q=-QgaMCHA||JEo_X-Z2!UMa_U+%VjR3k_SH49G)Cnv(&`=`?>Kxto@eE}5?Mw4xS97F<9{x{=1Vi|mHG9r@rs}Gk{ z&av;Oft*QvVmPsCAO)aO6lPe^(6O=5o-~zK3j9{f{`RU9&?5*HIZXyA;2{D)GDh6l{eSnS#Gc-1!+Y?w09 zx2+E9{%;f!=VwZ)by~qZvhYxhPAUp;#LI&B7xrm{q;o5OWCj_-S}cxaCcTQz@;~GWU@2 zDl5;c+r%eNbO?+%AiDFIoI?6JuutAIDuc&!sj`G#r?QWqMp}@ts|YNu(7l1~+oVD7 zQeIRJps_yB3F=>AH({_#ET5W!-PZly$@fJgSteGT>vcC3r4ZG_CpujNXjliTv_$lk zpXF5AXnRt|wVM@mB2Qwi44o0mF!-vpcF@0Xe1*vjLuWvXmKuSy}+ zb`3rI`sYK*wPj&1=7SirKGr7)A=m>95DB)#&;kNeE z510jxkBWi_Aog!M0Aa7!b5%)WPQKv*3XkGrcbIygAMP}x?5iu=jq;)07Qg11U-lxe zZ93~0MiJ0>*6uj3m>Zp?T@c@Ty-o}Klk+|V=BxJ?OOnfJ&RTU?k?cha`TzPt-Pf?I z2g}{-2#4is_VsnHWX%8@W3Soy>J>f7TwKqXd z#4?hSM02|2AHi5)@lWg07JsNME{UGGW!df1ng2WqE#%8VU1vQ)t!q$N66VF$DWi!m zDH1l8L)8kRAPA$gyG;uWCYppRLp{b?1w9r7Xg-I2H3Ivlt%4oe)Xm~C4Jm)0q978W z!AY&3j>(QlkZ1$sh8tdl+R!c!W2tuv2ZQyhhXSl=H*$wCc@#KW z6hoaW>t(X(b^6a{@ZL;VaitOYGUdDdnDPu=F%F&fxwGa)x<gDbX;(C&eA+=vh2h#Rj1v*r;8q&6?w~j+DT~qx z_gT{+Vl(n;YFw_DWQ^ga<1m~=dc&7K&fw~V{KFeUzRo{_|N zSPT|B!Z27!(9J4%mViR~(u7D+;R3`P(vNx<$C|C1Y43D%%q*ZI*+oSed{IA$!-39; zUUs9xUROLtgY5Qdj4WuB7NT7R(>}zH2OQaQ5Fl+~ z{Ku=&@yK#;#>O*4Tk$3BWmLL?;@>S@aF`}9MAIBt8#@!YgSwg1(!@m4;`1Oh<&-&b zI557|6s=kkp9g4R)LU8XSuvMCCQtN<-?sVxYU&i!CzUlFzs|>$wzhD5wN8v)XiYGQBsg@5-&!znQH%q zoeDp3RvO2Kq;ZA&^Z&3&Wk^|%&qbjlz3}bM^+laH-&%)qf;=7kf)q&0;Tr%{m~5k? zxu@e_)2?)Cv{QbT!R3$5g|P@)M!#L8bHDpWV=pyh4eS$^LSLTgG3;1i5RdUN7v=D; z5wrZ)c#q7q6R3Qk7;9U2W0py}D6P3DXj<`Ka2(Ik4bjC8=!7oz|fIW@WB+h6;bRz3|oTFw2|0q9Sy`zm_ zn~NH?WBl;%pyLVIteHLnDUmDJSvx>Y|CFfg~STrD1?Iqm>-&YE`Sc!UfAtSJ1>xa-+Co>cnGAv+9f^j4k`jy0j36C$AR z!6a?dA};22s0EkG278_!H6Ez}OwhmS-H7(DogbVOKH}RKkrGg~;grG47wvzVWZgOR zDEMGHYq1_XMAO+Xxd05*qo35o!3u{Dr2xz5)qem1(hKizd;lIV8;!|dwXH6^v*4Gb z3CXC4FQrfR@&>@Q?Ud+4zxs0?{@hhm)BlAOwtTE?uJjXs;HOoc4W8>swLNRoVApeS zm7GF|nVl+OLgc-cj7vpplZT4%CHuZHIu`KNTPY=I*bO(E)Jv~^;Fevi&>KW*qqXrb z>9xo6{M}j=iGH;Dkp#gc(oU9Q&R)|xEqeI}XhHo<;l4(k_L#|CaKm85!jm!=5KX9? zh+Cqn3Qa3z8;6|PWr2khp>i`z39}lH3AFvsh1^(KF^DeE?p#^qV3K&zh0yFjXkGPE zSm4fmRx$kgsw&y5HP_ekp)XP9Z6akn*3bgNsu^@(nfC31hnk|t1+&kK{?$&RdOMD| zz`bi=`$y0D=)hgPYKZkNYeq+A1h9W{AP9ndKTqp~ob94T-ua&xd$ytLBXCpgzEZitwb-4Dx4RW(OfM(nYSq5vdLTX?qV;+N-7jsZ2Gh= z2dQrAWtK8}@|A9Y-@tSak>MKpAtMy*r==hLmF5CC{PW?W3idt1nRFq9N!j`bb)`pl z1ajLnDV5U;zkigRMR)5A4l4!s!|F+JI`ynuW&d5v<}z16lF!RH8%g{bK+RGb^Dia9 z_WswsWW9k4Rh#y`t*~?0RXv4;pbN;QZD1?8B96Z8gECE;0wSC5BEJyGqzTsd!(>4Q zLFIlG_v(8j68nOBwEIm4?CJ-t3WZ>RHE@(VsS3zDj`#!9C(UuRBFKhN!TPK7=kONE3QVuQcL_Xo(@Q=srr>4}<*6UePP$~etKjZY$?B)N>74nYx78bn7#r6OiiV`?(MDlXq?B~lT1F3Ou27!beiHrvcu?M+3EGr5m;1aAQm-Ex$!RRo)d~yx0mvP z(Yn`NK;tK$vn0pR#U#frbl`iw=@3>@O#hZT;v-? zFpn_W$|WUU{D?&g8FR>Gfq7<-EQag+UqM|`OE=G{gzoh4V=Uy$&5-x<2i>UkaX9<5 zKCzcs-rq?D!cwHg!*oH{hQ8ew=f4eP^=dSK(!*_01uMejNe?$$Ph{=&;FlE?vA}${ zuIMQhIv0MtTDfU&8Nj3xMGgCT{ZH=;_;5;#bYsC(XG3O|c1InO%9WH^GJ)ZFuFQ1b z?&TTplgJIp|B1OcYTOx_{YOfGAaR7B)zkTrZWhY4DE~A8EHLNV08B%Nx(22J>_fNO zxSh>TpkB0~Jn)s%m(@2_F=(2~Y31yflig3d>2 zljVx1swN(pLa`}_l0G#%^>wW!XsS&?Lk#Az zlVqxK_aovgwe;DfDX= zdHfA3yem!A4_)kfBggPGarNbvMd~(Mfr}=JV(%D#|AT zDxeVM0g`7re>%ySpwtXm1K9n`X|!RGG2s+8JB-yxqCD(RGMC!HP|wST?YWYg1rK)x z3`r08Lr7#L0nWUE)p$krv4!F!U2>j|E~&(obGI=#Kf49)2xnwhO?(37);rd)sQco5 zhy)s*mMSHpBe}Pk!fH~$*)5TMWSrZB8?)6HlimglK~v%s z1Vs7DZNT^6=l=}$-TgacmpnJlQ=~z@pRlvopDhxC`I017k#e3~#U-#$(EXeFXW!pi z4I2Vt80gdhuA{oCJuUFW%ecmsKCgB;eoJGOvItLBzYUYHnQcmMkGPGxFGPfZjb`sL z??6g*ETPH?gY3MyTsNl_myS25^Vn2$;4CN}#M|8&FTan_J3T#lv|%@p;+bNl!x9~2 z?Ug0S>H&u6K%!_;h$g5uo-WgR7UNZ>(WSg7RcN%mnKL6ho`j-xM+B^x`vIr4Nap{3 zjTrd|*7Z&}Ymv>2+Pz#oPDTpt z8_6Jb55+7d2Gl+{5@On+p6q3%=b3HsrRz|`h2meQ(uSDrupw&~LzId-vnF3{&xYvE zBTVp!CuWlH)l@{vSbQC@3YC5F7Bx_0x3Kd&6wjz?{bnvW{=AVd|D|d$gdnSBKqd+U z7m-0Bdn?)WoDoV;KVb{0+u6C)1Cd75sKtgwbtBxNHmyP>li7y4FG>EGe+$?7AP{1y z`iAFdB4Xb8a4$_hwY(Nt;byArPnN)Kz3Grc^(J;s6X+g+I+LTkn`igK?K<(ws<)}g zM)tcnT~a4ywS;WjW&)jWlc%}t2~p#uJTXm)b@pVfAb1SUvti6P-~;oh)0De1ahkZJ z?{b6c|D4R9pmo;^h*VTO&`itW&`ArsG2@Q_6>=X@Ep>XcySKwj%A}yb7$$sAP+y$R zCZu%9xN5jG>E`AXWWRZ}L@{})iD+QKY^utp)(E*6BwT>I4N#S%EAYMxiKQA4Jbnz+ z2ML+y+W_1G6#h9nl;sgmQJPe`A{kcG>DjMXa}EkJiA@{==}Gej6yLsG3VlcCYzBv< z;Eh0sPFMd7yM}`nPDlrb2ZcHkVw)svZp;0lTi^rR*IOsm@@vPQk!3a-i?KQn?Rbh48S-*mBaKeJp`7eckj=P&($ zjIM*LkbT}Q=G)9}p2MKtP>m|Izoc^;3NZ87K3azG1Jv2HMPE~J8}kjamw?oJF*lp; z9DcuQep#EDMiZVYBgLrFLI5K~<4Y)`Ol5lgGyLyC_}M3bDD|RPSy`(sZxB^7U*cYv z`-&){D}#cih^1B zXW$^xoG%_PHTAx*#>^p}dZj9)!#^pryu%y*#sg(IrGa23cupfo*oxb0hLbPn6|f!C zGpQb(1?!KW5ZVAW;hRWJPdtP|NmpmD+Bh_xcwA^`S6sh}CfdxFII{DBiT*#3&+#3j zWlBMIzppUsJ-C+muk0^ftLssq&B5>;=Z(X1K6H^mP2FBbf)U%yDm-yJJh{FEP~XWM zrp-W~%*pSW1!>q(y1@2{V=k-pYcr9oTZLwxe#_SAe}EyGz;CJ!C#&QO{#}T#R6Jw&!0c9qdm${ z1Jh8q4#v7vh9Kwn7YVf|1_d?d!br)5h{)+ieh$k_M;YH8AzaB-@55@E|159r=xd=T z9){fcbfaBwM!l(`T)t2ZX9Lti6;PRBLz|r$JOd7JZXj_89R%q^Nm9W=OH@b#RE_}v zsAH}X%b2+*=6K8*PTBP$r8_+6?+b2ybu~>H>s%%^omgmUsqVBX*J;5h4L9-!Fl*iJ zX4C}QZns;7iut$CGS{k+Lo!YR=k3~G)pyMn=Sn!Ko?t)!%}kGv0c9BP<0`jB-Nt?! zpQp50q-w4ue#qoR_gl;egfAm2d#%c9k%@2}O=sOa-+aD;kfWAy44pC%=TjmAbP8<7 zfx+j;FatRTnGEMG;)YkYBF}71=}GnE`fsKBJd2Tc zXS~v0kllM7Mx(^urT`PFRbmqZMXiM{g1UbJ zDQR-{Le74uX~t`q>pEvs(Y>hE#NidZ_BBR3l1+Q$@9JD`9iotM;9dMxqFAg=g7q}~ zZbLC3+~vm;2_S@9eywl>+4Wgln%MAUnPYD!zd;Fdb@w>ykh^jH2smDj*Xbkcv1k;RMZO~@3#Z&#TB2DF>L6QIo1JCO@Kkj&T9-K z%|3SjQ6bf9?{CE=4%?>~pOgliuD768V=rq)^30%o&%$SYqaSb|or#kuba>n+fsW5{7{?|t^LV$b?n!Q~Og1A)B>x83s z7S1=Qc>`MS)fKBzK9EM3bEpT|4_^HUQ!~G|D!S}{GLCeWzZp)u|XW*wtgw)F=Vg*6Ceew zGuO2-gs0#7bc@82d_Zf}0oZxj0o#UvM(XW2wjUiMP8# z@7!_sK%(LHgp(p(7Qq4geuE+@?kHwq2GxoZCg-_uRD+?EQkM=;0%9jdmvC-X&!YpRQr)QA2iWillhs5LPE&NQLe9^|#QdS6N9Mmo1#%k`RST&TD zqbo&%fD`H^)iwKaX@v6g5pz8acPWOQF@#E6l)|ZDi)eJqfH(#;Cv!D3L2yXa*xPE9 zjClWxav+vm9fYBBm3-ew<1)OPl3YA|=3GX-p-qiA25h?AI8 z*HHX0`J!8>aqfFUHINxg=*wuit%h9VwJH1Kn9;&^;7Nl}JG5?h3^z#=GNTOb&4p72 zM+I!Fsv(YWlzk%VUUPkkJJ6Rubf(Cov(INrq(4 z=>{5Jd9I7wc)O~8QC6*EGri4>q$`nclYB3RDseqFhAJ^#0x8W5bqBMq_P&6A(wwTZ ziSS;)Ye?hQJaqiz_#CA(Wik7bq8Yv?)bRE5jBB#;C19Zpa=awW< zDw;9q?t7E73hoTQnRH;x_$*X7lD+A1rBx%zBpEBHDJMFFRo^g;jyZ(^<{(YY`7n`C zu(5^8C%_Tq2n4dtsActZSxNxJs>KLyg%S8aIJK-p8AqOV*R}2Bd0*)_5e_*uB%GOe z8v>Id=|ctlRfGB7m_p2BU)R-Jp zZwT*VIIiv|H`*hlA{F3#6w;CIDZWR=-k1S1RKgmT#gWM;rD6#HIz191t~{_4pLSPM zH6^YF>pqfmP54XH4P&ud{v#UP$<8W<_LLD9j%2u@_tnWF))1~od#jH{iL8*suT_5F zhH&)7V7HMYJ1ZpOqq{*cfCv_>(qv-eSp=I}F>4eHFM6J)#j!!c--}9gMUG&$Eh?K# zJ}G&W>Yj_vgk3d9C&_p7YH;M?^!DZdftt&s4vWC^lw)9eAn!%PRl6P>MHuv~stA1J zS!^%8&q2aW1%4STP=RkZDLCq*9|KD^uXM)dr@> zk6~|KMgDd?_8d$_52C@*SoXvyJ|FZw6}irS?4m3%b88M_yfR7r4Ir?AW+rln4)5l_QI(U%5J3}C^U>&TD%gCMQan;lt+DK z>1cbdvG6CVSTj0BqV~z!fadhaNJv`n$vxcs)cGp@i1$*_HUDihjjPXaO=SaINJjTV zn4cvlshK7kg87Qdm7hx}@x3F5Apo%ON^6xiHw(YAG}*uQ`yN z$oxB@EHLKIkID3sILgsnlGdw9~MYo%dgn(T8#eZW>9i zwv)hN0ii<%uSRa>I zG@GOkfRd)uYNp^GSCaq!5~Sq6LR5eL_LtJt^(6o0E6K0@ved_}UOLv}y0Y}QYfAq2 zn%jQ6Wb8lh`twpB|Ls8@EqV1>)G%GS^4PyVYWn~8AmyJAx^m^N->%8|?NM|8&x1mF KlPVz#ME?NOoQ1mp literal 204769 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 diff --git a/firmware/fpga/dsp/cic.py b/firmware/fpga/dsp/cic.py index fa0f3fa0..99f5376a 100644 --- a/firmware/fpga/dsp/cic.py +++ b/firmware/fpga/dsp/cic.py @@ -240,6 +240,7 @@ class ProgrammableShift(wiring.Component): # Implement the map itself (should it be done outside?) max_shift = max(self.shift_map.values()) + min_shift = min(self.shift_map.values()) value_scaled = [ Signal(signed(self.width_in + max_shift)) for _ in range(self.num_channels) ] scaled_valid = Signal() @@ -255,7 +256,9 @@ class ProgrammableShift(wiring.Component): for k, v in self.shift_map.items(): with m.Case(k): m.d.sync += value_scaled[c].eq(self.input.payload[c] << (max_shift - v)) - + with m.Default(): + m.d.sync += value_scaled[c].eq(self.input.payload[c] << (max_shift - min_shift)) + with m.If(~self.output.valid | self.output.ready): m.d.comb += scaled_ready.eq(1) m.d.sync += self.output.valid.eq(scaled_valid) From 595ea6c072fdbed6e77b1ddf9cbba7dc0342eaaf Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 29 May 2026 06:30:57 +0100 Subject: [PATCH 213/238] Make switching SPI bus modes automatic. --- firmware/common/fpga.c | 5 ----- firmware/common/fpga_image.c | 3 --- firmware/common/fpga_selftest.c | 2 -- firmware/common/ice40_spi.c | 11 ++++------ firmware/common/ice40_spi.h | 1 - firmware/common/max2831.c | 2 +- firmware/common/max2831.h | 1 + firmware/common/max2837.c | 4 ++-- firmware/common/max2837.h | 1 + firmware/common/max2839.c | 4 ++-- firmware/common/max2839.h | 1 + firmware/common/max283x.c | 9 +++------ firmware/common/max283x.h | 1 - firmware/common/max5864.c | 7 +------ firmware/common/max5864.h | 1 - firmware/common/pins.c | 2 -- firmware/common/rf_path.c | 10 --------- firmware/common/rffc5071.c | 4 ++-- firmware/common/spi_bus.c | 14 ++++++++++++- firmware/common/spi_bus.h | 7 ++++++- firmware/common/ui_rad1o.c | 6 ------ firmware/common/w25q80bv.c | 36 ++++++++++++++++++++++++--------- 22 files changed, 63 insertions(+), 69 deletions(-) diff --git a/firmware/common/fpga.c b/firmware/common/fpga.c index f68b6525..ec4ff2ec 100644 --- a/firmware/common/fpga.c +++ b/firmware/common/fpga.c @@ -25,7 +25,6 @@ #include #include "ice40_spi.h" -#include "max283x.h" /* Driver instance. */ fpga_driver_t fpga = { @@ -57,9 +56,7 @@ void fpga_setup(fpga_driver_t* const drv) uint8_t fpga_reg_read(fpga_driver_t* const drv, uint8_t r) { uint8_t v; - ssp1_set_mode_ice40(); v = ice40_spi_read(drv->bus, r); - ssp1_set_mode_max283x(); drv->regs[r] = v; return v; } @@ -67,9 +64,7 @@ uint8_t fpga_reg_read(fpga_driver_t* const drv, uint8_t r) void fpga_reg_write(fpga_driver_t* const drv, uint8_t r, uint8_t v) { drv->regs[r] = v; - ssp1_set_mode_ice40(); ice40_spi_write(drv->bus, r, v); - ssp1_set_mode_max283x(); FPGA_REG_SET_CLEAN(drv, r); } diff --git a/firmware/common/fpga_image.c b/firmware/common/fpga_image.c index 3ebadad8..6b440337 100644 --- a/firmware/common/fpga_image.c +++ b/firmware/common/fpga_image.c @@ -26,7 +26,6 @@ #include "fpga.h" #include "ice40_spi.h" #include "lz4_blk.h" -#include "max283x.h" #include "selftest.h" struct fpga_image_read_ctx { @@ -86,7 +85,6 @@ bool fpga_image_load(struct fpga_loader_t* loader, unsigned int index) // A callback function is used by the FPGA programmer // to obtain consecutive gateware chunks. ice40_spi_target_init(&ice40); - ssp1_set_mode_ice40(); struct fpga_image_read_ctx fpga_image_ctx = { .loader = loader, .addr = loader->start_addr + bitstream_offset, @@ -96,7 +94,6 @@ bool fpga_image_load(struct fpga_loader_t* loader, unsigned int index) loader->out_buffer, fpga_image_read_block_cb, &fpga_image_ctx); - ssp1_set_mode_max283x(); // Update selftest result. selftest.fpga_image_load = success ? PASSED : FAILED; diff --git a/firmware/common/fpga_selftest.c b/firmware/common/fpga_selftest.c index 06f2e8ee..b9d7025e 100644 --- a/firmware/common/fpga_selftest.c +++ b/firmware/common/fpga_selftest.c @@ -71,10 +71,8 @@ bool fpga_spi_selftest(void) // Test writing a register and reading it back. uint8_t reg = 6; uint8_t write_value = 0xA5; - ssp1_set_mode_ice40(); ice40_spi_write(&ice40, reg, write_value); uint8_t read_value = ice40_spi_read(&ice40, reg); - ssp1_set_mode_max283x(); // Update selftest result. selftest.fpga_spi = (read_value == write_value) ? PASSED : FAILED; diff --git a/firmware/common/ice40_spi.c b/firmware/common/ice40_spi.c index 2685092a..ce646fd6 100644 --- a/firmware/common/ice40_spi.c +++ b/firmware/common/ice40_spi.c @@ -40,11 +40,6 @@ ice40_spi_driver_t ice40 = { .bus = &spi_bus_ssp1, }; -void ssp1_set_mode_ice40(void) -{ - spi_bus_start(&spi_bus_ssp1, &ssp_config_ice40_fpga); -} - void ice40_spi_target_init(ice40_spi_driver_t* const drv) { const platform_scu_t* scu = platform_scu(); @@ -67,14 +62,14 @@ void ice40_spi_target_init(ice40_spi_driver_t* const drv) uint8_t ice40_spi_read(ice40_spi_driver_t* const drv, uint8_t r) { uint8_t value[3] = {r & 0x7F, 0, 0}; - spi_bus_transfer(drv->bus, value, 3); + spi_bus_transfer(drv->bus, &ssp_config_ice40_fpga, value, 3); return value[2]; } void ice40_spi_write(ice40_spi_driver_t* const drv, uint8_t r, uint16_t v) { uint8_t value[3] = {(r & 0x7F) | 0x80, v, 0}; - spi_bus_transfer(drv->bus, value, 3); + spi_bus_transfer(drv->bus, &ssp_config_ice40_fpga, value, 3); } static void spi_ssp1_wait_for_tx_fifo_not_full(void) @@ -107,6 +102,8 @@ bool ice40_spi_syscfg_program( size_t (*read_block_cb)(void* ctx), void* read_ctx) { + spi_bus_start(drv->bus, &ssp_config_ice40_fpga); + // Drive CRESET_B = 0, SPI_SS = 0, SPI_SCK = 1. gpio_clear(drv->gpio_creset); gpio_clear(drv->gpio_select); diff --git a/firmware/common/ice40_spi.h b/firmware/common/ice40_spi.h index a1362033..331814aa 100644 --- a/firmware/common/ice40_spi.h +++ b/firmware/common/ice40_spi.h @@ -48,4 +48,3 @@ bool ice40_spi_syscfg_program( /* Driver instance. */ extern ssp_config_t ssp_config_ice40_fpga; extern ice40_spi_driver_t ice40; -void ssp1_set_mode_ice40(void); diff --git a/firmware/common/max2831.c b/firmware/common/max2831.c index 05d5cb29..08e59a59 100644 --- a/firmware/common/max2831.c +++ b/firmware/common/max2831.c @@ -109,7 +109,7 @@ static void max2831_write(max2831_driver_t* const drv, uint8_t r, uint16_t v) { uint32_t word = (((uint32_t) v & 0x3fff) << 4) | (r & 0xf); uint16_t values[2] = {word >> 9, word & 0x1ff}; - spi_bus_transfer(drv->bus, values, 2); + spi_bus_transfer(drv->bus, drv->config, values, 2); } uint16_t max2831_reg_read(max2831_driver_t* const drv, uint8_t r) diff --git a/firmware/common/max2831.h b/firmware/common/max2831.h index 0885fd39..f1a28c54 100644 --- a/firmware/common/max2831.h +++ b/firmware/common/max2831.h @@ -50,6 +50,7 @@ typedef enum { typedef struct _max2831_driver_t { spi_bus_t* bus; + void* config; gpio_t gpio_enable; gpio_t gpio_rxtx; gpio_t gpio_rxhp; diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index 561a17f9..f512c6af 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -156,14 +156,14 @@ void max2837_setup(max2837_driver_t* const drv) static uint16_t max2837_read(max2837_driver_t* const drv, uint8_t r) { uint16_t value = (1 << 15) | (r << 10); - spi_bus_transfer(drv->bus, &value, 1); + spi_bus_transfer(drv->bus, drv->config, &value, 1); return value & 0x3ff; } static void max2837_write(max2837_driver_t* const drv, uint8_t r, uint16_t v) { uint16_t value = (r << 10) | (v & 0x3ff); - spi_bus_transfer(drv->bus, &value, 1); + spi_bus_transfer(drv->bus, drv->config, &value, 1); } uint16_t max2837_reg_read(max2837_driver_t* const drv, uint8_t r) diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index f32bde6e..a33179ac 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -43,6 +43,7 @@ typedef enum { typedef struct _max2837_driver_t { spi_bus_t* bus; + void* config; gpio_t gpio_enable; gpio_t gpio_rx_enable; gpio_t gpio_tx_enable; diff --git a/firmware/common/max2839.c b/firmware/common/max2839.c index 87917ed8..a938b733 100644 --- a/firmware/common/max2839.c +++ b/firmware/common/max2839.c @@ -164,14 +164,14 @@ void max2839_setup(max2839_driver_t* const drv) static uint16_t max2839_read(max2839_driver_t* const drv, uint8_t r) { uint16_t value = (1 << 15) | (r << 10); - spi_bus_transfer(drv->bus, &value, 1); + spi_bus_transfer(drv->bus, drv->config, &value, 1); return value & 0x3ff; } static void max2839_write(max2839_driver_t* const drv, uint8_t r, uint16_t v) { uint16_t value = (r << 10) | (v & 0x3ff); - spi_bus_transfer(drv->bus, &value, 1); + spi_bus_transfer(drv->bus, drv->config, &value, 1); } uint16_t max2839_reg_read(max2839_driver_t* const drv, uint8_t r) diff --git a/firmware/common/max2839.h b/firmware/common/max2839.h index 0e397294..6430ce37 100644 --- a/firmware/common/max2839.h +++ b/firmware/common/max2839.h @@ -46,6 +46,7 @@ typedef enum { typedef struct _max2839_driver_t { spi_bus_t* bus; + void* config; gpio_t gpio_enable; gpio_t gpio_rxtx; void (*target_init)(struct _max2839_driver_t* const drv); diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index e7221bb0..c0478ae0 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -29,7 +29,6 @@ #include "fixed_point.h" #include "platform_detect.h" #include "platform_gpio.h" -#include "spi_bus.h" #ifdef IS_PRALINE #include "max2831_target.h" @@ -56,14 +55,10 @@ ssp_config_t ssp_config_max283x = { max283x_driver_t max283x = {}; -void ssp1_set_mode_max283x(void) -{ - spi_bus_start(&spi_bus_ssp1, &ssp_config_max283x); -} - #ifdef IS_PRALINE max2831_driver_t max2831 = { .bus = &spi_bus_ssp1, + .config = &ssp_config_max283x, .target_init = max2831_target_init, .set_mode = max2831_target_set_mode, }; @@ -72,6 +67,7 @@ max2831_driver_t max2831 = { #ifdef IS_NOT_PRALINE max2837_driver_t max2837 = { .bus = &spi_bus_ssp1, + .config = &ssp_config_max283x, .target_init = max2837_target_init, .set_mode = max2837_target_set_mode, }; @@ -80,6 +76,7 @@ max2837_driver_t max2837 = { #ifdef IS_HACKRF_ONE max2839_driver_t max2839 = { .bus = &spi_bus_ssp1, + .config = &ssp_config_max283x, .target_init = max2839_target_init, .set_mode = max2839_target_set_mode, }; diff --git a/firmware/common/max283x.h b/firmware/common/max283x.h index 4db5edfe..7c9c03dd 100644 --- a/firmware/common/max283x.h +++ b/firmware/common/max283x.h @@ -143,4 +143,3 @@ void max283x_rx_calibration(max283x_driver_t* const drv); /* Driver instance. */ extern ssp_config_t ssp_config_max283x; extern max283x_driver_t max283x; -void ssp1_set_mode_max283x(void); diff --git a/firmware/common/max5864.c b/firmware/common/max5864.c index 88d781b9..5f3417fc 100644 --- a/firmware/common/max5864.c +++ b/firmware/common/max5864.c @@ -48,14 +48,9 @@ max5864_driver_t max5864 = { .target_init = max5864_target_init, }; -void ssp1_set_mode_max5864(void) -{ - spi_bus_start(max5864.bus, &ssp_config_max5864); -} - static void max5864_write(max5864_driver_t* const drv, uint8_t value) { - spi_bus_transfer(drv->bus, &value, 1); + spi_bus_transfer(drv->bus, &ssp_config_max5864, &value, 1); } static void max5864_init(max5864_driver_t* const drv) diff --git a/firmware/common/max5864.h b/firmware/common/max5864.h index a617cdf0..0f561685 100644 --- a/firmware/common/max5864.h +++ b/firmware/common/max5864.h @@ -42,4 +42,3 @@ void max5864_xcvr(max5864_driver_t* const drv); /* Driver instance. */ extern ssp_config_t ssp_config_max5864; extern max5864_driver_t max5864; -void ssp1_set_mode_max5864(void); diff --git a/firmware/common/pins.c b/firmware/common/pins.c index 3010cd9f..1f98fd9a 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -318,8 +318,6 @@ void pins_setup(void) } #endif - ssp1_set_mode_max283x(); - mixer_bus_setup(&mixer); #ifdef IS_H1_R9 diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index b497a197..27dd548f 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -494,11 +494,9 @@ void rf_path_pin_setup(rf_path_t* const rf_path) void rf_path_init(rf_path_t* const rf_path) { - ssp1_set_mode_max5864(); max5864_setup(&max5864); max5864_shutdown(&max5864); - ssp1_set_mode_max283x(); max283x_setup(&max283x); max283x_start(&max283x); @@ -536,9 +534,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d } else { mixer_enable(&mixer); } - ssp1_set_mode_max5864(); max5864_tx(&max5864); - ssp1_set_mode_max283x(); max283x_tx(&max283x); break; @@ -553,9 +549,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d } else { mixer_enable(&mixer); } - ssp1_set_mode_max5864(); max5864_rx(&max5864); - ssp1_set_mode_max283x(); max283x_rx(&max283x); break; @@ -564,9 +558,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d case RF_PATH_DIRECTION_RX_CALIBRATION: rf_path->switchctrl &= ~SWITCHCTRL_TX; mixer_disable(&mixer); - ssp1_set_mode_max5864(); max5864_xcvr(&max5864); - ssp1_set_mode_max283x(); if (direction == RF_PATH_DIRECTION_TX_CALIBRATION) { max283x_tx_calibration(&max283x); } else { @@ -581,9 +573,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d /* Set RF path to receive direction when "off" */ rf_path->switchctrl &= ~SWITCHCTRL_TX; mixer_disable(&mixer); - ssp1_set_mode_max5864(); max5864_standby(&max5864); - ssp1_set_mode_max283x(); max283x_set_mode(&max283x, MAX283x_MODE_STANDBY); break; } diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 2a1866d2..0644a1fa 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -202,7 +202,7 @@ static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) (void) drv; uint16_t data[] = {0x80 | (r & 0x7f), 0xffff}; - spi_bus_transfer(drv->bus, data, 2); + spi_bus_transfer(drv->bus, drv->bus->config, data, 2); return data[1]; } @@ -211,7 +211,7 @@ static void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t (void) drv; uint16_t data[] = {0x00 | (r & 0x7f), v}; - spi_bus_transfer(drv->bus, data, 2); + spi_bus_transfer(drv->bus, drv->bus->config, data, 2); } uint16_t rffc5071_reg_read(rffc5071_driver_t* const drv, uint8_t r) diff --git a/firmware/common/spi_bus.c b/firmware/common/spi_bus.c index 1b05c298..a667db8a 100644 --- a/firmware/common/spi_bus.c +++ b/firmware/common/spi_bus.c @@ -31,17 +31,29 @@ void spi_bus_start(spi_bus_t* const bus, const void* const config) void spi_bus_stop(spi_bus_t* const bus) { bus->stop(bus); + bus->config = NULL; } -void spi_bus_transfer(spi_bus_t* const bus, void* const data, const size_t count) +void spi_bus_transfer( + spi_bus_t* const bus, + const void* const config, + void* const data, + const size_t count) { + if (config != bus->config) { + spi_bus_start(bus, config); + } bus->transfer(bus, data, count); } void spi_bus_transfer_gather( spi_bus_t* const bus, + const void* const config, const spi_transfer_t* const transfers, const size_t count) { + if (config != bus->config) { + spi_bus_start(bus, config); + } bus->transfer_gather(bus, transfers, count); } diff --git a/firmware/common/spi_bus.h b/firmware/common/spi_bus.h index 07d5787d..bc9c7dee 100644 --- a/firmware/common/spi_bus.h +++ b/firmware/common/spi_bus.h @@ -46,8 +46,13 @@ typedef struct _spi_bus_t { void spi_bus_start(spi_bus_t* const bus, const void* const config); void spi_bus_stop(spi_bus_t* const bus); -void spi_bus_transfer(spi_bus_t* const bus, void* const data, const size_t count); +void spi_bus_transfer( + spi_bus_t* const bus, + const void* const config, + void* const data, + const size_t count); void spi_bus_transfer_gather( spi_bus_t* const bus, + const void* const config, const spi_transfer_t* const transfers, const size_t count); diff --git a/firmware/common/ui_rad1o.c b/firmware/common/ui_rad1o.c index acaa2153..a6d3e544 100644 --- a/firmware/common/ui_rad1o.c +++ b/firmware/common/ui_rad1o.c @@ -26,7 +26,6 @@ #include #include "clock_gen.h" -#include "max283x.h" #include "rf_path.h" #include "transceiver_mode.h" @@ -195,9 +194,6 @@ static void ui_update(void) rad1o_lcdNl(); rad1o_lcdDisplay(); - - // Don't ask... - ssp1_set_mode_max283x(); } static void rad1o_ui_init(void) @@ -211,8 +207,6 @@ static void rad1o_ui_deinit(void) { rad1o_lcdDeInit(); enabled = false; - // Don't ask... - ssp1_set_mode_max283x(); } static void rad1o_ui_set_frequency(uint64_t frequency) diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index 11c6d5c0..9afa9bea 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -67,6 +67,22 @@ w25q80bv_driver_t spi_flash = { .target_init = w25q80bv_target_init, }; +static void w25q80bv_transfer( + w25q80bv_driver_t* const drv, + void* const data, + const size_t count) +{ + spi_bus_transfer(drv->bus, &ssp_config_w25q80bv, data, count); +} + +static void w25q80bv_transfer_gather( + w25q80bv_driver_t* const drv, + const spi_transfer_t* const transfers, + size_t size) +{ + spi_bus_transfer_gather(drv->bus, &ssp_config_w25q80bv, transfers, size); +} + /* * Set up pins for GPIO and SPI control, configure SSP0 peripheral for SPI. * SSP0_CS is controlled by GPIO in order to handle various transfer lengths. @@ -96,7 +112,7 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv) uint8_t w25q80bv_get_status(w25q80bv_driver_t* const drv) { uint8_t data[] = {W25Q80BV_READ_STATUS1, 0xFF}; - spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); + w25q80bv_transfer(drv, data, ARRAY_SIZE(data)); return data[1]; } @@ -104,7 +120,7 @@ uint8_t w25q80bv_get_status(w25q80bv_driver_t* const drv) uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv) { uint8_t data[] = {W25Q80BV_DEVICE_ID, 0xFF, 0xFF, 0xFF, 0xFF}; - spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); + w25q80bv_transfer(drv, data, ARRAY_SIZE(data)); return data[4]; } @@ -124,7 +140,7 @@ void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* 0xFF, 0xFF, 0xFF}; - spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); + w25q80bv_transfer(drv, data, ARRAY_SIZE(data)); for (size_t i = 0; i < 8; i++) { unique_id->id_8b[i] = data[5 + i]; @@ -141,7 +157,7 @@ void w25q80bv_write_enable(w25q80bv_driver_t* const drv) w25q80bv_wait_while_busy(drv); uint8_t data[] = {W25Q80BV_WRITE_ENABLE}; - spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); + w25q80bv_transfer(drv, data, ARRAY_SIZE(data)); while (!(w25q80bv_get_status(drv) & W25Q80BV_STATUS_WEL)) {} } @@ -159,7 +175,7 @@ void w25q80bv_chip_erase(w25q80bv_driver_t* const drv) w25q80bv_write_enable(drv); uint8_t data[] = {W25Q80BV_CHIP_ERASE}; - spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); + w25q80bv_transfer(drv, data, ARRAY_SIZE(data)); } /* write up a 256 byte page or partial page */ @@ -190,7 +206,7 @@ static void w25q80bv_page_program( const spi_transfer_t transfers[] = {{header, ARRAY_SIZE(header)}, {data, len}}; - spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers)); + w25q80bv_transfer_gather(drv, transfers, ARRAY_SIZE(transfers)); } /* write an arbitrary number of bytes */ @@ -265,7 +281,7 @@ void w25q80bv_read( const spi_transfer_t transfers[] = {{header, ARRAY_SIZE(header)}, {data, len}}; - spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers)); + w25q80bv_transfer_gather(drv, transfers, ARRAY_SIZE(transfers)); } void w25q80bv_clear_status(w25q80bv_driver_t* const drv) @@ -273,16 +289,16 @@ void w25q80bv_clear_status(w25q80bv_driver_t* const drv) w25q80bv_wait_while_busy(drv); w25q80bv_write_enable(drv); uint8_t data[] = {W25Q80BV_WRITE_STATUS, 0x00, 0x00}; - spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); + w25q80bv_transfer(drv, data, ARRAY_SIZE(data)); } void w25q80bv_get_full_status(w25q80bv_driver_t* const drv, uint8_t* data) { uint8_t cmd[] = {W25Q80BV_READ_STATUS1, 0xFF}; - spi_bus_transfer(drv->bus, cmd, ARRAY_SIZE(cmd)); + w25q80bv_transfer(drv, cmd, ARRAY_SIZE(cmd)); data[0] = cmd[1]; cmd[0] = W25Q80BV_READ_STATUS2; cmd[1] = 0xFF; - spi_bus_transfer(drv->bus, cmd, ARRAY_SIZE(cmd)); + w25q80bv_transfer(drv, cmd, ARRAY_SIZE(cmd)); data[1] = cmd[1]; } From ff052af3526dd915ac8a0728a2196ab58fc0cf16 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 8 Jun 2026 16:17:11 +0100 Subject: [PATCH 214/238] si5351c: Move the clk array into the driver struct. --- firmware/common/si5351c.c | 74 +++++++++++++++++++-------------------- firmware/common/si5351c.h | 15 ++++---- 2 files changed, 44 insertions(+), 45 deletions(-) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 353a4d2e..2fe487a3 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -51,8 +51,6 @@ si5351c_driver_t si5351c = { .i2c_address = 0x60, }; -si5351c_clk_t clk[8]; - uint8_t clkout_id; uint8_t mcu_clkin_id; @@ -267,12 +265,12 @@ void si5351c_configure_multisynth( void si5351c_configure_clock_control(si5351c_driver_t* const drv) { for (int i = 0; i < 8; i++) { - set_CLK_PDN(drv, i, clk[i].power_down); - set_MS_INT(drv, i, clk[i].mode); - set_MS_SRC(drv, i, clk[i].pll); - set_CLK_SRC(drv, i, clk[i].source); - set_CLK_IDRV(drv, i, clk[i].drive); - set_CLK_INV(drv, i, clk[i].invert); + set_CLK_PDN(drv, i, drv->clk[i].power_down); + set_MS_INT(drv, i, drv->clk[i].mode); + set_MS_SRC(drv, i, drv->clk[i].pll); + set_CLK_SRC(drv, i, drv->clk[i].source); + set_CLK_IDRV(drv, i, drv->clk[i].drive); + set_CLK_INV(drv, i, drv->clk[i].invert); } si5351c_regs_commit(drv); @@ -284,15 +282,15 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) set_CLK_OEB( drv, i, - clk[i].output_enable ? SI5351C_OUTPUT_ENABLE : - SI5351C_OUTPUT_DISABLE); + drv->clk[i].output_enable ? SI5351C_OUTPUT_ENABLE : + SI5351C_OUTPUT_DISABLE); } si5351c_regs_commit(drv); #ifdef IS_H1_R9 if (IS_H1_R9) { const platform_gpio_t* gpio = platform_gpio(); - if (clk[clkout_id].output_enable) { + if (drv->clk[clkout_id].output_enable) { gpio_set(gpio->h1r9_clkout_en); } else { gpio_clear(gpio->h1r9_clkout_en); @@ -355,8 +353,8 @@ bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv) void si5351c_clkout_enable(si5351c_driver_t* const drv, bool enable) { - clk[clkout_id].output_enable = enable; - clk[clkout_id].power_down = !enable; + drv->clk[clkout_id].output_enable = enable; + drv->clk[clkout_id].power_down = !enable; /* Configure clock to 10MHz */ si5351c_configure_multisynth(drv, clkout_id, 80 * 128 - 512, 0, 1, 0); @@ -375,8 +373,8 @@ void si5351c_mcu_clkin_enable(si5351c_driver_t* const drv, bool enable) #endif #ifdef IS_NOT_H1_R9 if (IS_NOT_H1_R9) { - clk[mcu_clkin_id].output_enable = enable; - clk[mcu_clkin_id].power_down = !enable; + drv->clk[mcu_clkin_id].output_enable = enable; + drv->clk[mcu_clkin_id].power_down = !enable; /* Configure clock to 40MHz */ if (mcu_clkin_id >= 6) { @@ -485,7 +483,7 @@ void si5351c_init(si5351c_driver_t* const drv) }; /* CLK0: MAX5864/CPLD */ - clk[0] = (si5351c_clk_t){ + drv->clk[0] = (si5351c_clk_t){ .output_enable = true, .mode = SI5351C_MODE_FRAC, .pll = SI5351C_PLL_A, @@ -493,7 +491,7 @@ void si5351c_init(si5351c_driver_t* const drv) .drive = SI5351C_DRIVE_8MA, }; /* CLK1: CPLD */ - clk[1] = (si5351c_clk_t){ + drv->clk[1] = (si5351c_clk_t){ .output_enable = true, .mode = SI5351C_MODE_INT, .pll = SI5351C_PLL_A, @@ -502,7 +500,7 @@ void si5351c_init(si5351c_driver_t* const drv) .invert = true, }; /* CLK2: SGPIO */ - clk[2] = (si5351c_clk_t){ + drv->clk[2] = (si5351c_clk_t){ .output_enable = true, .mode = SI5351C_MODE_INT, .pll = SI5351C_PLL_A, @@ -510,10 +508,10 @@ void si5351c_init(si5351c_driver_t* const drv) .drive = SI5351C_DRIVE_2MA, }; /* CLK3: CLKOUT */ - clk[3] = clkout; + drv->clk[3] = clkout; clkout_id = 3; /* CLK4: RFFC5072 (MAX2837 on rad1o) */ - clk[4] = (si5351c_clk_t){ + drv->clk[4] = (si5351c_clk_t){ .output_enable = true, .mode = SI5351C_MODE_INT, .pll = SI5351C_PLL_A, @@ -522,7 +520,7 @@ void si5351c_init(si5351c_driver_t* const drv) .invert = true, }; /* CLK5: MAX2837 (MAX2871 on rad1o) */ - clk[5] = (si5351c_clk_t){ + drv->clk[5] = (si5351c_clk_t){ .output_enable = true, .mode = SI5351C_MODE_INT, .pll = SI5351C_PLL_A, @@ -530,15 +528,15 @@ void si5351c_init(si5351c_driver_t* const drv) .drive = SI5351C_DRIVE_4MA, }; /* CLK6: none */ - clk[6] = powered_down; + drv->clk[6] = powered_down; /* CLK7: LPC43xx */ - clk[7] = mcu_clkin; + drv->clk[7] = mcu_clkin; mcu_clkin_id = 7; #ifdef IS_H1_R9 if (IS_H1_R9) { /* CLK0: MAX5864/CPLD/SGPIO (sample clocks) */ - clk[0] = (si5351c_clk_t){ + drv->clk[0] = (si5351c_clk_t){ .output_enable = true, .mode = SI5351C_MODE_INT, .pll = SI5351C_PLL_A, @@ -546,7 +544,7 @@ void si5351c_init(si5351c_driver_t* const drv) .drive = SI5351C_DRIVE_6MA, }; /* CLK1: RFFC5072/MAX2839 */ - clk[1] = (si5351c_clk_t){ + drv->clk[1] = (si5351c_clk_t){ .output_enable = true, .mode = SI5351C_MODE_FRAC, .pll = SI5351C_PLL_A, @@ -554,21 +552,21 @@ void si5351c_init(si5351c_driver_t* const drv) .drive = SI5351C_DRIVE_4MA, }; /* CLK2: CLKOUT/LPC4320 */ - clk[2] = clkout; + drv->clk[2] = clkout; clkout_id = 2; mcu_clkin_id = 2; /* Other outputs not present on Si5351A */ - clk[3] = powered_down; - clk[4] = powered_down; - clk[5] = powered_down; - clk[6] = powered_down; - clk[7] = powered_down; + drv->clk[3] = powered_down; + drv->clk[4] = powered_down; + drv->clk[5] = powered_down; + drv->clk[6] = powered_down; + drv->clk[7] = powered_down; } #endif #ifdef IS_PRALINE if (IS_PRALINE) { /* CLK0: AFE_CLK */ - clk[0] = (si5351c_clk_t){ + drv->clk[0] = (si5351c_clk_t){ .output_enable = true, .mode = SI5351C_MODE_FRAC, .pll = SI5351C_PLL_A, @@ -576,7 +574,7 @@ void si5351c_init(si5351c_driver_t* const drv) .drive = SI5351C_DRIVE_4MA, }; /* CLK1: SCT_CLK and FPGA_CLK */ - clk[1] = (si5351c_clk_t){ + drv->clk[1] = (si5351c_clk_t){ .output_enable = true, .mode = SI5351C_MODE_FRAC, .pll = SI5351C_PLL_A, @@ -585,10 +583,10 @@ void si5351c_init(si5351c_driver_t* const drv) }; /* CLK3: CLKOUT */ clkout.pll = SI5351C_PLL_B; - clk[3] = clkout; + drv->clk[3] = clkout; clkout_id = 3; /* CLK4: XCVR_CLK */ - clk[4] = (si5351c_clk_t){ + drv->clk[4] = (si5351c_clk_t){ .output_enable = true, .mode = SI5351C_MODE_INT, .pll = SI5351C_PLL_B, @@ -597,7 +595,7 @@ void si5351c_init(si5351c_driver_t* const drv) .invert = true, }; /* CLK5: MIX_CLK */ - clk[5] = (si5351c_clk_t){ + drv->clk[5] = (si5351c_clk_t){ .output_enable = true, .mode = SI5351C_MODE_INT, .pll = SI5351C_PLL_B, @@ -606,7 +604,7 @@ void si5351c_init(si5351c_driver_t* const drv) }; if ((detected_revision() & ~BOARD_REV_GSG) < BOARD_REV_PRALINE_R1_1) { /* CLK2: FPGA_CLK (not shared with SCT_CLK on older boards) */ - clk[2] = (si5351c_clk_t){ + drv->clk[2] = (si5351c_clk_t){ .output_enable = true, .mode = SI5351C_MODE_FRAC, .pll = SI5351C_PLL_A, @@ -615,7 +613,7 @@ void si5351c_init(si5351c_driver_t* const drv) }; } else { /* CLK2: MCU_CLK */ - clk[2] = mcu_clkin; + drv->clk[2] = mcu_clkin; mcu_clkin_id = 2; } } diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index dad74a17..c3a0558e 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -89,13 +89,6 @@ typedef enum { SI5351C_INPUT_CLKIN = 1, } si5351c_input_t; -typedef struct { - i2c_bus_t* const bus; - uint8_t i2c_address; - uint8_t regs[SI5351C_CACHED_REGS]; - uint32_t regs_dirty[(SI5351C_CACHED_REGS + 31) / 32]; -} si5351c_driver_t; - typedef struct { bool output_enable; bool power_down; @@ -106,6 +99,14 @@ typedef struct { bool invert; } si5351c_clk_t; +typedef struct { + i2c_bus_t* const bus; + uint8_t i2c_address; + si5351c_clk_t clk[8]; + uint8_t regs[SI5351C_CACHED_REGS]; + uint32_t regs_dirty[(SI5351C_CACHED_REGS + 31) / 32]; +} si5351c_driver_t; + void si5351c_disable_all_outputs(si5351c_driver_t* const drv); void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv); void si5351c_power_down_all_clocks(si5351c_driver_t* const drv); From a716b642eca1247a2e41a68fc594ecaa59be1f47 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 8 Jun 2026 16:24:15 +0100 Subject: [PATCH 215/238] si5351c: Move other globals into driver struct. --- firmware/common/si5351c.c | 42 +++++++++++++++++---------------------- firmware/common/si5351c.h | 4 ++++ 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 2fe487a3..9fbe8764 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -51,12 +51,6 @@ si5351c_driver_t si5351c = { .i2c_address = 0x60, }; -uint8_t clkout_id; -uint8_t mcu_clkin_id; - -static bool input_initialized = false; -static si5351c_input_t active_input; - /* write to single register */ void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val) { @@ -290,7 +284,7 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) #ifdef IS_H1_R9 if (IS_H1_R9) { const platform_gpio_t* gpio = platform_gpio(); - if (drv->clk[clkout_id].output_enable) { + if (drv->clk[drv->clkout_id].output_enable) { gpio_set(gpio->h1r9_clkout_en); } else { gpio_clear(gpio->h1r9_clkout_en); @@ -310,7 +304,7 @@ void si5351c_set_int_mode( void si5351c_change_input(si5351c_driver_t* const drv, si5351c_input_t input) { - if (input_initialized && input == active_input) { + if (drv->input_initialized && input == drv->active_input) { return; } si5351c_disable_all_outputs(drv); @@ -334,8 +328,8 @@ void si5351c_change_input(si5351c_driver_t* const drv, si5351c_input_t input) } #endif si5351c_configure_pll_multisynth(drv, input); - active_input = input; - input_initialized = true; + drv->active_input = input; + drv->input_initialized = true; si5351c_reset_plls(drv, SI5351C_PLL_MASK_BOTH); } @@ -353,11 +347,11 @@ bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv) void si5351c_clkout_enable(si5351c_driver_t* const drv, bool enable) { - drv->clk[clkout_id].output_enable = enable; - drv->clk[clkout_id].power_down = !enable; + drv->clk[drv->clkout_id].output_enable = enable; + drv->clk[drv->clkout_id].power_down = !enable; /* Configure clock to 10MHz */ - si5351c_configure_multisynth(drv, clkout_id, 80 * 128 - 512, 0, 1, 0); + si5351c_configure_multisynth(drv, drv->clkout_id, 80 * 128 - 512, 0, 1, 0); si5351c_configure_clock_control(drv); si5351c_enable_clock_outputs(drv); @@ -373,18 +367,18 @@ void si5351c_mcu_clkin_enable(si5351c_driver_t* const drv, bool enable) #endif #ifdef IS_NOT_H1_R9 if (IS_NOT_H1_R9) { - drv->clk[mcu_clkin_id].output_enable = enable; - drv->clk[mcu_clkin_id].power_down = !enable; + drv->clk[drv->mcu_clkin_id].output_enable = enable; + drv->clk[drv->mcu_clkin_id].power_down = !enable; /* Configure clock to 40MHz */ - if (mcu_clkin_id >= 6) { + if (drv->mcu_clkin_id >= 6) { // MCU_CLKIN on CLK6 or CLK7, integer only MS. - si5351c_configure_multisynth(drv, mcu_clkin_id, 20, 0, 0, 0); + si5351c_configure_multisynth(drv, drv->mcu_clkin_id, 20, 0, 0, 0); } else { // MCU_CLKIN on CLK0 to CLK5, fractional-capable MS. si5351c_configure_multisynth( drv, - mcu_clkin_id, + drv->mcu_clkin_id, 20 * 128 - 512, 0, 1, @@ -509,7 +503,7 @@ void si5351c_init(si5351c_driver_t* const drv) }; /* CLK3: CLKOUT */ drv->clk[3] = clkout; - clkout_id = 3; + drv->clkout_id = 3; /* CLK4: RFFC5072 (MAX2837 on rad1o) */ drv->clk[4] = (si5351c_clk_t){ .output_enable = true, @@ -531,7 +525,7 @@ void si5351c_init(si5351c_driver_t* const drv) drv->clk[6] = powered_down; /* CLK7: LPC43xx */ drv->clk[7] = mcu_clkin; - mcu_clkin_id = 7; + drv->mcu_clkin_id = 7; #ifdef IS_H1_R9 if (IS_H1_R9) { @@ -553,8 +547,8 @@ void si5351c_init(si5351c_driver_t* const drv) }; /* CLK2: CLKOUT/LPC4320 */ drv->clk[2] = clkout; - clkout_id = 2; - mcu_clkin_id = 2; + drv->clkout_id = 2; + drv->mcu_clkin_id = 2; /* Other outputs not present on Si5351A */ drv->clk[3] = powered_down; drv->clk[4] = powered_down; @@ -584,7 +578,7 @@ void si5351c_init(si5351c_driver_t* const drv) /* CLK3: CLKOUT */ clkout.pll = SI5351C_PLL_B; drv->clk[3] = clkout; - clkout_id = 3; + drv->clkout_id = 3; /* CLK4: XCVR_CLK */ drv->clk[4] = (si5351c_clk_t){ .output_enable = true, @@ -614,7 +608,7 @@ void si5351c_init(si5351c_driver_t* const drv) } else { /* CLK2: MCU_CLK */ drv->clk[2] = mcu_clkin; - mcu_clkin_id = 2; + drv->mcu_clkin_id = 2; } } #endif diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index c3a0558e..666a79f4 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -103,6 +103,10 @@ typedef struct { i2c_bus_t* const bus; uint8_t i2c_address; si5351c_clk_t clk[8]; + uint8_t clkout_id; + uint8_t mcu_clkin_id; + bool input_initialized; + si5351c_input_t active_input; uint8_t regs[SI5351C_CACHED_REGS]; uint32_t regs_dirty[(SI5351C_CACHED_REGS + 31) / 32]; } si5351c_driver_t; From c77c962b7185593cf975134e924e066c33791d7d Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 18 May 2026 18:25:25 +0100 Subject: [PATCH 216/238] Move max283x-related bits out of pins_setup. --- firmware/common/max283x.c | 5 +++++ firmware/common/pins.c | 14 -------------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/firmware/common/max283x.c b/firmware/common/max283x.c index c0478ae0..f9486921 100644 --- a/firmware/common/max283x.c +++ b/firmware/common/max283x.c @@ -26,6 +26,8 @@ #include #include +#include + #include "fixed_point.h" #include "platform_detect.h" #include "platform_gpio.h" @@ -88,8 +90,10 @@ void max283x_setup(max283x_driver_t* const drv) const platform_gpio_t* gpio = platform_gpio(); /* MAX283x GPIO PinMux */ + ssp_config_max283x.gpio_select = gpio->max283x_select; #ifdef IS_PRALINE if (IS_PRALINE) { + ssp_config_max283x.data_bits = SSP_DATA_9BITS; drv->type = MAX2831_VARIANT; max2831.gpio_enable = gpio->max283x_enable; max2831.gpio_rxtx = gpio->max283x_rx_enable; @@ -101,6 +105,7 @@ void max283x_setup(max283x_driver_t* const drv) #endif #ifdef IS_NOT_PRALINE if (IS_NOT_PRALINE) { + ssp_config_max283x.data_bits = SSP_DATA_16BITS; #ifdef IS_H1_R9 if (IS_H1_R9) { drv->type = MAX2839_VARIANT; diff --git a/firmware/common/pins.c b/firmware/common/pins.c index 1f98fd9a..3fcbf037 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -24,12 +24,10 @@ #include "pins.h" #include -#include #include "cpld_jtag.h" #include "gpio.h" #include "leds.h" -#include "max283x.h" #include "max5864.h" #include "mixer.h" #include "platform_detect.h" @@ -266,18 +264,6 @@ void pins_setup(void) #endif /* Configure drivers and driver pins */ - ssp_config_max283x.gpio_select = gpio->max283x_select; -#ifdef IS_NOT_PRALINE - if (IS_NOT_PRALINE) { - ssp_config_max283x.data_bits = SSP_DATA_16BITS; - } -#endif -#ifdef IS_PRALINE - if (IS_PRALINE) { - ssp_config_max283x.data_bits = SSP_DATA_9BITS; // send 2 words - } -#endif - ssp_config_max5864.gpio_select = gpio->max5864_select; ssp_config_w25q80bv.gpio_select = gpio->w25q80bv_select; From 9d6e43a1cb611fc9bbd1917915745adae38bb23f Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 13 May 2026 23:11:47 +0100 Subject: [PATCH 217/238] Move max5864-related bits out of pins_setup. --- firmware/common/max5864.c | 3 +++ firmware/common/pins.c | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/common/max5864.c b/firmware/common/max5864.c index 5f3417fc..0b825fcd 100644 --- a/firmware/common/max5864.c +++ b/firmware/common/max5864.c @@ -27,6 +27,7 @@ #include #include "max5864_target.h" +#include "platform_gpio.h" #include "spi_bus.h" /* Driver instance. */ @@ -60,6 +61,8 @@ static void max5864_init(max5864_driver_t* const drv) void max5864_setup(max5864_driver_t* const drv) { + ssp_config_max5864.gpio_select = platform_gpio()->max5864_select; + max5864_init(drv); } diff --git a/firmware/common/pins.c b/firmware/common/pins.c index 3fcbf037..d917f7d2 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -28,7 +28,6 @@ #include "cpld_jtag.h" #include "gpio.h" #include "leds.h" -#include "max5864.h" #include "mixer.h" #include "platform_detect.h" #include "platform_gpio.h" @@ -264,8 +263,6 @@ void pins_setup(void) #endif /* Configure drivers and driver pins */ - ssp_config_max5864.gpio_select = gpio->max5864_select; - ssp_config_w25q80bv.gpio_select = gpio->w25q80bv_select; spi_flash.gpio_hold = gpio->w25q80bv_hold; spi_flash.gpio_wp = gpio->w25q80bv_wp; From a7925bd74ea4229e8437991cd61af77bc306dd63 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 18 May 2026 16:31:54 +0100 Subject: [PATCH 218/238] Remove some superfluous spi_bus_setup calls. --- firmware/common/rom_iap.c | 2 -- firmware/hackrf_usb/hackrf_usb.c | 1 - firmware/hackrf_usb/usb_api_spiflash.c | 3 --- 3 files changed, 6 deletions(-) diff --git a/firmware/common/rom_iap.c b/firmware/common/rom_iap.c index 25dfa269..ce1f113b 100644 --- a/firmware/common/rom_iap.c +++ b/firmware/common/rom_iap.c @@ -23,7 +23,6 @@ #include #include "rom_iap.h" -#include "spi_bus.h" #include "w25q80bv.h" #define ROM_IAP_ADDR (0x10400100) @@ -77,7 +76,6 @@ isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res) Alternative way to retrieve Part Id on MCU with no IAP Read Serial No => Read Unique ID in SPIFI (only compatible with W25Q80BV */ - spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv); w25q80bv_setup(&spi_flash); switch (iap_cmd_res->cmd_param.command_code) { diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 5d71fa80..197ffb8a 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -275,7 +275,6 @@ extern uint32_t _binary_fpga_bin_start; void fpga_loader_setup(void) { - spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv); w25q80bv_setup(&spi_flash); } diff --git a/firmware/hackrf_usb/usb_api_spiflash.c b/firmware/hackrf_usb/usb_api_spiflash.c index c698d599..21370bd0 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.c +++ b/firmware/hackrf_usb/usb_api_spiflash.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -40,7 +39,6 @@ usb_request_status_t usb_vendor_request_erase_spiflash( const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { - spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv); w25q80bv_setup(&spi_flash); /* only chip erase is implemented */ w25q80bv_chip_erase(&spi_flash); @@ -69,7 +67,6 @@ usb_request_status_t usb_vendor_request_write_spiflash( len, NULL, NULL); - spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv); w25q80bv_setup(&spi_flash); return USB_REQUEST_STATUS_OK; } From 9c0a211f1362b57a40f09f2a99ad5f9deee33516 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 18 May 2026 16:34:24 +0100 Subject: [PATCH 219/238] Move w25q80bv-related bits out of pins_setup. --- firmware/common/pins.c | 5 ----- firmware/common/w25q80bv.c | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/firmware/common/pins.c b/firmware/common/pins.c index d917f7d2..3ce27b8d 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -35,7 +35,6 @@ #include "power.h" #include "rf_path.h" #include "sgpio.h" -#include "w25q80bv.h" #ifdef IS_PRALINE #include "clock_io.h" #include "ice40_spi.h" @@ -263,10 +262,6 @@ void pins_setup(void) #endif /* Configure drivers and driver pins */ - ssp_config_w25q80bv.gpio_select = gpio->w25q80bv_select; - spi_flash.gpio_hold = gpio->w25q80bv_hold; - spi_flash.gpio_wp = gpio->w25q80bv_wp; - sgpio_config.gpio_q_invert = gpio->q_invert; #ifdef IS_NOT_PRALINE diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index 9afa9bea..abd18624 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -35,6 +35,7 @@ #include #include "platform_detect.h" +#include "platform_gpio.h" #include "w25q80bv_target.h" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) @@ -90,6 +91,11 @@ static void w25q80bv_transfer_gather( void w25q80bv_setup(w25q80bv_driver_t* const drv) { uint8_t device_id; + const platform_gpio_t* gpio = platform_gpio(); + + ssp_config_w25q80bv.gpio_select = gpio->w25q80bv_select; + spi_flash.gpio_hold = gpio->w25q80bv_hold; + spi_flash.gpio_wp = gpio->w25q80bv_wp; drv->page_len = 256U; if (detected_platform() == BOARD_ID_PRALINE) { From b533e1c5dce61c2a34571844737d6290af4433ef Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 13 May 2026 23:29:39 +0100 Subject: [PATCH 220/238] Move sgpio-related bits out of pins_setup. --- firmware/common/pins.c | 18 ------------------ firmware/common/sgpio.c | 16 ++++++++++++++++ firmware/hackrf_usb/hackrf_usb.c | 2 ++ firmware/hackrf_usb/usb_api_board_info.c | 2 ++ 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/firmware/common/pins.c b/firmware/common/pins.c index 3ce27b8d..2bd135a3 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -34,7 +34,6 @@ #include "platform_scu.h" #include "power.h" #include "rf_path.h" -#include "sgpio.h" #ifdef IS_PRALINE #include "clock_io.h" #include "ice40_spi.h" @@ -228,7 +227,6 @@ void pins_shutdown(void) rf_path_pin_shutdown(); } #endif - sgpio_pin_shutdown(&sgpio_config); /* enable input on SCL and SDA pins */ SCU_SFSI2C0 = SCU_I2C0_NOMINAL; @@ -262,14 +260,6 @@ void pins_setup(void) #endif /* Configure drivers and driver pins */ - sgpio_config.gpio_q_invert = gpio->q_invert; - -#ifdef IS_NOT_PRALINE - if (IS_NOT_PRALINE) { - sgpio_config.gpio_trigger_enable = gpio->trigger_enable; - } -#endif - #ifdef IS_PRALINE if (IS_PRALINE) { ssp_config_ice40_fpga.gpio_select = gpio->fpga_cfg_spi_cs; @@ -298,12 +288,6 @@ void pins_setup(void) mixer_bus_setup(&mixer); -#ifdef IS_H1_R9 - if (IS_H1_R9) { - sgpio_config.gpio_trigger_enable = gpio->h1r9_trigger_enable; - } -#endif - // initialize rf_path struct and assign gpio's #ifdef IS_HACKRF_ONE if (IS_HACKRF_ONE) { @@ -375,6 +359,4 @@ void pins_setup(void) /* Configure external clock in */ scu_pinmux(scu->PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1); - - sgpio_configure_pin_functions(&sgpio_config); } diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index 09a5d8cf..1528933a 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -29,6 +29,7 @@ #include #include "platform_detect.h" +#include "platform_gpio.h" #include "platform_scu.h" #include "sgpio.h" #ifdef IS_NOT_PRALINE @@ -91,8 +92,23 @@ void sgpio_pin_shutdown(sgpio_config_t* const config) void sgpio_configure_pin_functions(sgpio_config_t* const config) { + const platform_gpio_t* gpio = platform_gpio(); const platform_scu_t* scu = platform_scu(); + config->gpio_q_invert = gpio->q_invert; + +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { + config->gpio_trigger_enable = gpio->trigger_enable; + } +#endif + +#ifdef IS_H1_R9 + if (IS_H1_R9) { + config->gpio_trigger_enable = gpio->h1r9_trigger_enable; + } +#endif + scu_pinmux(scu->PINMUX_SGPIO0, scu->PINMUX_SGPIO0_PINCFG); scu_pinmux(scu->PINMUX_SGPIO1, scu->PINMUX_SGPIO1_PINCFG); scu_pinmux(scu->PINMUX_SGPIO2, scu->PINMUX_SGPIO2_PINCFG); diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 197ffb8a..944b9556 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -429,11 +429,13 @@ int main(void) board_id_t board_id = detected_platform(); pins_shutdown(); + sgpio_pin_shutdown(&sgpio_config); if (board_id != BOARD_ID_RAD1O) { clock_gen_shutdown(); } delay_us_at_mhz(10000, 96); pins_setup(); + sgpio_configure_pin_functions(&sgpio_config); #ifdef IS_PRALINE if (IS_PRALINE) { enable_3v3aux_power(); diff --git a/firmware/hackrf_usb/usb_api_board_info.c b/firmware/hackrf_usb/usb_api_board_info.c index 2d017378..671cb862 100644 --- a/firmware/hackrf_usb/usb_api_board_info.c +++ b/firmware/hackrf_usb/usb_api_board_info.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -130,6 +131,7 @@ usb_request_status_t usb_vendor_request_reset( { if (stage == USB_TRANSFER_STAGE_SETUP) { pins_shutdown(); + sgpio_pin_shutdown(&sgpio_config); clock_gen_shutdown(); #ifdef IS_H1_R9 if (IS_H1_R9) { From e3ffbf68f0121bfa752577113c087691263a405b Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 13 May 2026 23:46:48 +0100 Subject: [PATCH 221/238] Move rf_path-related bits out of pins_setup. --- firmware/common/pins.c | 74 ------------------------ firmware/common/rf_path.c | 74 +++++++++++++++++++++++- firmware/hackrf_usb/hackrf_usb.c | 2 + firmware/hackrf_usb/usb_api_board_info.c | 2 + 4 files changed, 76 insertions(+), 76 deletions(-) diff --git a/firmware/common/pins.c b/firmware/common/pins.c index 2bd135a3..97f3f413 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -33,7 +33,6 @@ #include "platform_gpio.h" #include "platform_scu.h" #include "power.h" -#include "rf_path.h" #ifdef IS_PRALINE #include "clock_io.h" #include "ice40_spi.h" @@ -204,7 +203,6 @@ void pins_shutdown(void) p2_ctrl_set(P2_SIGNAL_CLK3); p1_ctrl_set(P1_SIGNAL_CLKIN); - narrowband_filter_set(0); clkin_ctrl_set(CLKIN_SIGNAL_P1); gpio_output(gpio->p2_ctrl0); @@ -214,7 +212,6 @@ void pins_shutdown(void) gpio_output(gpio->p1_ctrl2); gpio_output(gpio->clkin_ctrl); gpio_output(gpio->pps_out); - gpio_output(gpio->aa_en); gpio_input(gpio->trigger_in); gpio_input(gpio->trigger_out); gpio_clear(gpio->fpga_cfg_spi_cs); @@ -223,8 +220,6 @@ void pins_shutdown(void) gpio_output(gpio->fpga_cfg_creset); gpio_input(gpio->fpga_cfg_cdone); gpio_input(gpio->max5864_select); - - rf_path_pin_shutdown(); } #endif @@ -288,75 +283,6 @@ void pins_setup(void) mixer_bus_setup(&mixer); - // initialize rf_path struct and assign gpio's -#ifdef IS_HACKRF_ONE - if (IS_HACKRF_ONE) { - rf_path = (rf_path_t){ - .switchctrl = 0, - .gpio_hp = gpio->hp, - .gpio_lp = gpio->lp, - .gpio_tx_mix_bp = gpio->tx_mix_bp, - .gpio_no_mix_bypass = gpio->no_mix_bypass, - .gpio_rx_mix_bp = gpio->rx_mix_bp, - .gpio_tx_amp = gpio->tx_amp, - .gpio_tx = gpio->tx, - .gpio_mix_bypass = gpio->mix_bypass, - .gpio_rx = gpio->rx, - .gpio_no_tx_amp_pwr = gpio->no_tx_amp_pwr, - .gpio_amp_bypass = gpio->amp_bypass, - .gpio_rx_amp = gpio->rx_amp, - .gpio_no_rx_amp_pwr = gpio->no_rx_amp_pwr, - }; - #ifdef IS_H1_R9 - if (IS_H1_R9) { - rf_path.gpio_rx = gpio->h1r9_rx; - rf_path.gpio_h1r9_no_ant_pwr = gpio->h1r9_no_ant_pwr; - } - #endif - } -#endif - -#ifdef IS_RAD1O - if (IS_RAD1O) { - rf_path = (rf_path_t){ - .switchctrl = 0, - .gpio_tx_rx_n = gpio->tx_rx_n, - .gpio_tx_rx = gpio->tx_rx, - .gpio_by_mix = gpio->by_mix, - .gpio_by_mix_n = gpio->by_mix_n, - .gpio_by_amp = gpio->by_amp, - .gpio_by_amp_n = gpio->by_amp_n, - .gpio_mixer_en = gpio->mixer_en, - .gpio_low_high_filt = gpio->low_high_filt, - .gpio_low_high_filt_n = gpio->low_high_filt_n, - .gpio_tx_amp = gpio->tx_amp, - .gpio_rx_lna = gpio->rx_lna, - }; - } -#endif - -#ifdef IS_PRALINE - if (IS_PRALINE) { - rf_path = (rf_path_t){ - .switchctrl = 0, - .gpio_tx_en = gpio->tx_en, - .gpio_mix_en_n = gpio->mix_en_n, - .gpio_lpf_en = gpio->lpf_en, - .gpio_rf_amp_en = gpio->rf_amp_en, - .gpio_ant_bias_en_n = gpio->ant_bias_en_n, - }; - if ((detected_revision() == BOARD_REV_PRALINE_R1_0) || - (detected_revision() == BOARD_REV_GSG_PRALINE_R1_0)) { - rf_path.gpio_mix_en_n = gpio->mix_en_n_r1_0; - } - scu_pinmux(scu->PINMUX_FPGA_CRESET, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - scu_pinmux(scu->PINMUX_FPGA_CDONE, SCU_GPIO_PUP | SCU_CONF_FUNCTION4); - scu_pinmux(scu->PINMUX_FPGA_SPI_CS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - } -#endif - - rf_path_pin_setup(&rf_path); - /* Configure external clock in */ scu_pinmux(scu->PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1); } diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 27dd548f..51488c16 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -30,8 +30,6 @@ #ifdef IS_NOT_JAWBREAKER #include #include "platform_scu.h" -#endif -#ifdef IS_PRALINE #include "platform_gpio.h" #endif @@ -344,6 +342,10 @@ void rf_path_pin_shutdown(void) /* Configure RF power supply (VAA) switch */ scu_pinmux(scu->NO_VAA_ENABLE, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + + /* Disable narrowband filter. */ + narrowband_filter_set(0); + gpio_output(platform_gpio()->aa_en); } #endif } @@ -353,9 +355,77 @@ void rf_path_pin_setup(rf_path_t* const rf_path) #ifdef IS_JAWBREAKER (void) rf_path; #else + const platform_gpio_t* gpio = platform_gpio(); const platform_scu_t* scu = platform_scu(); #endif + // initialize rf_path struct and assign gpio's +#ifdef IS_HACKRF_ONE + if (IS_HACKRF_ONE) { + *rf_path = (rf_path_t){ + .switchctrl = 0, + .gpio_hp = gpio->hp, + .gpio_lp = gpio->lp, + .gpio_tx_mix_bp = gpio->tx_mix_bp, + .gpio_no_mix_bypass = gpio->no_mix_bypass, + .gpio_rx_mix_bp = gpio->rx_mix_bp, + .gpio_tx_amp = gpio->tx_amp, + .gpio_tx = gpio->tx, + .gpio_mix_bypass = gpio->mix_bypass, + .gpio_rx = gpio->rx, + .gpio_no_tx_amp_pwr = gpio->no_tx_amp_pwr, + .gpio_amp_bypass = gpio->amp_bypass, + .gpio_rx_amp = gpio->rx_amp, + .gpio_no_rx_amp_pwr = gpio->no_rx_amp_pwr, + }; + #ifdef IS_H1_R9 + if (IS_H1_R9) { + rf_path->gpio_rx = gpio->h1r9_rx; + rf_path->gpio_h1r9_no_ant_pwr = gpio->h1r9_no_ant_pwr; + } + #endif + } +#endif + +#ifdef IS_RAD1O + if (IS_RAD1O) { + *rf_path = (rf_path_t){ + .switchctrl = 0, + .gpio_tx_rx_n = gpio->tx_rx_n, + .gpio_tx_rx = gpio->tx_rx, + .gpio_by_mix = gpio->by_mix, + .gpio_by_mix_n = gpio->by_mix_n, + .gpio_by_amp = gpio->by_amp, + .gpio_by_amp_n = gpio->by_amp_n, + .gpio_mixer_en = gpio->mixer_en, + .gpio_low_high_filt = gpio->low_high_filt, + .gpio_low_high_filt_n = gpio->low_high_filt_n, + .gpio_tx_amp = gpio->tx_amp, + .gpio_rx_lna = gpio->rx_lna, + }; + } +#endif + +#ifdef IS_PRALINE + if (IS_PRALINE) { + *rf_path = (rf_path_t){ + .switchctrl = 0, + .gpio_tx_en = gpio->tx_en, + .gpio_mix_en_n = gpio->mix_en_n, + .gpio_lpf_en = gpio->lpf_en, + .gpio_rf_amp_en = gpio->rf_amp_en, + .gpio_ant_bias_en_n = gpio->ant_bias_en_n, + }; + if ((detected_revision() == BOARD_REV_PRALINE_R1_0) || + (detected_revision() == BOARD_REV_GSG_PRALINE_R1_0)) { + rf_path->gpio_mix_en_n = gpio->mix_en_n_r1_0; + } + scu_pinmux(scu->PINMUX_FPGA_CRESET, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(scu->PINMUX_FPGA_CDONE, SCU_GPIO_PUP | SCU_CONF_FUNCTION4); + scu_pinmux(scu->PINMUX_FPGA_SPI_CS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + } +#endif + #ifdef IS_HACKRF_ONE if (IS_HACKRF_ONE) { /* Configure RF switch control signals */ diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 944b9556..c4d32fae 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -430,12 +430,14 @@ int main(void) pins_shutdown(); sgpio_pin_shutdown(&sgpio_config); + rf_path_pin_shutdown(); if (board_id != BOARD_ID_RAD1O) { clock_gen_shutdown(); } delay_us_at_mhz(10000, 96); pins_setup(); sgpio_configure_pin_functions(&sgpio_config); + rf_path_pin_setup(&rf_path); #ifdef IS_PRALINE if (IS_PRALINE) { enable_3v3aux_power(); diff --git a/firmware/hackrf_usb/usb_api_board_info.c b/firmware/hackrf_usb/usb_api_board_info.c index 671cb862..a5bad4d8 100644 --- a/firmware/hackrf_usb/usb_api_board_info.c +++ b/firmware/hackrf_usb/usb_api_board_info.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -132,6 +133,7 @@ usb_request_status_t usb_vendor_request_reset( if (stage == USB_TRANSFER_STAGE_SETUP) { pins_shutdown(); sgpio_pin_shutdown(&sgpio_config); + rf_path_pin_shutdown(); clock_gen_shutdown(); #ifdef IS_H1_R9 if (IS_H1_R9) { From d534e1d019c6841d76a7d8a9c4f6f66c828ea719 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 18 May 2026 16:56:31 +0100 Subject: [PATCH 222/238] Move mixer-related bits out of pins_setup. --- firmware/common/pins.c | 3 --- firmware/hackrf_usb/hackrf_usb.c | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/firmware/common/pins.c b/firmware/common/pins.c index 97f3f413..b2d89b73 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -28,7 +28,6 @@ #include "cpld_jtag.h" #include "gpio.h" #include "leds.h" -#include "mixer.h" #include "platform_detect.h" #include "platform_gpio.h" #include "platform_scu.h" @@ -281,8 +280,6 @@ void pins_setup(void) } #endif - mixer_bus_setup(&mixer); - /* Configure external clock in */ scu_pinmux(scu->PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1); } diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index c4d32fae..b6161cc8 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -56,7 +57,6 @@ #include #endif #ifdef IS_NOT_RAD1O - #include #include #endif #ifdef IS_PRALINE @@ -436,6 +436,7 @@ int main(void) } delay_us_at_mhz(10000, 96); pins_setup(); + mixer_bus_setup(&mixer); sgpio_configure_pin_functions(&sgpio_config); rf_path_pin_setup(&rf_path); #ifdef IS_PRALINE From 0585339269c9ae4a2ae760e68c35543d4ae2acb7 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 18 May 2026 18:30:59 +0100 Subject: [PATCH 223/238] Move cpld_jtag-related bits out of pins_setup. --- firmware/common/cpld_jtag.c | 23 +++++++++++++++++++++++ firmware/common/cpld_jtag.h | 1 + firmware/common/pins.c | 18 ------------------ firmware/hackrf_usb/hackrf_usb.c | 5 ++--- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/firmware/common/cpld_jtag.c b/firmware/common/cpld_jtag.c index e6413ba4..ab998808 100644 --- a/firmware/common/cpld_jtag.c +++ b/firmware/common/cpld_jtag.c @@ -22,6 +22,7 @@ #include "cpld_jtag.h" #include "platform_detect.h" +#include "platform_gpio.h" #ifdef IS_NOT_PRALINE #include #include @@ -42,6 +43,28 @@ jtag_t jtag_cpld = { .gpio = &jtag_gpio_cpld, }; +void cpld_jtag_pin_setup(void) +{ + const platform_gpio_t* gpio = platform_gpio(); + + jtag_gpio_cpld.gpio_tck = gpio->cpld_tck; + +#ifdef IS_NOT_PRALINE + if (IS_NOT_PRALINE) { + jtag_gpio_cpld.gpio_tms = gpio->cpld_tms; + jtag_gpio_cpld.gpio_tdi = gpio->cpld_tdi; + jtag_gpio_cpld.gpio_tdo = gpio->cpld_tdo; + } +#endif + +#ifdef IS_EXPANSION_COMPATIBLE + if (IS_EXPANSION_COMPATIBLE) { + jtag_gpio_cpld.gpio_pp_tms = gpio->cpld_pp_tms; + jtag_gpio_cpld.gpio_pp_tdo = gpio->cpld_pp_tdo; + } +#endif +} + void cpld_jtag_take(jtag_t* const jtag) { const jtag_gpio_t* const gpio = jtag->gpio; diff --git a/firmware/common/cpld_jtag.h b/firmware/common/cpld_jtag.h index c1f707d4..39cfc1e7 100644 --- a/firmware/common/cpld_jtag.h +++ b/firmware/common/cpld_jtag.h @@ -45,6 +45,7 @@ typedef struct { typedef void (*refill_buffer_cb)(void); +void cpld_jtag_pin_setup(void); void cpld_jtag_take(jtag_t* const jtag); void cpld_jtag_release(jtag_t* const jtag); diff --git a/firmware/common/pins.c b/firmware/common/pins.c index b2d89b73..016b4520 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -25,7 +25,6 @@ #include -#include "cpld_jtag.h" #include "gpio.h" #include "leds.h" #include "platform_detect.h" @@ -263,23 +262,6 @@ void pins_setup(void) } #endif - jtag_gpio_cpld.gpio_tck = gpio->cpld_tck; - -#ifdef IS_NOT_PRALINE - if (IS_NOT_PRALINE) { - jtag_gpio_cpld.gpio_tms = gpio->cpld_tms; - jtag_gpio_cpld.gpio_tdi = gpio->cpld_tdi; - jtag_gpio_cpld.gpio_tdo = gpio->cpld_tdo; - } -#endif - -#ifdef IS_EXPANSION_COMPATIBLE - if (IS_EXPANSION_COMPATIBLE) { - jtag_gpio_cpld.gpio_pp_tms = gpio->cpld_pp_tms; - jtag_gpio_cpld.gpio_pp_tdo = gpio->cpld_pp_tdo; - } -#endif - /* Configure external clock in */ scu_pinmux(scu->PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1); } diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index b6161cc8..7135332e 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -67,9 +68,6 @@ #include #endif #endif -#ifdef IS_NOT_PRALINE - #include -#endif #include "usb_api_adc.h" #include "usb_api_board_info.h" @@ -436,6 +434,7 @@ int main(void) } delay_us_at_mhz(10000, 96); pins_setup(); + cpld_jtag_pin_setup(); mixer_bus_setup(&mixer); sgpio_configure_pin_functions(&sgpio_config); rf_path_pin_setup(&rf_path); From 977a9d24a625fb17709606c4772eaaa801e05c75 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 14 May 2026 16:56:23 +0100 Subject: [PATCH 224/238] Move ice40-related bits out of pins_setup. --- firmware/common/ice40_spi.c | 8 ++++++++ firmware/common/pins.c | 11 ----------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/firmware/common/ice40_spi.c b/firmware/common/ice40_spi.c index ce646fd6..c2777745 100644 --- a/firmware/common/ice40_spi.c +++ b/firmware/common/ice40_spi.c @@ -26,6 +26,7 @@ #include #include "delay.h" +#include "platform_gpio.h" #include "platform_scu.h" /* Driver instance. */ @@ -42,8 +43,15 @@ ice40_spi_driver_t ice40 = { void ice40_spi_target_init(ice40_spi_driver_t* const drv) { + const platform_gpio_t* gpio = platform_gpio(); const platform_scu_t* scu = platform_scu(); + /* Configure drivers and driver pins */ + ssp_config_ice40_fpga.gpio_select = gpio->fpga_cfg_spi_cs; + ice40.gpio_select = gpio->fpga_cfg_spi_cs; + ice40.gpio_creset = gpio->fpga_cfg_creset; + ice40.gpio_cdone = gpio->fpga_cfg_cdone; + /* Configure SSP1 Peripheral and relevant FPGA pins. */ scu_pinmux(scu->SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); scu_pinmux(scu->SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); diff --git a/firmware/common/pins.c b/firmware/common/pins.c index 016b4520..51cfec0f 100644 --- a/firmware/common/pins.c +++ b/firmware/common/pins.c @@ -33,7 +33,6 @@ #include "power.h" #ifdef IS_PRALINE #include "clock_io.h" - #include "ice40_spi.h" #endif void pins_shutdown(void) @@ -252,16 +251,6 @@ void pins_setup(void) } #endif - /* Configure drivers and driver pins */ -#ifdef IS_PRALINE - if (IS_PRALINE) { - ssp_config_ice40_fpga.gpio_select = gpio->fpga_cfg_spi_cs; - ice40.gpio_select = gpio->fpga_cfg_spi_cs; - ice40.gpio_creset = gpio->fpga_cfg_creset; - ice40.gpio_cdone = gpio->fpga_cfg_cdone; - } -#endif - /* Configure external clock in */ scu_pinmux(scu->PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1); } From 9153f3d55e2530c8e6a7fbf9ec7386ecc7e9949f Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 11 Jun 2026 20:23:35 +0100 Subject: [PATCH 225/238] Use PLL B for MCU_CLKIN on Praline. --- firmware/common/si5351c.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 136f63ea..259c062a 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -604,6 +604,9 @@ void si5351c_init(si5351c_driver_t* const drv) drv->clk[2] = mcu_clkin; drv->mcu_clkin_id = 2; } + + // Use PLL B for MCU, since we reset PLL A during sample_rate_set. + drv->clk[drv->mcu_clkin_id].pll = SI5351C_PLL_B; } #endif } From 42b7f7703dba64b34f921ec58448a06652c22fec Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 12 Jun 2026 16:00:48 +0100 Subject: [PATCH 226/238] Fix management of CLKOUT/MCU_CLK synth sharing on H1R9. --- firmware/common/si5351c.c | 47 +++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 259c062a..a455a23e 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -274,17 +274,6 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) SI5351C_OUTPUT_DISABLE); } si5351c_regs_commit(drv); - -#ifdef IS_H1_R9 - if (IS_H1_R9) { - const platform_gpio_t* gpio = platform_gpio(); - if (drv->clk[drv->clkout_id].output_enable) { - gpio_set(gpio->h1r9_clkout_en); - } else { - gpio_clear(gpio->h1r9_clkout_en); - } - } -#endif } void si5351c_set_int_mode( @@ -339,7 +328,7 @@ bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv) } } -void si5351c_clkout_enable(si5351c_driver_t* const drv, bool enable) +static void si5351c_clkout_ms_enable(si5351c_driver_t* const drv, bool enable) { drv->clk[drv->clkout_id].output_enable = enable; drv->clk[drv->clkout_id].power_down = !enable; @@ -351,12 +340,42 @@ void si5351c_clkout_enable(si5351c_driver_t* const drv, bool enable) si5351c_enable_clock_outputs(drv); } +void si5351c_clkout_enable(si5351c_driver_t* const drv, bool enable) +{ +#ifdef IS_H1_R9 + if (IS_H1_R9) { + const platform_gpio_t* gpio = platform_gpio(); + + /* CLKOUT is shared with MCU_CLK, enable MS when either on. */ + bool mcu_clkin_enabled = gpio_read(gpio->h1r9_mcu_clk_en); + bool ms_needed = enable | mcu_clkin_enabled; + si5351c_clkout_ms_enable(drv, ms_needed); + + /* Set GPIO to gate CLKOUT output downstream of MS. */ + gpio_write(gpio->h1r9_clkout_en, enable); + } +#endif +#ifdef IS_NOT_H1_R9 + if (IS_NOT_H1_R9) { + /* We have a dedicated CLKOUT multisynth. */ + si5351c_clkout_ms_enable(drv, enable); + } +#endif +} + void si5351c_mcu_clkin_enable(si5351c_driver_t* const drv, bool enable) { #ifdef IS_H1_R9 if (IS_H1_R9) { - /* MCU clock is shared with CLKOUT. */ - si5351c_clkout_enable(drv, enable); + const platform_gpio_t* gpio = platform_gpio(); + + /* MCU_CLK is shared with CLKOUT, enable MS when either on. */ + bool clkout_enabled = gpio_read(gpio->h1r9_clkout_en); + bool ms_needed = enable | clkout_enabled; + si5351c_clkout_ms_enable(drv, ms_needed); + + /* Set GPIO to gate MCU_CLK output downstream of MS. */ + gpio_write(gpio->h1r9_mcu_clk_en, enable); } #endif #ifdef IS_NOT_H1_R9 From 092d034d805b030de7b885bcc4b8d7ad151e723f Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 21 May 2026 18:55:25 +0100 Subject: [PATCH 227/238] Simplify PortaPack detection and init API. --- firmware/common/clock_gen.c | 4 ++-- firmware/common/portapack.c | 16 ++++++++-------- firmware/common/portapack.h | 8 +++----- firmware/common/ui_portapack.c | 2 +- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/firmware/common/clock_gen.c b/firmware/common/clock_gen.c index 8a75074f..0cf21ab2 100644 --- a/firmware/common/clock_gen.c +++ b/firmware/common/clock_gen.c @@ -131,7 +131,7 @@ clock_source_t activate_best_clock_source(void) #ifdef IS_EXPANSION_COMPATIBLE if (IS_EXPANSION_COMPATIBLE) { /* Ensure PortaPack reference oscillator is off while checking for external clock input. */ - if (portapack_reference_oscillator && portapack()) { + if (portapack_present()) { portapack_reference_oscillator(false); } } @@ -146,7 +146,7 @@ clock_source_t activate_best_clock_source(void) #ifdef IS_EXPANSION_COMPATIBLE if (IS_EXPANSION_COMPATIBLE) { /* Enable PortaPack reference oscillator (if present), and check for valid clock. */ - if (portapack_reference_oscillator && portapack()) { + if (portapack_present()) { portapack_reference_oscillator(true); delay_ms(18); // for oscillator to enable. if (si5351c_clkin_signal_valid(&si5351c)) { diff --git a/firmware/common/portapack.c b/firmware/common/portapack.c index 0c3cbce2..b84bf03c 100644 --- a/firmware/common/portapack.c +++ b/firmware/common/portapack.c @@ -610,23 +610,23 @@ static bool portapack_detect(void) return idcode == 0x020A50DD || idcode == 0x00025610; } -static const portapack_t portapack_instance = {}; +static bool portapack_detected = false; -static const portapack_t* portapack_pointer = NULL; - -const portapack_t* portapack(void) +bool portapack_present(void) { - return portapack_pointer; + return portapack_detected; } -void portapack_init(void) +bool portapack_init(void) { if (portapack_detect()) { portapack_if_init(); portapack_lcd_reset(); portapack_lcd_init(); - portapack_pointer = &portapack_instance; + portapack_detected = true; } else { - portapack_pointer = NULL; + portapack_detected = false; } + + return portapack_detected; } diff --git a/firmware/common/portapack.h b/firmware/common/portapack.h index fdc369b8..3926bc3f 100644 --- a/firmware/common/portapack.h +++ b/firmware/common/portapack.h @@ -63,15 +63,13 @@ typedef struct { typedef struct { } portapack_t; -void portapack_init(void); +bool portapack_init(void); -/* If the "portapack" symbol is defined, PortaPack support is compiled in */ -/* If the portapack() call returns non-NULL, a PortaPack was detected and is initialized. */ -const portapack_t* portapack(void) __attribute__((weak)); +bool portapack_present(void); void portapack_backlight(const bool on); -void portapack_reference_oscillator(const bool on) __attribute__((weak)); +void portapack_reference_oscillator(const bool on); void portapack_fill_rectangle(const ui_rect_t rect, const ui_color_t color); diff --git a/firmware/common/ui_portapack.c b/firmware/common/ui_portapack.c index 85ffa705..3387b5eb 100644 --- a/firmware/common/ui_portapack.c +++ b/firmware/common/ui_portapack.c @@ -760,7 +760,7 @@ const hackrf_ui_t portapack_hackrf_ui = { const hackrf_ui_t* portapack_hackrf_ui_init(void) { - if (portapack()) { + if (portapack_present()) { return &portapack_hackrf_ui; } else { return NULL; From 3afd5d2acd75ba030389208b3a773c95fe9a9a48 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 15 Jun 2026 11:56:10 +0100 Subject: [PATCH 228/238] Move i2c_bus_start calls out of clock_gen_init and clock_gen_shutdown. --- firmware/common/clock_gen.c | 5 ----- firmware/hackrf_usb/hackrf_usb.c | 4 ++++ 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/firmware/common/clock_gen.c b/firmware/common/clock_gen.c index 8a75074f..b3d8fd4c 100644 --- a/firmware/common/clock_gen.c +++ b/firmware/common/clock_gen.c @@ -24,8 +24,6 @@ #include #include "hackrf_ui.h" -#include "i2c_bus.h" -#include "i2c_lpc.h" #include "platform_detect.h" #include "sgpio.h" #include "si5351c.h" @@ -36,8 +34,6 @@ void clock_gen_init(void) { - i2c_bus_start(si5351c.bus, &i2c_config_fast_clock); - si5351c_init(&si5351c); si5351c_disable_all_outputs(&si5351c); si5351c_disable_oeb_pin_control(&si5351c); @@ -120,7 +116,6 @@ void clock_gen_init(void) void clock_gen_shutdown(void) { - i2c_bus_start(si5351c.bus, &i2c_config_fast_clock); si5351c_disable_all_outputs(&si5351c); si5351c_disable_oeb_pin_control(&si5351c); si5351c_power_down_all_clocks(&si5351c); diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index ce24d879..6bc00417 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include #include #include @@ -426,6 +428,8 @@ int main(void) detect_hardware_platform(); board_id_t board_id = detected_platform(); + i2c_bus_start(&i2c0, &i2c_config_fast_clock); + pins_shutdown(); sgpio_pin_shutdown(&sgpio_config); rf_path_pin_shutdown(); From d6913807a658f361456f13aab10f366808f5ccd6 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 15 Jun 2026 11:56:40 +0100 Subject: [PATCH 229/238] Specify I2C clock in kHz, and adjust for CPU clock changes. --- firmware/common/i2c_lpc.c | 8 ++++++-- firmware/common/i2c_lpc.h | 2 +- firmware/hackrf_usb/hackrf_usb.c | 3 +++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/firmware/common/i2c_lpc.c b/firmware/common/i2c_lpc.c index 9d6499fa..2c0fc5e2 100644 --- a/firmware/common/i2c_lpc.c +++ b/firmware/common/i2c_lpc.c @@ -25,6 +25,8 @@ #include #include +#include "cpu_clock.h" + /* Driver instances. */ i2c_bus_t i2c0 = { .obj = (void*) I2C0_BASE, @@ -41,7 +43,7 @@ i2c_bus_t i2c1 = { }; const i2c_lpc_config_t i2c_config_fast_clock = { - .duty_cycle_count = 255, + .clock_khz = 400, }; /* FIXME return i2c0 status from each function */ @@ -51,7 +53,9 @@ void i2c_lpc_start(i2c_bus_t* const bus, const void* const _config) const i2c_lpc_config_t* const config = _config; const uint32_t port = (uint32_t) bus->obj; - i2c_init(port, config->duty_cycle_count); + const uint16_t duty_cycle_count = + (cpu_clock_mhz * (2000 / config->clock_khz)) / 4; + i2c_init(port, duty_cycle_count); } void i2c_lpc_stop(i2c_bus_t* const bus) diff --git a/firmware/common/i2c_lpc.h b/firmware/common/i2c_lpc.h index e71cb362..2a2562ee 100644 --- a/firmware/common/i2c_lpc.h +++ b/firmware/common/i2c_lpc.h @@ -29,7 +29,7 @@ #include "i2c_bus.h" typedef struct { - const uint16_t duty_cycle_count; + const uint16_t clock_khz; } i2c_lpc_config_t; void i2c_lpc_start(i2c_bus_t* const bus, const void* const config); diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 6bc00417..813a9453 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -491,6 +491,9 @@ int main(void) #endif cpu_clock_init(); + /* Clock speed has changed, adjust I2C clock */ + i2c_bus_start(&i2c0, &i2c_config_fast_clock); + /* Wake the M0 */ ipc_halt_m0(); ipc_start_m0((uint32_t) &__ram_m0_start__); From aa76109b6ac96d7b2d2ad45cc5406eefbc435c35 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 15 Jun 2026 13:23:11 +0100 Subject: [PATCH 230/238] CI: Bump actions/checkout to v6. --- .github/workflows/build.yml | 4 ++-- .github/workflows/clang-format-check.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 02239f82..6db34ce5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -57,7 +57,7 @@ jobs: shell: '${{ matrix.sys.shell }} {0}' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Setup cmake uses: lukka/get-cmake@latest @@ -179,7 +179,7 @@ jobs: runs-on: ${{ matrix.os }}-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: submodules: true diff --git a/.github/workflows/clang-format-check.yml b/.github/workflows/clang-format-check.yml index 0bf33429..d498d609 100644 --- a/.github/workflows/clang-format-check.yml +++ b/.github/workflows/clang-format-check.yml @@ -16,7 +16,7 @@ jobs: - check: 'firmware/hackrf_usb' exclude: '' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Run clang-format-action uses: jidicula/clang-format-action@v4.6.2 with: From 73562ded31e91db216a99d2dc5383a9a6ee388a4 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 15 Jun 2026 13:59:17 +0100 Subject: [PATCH 231/238] CI: Simplify host build matrix and specify CMake generators. --- .github/workflows/build.yml | 95 ++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 38 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6db34ce5..e869824d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,44 +17,63 @@ jobs: host: strategy: matrix: - sys: - - {os: 'macos', shell: 'bash'} - - {os: 'ubuntu', shell: 'bash'} - - {os: 'windows', shell: 'pwsh'} - - {os: 'windows', shell: 'msys2'} - cmake: ['3.10.0', '3.16.0', '3.21.0', '4.0.0', 'latest'] + os: ['macos', 'ubuntu', 'windows'] + cmake: ['3.10.0', 'latest'] + compiler: ['gcc', 'msvc'] exclude: - # GitHub runners use Visual Studio 2022. Support added in CMake 3.21. - - sys: {os: 'windows', shell: 'pwsh'} + # MSVC only runs on Windows. + - os: 'macos' + compiler: 'msvc' + - os: 'ubuntu' + compiler: 'msvc' + # Only use the latest CMake on Windows. For MSVC, we can't use + # older CMake versions since the GitHub runners only have the + # latest Visual Studio release installed, and older CMake VS + # generators won't work. For GCC, we get curent CMake from the + # MSYS2 packages. + - os: 'windows' cmake: '3.10.0' - - sys: {os: 'windows', shell: 'pwsh'} - cmake: '3.16.0' - # MSYS2 always supplies the latest cmake. - - sys: {os: 'windows', shell: 'msys2'} - cmake: '3.10.0' - - sys: {os: 'windows', shell: 'msys2'} - cmake: '3.16.0' - - sys: {os: 'windows', shell: 'msys2'} - cmake: '3.21.0' - - sys: {os: 'windows', shell: 'msys2'} - cmake: '4.0.0' include: - - sys: {os: 'windows', shell: 'pwsh'} + # Shell selection + - os: 'macos' + shell: 'bash' + - os: 'ubuntu' + shell: 'bash' + - os: 'windows' + compiler: 'msvc' + shell: 'pwsh' + - os: 'windows' + compiler: 'gcc' + shell: 'msys2' + # CMake generator selection + - os: 'macos' + generator: 'Unix Makefiles' + - os: 'ubuntu' + generator: 'Unix Makefiles' + - os: 'windows' + compiler: 'msvc' + generator: 'Visual Studio 18 2026' + - os: 'windows' + compiler: 'gcc' + generator: 'MSYS Makefiles' + - os: 'windows' + compiler: 'msvc' cmake_args: >- -DPKG_CONFIG_EXECUTABLE=C:/vcpkg/installed/x64-windows/tools/pkgconf/pkgconf.exe -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake --install-prefix=$env:GITHUB_WORKSPACE/install - - sys: {os: 'windows', shell: 'msys2'} + - os: 'windows' + compiler: 'gcc' cmake_args: >- --install-prefix=/usr/local # Don't cancel all builds when one fails fail-fast: false - runs-on: ${{ matrix.sys.os }}-latest + runs-on: ${{ matrix.os }}-latest defaults: run: - shell: '${{ matrix.sys.shell }} {0}' + shell: '${{ matrix.shell }} {0}' steps: - uses: actions/checkout@v6 @@ -63,24 +82,24 @@ jobs: uses: lukka/get-cmake@latest with: cmakeVersion: ${{ matrix.cmake }} - if: matrix.sys.shell != 'msys2' + if: matrix.shell != 'msys2' - name: Install dependencies (macOS) run: brew install fftw - if: matrix.sys.os == 'macos' + if: matrix.os == 'macos' - name: Install dependencies (Ubuntu) run: | sudo apt update sudo apt install libfftw3-dev libusb-1.0-0-dev - if: matrix.sys.os == 'ubuntu' + if: matrix.os == 'ubuntu' - name: Install dependencies (Windows) run: vcpkg install --triplet=x64-windows libusb fftw3 pthreads pkgconf - if: matrix.sys.os == 'windows' && matrix.sys.shell != 'msys2' + if: matrix.os == 'windows' && matrix.shell != 'msys2' - name: Setup MSYS (Windows) - if: matrix.sys.os == 'windows' && matrix.sys.shell == 'msys2' + if: matrix.os == 'windows' && matrix.shell == 'msys2' uses: msys2/setup-msys2@v2 with: msystem: UCRT64 @@ -98,7 +117,7 @@ jobs: run: | cmake -E make_directory host/build cd host/build - cmake .. -DCMAKE_BUILD_TYPE=Release ${{matrix.cmake_args}} + cmake .. -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE=Release ${{matrix.cmake_args}} cmake --build . --config Release # Build libhackrf ONLY @@ -107,22 +126,22 @@ jobs: run: | cmake -E make_directory host/libhackrf/build cd host/libhackrf/build - cmake .. -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_args }} + cmake .. -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_args }} cmake --build . --config Release - name: Install (libhackrf) run: | sudo cmake --install host/libhackrf/build --config Release - if: matrix.sys.os != 'windows' && matrix.cmake != '3.10.0' + if: matrix.os != 'windows' && matrix.cmake != '3.10.0' - name: Install (libhackrf, CMake 3.10) run: | sudo cmake --build host/libhackrf/build --target install --config Release - if: matrix.sys.os != 'windows' && matrix.cmake == '3.10.0' + if: matrix.os != 'windows' && matrix.cmake == '3.10.0' - name: Install (libhackrf, Windows) run: cmake --install host/libhackrf/build --config Release - if: matrix.sys.os == 'windows' + if: matrix.os == 'windows' # Build hackrf-tools ONLY @@ -130,22 +149,22 @@ jobs: run: | cmake -E make_directory host/hackrf-tools/build cd host/hackrf-tools/build - cmake .. -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_args }} + cmake .. -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_args }} cmake --build . --config Release - name: Install (hackrf-tools) run: | sudo cmake --install host/hackrf-tools/build --config Release - if: matrix.sys.os != 'windows' && matrix.cmake != '3.10.0' + if: matrix.os != 'windows' && matrix.cmake != '3.10.0' - name: Install (hackrf-tools, CMake 3.10) run: | sudo cmake --build host/hackrf-tools/build --target install --config Release - if: matrix.sys.os != 'windows' && matrix.cmake == '3.10.0' + if: matrix.os != 'windows' && matrix.cmake == '3.10.0' - name: Install (hackrf-tools, Windows) run: cmake --install host/hackrf-tools/build --config Release - if: matrix.sys.os == 'windows' + if: matrix.os == 'windows' # Publish the contents of install/bin (which should be the combination libhackrf and host-tools) for Windows - name: Publish Artifacts (Windows) @@ -153,7 +172,7 @@ jobs: with: name: hackrf-tools-windows path: ${{github.workspace}}/install/bin - if: matrix.sys.os == 'windows' && matrix.cmake == 'latest' && matrix.sys.shell == 'pwsh' + if: matrix.os == 'windows' && matrix.cmake == 'latest' && matrix.shell == 'pwsh' firmware: strategy: From 3e274a881d51504189bafebe0f2ef5bf38c79de1 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 15 Jun 2026 15:07:06 +0100 Subject: [PATCH 232/238] CI: Simplify install steps. --- .github/workflows/build.yml | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e869824d..64aa1bee 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -66,6 +66,19 @@ jobs: compiler: 'gcc' cmake_args: >- --install-prefix=/usr/local + # CMake 3.10 uses --build with --target install + - cmake: '3.10.0' + install_cmd: --build + install_args: --target install + # Later versions just use --install + - cmake: 'latest' + install_cmd: --install + # We need sudo on MacOS and Ubuntu only + - os: macos + sudo: sudo + - os: ubuntu + sudo: sudo + # Don't cancel all builds when one fails fail-fast: false @@ -131,17 +144,7 @@ jobs: - name: Install (libhackrf) run: | - sudo cmake --install host/libhackrf/build --config Release - if: matrix.os != 'windows' && matrix.cmake != '3.10.0' - - - name: Install (libhackrf, CMake 3.10) - run: | - sudo cmake --build host/libhackrf/build --target install --config Release - if: matrix.os != 'windows' && matrix.cmake == '3.10.0' - - - name: Install (libhackrf, Windows) - run: cmake --install host/libhackrf/build --config Release - if: matrix.os == 'windows' + ${{ matrix.sudo }} cmake ${{ matrix.install_cmd }} host/libhackrf/build ${{ matrix.install_args }} --config Release # Build hackrf-tools ONLY @@ -154,17 +157,7 @@ jobs: - name: Install (hackrf-tools) run: | - sudo cmake --install host/hackrf-tools/build --config Release - if: matrix.os != 'windows' && matrix.cmake != '3.10.0' - - - name: Install (hackrf-tools, CMake 3.10) - run: | - sudo cmake --build host/hackrf-tools/build --target install --config Release - if: matrix.os != 'windows' && matrix.cmake == '3.10.0' - - - name: Install (hackrf-tools, Windows) - run: cmake --install host/hackrf-tools/build --config Release - if: matrix.os == 'windows' + ${{ matrix.sudo }} cmake ${{ matrix.install_cmd }} host/hackrf-tools/build ${{ matrix.install_args }} # Publish the contents of install/bin (which should be the combination libhackrf and host-tools) for Windows - name: Publish Artifacts (Windows) From eb8bc546a84b2774f1131bfb9b8d21b742b8d1e0 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 15 Jun 2026 15:32:28 +0100 Subject: [PATCH 233/238] CI: Build with more CMake and Visual Studio versions. --- .github/workflows/build.yml | 41 +++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 64aa1bee..21593d8a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: os: ['macos', 'ubuntu', 'windows'] - cmake: ['3.10.0', 'latest'] + cmake: ['3.10.0', '3.21.7', '4.2.6', 'latest'] compiler: ['gcc', 'msvc'] exclude: # MSVC only runs on Windows. @@ -26,13 +26,14 @@ jobs: compiler: 'msvc' - os: 'ubuntu' compiler: 'msvc' - # Only use the latest CMake on Windows. For MSVC, we can't use - # older CMake versions since the GitHub runners only have the - # latest Visual Studio release installed, and older CMake VS - # generators won't work. For GCC, we get curent CMake from the - # MSYS2 packages. + # We can't use the oldest CMake versions on Windows. - os: 'windows' cmake: '3.10.0' + # The in-between CMake versions aren't so intersting with GCC. + - compiler: 'gcc' + cmake: '3.21.7' + - compiler: 'gcc' + cmake: '4.2.6' include: # Shell selection - os: 'macos' @@ -45,17 +46,31 @@ jobs: - os: 'windows' compiler: 'gcc' shell: 'msys2' + # MSVC version selection + - cmake: '3.21.7' + msvc: '17.14' + - cmake: '4.2.6' + msvc: 'latest' + - cmake: 'latest' + msvc: 'latest' # CMake generator selection - os: 'macos' generator: 'Unix Makefiles' - os: 'ubuntu' generator: 'Unix Makefiles' - - os: 'windows' - compiler: 'msvc' + - compiler: 'msvc' + cmake: '3.21.7' + generator: 'Visual Studio 17 2022' + - compiler: 'msvc' + cmake: '4.2.6' + generator: 'Visual Studio 18 2026' + - compiler: 'msvc' + cmake: 'latest' generator: 'Visual Studio 18 2026' - os: 'windows' compiler: 'gcc' generator: 'MSYS Makefiles' + # Additional CMake arguments - os: 'windows' compiler: 'msvc' cmake_args: >- @@ -71,6 +86,10 @@ jobs: install_cmd: --build install_args: --target install # Later versions just use --install + - cmake: '3.21.7' + install_cmd: --install + - cmake: '4.2.6' + install_cmd: --install - cmake: 'latest' install_cmd: --install # We need sudo on MacOS and Ubuntu only @@ -97,6 +116,12 @@ jobs: cmakeVersion: ${{ matrix.cmake }} if: matrix.shell != 'msys2' + - name: Install MSVC (Windows) + uses: k3DW/setup-msvc@v1 + with: + vs-version: ${{ matrix.msvc }} + if: matrix.compiler == 'msvc' && matrix.msvc != 'latest' + - name: Install dependencies (macOS) run: brew install fftw if: matrix.os == 'macos' From 74c3b730fa95163bcd4a3dbff9f3b2d60e174d22 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Mon, 29 Jun 2026 19:28:50 +0100 Subject: [PATCH 234/238] Add 1.63 fixed point type. --- firmware/common/fixed_point.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/firmware/common/fixed_point.h b/firmware/common/fixed_point.h index b6908797..974e34d2 100644 --- a/firmware/common/fixed_point.h +++ b/firmware/common/fixed_point.h @@ -54,3 +54,20 @@ typedef uint64_t fp_28_36_t; #define SR_FP_MHZ(mhz) (mhz##ULL * SR_FP_ONE_MHZ) #define SR_FP_KHZ(khz) (khz##ULL * SR_FP_ONE_KHZ) #define SR_FP_HZ(hz) (hz##ULL * SR_FP_ONE_HZ) + +/* 1.63 fixed point */ +typedef uint64_t fp_1_63_t; + +#define FRAC_ONE (1ULL << 63) + +/* one hundredth in 1.63 fixed point */ +#define FRAC_ONE_PERCENT (FRAC_ONE / (100ULL)) + +/* one thousandth in 1.63 fixed point */ +#define FRAC_ONE_PERMILLE (FRAC_ONE / (1000ULL)) + +/* one millionth in 1.63 fixed point */ +#define FRAC_ONE_PPM (FRAC_ONE / (1000000ULL)) + +/* one billionth in 1.63 fixed point */ +#define FRAC_ONE_PPB (FRAC_ONE / (1000000000ULL)) From dda161cb1f588bc7bc6a1888958b2d6f014f4f49 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 30 Jun 2026 01:56:12 +0100 Subject: [PATCH 235/238] Add multiply & divide implementations for 128-bit unsigned integers. --- firmware/common/u128.c | 88 ++++++++++++++++++++++++++++++++++++ firmware/common/u128.h | 32 +++++++++++++ firmware/hackrf-common.cmake | 1 + 3 files changed, 121 insertions(+) create mode 100644 firmware/common/u128.c create mode 100644 firmware/common/u128.h diff --git a/firmware/common/u128.c b/firmware/common/u128.c new file mode 100644 index 00000000..3543f332 --- /dev/null +++ b/firmware/common/u128.c @@ -0,0 +1,88 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "u128.h" + +/* From https://stackoverflow.com/a/58381061 */ + +u128 u128_multiply(uint64_t lhs, uint64_t rhs) +{ + uint64_t lo_lo = (lhs & 0xFFFFFFFF) * (rhs & 0xFFFFFFFF); + uint64_t hi_lo = (lhs >> 32) * (rhs & 0xFFFFFFFF); + uint64_t lo_hi = (lhs & 0xFFFFFFFF) * (rhs >> 32); + uint64_t hi_hi = (lhs >> 32) * (rhs >> 32); + uint64_t cross = ((lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi); + return (u128){ + .hi = ((hi_lo >> 32) + (cross >> 32) + hi_hi), + .lo = ((cross << 32) | (lo_lo & 0xFFFFFFFF)), + }; +} + +/* From https://stackoverflow.com/a/70052545 */ + +/* clang-format off */ + +#define SUBCcc(a,b,cy,t0,t1,t2) \ + (t0=(b)+cy, t1=(a), cy=t0= divisor + rem.lo = tmp.lo; + rem.hi = tmp.hi; + quot.lo |= 1; + } + } + + return quot; +} diff --git a/firmware/common/u128.h b/firmware/common/u128.h new file mode 100644 index 00000000..c51dc5f5 --- /dev/null +++ b/firmware/common/u128.h @@ -0,0 +1,32 @@ +/* + * Copyright 2026 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include + +typedef struct { + uint64_t hi; + uint64_t lo; +} u128; + +u128 u128_multiply(uint64_t a, uint64_t b); +u128 u128_divide(u128 dvnd, u128 dvsr); diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index dfc67d9e..8f6698da 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -203,6 +203,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/adc.c ${PATH_HACKRF_FIRMWARE_COMMON}/da7219.c ${PATH_HACKRF_FIRMWARE_COMMON}/max283x.c + ${PATH_HACKRF_FIRMWARE_COMMON}/u128.c ) if(BOARD STREQUAL "RAD1O") From 8bfbd716da361e49bcaefb960b12ea837a2dffb8 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 30 Jun 2026 02:17:27 +0100 Subject: [PATCH 236/238] Add RADIO_CLOCK_CORRECTION register, bump USB API to 1.13. --- firmware/common/radio.c | 96 ++++++++++++++++++++++++++-- firmware/common/radio.h | 18 ++++-- firmware/hackrf_usb/usb_descriptor.c | 2 +- host/hackrf-tools/src/hackrf_debug.c | 2 +- 4 files changed, 103 insertions(+), 15 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index f8b2e514..6bf89784 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -34,6 +34,7 @@ #include "rf_path.h" #include "transceiver_mode.h" #include "tuning.h" +#include "u128.h" #ifdef IS_PRALINE #include "fpga.h" #include "tune_config.h" @@ -132,6 +133,75 @@ static uint32_t radio_update_direction(radio_t* const radio, uint64_t* bank) return (1 << RADIO_OPMODE); } +/* Apply correction to a true frequency to get an adjusted frequency. */ +static uint64_t adjust(uint64_t freq, uint64_t correction) +{ + /* skip if we can */ + if (correction == FRAC_ONE) { + return freq; + } + + u128 product = u128_multiply(freq, correction); + + /* product >> 63 */ + return (product.hi << 1) | (product.lo >> 63); +} + +/* Given an adjusted frequency and correction, return the true frequency. */ +static uint64_t unadjust(uint64_t freq, uint64_t correction) +{ + /* skip if we can */ + if (correction == FRAC_ONE) { + return freq; + } + + /* (1 << (63 + 63)) */ + u128 numerator = (u128){ + .hi = 1ULL << 62, + .lo = 0, + }; + u128 denominator = (u128){ + .hi = 0, + .lo = correction, + }; + u128 reciprocal = u128_divide(numerator, denominator); + return adjust(freq, reciprocal.lo); +} + +static uint64_t restrict_correction(uint64_t requested_correction) +{ + /* Correction should be in the range 0.99 to 1.01 */ + const uint64_t min_correction = FRAC_ONE - FRAC_ONE_PERCENT; + const uint64_t max_correction = FRAC_ONE + FRAC_ONE_PERCENT; + if (requested_correction >= min_correction && + requested_correction <= max_correction) { + return requested_correction; + } else { + return FRAC_ONE; + } +} + +static uint64_t set_lo(uint64_t freq_lo, uint64_t correction, bool apply) +{ + fp_40_24_t corrected_lo = adjust(freq_lo, correction); + fp_40_24_t achieved_lo = mixer_set_frequency(&mixer, corrected_lo, apply); + return unadjust(achieved_lo, correction); +} + +static uint64_t set_if(uint64_t freq_if, uint64_t correction, bool apply) +{ + fp_40_24_t corrected_if = adjust(freq_if, correction); + fp_40_24_t achieved_if = max283x_set_frequency(&max283x, corrected_if, apply); + return unadjust(achieved_if, correction); +} + +static uint64_t set_afe_rate(uint64_t afe_rate, uint64_t correction, bool apply) +{ + fp_28_36_t corrected_rate = adjust(afe_rate, correction); + fp_28_36_t achieved_rate = sample_rate_set(corrected_rate, apply); + return unadjust(achieved_rate, correction); +} + #define ABSOLUTE_MIN_AFE_RATE SR_FP_KHZ(200) #define ABSOLUTE_MAX_AFE_RATE SR_FP_KHZ(43600) #define MAX_SUPPORTED_AFE_RATE SR_FP_KHZ(40000) @@ -183,6 +253,9 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank) bool new_n = false; const uint64_t requested_rate = bank[RADIO_SAMPLE_RATE]; + const uint64_t requested_correction = bank[RADIO_CLOCK_CORRECTION]; + + uint64_t correction = restrict_correction(requested_correction); if (requested_rate != RADIO_UNSET) { rate = MIN(requested_rate, MAX_MCU_RATE); @@ -236,7 +309,7 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank) new_n = (n != previous_n); afe_rate = rate << n; - afe_rate = sample_rate_set(afe_rate, false); + afe_rate = set_afe_rate(afe_rate, correction, false); previous_rate = radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE]; if ((previous_n == RADIO_UNSET) || previous_rate == RADIO_UNSET) { previous_afe_rate = RADIO_UNSET; @@ -245,7 +318,7 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank) } new_afe_rate = (afe_rate != previous_afe_rate); if (new_afe_rate) { - afe_rate = sample_rate_set(afe_rate, true); + afe_rate = set_afe_rate(afe_rate, correction, true); } rate = afe_rate >> n; @@ -373,6 +446,7 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) #ifdef IS_PRALINE const uint64_t requested_rotation = bank[RADIO_ROTATION]; #endif + const uint64_t requested_correction = bank[RADIO_CLOCK_CORRECTION]; const uint64_t applied_rf = radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF]; const uint64_t applied_if = radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF]; @@ -381,6 +455,8 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) radio->config[RADIO_BANK_APPLIED][RADIO_IMAGE_REJECT]; const uint64_t applied_rotation = radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION]; + const uint64_t applied_correction = + radio->config[RADIO_BANK_APPLIED][RADIO_CLOCK_CORRECTION]; uint64_t freq_rf = applied_rf; uint64_t analog_rf = applied_rf; @@ -388,6 +464,7 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) uint64_t freq_lo = applied_lo; uint64_t img_reject = applied_img_reject; uint64_t rotation = applied_rotation; + uint64_t correction = applied_correction; uint64_t opmode = bank[RADIO_OPMODE]; if (opmode == RADIO_UNSET) { @@ -405,11 +482,12 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) img_reject = RF_PATH_FILTER_BYPASS; } } + correction = restrict_correction(requested_correction); if (requested_if != RADIO_UNSET) { - freq_if = max283x_set_frequency(&max283x, requested_if, false); + freq_if = set_if(requested_if, correction, false); } if (requested_lo != RADIO_UNSET) { - freq_lo = mixer_set_frequency(&mixer, freq_lo, false); + freq_lo = set_lo(requested_lo, correction, false); } #ifdef IS_PRALINE if (IS_PRALINE) { @@ -491,7 +569,7 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) freq_lo = RADIO_UNSET; } if (freq_lo != RADIO_UNSET) { - freq_lo = mixer_set_frequency(&mixer, freq_lo, false); + freq_lo = set_lo(freq_lo, correction, false); } } @@ -513,12 +591,12 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) /* Apply settings. */ if ((freq_if != applied_if) && (freq_if != RADIO_UNSET)) { - freq_if = max283x_set_frequency(&max283x, freq_if, true); + freq_if = set_if(freq_if, correction, true); radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF] = freq_if; changed |= (1 << RADIO_FREQUENCY_IF); } if ((freq_lo != applied_lo) && (freq_lo != RADIO_UNSET)) { - freq_lo = mixer_set_frequency(&mixer, freq_lo, true); + freq_lo = set_lo(freq_lo, correction, true); radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_LO] = freq_lo; changed |= (1 << RADIO_FREQUENCY_LO); } @@ -561,6 +639,10 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank) radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF] = freq_rf; changed |= (1 << RADIO_FREQUENCY_RF); } + if ((correction != applied_correction) && (correction != RADIO_UNSET)) { + radio->config[RADIO_BANK_APPLIED][RADIO_CLOCK_CORRECTION] = correction; + changed |= (1 << RADIO_CLOCK_CORRECTION); + } return changed; } diff --git a/firmware/common/radio.h b/firmware/common/radio.h index 821c7fea..84b18c6e 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -165,17 +165,23 @@ typedef enum { * DC block enable of type bool. */ RADIO_DC_BLOCK = 22, + /** + * Correction factor for radio reference clock, of type fp_1_63_t. + */ + RADIO_CLOCK_CORRECTION = 23, } radio_register_t; -#define RADIO_NUM_REGS (23) +#define RADIO_NUM_REGS (24) #define RADIO_UNSET (0xffffffffffffffff) /* register groups for bitfield convenience */ -#define RADIO_REG_GROUP_RATE \ - ((1 << RADIO_SAMPLE_RATE) | (1 << RADIO_RESAMPLE_TX) | (1 << RADIO_RESAMPLE_RX)) -#define RADIO_REG_GROUP_FREQ \ - ((1 << RADIO_FREQUENCY_RF) | (1 << RADIO_FREQUENCY_IF) | \ - (1 << RADIO_FREQUENCY_LO) | (1 << RADIO_IMAGE_REJECT) | (1 << RADIO_ROTATION)) +#define RADIO_REG_GROUP_RATE \ + ((1 << RADIO_SAMPLE_RATE) | (1 << RADIO_RESAMPLE_TX) | \ + (1 << RADIO_RESAMPLE_RX) | (1 << RADIO_CLOCK_CORRECTION)) +#define RADIO_REG_GROUP_FREQ \ + ((1 << RADIO_FREQUENCY_RF) | (1 << RADIO_FREQUENCY_IF) | \ + (1 << RADIO_FREQUENCY_LO) | (1 << RADIO_IMAGE_REJECT) | (1 << RADIO_ROTATION) | \ + (1 << RADIO_CLOCK_CORRECTION)) #define RADIO_REG_GROUP_BW \ ((1 << RADIO_BB_BANDWIDTH_TX) | (1 << RADIO_BB_BANDWIDTH_RX) | \ (1 << RADIO_XCVR_TX_LPF) | (1 << RADIO_XCVR_RX_LPF) | \ diff --git a/firmware/hackrf_usb/usb_descriptor.c b/firmware/hackrf_usb/usb_descriptor.c index 005babb3..dde22e6e 100644 --- a/firmware/hackrf_usb/usb_descriptor.c +++ b/firmware/hackrf_usb/usb_descriptor.c @@ -28,7 +28,7 @@ #define USB_VENDOR_ID (0x1D50) -#define USB_API_VERSION (0x0112) +#define USB_API_VERSION (0x0113) #define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF) diff --git a/host/hackrf-tools/src/hackrf_debug.c b/host/hackrf-tools/src/hackrf_debug.c index 52ede9cb..5f8785b5 100644 --- a/host/hackrf-tools/src/hackrf_debug.c +++ b/host/hackrf-tools/src/hackrf_debug.c @@ -501,7 +501,7 @@ int radio_read_register( return result; } -#define RADIO_NUM_REGS (23) +#define RADIO_NUM_REGS (24) int radio_read_registers(hackrf_device* device, const uint8_t bank) { From 2b7ba8d7ab5d19b1df0eb31ab57cbc238875861c Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Thu, 16 Jul 2026 12:31:31 +0200 Subject: [PATCH 237/238] radio: rename RADIO_BANK_ACTIVE to RADIO_BANK_REQUESTED --- firmware/common/radio.c | 12 ++++---- firmware/common/radio.h | 8 +++--- firmware/hackrf_usb/usb_api_sweep.c | 4 +-- firmware/hackrf_usb/usb_api_transceiver.c | 34 +++++++++++------------ 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index 6bf89784..36f65cad 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -54,7 +54,7 @@ void radio_init(radio_t* const radio) } } radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF; - radio->config[RADIO_BANK_ACTIVE][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF; + radio->config[RADIO_BANK_REQUESTED][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF; radio->config[RADIO_BANK_IDLE][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF; radio->config[RADIO_BANK_RX][RADIO_OPMODE] = TRANSCEIVER_MODE_RX; radio->config[RADIO_BANK_TX][RADIO_OPMODE] = TRANSCEIVER_MODE_TX; @@ -78,7 +78,7 @@ radio_error_t radio_reg_write( } switch (bank) { - case RADIO_BANK_ACTIVE: + case RADIO_BANK_REQUESTED: mark_dirty(radio, reg); /* fall through */ case RADIO_BANK_IDLE: @@ -937,7 +937,7 @@ bool radio_update(radio_t* const radio) return false; } radio->regs_dirty = 0; - memcpy(&tmp_bank[0], &(radio->config[RADIO_BANK_ACTIVE][0]), sizeof(tmp_bank)); + memcpy(&tmp_bank[0], &(radio->config[RADIO_BANK_REQUESTED][0]), sizeof(tmp_bank)); nvic_enable_irq(NVIC_USB0_IRQ); if ((dirty & RADIO_REG_GROUP_RATE) || @@ -998,14 +998,14 @@ void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode) nvic_disable_irq(NVIC_USB0_IRQ); for (uint8_t reg = 0; reg < RADIO_NUM_REGS; reg++) { value = radio->config[source_bank][reg]; - previous = radio->config[RADIO_BANK_ACTIVE][reg]; + previous = radio->config[RADIO_BANK_REQUESTED][reg]; if ((value != RADIO_UNSET) && (value != previous)) { - radio->config[RADIO_BANK_ACTIVE][reg] = value; + radio->config[RADIO_BANK_REQUESTED][reg] = value; mark_dirty(radio, reg); } } - radio->config[RADIO_BANK_ACTIVE][RADIO_OPMODE] = mode; + radio->config[RADIO_BANK_REQUESTED][RADIO_OPMODE] = mode; mark_dirty(radio, RADIO_OPMODE); nvic_enable_irq(NVIC_USB0_IRQ); radio_update(radio); diff --git a/firmware/common/radio.h b/firmware/common/radio.h index 84b18c6e..8e12471a 100644 --- a/firmware/common/radio.h +++ b/firmware/common/radio.h @@ -191,7 +191,7 @@ typedef enum { (1 << RADIO_GAIN_RX_IF) | (1 << RADIO_GAIN_RX_BB)) /** - * Register bank RADIO_BANK_ACTIVE stores the active configuration. Active + * Register bank RADIO_BANK_REQUESTED stores the active configuration. Active * register settings are copied to the applied register when applied. * * The other three banks store settings that will be applied when switching to @@ -202,7 +202,7 @@ typedef enum { */ typedef enum { RADIO_BANK_APPLIED = 0, - RADIO_BANK_ACTIVE = 1, + RADIO_BANK_REQUESTED = 1, RADIO_BANK_IDLE = 2, RADIO_BANK_RX = 3, RADIO_BANK_TX = 4, @@ -237,7 +237,7 @@ typedef struct { void radio_init(radio_t* const radio); /** - * Write to one or more registers. Writes to RADIO_BANK_ACTIVE are applied at + * Write to one or more registers. Writes to RADIO_BANK_REQUESTED are applied at * the next radio_update(). Writes to RADIO_BANK_APPLIED are not supported. */ radio_error_t radio_reg_write( @@ -255,7 +255,7 @@ uint64_t radio_reg_read( const radio_register_t reg); /** - * Apply changes requested in RADIO_BANK_ACTIVE. + * Apply changes requested in RADIO_BANK_REQUESTED. * Return true if any changes were applied. */ bool radio_update(radio_t* const radio); diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index 0da2cf6e..1bea5dd2 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -132,7 +132,7 @@ usb_request_status_t usb_vendor_request_init_sweep( radio_reg_write( &radio, - RADIO_BANK_ACTIVE, + RADIO_BANK_REQUESTED, RADIO_FREQUENCY_RF, (sweep_freq + offset) * FP_ONE_HZ); usb_transfer_schedule_ack(endpoint->in); @@ -263,7 +263,7 @@ void sweep_mode(uint32_t seq) nvic_disable_irq(NVIC_USB0_IRQ); radio_reg_write( &radio, - RADIO_BANK_ACTIVE, + RADIO_BANK_REQUESTED, RADIO_FREQUENCY_RF, (sweep_freq + offset) * FP_ONE_HZ); nvic_enable_irq(NVIC_USB0_IRQ); diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index dbbbf661..e72a408b 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -94,12 +94,12 @@ usb_request_status_t usb_vendor_request_set_baseband_filter_bandwidth( (endpoint->setup.index << 16) | endpoint->setup.value; radio_reg_write( &radio, - RADIO_BANK_ACTIVE, + RADIO_BANK_REQUESTED, RADIO_BB_BANDWIDTH_TX, bandwidth); radio_reg_write( &radio, - RADIO_BANK_ACTIVE, + RADIO_BANK_REQUESTED, RADIO_BB_BANDWIDTH_RX, bandwidth); usb_transfer_schedule_ack(endpoint->in); @@ -123,22 +123,22 @@ usb_request_status_t usb_vendor_request_set_freq( set_freq_params.freq_mhz * 1000000ULL + set_freq_params.freq_hz; radio_reg_write( &radio, - RADIO_BANK_ACTIVE, + RADIO_BANK_REQUESTED, RADIO_FREQUENCY_RF, freq * FP_ONE_HZ); radio_reg_write( &radio, - RADIO_BANK_ACTIVE, + RADIO_BANK_REQUESTED, RADIO_FREQUENCY_IF, RADIO_UNSET); radio_reg_write( &radio, - RADIO_BANK_ACTIVE, + RADIO_BANK_REQUESTED, RADIO_FREQUENCY_LO, RADIO_UNSET); radio_reg_write( &radio, - RADIO_BANK_ACTIVE, + RADIO_BANK_REQUESTED, RADIO_IMAGE_REJECT, RADIO_UNSET); usb_transfer_schedule_ack(endpoint->in); @@ -160,17 +160,17 @@ usb_request_status_t usb_vendor_request_set_freq_explicit( } else if (stage == USB_TRANSFER_STAGE_DATA) { radio_reg_write( &radio, - RADIO_BANK_ACTIVE, + RADIO_BANK_REQUESTED, RADIO_FREQUENCY_IF, explicit_params.if_freq_hz * FP_ONE_HZ); radio_reg_write( &radio, - RADIO_BANK_ACTIVE, + RADIO_BANK_REQUESTED, RADIO_FREQUENCY_LO, explicit_params.lo_freq_hz * FP_ONE_HZ); radio_reg_write( &radio, - RADIO_BANK_ACTIVE, + RADIO_BANK_REQUESTED, RADIO_IMAGE_REJECT, explicit_params.path); usb_transfer_schedule_ack(endpoint->in); @@ -215,7 +215,7 @@ usb_request_status_t usb_vendor_request_set_sample_rate_frac( uint32_t numerator = set_sample_r_params.freq_hz; uint32_t denominator = set_sample_r_params.divider; uint64_t value = round_sample_rate(numerator, denominator); - radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_SAMPLE_RATE, value); + radio_reg_write(&radio, RADIO_BANK_REQUESTED, RADIO_SAMPLE_RATE, value); usb_transfer_schedule_ack(endpoint->in); } return USB_REQUEST_STATUS_OK; @@ -228,12 +228,12 @@ usb_request_status_t usb_vendor_request_set_amp_enable( if (stage == USB_TRANSFER_STAGE_SETUP) { radio_reg_write( &radio, - RADIO_BANK_ACTIVE, + RADIO_BANK_REQUESTED, RADIO_GAIN_TX_RF, endpoint->setup.value); radio_reg_write( &radio, - RADIO_BANK_ACTIVE, + RADIO_BANK_REQUESTED, RADIO_GAIN_RX_RF, endpoint->setup.value); usb_transfer_schedule_ack(endpoint->in); @@ -247,7 +247,7 @@ usb_request_status_t usb_vendor_request_set_lna_gain( { if (stage == USB_TRANSFER_STAGE_SETUP) { uint8_t gain = endpoint->setup.index; - radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_GAIN_RX_IF, gain); + radio_reg_write(&radio, RADIO_BANK_REQUESTED, RADIO_GAIN_RX_IF, gain); endpoint->buffer[0] = RADIO_OK; usb_transfer_schedule_block( endpoint->in, @@ -266,7 +266,7 @@ usb_request_status_t usb_vendor_request_set_vga_gain( { if (stage == USB_TRANSFER_STAGE_SETUP) { uint8_t gain = endpoint->setup.index; - radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_GAIN_RX_BB, gain); + radio_reg_write(&radio, RADIO_BANK_REQUESTED, RADIO_GAIN_RX_BB, gain); endpoint->buffer[0] = RADIO_OK; usb_transfer_schedule_block( endpoint->in, @@ -285,7 +285,7 @@ usb_request_status_t usb_vendor_request_set_txvga_gain( { if (stage == USB_TRANSFER_STAGE_SETUP) { uint8_t gain = endpoint->setup.index; - radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_GAIN_TX_IF, gain); + radio_reg_write(&radio, RADIO_BANK_REQUESTED, RADIO_GAIN_TX_IF, gain); endpoint->buffer[0] = RADIO_OK; usb_transfer_schedule_block( endpoint->in, @@ -315,7 +315,7 @@ usb_request_status_t usb_vendor_request_set_antenna_enable( if (stage == USB_TRANSFER_STAGE_SETUP) { radio_reg_write( &radio, - RADIO_BANK_ACTIVE, + RADIO_BANK_REQUESTED, RADIO_BIAS_TEE, endpoint->setup.value); usb_transfer_schedule_ack(endpoint->in); @@ -427,7 +427,7 @@ usb_request_status_t usb_vendor_request_set_hw_sync_mode( if (stage == USB_TRANSFER_STAGE_SETUP) { radio_reg_write( &radio, - RADIO_BANK_ACTIVE, + RADIO_BANK_REQUESTED, RADIO_TRIGGER, endpoint->setup.value); usb_transfer_schedule_ack(endpoint->in); From 6259086c9625ebef760f51305aae9a364a465a9a Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Tue, 21 Jul 2026 11:44:26 +0200 Subject: [PATCH 238/238] libhackrf: set a 500ms timeout for changing fpga bitstream --- host/libhackrf/src/hackrf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 7bafd5f3..4018ac63 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -57,6 +57,7 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI #define DEFAULT_REQUEST_TIMEOUT 100 #define CPLD_WRITE_TIMEOUT 10000 #define SPIFLASH_WRITE_TIMEOUT 50000 // W25Q32JV max chip erase time +#define FPGA_BITSTREAM_TIMEOUT 500 // TODO: Factor this into a shared #include so that firmware can use // the same values. @@ -3496,7 +3497,7 @@ int ADDCALL hackrf_set_fpga_bitstream(hackrf_device* device, const uint8_t index 0, NULL, 0, - DEFAULT_REQUEST_TIMEOUT); + FPGA_BITSTREAM_TIMEOUT); if (result != 0) { last_libusb_error = result;

    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/rf901EkpCLQNPWtrLnbDGTmUxmnue9PPPy36tabSu4XHUwMDFiW1tva1vWbc907L5vzrZeh9dvLH9iey40kejviTf1e9GdwyBcdTAwMThP3r55XHUwMDEz9zB63uihl+VYI8tcciZw3z/wd632X/R/aLH7YV98Izv9XHRvKlx1MDAxM1x1MDAwZqzGYa/eXHJmR1HX6KbHyfhWLzDdgWPFTbdwnVFqaMFcdTAwMThHUkmBqVq03kGrYNRQhFwiTTFnQiZaZ3Y/XHUwMDE4hndIbUiMKfTXRGNNXHUwMDE3d1xmLXswXGbgXHUwMDE2TLhBJEaUaso4hS+Le1x1MDAxZSb0toZcdTAwMTZXJoHvXVnbnuP54az/wFb4Xzznrtm7XHUwMDFh+N7U7cf3mLyvLi7iey5sx+lcdTAwMDR30ciwyLCgW0vjn81nT5auXHUwMDE39YJcdTAwMDdcdTAwMGWGrjWZpObqjc2eXHUwMDFkhOuEUXw1nN14v1x1MDAxZu3Xv/GcfHNk7YdcdTAwMWLmTlx1MDAxZGdx2Xb7VrhcclufblJPc/vzp6XunlhWOFx1MDAwMtNIcS3jZYyBRSlZvnrouVx1MDAxMchgd6RAXFzi+OGTXHUwMDFkXHUwMDAwV1x1MDAxMI15YTpcdTAwMTMrXuVwXHUwMDA2u1x04MUvMlx1MDAxZPfNhy5YSq1gX6XERC7aXHUwMDFk271anrfj9a7ip0RXv7zOw3Ljvd9cdTAwMTX9v+uHXHUwMDFlac66XHUwMDFmqX1w0GxmsVx1MDAxY1i3QSGMiaZcXHKZxjGShqJcdTAwMWNjJKjkXGLJXGaOMWFcdTAwMDZcZkIpXHUwMDAzKHNYXpZcdTAwMDUy4dVcdTAwMDI38E13MjZ9WOSfXHUwMDFivF3krI5ejFx1MDAxNZhcdFx1MDAwMluRg1+BWVx1MDAxMX45w5grTemPxm9cZsdcdTAwMTCG8Pon57WdznGtNzRtN7GRnlx1MDAxYnTs+4h6KHW1ZY5sJ4JlaqiGY1x1MDAwZsI12HKsi1x1MDAwNCBgXHUwMDE5XHUwMDAyXHUwMDFi3MKiOfDGcWtcdTAwMGbGg8dafnZ7PN9cdTAwMWXYrumclk7TnFx1MDAwNt6JNXmYaOBPreRKWHtcdTAwMGIjblx1MDAxMF5CXFx9dDZcdTAwMWIzb3zFJi25Z3kmXHUwMDFhje+yxDV935ulmUuVNlx1MDAxMGaKYqaFVIn9XHUwMDBmV0hcImEwXHUwMDAx5CSwR1IpnSWuklx1MDAwNngmRmFcYspJnlx1MDAwM0LwXHUwMDAwXHUwMDBlvkdppbgkQsbPeOFxmse3+Tx+3O14K8n8ypdlesOOMcKVTOJ3Tm7JMy7rkdywP4TB1rBcbtmtXHUwMDEwXHUwMDEzWnCRfOxcdTAwMWHsXHUwMDFle3Yy6lxuP/G3WrxcdTAwMDPRXHUwMDFmi+//vs69u1x1MDAxMKVR71xmPuPhXi1cclx1MDAwYlx1MDAxODH9oFx0W2a7g+U3sdx+QUvUq1x1MDAxMbJvaJn9XHUwMDA30NpL4SD0Tt6RXHUwMDFl2el6s5xFXHUwMDFheTfWe7t/XHUwMDFjrdWZXHUwMDFkXGbn27KCr1x1MDAxZnnmZNS4PT1jl3V60fXsk8O/XHUwMDBlVzJcdTAwMTlaXHRcdTAwMDNgRpWgXHUwMDE0QTxcdTAwMTlcdTAwMWKF2GQoXHUwMDAyK6oohKcx2Vx1MDAxNyZDXHUwMDEyXHUwMDAzXHUwMDFjXHLmhHKtOM1x9bAlXGJcdTAwMTFKhFawXHUwMDFmOlxmXHRwXHUwMDFj/L5YjbTVuPtqq1x1MDAwMelcdTAwMDXjXHUwMDEwn4m8oFx1MDAxNsK2wqhcdTAwMTbCXGItJUL6VzVcdTAwMWNFWFxyP/VcXJj+XHUwMDBlxuOUWT7vTNrTvf3xh1Pnw8zaudxdP+nFkEhRgF7KgEBcdTAwMWVrYIo1XHUwMDE3WHCw1XHC9JyS3ouLnu7pn9xy4MZcdTAwMWF5g9RCXHUwMDAxMXVeaMFIJptYWFxioSFhRlx1MDAwMv3wxKFcdTAwMDTPzYtcdTAwMDG/camsX/ddvq9cdTAwMGaDz2ft7sp4XHUwMDBl8VxiXGLjSlxiolx1MDAxMMdcIo1nIVxywCFcdTAwMThcdTAwMDdcYj5cdTAwMTBl2Vx1MDAxOJogXHUwMDFlXHUwMDFhkvijs4Bm2mA68anYXHUwMDFiXHUwMDAynsPPz47n1lx1MDAxYXhmXGKMO8nHMyaqMFx1MDAxMYZOglwihDdcdTAwMTJyXHUwMDE2ziF2zlx1MDAwYlx1MDAxMKrdk5133fessz3anur71vm+3IkzxVx1MDAxNFx1MDAxMKPUd9Hw5XXZsMO9k0DtXHUwMDFmd1x1MDAwZrZb3ufhO10/O3x3lj/sQ7C34riXx7rdXHUwMDFje+ez66Nue9Twj/X79t5q42ZcdTAwMWNjPrlVNeQuX9dcdTAwMTJVXHUwMDBiQlx1MDAxYkMqoVx00vBcdTAwMGaVS7xcdTAwMDbWXHUwMDEzVcZrXGbMXHUwMDE3oaiFXHSkXHUwMDE2RGGS5fUvIGrhb0TmP9cgs0BcdTAwMWNpcFG5ZMZcdTAwMWNcdTAwMTWRXHUwMDE5Ylx1MDAwNM1cdE7ky1x1MDAxNTgncJRgoelm4eujqrV7XHUwMDFiQFBXXHUwMDBivJqqd+2gtv+mXYW41YPJW36JvDWy+/2kg0srXFxPecpl0av0LarRvu7IyD09+njDr9Fw3G+cXHUwMDEwdnh0upZoXHL5jURcdTAwMTDCp+itNDUwo1pSXHUwMDAx/OZcIm6NNWtq0NBdU/D5kktcdTAwMTVcdTAwMTPhV6L3t/LVf61Bb1wimFZAK57E7aOshTKkX7BcdTAwMWKB6WWYVZmdViRan/5cdTAwMWOidf40qyFueWBSpkBcdEnLXHUwMDAybo2NUMnGYNshXHUwMDFmZ1lcdTAwMDWKSGFcYkRcdTAwMDBQXG5pqlTcP6FAUcJcdTAwMThkPDCO4Fx1MDAwMlVcdTAwMWZv/1xu+ePp6lx1MDAxY4aUXHUwMDA1XCIlyXBcdTAwMTKki2PTwmibKYS5XHUwMDE0skJcdTAwMDdcdTAwMWTpS5xrMFxymzC4Un2pXlxixag1g8J4vExcZr0kLiXUv3lcdMMqXHUwMDBlvFx1MDAxNspC/VxiTp5cdTAwMGZcdTAwMGU72XBh31pcdTAwMGZqUerll1/Z4JBcdTAwMWNl5lx1MDAxOUuOP5XQVZ7klNkoiDo55Fx1MDAwN0TyXHUwMDEw9VwiUS5cdTAwMTDbKMX4Q/JcdTAwMTD7tYWJXHUwMDEy3IB4XHUwMDE2XHUwMDAzLlx1MDAxOFi5vNQhpu+LSYpN0ofVTVx1MDAxMlx09VpBwKXn2CRCMlfjsIJJyFxyXHSvsJbjeVx1MDAxOaVcIvAtdX/KXHUwMDA2XHUwMDE1XHUwMDBi3N/ROuG0toZQ+m2eMlfP0Ci977mSbX/g7+5uXHUwMDBmXHUwMDA2nfp9bzjw0MpqJYSvhpI8VGSFojhdcVx1MDAwNjBcdTAwMDSjJSlcIlx1MDAxMD2Bw8lmPVxuXHUwMDFiXHUwMDAwXHTBMURf4LZ0TuxEw3NcdTAwMTGmOVxutX3KwcatYamUUJZcdTAwMTa/g1j596rHdjRcdTAwMGLKXHUwMDA3XHUwMDAzxjXDmlKVZ78kL5TkXHUwMDE5h1CMk81cdTAwMTT5xexyJMFb11He5Hra4uxcdTAwMTS3XHUwMDBlxp/a15PGVpJum0mNXHUwMDFme1x1MDAwN/fjY7IzpXrUu79u3e01XHUwMDBld1ZSRjNcdTAwMTYqe9CIXHUwMDA0IH1ccptbQszyeZZIXHUwMDExSoVcdTAwMDVyXHUwMDFhXHUwMDEyXHUwMDE2KqRglC6RMlRcdTAwMWG1lJIyJWW2XG6UaUOGOiNkRNBbMJVXPbdOuPD7kPBs9XBcdTAwMDFcdTAwMDDDXHSjXHUwMDA051x1MDAxZJJcdTAwMGJSqDFiTFxiwbCpelx1MDAxM75VXHTdXHUwMDE4iY/ynGt2k/4hoT8kkurvoSs+4dMyuuLSxKtRJE7Oj3a8XfdMclNMPu9eXHUwMDBlu62RXt2xMjavi4FMLqymSpFYgONkVDCiXHSkXHUwMDA2XCLvuIByI3nEl1x1MDAxMLOLj1x1MDAwMeOHvJxcdTAwMDPGrD5fh9WcSFxmVjNPmMBSXHUwMDE2ioswT1x1MDAwZTGy2qxmrszd/dncbrJcdTAwMDa5PJ/dXFw1d4/Odi/b2F/J3ZV60W/lncfKufx8fHCpj0xnXHUwMDFiXHUwMDA391x1MDAxZph/VcVB4LxcdTAwMGVIaVbRKX/5upa5Z1ximUuYrakhVFx1MDAxObPVy8HfOuz9uIaqKFC4MTj33C95aLNM3uhcXJclq4uei0/e2a51w1uew2nfXHUwMDEzXHUwMDBlcdkrZ6dejV+2W5/2fLTf9vbZSdup351cXOJcdTAwMWSxsl/milx1MDAwMD9cdTAwMTVcdTAwMTFz9qbrVZ/2yy/lOVVcdTAwMTH701x1MDAxYW5cdTAwMTlrzlx1MDAwNaIo1y1rpZYvL5itgYdMbFx1MDAxOG2X+bmLsXvsdO6mreOPnVtZ327ttVx1MDAwZiuoz/m27lNgjdepQyhhYfn7l9XRIGpwXG5cdTAwMDRkYVGvTpd7Pu09sVg6Z39xpmtwzlxcg3NcdTAwMWFBXHUwMDBlI7HK5Vx1MDAxYyS/hZwjklx1MDAxMsE5qzzDpWC0N1x1MDAxMsRcdTAwMTc/XHUwMDBlXHUwMDBin1x1MDAxNtafsOdURfOEQ8v8dKzkJarxsOW5QemvQTAxJGZR0Vx1MDAxM0VcIlFcdTAwMTZcdTAwMTn9XHUwMDFhRKsn9ORIK+ZcdTAwMDA7sNiSc1xuVj9HvVx1MDAxMtigXHUwMDFjKXDeXHUwMDFjvCtH66S9P0jM6puTofWdXHUwMDFkbHdcdTAwMWSyQ0BEwa7m1dRgJIpcdTAwMWSsXHUwMDEwSnJK5fORsyo9/SpcdTAwMDNk+KlnsFx1MDAxOI+YccgrXHUwMDFlyperX7WNXHUwMDBl5aODrYI3n38rOJQvmmV5NlDRLLPHdSXTzlx1MDAxY84tnzg+dXBXcDhcdTAwMTfNt2Ncclx1MDAxZWGbLVPYn3TGVs82nZyHXHUwMDE2tn3FmV95lFhmoFx1MDAxNVUl4kX4c70wRJSF4Vx1MDAxN4PsXHUwMDA3Qlx1MDAwMjzPbEROleNLJUKeMe6tU+DIXHSTXGbMTZ4x5sXVUVx1MDAxMlx1MDAxYyvs6iYqRmpcdTAwMWU5iVx1MDAwM8csXoNcdTAwMWZWilCIvqXum1reb2HTUlNcXKtcdTAwMWOqaJbl8eJGs6y6LOLrLO+D5Xs138AtczzuXHUwMDA0XHUwMDAwyMWSbN3Y1qxZXHUwMDFjuL2azy00XHUwMDE1VnSK/uXVl/9cdTAwMDEsMploIn0=RX DSP chainExtend to 8-bit I/QTX DSP chainEnableDC blockRound to 4-bit I/Q \ No newline at end of file diff --git a/docs/images/gateware-rx-only-basic-block-diagram.png b/docs/images/gateware-rx-only-basic-block-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..421ae2c76396799d808b7bbd725a406bbd760b2d GIT binary patch literal 138600 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 z zbF;OEdhRw_8_yDrGFh{Q&jPGlewRBgAYlJKUgPvG+IGo1-2%ONs?{FV1nf-~%^9nv zq6Lba2D=pXvRYyXM3z$i05e`(YzPc54XN4U3xO=Zio8FfA_@?mRnv zD+;2JEYE2d+r-Mnu$hxL)$1$Ma;a`@F@w*51;^CV;)4Y5w)qF~TWDjz_teVTEQy1S zZ+}My6GZZo#Pyv5^v*DFhKuP)eG0*AH`Km)=UpNHu9`NT|n;!n-S_GVdzwfX6DW;mnMK#7q&GlS#HP2j_PrhZ#z1lrrLMs|;lonSb_T=z$TTPU_dAsnxA|7mGxVtk|blZVwz(R`*ra0c0 zoz)Eb)j9sg;Xzb{!m}DRk$a`uIR8N4B=*j?*dZFY*T3URHzN={xnAmu)+~x3mVB5|4Pwa$F2`}o!8dgyc|=cQ6iCe zSIuJUTVSF`oybB#&+nII+SAH#T)e;jCfkkKd^128I zYAtRd51cdfAVhg&O)crR?xdK}HJf7Rh`f)9y_`A*hbZ;iZ zM%c)o?i09vo}0;z3HQ+oC8DL}(45U8<1?z(r?xk$QrHpNrpvt=aUj5(tItKH~Wra8xpVtXWg+^Vt>)V@7=Vhng2crot+mukrud_jmp#b0j_3T zC!6T`K$G4zCpWw9uJEeDX_N24hQ|ZUsexRn<%KXhRcmEJ4>@3ELb1`ox6o&CKp60& z?ge=;-a}s@T&UmCC@IfbW=IXI(3cxbo>M36ifD3yo)5e|OA$RjVg6?t?8pIVx7IyV zT}mTth=-#Q7m*S1wb$ir9C>&>hm6Zqvq;0zA0@Ssr&4%C_yW>@}r4W|3if-rS zyu1S4jzu#Qob9}x33U?MT@a_6Ij0sfA?JBmzcB;_X@l9<^G+0fCJ~xn6NDZNGAIUQ z=5nKk7HVGzWpCvKYcwp^Zng#A5(zs@VemADKSG{kG@U>2U)UZWic8HMr5av_Cb7Hz zJdA5jOz>=>Jw8h0641h$b2S=%Eo1aCXRmK{#ydB|`C6f!mX0!?wQ(qD6HB4R?$SWO z=-*s`K4**Et%+v+9g(Bs$NZ4!+TUGv`Dee{=ju(?)uNVCD^}$fJye$00y-uUTa%wO zuf2b(nD7?S|A43&v7`LH#^$7q-BN4S4#%gPvb^0l)zy0!`yi11nJz46RR3q9QV(vu zJn-R2>1ixKGG}N#j6dm?4`4&2!Z4 zgMAMBos~PE#N5=Z?U&saM7ZP=J+QMhr5)MHFIigxZVIS9q_Nk>H|G!NX!>TalLXUa za)O_54IMKhU+BppvC%NzgZKvL_#7M|Ti3203S{8kYH7a@vf?4&#}FWC@ogkw3!!$| zZ@?LOM@Szc3d*K$A^H2%E^px#hK65C zrx>4zof$O;9Q0IP4X2--D4)i`OEtKQcS>D`mU{ymHMT^FRQ)xI^$?Jn-kTK)?>`l4 z6c4Sbhjdu5wvBNvQPmHwk z94UVRNJTrSrs#+|FAM41b{u18ab2@$an7<(6IOfFYvU?^71FQUNC-vxFgY#fG<*C& zob-IW%~{?5gvG7}l?wU^9iLTBnUQs(z?8Z4gOM50iqH*4Nz}>eH&10 z{wCc+6-42Y+|Es(VMSMTT#KjhPk&OnYIGcINz${kv;9d9uFecDOCj3T{Ds0!-BEwL zs3~`B2z-Xi=)^rCUdiP%QlAZ}4}EYKKCqm>akcjGBhOh3m*Sz*XkF;^<*}IA4v|FY z+alq)gq+~jCFSs2=(xb$%HQIOl>#Ai^vVNd4sBHvqTd1)Ybb5E@v8Yh3ai<%->umT z<0@n4HqhPRZr_GAn_ASF9X?{Sy0U6biOy+T`P{SIp58~;kSQf0f}pBNieaY+ORgx7 zhE0~y;SqY>eAHhmx81z6?wOr6f`c}EX-lR{an&G^RSy3<_t?VD%>)xlRG9*3Vv zl`|DS=M{qs`M0?&Q>p<)(szGkGds-x;*DJSrwZbQ;}1sRnfAR$e@J&bgsacp3@S`5S$rss+nGKT2T@dM znMaWSO`*5OcgoTGC*EcfS#y#9bDBB;PnvGTOh)8L{)A`k%EMaST$!Z-MIRXFgCL5I z+yEkIss4V6u$#lpz`GhTlOO}T14h zYFLYqv;L&uZrsFYL|&uo1*XjG+c@F*NV(bMmCX9k=0=Y{ew4hw^)`zQN=$ch@C5N2 zk40_Vr3)*~v^g&oj83O?b1Qf^$F<7++?9VW7So9RD+d_hrkFW+U%l<3H_Yu}ugBsv z?fcMkWQLp5arTO%7 z;e(qE?}LL2RMek+I*kFj%WsZ>LA<95_MPWw*IO_bJj3svJOopaFP$#XMRpgJYFReW zz+p8MUg!HA_V`DZ$5)B8$%-S;_E!f(-|3cTE@mIO@}eUeUXvJ$SsK^3?0uMhdVMr? zw%-Ja4sS$Aw+6&a@qP}*%q-_~S2n{LrPll(Fh_aURQ&zav?Y^R)$8D6sB{Ewkh; zGzwG-5VZCJrv>E4R1+1`eDIVj9;smn*6Z0nrPSWj3Njcg%GaIEGA}2G%kExZpYy*- zA-{emwx2VdLGAr}e>V44E2@-0qbe+NZuZ^Z*PI_SBA*;ZLtH(iEm7zAb1<@JYd0G)^vzYd zC6`e9)p!le3x&0t4QJHEWjKm_C^Oo)cX6_l(r@hF*=+GGVABuJ$u@&io2Jmvqv7Zh z+1Ti^x;NlJ53iKQRDSP3rOo+fg0!QvG-8*WvLUB$Cxk1}akQm-gow?BwI)NUUH&&A zu($BtwqXp2fw(yius3C3Z&t$!@4|B=HO7Io1IpecQw2KUf9=f?Wp8-z8jica9O-ZK z7xY*@yMv9Sc;;z8$w`%3k!rB1V)2>RW)2S3j-mDFoX%vM8gr`Jp=?kYEE52AJ5EHY zK2?6QiV~80BW7ErgnyC&_o(RjdCg^`-^I`$D7AW(Q5V-hyP#3&#j@q`MZ~RXV%j|> zaQW6im#TH6pf5-w3Z zRz_l{(7v;pqPftjMZ{k=`=H^=R+92&H-na~)@MikU(@P0zy%F!mtm8_2fBOaap>n! zNKvYU5@p}6L}>7kX7*CWNM*!P?MKrHtI~3>O0xqW5EVESF@z47H8mRO)_A=fMotaj z&5p*_2|yoLdiT0ce0E4Yy2st`6aCgQPW{va;~_yxop0FDTYIy$@%?1z)IwzUh+X^B zz<_`(d!vRnLP~fE!dkgQdZ*gyM0LW^@L{fM-pZ)k8+x4a;&sF zASaNrC(tB;4+M3`rmmg2%P`*pdNMaawgD2++x-99xWF zfa0}I8{LIJuHlEjzJ)FW{@JSm8hjVNryVmv{8$G(rmiWXfF~I5BkM;{Wqr#C{zH=L zT2V+&Fs+WPj5rRo5{DQk1qv;dG0~{bBt*M;-g9}|dvTz5$5NhNNSs!9RT@ciV z)n0%>V0=itAbVGYQsEc@yUdLl&&y3%#xg`WL9`0fL8|^=q`+s@H|G0(!_}u^a-2WVCpp5+A1E&ADh5xvP|G0(!xP||?h5z4^2&O=m zLaU_2NG-dy%p{Of-Fo>9)5B@*(V4e*ZeB&hj$qyPm#N>>G2fI?iv>zJERWF>h)#VB z$K?dGCm%ju?TDa{w?*G1FH7KNn#C2`1|63l?uYF5@$ait;b}p;Y3QzcJXa-JaX=k= zzGxw?GX;?@WqeQ29VvXd_l=m69=7D^SWxV`7-f79M){CF2$iLa`fOx>vOXRj;0O23 zu!9@Ef)xKLcHu{fzd_~OxU&T|VCW4`AALjpk1SNh^3_C@0!Z&=d!>t*zusiD5Ek0$QWdv$&`vxEgP% zK6y-#E2M#GpdMj2(coDj6vB;%4j%RKE6`jwAFni_?eBK42cueh zV=yX}mpRn3`9AVS_k!}v{6yWh>eT;8w~8F(u;8ahztW;FpM;}mh|iC=(MT-)r# zGf0{Lh^EX9rsA__waW7T5U3iY2uk%2F*n94`jg4f$GyQ&?4gC`ufJvpxGnAXaHVqS ze+l=Issg>zmSnOJ@T^qvW`x4G>FMc#k2W?opMY9?G)u3mssWOBRA_uI(_4nMYx&U}RF)H1c*koM=B=juYt-0)nLzX|^=!*5<>D6ua6Ih=( zx+k!LB+MFVmHvlEpxg0C7;P-K`|W=pKX`i4Bd|s-GpmTZH^;HvD9@9FDh=z&3DBWH z-<ZxoV8Wkpl9hhY!~HADT#|Mt9m6y$m1kv*nxIVA)I2o6Rt zpl~o)(=7XeX@3GnoTX014N8hklf*hC!f0_(F(Ln2zyDfER=~6i4y3@YNId=5d}Dx| zUUERN`wXnC75Y}HV)ehd0H_irpDAN7o@_NkIinXkEd>=e!`~sjND>bSXf{-P$72y) z9A)~?OXRgsv$!q%KRx>Yeq1^iQQG-c+$YB?ESuRSXMtmD$JWIjW{sz)6=29g$D`tN zOo>P=RP>o}7x09M6~S_aRsT-NYrLPCH|duj&EHXLM&kPMf*?I`T032DFt?-Rl z6k>&{{!Skm!1}%xqpbKhsKOJoWT+7V&c)CVU5f*Z>6RupjWg_Qf6l0sM?^HP?u8z% zcwEtf4CcltLw<$^(Rki;tVVe@%aS`e41rvG^cHC33Y%aq-j|iYp^x83cU!rFW~*KE zEx~pN1YOrLSMwW{U}yl4tEu{*j0yPg=*jR1)W&&T8##~bWnkYdXx-6gxIbO8`)VY^ zvMB+vNuZ;krutV z85up-T79n5W;0P5VUny7O9c*vX_#`~y++kH)Si|yC=);-jW4xO=Kq}ySdQwmY+3-V z7RFR{ui(}O`cl{}C$?Nk1YEACGB%v7j~K?TPcw{~j1&Fc*Nop7e}4iF#akYS`k!w_YM!SIsfwx#dRpJ6MD3Cw2K2ny z8@P74k-j}|sQqwmbkwriYuKC$enUawM|Mto&!Dv+9DGNX+2|7+;@cRTyK5(|qFV@)=VnrKUO=tC%>gG~eAU)2WFy@L3RO zenuB5jatZOtdGr(so(K9$im+|!9GkLEz|poIx*0E{Bu%D$c~w z{GEoMB&T!iPCb2w4SD3lNE83MwZFB52v8&r10xAMEUJZiXMS&K%5w!9 zp57X4ncz|NK0x3R27%x_bI>m;l}0`L zcywms@BW~VK(A=zmF07oxUY%Hk;a?ihJ6%gW9$Jco~TO3i;LLI{YyJ0Gup#fjvb08 zi?OlZfgVp$^p1(E2yL4Gh1dLp-6Xo;NOId-1U!N#!#N|_XqX%_VGzah z)4Vu~yb{Q^MF4~ixs`X5YWrm6IaE$5LX+e^{7>7mYi826$L$poE!=ex8vzv%R~CCS zYs?()2J-=_Rof2UBZSpEX54Y^d@2*s0etFO`8yeo2NFnX&6Z7D3T)Vzj;|jx5(?p6 z9u$cAqO+`OcWBNi@X#+F>*I(?T06%XVRbucvvYI&Hy6Vu1?Lv!Rw*bOyG?h(8jZ_-I*SWknMS5 z0S1GL5b_viGKVY)faQ3`(i=}_GV%)roW&}1^;PvskMK{&E*{#UI*x4zirJ?ASgshu(I(g{lKDKCAX?*(-{9`ASFX+MybKea~8HO7QWB>NF(!wnS0Fb8s zUP29*c{>kUNzVjmU_@7JtCV1s1_rK~*dss+3jo2ms+;5`W;d_AT}4C`kM!3B;{dRs_HI9miFFxmS-zcMt^GH6*9OJ93$KrkJlfj3BdWER72ldPU1AOEXq9|# z4=V}1oiRNXfDMhTd0T&6$(|HtUxm-k(tzOF3_s|`0!P0B!QHD_V?wtJGtmjzXhab< z7A=xSp|&3#SRnUoVZC2YlI%9W7yS}SINJrK3F6ehGQEeSeksh{z%HK>Y@kC1*B!`t zi%bJ2xL=m~=**tYIvwlOZ}0I&j)|T9Szg&>t6~|_;4x%LcO|AnFN7NZq?RFO$w1pm zbX=GSc=nv=k~lWL=}aFCiMQ`k3dl^|Yo}U>AJL29vx@tEgCb5F_`fz3%-9KFgC~JT zSd|+Gh+sPHjuGuEaJyAiB@+^=k7uw7 z_JJ&FZ+V^Tq=WgwHjj;6c^sdM2>4f#EhyLP5&9AB8h=|sGynp2S6<2h$DkGR3E)p= z#-Pwx){l{Fk(;4ul5%o+mD@hbxtdSUq1NdyE)U7@2PPu!LclPJar$Ic=V!a~$~Z$$ z&0zp5qf(~f(~1-1&k$Ad<9So8{3J{37edq9<6H@Km}gQ*0wQMu)@Iw)i9kmzK8?Kc zG%9$#Tjn*PJH*7N*729Rw={jftL{l7I~#Oz)lDxiP5hrR~tW#*w3P)g?;DQ)bipe zrcy&4iq--M?}IT8Nc+ z%rf;>^U#!^EEiXAs?peBZ<+JuI2@2{G}K)LDHPmYP5xlAQ`U8<>qkg*MNdhn0t9*V zPZccTRi*D}|GJq4v;M{_rP)^1u98n(iO`C&2tFOWjAPTP7#--VTls81_x)js4rORV zHFO@qzbHV%CH~2uw5JKmV5xWm06@ZJdmR_24P~zfE8A_ffjc`6=Jrnr$zMv_eEOdj zRlemPTiO~G_^oYC(49mm>E=N8$m_!E&u%e3x_%a$S2l5ObavRZtxdT9qNZsN_P;q8 z`LSC-sbd)G!NgA~tk+5w4l99MOGYJ%9c=Z^>~q-3E?l}0*!(Oe0$3qBzpGny89OLsRGu~zn&#HI_k(bP`lHo&?Uco z&$aKHzXMShlxm7d6RwQbXmRCe>0O_+E3}^*nj&i(>PvfDt6ibUz>kUROSK4Ze_HJ# zyM|$S0=7?Z_CI8zA~oct27RWkp0j8Jd)0hZmAu+n541m5=`_ST*>IlXVog_F-GmpD zmCrzqK&DY^=ii^NCIK1pTiy(^$HuL^xY&zK;++3ILO)>6nBCxi&To~@pqRafBs^){33NVG z+s#RT7OGJxb7F^C8gSKsP_lD~q=;vne&|Sk3)&kfWD~;m*buTu?FX-IDeieJYV;_VQwM2zNpAZ1U~L^>KyB!OYPkRD6)P%S3k^{>$!~2MT9#y~KzZiplTh{> zK*C3368}ciTzT|*Pbiv3CL(udr|IVX3`R1oz^)OjYXX)b2n4yN;U-87(hc@*5A5O? z0P~@5168ipyfbO4ZK;!PFl5{UmUnsZd4uG5; z032`Y^CsM9MY3}>uV1S9>eUC^(>f(VRswX`;=*!`)B>u7MVEtd475KGB?4* z2`vB>H~X_$7Z9F)Dd~}@>N|HF^nh53v+()S*7u`9QqxrN5(~SA3ZE3s0T!vuk5Us*UXzeI zM8AnUZfQG@_1GdbmGyj6U0)gr2C`McKajG7l@}45u^BB?DP14dSiI*%o~g8aB~zhB zQ?}F5f|`!eLE!$M91HA?AwSpHF|0r|YUI>tFAhxy?~ z>nNJx_vw?v(r{@BV2$X_9q$zgfK3~>mHo!_=nTxyZEK;kbaMRAXp<{iXxXf-%=$-P zhnrHiNzt7*q#;u`Ss-mRgw6(XlL|ltQvzYeW%C@(A~~<412RCIBZ_V8-#9GEzU$l; zzilh#O(4|-duahc=aryFtO;sEJ8+ZXEC8KZgc-0^>yc8OZ(cmQPAlUkb>yl=;*R8x z67vChAu!OhTKrez^N+{6?VAI}cCT9CFxtgKL=Sxi+})Jla?e&_@||H1Z6VYq7@Yu2LwnD)I+ zA()+?Zv$X(Hjtqs#iPQmw^GGE)4-Rsw|v}15&i4i>~Dq%2rj^#%WMJ>&LG@*BxTx} za7$IZK?Pi~SrAL9I<0!8ZH3q#0%xg!aA2BvCkW{>Ctl7YZ%5Rdnn9J0`POl~It^Oi zmG3)H2m}$kLn9r5G?D5IhfbyaXA%B|a~^jqN9NPQ{QNuArKl7wSidVh+YMIGTL(u2 zQwD&2vVGu|79mERj^vJ~5xg>c!&GlI&5f5oOG&`o-Ix_{iq&BS&hibuE@rc*`PRQB zCezv?HQfb{WA_hC8rFBubMLNnT|)^}ZlvYuJBgJUrOGf`W2Uu-5#Z?RhS`+zz&~?c zfS-N}_T{=N>>NN(jGf<}g;dxeWaD^LuCwdt-p-Mif8pj<$z#(id9y#C5p_A29)%pd z>Nw!rTXr_-9G~}d7D-zgnX6P8Of`OA-Q{5poE}GW$yqAG`n#CxBjfuO_Pg87lWicI z36k}k7l#13d?3tub<$|6*KQ`QYfy!rPYYA=v~+#k+?T|TVTgd~iI5$8d5joF$xX_4 zYfdSgW3D?E$V{vIpOLit8PsPH(|Mr-RA4ipYsK3N*7l-W({#V*>(*oy3w}=RFPeP! z(Yd3mE1WcYuzmewWP7bAdWKTGx3^t#Rr9Sn!q}SmZGXVD)_BVmfM-zbtL&1g zjztb-mB7K;BGe-l{p+aQkJTMB5cy9A1Ko_CZ}yTFIyAG4)Csdr_7SVV*q0ZobLW)M zK{2+0N*ibiPqz-Kx~;9P9GI6?WbT-A6Hl3&5)VE79Wy{9i8}qt1jS;rEg>fB0 z96k$0s${qF`y4itUXtg;Vb`k=7dk%5K5NtdR2y6mW~(ZQeD+q8*AhbX(y17DQBT{A zEGpDFWI1Q8Q!3S1x~2;MdgsaR$K7VDAK-!*7+f`oFkABLiAq$3zP$*eB?I2Vy`p*j_3jaT+8YNu;&_tv2GQFS&Sw_hB;2nz-i zn5D1epAs#zlwRC>`b4Ln#M6WUne0t~ENrp1 zdOt|AgChA@#Knehe(fSD>5*Uw6(;WL!VLBD-Zl$s|LzYL=M!Cu{o^eL+Q;`gjg&JucAl0UqxR;D0u@WvWMw~sgSWv`bJ zoxcg4`L9oFQYRMmy^%DG1tKC<0C}x8$$~J3|A1sTHrl*qdMo_+TU@MG10g=;DAkgS zI_g6Ix@mU=HTZP9nEy^elfn$kiL9^N!BbkRH2XVbsZ;z!) zew984v>(U82tgzu874~HSVmDh#lr9B9F$N@v6)jn4sOriqqAWV2nR#Hr5o#q1>StZ zCo7YO%(;5Lu-jV~T=v!`=CUkpf&c+iKChIi_!N|1sLkE>4FXy^3xyPfjdryUyyjs6 zf$U4K0J>|{6nfdNxJ?+24loQ^kUdgREZPtewalZ*C-&gN6|_$@{()Rd@eUXP%IeaU+7 zj|5fJm=pp%)1D#bhVPF~?e!hTF-erZn0Jw74^+#oTR%qcgs8H|Jj|2OX)s&!_T366 z{p4V&bo^ng1v%7-m~VF;G*T_QkJ_FrQ@gC7HfdKm5(qa{4}|B$jF0vYe0FmZ6bHb^ zXNLCjBTS5mU`y1({&2{pms>7Ec0_aB6NfsB$Qjp?gxr>F_8FJztif&0K{r)VJ@A$L z{F81D`%e-gD|Ix{gA%O@lw%sSfyhD9nD$CXW062s!RG(!2Cl7LdE&Ig($Y7$k zzKi__ndXGoPq~@`0hfAayM2R;6o|CruOCrjHEy=;xz7%E*0r_>bAdlV`ewS;op9*M zMbE49?=o(m-zm{$vYZ5xcGKN2@g`x6*Vp43Tr#Z-HmGSk^69W?+FN%2O!4FM4jGaj z@yZ!oM+UFiT;E!~Ec{R~oOmz)MeagT&ja?nj-^o>icTFGrP|n^nt~R`M33ffv)=eV zycvbwU5~V>jb#QkN+cv4`Gyp3kh$_&_kRcb>rYh%$7IN~QtumAA2vm?WKIiHMz);6 zr_nF3f88R?sNRq}AHX_r^@zJ50qmZB&8AfV>}QKnfH%S5R39RzE`938)*g@6u_vNT zzV>AIe2ZoNY+X9(EW|dMK8ri=>G()j#U^D`wCkHc1tJ-lOYl_g$RcaT$Z?+n-%dTS zC9PuLrStHZWO-(w)xLLgUji@C9ks|3FHmgzB9A^wd2~Df`BNl5PG(EC&*5J9owow; zYK#1ZDYCJinTb*2Oo`kDP>{Dr9Rxh&MBk?yTrF09u#|DhYBjqmW9(kDCn0y)mm7@c z0O5v+BQ~1A$-XQuf3f}`C(vJ3T_;9oH9?>YDhJl!Z>_(tXpha zRuHOS?0yGln?{$dvBCh+4>hwohr{3x%6};V~jfT{r&ekJ*AXf^U1b_MhhHd zNM<7)y3#yP%TN1*u!Nkl!5%b1*1_bM32_c}DSZ1}J#)1_f~>q_9aKm zz!N^y60IW`DX1)8!at#0ci(E#V&b83wI^)&N!i)u^n`(YFGY?3_onN$$~lKS+Mi<& z$%V%Wm;mA__nKUlS+W+|K)3jMrD`23a^@wBXIJIu)kzH=Rp<^LS2XA*BcH`RnSm?* z=>%i~5_UZmWoXQOC9ym`aXq;^)+_YW6P?+H;T zv0QY3SqS>_$}Rb>y(v4GAXF~7uzJYlcgQXJ}ECI*)3vmo!U_s>EHh3 zzN2nBczN{fBp4|H*MNM3N!U`^{%F9;*+oM+9h;!?)+$BM|M?A zxbL;zXMLGI2#Y}3N5$JuFDQ75>Ev!wR(&0EGZyae2{{yWNpqaLgW6{do_d=_Rpup3 z_K1o*H6d&87-<={wVz&$5ajdB(!gr2unl)k_H)u&Pj9zv*$L~!@-d?d%|JppY`}Aw zJ9n(IVslUDm_1iDS6Xa&1O%$xDd%h|lzl|&jH^oEp;p1fAv%0<-Hgv;d?ivqSnoVl zAj2U*PIAh1h|8H8jcaPvfqd0oCn|^Q)XpB`Zq>*^H>Yf>0ZxhK7Pl2MVeta0*sK=Y zxptFb%csXmdTN320rP_L|d_Q0<*JFf# z#2jgY?93O34uuo$7R)`_ws-)L6>kLBK^h(69Yn62az(r`M#E4IsCDb;*hk_?@3KN$?=DiZR^qX$9>3q zHpjPjT^{G2LwC(T$%|;(ZiqrmMwcZR=?Oc@snj?no-n@tZqcc}vgnRwifAFC`M>mI z0ak(?r{ElEv21tZg$tk$gH{MzSNsHq>S?KOj8PBPH5Zz9TsI#AJg$cr-?H6~iGO}P zjtrT+&7oCM-jxyylqS?+2blk1HA16Pb`8|zL4`#!4^CIK{ZNX|jp8GgBu@iyl8=|1 z5aRu4zF>J6&3~g;A()9RS`!O|e8 z{&!jh`~9!bmqdY1pN7ubCPmWx(5BB#pe_bJ)rClXv1ooQsp!E8{-Tb37AovW%>CQH zLVx++)ZW4KrvRz5VMB;55MZ0<{vGT?bFnR2L))Qcx<{`;HTpjj?Nj?VL-7UfJq4hE7zttrsLZ*k#Z7fyg(c<8?` zoTi0<<*4*|<|p*8Rtw{a-lg1XA2WLDd!3+Env}J*UI`X4|Lk%L zI0=n48nEOKkkxU3^R|Di?%!(9zy>sdxSksfJY0<7wM=o}Tl-xC6N#+OIKyqjCW`ZsI8Ak?RygJT^_p0hi z`buRU8IF?A(7TsknBr%=`U?8FOxm`>6*=f1Yu>k{1H}Noyckk=2+}tBg%8D;{D{tx6?RTZ4n@ zp?a2Dc2*s}={uIh!$Q}N`>yUQ5`}PhgeR}B=G*=tgU9D&e7D|^s-OBT{M$;PTa^n% z5*wQ+X6QwMHHPT~un~V-Kt1G7hQ`4XSX6Uw2g<>}!5PJx0fr*R;hfqRJ^(YtlI+1C z<7Z>e>m#h|wU|r*A=!Bhz}=rI@G0HiELSC)5Bd?rcy@MnCWkqQxhnFa$7o~Y6q!1q znv~UG_TWEm{d69+m$woa|M*|oePE`z8i4i1RDvV%aKU6lTt)Dsm|bO^&6L-HT|3Xg zKqcOj2G!rS5U7vD?t|fA(5p(pmZ3h=R+#<5+uDeP1P;(65zY}mO7HvI@K2{n9pR?m z$q1sMc?%%DwvhrK+b8T837+jH-VCbRpx1ELL0CXQYra#DDKz~=e$juU z(9XDH9%{g1OlLB^2vz3pVFL?|ejbpfy}Od82`;HL$uBfk@pQo-Y)Hqrp2iEv@xWI> z8*N>J!aZz@GcEr_58!@HSk*c}?m|Qw6cKUfE%l&Cw=jBV_F8ieEwFC3bElTm2|9AY zOabZaPl;mYVjk3xLDjQ@KhTxpK6NemkecOtLi@% zp?w*Z`1gI;s;mP!gzHI3a7bh%8Ovvja2C6PjU>f9ZSgGvBU9Rpdb9whO48>4osoeNq?)eepqW$~s-SUY z`25^m0s8Eh5!OS)UmpBe@_vHt;!{|yc_&x2c@ z!y|z|uZQLmbND>G0lEjzvIRQNeITIn;if#5`6aNJ2lZSp)W9Gy-Z$9p>}x-a;WF4W>)ty=?=S@e1`ZoG!(_6Ak2t&i2|)t)$29u-cP$zN5;QjQ?(;eQN(8NI9T zy`tIK`Swp5_Qs<-8npgU?RqLbvY5Y+K@4k8Ah7*iBK0P?fMW*^27$0^309(=Y>aJQ zeN6))bUo+)WpC`aw~SFSj$4~=q@aKc8X>~zweClrN#BvvRp@*{IJ>aW;pZPa*Y$&X z6a$auqC;AcsS(|xBV|<;!GcZTNPgeYaY62xJgun6rPJ2MQ`r-NnYy4dZwz$xWSIl( zF6z^VtCEoFwyoC^u)P>7)nQS~Vk|U(QA#ObGJq@z2@a<9zr`EGq8fPG z>IRTU1ti&JMC%HW?2j3Btp4#qijdg`wc-7R1Km9^T{rkYNw$4rVf<7dfYZZ3&PcC^ zfCXwt{I92c{tZ2Wp?3d1Vu&0nte^URk!;|dbE`GagV`)tQv@QQ0M_&JRdXJ86Tt~xi)MSK7N7~D;8MkBA=F;`w8{#g%FL!y*`G+j%%BK4Fq|{E zN4J4rhfRD|{qv50K^vxX_8-E}r>i&a8NR7L+Uoe${}?n;O+!e*SHcqZqSwxNd-Zw`!aI)yt z0odfub#Q=b+x-bR#t4lB#>qbOxAf~_;P*%Uxf`0$xsubo{YCtIC@+3xw1m~+1(<;qk`PQaq)q{Jx{ai@eVns`zv3wYWV{JY54lBs)l;EE zGO|#cvlv;%zm`k`ZB>DEbQv{xDL1jF&?B-SHejIJesUCVw9JN6zFx~uG&H}-CeE=_?EiYlaY=s}&d}g~0(PLUEn~<5 z=ACsauYduO=fJz%O}r3xs^eJSQ3QZ%ROY8KFhtUpJqhwcb_Bs<&`AZxA^orUZQwni1fR_D zd})G$zzW{%hq&DZQ+c@ahVwyt7WsXLFUQ{=Xl>yt zOB!rPV2sw~re9=XgahD2-)^8E?g|oUqs{$fJ^H*fV|G7WQ8I^HI$rKl9~tyK$Jq1;+HG9 zM8FvDHknz18zV}wa$N*+O(f}Tnr{h21g*o5G)^??+Jr3yG1RC4}p+Y+pZ~Uk6u9Uo!XdG|II7iRbnx?R@Zc}_5e8S^L0J)#PwWFqFqHltIcUFQ1AT1z{I;zZ0w{$!Lesl<1b1ms(w*^I z*4AD%%4~YyYC$jtM}NglyL4{XVJg1n2h&SjGVk4B0qt>yZ+?e}dU0TE_kZ1r10BDj zBH-$2u-{RT0C+%lMgw^?XIz{~$Xic7BvyWDv#QRIQvfZvHj700OOH@?^aU1UhNk6H zO&JDrU>k(olR<`Xmqii|8TgqZ;I^U|+8*Gi02``jfBlLNd{AB%0GhG11XKe=*nofe zl8?kCT`B6ZF!d(TxUl)~R5H8J%lAw!b^`S#=siumpgwq0DXvRE<;%}s*+>COxEB!) zcF?k={p!1?;J3Rf@rmA^yBb}x^0ch9y4V;mQZEGkX5?0UbfUL{=;7&W0*BMUCiM-% zS$m)}4lmN%}Y`dg=Ht^+SHtmX)F8T-<&rt;6ytl95j%{ zu$hemcyDpMr9jBo^r5+SMYqY%gB6dT#diUk;O*WaE&tPFRZ&s#HU~#{O|$VFeiP&q z(H}ru7DDHkg4{a%O8#ls)<;0US@G`%zssOG#v+PN;EVMmZqLvJ$xZ+I$Qdy^Ym9NW z@vIKzS#lEuXH=)Tz|%Nb)nn$qS;!mgrRfy@S`ao_j}R=hY?K=*vW=wR4`MqYScvQ$ zXqQxMCRWVR4hgF(4^gfzR*b-tnB!d$@8m2g$d&i zz$>&%{~x~`*vhiM_4S*k{LlJ;W3HK8W-j>GxGx`_3~D~6JVgvDW~znJIo~h-rA5lu@ykxFU+$kh zzEzp^?CcU(ajf(GC{sqDxvZ>^#EW906U9`;s!xxFzw!i1uu{Ya;w@gX_YPJM??T69 zG{7+#k%!Rk663o(hIV)Ph79PbklXk8{`M+awwq5(@6WceRP}=tA|u(Go8g@vaJMF- zbSE}lTB*t!hy1WiU5-X|R#VPU+dcnHxL%2;Tf4pAg7IIQ@oB+PoC<{toj;`mRJK*y zhutL(hIBKXNL}}5PV&ZOR6jzB66BZ7sTyxDWKthNxm11Gzy57)vJvCKP~MlN(K{$%Shc@RUmr1OA%5N z>)i1k4#Ty|9=#a#=yszei5?ZFu;<-IjHjcRSOc-IPk`2(qNwj(>*w*$z+Lr>`52p&oF7ypNfu5+GJ>h5$ubTBhH!gt0;N?>F`^tGHT#c1 zzbi@%Oio=7K(*_FU~M%eMswhkS3}@+Tyj6Jv_R33LW$tI_bZ6i@!Nl~N^U;ele++S$Nhw zYKoVqn2oJ^QsY8rkJ}2}PNbtB*@^k_-*kFGM|s}q!XgaJlbmAFIvKsq>GX*DQN>PW z$85q6&rU?^ud5eWfIr*6zI_oUPkXaHxC>kx$i?S&dPMySbT;FMe5vUr(6CU>#R7Ri z>==y0uEp0P>fjx|8h*Zt69An4^ggk#wmus!>7BqB8sS<2_WHzuvsS6*fw8x>v`b|_ zI%^6X>u=8Dac$R_*D77fv*;74BwCF~3Y<(78$HucfegNcR5~`#f34&vrRYn1Vgt^M zV)mldCa3q>g}!Fq4fMj7Xp6ZI)WDY4NEx_WCg{Wngaifw=K1oC_a>BT`*GQ0!ND8o z;0p!AD9x4EAVT4PU-W);7HG|bFH8m;%;2&D`l?Hj7vVYEAGN1)D~esqb)v*Dyh?%i zl9Q2acppgdM|&i}4HPafht7}>y6M+vUKSKbMQHMAuOR{xz4JnR2ZmW~Hr!39e_jK3 zDL#-MELITpwMp*^^N%e%V3Y*mPP43B7u+LY)Rpq-X2dJNx<9fBJ`$7c5C78(u-ifa zM^o_IwU%7W59zSfp%}cugC!n;|Fwjae&(jX!UdKmkAK&fzJjoSC4kuK$~zGNC~==V zh}OS`bVxnyZsaTq)S+_|*XQ=mJ%7aQSbmLF?U8KKMhy8ymJE$axI^5Lkkxzm*Vx12 zi1`}pT{y@yt2GzR=fe5+YYGEjT1Y^$vK*xl@cM=EA<#M|fds0#p23oF*L~6uw5!gY zf6T%Ys3VPwqbP@sSL*opWZ!G-N^DBPj$BPPQ=B2sI`}?hi5@P0_9K&NyyTxM zo-A{l!(BVg$dmVo`(UmQ;bCQ6neWe2R~8=k&{jIaqe{fobH`_8q*&lFrjRT=@{W#8 z5UbVzq04Gh9ph|`#AMh-8O)}qo@e}tB3c$cP_e{PvAUFZVslBIFV^`dD`jhtN8 z)wUa`QC;@>t^Q&ITF1INYamJv`SYu_~aQ`imgVJ+r#he^(b2; z!lsLzK7Y;8yWZM62R{&)@25I`Il+rc-DTk2xhQUlg&yE+Ds)#zW}E^gV78SjqOqkS z8WJclQQ@mYc{ZK8-%}dsdX>*a*1sHdFS9UZNg#JGxIC`3UOwz~RCgvJeF_xIgKJt) zgU7rUu5)peH$={7Z3k{;B5yELcyVh}X&u+IPxwZdrdHKSd~xVi99Y_eLSc>C8%G6f zXmfM*+HlVNtoWO@`LjcEqWDhnf}Y}3ITL*t#oDh2bMN!dx5avjqrYC$&{?`TASB^H z6`@j=n14Cuq?$AF>WgP*YboiH*E~d>a)mMHtdTU$thd|xloAMU^u1v8Ccq`7tITwC zI@}w!jow)087bKIc)$cRvKe4;7z^5gA!7*DE;xDNp`^tk8#I`zv#5wcaKeKm8$H&{&$0Sg#hZgybT z%2-MH@X>(AO~=Z?DI4^t6<5~sMq>Ikvw#0NECNfeUDfi4T^|e;+jk@bP zoF_13amKP`o%6P}>uwrj<67*fe01RD+jFKUg0%Lc*Ct89&QS0DmS;T)fB zr8+*#igwv!zY_8&(PuRW9&IHhsq?&%lFc&Nl1U-Kbw5mbG7{xzqxig>>Te?A9;i#} z$d6(KS-lC)JFP^f#|lL>q^0dj`hn2E!BBEALt@u9$zJ7|F35&Jy{%hi4|EK(Tz`&4 zA8NPrlaHYI6&SCl)P&hQX1}KR*-(n#Yo~l=-z>KCz$4)LVd6sADsLE{8WvZTy z8}Ia!UKP(w^{1DFA zXte;rXCQw&K-xaBOuobh^@=_#_fJ0RiRW`xZ}#WO_yWNGf%Og_IaPS# zyjnU@Q*-mdLKz*n6=pBbZT!ix)-CDM7b9FNo*jCz#y|PCXFD_ddUt~_g{ad6=KB-e z%aBk@smWXWu5RsKY3X;bJAt2730wjOVU+2TOJ^(JJzSz&C1tq=uIP2H8|Hpq{sixG z8tBxle{eRPC^UtDfh&h01RFOdgjW+5Z#$0h;9HobD&0ooFMo5=Pu|&k;eV6Y7zseh z52k_OWK6p|!h@kDfO-!W$!9}Vk=>UY0z-#)2)$MsMYQS3#nFv9t!#0M;gOD(SaZyE zBwVf@DHHph_tQ85m{MN0`#TQ>sh11H1P`&adr?4hjqauD)8gNN6!~4xU^hU!@~udo zSAmCh$;&@*p}Zikx*}os!of#wk5OT(pS|ZvrPbK!$p-VU7MCKQog9ztwo$Eyc?-sN z3oi>=&6uTKiZq-qlCAKjzT$FwBWdA~gtI(#ss;xyVxJa}yx`{2OmCF?QTq_q_S#)zQILdyTVm z#L7s|+pHBWgOzR%MYR3?1ngVK&sln}H`<$2}BG_uF%2>tt=aC1YPBlx;+usXWTUGPGHq zBX&f6zns6+d$&IpX?mX26wak|=Mkm?jt3>1W^fl#_x{J#d2_5SKg%AGd}l185w&=X zih6f7{w>~)yG8F6W{tUO+b{CArjOe_ zpjAG(%>7GO&B@Fmefq9qe4ZCLbJ#tQQyaH{bNri;p+|)B>3O$FSy`N&t<8EqM-6bk zJZh36=UzLj;3!=~Y&RDoBv>i!;USmu+XMcekS8D+rL{_RvKgIo=XT%z;9vN&$B`Ds zCpiXgE}RDtMLSiHD{&6sc>T?3M!YCW<$c4A7A~8k7noh^#Yt_=y#b8h47Kplopqrj zKR5-c%MBqjW%WAda})b-R>n$)rgpm*+*?W6mk;VLT_P2>Dl>9lo4e@52zn0U0!QL2qSjZCh-`4!-_9Z8$lP| z-MfN-v~_X7jzRhjHHiG`T_I(;_;=#lA?mxMBH%R}^+KmaV~|6G9^R$%6TP<+={8=k z6#7WNRpmE8!fWtI=$0xKap9SkN!hkd)`qhKfIX+dorz291~iyAs?L z6+EFuA$b<%%)jRauf@6^mNRqB4ZJ_`BIB)AcdOf!SD*Q`iu#b#o1>I}|9G?m<&1#$ zajP@w59eG}Omu0GZGq_pM(mY^-*PYQ{LYBgo2BS=M5y6hD3?xXxLoiGeGU%)7r^?v zf3TBwH}1-Zvqka~M(mRX0eY_@MI3aD&RV!%Z_W`q_`!htcAZz@KN(al-$U^M~EQ~(1FTpLrIL>GPMZV$d2spNX9qNJ8 z#;REpJr6tSazGg#@_oDIT&p{ZS~o`e8#sY$hbujw)GQ^qp!ypyfDKVj;K<6)zjA6e61Sl|SzY*7Dj4IeJx?gj&}V=#1~I#bDqLh2T% zJSEGlj*sI9;@OQ~MJ0eQ>pXx_2y$>v-oHIvaODprlbB2f`qi)DI^Oi2T(0r5Y40Vk zJFF_{rPBMc0w;%Y;@@9mJUbcsG;|)VS6QoNZ@#^8&;oN|&d^UK5yb=ZCE-&@EBMY7 zd~Sx5u`Q{w?Ih2Y*uEoo)QDO-k}b*k!DuYgOXQAu^!^0V$QRdacz+zfon)WoEel3n z?dQK_iF_fp4rIl_V9D>Ebdh_4tT*{m4k%Iq?)wecyEFet-}>g<8(=&cV8keKqB8tM z`w*8G7r!Nb1!P31-VXy2GIIy5&>Yd;lKuH+PLn~21%#H~dW2uE>xPbj|F+oM zhBJY~^2f@U{tmz!L7M|c^eyvgzww7m6Mcyy%vtD=OaBed!M0RS)x-CPJ3^73IE-=$ zVSH0)+5SwjOtrjym!;8y+-t0w!+<8{{tYYkfym4E#33GZv;Z10RS(r=t5p?tXP`SL z0+{g#Me9M00q?O#sS{w5crojJ5v}OJfNj1VKu~r~CY#K~&7F9r!dJuwxiBSB2PY2E zJil1s+k|-;cP`gr)FUQ(ELy^a)tBLCRu8@Q%av=ZvoP*IF0q8=Yba118;Yb^UM@|0 zNp-BBs&tqr)-1y+RR=?~7oM|z5p+_=$7|6al&N%qMO~w#Z)V5rTg`k^c*UKujDh3MFtxS__FI0xbxkSu2} zpZ+kV#_#x%BEdD*X-ou2Lj61Lx4!Fc#39nvJ#tH14&VU_+Bfx4wIf?lcQ?OEUy+vl zuk+lD(KVT{9L@-nW9C~m89dJB$4x#O7ST`9SDOJO2ApsZdTqJwoIsfVCu4Nt@ z#?l|-&hkXDMw8UsamG>dlxKSN>MYpg2Z{JsIbJ7F$?@mOdRPszG>=o~t>b0>?xoQ5*>C~9ur5}< z!!cZe%&*AAubDH9b3a+#&ga-~T;`PisrXbZPp~)9J6x{8;$Z9Z&}~{9Yn>8@$3_4F z=7zYfH0BASXMK9^;L67F!9I^WS+X*#zL6k&QbzZ>D6>WAlji~nzbi5f;|mHQ7PP*W zshZ)^P8|NfdpSg=F%SmaQ~m#@@w;vy!W4=MR??yr)6YSC7SGDC`qs71TfHYB>(CH{ zr+VC9e9T{r))%RIJ#{fW>J`ea?{Qu48$T6?X(+6Zr} z8FHA9&z)<#ifA0-IL;(Ny04(^+=jU&tNWwWv5AsRH!h27Mp>MHclX2V@hoYq?zhUsb1pa3iqgkVx)^*f8#UzJr@`_euNU=u`{?H*R!o$xHmT_JgWvBMEJu#*j5b>2< zt3f*{yvF1B6W^iP6UV&o9PmJb9iEKEfUib?-gI6!d4zicev4Cv^CxV%31(~z*dy9G z5nTkDiP9z6?+&lQe-t*SylkTj;ilCMSb;@6cE8lNr6FU|lQuzq=<7x@l`HByam%?q zNcAk&%69KEN9aR#q%^1+pv5kr%T`16(%HfeNapv)CJ#I=S9~@RoEk!Qp%-i@Z=*|B zFW!*x?@QF7XI9Dm)U@y+auxF;6d`=5uzgIQsM94L*;->n-T5T|RH=nL56^1sca6WQ z;LLFj?ypKsy2hfR9>72y>Laixld7qb;!sjpTO*`c1`|P(Ed&NP;kXta`P8#8@)o## z@^gz5A6<^=9%^Iox0DjA9VbQv$w;d*htJ)Np9H+218Z1F$mbgJS_vUaVJXF8zHbBJ zL9CHH7B5q^z0A87Is8Vr@NZM|v#fg@rN;HjWhxA`B?wk&Yi^5~J6X{e|ACmaK(G{w z@9-l4Ta3d~iA}QAp$n0SRnI+rB_UisM1BevN~78-8;1 z)A5}cYyNrCkUh$XdlPz>_M1FXa{R3==_t=RTo|3m6~!xweoC^?#&~vWsH+!Mv8K2; ze|X|`E7B?mK|2L;8^aR;ASIY|-hVFOT+rGVa-*7u!0InX$f zWNhohD+VAKHUkrR$enFc$@f&~Zf+wAoja&TN(|ChM#^OZC?q31e77wTx7m{^opr_B zxtXQf^|Yl}bYoCOHUr!hk=^?$C%Wa*-4?=&-AKir05yd5u4lUjI=%e9UiB{XLJo&x zF}j$qZkyNA2}X!X_b5WPEYIUV;0H8g>(z>-wAkDH{2H3Y&uM!E_u}|t2k*82Y2?C!&;Rr*3PTa}&suKuh3OeKjHra>MQa3PtQ!f(A0rRwgF8ivTJX08Ne9d75l z=BxH59`l9>O6(@;m{uRxc<>$G!dSAql|@{yvAJZn|79#k?=bLF<%}!b-I1=Tk$UfP z72Ncq8t1;u2B@U5+B#K%NqAgT@OP^#r!p@G$@xce1*5J zx04mOjr5t#HjE0M)xA};V)ecw!PUk36ee%CB$dGni?ovk{pk8p9qGbtYK_7j4$GO7 z4TC&eWqe-`ZB&rBrUIF^1NS!8AMvP092fJ<3i)-rX%JlJye9Xaa?CH$+eoJI>u>D^ zd*=-Sx^*jXThu>PW*!}aG&|_5z;4HZMgI2z@{`Z$*ylV@D${8{!SKEecjoM(+&CiQbqV?}ZeZiFL*5p7T zmXBndyEU&P-2_2%c`s<%$xyXj{GPP6J7!}RRV3z1V23&0lc{oA{al$)9NH`YXG^-7^-pUJzOfSBhp3|AW1^ zj>>B9+D5kss3?em3MfcRNGb@3q$rZoA)!c@BAqJIA{~O1bf+}jh#)21tbKXDBIAj0gVBlh{U(USdHRqS_3?%K&<4Tfdx_)Gj>h-gVadz5P)79VS zepxk}xz}=_Lw$UPz{ior5j}T<9h0W%fXNghwLY@wKOWxB#X2D7<1Dppu{!uAPiLo9 znms+qqKmy96QO6B)nRZBZcqkg`Zp3G#CkoCkTWlo^CR&Qt8|0_b_obzak3PGcCSF& zt*0EfVxzb-hYxzK$kyJqwpq5KSG-35jxbQvfreuwnryli?F5lnvBJ;={H^yRIqxtH z+W2G#!?ZV8;;1!`O`gp%J5%{-{}uY=Y==#A;wukgb~Y!Y1-lG8lPTnqqhIAf`;o10_-mW5e7rrvk0HA@vn}FquR?_WPDwIE zSv%Fe<>;j93ofh0e{dbQa4gYi5n%{>W7(xke<#;N$N7Bu z*Oc9aXz*qU9;Yn1;PEB%C*>I=oloX(q}mig@qD6FyTd7#Dnn_UDOW4qP=G3&$#lmn zKi6BK`NCk`y`-~T=Cv$6lDyPf=#-=CoaPs0$$KT+16fN*X!R9Z`X)b?T6@JEe=nmU zWGGa0Ju8V{5Qk4Sf6po21LcxThntsry3`KC;*o|l119DK}o z%8BEz;fJG}fD?Od z+SCBbJPr$z!*2wvw2G94hYkZprQa2D~}_FdQd1%-7NP*?{e8Xn>wVz`n?&2$h3 z@1X)iW>d4{G<^d{Ce4+D+!?dx$i5Sz$Nuc7A!mt*>hOqS07GzV6h9d`tH;*Z7x3E} z@^ePE$lv(&e|!_Xs2j%WC=>f|ayCI7BSmp~Vw*Z^?a*M?SEYtA{}b#V+OoAzKxju? zz!_#We8bR+*9EU5Q8Mtfro(Mc<6gp3B5w@4#@xxB4yI+O_$(BS5^Ro#VqSP2ooqn# ztK(|da@Ap$oAm*)zP(5F($o71@SKB;- zIFsFO!H5l=1LzovZiZ&3IOGSzPC>fxZ=ON^;~rJMR>knOqI&CUE8QN0`4yL%z|(af z))P0S1dF~w2Grb`?OgB-4#+%uUTP-cHtBlw6+6?%4YMC}d5Sk$>l@k@ccZbuWWZwI zod<7m*dI+us5?IAtk_;C)#*-GIfgHnrz<%hG?*r? zk)WYc>l^u@P^Wa`EQyD{P=*}zKp3kfcYdB>Qn=uJ zc!LG5eB{H@cee}{I1%F4tic?qF303O7`OuW{FeJ*0X!Mlzt0<)BsS^$?3w(h6`>=f zt;;V{-X$m(f4;jyfbwjMc^W>wd!x1<+|muY@)T(!gW*|S43Mi-Ww|R{g#L*(t6fUh zcX2S4PxiYN+)k0D*#yah?-N`275W44zhu*P8#WajIL#n`)3kJ+)Aq9`odhxDq3NF^ zgrm117)(f`pSTAL-MhT32pF9HdBG7OnYX8`XumOj?+q2}&!O_7`^4=rQQ|u_jtP$u+E~p_O$Ziros4$YfVwC-F)1ld zolPPJc|T33&6=Q`s&nzyi^I#i>m%+1SJSNy9XixrX8Xu?JXop9kUSN_Qo;@vK&f;A z!AG9G6ZzCqYSw9OPKDcMD*GgppQic52l|)%bBxQIQ^XaIQ+-OnQ68&&`z`?7Cu-`k z0OP)7sSU6EJ=Si4N~9d}l}hLXMS!LuIez3)hyY|o=u*&2Dq7gNUZpjv0|5!naTWUx zpJBE2fS7JW=k=G6q}&|7^zxGVQ)l(l-K94d>`S9DMo;k)LzrH_O+UzRr2M+0J*c&M02FkOqdG373k&0!V#wkg**=pUvKZgt<~AaM=gAG&}E~C4;PwE z-nW3oCxx#+b6>O{;9YGpo9`K|m97KoFP$N`rrd{(oZOElo}a9XmR98~RlJnPCh`Ld z&=A5*JRFnHE_wcPSd0^2n(K*fvq4J8v&47l1-`oSQ1-Cjm>+3Ysi>i1mSO*^Z=i6P z^%`=OYKNYy9AXHItvj=KSasodtit|mga;Axba>!1gxw};Nb-%SBXNhOVVj?((0J>!a=766US0NBl-v!ZlNQYnN#_Z^sHQm46cMVx zA*bm)73+TgbM@Dxr(rxc;cuBsrYLQ9zSJf>9DRRR8oU8x1`rsfpjWqMZR=l z?aP%z)^go(CN~{FUo*KNSpLOvuJ<8#kb}tD+z=hF^+Pz z`4}A%^tK49tug(?A7!~w7{jk4m}E_<$g4C5j?x(=(Vh*M=e4Sr%HZU+oa&(Z=bMu6x$}70Fc(PXq%23HC&dX*o3onGE^=r%{i$tHme#wJa&=owj zy640kV=L1gZruS2lhF91@hQ&XTtnTN+1;(xuaN}DGQ{U|^jf0KCnG2K^Tk4*mM|lg z73m#I5yO@IK$VwUAd))!a~5iREJf}Z3k7sHkxi68RQx$toSH%@)1wv+OuE(Uw~CvO zY7E~!DTDL}sKTeOcq~<=^gmU^VaNiRmC_^BgI*kSAD%dE?CIGm29_`VqZi>>trd@5(>F*&23&Aco3on<91nJ$h1DT>=D}So!){G4)ftyFzVy ziTX-&Sl*Bm9D?b{(iblC_RRa;HNn+Y77>cVE*|Uem;D+p9{)K(Azr4w>KIF>zRV}@ zx8#jwU-I@(IGcagqPG+@z^or+5V=Fv!6Ql{FXL-jv{hMj8{Ek2Q$+Q)h*#?N{oC@*y7a=Cj-u zM;~pi5UZ>Vkh7b$nU!p-wh7J)mLIBcoHUg~lcr}L2q7DqclET%H^2r zmwGsD|{()xVZ2^?l9k{Mr4l|_H{lC99ao}ygpHP%cz z%$DzuOJrrzOF!a+7Db$)Kg60w7W3%dNYB=6q9Ce|-o6kJBLtOy<8}U2Yb?W~j55(! z!`XL*>(rt2V*|f(jc_UKaa2szv3ZLpN3UT-c?~{lcAV@a9iCU?3T+^2oF$XXm<;?9 z_@qiG4K)!beE0&dWM?gDp~BxnWgXDhJm~())k+@DV$kAMrHYT!ZO zV|c<{(*as1@mxq=3O*&@O14jHHQ4THrE}jiOw}QpKrbV+-q7IG{!wDDQ}om`U$8m! zT6)NYa~kr;lWT8VEX3dtd0jsxzk#le)>$2y*v0JE7Ie*Hw{FYIo$BG2__~>Oc2e4U z$@N5j-~}%O-=+&ni9vU41Zn6MDC;{n&-^H>o7cwB2t}q(X&EPrhWx-kPJ9Zq2Vx7arFIIR!f26Ay3U=#bz>HvTzw3ZG*AUH;wdk{O)zee; z0c8?3?L;X9~Qa8^(?=+L_uahlTm28KWZX#Y1e)$4Kfb4hRcNYfC{M; zpLW3ma5OdaETNce^k+<>R=7Zc`1Wn=HStvmKnui7ndc4R;C27un5U{acB2)7F1Y4* zw%?+*z3#Y35Wx-BYfHEcfN5c684k3UM~5+&g>Wy&gF3tw|nurYH34OYg4 zP}R}mP2n?yUAZj$JzIe|VKIn@Y|3710n^#5#()6D1XzF7I~V_WtN;QiJ>ZSionKO; zVabxHHS^seE?fteKRwArWr&1cIF9;oZDHZru|U?aMjvb*D@5nY{U`}VT!9t%O)KNX zD}a-{k~^%3xRBMree9}?+TV-Pfk86Gy>a+>;)ZXdcOm{E8>VWVrc6Imss;Qo;4vLf zcu=SlJcF{1C+#nuL-%1tk6@R_H2~28s#ECPcuI$1dreHJ|M}1Wl_6RY@Tq0 zxEbJye-lEsC4C=D#Rfg%P1TUxckn{b>QlKUZUKo_5|;%YrWcTwYSc} z7Y%|CEB-cs^aye8C+@jz-+VU&?PCyhn;c5II_qEVwFx=@3|SuhUzX>4(hp;-^v2-4 zx|`MEu*efcujP+KB;_z9`;}yX^lcD6%16zi*Bk_~E8>2W3WrS*ob#`36EJU|4HtW# zq^AVGI226Ssrhgnd#GF(E3(gBuB^ zD4BDfy$CZlw8qq~vwiBcC5l;@Jy+xBqbS7gs)MyQer zIaAU|RnN)a^o}F5X1!a54c_F7IwrH>vgIC4=j)wZ?Na2ADimaf1UEJ4MW&2Wrw{m92l{YYTrUU6c*w+}(yC`cYoN*FcMMcil6eLeTZ*_`SFh2r}1M zYtwFVMPxm2B3}D?(6bSm#QibXju4@rRXTp^hvPG+FdUO323YBX{DSHTD)QkP4`V{W8#1&u_R*>9y zq{|EZ1>4)7+{wqrLp4KC7&LGCMLJsAhMBIkcZNoaRF+sGD5u@rvzhm5yby8}@vjq2 zdB#SH`;h`DyGO51^Bf7uNaH+UywKKi;O3?`qiV&cJiX?IoH6I?u2e;YH^DTiEQj^~ zp>}CuYfMuWKSDX`--mS_6K)P$E5EmJR)P5TU7KS+@ag_NpsY;cG_u?Ksif>Y?EPF7B*XzkGL# z|6SK-P1Tj~vF3<@cE|Lva*1mWI~TdXEFLP(9=_f_nc+?Y8IzFa`i~1pz1a(%oL__) z298?Mx)h?({tlY37D730?6tPxUc+wNxtCRGZs<(96R~bcgWs=7)%WQB(SDux10#*r zai}k-?$_2v25s9D58RHHHbE9TesR1UtKWCWG95{6ubsJciT2~O7@-*g1Wy5u4JtYC zlvLE!mv^;inwljeIEe?cn}-h&ob~H}W285w0MR(&t2WtpoHoaKZd}UZMi6r4SK8mI zA3(x8I$eXove_aOkmR*Xv47;)Sjbb*!`T0dap&vRFI^n6iFVwLlR8+F5U_dRl-etO7MS>FQ;wA()*Ttv7h%GcN%S0q#tS>j{#2NC=6)*f{&r zR4B5SHGfs0am08Fij1Hd>g>o>rTla{>uV$Lh>O^A@#t`f+5?Ufvx`)0%`kF1Y-D2w zzJV>0M9bN^1|PVjtCx0jnE_FhLv*SP9euCkG5PFLtPkW89}@=L8YY5CcUguo%~Z1U zsWVy>(0`}s(4RS=K}6U|cH!M&{5|3a>y-IU9UHgZQu1Q7^HK8Pjb}DuA3`s8kJ0+-E$M^7=F^IzFIyNbC7tKCCc~R{S zl2D$erl+Sjzpt5_wF_r8p~#9s;>kT6N;Tzh4Z0U(p^>xJw;KBLWQ*jF(aV&@RM+5S zDn#1knayg@s}u*__ij98-V8B18tErx#B1Swl)>-bMjpujvVPNaUOtL)Mm`G5wyHn$ zr6A6#O&nz68$Jykpkcm2K!3Y99&Rdcx@EGcA$cj+LcmioR}nt+h21yK+t-?G-OWCD zyi%KduwZ9-TAElxZd9>k z4$Gi@6&E0HqP^boMiFeLUdF09f@{Y8k+CEALlNSm%{|*fhcP>Ah0iNyuWOP5S#{;2 zn^l%Uwft!io&5=3>w;t~h zdRn4#*MSJ0k!#Dpnv-+PkZxS+s{FtL=(!pjooaYyl zhhHhuQ8-+idKcreYLnpGS%PNA7|me2PMb;jr)bl;U*3FUeJNP+XhHC+;?Eo=sHKSF z<>?OcXP0$He53qmMwtEf02mmv6-V=W%QySC%rr|S-HgmSlQb+%QyHzxmryZ}j8!WH zui4CHJoXdS^-dX%Nwlz=AQ&+?>Y{dy_>!`Jm+s7)a#fzA#k?_nU#M!w;?RqAUVV+Z zGYj_Wt4gETrJVXty#3YPw>4$wNrt;c-doty>xT)s3INz~%*?EsI=!Y=iwYJ+*`nb2 zj~iWt7@79oz?Jkj>E^#%6ciq$A%$iX)?P2?T6RtN?dRjNj~`>%8i_mGNw+fMxZx8M zy)4bgcD~mDYi8w%Q#2p(at@Xz!KTQB(`H^~Q}T)9omA(LxMgX*f(Z%s^BlwBTg3K@ z7clD#U73_eod@~fU7e}Mv0N6)7N2MAjglYeZ<@Keeyn_KG-)^(5=2v~D8s=8PpS5z z##OYF`})~{wjqrpBz8AZBl&?TC&*OSO+xRYSGJYt*plVQh2|%RbB^8uB+JHoHpADX zRH8f(>Gv1Pll&otDyhJl8C1LZo3Pe@RkUwyb{rsT_kD2top-_vQ5SWJEd7Y~A%F@@ znz4`0FOHYCjbK|8mk4VYqZf41wZd~lWoq39zLFbj!DhKfjwe6i+(~hqK{akl?22!?d`JI1r;^hX)rv?~wCip(}g-5p6Du)Ek{i@vctjZ;L#tb$aC zyvOjZ7P;q?YxqNc5I5fl%7;^|#f8N_L{CNN4TN9JwR@{cJj42+ffdQ(#+U)7a7#69 zE0r%KLqp@1fxXncnVTn?mxI#|7SV?%PyFX1GVU#+*gs!HVc<3f&i{rO8P6)g1Cp3C zI9*fW16jdq(pCihPG1{*mfKB)ce7GX>;pGT!<=Sf*;%@rBC|i9zb$sV4)FU1kw-?O zc%0f#V<}%UaB}N`xc=O5zPMYy1A|tiv?SSUoJ-3fhCJhH$JeJ(4HX&o2~EZ z+Elp9rz+4)g{QN&IVaiW9RRM3?qKzwp0@@VkROK|ejh*hwe;?Ud}|9iQ*z9U?ZwTl z{Q(dO_S^6D-9p~UQp!+M2h0#7Vu$tVwN=|L*H^CZW{sfdBBAD56rJ@QKXjrM)%0$D zY|FGs_(h5okLX^k>EC``m>`kNu@%)OjJ`pZ?B{}JGXH4lZfwIX1vO~Gd#z~6QdH3z%2EBqo(Z8Z6{`c zt)1W3uW0U}%0;TNSx6UuFDFJVf(pK0=gT5iP}KVN*yYU;s9Q{1f4-CzH<`BHSR-kO zVE^T1D2@=luba!QqP{2LYY7c9bDrj&`+2TM_s+G}KR?$X92zv_HOR;@7K!^)Zg7;f z-pxiyLXyGOpv~xIRHa|PO{ua1&Ai$lCK2V=B)0cUl?Gd=Us zWOM!Q>Ggy9rwn9}660I9}sGSMyl6_i{$(78y9r%*{(`L)AcFJa{ z?^N*kAXJqH?d!Sr*(^!uJj0OyJDkG|WknymB&6kJ95Yz!%{kcGAt(9#WVp#s(oV9y z;Fr)pKfKY`k{{@#*_qcaRdVfi_>#)I2}V%s`jG!bDfoNTXxh@PtIfOy+KT z-65nbdmpfG+cS^90@EM`HPUsCq|rp$deu4d8kE3!BZVDT$`T`Oq{Mz`fY>~oWtR5V-BY+GhX z8AudNOu7hRx_EvSN~Xu>ecGdy{gHutOktYx?&6yjh$#oY7eExV%>4pj%K0{S8>C3r z-W!OO{-I)arWSN9)JfN90R-B%?`4Q@laAj!_3Sq%mLwa>+Nz1=MNhf(;fA?FO)w4 zo}NBhH?B#4=zwk$?`QmtYYhpz90Rvu;o_y=dn`NWg|BO$_jPf<*w%H zjEnXyP4e{R8CbVo9@^S4X^)@9C)Vg7mH%D}z`s!oo~v#X#c0vXx7BpjhuS5Xsn=i1T*lk0dd~A7xl^8l@;s{!~M;zS?nsxKw1f&DgS`S5O(*T1&hWsghUvF@00&H;>0ZScX0~sTW^I3SrMO-FggRC znws>bPJVEQ_wC0v3%WBa+bi@bHU>1ihi`UhPp{A{4^xd|y)VMdJIQ7YSMi$T{=foU zr>Ir%)whZ3VN`vfr654c2rlFannhkFX-=mrTEpK8_Ph=_n57p~C_GZyK=nZVg)G!z zP^_=4zwTN#^bOt3q8k(Qqu?)RD*igbIcB6IBbenG>tpl3pko36%QB9b!~u(^w&>(3 zT;2I?Wpi~J6P=G?Mn;hea)29PZJo~Yqn^Qj`dVlI$d0th3g~>D;f+4x354WKa?7se zHo{SX+3|I{CIHx1HZ8sp)HM~Txy-=WBY}~~sA8&kIRu`cD#p)ke!g!cahmVq*u()d zpI$|TDUIUJ31QMNGC+Jp#z3p~6Zvuvs1e{c1B&OL-eyp7mZ*$ir3E_*EumFhhXJQ~ z8j5NB;$%81?m9K=Z3>aZL)+xs!Fw2p0C3demWMZxSTF z*&g4B|5_^if^13htE*PB1O^pI%1DJAO-LACq-}F_#3n^49*U79Rz^~W=K$>+VX33^ z<3c}Hf>cCNVeUWITBHCvlU_pgkB&$vysi4xk(u)|9Ep|kmU;VFOKFj7yWzT0&xfS|JkIB{9JJ}Xh;+E^ z+a}Wk=JS1#$xr(}xnv8VQEl&{S9+w}l0PpVHvmB03BK(mb2Z?Z$Yi$v8PF(0$gRpR z|MShp)LJLi-=Dw#xHD~h*JS*C)WvsXQ|VTCl|enUo+LL~y5^!H#uB&tZ{AreiW%yx z$NNgRL&;yxFT7?lK$_o#qa+^)BqAZHN*Wh5kD#x7WFv%dop7eUE&9^F%asLPYGa#g zEnBszL+LLp$lDmT=8%|}l$SC@>Z9iCB3nk{nyeM-uDP$1t-12Z$57_YKCveEhXUj6 zh_ijsOyqoH8q%WelDbV0x|(~ zYKkTS`v=yId~fu!^yS|W13C@~`xU`M5G{*GZ5ypWM~FK%QBG4XwF$Q(Q}?|~3&e*Y zff#yo)$Dc>)!?eEbV}b;K#aHy^CMK)MQ_@s!^Py6MFV-mZ^cPTitsH{rph+{6cgvFqxSRI-`G3$+5hy|Q;zaGE(gu^mDQg9qYf~| zxq@g^s2#`7(y(wqdgS>BLiW#GO7KD%C|z%z@<029`-o4Z$|Txn3%6{O-=e!wHrpmP zM!g_wh_Byb>#DnzcAJESbh#VI~=!Z=-8s~JM7W;a!9EVtLE^nJ9m~k=-UZW zCkFC#3aP1SH?~CVUYZ=A<{2CYnB)Ls-PR8R(o^jmPr z^Pk-d&TADwLMZQg92c3O>y!$|3B;@wm;h(0NSH7iv2CwsAMq9lg0YGa4^~eD7lVgE zhm0m_$#rMvi!Zvbu_ygPk41%4YEKr0?cr$W&ZlCNX$ynY_kD;5{_chmViF#aQEe~Ri8qkk%Wv=~wJfxh3Wd?)?1iQwvV(&IrX{sEIm z-<{I%+*7!Mm4>jEiibI_{rN2f^!cIl`GPX=zRWfm@15pYnAZdA^I8BJ#_`r7KJ^V> z`XkWYkr+#`$j3y^zxg6vrRdf=9un9yb$lI2Jto#V6iRTg7is@NU^(#(R*GZ_J>+?ZM=B)>r<2O1y2=Qwr(rQ!qK{*3f;V(tjaH51Vb|5Nm zu2t*Aoj>V!w%<{JV1efXxA}x$nd?_Es9h7`!=u#n-+>?p=b}l}Ia?^yemW`s0r$tz z-zN>!Fb~YQ|Ec}j+t4xwFb9NVMv6838_@z1;O#}M3q>d4Kw$a!k!3gm8xiJFFLN*+ zN$>4G{yR2BkDAoHpE-$2q}ez)i~rQ&|CQhJ`NR)V_6Jr00(l4?X@w@bN4~TXBgx)M zgvpuq9{Wiw1LSz{pZ|!Em@Q;befOIPz2VdMa%SfCoAGIq@VD_C8_wt0Q0f`hlwP8xIr@ynPBg4!P*x(wUDl;1T0-u1k<=+k-p9 zt66Wu@_B|GaTP$M!{E^$3Z+X1WB-ly6Gk(Lbf+kP1APJhQQSw1kw1{? z@nb1?JI`DFZ}e1%G}1yymen@#CE*yX8V4>H5inJ2ox`{P6k81G&A^1r?E=N*Af=CC$UP-`JQSme%JJO`Y! z3409xw2%{IB@X)ZXR?$DF18kZR)P!Y#2|z}ACBrCaq^Sva@Z>e0gNLIn5ERD!zNI& zg5YLeX)-;7v?>`O^}jJ>N+IS!ykYhp3p654{&eFb(&}@mh1pS zH)lVCNRP++kf**^`xEYUQdfeqgoQL>M$z*jAZDt~SNnK>$eE9bE?G!ZneqCYZQT<^ z-wScYq1S;HJwk2%xE_{J0$1l-XYReAt2n$?xxr}qBOsi{b-t18@3rjKY6Dy}KxVAq zfubyghe(M-@wosKQn@icllP6)2@$ghk?5dOUMJDt*iw5QdA0~_3Qc+l0T8Cj?lm0< zgm;D=X?XDCeExwIg2?Znp7yuEp0Gz352AFBQM~dsJu+c|IYa_!&cjr*bkol~Q3h@j z!p1JW#UHPDjBwS$|D`bgO{9DeEUblKX2g{*BE1j(AD!;K>^qWmsOX2OYBnjeVdXFZ zcqk;TW%y4?iQF{JCRwGw2|nzVFjgLiZ41d(<$*RD;(IMeBoLkz_6zTRrZx^LBdS$a zLmZg#zik{y@+m-_#O(J@+?#L?q8uFG05g6?c+NfSdq^)FCZ*`|pW1l=VJxW#Psj}W zZ)NtaEes888`Ir47SQ=5WSJfM9E8DK-rkpS`{_{TG`#to(NVVB3_d45wp$ zoIh5CpQk?N$dBp*xTh(|#@Svx_v**SfjNRO(-JU+??u$B5$gQ)t|(+I@4b$BAgpdV zcO2J#-nJs7>BzQWNXfmwu`~7-Gz6)jdDhh~_~ZO(A%y0Eg1@vYsFX!EZdsKF$bY|W z9N~9He&tJh639b+??M75cfIR55fx!0tnj_!t-0@H%3xn0)W_>xOqMl&<8$qaSSH8| zXdOyRa5?^6x>h0`A81{E?N^Y1Y~1)83jle1+c*#$1n?A3w*DSX2w~~og#;|$zk=gW z!O?+f70LA+`w-mWNP4#hNPbRySE45|8b;qMdp*nZ#P$y5-aqUA_$KQ^S$RSp8`3L8 zD^uXh=bG!gh3-Gt0g!#ALxk5og(|fZ2%JZM4|J-9v>BZBdAZl#pmP7-o>fnGB#E~~ z@eLI|P(&~T`dD1UHgV5Mxd;ybIWFw8NDo4PokK>qztip_^6@0xBawYC>GzJ&Aku>{ z@^ZRjMmWH|t0KMix?sk6SjCSfLlVS8Z{53h?*mEp!$04thrqk69NE>*{m=K5Bv?=l z_ynAHS3{jM4>K1Dkl9VeCVyz6MutF*1$ouy@uZG>WBB%u2UKReCf|;@2Bm);V#MEI ztU_>Fk5#qpH3C0hfXMB_;T@d8@3C6MYW-$N|AEzvK%+jCJj-Knk~)r%-Xf;MYY;)e zQ2b#JC-u<|xpWsPocCFqees!1~3_Xaz-^dH%Cr$Jd$eR&dck_GvhnjV%Z{ZtyJE{(Gr;=t#k~6 zN&>vt*hKxYb0pY6S}S9>PtbLlAeQCh_&MH-bOMk6*oTGu9)5Vze3DRp>cd0&b_P`7 z$=kB-$ba=yoKJ2g(COKGp#3nkZLvP+xQ}JA*MR%yA0j_kB!aD^_d?uXaWgXBBLIv{ z!t<>J@GYwgrMSogK^g)wv1P(jhizgz$B6v$w# z4jyF47w)@^j4fsbI(3Yn6Vj|~@9$J{wAzvCJ!WjK*^BTj$_g^D`{;0X@8f3>FhbCk=u}#Jnz~2qXVBPe>@Q@1ARf%uZk$ zX4Sy^tm1K~^<4g|pMQw_z#|6(kh%-TzeoizS^gT8&b^(722lAHOu>bP|P<*k{$Z~eQ)|8DWWxA-62Vl(9!<-F)!rrotd)Hw@Yx1B{X%woFB zm7(;!W*(2YbGP<<3Q->c2T#jakb#d!ttFo?1QI&1d7eqG>vjqpB}iVaH7;|Dh) zf%VgmDxhpJOrcQjefy{o-MU51a$Wm&LpU3qKs%vk3(bV<(2)^IGZE_I>kF zLW(UFr(46`MEi28e`GY`YvTCnAz~7t8XPn!2Qr z=gzobzqqKk{acls|rpVo6C4+T2s-C50~CK&GX%NNvYC&P_0S87gc24(d1izBO|&cyoe2uJ+( zA__&rXRIO<+a8YEoj1E^5El6DV{h@8DmFg5@VSoOaH*7b-s;GIPh#}kjj@#a*J&Lj zoYHubQP7`i&)ZYO$NQ!FM2D>S#jYB@&dbQ8E_hdV%1K9lzWYuwIOG74Y8UGy;(`A4 z4Zpg6$bXecg9o?$Uf%cT;{E0afm*~*oNLuT^FO~326+v<(FIaDKFa^w*UvG6&zmD0 zclXb&`}?oQY=i4xVkWWb@qd}lK?~@vCR9t{Sr^WUD0e`V&s3h4LB<$qBDJs~)5Gd~)n zu@&P&(iubF*wnje(kX;!z$qliy>RA6`ET_mkNo+kc-E-lSf6c7#AS4APk$C~nY(}J6a3z~IZ1TpgbN;G;qr|63Ag)j4Tqgl)_Rf;>_kbx znToogl4S?{YZ8S+R%#`qFL>LNqMiDeu4?=8S%uqt_Usr7l#Zf}FwVWSKKLlf^_1!b z$xCe_`zx&C_K(=jW>_qiuP36=t69^cD(JoEy)sIU zx#GjSP_+M=^w}#88%q{I)|teZRhFCbbq=_D4H_>Ne!w~zDMPuF1Jq6H&lnSWve$!MHr3>L&6ag)6gcZtgmf1 z$P;Kn@38Mq@?)mC6&yHC%D%jJ;d?Wxb{>pDERm$&p1*^aj-TmxinmzyRZ7)3r^fE# z&IA`qEW)Iq@3Co+%`J40oD^|uPS*iR?(v}M7#D(DM!?baxY_bOv0nUCtyaUe?YTg! zVcW^KuU^yCz8^D5x4Nw!<+#>&3B55|IJOfvN}W@39b1-xX5n2U3(CRbQo_>Z#@>ml zNYW-E*yJ^)v-0YcC(U7NeJ4VS9U!k$boBR@W1NhZ#9@Y452_ALgTFFQLz2c&9dB&h z(rWDaK;Rj+ssiVbMF&$h>#)rz5syy#H9|F&SC5*x9lL$ci=_81O+=Wjsjxgf&A;8( zf~RgTuW(%cj6!Zxq>@Z5cb2YUts>LN?t--uK_8r1*>uy_&z<18 zl-~f4FVFMsOhR{>`xkyukPIs5(~Zb)=9!IusTakKe~#x;X*baS zMri;FU~cQ-T=v~}hW&)nyW{``kmSu@hU~VYA;Hd_r+E7d8O_JwCEA8TWo|U5G_9NRGC2%?;Dk!{g ziDn|N2w@#K`#`{MIa7_=~`M!gfOQJC3>M}aQ*`1CNR<$)u>@p{@TyE0fwanxcKun28vv&f1RoTe4s(_aBYN=NinOcrzZN#vEzCP<+m= zkjN|~M(APMZ5270yYe$U)^xBs7Ryumr2p~ppC?kr?g<-BayGmoali~!u2&|-JD;E5 zZS9`&2ON$B$R;WUF5IOQRT@2|1m4}TPdh?sEH z2#|dlbgSsi*KIGqJIXHs5runOJ6~HmK5(?WN{lcqxdck1%ftw3BdJ86*JYCSMC*nd z@qq0IF-2AGrz!{O+*B>T88%4bW+O} zyTw#%mE-1eBTL6&mNLHyxZjtWuZ(t{U4MIkJRY+djS*W!VVuJ4W>WIjq(Q^rx9mdL zARgGw_>AP9s|+6H_`oVmVn3I2xG<^Y-Yb@cCmSpac|}fT7?Po$Rp#T98z5$9Dr(be z85TY*HLkNb3D zm{}B>vF4dmf=FcYfY|sUO7RumC4)r3OW;L&S*fWaQki?~+vS`);NjqFWo$Ahi3of%9}F zjy%EUXv^iEJA5qHd#Q#=PixrR&Dvs1K@C|A=yYGl!aY_}wAOFb0bkcxANI0hE*=Xo zm`(_liZH9NB{3`eLh?f8%zXAcf{cmX zcvtk%i!n3I>5I2!{Pol77Om?a!fdbvUD+OXuD<+L}#05!(6rto+%gCOD@$XJc z_c4&I-f~h1f+1wkY8|VsUhP&hD~|#hr{%&lc1*2r%!Pe5^Wj`hZTDHtqA%Ju*I}`D za9aVc{P#Lts}s+{9?-l6n)m&$8xm4IBW!F@3Jp7$9`*RSXKNTClPt2vvl+z`;nVeW z(R0NX<@KM!n3|8SID@LIf6!p=$(zhv#%M-nU@%Cb(i=d9;8x6eNM;Qx7gf>Qi#Ay0Dl zY-VXxr zHRpP6Pu)mJ&u_ogXN7$m_qhDV(4tc)VvzJ$ute$mCah}LJOg7ielp6Q*}e)5W^_i% z=`{UkU-CPo2D~R%do)`@zO;lYt2)ENwQOB_i+v&`M-HWE5T&3i zC?`IX;_;C3OrlBkd!977S1s6>jWXUSO8!ABrP!Hd{z;UPq52elj*bZW5N4{e-zX~* zNB>^1kMcu`sHGO^{Mu7E5Hz;VLa%}rdxZITfWPkj+?yVa#)79)jPb`EhYZs)+OK~7 z5SY%eIv7yhaJnrC#OIZ#FJ8p{zyj11oP4-D6C>B@>sNEv{T%1VZ9R#rGBS51 z&RROs{+Hac8}apSrKU3&{Y z7LC4`EjE^T4bs2ka+3!U`8{u!Tb@bj`mm3HEv^Olu)Uq!J-lx zwQ^%Q3YB{r0GfiN`!qq_x7~C?eia^L=gQ*12-@n@*)Wj0_N&`qW!7gZso$gV4jXF< z?d3dQh2KR}#gcPb_!;@~I5}qHM#)%!csnA?*G8N%m-_Ap>L_d-X6PJvef~ZA>0#z% z`xZ`)u(l`%!Wfn4B8|A1DzGWL7%1(MkuVh z;AEE$V)xeaqaO~L&{4*mJh2*Va)qI`t5lP!lJHZEgQs5&Shz2BqaD|nR&Mtt#t&Z^ zTYTAz8_&b4z^%(F=z0)cy~eP)&0E0lsc;q4WkpnC&7^Sp8IBSciKfB4xYEp+swuL4 zJ%0hK{c0s~rc24tAHJ9`<8^38lqTxEZ_+ZO4kUG2qMj{ep!TTa_yLtFUWmoqlj#lCv*9sb57eGMIpS%rDBhHhvw9QZ;K!5A;^og=E4shcUWg zs`v-6L+h${V^Bt&_I!%09`zeD>@v}Ig04HM*g59}(?eQEI<_~ruNrH!m)k9uYsgS2 za(b8$%mnL2+0tf|%%omsxt^>CMyct|(*u-)Fa^G>+J*zi=FUjeNA#!>(KPe7##9k0 z-D#W6OD!qS5&8i3q)LaYa*lSz<^-uk;rnE59HRHhpSo3kC#qwHu!dm854C_SM7eX& z;*A+W+_8aAm%Yo$UsBultw2zx|q{0EK#W#>JSz?v@Yw!>uNK@ z8`V#K(||U4328;f$Sof#+PFSBVE*yRfy6NVtRTcm&{gnJ=KBP8_@b>N$bSh?T#EuF z^47ENz1Jugif4|WSj!0za^CmywNLW8#jb!O9IfRv`|4X*U24!`a1u^)ut}k;Iwdwc z$o|zGdUARFe0IU{$9A#Lm38jc(}Wt=1v|IYTH%49cDy}YvPyZCW576XbsK#aIB5!Q z5rbaYHr9S7ms*%xJeS*OS1yg)RnH8}SFw!;l-K`WjR91%jj4;{}l>JD$1hcXsHYkyOe8M~``O1|3%Efk`F# zqfG!7rsBkZGJz?>HW-cZ>HRv(rRC! zpoRt<7bye%6KdQaAjNq(3xwjXfg7=|zRd@4GhQ`A*dwZk%H#Nxpo#|QL=$>%)vZUv z{^E6kDa7f1IDd>vG`{89Hq-TyRHa9rkGc*Y$EQvvTo=Wb++s}2C{QKgG**^=gT^A= zjWm<6R|i!>`f!)#x2lAp)kn}3)M^qa)y(&7v`t^7uW&uR_UYLPLk%RA+Q9-wuG=Ww zMlrr&WaA7iwot$bsY}jbkl-?Msk7km(MQc? zF(Vxl5J4>WwGd7FPz|^JqezZn4TNTfzRqYBi0MNY<7f{}P^2B;Gsq{GhH5(5_QM|A z&rB4io%ulRP_gg2qP((YmqG`aq=SpOXjh(fjFMr3w0}%hLa0W+k+{3)e3QHR^4*9X zFTCBM(KrU^c&enSb2s6Msm}4;)AITgndf#bafn1QXY}{|s;qv!MXfbhL#O1Ext@%8 zeeyQJ2bVmuB*{=m=5Cx1=PjVM)oij{_&@D^XIK7%l^`Nfa^VcfG3$kPE`>TmHr8Za$v3c4$iVV8nz226ijQuLNvFk4}$oY213i4kX$B zgHe27TXfjOw{*CM34IB40Rw44GYB7+|0r@zW0cOn69)f5QP6MSC2m}95Ub7gkoL%UKP?WE|ZeQM-om2&a@izH@|JYuIfx3M&^YUEh6Z`Hm z6&Ypr{+`_ar*}NBSXNx0O!ECAxL~jh`CVD3>0ufaf_K>ww{hc;;RS$elq>IrG{1~@ z@9osE2W&I@{_S3;H{9k7nNrHc@f;XQPpX0$c^`B3V%G;$ zg!-==MtqdM`8{!S&0No^p4mFPw&v?%#bUW(KrvJ1H*nC>VD5>4a`hw*SAv!2@iax9 zk!2PZ{>=W(;^$IV87sM^?uh#C%Ei7X!D`n%_JDgn`dfGui&>mwtzpIr z$P{&(PE~{85YJD%{hE`D0b*;6dHJ|mIVf5PajH} zwr=)qZny{6Z@_2Y%7)@*RuVVnG6?mjBM9DkW50b_0}#hS0W*Zcgok2W;PYw=alUYK za`}9cDROJ_uV9RdS?1{A**mtUY54D2);bk-W-QZi(ZjWLpn!?~FkrZCwx1TRZ9CAV zJmvpWlP2bLvl8f`;H~(q<0{?ZkmU8-(N^#Whz9WeKfu?YG;px9D9@UL%^Aa0`K@aA zdw6i2oDR(+9_<~};?v$`J^+cB=?DE6{PSSQ9vg;Wm24Hx5{hO~CTDglLNObCr2*&62h6Zwh9;0Q|vl -TuOxSK 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 literal 0 HcmV?d00001 diff --git a/docs/images/gateware-rx-only-basic-block-diagram.svg b/docs/images/gateware-rx-only-basic-block-diagram.svg new file mode 100644 index 00000000..bf470a17 --- /dev/null +++ b/docs/images/gateware-rx-only-basic-block-diagram.svg @@ -0,0 +1,4 @@ + + +eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO1d2XLiyFx1MDAxMn3vr3D4vjaaytpr3mjjfaPbu+/ccFxiXHUwMDEwoDabXHUwMDAxL3hi/v1mYVx1MDAxYklIXGKE5W6Pw3SMx9ZSVKky85zMyiz9/WVlZXU46nmrf66selx1MDAwZlW35df67v3qV3v8zutcdTAwMGb8blx1MDAwN0/R8d+D7m2/Or6yOVx1MDAxY/ZcdTAwMDZ//vFHcIdT7baf7vJaXtvrXGZcdTAwMDd43X/x75WVv8c/8Yxfs/deNM/o7ujuql4oVbav6i2v2aSn41vHXHUwMDE3vXSm71WHbqfR8oJTXHUwMDBmeFxcMO1wKTVcdTAwMDFuqKJCTs6O8GyBa4dcYmXwnz3HXHUwMDE5nZy+92vDJl7CXHJzJDFcdTAwMDZcZlx1MDAwM8KUXHUwMDExkyuant9oXHUwMDBl7Wg1OFx1MDAwMlxiMDBaaS745JKnXHUwMDBl/blCJkdcdTAwMDbDfvfaW+u2un3b6/+AZ/9cdTAwMDV9rrjV60a/e9upXHUwMDA119THn+Caut9qXHUwMDFkXHJH45bxIeNcdTAwMDNdnWr/7LnzdOr4rLvwXHUwMDBiXHUwMDFizY43XHUwMDE4RPra7blVf2ifXHUwMDEzkOCo7V1vuzaer/9cdTAwMDV96rttb9tOWOe21ZpcdTAwMWP2OzXPTsPq5TDybZ3a87dFrlx1MDAxZXiebYFcdTAwMGIhqVx1MDAwNFx1MDAxNjzHQLKA89jhg25nLGaUaU6lYkFf/UFcdMVrOG617rZcdTAwMDZe8JxtXHUwMDFm1kOiXHUwMDE3XGbltldzn25cdTAwMDGlXHSRnEtNZfCtLb9zPd3zVrd6XHUwMDFkfMv46D9fk6S53+tcbulcdTAwMTd/XGbd9qj/sOOLm59bN1x1MDAwYkszSrCD4zNcdTAwMDL7pFhMmlx1MDAwNXEkaFBCK0GlXHUwMDExIGLiTIE4nFx1MDAxYk3wZsVcdFxinSTP3CGKMKqe2/mU57g83y8uzyBcdFx1MDAxYSCGZihBoLVms+RcdTAwMTm4UspIQmneXHUwMDAyrVCNIFx1MDAxZoG+OamU5F79bHR0f7R+8qM8gDatLyzQhmhHXHUwMDEzNL7mSaBFVKCBoSAqYTjHh0BQ+nVMoIFSR4OQhlx1MDAxMTS9ilx1MDAwM8RcdTAwMDVaS8dcdTAwMDDFdsBcdTAwMWFyLfM20K6o6X+9QD9sLi7RRlx1MDAxYsJcciiTINCGxsR8XCLQRCptOFx1MDAxNUtZ6OdcdTAwMTOBXHUwMDA0hqSwtv1QqT6sXHUwMDE1Ovvt01x1MDAxMpR33fJN20zGXHUwMDEzkUS33+/er07O/PM1rV3eO14vnVx1MDAxZmx8q+5tsmH52uyvlcvJ7Vx1MDAwZb2H4aLNbq3vXHUwMDE2XHUwMDFh3X3wXG7175detaaborBgd59/S9Fuxlx1MDAwNf6Wj3anjz869qhiM+IoTSlcdTAwMDcpXGZBVI4otnBcdTAwMThii0aAQq3EXHUwMDBi4rRLoV2Q+NGKXHUwMDAwKNBcdDBcdTAwMTWSolxc1HjYdzuDnttHefu3q/JpXHUwMDA2cEJWq/E7eVxmhqzhXHUwMDE0M3XZIKRpXCJcYiyjysnSq4yRaFe01lnIViCMVlxicfjF0tpfXHUwMDFkvzP0+nW3XHUwMDFhmvJ6tzM88lx1MDAxZsdMkUSObrhtv2WfvYw0Vmz5XHL7XHUwMDE0VquebW01/CiGPnoyk1x1MDAwYtp+rVx1MDAxNoa2Kjbq+lx1MDAxZK+/vVxiRnb7fsPvuK3jYFx1MDAwMCtcdP13b4fdXHUwMDFm3uBpXHUwMDA0w/6tXHUwMDE3fkje1otagENFikZcdTAwMWa6ZLChL3Yv5NlGcXR1eDHY+Xa/MF5cdTAwMDPRyuGKXHRBXHUwMDAx/5M6QIAoXHUwMDAzVZKhY0V48ERjXGaUSVwimFx1MDAwMpLoUb0w0Jd2PiloXFzNR4truVx1MDAxNJSjtuokXHUwMDA2XG7hrkxpOUP6r1xmzlbuXGaUh1x1MDAxYn1cdTAwMTVGeeXSjfDvKqVBa3/jiJOu2iolXHUwMDA0XGKegDRcIs3SWDFjXHUwMDE0u8KQzfAo+0Rwclx1MDAxMJ7wySkplSBExWR5XHUwMDFjXHUwMDFi4MBcYt4umTJcdNxcdTAwMTM9NmSvTFx1MDAxOM1cclx1MDAwMzRwXHUwMDE5JFlL7Vx1MDAxOflbQKvmXHUwMDBlmt6vXHUwMDE158fFxVx1MDAxOW2I0FpRkVx1MDAxOFwioFxuZsmzvVFcbkVV/jFcdTAwMDJcYmtXXHUwMDA22Op1/WmCXHUwMDFi/LZcdTAwMTI87PFcdTAwMWaT3//3NfHqmVx1MDAwMvn6u1x1MDAwYjFJXHUwMDBlmouR0sHQ7Vx1MDAwZr/h3PqdXHUwMDA2XHUwMDBlLaDAL+G+J2AkN2c/XHUwMDA2XHUwMDE3Pc/b2W9cdTAwMWPv3m6sb1xmT9ZDPHi13a2NxbHbr/jD8Im6/+DVyvbRRZ7cXG7CXHUwMDFm9l5cdTAwMWJglKEzSIiOPFx1MDAwMVx1MDAwN1VcdTAwMWRpJ/7QNlgnaWxcZlx1MDAxM+K+6nVq80dwdXn0uKtkoXRdO9+/XHUwMDE5kn3dPi2+blx1MDAwNLaThjGBPjrOXHUwMDA2XHUwMDAzqdTX6Fx1MDAwMCV2XHUwMDFmXSnkX2izXHUwMDE4T1x1MDAxOcN4XHUwMDFlitbyNT03pns4wvA5NCb+XHUwMDE05nutSvd+LLRcdTAwMTHCMe77kdd40Yyojtrv3Fx1MDAxZVx1MDAxY/W8qu+2XHUwMDEyvnP6XFyKbb91XHUwMDA37v366UW/w/3e2fre4SWqzsJsXHUwMDA1XHUwMDE5hsOkXHUwMDE4442hYFjUXHUwMDBiseFcdTAwMDWjJUVHXHUwMDAzT6E7YuLxsiC8XHUwMDAw3KpFiPBcdTAwMDThXHUwMDA15Whcbuh1PTVcdTAwMTNYgXy4SoXWaaXy7+Yq7uHixl0xdFx1MDAxOI2BXHUwMDE4KbGPWurpo5PgXHUwMDAy+lwiaNp1KGycU3Dhe/Ho8q7VumxteuKAbO6VOlx1MDAwN98uX1x1MDAxZlx1MDAwNPjWk7DfuNhsr3Xq/Ye19vHPs6uLXHUwMDFjYlx1MDAxNm9cdTAwMWJcXGBcIrxcdTAwMDbyKuKW/lxcU4JcdTAwMGKoh1xiVJJynHItXHUwMDE4TPE29FAo53hcdTAwMTGeXHUwMDAyXHUwMDEydlx1MDAxZV602tpcdTAwMDX7oUSCQm6XXHUwMDE0XHUwMDA0zznq/WGiXHUwMDBibnlxVcbZXHUwMDExmiGVSOJpis6kacCUpnhnyH3Mh6ZlXHUwMDE230BcdTAwMWGfnfOjzfJ2yJj9vqDCXHUwMDFjaJxcdTAwMGUqTPU7n2BCOvuZXHUwMDA3z1xuqCOU9e9cdTAwMDE00s6pWFx1MDAwMqIzVZSg30WQbUpcdTAwMWVXYzT5XHUwMDBlJ1pySdFJMyoplIDgjDZcdTAwMDCRQVwi/lx1MDAxYqlcdTAwMDNF+oz9T1T6e1x1MDAwNnRWklx1MDAwMeGhNalAo5mauZZFiUZcdTAwMDfbXHUwMDE4vtRaVlx1MDAxYdzRb3fNXHUwMDFk3z/c5o/HJ/euvzV42D57PTq/1YpCaX9fN0/uz9tUXHUwMDBlvvPvpHk56vdyaDc9XG6S2u5cdTAwMDKoL7nSKmxcIpZH/fT5SkF9dPdcdTAwMWQhUZfRYlxi9OFiqK+QqCNcdTAwMTEnSqF7XHUwMDFhXHUwMDBm1lx1MDAwMOVcdTAwMGW3qM+ZIFx1MDAwMtl+YFA+UX++iciwpoAsXVCi4lx1MDAwYoHWRsRcdTAwMTdcdTAwMWEmqK9xXlxm1yE37b2sKfw4XylcdTAwMWSVV6pNXHUwMDA04PdcdTAwMDD+c4B3XHUwMDFh/JO7n9OCQrV9bVxu+nrjorB3RnrNi3p95C6zoGCYYCTkvb2QXHUwMDAwzVHruVx1MDAwNqltJkBCXHUwMDA2wFwiLOAzXHUwMDAzYL6KV1x1MDAxNtdwY2zQXFyoJFx1MDAxZl2JlPArJ0ZIXHUwMDAzS2l4XHUwMDFh/NXP21e8tLtdVK39+ulVr/ZjIDtcdTAwMGKxgFT0W858pGhLej9T0Fx1MDAwZoCDXHUwMDAzNiVLakBIXHUwMDA2XHUwMDE2UVx1MDAxNIQ/6+sqVCVNNGNx+OPMQdk3RnPFXHUwMDAxUfJcdTAwMTP+suhGNYPTy1x1MDAwNTNM0UT4k7PXJlx1MDAwMKdNKibpu1xcUn9cdTAwMGaoN1x1MDAwN2pcdTAwMTLW0fNcdTAwMDa75maxt/F4XHRcdTAwMGZcdTAwMTfkYueuoTvFarO0iPpcdTAwMDaZm0xLXGJcdMFcdTAwMTjlrJMqhFx1MDAwNoriYVxipfE4NFx1MDAxN1x1MDAwZbXaayhTRFx1MDAxMpG0aP6pvDOU18+gvIJIVEEqk/zbcNJkLGJlXHUwMDE0slx1MDAwZmreRHlZWFizKu/+2klcdTAwMWXK2/Lqw1x1MDAxNNVcdTAwMWR2e7P0NtLZaSWN9C5cdTAwMWYlLVx1MDAxNvp7m+6t7vXgdHercvyjPLh8yL5ohD84ejFcdTAwMDHhXHUwMDFjSyNlXHUwMDBlaEI1Z6isQqmEqFx1MDAxNFx1MDAwNUdcbirQU+VEUJ1UMiCMg+4sXHUwMDEwyiUg7YXcc6w/xKLRz8X1lkslhVaJi0ZcdTAwMTCOXHUwMDA2TOuttCutXG5nNG9GurW5dbKzUXvY6V+Qy+bjkfx5R4dcdTAwMGIx0q9pzfJz2lx1MDAxMKdra71cdTAwMGLvhFx1MDAxY69cdTAwMWaOXHUwMDFlR416crPZ4zzcXG5sTkw3ffwpUMmJdKxiXGJCXHUwMDE5OmuhiOFYrDhxUC81eoxCccZcdTAwMTmLKSB7Xt1haD5cdTAwMDHCfOpcdTAwMTMr5+rc9eI6J1x1MDAwMFx1MDAxNFMwQ+dYXGZBX3ROWD+f8eWywNOlXHUwMDE3zfNroPKovP1cdTAwMWV47lx1MDAxY1x1MDAwMIst7YR7nVx1MDAwZoSmJ+bML7pTjpRcXFx1MDAxMiaBszBGPlx0qbb5XHUwMDEyhiPqKVwiQMazv9/Dws6HQNBOXHUwMDA25iupYFooXHUwMDE2y7CwXHUwMDBmW8zUZkAuZG9drkopXHLqTs9cdTAwMWJFfjeCjXqxcHDrN+RVkd6+XHUwMDFlQV+xUvJWyJzarto+6P9sjjr1q7K7Y6rtbqmyX32PiJ8+XymILyRzOFx1MDAwMrp1blGbp1xit3JYOFx1MDAwYjeO9+azVmR5XHUwMDBi0c2QRE5cZoI250musYbZrrGg6Fx1MDAxYmtcdLknkWeV3SS8X7HY2++2/ur0vYY/QNxcdTAwMWW8XHUwMDA3XG4wXHUwMDA3gFx1MDAxMyjAy0BWXHUwMDEyxpFcdTAwMGYpOLi4Wz9Qt5U1MyhcdTAwMWU23IJcdTAwMTi11k1cdTAwMDZSoFx1MDAxZGSFKECCaCFIfKFnnO1cdTAwMDFUXHUwMDEyKVx1MDAxOUmIgS2YizlmXHUwMDA18rmZvFx1MDAxN3o+XHUwMDAyK6hcdTAwMTCeYaVHaGRYWiWxgrTKXHUwMDExQFx1MDAwN04ztN65p2M+XHUwMDE2y63SNavf3Fx1MDAxY1xct+/IIS9ublx1MDAxZbzfdMy3Svh4U1rAcMJlTlx0XHUwMDFm6fOVRlx1MDAwYjh3XGbTXHUwMDA0XGZcdTAwMDFpwlx0KE81pNTme4CWXHUwMDA2oZ+bOC9cdTAwMDBiXHUwMDFjsMSAo1soXHUwMDE4elx1MDAxYZ/EIIORXHUwMDEwWZa8gKKNICwpXHUwMDE0YMzMXHUwMDFkO2z0zVYwmKWMRGqeJ4HQ4vSyeZ4rbqf2V6fe6t6/oOt74Fx1MDAwNnNwODHz045kJXkg+ZCDdPOZVoXHtbEhdVszXG5GXHUwMDAy0OiuJtQ4WoNcdTAwMDRcIlx0UYxcdTAwMTBcdTAwMWVcdTAwMGZcdTAwMTdwinZcdTAwMDKRxtbFXHUwMDE4JFx1MDAwNlx0XHUwMDAxP+IwobhcdTAwMDFcIpTgzKA3kTMz+ECKLzMovlHomymZWIjH9MxiXHJcdTAwMGVgluVcdTAwMDYpai9cdTAwMThcbsFSap9rXHUwMDE13kx5XHUwMDFj31x1MDAxZJfEoL1cdTAwMTgyL1hIl55cZr6yZCFcdTAwMWTXWjBpQFJjgp1cdTAwMDCeXHUwMDA2wfFcdTAwMTDCKqVcdTAwMWNcdTAwMDfKiVx1MDAxNLFBZKykS7dqS1xyoUCmxlx1MDAxMNquIPsoYrV0SfVy0Yq6aOXbpJYuKnr5XHUwMDE2003Otbt33r7/9FxcXHUwMDA2Z/6w+axDXHUwMDBiMLb0SFa6LddcdTAwMGWx5f9EXHUwMDE5rpicWjxcdTAwMTWoXHUwMDE4SuH/KCBGk3guXHUwMDFmZ47ktvBfI1x1MDAxNKB7XHUwMDFmUL6QJVx1MDAxN9Q6iXpM/YCGss0+XHJ51JBcdTAwMTczXHUwMDE4cvSmldaUJ+bswsycXck1RVx1MDAwNVx1MDAxM3lb8uXXcvK15LPk0X5cbnFRfL0lT1/7WcpcZlx1MDAxMsdMfaJGUFx1MDAxMFx1MDAxMu94Ruv9XHUwMDA2ldwkUy+XsM6p9c5RoXqFMd0+Lz9enFx1MDAxNlx1MDAwZb3G962T81x1MDAxZF070qejhYwpoGCNo1lEXHUwMDFiSamK+r/Ii1FJOPJcZlx1MDAwNDe7RWHcmlxu4qBcdTAwMTckuEL+zG0tXlwiL5bIRuzea5pcdTAwMTOtaPAln9Y0ak03Z1RAhFTieTJpXFw6n60sui/4XHUwMDAxSIymJWSvTPiysvlEMlQ78buzy3I1s4WZkjo+XHUwMDFiXHUwMDE30sXt7DRfmnEmv41cdTAwMTJyM1x1MDAxY+lcdTAwMTVoaYbDXHUwMDEwXHUwMDFh2VUxXHUwMDFharfpMYorhC6NpJdcdTAwMThcdTAwMWRPYWPM0YhrVFx1MDAwMkVh5Twh0I7UWoFiXHUwMDAy/XVBXHQ2l3eo/Vx1MDAwM1mOrVxma2xUMatcdTAwMDNJa2ygU1x1MDAwYiuIYeEo6McyXHUwMDEwMyVyfDZBXHUwMDE4X8/E0ndt+1x1MDAwNZTmd21AXHUwMDAzmXr5XHUwMDBlLWf6kkua5VREhkvSY4aT2q1JkHFJ677Ga2yYcezaiUC7i+4v6IRcdTAwMDVcdTAwMDewcmyUVFx1MDAxNFxiXHUwMDE4vNArfFKuWYZzd3HDSYkhQsjE7CUmZvqvjKLhVOGZzilcdTAwMTJpXHUwMDE3s4NH+fvs5iyJXHUwMDFjn01cdTAwMTLG11x1MDAxYs632Fx1MDAxMyt/w/lcdTAwMDbxxn+94TwtnVxuenj6rXZ17N81qvdnP1x1MDAwZk9cdTAwMWbjhnN2LS9cdTAwMGVaXHUwMDExxjklgk5vT09cdTAwMDV6rFx1MDAwNvk7JYjjUsb9VWp3XHUwMDBmXHUwMDFkr9xcdG3TN1x1MDAxMvxVUI6x8Vx1MDAxOGycXHUwMDE5YFmCf4l28aNcdTAwMTbzVsjF4raTXHUwMDFiidaTmcRE7jDOTS/fXHUwMDAyMjJcdTAwMDTD3HdTXHUwMDE0oJXJKSuxLLfafKu8R1x1MDAxZUeHpdvd0vd+736hOlx1MDAwNFx1MDAwMMJcdTAwMWRFXHUwMDE5XHUwMDEzxu5eYqbjL1x1MDAwMqlcdTAwMDJnUlBcclx1MDAxY59dQiGQYVx1MDAwZdhwXHUwMDFiml5Nw1umfKZcdTAwMWbMl99GluC11DZ4nSC+JlRZXHUwMDE1Sz7gyjAlVN55iXYjukzvXHUwMDBiXHSEMbRcdTAwMDN01V6zUuu2Xb/zV2fbplxmdNxW5HBcdTAwMWXJXGJvVNaXeVx1MDAwNPlkIVx1MDAxOOJvb19ccn72z+q33aPznUdf3NGFco2YduyylFx1MDAxMVJzYqZerPJSn4u20Fx1MDAxOEpcdTAwMTNeXHUwMDEzJOhTXHUwMDBlMrrLKFZcXH7WXHUwMDFjZdH1ZpaMXHUwMDAzZpBcdTAwMWSwxOp6XHUwMDFlh7BcdTAwMDCrqFwiaMjfYYHuRnmz+I5VOdq9fPR0r9pyq4Otys559fL+plHQ1cPL5kKgXHUwMDFjrImAofZNUcmaSqXdbEyx+P7zQKhD7d6PZlx1MDAxYyA1SbD8qaozVTVLLb3lPUaHX/dcdTAwMTLaXGKDzlZVXHUwMDAxdjNtSoOw83tR1WM7kVXPv1x1MDAwYufvvTuNTexlPoqbvrlsamqILYu3XHUwMDFiJCCtNlx1MDAxY1x1MDAwNI1uYKOkXHUwMDAzTElcIkBcdTAwMTD0XHUwMDFlTVxccVx1MDAwNddcdTAwMGV6loix6K4gXHUwMDFkT4JY5lx1MDAxMI183Vx1MDAxOPt2XG5mZJaiwFx1MDAwNXbbf4v3Rvz6nfYrkME3tPVcdTAwMWFKm+Sd9iFcdTAwMWVumyixwilAzyn3XHUwMDFjP3RcdTAwMGXDW4X+rsha5Oq43M27faYwv0FzzJFG4VxcXGKhXHUwMDA0sagog+a+TDX7XHUwMDFiXHUwMDEzXHUwMDBlx9l4oIVSoIlEXHUwMDE3Klx1MDAxMFx1MDAxZPtcdTAwMDGHUEnBVpIxlEdcdTAwMTNcdTAwMGZUZlxmXHUwMDAwvsX6TnhcYnanYTE1XHUwMDAyxCCG7lx1MDAwMVx1MDAwM1x1MDAwNlxcMpYyhF+0c/+sSptnW0HD/X/q09SQpzQhVXgj4vs0ilhrqZI8r/XJ7/FcdTAwMTKXWFwiZdQ2TGVSzq1p0Y+lbu+0ecf3dsnQVzdH9e+Lv8YzXGKUMkVQlqdee2jffiRtXHUwMDFlhNKCo0+aUFxu905cIqVcdTAwMWaiXHUwMDFhXHUwMDBl3MXRXHUwMDEwXHUwMDFkXHUwMDA2qoxiSS8+RI2OXHUwMDFknqRJMmmE3W4+ZzBcdTAwMTTAc1x1MDAwYpSmXHUwMDE3lGV5j9LUflx1MDAwZtPvUUqIlDLpSFx1MDAwMdq+koVwXHUwMDFiUI3L8+T1M8+t5E3t3kCWf1x1MDAwN7XLsIkngJGCiMQlUzq7slOg1Fx1MDAxMSXpMrJcdTAwMWPpRmJBN1sqcJpz+cYrLi9cYkQowe1cdTAwMGXUXHUwMDA00JOBudytgNqTLPxv0l5Mj15PXHUwMDA2f8FrnFR0Tqbe44Qg+Fo2+Fx1MDAwNsvB04Q2OobQe5xcdTAwMTghdufPd89cdTAwMDZZuP8z2GBUXHUwMDFiUuV3XHUwMDExOpguzPOaf1x1MDAwYj745bmVVbfXO1x1MDAxYaJcdTAwMDGbXGLV6p3v3X+bXHUwMDFkNfjyPKNcdTAwMTZavHHm8D9f/vk/eadZeyJ9ADCinterfaceSGPIORX DSP chainADCMCUSPISPI controlregistersSGPIO andflow controlADC clock domainInternal clock domainFPGATransceiver \ No newline at end of file diff --git a/docs/images/gateware-standard-dsp-chain.png b/docs/images/gateware-standard-dsp-chain.png new file mode 100644 index 0000000000000000000000000000000000000000..69973a94db572f97d8fcc83fb1b9001dd682c6e5 GIT binary patch literal 130043 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μqJBWb83Z3Q+%c7x5_t^?V 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

    1ONTR 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 Date: Mon, 16 Mar 2026 16:55:29 -0400 Subject: [PATCH 064/238] Fix radio_update() usage in sweep mode --- firmware/hackrf_usb/usb_api_sweep.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/firmware/hackrf_usb/usb_api_sweep.c b/firmware/hackrf_usb/usb_api_sweep.c index 0c5dbfff..782f69cd 100644 --- a/firmware/hackrf_usb/usb_api_sweep.c +++ b/firmware/hackrf_usb/usb_api_sweep.c @@ -100,15 +100,12 @@ usb_request_status_t usb_vendor_request_init_sweep( } sweep_freq = (uint64_t) frequencies[0] * FREQ_GRANULARITY; - nvic_disable_irq(NVIC_USB0_IRQ); radio_reg_write( &radio, RADIO_BANK_ACTIVE, RADIO_FREQUENCY_RF, (sweep_freq + offset) * FP_ONE_HZ); usb_transfer_schedule_ack(endpoint->in); - nvic_enable_irq(NVIC_USB0_IRQ); - radio_update(&radio); } return USB_REQUEST_STATUS_OK; } @@ -237,6 +234,7 @@ void sweep_mode(uint32_t seq) RADIO_FREQUENCY_RF, (sweep_freq + offset) * FP_ONE_HZ); nvic_enable_irq(NVIC_USB0_IRQ); + radio_update(&radio); blocks_queued = 0; } From f2a221d0b89ed4e6150bf50b8bca88e43c57c34e Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Wed, 1 Apr 2026 08:11:29 -0400 Subject: [PATCH 065/238] Remove radio_update() call from radio_reg_write() This was intended to be removed in #1648. Registers are typically written from within USB ISRs. Updates are meant to happen outside of ISRs. --- firmware/common/radio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/firmware/common/radio.c b/firmware/common/radio.c index c714d5e7..cb441a64 100644 --- a/firmware/common/radio.c +++ b/firmware/common/radio.c @@ -89,7 +89,6 @@ radio_error_t radio_reg_write( return RADIO_ERR_INVALID_BANK; } - radio_update(radio); return RADIO_OK; } From e5f79913ebc51467e108b79ab4c87e5d50fc720c Mon Sep 17 00:00:00 2001 From: mndza Date: Wed, 1 Apr 2026 17:38:22 +0200 Subject: [PATCH 066/238] gateware: unify resampling factors between gatewares --- firmware/fpga/build/praline_fpga.bin | Bin 200305 -> 200273 bytes firmware/fpga/top/ext_precision_rx.py | 11 +++++++---- firmware/fpga/top/ext_precision_tx.py | 11 +++++++---- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/firmware/fpga/build/praline_fpga.bin b/firmware/fpga/build/praline_fpga.bin index 90115bedb48a0a491a4476e667ab4ce0322b2ea1..b327ec0833617821f9e341fbd773c782fcebb524 100644 GIT binary patch delta 125874 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