mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-15 19:13:00 +00:00
Next praline clean up (fixed BLE RX crashes) (#3080)
* Cleaned up #ifndef PRALINE and updated logic to being with #ifdef PRALINE entries where possible to make logic flow for PRALINE code execution pipeline clearer. Cleaned up compiletime warnings for PRALINE related codebase updates. * Addressed comments provided by copilot during PR review. Combed through frequency definitions for consistency between PLL A and PLL B register definitions for CLKs 0-7. Ensured CLK3/LK6 <- SMA PORTs and CLK7 <- not utiliized are disabled during core development phase to support root cause analysis of any spectral artifacts. Updated MCU frequency to 40MHz to ensure audio harmonics are outside FM radio band range (< 80 MHz, >120MHz) and added comments clarifying choice of 40 over 10 MHz for potential future root cause analysis in other bands where audio may be expected as needed. Added CLK6 and CLK7 to Clocks Status View Debug display. Moved CLK defintions and PLL instantiations for components that are most RF sensitive to PLL A. Left others in PLL B. That is move FPGA CLK1 to PLL B, while moving CLK2, CLK4, and CLK5 to PLL A. * Cleaned up PLL A and B XTAL reference checks relative to 800 MHz. * Encapsulated HackRF Pro Praline debug and status vies into a single Pro Debug submenu as part of clean up. * Fixed BLE RX Out of Memory error. Updated LPC43xx ld scripts to accouint for additional HackRF Pro praline memory. * Addressed copilot comments for ble_rx_app by adding recent_entries_view.set_dirty. Updated ble_rx_app for easier use with heap limit set to one less than recent entries max limit. * Addressed copilot comments by updating comment clarity in source files. Updated ui_debug to allow for return reference if set for PRO debug menu item. * Improved readability of intialization parameters for the FPGA registers, and addressed 20Mhz nulls by initializing DC Notch width with standard setting, and DC Adaptiation rate with a balanced setting. * Ran format-code.sh * Added option to allow for user to set number if entries in recent list. Default is set to a relatively stable 32. * Removed #ifdef PRALINE pragmas from ble_rx_app such that HackRF One can also use the updated UI widget to allow for user to set number of entries in recent list. * Ran format-code.sh
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
|
||||
// Check if PRALINE was passed from CMake
|
||||
#ifdef PRALINE
|
||||
#include "fpga_bridge.h"
|
||||
|
||||
// Necessary headers
|
||||
#include "lz4_blk.h"
|
||||
@@ -120,6 +121,27 @@
|
||||
#define FPGA_CDONE_PIN 14
|
||||
#define FPGA_SPI_CS_PORT 2
|
||||
#define FPGA_SPI_CS_PIN 10
|
||||
|
||||
// ============================================================================
|
||||
// Canonical Default Values - SINGLE SOURCE OF TRUTH
|
||||
// ============================================================================
|
||||
/* Define the canonical RX defaults in ONE place */
|
||||
#define FPGA_RX_DEFAULT_DC_WIDTH 0x04 /* Typical for 40MHz stability */
|
||||
#define FPGA_RX_DEFAULT_ADAPT_RATE 0x08 /* Typical for 40MHz stability */
|
||||
#define FPGA_RX_DEFAULT_DIGITAL_GAIN 0x00 /* No shift initially */
|
||||
|
||||
/* Define TX defaults */
|
||||
#define FPGA_TX_DEFAULT_NCO_CTRL 0x00 /* NCO disabled */
|
||||
#define FPGA_TX_DEFAULT_INTERP 0x00 /* No interpolation */
|
||||
#define FPGA_TX_DEFAULT_PHASE_STEP 0x00 /* Zero phase step */
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Static Variables - Declare BEFORE use
|
||||
// ============================================================================
|
||||
static fpga_mode_t current_mode = FPGA_MODE_OFF;
|
||||
// Cached register values for debug reads (since reads may require mode switch)
|
||||
static uint8_t fpga_reg_cache[6] = {0, 0x01, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
// Context structure for SPIFI-based reading
|
||||
struct spifi_fpga_read_ctx {
|
||||
@@ -129,6 +151,10 @@
|
||||
uint8_t buffer[4096 + 2]; // Compressed block + next size
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Low-Level Helper Functions
|
||||
// ============================================================================
|
||||
|
||||
// Simple delay loop
|
||||
static void delay_cycles(volatile uint32_t count) {
|
||||
while (count--) {
|
||||
@@ -224,14 +250,19 @@
|
||||
// FPGA Register Map:
|
||||
// Reg 1 (CTRL): DC_BLOCK(b0), QUARTER_SHIFT_EN(b1), QUARTER_SHIFT_UP(b2), PRBS(b6), TRIGGER_EN(b7)
|
||||
// Reg 2 (RX_DECIM): Decimation ratio [2:0]
|
||||
// Reg 3 (TX_CTRL): NCO_EN(b0)
|
||||
// Reg 4 (TX_INTRP): Interpolation ratio [2:0]
|
||||
// Reg 5 (TX_PSTEP): NCO phase step [7:0]
|
||||
// Reg 3 (RX/TX): RX Digital Shift OR TX NCO Control
|
||||
// Reg 4 (RX_DC_BLOCK_WIDTH/TX_INTERP) [2:0]
|
||||
// Reg 5 (RX_DC_ADAPT_RATE/TX_PSTEP) [7:0]
|
||||
//
|
||||
// SPI Protocol:
|
||||
// Read: Send [reg & 0x7F, 0x00, 0x00] -> value in byte 3
|
||||
// Write: Send [(reg | 0x80), value, 0x00]
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// SPI Mode Switching
|
||||
// ============================================================================
|
||||
|
||||
// Configure SSP1 for iCE40 FPGA register access (Mode 3, 8-bit)
|
||||
static void ssp1_set_mode_ice40(void) {
|
||||
SSP1_CR1_LOCAL = 0; // Disable SSP1
|
||||
@@ -252,6 +283,11 @@
|
||||
SSP1_CR1_LOCAL = SSP_CR1_SSE; // Enable SSP1
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Low-Level SPI Register Access (internal, no mode switch)
|
||||
// ============================================================================
|
||||
|
||||
// Read an FPGA register via SPI
|
||||
static uint8_t fpga_spi_read(uint8_t reg) {
|
||||
uint8_t value;
|
||||
@@ -271,31 +307,10 @@
|
||||
ssp1_transfer_byte(0x00); // Dummy byte
|
||||
fpga_cs_high();
|
||||
}
|
||||
|
||||
// Initialize FPGA registers after bitstream load
|
||||
// This is equivalent to fpga_init() in the reference HackRF firmware
|
||||
static void fpga_register_init(void) {
|
||||
// Already in iCE40 mode after programming, so we can directly access registers
|
||||
|
||||
// Register 1 (CTRL): Enable DC block (bit 0), disable everything else
|
||||
// DC_BLOCK is CRITICAL for RX to work!
|
||||
fpga_spi_write(1, 0x01); // DC_BLOCK = 1
|
||||
|
||||
// Register 2 (RX_DECIM): No decimation
|
||||
fpga_spi_write(2, 0x00);
|
||||
|
||||
// Register 3 (TX_CTRL): Disable NCO
|
||||
fpga_spi_write(3, 0x00);
|
||||
|
||||
// Register 4 (TX_INTRP): No interpolation
|
||||
fpga_spi_write(4, 0x00);
|
||||
|
||||
// Register 5 (TX_PSTEP): Zero phase step
|
||||
fpga_spi_write(5, 0x00);
|
||||
}
|
||||
|
||||
// Cached register values for debug reads (since reads may require mode switch)
|
||||
static uint8_t fpga_reg_cache[6] = {0, 0x01, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
// ============================================================================
|
||||
// Public Debug Functions (switch SPI mode, access register, switch back)
|
||||
// ============================================================================
|
||||
|
||||
// Public function to read FPGA register (callable from C++ application code)
|
||||
// Switches SPI mode, reads register, switches back
|
||||
@@ -322,6 +337,139 @@
|
||||
fpga_reg_cache[reg] = value;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Public Register Access (wraps debug functions)
|
||||
// ============================================================================
|
||||
|
||||
uint8_t fpga_register_read(uint8_t reg) {
|
||||
if (reg == 0 || reg > 5) return;
|
||||
|
||||
ssp1_set_mode_ice40();
|
||||
uint8_t val = fpga_spi_read(reg);
|
||||
ssp1_set_mode_max2831();
|
||||
|
||||
fpga_reg_cache[reg] = val;
|
||||
return val;
|
||||
}
|
||||
|
||||
void fpga_register_write(uint8_t reg, uint8_t value) {
|
||||
if (reg == 0 || reg > 5) return;
|
||||
|
||||
ssp1_set_mode_ice40();
|
||||
fpga_spi_write(reg, value);
|
||||
ssp1_set_mode_max2831();
|
||||
|
||||
fpga_reg_cache[reg] = value;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Mode Management
|
||||
// ============================================================================
|
||||
|
||||
fpga_mode_t fpga_get_mode(void) {
|
||||
return current_mode;
|
||||
}
|
||||
|
||||
/* fpga_set_mode with consistent values */
|
||||
void fpga_set_mode(fpga_mode_t mode) {
|
||||
current_mode = mode;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// RX Mode Functions (with mode assertion)
|
||||
// ============================================================================
|
||||
|
||||
/* RX decimation */
|
||||
void fpga_rx_set_decimation(uint8_t ratio) {
|
||||
if (current_mode != FPGA_MODE_RX) return;
|
||||
fpga_register_write(FPGA_REG_DECIM, ratio & 0x07);
|
||||
}
|
||||
|
||||
/* RX DC block enable (bit 0 of register 1) */
|
||||
void fpga_rx_enable_dc_block(bool enable) {
|
||||
if (current_mode != FPGA_MODE_RX) return;
|
||||
uint8_t ctrl = fpga_register_read(FPGA_REG_CTRL);
|
||||
if (enable)
|
||||
ctrl |= FPGA_CTRL_DC_BLOCK_EN;
|
||||
else
|
||||
ctrl &= ~FPGA_CTRL_DC_BLOCK_EN;
|
||||
fpga_register_write(FPGA_REG_CTRL, ctrl);
|
||||
}
|
||||
|
||||
/* RX Functions with mode assertion */
|
||||
void fpga_rx_set_digital_gain(uint8_t shift) {
|
||||
if (current_mode != FPGA_MODE_RX) {
|
||||
/* Log error or assert - wrong mode! */
|
||||
return;
|
||||
}
|
||||
fpga_register_write(FPGA_REG_SHARED_3, shift & FPGA_RX_GAIN_SHIFT_MASK);
|
||||
}
|
||||
|
||||
void fpga_rx_set_dc_block_width(uint8_t width) {
|
||||
if (current_mode != FPGA_MODE_RX) return;
|
||||
fpga_register_write(FPGA_REG_SHARED_4, width & FPGA_RX_DC_WIDTH_MASK);
|
||||
}
|
||||
|
||||
void fpga_rx_set_dc_adapt_rate(uint8_t rate) {
|
||||
if (current_mode != FPGA_MODE_RX) return;
|
||||
fpga_register_write(FPGA_REG_SHARED_5, rate);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// TX Mode Functions (with mode assertion)
|
||||
// ============================================================================
|
||||
|
||||
/* TX Functions with mode assertion */
|
||||
void fpga_tx_set_nco_enable(bool enable) {
|
||||
if (current_mode != FPGA_MODE_TX) return;
|
||||
uint8_t val = fpga_register_read(FPGA_REG_SHARED_3);
|
||||
if (enable)
|
||||
val |= FPGA_TX_NCO_EN;
|
||||
else
|
||||
val &= ~FPGA_TX_NCO_EN;
|
||||
fpga_register_write(FPGA_REG_SHARED_3, val);
|
||||
}
|
||||
|
||||
void fpga_tx_set_interpolation(uint8_t ratio) {
|
||||
if (current_mode != FPGA_MODE_TX) return;
|
||||
fpga_register_write(FPGA_REG_SHARED_4, ratio & FPGA_TX_INTERP_MASK);
|
||||
}
|
||||
|
||||
void fpga_tx_set_phase_step(uint8_t step) {
|
||||
if (current_mode != FPGA_MODE_TX) return;
|
||||
fpga_register_write(FPGA_REG_SHARED_5, step);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// FPGA Register Initialization (called after bitstream load)
|
||||
// ============================================================================
|
||||
|
||||
// Initialize FPGA registers after bitstream load
|
||||
// This is equivalent to fpga_init() in the reference HackRF firmware
|
||||
/* fpga_register_init with consistent values */
|
||||
static void fpga_register_init(void) {
|
||||
|
||||
/* Boot into RX mode */
|
||||
current_mode = FPGA_MODE_RX;
|
||||
|
||||
fpga_spi_write(FPGA_REG_CTRL, FPGA_CTRL_DC_BLOCK_EN);
|
||||
fpga_spi_write(FPGA_REG_DECIM, 0x00);
|
||||
fpga_spi_write(FPGA_REG_SHARED_3, FPGA_RX_DEFAULT_DIGITAL_GAIN);
|
||||
fpga_spi_write(FPGA_REG_SHARED_4, FPGA_RX_DEFAULT_DC_WIDTH);
|
||||
fpga_spi_write(FPGA_REG_SHARED_5, FPGA_RX_DEFAULT_ADAPT_RATE);
|
||||
|
||||
/* Update cache */
|
||||
fpga_reg_cache[1] = FPGA_CTRL_DC_BLOCK_EN;
|
||||
fpga_reg_cache[2] = 0x00;
|
||||
fpga_reg_cache[3] = FPGA_RX_DEFAULT_DIGITAL_GAIN;
|
||||
fpga_reg_cache[4] = FPGA_RX_DEFAULT_DC_WIDTH;
|
||||
fpga_reg_cache[5] = FPGA_RX_DEFAULT_ADAPT_RATE;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// LZ4 Decompression for FPGA Bitstream
|
||||
// ============================================================================
|
||||
|
||||
// SPIFI-based read callback for LZ4 decompression
|
||||
// Reads from SPIFI memory-mapped address instead of using SPI flash driver
|
||||
static size_t spifi_fpga_read_block_cb(void* _ctx, uint8_t* out_buffer) {
|
||||
@@ -415,6 +563,10 @@
|
||||
return success;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Main Initialization Entry Point
|
||||
// ============================================================================
|
||||
|
||||
int fpga_bridge_init(void) {
|
||||
// Enable SSP1 clock for FPGA programming
|
||||
// Use PLL1 (204MHz) to match original HackRF - IRC (12MHz) is 17x too slow
|
||||
|
||||
@@ -12,15 +12,131 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef PRALINE
|
||||
|
||||
/* FPGA Register Map Address 0x03 (Dual Purpose) */
|
||||
#define FPGA_REG_RX_DIGITAL_GAIN 0x03 /* Digital Shift / scaling (RX Mode) */
|
||||
#define FPGA_REG_TX_CONTROL 0x03 /* NCO_EN and TX flags (TX Mode) */
|
||||
|
||||
/* FPGA Register Map Address 0x04 (Shared) */
|
||||
#define FPGA_REG_RX_DC_BLOCK_WIDTH 0x04 /* Notch filter cutoff (RX Mode) */
|
||||
#define FPGA_REG_TX_INTERP 0x04 /* Interpolation ratio (TX Mode) */
|
||||
|
||||
/* FPGA Register Map Address 0x05 (Shared) */
|
||||
#define FPGA_REG_RX_DC_ADAPT_RATE 0x05 /* Settle time/Integration (RX Mode) */
|
||||
#define FPGA_REG_TX_PHASE_STEP 0x05 /* NCO frequency step (TX Mode) */
|
||||
|
||||
/*
|
||||
* Initialize the FPGA - loads bitstream from SPIFI flash
|
||||
* Returns: 0 on success, non-zero on failure
|
||||
* FPGA Operating Mode
|
||||
*/
|
||||
typedef enum {
|
||||
FPGA_MODE_OFF = 0,
|
||||
FPGA_MODE_RX,
|
||||
FPGA_MODE_TX
|
||||
} fpga_mode_t;
|
||||
|
||||
/*
|
||||
* FPGA Register Addresses
|
||||
* Note: Registers 3-5 are dual-purpose (meaning depends on RX/TX mode)
|
||||
*/
|
||||
#define FPGA_REG_CTRL 0x01 /* Control register */
|
||||
#define FPGA_REG_DECIM 0x02 /* Decimation (RX) / unused (TX) */
|
||||
#define FPGA_REG_SHARED_3 0x03 /* Dual-purpose register */
|
||||
#define FPGA_REG_SHARED_4 0x04 /* Dual-purpose register */
|
||||
#define FPGA_REG_SHARED_5 0x05 /* Dual-purpose register */
|
||||
|
||||
/*
|
||||
* Register 1 (CTRL) Bit Definitions
|
||||
*/
|
||||
#define FPGA_CTRL_DC_BLOCK_EN (1 << 0) /* DC block enable */
|
||||
#define FPGA_CTRL_QUARTER_SHIFT_EN (1 << 1) /* Quarter-rate shift enable */
|
||||
#define FPGA_CTRL_QUARTER_SHIFT_UP (1 << 2) /* Shift direction: 1=up, 0=down */
|
||||
#define FPGA_CTRL_TX_MODE (1 << 5) /* TX mode indicator (if applicable) */
|
||||
#define FPGA_CTRL_PRBS_EN (1 << 6) /* PRBS test mode */
|
||||
#define FPGA_CTRL_TRIGGER_EN (1 << 7) /* External trigger enable */
|
||||
|
||||
/*
|
||||
* Register 3 Dual-Purpose Definitions
|
||||
*/
|
||||
/* RX Mode: Digital gain/shift */
|
||||
#define FPGA_REG3_RX_DIGITAL_GAIN 0x03
|
||||
#define FPGA_RX_GAIN_SHIFT_MASK 0x0F /* Bits [3:0] - shift amount */
|
||||
|
||||
/* TX Mode: NCO control */
|
||||
#define FPGA_REG3_TX_NCO_CTRL 0x03
|
||||
#define FPGA_TX_NCO_EN (1 << 0) /* NCO enable */
|
||||
#define FPGA_TX_NCO_INVERT (1 << 1) /* Invert spectrum */
|
||||
|
||||
/*
|
||||
* Register 4 Dual-Purpose Definitions
|
||||
*/
|
||||
/* RX Mode: DC block notch width */
|
||||
#define FPGA_REG4_RX_DC_WIDTH 0x04
|
||||
#define FPGA_RX_DC_WIDTH_MASK 0x07 /* Bits [2:0] */
|
||||
|
||||
/* TX Mode: Interpolation ratio */
|
||||
#define FPGA_REG4_TX_INTERP 0x04
|
||||
#define FPGA_TX_INTERP_MASK 0x07 /* Bits [2:0] */
|
||||
|
||||
/*
|
||||
* Register 5 Dual-Purpose Definitions
|
||||
*/
|
||||
/* RX Mode: DC block adaptation rate */
|
||||
#define FPGA_REG5_RX_DC_RATE 0x05
|
||||
#define FPGA_RX_DC_RATE_MASK 0xFF /* Bits [7:0] */
|
||||
|
||||
/* TX Mode: NCO phase step (frequency) */
|
||||
#define FPGA_REG5_TX_PHASE_STEP 0x05
|
||||
#define FPGA_TX_PHASE_STEP_MASK 0xFF /* Bits [7:0] */
|
||||
|
||||
/* Export default values so other methods can use them */
|
||||
#define FPGA_RX_DEFAULT_DIGITAL_GAIN 0x00
|
||||
#define FPGA_RX_DEFAULT_DC_WIDTH 0x04
|
||||
#define FPGA_RX_DEFAULT_ADAPT_RATE 0x08
|
||||
|
||||
/*
|
||||
* Core Functions
|
||||
*/
|
||||
|
||||
/* Initialize the FPGA - loads bitstream from SPIFI flash
|
||||
* Returns: 0 on success, non-zero on failure */
|
||||
int fpga_bridge_init(void);
|
||||
|
||||
/* Set operating mode - MUST be called before using mode-specific functions
|
||||
* This ensures registers 3-5 are interpreted correctly */
|
||||
void fpga_set_mode(fpga_mode_t mode);
|
||||
|
||||
/* Get current operating mode */
|
||||
fpga_mode_t fpga_get_mode(void);
|
||||
|
||||
/*
|
||||
* Low-Level Register Access (use with caution)
|
||||
*/
|
||||
uint8_t fpga_register_read(uint8_t reg);
|
||||
void fpga_register_write(uint8_t reg, uint8_t value);
|
||||
|
||||
/*
|
||||
* RX Mode Functions (only valid when mode == FPGA_MODE_RX)
|
||||
*/
|
||||
void fpga_rx_set_decimation(uint8_t ratio);
|
||||
void fpga_rx_set_digital_gain(uint8_t shift);
|
||||
void fpga_rx_set_dc_block_width(uint8_t width);
|
||||
void fpga_rx_set_dc_adapt_rate(uint8_t rate);
|
||||
void fpga_rx_enable_dc_block(bool enable);
|
||||
|
||||
/*
|
||||
* TX Mode Functions (only valid when mode == FPGA_MODE_TX)
|
||||
*/
|
||||
void fpga_tx_set_interpolation(uint8_t ratio);
|
||||
void fpga_tx_set_nco_enable(bool enable);
|
||||
void fpga_tx_set_phase_step(uint8_t step);
|
||||
|
||||
/*
|
||||
* Debug Functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Read an FPGA register via SPI
|
||||
* reg: Register number (1-5)
|
||||
@@ -29,9 +145,9 @@ int fpga_bridge_init(void);
|
||||
* FPGA Register Map:
|
||||
* Reg 1 (CTRL): DC_BLOCK(b0), QUARTER_SHIFT_EN(b1), QUARTER_SHIFT_UP(b2), PRBS(b6), TRIGGER_EN(b7)
|
||||
* Reg 2 (RX_DECIM): Decimation ratio [2:0]
|
||||
* Reg 3 (TX_CTRL): NCO_EN(b0)
|
||||
* Reg 4 (TX_INTRP): Interpolation ratio [2:0]
|
||||
* Reg 5 (TX_PSTEP): NCO phase step [7:0]
|
||||
* Reg 3 (RX/TX): RX Digital Shift OR TX NCO Control
|
||||
* Reg 4 (RX_DC_BLOCK_WIDTH/TX_INTERP) [2:0]
|
||||
* Reg 5 (RX_DC_ADAPT_RATE/TX_PSTEP) [7:0]
|
||||
*/
|
||||
uint8_t fpga_debug_register_read(uint8_t reg);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user