From 7ea3eec016226812fce47871daf06582f9d94224 Mon Sep 17 00:00:00 2001 From: stafur Date: Fri, 20 Feb 2026 22:48:23 -0500 Subject: [PATCH] Update to additional gpio definitions for praline (#3018) * Initial commit and pr for HackRF Pro (praline) arch-port to mayhem-firmware. Please see https://github.com/portapack-mayhem/mayhem-firmware/issues/2957. Added flash specifics for -DBOARD=PRALINE. This firmware only builds with toolchain v9.2.1 if hackrf codebase has -B arm in firmware/hackrf_usb/CMakeLists.txt. * Updated CMakeLists.txt per coordination with @HtoToo. For -DBOARD=PRALINE FLASH_MB_SIZE and FLASH_MB_LIMIT_SIZE are now 4. Removed praline specific variable for FLASH limits. * Updated chibios-portapack's board.cpp to support initialization of the HachRF-Pro (praline) FPGA. Added append_fpga_bitstream.py tool to ensure that praline_fgpa.bin bitstream can be appended to -DBOARD=PRALINE produced firmware. In order to ensure successful execution of append_fpga_bitstream.py to append the fpga bitstream we should expect that the bistsream will be located at 0x180000 in flash. This requires that FLASH_MB_LIMIT_SIZE must be 1.5, and FLASH_BYTES_LIMIT_SIZE must be 1535 * 1024. If we want to allow more or less space for the base firmware image sans the fpga bitstream the location of the bistream must be moved to a location other than 0x180000. * Updated location of praline_fpga.bin bitstream to 0x380000 to allow more room for firmware. Firmware now has 3.5MB, or 2MB more available than before as coordinated with @HTotoo. * Expanded #ifndef PRALINE to include og and r9 gpio and pin setup as coordinated with @HTotoo. * Added note for PRALINE FLASH_MB_LIMIT_SIZE and FLASH_BYTES_LIMIT_SIZE to explain why we are using the 3.5 and 3584 values respectively as coordinated with @HTotoo. * Next round of modifications derived heavily, if not entirely from work done by @banandana at https://github.com/Banandana/mayhem-firmware. This commit should power on the HackRF Pro (praline) display, power on the fpga, and enable gpio, and provide debug utilties. There is still a lot of work to be done to fully enable the new praline board with this build and firmware architectural porting effort. However, hackrf-one boards do not seem to be adversely impacted by the #ifdef PRALINE statements, and CMakeLists updates, as far as I have been able to test. * Ran format-code.sh. Updates for this commit are only due to formatting. Tested builds and they seem to work as exptected. * Addressed fixes in firmware/application and firmware/baseband. Stream now flows to capture and looking glass. Issues were related to thread management. Issues were originally addressed by @banandana. * Ran format-code.sh to allow for consistency with autoamted clang checks. * Update hackrf ref repo to mayhem-portapack-hackrf next from https://github.com/portapack-mayhem/hackrf * Addressed format edits necessary to pass clang-format check. * Starting addressing Si5351 Clocks for radio sampling. These updates correctly set the Si5351 clock at start up. There appears to be an issue during runtime when testing with RX Test Init, Capture and Looking glass. * Updated clock_manager.cpp to restore correct function introduced by @banandana when testing with Rx Test Init. * Switched to using decimation for setting the sample rate without changing the Si5351 clock. This assumes that for the praline board Si5351 CLK0 runs at fixed 8 MHz (constant) and the FPGA decimates to get the desired sample rate. For example, for a 1 MHz sample rate -> Si5351 outputs 8 MHz, FPGA decimates by 8. There is still more work needed here, and potential verification that this is the correct way to operate with this new archteitecture. * After deliberating on hackrf_usb hackrf_core.c and radio.c, and reviewing firmware/application/hw/si5351.cpp the original approach of using the aproach detailed in hackrf_core.c sample_rate_frac_set() lines 580-582, via the implementation in firmware/application/hw/si5351.cpp seems like the best place to continue testing efforts. * Tested at ~2.4GHz (2.3 - 2.5) with lookgin glass and was able to receive signals. Added a Signal Path debug app to test gains, and readio mode (receive/transmit). * Added two debug apps for the RFFC507x. Status View and Tuning View. This helped debug some of the potential issues with tuning. * update submodule * format code * Small touch up merging latest next and ensuring build for HackRF One. * Fix ui addition of max2831 debug display. * Reverted edits to re: firmware/baseband/sd_over_usb/scsi.c and firmware/application/portapack.cpp. Source now builds, had to pull latest hackrf submodule. * Skipped detect hardware for praline board to avoid backscreen in HackRF Pro praline board. * Added UI debug display for max2831 like the rffc507x. Added Filter Band display and Mixer status to Signal Path Status debug display. * Added ability to set Q: INV, or Q:NOR in Signal Path Status Debug view for testing. Also added display entries for the FGPA Ctrl register fir debugging. * Added System Diagnostics which allows testing sample rate, q-inv, and dc blk * Corrected LP - GPIO4[8], and GPIO4[9] issue which was preventing RF Amp, and LPF from chaning state. HackRF Pro (praline) now correctly changes state of LPF and RF Amp as expected. * Corrected LP - GPIO4[8], and GPIO4[9] issue which was preventing RF Amp, and LPF from chaning state. HackRF Pro (praline) now correctly changes state of LPF and RF Amp as expected. * Added consistency for testing. * Added ui to debug whether rffc5072 is locking correctly. Also addressed rf_amp fixed in on state, such that it may now be able to be toggled in HackRF Pro praline setups. * Updated format to support automated tests. * format code * Updated rffc5072 status view in ui_debug to help with debugging. Made updated recommendtions for merge from PR comments. Made updates to ensure resetx isn't reconfigured for output in rffc507x.cpp. * Ran ./format-code.sh * Added reference comment that addresses debugging in PRALINE to detail that when the capture app was requesting 15 MHz, it matched 15100000 which resulted in the 8.5M setting. To get the actual 15M setting (22.6 MHz bandwidth), I had to force a request at least 22 MHz while debugging. * Debugging tunning ENX and frequency locking in low band. * Addressed pin differences between HackRF One and HackRF Pro (praline), resolved ENX configuration. * Cirrected pins, and debugging tuning for low band. High band now goes past 2.7GHz into 3.3 GHz. * Updated ui_debug to track ENX updates and support tracing which calls may be changing ENX. * Removed clkin reference in ui_debug.cpp to allow space for more information about CLK0, CLK1, CLK4, and CLK5. * Removed clkin reference in ui_debug.cpp to allow space for more information about CLK0, CLK1, CLK4, and CLK5. * Ran format-code.sh * Updated rffc507xx.cpp, and ensured hackrf submodule at f1dcd554. --------- Co-authored-by: gullradriel --- firmware/application/apps/ui_debug.cpp | 103 ++++++++++++------ firmware/application/apps/ui_debug.hpp | 55 +++++----- firmware/application/hw/rffc507x.cpp | 13 ++- firmware/application/main.cpp | 2 + firmware/application/radio.cpp | 46 ++++---- firmware/application/rf_path.cpp | 28 +++-- firmware/application/rf_path.hpp | 8 ++ .../boards/PORTAPACK_APPLICATION/board.cpp | 73 ++++++++++--- firmware/common/cpld_update.cpp | 20 ++++ firmware/common/hackrf_gpio.hpp | 33 +++++- 10 files changed, 271 insertions(+), 110 deletions(-) mode change 100755 => 100644 firmware/application/main.cpp diff --git a/firmware/application/apps/ui_debug.cpp b/firmware/application/apps/ui_debug.cpp index 168d8a5f7..c5cd42ece 100644 --- a/firmware/application/apps/ui_debug.cpp +++ b/firmware/application/apps/ui_debug.cpp @@ -1342,16 +1342,16 @@ Si5351DebugView::Si5351DebugView(NavigationView& nav) &text_sys_init_status, &text_xtal_cap_label, &text_xtal_cap_value, - &text_clkin_label, - &text_clkin_status, &text_clk0_label, &text_clk0_status, - &text_clk0_freq_label, &text_clk0_freq_value, - &text_clk0_div_label, &text_clk0_div_value, &text_clk1_label, &text_clk1_status, + &text_clk4_label, + &text_clk4_status, + &text_clk5_label, + &text_clk5_status, &button_refresh, &button_reset_pll, &button_done}); @@ -1424,11 +1424,6 @@ void Si5351DebugView::refresh_status() { // Read clock output enables (reg 16-23 control, reg 3 for output enable mask) uint8_t output_enable_mask = portapack::clock_manager.si5351_read_register(3); - // CLKIN - text_clkin_status.set(los_clkin ? "LOS" : "CLOCK SIGNAL"); - text_clkin_status.set_style(los_clkin ? Theme::getInstance()->fg_red - : Theme::getInstance()->fg_green); - // CLK0 (bit 0 of reg 3, reg 16 for control) uint8_t clk0_ctrl = portapack::clock_manager.si5351_read_register(16); bool clk0_enabled = !(output_enable_mask & 0x01) && !(clk0_ctrl & 0x80); @@ -1465,8 +1460,8 @@ void Si5351DebugView::refresh_status() { uint32_t freq_khz = 800000 / ms_div / r_div; // Result in kHz // Show P1 value and R45 for debugging - text_clk0_freq_value.set(to_string_dec_uint(freq_khz) + " kHz (P1:" + to_string_hex(p1, 4) + ")"); - text_clk0_div_value.set("MS=" + to_string_dec_uint(ms_div) + + text_clk0_freq_value.set("F:" + to_string_dec_uint(freq_khz / 1000) + "MHz (P1:" + to_string_hex(p1, 4) + ")"); + text_clk0_div_value.set("DIV: MS=" + to_string_dec_uint(ms_div) + " R=" + to_string_dec_uint(r_div)); // Color code based on expected 8 MHz @@ -1484,6 +1479,20 @@ void Si5351DebugView::refresh_status() { text_clk1_status.set(clk1_enabled ? "ON" : "OFF"); text_clk1_status.set_style(clk1_enabled ? Theme::getInstance()->fg_green : Theme::getInstance()->fg_red); + + // CLK4 (MAX2831 reference - bit 4 of reg 3, reg 20 for control) + uint8_t clk4_ctrl = portapack::clock_manager.si5351_read_register(20); + bool clk4_enabled = !(output_enable_mask & 0x10) && !(clk4_ctrl & 0x80); + text_clk4_status.set(clk4_enabled ? "ON (40MHz)" : "OFF"); + text_clk4_status.set_style(clk4_enabled ? Theme::getInstance()->fg_green + : Theme::getInstance()->fg_red); + + // CLK5 (RFFC5072 reference - bit 5 of reg 3, reg 21 for control) + uint8_t clk5_ctrl = portapack::clock_manager.si5351_read_register(21); + bool clk5_enabled = !(output_enable_mask & 0x20) && !(clk5_ctrl & 0x80); + text_clk5_status.set(clk5_enabled ? "ON (40MHz)" : "OFF"); + text_clk5_status.set_style(clk5_enabled ? Theme::getInstance()->fg_green + : Theme::getInstance()->fg_red); } void Si5351DebugView::reset_pll() { @@ -1827,11 +1836,6 @@ void SystemDiagnosticsView::read_gpio_states() { uint32_t gpio3_state = LPC_GPIO->PIN[3]; // GPIO3 for mixer uint32_t gpio4_state = LPC_GPIO->PIN[4]; // GPIO4 for LPF and amp - // Extract specific pins based on hackrf_gpio.hpp definitions: - // gpio_mix_enable_n = GPIO3_2 (P6_3) - bit 2 of port 3, INVERTED - // gpio_lpf_enable = GPIO4_8 (PA_1) - bit 8 of port 4 - // gpio_rf_amp_enable = GPIO4_9 (PA_2) - bit 9 of port 4 - bool mix_n_actual = (gpio3_state >> 2) & 1; // GPIO3[2] bool lpf_actual = (gpio4_state >> 8) & 1; // GPIO4[8] bool amp_actual = (gpio4_state >> 9) & 1; // GPIO4[9] @@ -1927,8 +1931,8 @@ void SystemDiagnosticsView::refresh() { GPIODebugView::GPIODebugView(NavigationView& nav) { add_children({ &text_lbl_gpio4, - &text_lbl_dir4, - &text_dir4, + &text_lbl_mixr1, + &text_mixr1, &text_lbl_pin4, &text_pin4, &text_lbl_set4, @@ -2031,7 +2035,7 @@ void GPIODebugView::refresh() { uint32_t gpio4_set = LPC_GPIO->SET[4]; // What we're trying to output // Display full registers - text_dir4.set("0x" + to_string_hex(gpio4_dir, 8)); + // text_dir4.set("0x" + to_string_hex(gpio4_dir, 8)); text_pin4.set("0x" + to_string_hex(gpio4_pin, 8)); text_set4.set("0x" + to_string_hex(gpio4_set, 8)); @@ -2075,6 +2079,22 @@ void GPIODebugView::refresh() { text_mix_dir.set_style(mix_dir ? Theme::getInstance()->fg_green : Theme::getInstance()->fg_red); text_mix_pin.set_style(mix_pin ? Theme::getInstance()->fg_green : Theme::getInstance()->fg_red); + + // Read GPIO5 (Mixer R1) - bit 2 + uint32_t gpio3_state = LPC_GPIO->PIN[3]; // GPIO3 for mixer + bool mix_n_actual = (gpio3_state >> 2) & 1; // GPIO3[2] + uint32_t gpio5_state = LPC_GPIO->PIN[5]; + bool mix_r10_pin = (gpio5_state >> 6) & 1; // GPIO5[6] = P2_6 + // Mixer is active LOW, so invert for display + bool mixer_enabled = !mix_n_actual; + + // Append to existing mixer display: + text_mixr1.set( + std::string(mixer_enabled ? "ENABLED" : "BYPASSED") + + " P6_3=" + to_string_dec_uint(mix_n_actual ? 1 : 0) + + " P2_6=" + to_string_dec_uint(mix_r10_pin ? 1 : 0)); + + text_mixr1.set_style(mixer_enabled ? Theme::getInstance()->fg_green : Theme::getInstance()->fg_red); } #endif @@ -2087,7 +2107,6 @@ RFFC5072StatusView::RFFC5072StatusView(NavigationView& nav) &text_title, &text_lbl_lock, &text_lock, - &text_lbl_ctrl, &text_ctrl, &text_lbl_enabled, &text_enabled, @@ -2113,6 +2132,7 @@ RFFC5072StatusView::RFFC5072StatusView(NavigationView& nav) &text_lbl_regs_status, &text_regs_status, &button_refresh, + &button_force_enx, &button_done, }); @@ -2122,6 +2142,14 @@ RFFC5072StatusView::RFFC5072StatusView(NavigationView& nav) refresh_status(); }; + button_force_enx.on_select = [this](Button&) { + // Force ENX to OUTPUT and drive LOW + LPC_GPIO->DIR[2] |= (1 << 13); // Set as OUTPUT + LPC_GPIO->CLR[2] = (1 << 13); // Drive LOW (enabled) + + refresh_status(); + }; + button_done.on_select = [&nav](Button&) { nav.pop(); }; @@ -2135,6 +2163,10 @@ void RFFC5072StatusView::focus() { } void RFFC5072StatusView::refresh_status() { + // === DEBUG: Capture GPIO state BEFORE any operations === + uint32_t gpio2_before = LPC_GPIO->PIN[2]; + bool enx_before = (gpio2_before >> 13) & 1; + // === READ RAW GPIO STATES FOR DEBUGGING === uint32_t gpio2_dir = LPC_GPIO->DIR[2]; uint32_t gpio2_pin = LPC_GPIO->PIN[2]; @@ -2164,11 +2196,10 @@ void RFFC5072StatusView::refresh_status() { bool enx = (gpio2_pin >> 13) & 1; bool resetx = (gpio2_pin >> 14) & 1; - text_ctrl.set( - std::string(enx ? "DIS" : "EN") + " " + - std::string(resetx ? "RUN" : "RST") + " " + - "EO:" + std::string(enx_is_output ? "Y" : "N") + " " + - "RO:" + std::string(resetx_is_output ? "Y" : "N")); + text_ctrl.set("ENX: " + std::string(enx ? "DIS" : "EN") + + " O:" + std::string(enx_is_output ? "Y" : "N") + + " | RST: " + std::string(resetx ? "RUN" : "RST") + + " O:" + std::string(resetx_is_output ? "Y" : "N")); text_ctrl.set_style((enx == 0 && resetx == 1) ? Theme::getInstance()->fg_green : Theme::getInstance()->fg_red); @@ -2209,15 +2240,25 @@ void RFFC5072StatusView::refresh_status() { uint32_t f_vco_mhz = (f_ref_mhz * n_int) / presc_val; uint32_t f_lo_mhz = f_vco_mhz / lodiv_val; - text_calc.set(to_string_dec_uint(f_lo_mhz) + " MHz"); - text_freq.set(to_string_dec_uint(f_vco_mhz) + " MHz VCO"); - // Check ranges + // RFFC5072 datasheet: Output 85-4200 MHz, VCO 2700-5400 MHz bool vco_ok = (f_vco_mhz >= 2700) && (f_vco_mhz <= 5400); - bool lo_ok = (f_lo_mhz >= 2300) && (f_lo_mhz <= 2700); + bool lo_ok = (f_lo_mhz >= 85) && (f_lo_mhz <= 4200); - text_calc.set_style(lo_ok ? Theme::getInstance()->fg_green - : Theme::getInstance()->fg_red); + // PRALINE mid-band (2320-2740 MHz) uses direct path, not RFFC5072 + bool in_bypass_range = (f_lo_mhz >= 2320) && (f_lo_mhz <= 2740); + + // Display with range annotation + if (in_bypass_range) { + text_calc.set(to_string_dec_uint(f_lo_mhz) + " MHz (MID)"); + text_calc.set_style(Theme::getInstance()->fg_orange); // Orange = bypass band + } else { + text_calc.set(to_string_dec_uint(f_lo_mhz) + " MHz"); + text_calc.set_style(lo_ok ? Theme::getInstance()->fg_green + : Theme::getInstance()->fg_red); + } + + text_freq.set(to_string_dec_uint(f_vco_mhz) + " MHz VCO"); text_freq.set_style(vco_ok ? Theme::getInstance()->fg_green : Theme::getInstance()->fg_red); diff --git a/firmware/application/apps/ui_debug.hpp b/firmware/application/apps/ui_debug.hpp index 31a9fc50b..7914e2ea8 100644 --- a/firmware/application/apps/ui_debug.hpp +++ b/firmware/application/apps/ui_debug.hpp @@ -643,37 +643,36 @@ class Si5351DebugView : public View { private: NavigationView& nav_; - Text text_title{{8, 16, 200, 16}, "Si5351 Clock Generator"}; + Text text_title{{0, 0, 200, 16}, "Si5351 Clock Generator"}; - Text text_status_label{{8, 40, 80, 16}, "Status Reg:"}; - Text text_status_value{{96, 40, 144, 16}, ""}; + Text text_status_label{{0, 16, 80, 16}, "Status Reg:"}; + Text text_status_value{{96, 16, 144, 16}, ""}; - Text text_pll_a_label{{8, 60, 80, 16}, "PLL A:"}; - Text text_pll_a_status{{96, 60, 144, 16}, ""}; + Text text_pll_a_label{{0, 32, 80, 16}, "PLL A:"}; + Text text_pll_a_status{{96, 32, 144, 16}, ""}; - Text text_pll_b_label{{8, 80, 80, 16}, "PLL B:"}; - Text text_pll_b_status{{96, 80, 144, 16}, ""}; + Text text_pll_b_label{{0, 48, 80, 16}, "PLL B:"}; + Text text_pll_b_status{{96, 48, 144, 16}, ""}; - Text text_sys_init_label{{8, 100, 80, 16}, "SYS_INIT:"}; - Text text_sys_init_status{{96, 100, 144, 16}, ""}; + Text text_sys_init_label{{0, 64, 80, 16}, "SYS_INIT:"}; + Text text_sys_init_status{{96, 64, 144, 16}, ""}; - Text text_xtal_cap_label{{8, 120, 80, 16}, "XTAL Cap:"}; - Text text_xtal_cap_value{{96, 120, 144, 16}, ""}; + Text text_xtal_cap_label{{0, 80, 80, 16}, "XTAL Cap:"}; + Text text_xtal_cap_value{{96, 80, 144, 16}, ""}; - Text text_clkin_label{{8, 140, 72, 16}, "CLKIN:"}; - Text text_clkin_status{{88, 140, 160, 16}, ""}; + Text text_clk0_label{{0, 96, 48, 16}, "CLK0:"}; + Text text_clk0_status{{50, 96, 28, 16}, ""}; + Text text_clk0_freq_value{{80, 96, 160, 16}, ""}; + Text text_clk0_div_value{{50, 112, 190, 16}, ""}; - Text text_clk0_label{{8, 160, 72, 16}, "CLK0:"}; - Text text_clk0_status{{88, 160, 152, 16}, ""}; + Text text_clk1_label{{0, 128, 96, 16}, "CLK1 (SCT):"}; + Text text_clk1_status{{112, 128, 128, 16}, ""}; - Text text_clk0_freq_label{{8, 180, 72, 16}, " Freq:"}; - Text text_clk0_freq_value{{88, 180, 152, 16}, ""}; + Text text_clk4_label{{0, 144, 96, 16}, "CLK4 (MAX):"}; + Text text_clk4_status{{112, 144, 128, 16}, ""}; - Text text_clk0_div_label{{8, 200, 72, 16}, " Div:"}; - Text text_clk0_div_value{{88, 200, 152, 16}, ""}; - - Text text_clk1_label{{8, 220, 96, 16}, "CLK1 (SCT):"}; - Text text_clk1_status{{112, 220, 128, 16}, ""}; + Text text_clk5_label{{0, 160, 96, 16}, "CLK5 (RFFC):"}; + Text text_clk5_status{{112, 160, 128, 16}, ""}; Button button_refresh{{8, 240, 72, 24}, "Refresh"}; Button button_reset_pll{{88, 240, 72, 24}, "Reset PLL"}; @@ -697,7 +696,7 @@ class SignalPathStatusView : public View { Text text_title{{0, 0, 240, 16}, "=== Signal Path Status ==="}; - Text text_lbl_max_enable{{0, 20, 1114, 16}, "MAX2831:"}; + Text text_lbl_max_enable{{0, 20, 114, 16}, "MAX2831:"}; Text text_max_enable{{116, 20, 124, 16}, "---"}; Text text_lbl_max_mode{{0, 36, 114, 16}, "RX Mode:"}; @@ -751,8 +750,8 @@ class GPIODebugView : public View { // GPIO4 (LPF and RF Amp) Text text_lbl_gpio4{{0, 0, 240, 16}, "Pin Diag: GPIO4 (LPF|Amp|Mix)"}; - Text text_lbl_dir4{{0, 18, 114, 16}, "DIR[4]:"}; - Text text_dir4{{116, 18, 124, 16}, "---"}; + Text text_lbl_mixr1{{0, 18, 56, 16}, "MixR1:"}; + Text text_mixr1{{58, 18, 180, 16}, "---"}; Text text_lbl_pin4{{0, 36, 114, 16}, "PIN[4] (read):"}; Text text_pin4{{116, 36, 124, 16}, "---"}; @@ -810,8 +809,7 @@ class RFFC5072StatusView : public View { Text text_lbl_lock{{0, 16, 114, 16}, "Lock Detect:"}; Text text_lock{{116, 16, 124, 16}, "---"}; - Text text_lbl_ctrl{{0, 32, 114, 16}, "Control:"}; - Text text_ctrl{{116, 32, 124, 16}, "---"}; + Text text_ctrl{{0, 32, 240, 16}, "---"}; Text text_lbl_enabled{{0, 48, 114, 16}, "Status:"}; Text text_enabled{{116, 48, 124, 16}, "---"}; @@ -848,7 +846,8 @@ class RFFC5072StatusView : public View { Text text_lbl_regs_status{{0, 224, 48, 16}, "Regs:"}; Text text_regs_status{{50, 224, 190, 16}, "---"}; - Button button_refresh{{2, 280, 56, 24}, "Rfrsh"}; + Button button_refresh{{2, 280, 72, 24}, "Refresh"}; + Button button_force_enx{{98, 280, 60, 24}, "T_ENX"}; Button button_done{{182, 280, 56, 24}, "Done"}; }; diff --git a/firmware/application/hw/rffc507x.cpp b/firmware/application/hw/rffc507x.cpp index 87acc938f..ef71ac239 100644 --- a/firmware/application/hw/rffc507x.cpp +++ b/firmware/application/hw/rffc507x.cpp @@ -197,7 +197,15 @@ struct SynthConfig { */ void RFFC507x::init() { -#ifndef PRALINE +#ifdef PRALINE + // CRITICAL: Enable RFFC5072 BEFORE any SPI communication! + // Without this, SPI writes are ignored when ENX=1 (disabled) + gpio_rffc5072_enx.output(); + gpio_rffc5072_enx.clear(); // ENX=0 (enabled) + + // Small delay for chip to power up + chThdSleepMilliseconds(1); +#else gpio_rffc5072_resetx.set(); gpio_rffc5072_resetx.output(); reset(); @@ -291,6 +299,9 @@ void RFFC507x::set_frequency(const rf::Frequency lo_frequency) { const SynthConfig synth_config = SynthConfig::calculate(lo_frequency); #ifdef PRALINE + // Ensure RFFC5072 is enabled before SPI writes + gpio_rffc5072_enx.clear(); // ENX=0 (enabled) + // Calculate VCO frequency from LO frequency and divider const size_t lo_divider = 1U << synth_config.lo_divider_log2; // 2^lodiv_log2 const rf::Frequency vco_freq = lo_frequency * lo_divider; diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp old mode 100755 new mode 100644 index 02b7531d8..76911cb8f --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -181,7 +181,9 @@ static void event_loop() { } int main(void) { +#ifndef PRALINE // Do not perform quick set up of GP01_RFF507X = 1 for PRALINE first_if.init(); /* To avoid initial short Ant_DC_Bias pulse ,we need quick set up GP01_RFF507X =1 */ +#endif if (config_mode_should_enter()) { config_mode_clear(); diff --git a/firmware/application/radio.cpp b/firmware/application/radio.cpp index fe5096f44..09266320e 100644 --- a/firmware/application/radio.cpp +++ b/firmware/application/radio.cpp @@ -147,15 +147,13 @@ void init() { ? (max283x::MAX283x*)&second_if_max2839 : (max283x::MAX283x*)&second_if_max2837; #endif + rf_path.init(); first_if.init(); second_if->init(); baseband_codec.init(); -#ifndef PRALINE - /* HackRF One uses CPLD for Q inversion control. - * PRALINE uses FPGA and the pin (P2_3) is used for LCD_TE on H4M. */ - baseband_cpld.init(); -#else + +#ifdef PRALINE /* Initialize FPGA registers - DC_BLOCK must be enabled for RX */ // debug::fpga::init(); fpga_debug_register_write(1, 0x01); // DC_BLOCK=1, QUARTER_SHIFT=0, Q_INVERT=0 @@ -166,6 +164,10 @@ void init() { ssp1_arbiter.invalidate(); chThdSleepMilliseconds(10); // Let FPGA registers settle +#else + /* HackRF One uses CPLD for Q inversion control. + * PRALINE uses FPGA and the pin (P2_3) is used for LCD_TE on H4M. */ + baseband_cpld.init(); #endif } @@ -204,9 +206,8 @@ void set_direction(const rf::Direction new_direction) { */ baseband_invert = false; } -#ifndef PRALINE - baseband_cpld.set_invert(mixer_invert ^ baseband_invert); -#else + +#ifdef PRALINE // TEST: Force baseband invert for Praline (like r9) // baseband_invert = (direction == rf::Direction::Receive); @@ -217,6 +218,8 @@ void set_direction(const rf::Direction new_direction) { } fpga_debug_register_write(1, ctrl_reg); ssp1_arbiter.invalidate(); +#else + baseband_cpld.set_invert(mixer_invert ^ baseband_invert); #endif second_if->set_mode((direction == rf::Direction::Transmit) ? max283x::Mode::Transmit : max283x::Mode::Receive); @@ -263,6 +266,10 @@ bool set_tuning_frequency(const rf::Frequency frequency) { if (tuning_config.first_lo_frequency) { first_if.set_frequency(tuning_config.first_lo_frequency); first_if.enable(); +#ifdef PRALINE + first_if.flush(); // Force register write with reference clock present + chThdSleepMilliseconds(10); // Allow PLL to settle +#endif } // Program second local oscillator frequency into MAX283x @@ -270,9 +277,8 @@ bool set_tuning_frequency(const rf::Frequency frequency) { rf_path.set_band(tuning_config.rf_path_band); mixer_invert = tuning_config.mixer_invert; -#ifndef PRALINE - baseband_cpld.set_invert(mixer_invert ^ baseband_invert); -#else + +#ifdef PRALINE // TEST: Force baseband invert for Praline (like r9) // baseband_invert = (direction == rf::Direction::Receive); @@ -283,6 +289,10 @@ bool set_tuning_frequency(const rf::Frequency frequency) { } fpga_debug_register_write(1, ctrl_reg); ssp1_arbiter.invalidate(); + // Log this value somewhere you can see it + uint32_t written_r15 = first_if.read(15); +#else + baseband_cpld.set_invert(mixer_invert ^ baseband_invert); #endif return result_second_if; @@ -352,20 +362,6 @@ void set_rx_max283x_iq_phase_calibration(const size_t v) { second_if->set_rx_LO_iq_phase_calibration(v); } -/*void enable(Configuration configuration) { - configure(configuration); -} - -void configure(Configuration configuration) { - set_tuning_frequency(configuration.tuning_frequency); - set_rf_amp(configuration.rf_amp); - set_lna_gain(configuration.lna_gain); - set_vga_gain(configuration.vga_gain); - set_baseband_rate(configuration.baseband_rate); - set_baseband_filter_bandwidth(configuration.baseband_filter_bandwidth); - set_direction(configuration.direction); -}*/ - void disable() { set_antenna_bias(false); baseband_codec.set_mode(max5864::Mode::Shutdown); diff --git a/firmware/application/rf_path.cpp b/firmware/application/rf_path.cpp index 9a2aa90a5..51b092db5 100644 --- a/firmware/application/rf_path.cpp +++ b/firmware/application/rf_path.cpp @@ -41,14 +41,18 @@ namespace { */ struct PralineConfig { bool tx_en; - bool mix_en_n; // Inverted: 0 = mixer enabled + // bool mix_en_n; // Inverted: 0 = mixer enabled + bool rffc_enx; // RFFC5072 ENX (GPIO2[13]) + bool mix_bypass; // RF path mixer bypass (GPIO3[2]) bool lpf_en; bool rf_amp_en; bool ant_bias_en_n; // Inverted: 0 = bias enabled static void gpio_init() { gpio_tx_enable.output(); - gpio_mix_enable_n.output(); + // gpio_mix_enable_n.output(); + gpio_rffc5072_enx.output(); + gpio_mix_bypass.output(); gpio_lpf_enable.output(); gpio_rf_amp_enable.output(); gpio_ant_bias_disable.output(); @@ -56,7 +60,9 @@ struct PralineConfig { void apply() const { gpio_tx_enable.write(tx_en); - gpio_mix_enable_n.write(mix_en_n); + // gpio_mix_enable_n.write(mix_en_n); + gpio_rffc5072_enx.write(rffc_enx); // Control RFFC5072 ENX + gpio_mix_bypass.write(mix_bypass); // Control RF path mixer gpio_lpf_enable.write(lpf_en); gpio_rf_amp_enable.write(rf_amp_en); gpio_ant_bias_disable.write(ant_bias_en_n); @@ -239,7 +245,9 @@ void Path::init() { /* Set safe initial state: RX mode, mixer enabled, LPF on, amp off, no bias */ PralineConfig config = { .tx_en = false, - .mix_en_n = false, // Mixer enabled (inverted) + //.mix_en_n = false, // Mixer enabled (inverted) + .rffc_enx = false, // RFFC5072 ENX (GPIO2[13]) + .mix_bypass = false, // RF path mixer bypass (GPIO3[2]) .lpf_en = true, // LPF on for low band .rf_amp_en = false, // Amp off .ant_bias_en_n = true // Bias off (inverted) @@ -276,7 +284,9 @@ void Path::update() { #ifdef PRALINE /* PRALINE RF path control: * - tx_en: 1 for TX, 0 for RX - * - mix_en_n: 0 to enable mixer (inverted), 1 to bypass + * // - mix_en_n: 0 to enable mixer (inverted), 1 to bypass + * - rffc_enx: 0 to enable RFFC5072 ENX (GPIO2[13]) + * - mix_bypass: 0 to enable RF path mixer bypass (GPIO3[2]) * - lpf_en: 1 for low band (< 2.4 GHz), 0 for high band * - rf_amp_en: 1 to enable RF amplifier * - ant_bias_en_n: 0 to enable antenna bias (inverted) @@ -294,8 +304,12 @@ void Path::update() { config.tx_en = (direction == Direction::Transmit); - /* Mixer bypass for mid band (2.3-2.7 GHz direct to MAX2831) */ - config.mix_en_n = (band == Band::Mid); // 1 = bypass (disabled) + // RFFC5072 ENX: Active LOW, so invert the band check + // ENX=0 (enabled) for Low/High, ENX=1 (disabled) for Mid + config.rffc_enx = (band == Band::Mid); // 0=enabled, 1=disabled + + // RF path mixer bypass: 0=enabled, 1=bypassed + config.mix_bypass = (band == Band::Mid); /* Move to the final state by turning on required signals. */ /* LPF for low band */ diff --git a/firmware/application/rf_path.hpp b/firmware/application/rf_path.hpp index 5393df87b..d098b2e37 100644 --- a/firmware/application/rf_path.hpp +++ b/firmware/application/rf_path.hpp @@ -39,9 +39,17 @@ enum class Direction { namespace path { +#ifdef PRALINE +/* PRALINE: MAX2831 direct path is 2320-2740 MHz */ +constexpr FrequencyRange band_low{0, 2320'000'000}; +constexpr FrequencyRange band_high{2740'000'000, 7250'000'000}; +constexpr FrequencyRange band_mid{band_low.maximum, band_high.minimum}; +#else +/* HackRF One: Original band boundaries */ constexpr FrequencyRange band_low{0, 2170'000'000}; constexpr FrequencyRange band_high{2740'000'000, 7250'000'000}; constexpr FrequencyRange band_mid{band_low.maximum, band_high.minimum}; +#endif enum class Band { /* Zero-based, used as index into frequency_bands table */ diff --git a/firmware/chibios-portapack/boards/PORTAPACK_APPLICATION/board.cpp b/firmware/chibios-portapack/boards/PORTAPACK_APPLICATION/board.cpp index 7aa060554..02ec6573f 100755 --- a/firmware/chibios-portapack/boards/PORTAPACK_APPLICATION/board.cpp +++ b/firmware/chibios-portapack/boards/PORTAPACK_APPLICATION/board.cpp @@ -61,7 +61,11 @@ const PALConfig pal_default_config = { .P = { { // GPIO0 .data +#ifdef PRALINE + = (0 << 15) // P1_20: CLKIN_CTRL - start low +#else = (1 << 15) // P1_20: CS_XCVR +#endif | (1 << 14) // P2_10: AMP_BYPASS | (0 << 13) // P1_18: SGPIO12, HOST_Q_INVERT | (0 << 12) // P1_17: SGPIO11, HOST_DIRECTION @@ -79,8 +83,12 @@ const PALConfig pal_default_config = { | (1 << 0) // P0_0: SGPIO0, HOST_DATA0 , .dir +#ifdef PRALINE + = (1 << 15) // P1_20: CLKIN_CTRL - output +#else = (1 << 15) // P1_20: CS_XCVR - | (1 << 14) // P2_10: AMP_BYPASS +#endif + | (1 << 14) // P2_10: AMP_BYPASS | (1 << 13) // P1_18: SGPIO12, HOST_Q_INVERT | (0 << 12) // P1_17: SGPIO11, HOST_DIRECTION | (0 << 11) // P1_4: SSP1_MOSI @@ -137,7 +145,11 @@ const PALConfig pal_default_config = { .data = (0 << 15) // P5_6: TX_AMP | (1 << 14) // P5_5: MIXER_RESETX, 10K PU +#ifdef PRALINE + | (0 << 13) // P5_4: MIXER_ENX, 10K PU +#else | (1 << 13) // P5_4: MIXER_ENX, 10K PU +#endif | (1 << 12) // P5_3: RX_MIX_BP | (0 << 11) // P5_2: TX_MIX_BP | (0 << 10) // P5_1: LP @@ -154,11 +166,19 @@ const PALConfig pal_default_config = { , .dir = (1 << 15) // P5_6: TX_AMP - | (1 << 14) // P5_5: MIXER_RESETX, 10K PU - | (1 << 13) // P5_4: MIXER_ENX, 10K PU +#ifdef PRALINE + | (0 << 14) // P5_5: MIXER_RESETX, 10K PU + | (1 << 13) // P5_4: MIXER_ENX - OUTPUT (MCU controlled) + | (0 << 12) // P5_3: RX_MIX_BP - unused on PRALINE + | (0 << 11) // P5_2: FPGA_CRESET - INPUT initially + | (0 << 10) // P5_1: FPGA_SPI_CS - INPUT initially +#else + | (1 << 14) // P5_5: MIXER_RESETX, 10K PU + | (1 << 13) // P5_4: MIXER_ENX, 10K PU | (1 << 12) // P5_3: RX_MIX_BP | (1 << 11) // P5_2: TX_MIX_BP | (1 << 10) // P5_1: LP +#endif | (0 << 9) // P5_0: Varies by revision, float until detection | (1 << 8) // P6_12: LED3 (TX) | (1 << 7) // P5_7: CS_AD @@ -306,7 +326,13 @@ const PALConfig pal_default_config = { { 1, 7, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* !MIX_BYPASS/P35: U1.VCTL1(I), U11.VCTL2(I), U9.V2(I) */ { 1, 19, scu_config_normal_drive_t { .mode=1, .epd=0, .epun=0, .ehs=0, .ezi=0, .zif=0 } }, /* SSP1_SCK/P39: MAX2837.SCLK(I), MAX5864.SCLK(I) */ { 1, 20, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* CS_XCVR/P53: MAX2837.CS(I) */ + +#ifdef PRALINE + { 2, 6, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=1, .ezi=0, .zif=1 } }, /* TRIGGER_OUT / MIX_EN_N_R1_0: GPIO5[6] - PRALINE */ +#else + /* HackRF One RFFC5072 SPI pins */ { 2, 6, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* MIXER_SCLK/P31: 33pF, RFFC5072.SCLK(I) */ +#endif { 2, 10, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* AMP_BYPASS/P50: U14.V2(I), U12.V2(I) */ { 2, 11, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* RX_AMP/P49: U12.V1(I), U14.V3(I) */ { 2, 12, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* !RX_AMP_PWR/P52: 10K PU, Q1.G(I), power to U13 (RX amp) */ @@ -319,8 +345,16 @@ const PALConfig pal_default_config = { { 5, 4, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* MIXER_ENX/P32: 10K PU, 33pF, RFFC5072.ENX(I) */ { 5, 5, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* MIXER_RESETX/P33: 10K PU, 33pF, RFFC5072.RESETX(I) */ { 5, 6, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* TX_AMP/P48: U12.V3(I), U14.V1(I) */ +#ifdef PRALINE + /* PRALINE RFFC5072 SPI pins - different from HackRF One */ + { 5, 7, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* P5_7: GPIO2[7], RFFC5072 CS */ + { 9, 5, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=0, .ehs=1, .ezi=0, .zif=0 } }, /* P9_5: GPIO5[18], RFFC5072 SCLK */ + { 9, 2, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=0, .ehs=1, .ezi=1, .zif=0 } }, /* P9_2: GPIO4[14], RFFC5072 SDATA (bidirectional) */ +#else +/* HackRF One RFFC5072 SPI pins - NOT used on PRALINE */ { 5, 7, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* CS_AD/P54: MAX5864.CS(I) */ { 6, 4, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=0, .ehs=0, .ezi=1, .zif=0 } }, /* MIXER_SDATA/P27: 33pF, RFFC5072.SDATA(IO) */ +#endif { 6, 8, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* MIX_BYPASS/P34: U1.VCTL2(I), U11.VCTL1(I) */ { 6, 9, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* !TX_AMP_PWR/P51: 10K PU, Q2.G(I), power to U25 (TX amp) */ @@ -346,7 +380,9 @@ const PALConfig pal_default_config = { { 6, 1, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* CPLD_TCK: PortaPack CPLD.TCK(I) */ { 6, 2, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* CPLD_TDI: PortaPack CPLD.TDI(I), I2S0_RX_SDA(O) */ { 6, 5, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* CPLD_TMS: HackRF CPLD.TMS(I) */ +#ifndef PRALINE { 9, 5, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=0, .ehs=0, .ezi=1, .zif=0 } }, /* CPLD_TDO: HackRF CPLD.TDO(O) */ +#endif /* PortaPack CPLD */ { 1, 5, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=0, .ehs=0, .ezi=1, .zif=0 } }, /* SD_POW: PortaPack CPLD.TDO(O) */ @@ -885,21 +921,34 @@ extern "C" void boardInit(void) { { volatile uint32_t delay = 100000; while(delay--); } /* Configure RFFC5072 pins for PRALINE */ - /* P9_2 = GPIO4[14] RFFC5072 data (SCU_GPIO_FAST | FUNCTION0 = 0xF0) */ - LPC_SCU->SFSP[9][2] = 0xF0; - /* P9_5 = GPIO5[18] RFFC5072 clock (SCU_GPIO_FAST | FUNCTION4 = 0xF4) */ - LPC_SCU->SFSP[9][5] = 0xF4; - LPC_GPIO->DIR[5] |= (1 << 18); /* Clock as output */ + /* Set GPIO directions for RFFC5072 SPI pins */ + /* P5_7 = GPIO2[7] RFFC5072 CS */ + LPC_GPIO->SET[2] = (1 << 7); /* CS high (deselected) */ + LPC_GPIO->DIR[2] |= (1 << 7); /* CS as output */ + + /* P9_5 = GPIO5[18] RFFC5072 SCLK */ + LPC_GPIO->CLR[5] = (1 << 18); /* CLK low */ + LPC_GPIO->DIR[5] |= (1 << 18); /* CLK as output */ + + /* P9_2 = GPIO4[14] RFFC5072 DATA (bidirectional) */ + LPC_GPIO->DIR[4] |= (1 << 14); /* DATA as output initially */ + + /* P2_6 = GPIO5[6] TRIGGER_OUT / MIX_EN_N_R1_0 (PRALINE R1.0 mixer bypass) */ + /* SCU configured in PAL array above with mode=4 */ + LPC_GPIO->CLR[5] = (1 << 6); /* Default low (mixer enabled) */ + LPC_GPIO->DIR[5] |= (1 << 6); /* Output */ /* Configure Port D pins for PRALINE (use SFSPD registers) */ /* PD_14 = GPIO6[28] MAX2831 chip select */ LPC_SCU->SFSPD[14] = 0xF4; /* SCU_GPIO_FAST | FUNCTION4 */ LPC_GPIO->SET[6] = (1 << 28); /* CS high (inactive) */ LPC_GPIO->DIR[6] |= (1 << 28); /* Output */ + /* PD_15 = GPIO6[29] MAX2831 RXHP control */ LPC_SCU->SFSPD[15] = 0xF4; /* SCU_GPIO_FAST | FUNCTION4 */ LPC_GPIO->CLR[6] = (1 << 29); /* RXHP low = 100 Hz HPF */ LPC_GPIO->DIR[6] |= (1 << 29); /* Output */ + /* PD_16 = GPIO6[30] MAX5864 chip select */ LPC_SCU->SFSPD[16] = 0xF4; /* SCU_GPIO_FAST | FUNCTION4 */ LPC_GPIO->SET[6] |= (1 << 30); /* CS high (inactive) */ @@ -938,14 +987,15 @@ extern "C" void boardInit(void) { /* Configure RFFC5072 control pins for PRALINE */ /* P5_4 = GPIO2[13] RFFC5072 ENX (active low: 0=enabled) */ LPC_SCU->SFSP[5][4] = 0xF0; /* FUNCTION0 (GPIO), no pulls */ - LPC_GPIO->DIR[2] &= ~(1 << 13); /* ENX: INPUT (let FPGA control) */ + LPC_GPIO->DIR[2] |= (1 << 13); /* ENX: OUTPUT */ + LPC_GPIO->CLR[2] = (1 << 13); /* ENX = 0 (ENABLED) */ /* P5_5 = GPIO2[14] RFFC5072 RESETX - FPGA controlled, MCU should not touch */ LPC_SCU->SFSP[5][5] = 0xF0; /* FUNCTION0 (GPIO), no pulls */ LPC_GPIO->DIR[2] &= ~(1 << 14); /* RESETX: INPUT (let FPGA control) */ /* PD_11 = GPIO6[25] RFFC5072 Lock Detect (input) */ - LPC_SCU->SFSP[0xD][11] = 0xF0; /* FUNCTION0 (GPIO), no pulls */ + LPC_SCU->SFSP[0xD][11] = 0xF4; /* FUNCTION4 (GPIO), no pulls */ /* Small delay for signals to stabilize */ for (volatile int i = 0; i < 10000; i++) {} @@ -979,9 +1029,6 @@ extern "C" void boardInit(void) { LPC_SCU->SFSP[2][2] = 0xF0; /* SGPIO6: P2_2 function 0, HOST_DATA6 */ LPC_SCU->SFSP[1][0] = 0xF6; /* SGPIO7: P1_0 function 6, HOST_DATA7 */ - /* NOTE: P9_5 is RFFC5072 mixer clock (SCU_MIXER_SCLK), NOT SGPIO! - * Do NOT override P9_5 here. */ - // Trigger FPGA bitstream loading via fpga bridge // Attempt to load the FPGA bitstream // This function returns LD_SUCCESS (0) if the FPGA confirms the bitstream diff --git a/firmware/common/cpld_update.cpp b/firmware/common/cpld_update.cpp index b0d359aa0..8865bb08a 100644 --- a/firmware/common/cpld_update.cpp +++ b/firmware/common/cpld_update.cpp @@ -213,6 +213,24 @@ CpldUpdateStatus update_autodetect(const Config config_rev_20150901, const Confi namespace hackrf { namespace cpld { +#ifdef PRALINE + +/* PRALINE has no HackRF CPLD - stub these functions out */ +bool load_sram() { + return true; +} +void load_sram_no_verify() { + return; +} +bool verify_eeprom() { + return true; +} +void init_from_eeprom() { + return; +} + +#else + static jtag::GPIOTarget jtag_target_hackrf() { return { hackrf::one::gpio_cpld_tck, @@ -262,5 +280,7 @@ void init_from_eeprom() { hackrf_cpld.init_from_eeprom(); } +#endif // PRALINE + } /* namespace cpld */ } /* namespace hackrf */ diff --git a/firmware/common/hackrf_gpio.hpp b/firmware/common/hackrf_gpio.hpp index 588928dfa..dedc6f4fe 100644 --- a/firmware/common/hackrf_gpio.hpp +++ b/firmware/common/hackrf_gpio.hpp @@ -52,7 +52,12 @@ constexpr GPIO gpio_r9_vaa_disable = gpio[GPIO3_6]; constexpr GPIO gpio_rx_mix_bp = gpio[GPIO2_12]; constexpr GPIO gpio_tx_mix_bp = gpio[GPIO2_11]; +#ifdef PRALINE +constexpr GPIO gpio_mix_bypass = gpio[GPIO3_2]; // P6_3: PRALINE RF path mixer bypass inverted +constexpr GPIO gpio_mix_en_n_r1_0 = gpio[GPIO5_6]; // P2_6: R1.0 board mixer bypass +#else constexpr GPIO gpio_mix_bypass = gpio[GPIO5_16]; +#endif constexpr GPIO gpio_not_mix_bypass = gpio[GPIO1_0]; constexpr GPIO gpio_og_rx = gpio[GPIO5_5]; @@ -68,8 +73,18 @@ constexpr GPIO gpio_amp_bypass = gpio[GPIO0_14]; constexpr GPIO gpio_not_rx_amp_pwr = gpio[GPIO1_12]; constexpr GPIO gpio_not_tx_amp_pwr = gpio[GPIO3_5]; +#ifndef PRALINE constexpr GPIO gpio_rffc5072_resetx = gpio[GPIO2_14]; +#endif + +#ifdef PRALINE +constexpr GPIO gpio_rffc5072_enx = gpio[GPIO2_13]; // P5_4: RFFC5072 ENX (active LOW) +constexpr GPIO gpio_rffc5072_select = gpio[GPIO2_13]; // P5_4: ENX doubles as SPI strobe +// constexpr GPIO gpio_rffc5072_select = gpio[GPIO2_7]; // P5_7: PRALINE CS +#else constexpr GPIO gpio_rffc5072_select = gpio[GPIO2_13]; +#endif + #ifdef PRALINE constexpr GPIO gpio_rffc5072_clock = gpio[GPIO5_18]; constexpr GPIO gpio_rffc5072_data = gpio[GPIO4_14]; @@ -103,8 +118,8 @@ constexpr GPIO gpio_max2839_rxtx = gpio[GPIO2_5]; #endif #ifdef PRALINE -constexpr GPIO gpio_max5864_select = gpio[GPIO6_30]; -constexpr GPIO gpio_fpga_select = gpio[GPIO2_10]; // FPGA SPI CS (P5_1) +constexpr GPIO gpio_max5864_select = gpio[GPIO6_30]; // PD_16: PRALINE MAX5864 CS +constexpr GPIO gpio_fpga_select = gpio[GPIO2_10]; // FPGA SPI CS (P5_1) #else constexpr GPIO gpio_max5864_select = gpio[GPIO2_7]; #endif @@ -118,8 +133,8 @@ constexpr GPIO gpio_1v2_enable = gpio[GPIO4_7]; // 1V2 enable (P8_7) constexpr GPIO gpio_3v3aux_disable = gpio[GPIO5_15]; // 3V3 aux disable (P6_7) // PRALINE RF path control -constexpr GPIO gpio_tx_enable = gpio[GPIO3_4]; // TX enable (P6_5) -constexpr GPIO gpio_mix_enable_n = gpio[GPIO3_2]; // Mixer enable inverted (P6_3) +constexpr GPIO gpio_tx_enable = gpio[GPIO3_4]; // TX enable (P6_5) +// constexpr GPIO gpio_mix_enable_n = gpio[GPIO3_2]; // Mixer enable inverted (P6_3) constexpr GPIO gpio_lpf_enable = gpio[GPIO4_8]; // LPF enable (PA_1) constexpr GPIO gpio_rf_amp_enable = gpio[GPIO4_9]; // RF amp enable (PA_2) constexpr GPIO gpio_ant_bias_disable = gpio[GPIO1_12]; // Antenna bias disable (P2_12) @@ -144,9 +159,17 @@ constexpr GPIO gpio_trigger_out = gpio[GPIO5_6]; // Trigger output (P2_6) constexpr GPIO gpio_pps_out = gpio[GPIO5_5]; // PPS output (P2_5) #endif +#ifdef PRALINE +/* PRALINE has no HackRF CPLD. These pins are used for RFFC5072 and TX_EN instead. + * Dummy assignments here allow cpld_update.cpp to compile; the functions + * that use them are never called on PRALINE. */ +constexpr GPIO gpio_cpld_tdo = gpio[GPIO3_0]; // dummy: reuse TCK pin +constexpr GPIO gpio_cpld_tms = gpio[GPIO3_1]; // dummy: reuse TDI pin +#else constexpr GPIO gpio_cpld_tdo = gpio[GPIO5_18]; -constexpr GPIO gpio_cpld_tck = gpio[GPIO3_0]; constexpr GPIO gpio_cpld_tms = gpio[GPIO3_4]; +#endif +constexpr GPIO gpio_cpld_tck = gpio[GPIO3_0]; constexpr GPIO gpio_cpld_tdi = gpio[GPIO3_1]; constexpr GPIO gpio_r9_clkin_en = gpio[GPIO5_15];