From b09efb4d3c00598af2520fdfae88f262890c4dd3 Mon Sep 17 00:00:00 2001 From: stafur Date: Tue, 24 Feb 2026 03:36:55 -0500 Subject: [PATCH] Mixer lock:: update clocks and move fpga_bridge_init to portapack.cpp (#3039) * Updated harckrf_gpio methods to more closely reflect hackrf_usb. Added some ui debug updates to RFFC5072 Status View. * Updated tuning tables for tuning.cpp. Remnoved 15MHz lower limit in max2831.cpp since lower bandwidths don't seem to be causing lower band issues. Added more opportunities for clocks to stabalize at startup in board.cpp. Added/amended UI to help with addresssing low band tuning issues. Cleaned up stale comments in radio.cpp. * Ran format-code.sh * Updated to remove commented lines as part of clean up addressing review comments. * Fixed clock_manager.cpp configruation for praline. Praline hackrf pro should have: CLK4: 6mA, Invert RFFC5072 40MHz ref and CLK5: 4mA, Invert MAX2831 40MHz ref. Improvements should be visible in the watefall at 2.4GHz, and between 2.311 and 2.599GHz. * After reviewin clock config, updated values to reflect: CLK0 MAX5864 (ADC) 40 MHz 4mA Normal Integer Minimizes sampling jitter for SNR. CLK1 iCE40 FPGA 40 MHz 6mA Normal Integer Stable timing for the SPI bridge. CLK2 LPC43xx MCU 40 MHz 4mA Normal Integer Standard reference for MCU PLL. CLK3 SMA Port P1 10 MHz 8mA Normal Integer Cleanest square wave for Ext Ref. CLK4 RFFC5072 (Mixer) 40 MHz 6mA Inverted Integer Crucial for PLL Lock stability. CLK5 MAX2831 (TRX) 40 MHz 4mA Inverted Integer Reduces phase noise in the 2.4GHz LO. CLK6 SMA Port P2 10 MHz 8mA Normal Integer Sync output for external gear. CLK7 Reserved Off N/A N/A N/A Disabled to save power/reduce EMI. * Ran format-code.sh * Moved fpga_brdige_init to portapack.cpp. This more closely resembles how hackrf_usb starts initializes the fpga, and allows time for the clocks to stabilize and facilitate locking to support low band tuning. * Ran format-code.sh * Added ProRadio Debug display to check for / debug locking. * Moved fpga_bridge_init before radio_init in portapack.cpp * Low band can now see signals. Updated clock_manager, rffc507 and portapack.cpp to ensure fpga intialized correctly. Ensures rffc507x.cpp has correct 40MHz reference frequency, prescaler, and synth configuration. * Updated radio to add q-invert on, dc-block on, and deimation=3 (8x, for 20 -> 2.5 MHz decimation for testing cleaner low band signals. * Ran format-code.sh --- firmware/application/apps/ui_debug.cpp | 76 +++++++++++++++++++ firmware/application/apps/ui_debug.hpp | 44 +++++++++++ firmware/application/clock_manager.cpp | 70 ++++++++++++----- firmware/application/hw/rffc507x.cpp | 30 +------- firmware/application/portapack.cpp | 53 ++++++++++++- firmware/application/radio.cpp | 10 ++- .../boards/PORTAPACK_APPLICATION/board.cpp | 21 +---- 7 files changed, 232 insertions(+), 72 deletions(-) diff --git a/firmware/application/apps/ui_debug.cpp b/firmware/application/apps/ui_debug.cpp index a93caa31d..d3e077486 100644 --- a/firmware/application/apps/ui_debug.cpp +++ b/firmware/application/apps/ui_debug.cpp @@ -515,6 +515,81 @@ void RadioDiagnosticsView::update_status() { } } +#ifdef PRALINE +PralineRadioDebugView::PralineRadioDebugView(NavigationView& nav) { + add_children({&text_title, &text_lbl_lock, &text_lock_status, + &text_lbl_clk5, &text_clk5_status, + &text_lbl_spi, &text_spi_status, &text_lbl_fpga_ctrl, &text_fpga_ctrl, + &text_lbl_vaa, &text_vaa_status, &text_status_msg, + &button_refresh, &button_toggle_clk5, &button_done}); + + button_refresh.on_select = [this](Button&) { this->refresh(); }; + button_toggle_clk5.on_select = [this](Button&) { this->toggle_clk5(); }; + button_done.on_select = [&nav](Button&) { nav.pop(); }; + + refresh(); +} + +void PralineRadioDebugView::focus() { + button_refresh.focus(); +} + +void PralineRadioDebugView::toggle_clk5() { + // Si5351 Register 3 is the Output Enable mask. Bit 5 = CLK5. + // 0 = Enabled, 1 = Disabled. + uint8_t reg3 = portapack::clock_manager.si5351_read_register(3); + reg3 ^= 0x20; // Toggle Bit 5 (CLK5) + portapack::clock_manager.si5351_write_register(3, reg3); + refresh(); +} + +void PralineRadioDebugView::refresh() { + // 1. Check Mixer Lock Detect (GPIO6[25] / PD_11) [cite: 16, 17] + uint32_t gpio6_state = LPC_GPIO->PIN[6]; + bool locked = (gpio6_state >> 25) & 1; + text_lock_status.set(locked ? "LOCKED (OK)" : "UNLOCKED!"); + text_lock_status.set_style(locked ? Theme::getInstance()->fg_green : Theme::getInstance()->fg_red); + + // 2. Check Si5351 CLK5 Status (Reg 3, Bit 5) - 0 = ON, 1 = OFF + uint8_t si_reg3 = portapack::clock_manager.si5351_read_register(3); + bool clk5_on = !(si_reg3 & 0x20); + text_clk5_status.set(clk5_on ? "ON (40MHz)" : "OFF"); + text_clk5_status.set_style(clk5_on ? Theme::getInstance()->fg_green : Theme::getInstance()->fg_red); + + // 3. Check SPI Bit Mode (SSP1 CR0) + // DSS (Data Size Select) is Bit 3:0. 0x8 = 9-bit (MAX2831), 0xF = 16-bit (Classic) + uint32_t cr0 = LPC_SSP1->CR0; + uint8_t dss = cr0 & 0x0F; + if (dss == 0x08) + text_spi_status.set("9-Bit (Pro)"); + else + text_spi_status.set("Other (Err)"); + text_spi_status.set_style((dss == 0x08) ? Theme::getInstance()->fg_green : Theme::getInstance()->fg_red); + + // 4. Check FPGA Register 1 (DC Block status) [cite: 12, 13] + uint8_t fpga_r1 = radio::debug::fpga::register_read(1); + text_fpga_ctrl.set(to_string_hex(fpga_r1, 2)); + + // 5. Check VAA RF Power (GPIO4[1] / P8_1) - Active LOW [cite: 16, 17] + uint32_t gpio4_state = LPC_GPIO->PIN[4]; + bool vaa_on = !((gpio4_state >> 1) & 1); + text_vaa_status.set(vaa_on ? "ON" : "OFF"); + text_vaa_status.set_style(vaa_on ? Theme::getInstance()->fg_green : Theme::getInstance()->fg_red); + + // Diagnostic Summary + if (!locked && clk5_on && vaa_on) { + text_status_msg.set("Clock/Pwr OK. PLL not locked. Check tuning registers."); + text_status_msg.set_style(Theme::getInstance()->fg_red); + } else if (!clk5_on) { + text_status_msg.set("Mixer Clock is OFF. PLL cannot lock."); + text_status_msg.set_style(Theme::getInstance()->fg_red); + } else { + text_status_msg.set("Hardware Link Active."); + text_status_msg.set_style(Theme::getInstance()->fg_green); + } +} +#endif + /* BasebandStatusView ******************************************************/ BasebandStatusView::BasebandStatusView(NavigationView& nav) @@ -2748,6 +2823,7 @@ void DebugMenuView::on_populate() { #ifdef PRALINE {"System Diag", ui::Theme::getInstance()->fg_yellow->foreground, &bitmap_icon_peripherals, [this]() { nav_.push(); }}, {"Radio Diag", ui::Theme::getInstance()->fg_yellow->foreground, &bitmap_icon_peripherals, [this]() { nav_.push(); }}, + {"ProRadio Debug", ui::Theme::getInstance()->fg_yellow->foreground, &bitmap_icon_peripherals, [this]() { nav_.push(); }}, {"Signal Path", ui::Theme::getInstance()->fg_yellow->foreground, &bitmap_icon_peripherals, [this]() { nav_.push(); }}, {"GPIO Debug", ui::Theme::getInstance()->fg_yellow->foreground, &bitmap_icon_peripherals, [this]() { nav_.push(); }}, {"RFFC Status", ui::Theme::getInstance()->fg_yellow->foreground, &bitmap_icon_peripherals, [this]() { nav_.push(); }}, diff --git a/firmware/application/apps/ui_debug.hpp b/firmware/application/apps/ui_debug.hpp index 90b5cab87..5b4dc6698 100644 --- a/firmware/application/apps/ui_debug.hpp +++ b/firmware/application/apps/ui_debug.hpp @@ -438,6 +438,50 @@ class RadioDiagnosticsView : public View { "Done"}; }; +#ifdef PRALINE +/* Praline-Specific Radio Debug View + * Monitors Mixer Lock, SPI Bit Depth, and toggles Si5351 CLK5 + */ +class PralineRadioDebugView : public View { + public: + PralineRadioDebugView(NavigationView& nav); + void focus() override; + std::string title() const override { return "Pro Radio Debug"; }; + + private: + void refresh(); + void toggle_clk5(); + + Text text_title{{0, 0, 240, 16}, "=== Pro Radio Debug ==="}; + + // Mixer Lock (PD_11 / GPIO6[25]) + Text text_lbl_lock{{0, 24, 124, 16}, "Mix Lock (LD):"}; + Text text_lock_status{{126, 24, 114, 16}, "---"}; + + // Si5351 CLK5 (Mixer Reference) + Text text_lbl_clk5{{0, 40, 124, 16}, "Si5351 CLK5(Mix):"}; + Text text_clk5_status{{126, 40, 114, 16}, "---"}; + + // SPI Bus configuration check + Text text_lbl_spi{{0, 56, 124, 16}, "SPI Bit Mode:"}; + Text text_spi_status{{126, 56, 118, 16}, "---"}; + + // FPGA DC Block (Reg 1) + Text text_lbl_fpga_ctrl{{0, 72, 124, 16}, "FPGA Reg 1:"}; + Text text_fpga_ctrl{{126, 72, 118, 16}, "---"}; + + // VAA Power Rail (P8_1 / GPIO4[1]) + Text text_lbl_vaa{{0, 88, 124, 16}, "VAA RF Power:"}; + Text text_vaa_status{{126, 88, 118, 16}, "---"}; + + Text text_status_msg{{0, 110, 240, 48}, ""}; + + Button button_refresh{{8, 240, 72, 24}, "Refresh"}; + Button button_toggle_clk5{{88, 240, 72, 24}, "CLK5_T"}; + Button button_done{{168, 240, 64, 24}, "Done"}; +}; +#endif + /* BasebandStatusView ***************************************************/ class BasebandStatusView : public View { diff --git a/firmware/application/clock_manager.cpp b/firmware/application/clock_manager.cpp index b1b33d10a..2a6bb156c 100644 --- a/firmware/application/clock_manager.cpp +++ b/firmware/application/clock_manager.cpp @@ -246,11 +246,11 @@ constexpr ClockControls si5351a_clock_control_common{{ {ClockControl::ClockCurrentDrive::_4mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, ClockControl::MultiSynthSource::PLLA, ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off}, // CLK3: CLKOUT (optional) SMA Port P1 {ClockControl::ClockCurrentDrive::_8mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, ClockControl::MultiSynthSource::PLLA, ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off}, - // CLK4: PRALINE RFFC5072 reference (40 MHz) - INVERTED, 6mA, Integer mode + // CLK4: PRALINE MAX2831 reference (40 MHz) - INVERTED per hackrf_usb, 4mA, Integer mode + {ClockControl::ClockCurrentDrive::_4mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Invert, ClockControl::MultiSynthSource::PLLA, ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off}, + // CLK5: PRALINE RFFC5072 reference (40 MHz) - INVERTED, 6mA, Integer mode // This matches HackRF One OG configuration for RFFC5072 {ClockControl::ClockCurrentDrive::_6mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Invert, ClockControl::MultiSynthSource::PLLA, ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off}, - // CLK5: PRALINE MAX2831 reference (40 MHz) - INVERTED per hackrf_usb, 4mA, Integer mode - {ClockControl::ClockCurrentDrive::_4mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Invert, ClockControl::MultiSynthSource::PLLA, ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off}, // CLK6: SMA Port P2 {ClockControl::ClockCurrentDrive::_8mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, ClockControl::MultiSynthSource::PLLA, ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off}, #else @@ -401,8 +401,8 @@ void ClockManager::init_clock_generator() { /* PRALINE uses Si5351A with: * CLK0 = AFE_CLK (codec/FPGA sample clock) * CLK1 = SCT_CLK (FPGA timing clock at 2x sample rate) - * CLK4 = first IF (RFFC5072) - * CLK5 = second IF (MAX2831) + * CLK4 = second IF (MAX2831) + * CLK5 = first IF (RFFC5072) * Uses PLLA on XTAL only (no CLKIN support). */ @@ -489,6 +489,21 @@ void ClockManager::init_clock_generator() { // CRITICAL: Add delay to ensure Si5351 writes complete before I2C bus stops chThdSleepMilliseconds(100); + + // ===== ADD THIS SAFETY BLOCK ===== + // Pre-configure CLK4/CLK5 with correct settings including inversion. + // This ensures the registers have correct values even if enable_if_clocks() + // is not called or fails. The clocks will still be powered off until + // enable_if_clocks() enables the outputs. + + // CLK5: OFF (for now), Integer, PLLA, INVERTED, MS_Self, 6mA = 0xDE + // (Same as 0x5E but with bit 7 set for power off) + clock_generator.write_register(21, 0xDE); + + // CLK4: OFF (for now), Integer, PLLA, INVERTED, MS_Self, 4mA = 0xDD + clock_generator.write_register(20, 0xDD); + // ===== END SAFETY BLOCK ===== + #else // Wait for PLL(s) to lock - with timeout to prevent hang uint8_t device_status_mask = hackrf_r9 @@ -496,14 +511,8 @@ void ClockManager::init_clock_generator() { : (ref_pll == ClockControl::MultiSynthSource::PLLB) ? 0x40 : 0x20; -#ifndef PRALINE + while ((clock_generator.device_status() & device_status_mask) != 0); -#else - uint32_t pll_timeout = 100000; - while ((clock_generator.device_status() & device_status_mask) != 0 && pll_timeout > 0) { - pll_timeout--; - } -#endif clock_generator.set_clock_control( clock_generator_output_mcu_clkin, @@ -579,11 +588,11 @@ void ClockManager::enable_codec_clocks() { #ifdef PRALINE /* PRALINE: CLK0 (AFE_CLK) for codec/FPGA, CLK1 (SCT_CLK) for FPGA timing. * Reference hackrf_core.c shows PRALINE needs both CLK0 and CLK1. */ - clock_generator.enable_clock(clock_generator_output_og_codec); /* CLK0 */ - clock_generator.enable_clock(clock_generator_output_og_cpld); /* CLK1 */ + clock_generator.enable_clock(clock_generator_output_og_codec); /* CLK0 MAX5864*/ + clock_generator.enable_clock(clock_generator_output_og_cpld); /* CLK1 iCE40 FPGA*/ + clock_generator.enable_clock(clock_generator_output_og_sgpio); /* CLK2 LPC43xx*/ clock_generator.enable_output_mask( - (1U << clock_generator_output_og_codec) | - (1U << clock_generator_output_og_cpld)); + (1U << clock_generator_output_og_codec) | (1U << clock_generator_output_og_cpld) | (1U << clock_generator_output_og_sgpio)); #else if (hackrf_r9) { clock_generator.enable_clock(clock_generator_output_r9_sgpio); @@ -611,12 +620,12 @@ void ClockManager::disable_codec_clocks() { * CLKx_DISABLE_STATE. */ #ifdef PRALINE - /* PRALINE: CLK0 (AFE_CLK) and CLK1 (SCT_CLK) used for codec/FPGA */ + /* PRALINE: CLK0 (AFE_CLK), CLK1 (SCT_CLK), and CLK2 MCU used for codec/FPGA */ clock_generator.disable_output_mask( - (1U << clock_generator_output_og_codec) | - (1U << clock_generator_output_og_cpld)); + (1U << clock_generator_output_og_codec) | (1U << clock_generator_output_og_cpld) | (1U << clock_generator_output_og_sgpio)); clock_generator.disable_clock(clock_generator_output_og_codec); clock_generator.disable_clock(clock_generator_output_og_cpld); + clock_generator.disable_clock(clock_generator_output_og_sgpio); #else if (hackrf_r9) { clock_generator.disable_output_mask(1U << clock_generator_output_r9_sgpio); @@ -633,7 +642,28 @@ void ClockManager::disable_codec_clocks() { void ClockManager::enable_if_clocks() { #ifdef PRALINE - /* PRALINE uses CLK4 (first IF) and CLK5 (second IF) like original HackRF One */ + /* PRALINE: CLK4=MAX2831, CLK5=RFFC5072 + * + * Force-write complete configuration to guarantee correct setup. + * Added force-write to verify correct registers are applying necessary register clock settings. + */ + + // Configure and enable CLK4 (MAX2831) + // Register 20: ON, Integer, PLLA, INVERTED, MS_Self, 4mA = 0x5D + clock_generator.write_register(20, 0x5D); + + // Configure and enable CLK5 (RFFC5072) - CRITICAL! + // Register 21: ON, Integer, PLLA, INVERTED, MS_Self, 6mA = 0x5E + clock_generator.write_register(21, 0x5E); + + // Enable outputs (register 3, bits 4 and 5 = 0) + uint8_t reg3 = clock_generator.read_register(3); + reg3 &= ~0x30; + clock_generator.write_register(3, reg3); + + chThdSleepMilliseconds(10); + + /* PRALINE uses CLK5 (first IF) and CLK4 (second IF) */ clock_generator.enable_clock(clock_generator_output_og_first_if); clock_generator.enable_output_mask(1U << clock_generator_output_og_first_if); clock_generator.enable_clock(clock_generator_output_og_second_if); diff --git a/firmware/application/hw/rffc507x.cpp b/firmware/application/hw/rffc507x.cpp index e8c2041b4..a7793c398 100644 --- a/firmware/application/hw/rffc507x.cpp +++ b/firmware/application/hw/rffc507x.cpp @@ -65,7 +65,11 @@ constexpr halrtcnt_t ticks_during_reset = (base_m4_clk_f * seconds_during_reset constexpr float seconds_after_reset = 5.0e-6; constexpr halrtcnt_t ticks_after_reset = (base_m4_clk_f * seconds_after_reset + 1); +#ifdef PRALINE +constexpr rf::Frequency reference_frequency = 40000000ULL; +#else constexpr auto reference_frequency = rffc5072_reference_f; +#endif namespace vco { @@ -114,31 +118,9 @@ constexpr size_t divider_min = 1U << divider_log2_min; constexpr size_t divider_max = 1U << divider_log2_max; constexpr size_t divider_log2(const rf::Frequency vco_frequency) { -#ifdef PRALINE - // PRALINE FIX: Avoid N register overflow (9-bit max = 511) - // With 40 MHz reference: - // - For VCO=5400 MHz, presc=÷2: N = (5400×2)/40 = 270 ✓ - // - For VCO=5400 MHz, presc=÷4: N = (5400×4)/40 = 540 ✗ OVERFLOW! - // - // Maximum safe VCO for ÷4 prescaler: - // N_max = 511, so VCO_max = (511 × 40) / 4 = 5110 MHz - // - // Use ÷4 only if VCO < 5110 MHz AND VCO > 3200 MHz - // Use ÷2 for VCO >= 5110 MHz to avoid overflow - - constexpr rf::Frequency overflow_threshold = 5110000000ULL; // Max VCO for ÷4 - constexpr rf::Frequency min_presc4_freq = 3200000000ULL; // Min VCO for ÷4 - - if ((vco_frequency > min_presc4_freq) && (vco_frequency < overflow_threshold)) { - return divider_log2_max; // ÷4 prescaler - } else { - return divider_log2_min; // ÷2 prescaler - } -#else return (vco_frequency > (prescaler::divider_min * prescaler::max_frequency)) ? prescaler::divider_log2_max : prescaler::divider_log2_min; -#endif } } /* namespace prescaler */ @@ -161,11 +143,7 @@ struct SynthConfig { const size_t prescaler_divider_log2 = prescaler::divider_log2(vco_frequency); -#ifndef PRALINE const uint64_t prescaled_lo_q24 = vco_frequency << (24 - prescaler_divider_log2); -#else - const uint64_t prescaled_lo_q24 = vco_frequency << (24 + prescaler_divider_log2); -#endif const uint64_t n_divider_q24 = prescaled_lo_q24 / reference_frequency; #ifdef PRALINE diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index 0ad489bd1..770ad8264 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -58,6 +58,10 @@ using asahi_kasei::ak4951::AK4951; extern "C" { #include "platform_detect.h" + +#ifdef PRALINE +#include "fpga_bridge.h" +#endif } namespace portapack { @@ -547,6 +551,12 @@ static void initialize_boot_splash_screen() { */ init_status_t init() { +#ifdef PRALINE + /* 1. HOLD FPGA IN RESET (Active Low) */ + // P5_2 is GPIO2[11] (FPGA CRESET) + palClearPad(GPIO2, 11); +#endif + set_idivc_base_clocks(cgu::CLK_SEL::IDIVC); i2c0.start(i2c_config_boot_clock); @@ -579,6 +589,25 @@ init_status_t init() { clock_manager.init_clock_generator(); +#ifdef PRALINE + // Force CLK4/CLK5 configuration BEFORE I2C bus stops + // This ensures the inversion bits are written while I2C is still active + + // CLK4 (MAX2831): ON, Integer, PLLA, INVERTED, MS_Self, 4mA = 0x5D + clock_manager.si5351_write_register(20, 0x5D); + + // CLK5 (RFFC5072): ON, Integer, PLLA, INVERTED, MS_Self, 6mA = 0x5E + clock_manager.si5351_write_register(21, 0x5E); + + // Enable CLK4 and CLK5 outputs NOW (before I2C stops) + uint8_t reg3 = clock_manager.si5351_read_register(3); + reg3 &= ~0x30; // Clear bits 4 and 5 to enable + clock_manager.si5351_write_register(3, reg3); + + // Wait for clocks to stabilize + chThdSleepMilliseconds(10); +#endif + i2c0.stop(); chThdSleepMilliseconds(10); @@ -618,6 +647,27 @@ init_status_t init() { clock_manager.enable_if_clocks(); clock_manager.enable_codec_clocks(); +#ifdef PRALINE + chThdSleepMilliseconds(20); + + // This function returns LD_SUCCESS (0) if the FPGA confirms the bitstream + // Call fpga_bridge_init and continue boot regardless of result + // (Watchdog was resetting device when we halted with while(1)) + int load_result = fpga_bridge_init(); + (void)load_result; // Ignore result for now, just let boot continue + + /* RELEASE FPGA RESET */ + // FPGA wakes up and latches the stable 40MHz CLK1 + // P5_2 is GPIO2[11] (FPGA CRESET) + palSetPad(GPIO2, 11); + + // Allow FPGA and related logic a brief stabilization period without busy-waiting + chThdSleepMilliseconds(10); + + // Keep LEDs off after FPGA load + LPC_GPIO->SET[2] = (1 << 1) | (1 << 2) | (1 << 8); +#endif + radio::init(); sdcStart(&SDCD1, nullptr); @@ -637,9 +687,6 @@ init_status_t init() { return_code = init_status_t::INIT_HACKRF_CPLD_FAILED; } -#else - // HackRF Pro (PRALINE) uses FPGA - already loaded in board.cpp __early_init() - // via fpga_bridge_init(), so nothing to do here #endif if (lcd_fast_setup) diff --git a/firmware/application/radio.cpp b/firmware/application/radio.cpp index 09c124473..c84f6b07d 100644 --- a/firmware/application/radio.cpp +++ b/firmware/application/radio.cpp @@ -156,8 +156,9 @@ void init() { #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 - fpga_debug_register_write(2, 0x00); // RX_DECIM=0 (no decimation for testing) + // These FPGA registers control DC_BLOCK, Q-Inv, QUARTER SHIFT, and Decimation. + fpga_debug_register_write(1, 0x03); // DC_BLOCK=1, QUARTER_SHIFT=1, Q_INVERT=0 + fpga_debug_register_write(2, 0x03); // RX_DECIM=8 (2^3 decimation for testing 20 MHz -> 2.5 MHz with audio for now) fpga_debug_register_write(3, 0x00); // TX_CTRL=0 fpga_debug_register_write(4, 0x00); // TX_INTRP=0 fpga_debug_register_write(5, 0x00); // TX_PSTEP=0 @@ -209,8 +210,9 @@ void set_direction(const rf::Direction new_direction) { #ifdef PRALINE - // CORRECT: FPGA register 1 only controls DC_BLOCK - fpga_debug_register_write(1, 0x01); // DC_BLOCK only, no QUARTER_SHIFT! + // This FPGA registers fix DC_BLOCK, Q-Inv, QUARTER SHIFT, and Decimation. + fpga_debug_register_write(1, 0x03); // DC_BLOCK, Q-Inv, no-QUARTER_SHIFT. + fpga_debug_register_write(2, 0x03); // RX_DECIM=8 (2^3 decimation for testing 20 MHz -> 2.5 MHz with audio for now) // Q inversion controlled by GPIO0[13] (SGPIO12), not FPGA register bool q_invert = mixer_invert ^ baseband_invert; diff --git a/firmware/chibios-portapack/boards/PORTAPACK_APPLICATION/board.cpp b/firmware/chibios-portapack/boards/PORTAPACK_APPLICATION/board.cpp index 43e1c9cd0..5a738b482 100755 --- a/firmware/chibios-portapack/boards/PORTAPACK_APPLICATION/board.cpp +++ b/firmware/chibios-portapack/boards/PORTAPACK_APPLICATION/board.cpp @@ -24,13 +24,6 @@ // Declare wrapper function. board.cpp to avoid conflicting gpio_t definitions. bool hackrf_r9; -// Declare the bridge function (no need to include HackRF headers here) -#ifdef PRALINE -extern "C" { - int fpga_bridge_init(void); -} -#endif - #if HAL_USE_PAL || defined(__DOXYGEN__) /** * @brief PAL setup. @@ -1043,10 +1036,8 @@ extern "C" void boardInit(void) { LPC_SCU->SFSP[1][0] = 0xF6; /* SGPIO7: P1_0 function 6, HOST_DATA7 */ { volatile uint32_t delay = 200000; while(delay--); } - // 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 - // Use LEDs to check if initi is successful. + // Trigger FPGA bitstream loading via fpga bridge in portapack.cpp + // Use LEDs to check if boardInit initialization is successful. // Setup LED pin directions // LED1 (USB) = GPIO2[1], LED2 (RX) = GPIO2[2], LED3 (TX) = GPIO2[8] @@ -1057,14 +1048,6 @@ extern "C" void boardInit(void) { LPC_GPIO->SET[2] = (1 << 1) | (1 << 2) | (1 << 8); { volatile uint32_t delay = 200000; while(delay--); } - // Call fpga_bridge_init and continue boot regardless of result - // (Watchdog was resetting device when we halted with while(1)) - int load_result = fpga_bridge_init(); - (void)load_result; // Ignore result for now, just let boot continue - { volatile uint32_t delay = 200000; while(delay--); } - - // Keep LEDs off after FPGA load - LPC_GPIO->SET[2] = (1 << 1) | (1 << 2) | (1 << 8); #endif }