Add praline gpio (#3218)

* Implement antenna bias control for Praline and update GPIO configurations
* Add GPIO power management functions and update board initialization for Praline
* Refactor power management functions for Praline and update GPIO configurations
* Update GPIO configurations for Praline and enable power control pins. AA_EN enabled
* Refactor GPIO configuration for Praline: update array size definitions and clean up comments
* Add P1 and P2 control functions for PRALINE
* Introduced P1_Function and P2_Function enums in ClockManager to manage multiplexer control.
* mplemented set_p1_control and set_p2_control methods for configuring P1 and P2 control pins based on specified functions.
* Updated clock_manager.hpp and clock_manager.cpp to include new functionality.
* Modified MAX2837 and MAX2839 initialization to conditionally configure GPIO based on PRALINE.
* Adjusted RFFC507x and RFFC507x_SPI initialization to include GPIO setup for PRALINE.
- Refactored RF path initialization to remove unnecessary GPIO setup.
- Updated board configuration for PRALINE to reflect new GPIO settings and pin configurations.
- Cleaned up FPGA bridge code by removing unused pin configuration functions.
- Adjusted SCU array size in pal_lld.h for PRALINE.
- Enhanced hackrf_gpio.hpp to define multiplexer control pins for PRALINE.
- Modified LED setup to accommodate active-low configuration for PRALINE.

* Refactor GPIO and power control functions

- Removed unused power control function declarations from board.h.
- Enhanced gpio.hpp with new pin setup functions and GPIO control structures for PRALINE.
- Consolidated multiplexer control pin definitions into gpio_control namespace.
- Moved power control function implementations to gpio.cpp, including detailed VAA power management logic.
- Updated power control functions to handle both PRALINE and HackRF R9 configurations.
- Cleaned up hackrf_gpio.hpp by removing redundant multiplexer control definitions.

* Refactor GPIO control for PRALINE: update MAX2831 and RFFC507x configurations, add new GPIO mappings

* Refactor GPIO configurations for PRALINE: update anti-aliasing filter pin mapping, enhance LED setup logic, and add placeholder GPIO entries.

* Refactor GPIO configurations for PRALINE: update LED mappings and remove unused anti-aliasing filter GPIO entry.
This commit is contained in:
Pezsma
2026-06-11 13:24:42 +02:00
committed by GitHub
parent c7a0846645
commit 9ab367f2e0
25 changed files with 961 additions and 706 deletions
+1
View File
@@ -192,6 +192,7 @@ set(CPPSRC
${COMMON}/battery.cpp
${COMMON}/performance_counter.cpp
${COMMON}/bmpfile.cpp
${COMMON}/gpio.cpp
app_settings.cpp
audio.cpp
baseband_api.cpp
+76 -22
View File
@@ -31,6 +31,11 @@ using namespace hackrf::one;
#include "lpc43xx_cpp.hpp"
using namespace lpc43xx;
#ifdef PRALINE
#include "hackrf_gpio.hpp"
#include "gpio.hpp"
#endif
#ifdef PRALINE
extern "C" {
#include "fpga_bridge.h"
@@ -429,32 +434,10 @@ static void portapack_tcxo_disable() {
using namespace hackrf::one;
void ClockManager::init_clock_generator() {
#ifdef PRALINE
/* Route the PRALINE P22 10MHz reference to the Si5351 CLKIN pin. */
LPC_SCU->SFSP[2][10] = 0xF0;
LPC_SCU->SFSP[6][8] = 0xF4;
LPC_SCU->SFSP[6][9] = 0xF0;
LPC_SCU->SFSP[1][20] = 0xF0;
gpio_p1_ctrl0.output();
gpio_p1_ctrl1.output();
gpio_p1_ctrl2.output();
gpio_clkin_ctrl.output();
gpio_p1_ctrl0.write(0);
gpio_p1_ctrl1.write(0);
gpio_p1_ctrl2.write(1);
gpio_clkin_ctrl.write(1);
chThdSleepMilliseconds(20);
#else
// HackRF One r9: GPIO0_8 (mcu_clk_en) gates Si5351 CLK2/CLK7 to GP_CLKIN
if (hackrf_r9) {
gpio_r9_mcu_clk_en.output();
gpio_r9_mcu_clk_en.write(1);
}
#endif
clock_generator.reset();
clock_generator.set_crystal_internal_load_capacitance(CrystalInternalLoadCapacitance::XTAL_CL_8pF);
@@ -1224,3 +1207,74 @@ void ClockManager::enable_clock_output(bool enable) {
}
#endif
}
#ifdef PRALINE
void ClockManager::set_p1_control(P1_Function func) {
// Truth table based on P1_Control.csv (L=clear, H=set)
switch (func) {
case P1_Function::TriggerIn:
gpio_control::p1_ctrl2.clear();
gpio_control::p1_ctrl1.clear();
gpio_control::p1_ctrl0.clear();
break;
case P1_Function::AuxClk1:
gpio_control::p1_ctrl2.clear();
gpio_control::p1_ctrl1.clear();
gpio_control::p1_ctrl0.set();
break;
case P1_Function::ClkIn:
gpio_control::p1_ctrl2.clear();
gpio_control::p1_ctrl1.set();
gpio_control::p1_ctrl0.clear();
break;
case P1_Function::TriggerOut:
gpio_control::p1_ctrl2.clear();
gpio_control::p1_ctrl1.set();
gpio_control::p1_ctrl0.set();
break;
case P1_Function::P22_ClkIn:
gpio_control::p1_ctrl2.set();
gpio_control::p1_ctrl1.clear();
gpio_control::p1_ctrl0.clear();
break;
case P1_Function::P2_5:
gpio_control::p1_ctrl2.set();
gpio_control::p1_ctrl1.clear();
gpio_control::p1_ctrl0.set();
break;
case P1_Function::NotConnected:
gpio_control::p1_ctrl2.set();
gpio_control::p1_ctrl1.set();
gpio_control::p1_ctrl0.clear();
break;
case P1_Function::AuxClk2:
gpio_control::p1_ctrl2.set();
gpio_control::p1_ctrl1.set();
gpio_control::p1_ctrl0.set();
break;
}
}
void ClockManager::set_p2_control(P2_Function func) {
// Ensure all P2 control pins are configured as outputs
// Truth table based on P2_Control.csv (L=clear, H=set)
switch (func) {
case P2_Function::Clk3:
// CTRL0 is 'X' (don't care) according to CSV, we default it to Low (clear)
gpio_control::p2_ctrl1.clear();
gpio_control::p2_ctrl0.clear();
break;
case P2_Function::TriggerIn:
gpio_control::p2_ctrl1.set();
gpio_control::p2_ctrl0.clear();
break;
case P2_Function::TriggerOut:
gpio_control::p2_ctrl1.set();
gpio_control::p2_ctrl0.set();
break;
}
}
#endif
+23
View File
@@ -77,6 +77,29 @@ class ClockManager {
void set_reference_ppb(const int32_t ppb);
#ifdef PRALINE
enum class P1_Function {
TriggerIn, // CTRL2: L, CTRL1: L, CTRL0: L
AuxClk1, // CTRL2: L, CTRL1: L, CTRL0: H
ClkIn, // CTRL2: L, CTRL1: H, CTRL0: L
TriggerOut, // CTRL2: L, CTRL1: H, CTRL0: H
P22_ClkIn, // CTRL2: H, CTRL1: L, CTRL0: L
P2_5, // CTRL2: H, CTRL1: L, CTRL0: H
NotConnected, // CTRL2: H, CTRL1: H, CTRL0: L (NC)
AuxClk2 // CTRL2: H, CTRL1: H, CTRL0: H
};
// Multiplexer 2 (P2) Functions - Based on P2_Control.csv
enum class P2_Function {
Clk3, // CTRL1: L, CTRL0: X (Don't care)
TriggerIn, // CTRL1: H, CTRL0: L
TriggerOut // CTRL1: H, CTRL0: H
};
// Function declarations
void set_p1_control(P1_Function func);
void set_p2_control(P2_Function func);
uint8_t get_resampling_n() const { return _resampling_n; }
// Si5351 diagnostic methods
+5 -4
View File
@@ -56,6 +56,8 @@ using namespace hackrf::one;
#include "ui_navigation.hpp"
#include "gpio.hpp"
static int delayed_error = 0;
extern "C" {
@@ -185,10 +187,11 @@ void EventDispatcher::charge_deep_sleep(const bool sleep) {
SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk;
power_control::vaa_power_off();
power_control::core_power_off();
#ifdef PRALINE
// Power management and GPIO configuration for Praline hardware
gpio_vaa_disable.set();
gpio_1v2_enable.clear();
LPC_GPIO->DIR[0] &= ~0xFFFF4000;
LPC_GPIO->DIR[1] &= ~0xFFFF1000;
LPC_GPIO->DIR[2] &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 11) | (1 << 10) | (1 << 6) | (1 << 0));
@@ -196,8 +199,6 @@ void EventDispatcher::charge_deep_sleep(const bool sleep) {
LPC_GPIO->DIR[5] &= ~(1 << 16);
#else
// Power management and GPIO configuration for legacy hardware
gpio_og_vaa_disable.set();
gpio_r9_vaa_disable.clear();
LPC_GPIO->DIR[0] &= ~0xFFFF4000;
LPC_GPIO->DIR[1] &= ~0xFFFF1000;
LPC_GPIO->DIR[2] &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 11) | (1 << 10) | (1 << 6) | (1 << 0));
+13 -6
View File
@@ -103,12 +103,6 @@ void MAX2831::flush_dirty() {
void MAX2831::init() {
set_mode(Mode::Shutdown);
/* Configure GPIO pins for MAX2831 control */
gpio_max283x_enable.output();
gpio_max2831_rx_enable.output();
gpio_max2831_rxhp.output();
gpio_max2831_rxhp.write(0); /* RXHP low = 100 Hz HPF (default) */
/* Reset to default register values */
std::memcpy(_regs.data(), default_regs.data(), sizeof(_regs));
_regs_dirty = 0xFFFF;
@@ -348,6 +342,16 @@ void MAX2831::set_lpf_rf_bandwidth_rx(const uint32_t bandwidth_minimum) {
#ifdef PRALINE
uint32_t actual_bw = bandwidth_minimum;
/* The MAX2831 internal analog low-pass filter cannot go below 1.75 MHz.
* For narrow-band signals (bandwidth < 1.75 MHz), we enable the custom
* external Anti-Aliasing (AA) filter on pin P1_14 to prevent aliasing.
*/
if (actual_bw <= 1750000) {
gpio_control::aa_en.set(); // Enable external narrow AA filter
} else {
gpio_control::aa_en.clear(); // Disable external AA filter for wideband operations
}
_desired_lpf_bw = actual_bw;
if (_mode == Mode::Receive || _mode == Mode::Rx_Calibration) {
set_lpf_bandwidth_internal(actual_bw);
@@ -361,6 +365,9 @@ void MAX2831::set_lpf_rf_bandwidth_rx(const uint32_t bandwidth_minimum) {
void MAX2831::set_lpf_rf_bandwidth_tx(const uint32_t bandwidth_minimum) {
_desired_lpf_bw = bandwidth_minimum;
#ifdef PRALINE
gpio_control::aa_en.clear(); // Disable external AA filter for wideband operations
#endif
if (_mode == Mode::Transmit || _mode == Mode::Tx_Calibration) {
set_lpf_bandwidth_internal(bandwidth_minimum);
}
+6
View File
@@ -99,9 +99,11 @@ constexpr uint32_t pll_factor = 1.0 / (4.0 / 3.0 / reference_frequency) + 0.5;
void MAX2837::init() {
set_mode(Mode::Shutdown);
#ifndef PRALINE
gpio_max283x_enable.output();
gpio_max2837_rxenable.output();
gpio_max2837_txenable.output();
#endif
_map.r.tx_gain.TXVGA_GAIN_SPI_EN = 1;
_map.r.tx_gain.TXVGA_GAIN_MSB_SPI_EN = 1;
@@ -157,9 +159,11 @@ void MAX2837::set_tx_LO_iq_phase_calibration(const size_t v) {
// TX calibration , Logic pins , ENABLE, RXENABLE, TXENABLE = 1,0,1 (5dec), and Reg address 16, D1 (CAL mode 1):DO (CHIP ENABLE 1)
set_mode(Mode::Tx_Calibration); // write to ram 3 LOGIC Pins .
#ifndef PRALINE
gpio_max283x_enable.output();
gpio_max2837_rxenable.output();
gpio_max2837_txenable.output();
#endif
_map.r.spi_en.CAL_SPI = 1; // Register Settings reg address 16, D1 (CAL mode 1)
_map.r.spi_en.EN_SPI = 1; // Register Settings reg address 16, DO (CHIP ENABLE 1)
@@ -348,9 +352,11 @@ void MAX2837::set_rx_LO_iq_phase_calibration(const size_t v) {
// RX calibration , Logic pins , ENABLE, RXENABLE, TXENABLE = 1,1,0 (3dec), and Reg address 16, D1 (CAL mode 1):DO (CHIP ENABLE 1)
set_mode(Mode::Rx_Calibration); // write to ram 3 LOGIC Pins .
#ifndef PRALINE
gpio_max283x_enable.output();
gpio_max2837_rxenable.output();
gpio_max2837_txenable.output();
#endif
_map.r.spi_en.CAL_SPI = 1; // Register Settings reg address 16, D1 (CAL mode 1)
_map.r.spi_en.EN_SPI = 1; // Register Settings reg address 16, DO (CHIP ENABLE 1)
+6
View File
@@ -100,8 +100,10 @@ static int_fast8_t requested_rx_vga_gain = 0;
void MAX2839::init() {
set_mode(Mode::Shutdown);
#ifndef PRALINE
gpio_max283x_enable.output();
gpio_max2839_rxtx.output();
#endif
_map.r.rxrf_1.MIMOmode = 1; /* enable RXINB */
@@ -150,8 +152,10 @@ void MAX2839::set_tx_LO_iq_phase_calibration(const size_t v) {
// TX calibration , 2 x Logic pins , ENABLE, RXENABLE = 1,0, (2dec), and Reg address 16, D1 (CAL mode 1):DO (CHIP ENABLE 1)
set_mode(Mode::Tx_Calibration); // write to ram 3 LOGIC Pins .
#ifndef PRALINE
gpio_max283x_enable.output(); // max2839 has only 2 x pins + regs to decide mode.
gpio_max2839_rxtx.output(); // Here is combined rx & tx pin in one port.
#endif
_map.r.spi_en.CAL_SPI = 1; // Register Settings reg address 16, D1 (CAL mode 1)
_map.r.spi_en.EN_SPI = 1; // Register Settings reg address 16, DO (CHIP ENABLE 1)
@@ -390,8 +394,10 @@ void MAX2839::set_rx_LO_iq_phase_calibration(const size_t v) {
// RX calibration , Logic pins , ENABLE, RXENABLE, TXENABLE = 1,1,0 (3dec), and Reg address 16, D1 (CAL mode 1):DO (CHIP ENABLE 1)
set_mode(Mode::Rx_Calibration); // write to ram 3 LOGIC Pins .
#ifndef PRALINE
gpio_max283x_enable.output(); // max2839 has only 2 x pins + regs to decide mode.
gpio_max2839_rxtx.output(); // Here is combined rx & tx pin in one port.
#endif
_map.r.spi_en.CAL_SPI = 1; // Register Settings reg address 16, D1 (CAL mode 1)
_map.r.spi_en.EN_SPI = 1; // Register Settings reg address 16, DO (CHIP ENABLE 1)
+6
View File
@@ -175,8 +175,14 @@ struct SynthConfig {
*/
void RFFC507x::init() {
#ifdef PRALINE
gpio_control::rf5072_mix_en.set(); // RF5072_MIX_EN
#endif
gpio_rffc5072_resetx.set();
#ifndef PRALINE
gpio_rffc5072_resetx.output();
#endif
reset();
_bus.init();
+2
View File
@@ -33,8 +33,10 @@ void SPI::init() {
gpio_rffc5072_select.set();
gpio_rffc5072_clock.clear();
#ifndef PRALINE
gpio_rffc5072_select.output();
gpio_rffc5072_clock.output();
#endif
gpio_rffc5072_data.input();
gpio_rffc5072_data.clear();
+5
View File
@@ -144,6 +144,9 @@ Continuous (Fox-oring)
#include "lpc43xx.inc"
#include "rffc507x.hpp" /* c/m, avoiding initial short ON Ant_DC_Bias pulse, from cold reset */
#include "gpio.hpp"
rffc507x::RFFC507x first_if;
ui::SystemView* system_view_ptr;
@@ -185,6 +188,8 @@ static void event_loop() {
int main(void) {
rtc_reset_default();
power_control::vaa_power_on();
#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
+6 -6
View File
@@ -56,11 +56,14 @@ using asahi_kasei::ak4951::AK4951;
#include "i2cdevmanager.hpp"
#include "battery.hpp"
#include "gpio.hpp"
extern "C" {
#include "platform_detect.h"
#ifdef PRALINE
#include "fpga_bridge.h"
#include "board.h"
#endif
}
@@ -561,12 +564,6 @@ 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);
@@ -594,9 +591,12 @@ init_status_t init() {
}
/* Cache some configuration data from persistent memory. */
rtc_time::dst_init();
chThdSleepMilliseconds(10);
power_control::core_power_on();
clock_manager.init_clock_generator();
i2c0.stop();
-1
View File
@@ -67,7 +67,6 @@ extern ReceiverModel receiver_model;
extern TransmitterModel transmitter_model;
extern uint32_t bl_tick_counter;
extern bool antenna_bias;
extern uint16_t touch_threshold;
extern TemperatureLogger temperature_logger;
+2 -6
View File
@@ -391,12 +391,8 @@ void set_baseband_rate(const uint32_t rate) {
void set_antenna_bias(const bool on) {
#ifdef PRALINE
/* Keep bias control inside the PRALINE RF path state machine so later
* band/direction/amp updates don't silently force ANT_BIAS_EN_N off.
* Reassert output mode here because this pin is safety-critical and
* direct GPIO writes on an input-configured pad have no effect. */
gpio_ant_bias_disable.output();
rf_path.set_antenna_bias(on);
/* Praline: P2_12 = GPIO1[12], ANT_BIAS_EN_N (active LOW) */
rf_path.set_ant_bias(on);
#else
if (hackrf_r9) {
gpio_r9_not_ant_pwr.write(on ? 0 : 1);
+8 -13
View File
@@ -46,14 +46,6 @@ struct PralineConfig {
bool rf_amp_en;
bool ant_bias_en_n; // Inverted: 0 = bias enabled
static void gpio_init() {
gpio_tx_enable.output();
gpio_mix_bypass.output();
gpio_lpf_enable.output();
gpio_rf_amp_enable.output();
gpio_ant_bias_disable.output();
}
void apply() const {
gpio_tx_enable.write(tx_en);
gpio_mix_bypass.write(mix_bypass); // Control RF path mixer
@@ -231,7 +223,6 @@ constexpr Config get_config(
void Path::init() {
#ifdef PRALINE
PralineConfig::gpio_init();
/* Set safe initial state: RX mode, mixer enabled, LPF on, amp off, no bias */
PralineConfig config = {
.tx_en = false,
@@ -263,11 +254,15 @@ void Path::set_rf_amp(const bool new_rf_amp) {
update();
}
void Path::set_antenna_bias(const bool new_antenna_bias) {
antenna_bias = new_antenna_bias;
void Path::set_ant_bias(const bool new_ant_bias) {
ant_bias = new_ant_bias;
update();
}
bool Path::get_ant_bias() const {
return ant_bias;
}
void Path::update() {
/* 0 ^ 0 => 0 & 0 = 0 ^ 0 = 0 (no change)
* 0 ^ 1 => 1 & 0 = 0 ^ 0 = 0 (ignore change to 1)
@@ -306,8 +301,8 @@ void Path::update() {
/* RF amp when amplification requested */
config.rf_amp_en = rf_amp;
/* Preserve requested antenna bias state across band/direction/amp updates. */
config.ant_bias_en_n = !antenna_bias;
/* Antenna bias */
config.ant_bias_en_n = !ant_bias;
config.apply();
+3 -3
View File
@@ -65,15 +65,15 @@ class Path {
void set_direction(const Direction direction);
void set_band(const Band band);
void set_rf_amp(const bool rf_amp);
void set_antenna_bias(const bool antenna_bias);
void set_ant_bias(const bool ant_bias);
bool get_ant_bias() const;
Band get_band() const { return _band; } //_band is used solely for debugging purposes.
private:
Direction direction{Direction::Receive};
Band band{Band::Mid};
bool rf_amp{false};
bool antenna_bias{false};
bool ant_bias{false};
void update();
File diff suppressed because it is too large Load Diff
@@ -33,12 +33,10 @@
#ifdef __cplusplus
extern "C" {
#endif
void boardInit(void);
void boardInit(void);
void configure_pins_portapack(void);
void configure_pins_portapack(void);
void vaa_power_on(void);
void vaa_power_off(void);
#ifdef __cplusplus
}
#endif
@@ -198,34 +198,6 @@ static void ssp1_init_ice40(void) {
SSP1_CR1_LOCAL = SSP_CR1_SSE;
}
// Configure SSP1 pins via SCU
static void configure_ssp1_pins(void) {
// P1_3 = SSP1_MISO (function 5)
MMIO32_LOCAL(SCU_SSP1_CIPO_LOCAL) = SCU_SSP_IO_LOCAL | SCU_CONF_FUNCTION5_LOCAL;
// P1_4 = SSP1_MOSI (function 5)
MMIO32_LOCAL(SCU_SSP1_COPI_LOCAL) = SCU_SSP_IO_LOCAL | SCU_CONF_FUNCTION5_LOCAL;
// P1_19 = SSP1_SCK (function 1)
MMIO32_LOCAL(SCU_SSP1_SCK_LOCAL) = SCU_SSP_IO_LOCAL | SCU_CONF_FUNCTION1_LOCAL;
}
// Configure FPGA control pins via SCU and GPIO
static void configure_fpga_control_pins(void) {
// P5_2 = GPIO2[11] = CRESET (function 0, output)
MMIO32_LOCAL(SCU_FPGA_CRESET_LOCAL) = SCU_GPIO_NOPULL_LOCAL | SCU_CONF_FUNCTION0_LOCAL;
// P4_10 = GPIO5[14] = CDONE (function 4, input with pullup)
MMIO32_LOCAL(SCU_FPGA_CDONE_LOCAL) = SCU_GPIO_PUP_LOCAL | SCU_CONF_FUNCTION4_LOCAL;
// P5_1 = GPIO2[10] = SPI_CS (function 0, output)
MMIO32_LOCAL(SCU_FPGA_SPI_CS_LOCAL) = SCU_GPIO_NOPULL_LOCAL | SCU_CONF_FUNCTION0_LOCAL;
// Set CRESET and SPI_CS as outputs (GPIO2[11] and GPIO2[10])
GPIO_DIR(FPGA_CRESET_PORT) |= (1 << FPGA_CRESET_PIN) | (1 << FPGA_SPI_CS_PIN);
// Clear both initially
GPIO_CLR(FPGA_CRESET_PORT) = (1 << FPGA_CRESET_PIN) | (1 << FPGA_SPI_CS_PIN);
// CDONE is input (GPIO5[14])
GPIO_DIR(FPGA_CDONE_PORT) &= ~(1 << FPGA_CDONE_PIN);
}
// GPIO control helpers
static void fpga_creset_low(void) {
GPIO_CLR(FPGA_CRESET_PORT) = (1 << FPGA_CRESET_PIN);
@@ -578,12 +550,6 @@ int fpga_bridge_init(uint8_t* mem_base) {
CGU_BASE_SSP1_CLK = CGU_BASE_SSP1_CLK_AUTOBLOCK(1) |
CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1);
// Configure SSP1 pins
configure_ssp1_pins();
// Configure FPGA control pins
configure_fpga_control_pins();
// Initialize SSP1 for iCE40 programming
ssp1_init_ice40();
@@ -52,8 +52,6 @@
/* Driver exported functions. */
/*===========================================================================*/
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
/**
* @brief LPC43xx I/O ports configuration.
* @details Ports 0 through 8.
@@ -62,15 +60,15 @@
*
* @notapi
*/
void _pal_lld_init(const PALConfig *config) {
for(size_t i=0; i<8; i++) {
LPC_GPIO->PIN[i] = config->P[i].data;
LPC_GPIO->DIR[i] = config->P[i].dir;
}
void _pal_lld_init(const PALConfig* config) {
for (size_t i = 0; i < 8; i++) {
LPC_GPIO->PIN[i] = config->P[i].data;
LPC_GPIO->DIR[i] = config->P[i].dir;
}
for(size_t i=0; i<ARRAY_SIZE(config->SCU); i++) {
LPC_SCU->SFSP[config->SCU[i].port][config->SCU[i].pin] = config->SCU[i].config.word;
}
for (size_t i = 0; i < SCU_ARRAY_SIZE; i++) {
LPC_SCU->SFSP[config->SCU[i].port][config->SCU[i].pin] = config->SCU[i].config.word;
}
}
/**
@@ -87,14 +85,14 @@ void _pal_lld_init(const PALConfig *config) {
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
iomode_t mode) {
/* TODO: Handling pull-up, pull-down modes not implemented, as it would
* require a map from GPIO to SCU pins. Not today.
*/
if( mode == PAL_MODE_OUTPUT_PUSHPULL ) {
LPC_GPIO->DIR[port] |= mask;
} else {
LPC_GPIO->DIR[port] &= ~mask;
}
/* TODO: Handling pull-up, pull-down modes not implemented, as it would
* require a map from GPIO to SCU pins. Not today.
*/
if (mode == PAL_MODE_OUTPUT_PUSHPULL) {
LPC_GPIO->DIR[port] |= mask;
} else {
LPC_GPIO->DIR[port] &= ~mask;
}
}
#endif /* HAL_USE_PAL */
@@ -50,10 +50,18 @@
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
*/
#ifdef PRALINE
#define SCU_ARRAY_SIZE 78
#else
#define SCU_ARRAY_SIZE 56
#endif
typedef struct {
/** @brief GPIO setup data.*/
gpio_setup_t P[8];
scu_setup_t SCU[60];
/** @brief GPIO setup data.*/
gpio_setup_t P[8];
scu_setup_t SCU[SCU_ARRAY_SIZE];
} PALConfig;
/**
@@ -94,50 +102,50 @@ typedef uint8_t iopadid_t;
/**
* @brief GPIO0 port identifier.
*/
#define IOPORT1 0
#define GPIO0 0
#define IOPORT1 0
#define GPIO0 0
/**
* @brief GPIO1 port identifier.
*/
#define IOPORT2 1
#define GPIO1 1
#define IOPORT2 1
#define GPIO1 1
/**
* @brief GPIO1 port identifier.
*/
#define IOPORT3 2
#define GPIO2 2
#define IOPORT3 2
#define GPIO2 2
/**
* @brief GPIO1 port identifier.
*/
#define IOPORT4 3
#define GPIO3 3
#define IOPORT4 3
#define GPIO3 3
/**
* @brief GPIO1 port identifier.
*/
#define IOPORT5 4
#define GPIO4 4
#define IOPORT5 4
#define GPIO4 4
/**
* @brief GPIO1 port identifier.
*/
#define IOPORT6 5
#define GPIO5 5
#define IOPORT6 5
#define GPIO5 5
/**
* @brief GPIO1 port identifier.
*/
#define IOPORT7 6
#define GPIO6 6
#define IOPORT7 6
#define GPIO6 6
/**
* @brief GPIO1 port identifier.
*/
#define IOPORT8 7
#define GPIO7 7
#define IOPORT8 7
#define GPIO7 7
/*===========================================================================*/
/* Implementation, some of the following macros could be implemented as */
@@ -237,7 +245,7 @@ typedef uint8_t iopadid_t;
*
* @notapi
*/
//#define pal_lld_readgroup(port, mask, offset) 0
// #define pal_lld_readgroup(port, mask, offset) 0
/**
* @brief Writes a group of bits.
@@ -253,7 +261,7 @@ typedef uint8_t iopadid_t;
*
* @notapi
*/
//#define pal_lld_writegroup(port, mask, offset, bits) (void)bits
// #define pal_lld_writegroup(port, mask, offset, bits) (void)bits
/**
* @brief Pads group mode setup.
@@ -268,8 +276,8 @@ typedef uint8_t iopadid_t;
*
* @notapi
*/
#define pal_lld_setgroupmode(port, mask, offset, mode) \
_pal_lld_setgroupmode(port, mask << offset, mode)
#define pal_lld_setgroupmode(port, mask, offset, mode) \
_pal_lld_setgroupmode(port, mask << offset, mode)
/**
* @brief Reads a logical state from an I/O pad.
@@ -285,8 +293,8 @@ typedef uint8_t iopadid_t;
*
* @notapi
*/
#define pal_lld_readpad(port, pad) \
(LPC_GPIO->B[((port) * 32) + (pad)])
#define pal_lld_readpad(port, pad) \
(LPC_GPIO->B[((port) * 32) + (pad)])
/**
* @brief Writes a logical state on an output pad.
@@ -303,8 +311,8 @@ typedef uint8_t iopadid_t;
*
* @notapi
*/
#define pal_lld_writepad(port, pad, bit) \
((LPC_GPIO->B[((port) * 32) + (pad)]) = (bit))
#define pal_lld_writepad(port, pad, bit) \
((LPC_GPIO->B[((port) * 32) + (pad)]) = (bit))
/**
* @brief Sets a pad logical state to @p PAL_HIGH.
@@ -317,8 +325,8 @@ typedef uint8_t iopadid_t;
*
* @notapi
*/
#define pal_lld_setpad(port, pad) \
(LPC_GPIO->SET[(port)] = 1 << (pad))
#define pal_lld_setpad(port, pad) \
(LPC_GPIO->SET[(port)] = 1 << (pad))
/**
* @brief Clears a pad logical state to @p PAL_LOW.
@@ -331,7 +339,7 @@ typedef uint8_t iopadid_t;
*
* @notapi
*/
#define pal_lld_clearpad(port, pad) \
#define pal_lld_clearpad(port, pad) \
(LPC_GPIO->CLR[(port)] = 1 << (pad))
/**
@@ -345,8 +353,8 @@ typedef uint8_t iopadid_t;
*
* @notapi
*/
#define pal_lld_togglepad(port, pad) \
(LPC_GPIO->NOT[(port)] = 1 << (pad))
#define pal_lld_togglepad(port, pad) \
(LPC_GPIO->NOT[(port)] = 1 << (pad))
/**
* @brief Pad mode setup.
@@ -362,7 +370,7 @@ typedef uint8_t iopadid_t;
*
* @notapi
*/
//#define pal_lld_setpadmode(port, pad, mode)
// #define pal_lld_setpadmode(port, pad, mode)
#if !defined(__DOXYGEN__)
extern const PALConfig pal_default_config;
@@ -371,10 +379,10 @@ extern const PALConfig pal_default_config;
#ifdef __cplusplus
extern "C" {
#endif
void _pal_lld_init(const PALConfig *config);
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
iomode_t mode);
void _pal_lld_init(const PALConfig* config);
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
iomode_t mode);
#ifdef __cplusplus
}
#endif
+184
View File
@@ -0,0 +1,184 @@
/*
* Copyright (C) 2026 Pezsma
*
* This file is part of PortaPack.
*
* 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 "gpio.hpp"
#include "platform.hpp"
namespace power_control {
/* VAA powers:
* MAX5864 analog section.
* MAX2837 registers and other functions.
* RFFC5072 analog section.
*
* Beware that power applied to pins of the MAX2837 may
* show up on VAA and start powering other components on the
* VAA net. So turn on VAA before driving pins from MCU to
* MAX2837.
*/
void vaa_power_on(void) {
/* Very twitchy process for powering up VAA without glitching the 3.3V rail,
* which can send the microcontroller into reset.
*/
#ifdef PRALINE
/* P8_1 (GPIO4[1]) does not have MOTOCONPWM hardware routing.
* Using software bit-banging (pseudo-PWM) for VAA soft-start.
* VAA is active LOW (0 = ON).
*/
/* Software soft-start loop to prevent brown-out */
for (uint32_t i = 0; i < 1000; i++) {
LPC_GPIO->W4[1] = 0; /* Turn ON briefly */
LPC_GPIO->W4[1] = 1; /* Turn OFF briefly */
}
/* Latch VAA to ON state (Active LOW) */
LPC_GPIO->CLR[4] = (1 << 1);
#else
if (hackrf_r9) {
/*
* There is enough VCC->VAA leakage prior to VAA activation from IO pins on
* HackRF One r9 that slowing down activation like this isn't necessary, but
* we do it just in case a different start-up sequence in the future results
* in less leakage.
*/
setup_pin(pin_setup_vaa_enablex_gpio_r9); // P6_10 GPIO3[ 6]: !VAA_ENABLE, 10K PU
for (uint32_t i = 0; i < 1000; i++) {
LPC_GPIO->W3[6] = 1;
LPC_GPIO->W3[6] = 0;
}
} else {
/* Configure and enable MOTOCONPWM peripheral clocks.
* Assume IDIVC is running the post-bootloader configuration, outputting 96MHz derived from PLL1.
*/
base_clock_enable(&motocon_pwm_resources.base);
branch_clock_enable(&motocon_pwm_resources.branch);
peripheral_reset(&motocon_pwm_resources.reset);
/* Combination of pulse duration and duty cycle was arrived at empirically, to keep supply glitching
* to +/- 0.15V.
*/
const uint32_t cycle_period = 256;
uint32_t enable_period = 2;
LPC_MCPWM->TC2 = 0;
LPC_MCPWM->MAT2 = cycle_period - enable_period;
LPC_MCPWM->LIM2 = cycle_period;
/* Switch !VAA_ENABLE pin from GPIO to MOTOCONPWM peripheral output, now that the peripheral is configured. */
setup_pin(pin_setup_vaa_enablex_pwm); // P5_0 /GPIO2[ 9]/MCOB2: !VAA_ENABLE, 10K PU
/* Start the PWM operation. */
LPC_MCPWM->CON_SET = (1 << 16);
/* Wait until VAA rises to approximately 90% of final voltage. */
/* Timing assumes we're running immediately after the bootloader: 96 MHz from IRC+PLL1
*/
while (enable_period < cycle_period) {
{
volatile uint32_t delay = 2000;
while (delay--);
}
enable_period <<= 1;
LPC_MCPWM->MAT2 = cycle_period - enable_period;
}
/* Hold !VAA_ENABLE active using a GPIO, so we can reclaim and shut down the MOTOCONPWM peripheral. */
LPC_GPIO->CLR[2] = (1 << 9); // !VAA_ENABLE
LPC_GPIO->DIR[2] |= (1 << 9);
setup_pin(pin_setup_vaa_enablex_gpio_og); // P5_0 /GPIO2[ 9]/MCOB2: !VAA_ENABLE, 10K PU
peripheral_reset(&motocon_pwm_resources.reset);
branch_clock_disable(&motocon_pwm_resources.branch);
base_clock_disable(&motocon_pwm_resources.base);
}
#endif
}
void vaa_power_off(void) {
/* TODO: There's a lot of other stuff that must be done to prevent
* leakage from +3V3 into VAA.
*/
#ifdef PRALINE
/* Safe state: OFF (VAA RF is active LOW, so Set = OFF) */
LPC_GPIO->SET[4] = (1 << 1);
/* Turn OFF LED3 (TX) */
LPC_GPIO->SET[2] = (1 << 8);
#else
if (hackrf_r9) {
LPC_GPIO->W3[6] = 1; // Turn OFF VAA for r9 P6_10
} else {
LPC_GPIO->W2[9] = 1; // Turn OFF VAA for OG P5_0
}
#endif
}
#ifdef PRALINE
void aux_power_on(void) {
// 3.3V Aux - P6_7 = GPIO5[15], Active LOW (Clear = ON)
LPC_GPIO->CLR[5] = (1 << 15);
}
void aux_power_off(void) {
// 3.3V Aux - P6_7 = GPIO5[15], Active LOW (Set = OFF)
LPC_GPIO->SET[5] = (1 << 15);
}
#endif /* PRALINE */
void core_power_on(void) { // Core power enable
#ifdef PRALINE
// 1.2V FPGA - P8_7 = GPIO4[7], Active HIGH (Set = ON)
LPC_GPIO->SET[4] = (1 << 7);
#else
if (hackrf_r9) {
// P5_0 (GPIO2[9]) is the EN1V8 pin
LPC_GPIO->SET[2] = (1 << 9);
} else {
// On older OG HackRF boards, P6_10 (GPIO3[6]) is the EN1V8 pin
LPC_GPIO->SET[3] = (1 << 6);
}
#endif
}
void core_power_off(void) { // Core power disable
#ifdef PRALINE
// 1.2V FPGA - P8_7 = GPIO4[7], Active HIGH (Clear = OFF) */
LPC_GPIO->CLR[4] = (1 << 7);
#else
if (hackrf_r9) {
// P5_0 (GPIO2[9]) is the EN1V8 pin
LPC_GPIO->CLR[2] = (1 << 9);
} else {
// On older OG HackRF boards, P6_10 (GPIO3[6]) is the EN1V8 pin
LPC_GPIO->CLR[3] = (1 << 6);
}
#endif
}
} // namespace power_control
+108
View File
@@ -22,10 +22,13 @@
#ifndef __GPIO_H__
#define __GPIO_H__
#include <array>
#include <cstddef>
#include <cstdint>
#include "ch.h"
#include "hal.h"
#include "pal.h"
struct PinConfig {
const uint32_t mode;
@@ -280,4 +283,109 @@ struct GPIO {
const uint16_t _gpio_mode;
};
constexpr uint32_t boot_bit(const GPIO& pin, bool state) {
return (state ? 1UL : 0UL) << pin.pad();
}
inline void setup_pin(const scu_setup_t& pin_setup) {
LPC_SCU->SFSP[pin_setup.port][pin_setup.pin] = pin_setup.config;
}
template <size_t N>
inline void setup_gpios(const std::array<gpio_setup_t, N>& pins_setup) {
for (size_t i = 0; i < N; i++) {
LPC_GPIO->PIN[i] |= pins_setup[i].data;
LPC_GPIO->DIR[i] |= pins_setup[i].dir;
}
}
template <size_t N>
inline void setup_pins(const std::array<scu_setup_t, N>& pins_setup) {
for (const auto& pin_setup : pins_setup) {
setup_pin(pin_setup);
}
}
#ifdef PRALINE
namespace gpio_control {
struct PinMap {
uint8_t scu_port;
uint8_t scu_pin;
uint8_t gpio_port;
uint8_t gpio_pad;
};
constexpr PinMap map_p1_ctrl0{2, 10, 0, 14}; // SCU: 2, 10 | GPIO: 0, 14
constexpr PinMap map_p1_ctrl1{6, 8, 5, 16};
constexpr PinMap map_p1_ctrl2{6, 9, 3, 5};
constexpr PinMap map_p2_ctrl0{8, 3, 7, 3};
constexpr PinMap map_p2_ctrl1{8, 4, 7, 4};
constexpr PinMap map_trigger_out{2, 6, 5, 6};
constexpr PinMap map_trigger_in{13, 12, 6, 26};
constexpr PinMap map_rf5072_mix_en{9, 0, 4, 12};
constexpr PinMap map_aa_en{1, 14, 1, 7}; // Anti-Aliasing filter
// P1 Multiplexer control pins
constexpr Pin pin_p1_ctrl0{map_p1_ctrl0.scu_port, map_p1_ctrl0.scu_pin}; // SCU: P2_10
constexpr GPIO p1_ctrl0{pin_p1_ctrl0, map_p1_ctrl0.gpio_port, map_p1_ctrl0.gpio_pad, PAL_MODE_OUTPUT_PUSHPULL}; // GPIO[0]14
constexpr Pin pin_p1_ctrl1{map_p1_ctrl1.scu_port, map_p1_ctrl1.scu_pin}; // SCU: P6_8
constexpr GPIO p1_ctrl1{pin_p1_ctrl1, map_p1_ctrl1.gpio_port, map_p1_ctrl1.gpio_pad, PAL_MODE_OUTPUT_PUSHPULL}; // GPIO[5]16
constexpr Pin pin_p1_ctrl2{map_p1_ctrl2.scu_port, map_p1_ctrl2.scu_pin}; // SCU: P6_9
constexpr GPIO p1_ctrl2{pin_p1_ctrl2, map_p1_ctrl2.gpio_port, map_p1_ctrl2.gpio_pad, PAL_MODE_OUTPUT_PUSHPULL}; // GPIO[3]5
// P2 Multiplexer control pins
constexpr Pin pin_p2_ctrl0{map_p2_ctrl0.scu_port, map_p2_ctrl0.scu_pin}; // SCU: PE_3
constexpr GPIO p2_ctrl0{pin_p2_ctrl0, map_p2_ctrl0.gpio_port, map_p2_ctrl0.gpio_pad, PAL_MODE_OUTPUT_PUSHPULL}; // GPIO[7]3
constexpr Pin pin_p2_ctrl1{map_p2_ctrl1.scu_port, map_p2_ctrl1.scu_pin}; // SCU: PE_4
constexpr GPIO p2_ctrl1{pin_p2_ctrl1, map_p2_ctrl1.gpio_port, map_p2_ctrl1.gpio_pad, PAL_MODE_OUTPUT_PUSHPULL}; // GPIO[7]4
// Trigger pins
constexpr Pin trigger_out_pin{map_trigger_out.scu_port, map_trigger_out.scu_pin}; // SCU: P2_6
constexpr GPIO trigger_out{trigger_out_pin, map_trigger_out.gpio_port, map_trigger_out.gpio_pad, PAL_MODE_OUTPUT_PUSHPULL}; // GPIO[5]6
constexpr Pin trigger_in_pin{map_trigger_in.scu_port, map_trigger_in.scu_pin}; // SCU: PD_12
constexpr GPIO trigger_in{trigger_in_pin, map_trigger_in.gpio_port, map_trigger_in.gpio_pad, PAL_MODE_INPUT}; // GPIO[6]26
// RF507x
constexpr Pin pin_rf5072_mix_en{map_rf5072_mix_en.scu_port, map_rf5072_mix_en.scu_pin};
constexpr GPIO rf5072_mix_en{pin_rf5072_mix_en, map_rf5072_mix_en.gpio_port, map_rf5072_mix_en.gpio_pad, 0};
// Anti-Aliasing filter
constexpr Pin pin_aa_en{map_aa_en.scu_port, map_aa_en.scu_pin};
constexpr GPIO aa_en{pin_aa_en, map_aa_en.gpio_port, map_aa_en.gpio_pad, 0};
} // namespace gpio_control
#endif
namespace power_control {
void vaa_power_on(void);
void vaa_power_off(void);
#ifdef PRALINE
void aux_power_on(void);
void aux_power_off(void);
#endif
void core_power_on(void);
void core_power_off(void);
static const motocon_pwm_resources_t motocon_pwm_resources = {
.base = {.clk = &LPC_CGU->BASE_APB1_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 1)},
.branch = {.cfg = &LPC_CCU1->CLK_APB1_MOTOCON_PWM_CFG, .stat = &LPC_CCU1->CLK_APB1_MOTOCON_PWM_STAT},
.reset = {.output_index = 38},
};
static const scu_setup_t pin_setup_vaa_enablex_pwm = {5, 0, scu_config_normal_drive_t{.mode = 1, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}};
static const scu_setup_t pin_setup_vaa_enablex_gpio_og = {5, 0, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}};
static const scu_setup_t pin_setup_vaa_enablex_gpio_r9 = {6, 10, scu_config_normal_drive_t{.mode = 0, .epd = 0, .epun = 1, .ehs = 0, .ezi = 0, .zif = 0}};
} // namespace power_control
#endif /*__GPIO_H__*/
+6 -11
View File
@@ -41,14 +41,6 @@ constexpr GPIO gpio_led_tx = gpio[GPIO2_8];
constexpr GPIO gpio_og_1v8_enable = gpio[GPIO3_6];
constexpr GPIO gpio_r9_1v8_enable = gpio[GPIO2_9];
constexpr GPIO gpio_vregmode = gpio[GPIO3_7];
#ifdef PRALINE
// PRALINE uses different power control pins
constexpr GPIO gpio_og_vaa_disable = gpio[GPIO4_1]; // PRALINE VAA disable (P8_1)
constexpr GPIO gpio_r9_vaa_disable = gpio[GPIO4_1]; // PRALINE VAA disable (P8_1)
#else
constexpr GPIO gpio_og_vaa_disable = gpio[GPIO2_9];
constexpr GPIO gpio_r9_vaa_disable = gpio[GPIO3_6];
#endif
constexpr GPIO gpio_rx_mix_bp = gpio[GPIO2_12];
constexpr GPIO gpio_tx_mix_bp = gpio[GPIO2_11];
@@ -70,7 +62,6 @@ constexpr GPIO gpio_hp = gpio[GPIO2_0];
constexpr GPIO gpio_rx_amp = gpio[GPIO1_11];
constexpr GPIO gpio_tx_amp = gpio[GPIO2_15];
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];
#ifdef PRALINE
@@ -80,6 +71,7 @@ constexpr GPIO gpio_rffc5072_resetx = gpio[GPIO2_14]; // P5_5: LPC43xx controls
#else
constexpr GPIO gpio_rffc5072_select = gpio[GPIO2_13];
constexpr GPIO gpio_rffc5072_resetx = gpio[GPIO2_14];
constexpr GPIO gpio_not_rx_amp_pwr = gpio[GPIO1_12];
#endif
#ifdef PRALINE
@@ -128,14 +120,16 @@ constexpr GPIO gpio_q_invert = gpio[GPIO0_13];
constexpr GPIO gpio_vaa_disable = gpio[GPIO4_1]; // VAA disable (P8_1)
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)
constexpr GPIO gpio_vbus_enable = gpio[GPIO8_4]; // VBUS_IN_EN P8_4 ->LOW
constexpr GPIO gpio_vin_enable = gpio[GPIO8_5]; // VIN_IN_EN P8_5 ->HIGH
constexpr GPIO gpio_3v3aux_oc = gpio[GPIO1_11]; // 3.3V aux overcurrent input (P2_11)
constexpr GPIO gpio_vbus_enable = gpio[GPIO4_4]; // VBUS_IN_EN P8_4 ->LOW
constexpr GPIO gpio_vin_enable = gpio[GPIO4_5]; // VIN_IN_EN P8_5 ->HIGH
// 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_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)
constexpr GPIO gpio_bias_oc = gpio[GPIO3_7]; // Bias tee overcurrent input (P6_11)
// PRALINE mixer lock detect (gpio_max2831_ld defined above at line 93)
constexpr GPIO gpio_rffc5072_ld = gpio[GPIO6_25]; // Mixer lock detect (PD_11)
@@ -155,6 +149,7 @@ constexpr GPIO gpio_clkin_ctrl = gpio[GPIO0_15]; // CLKIN control (P1_20)
constexpr GPIO gpio_trigger_in = gpio[GPIO6_26]; // Trigger input (PD_12)
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
+3 -3
View File
@@ -31,13 +31,13 @@ struct LED {
void setup() const {
#ifdef PRALINE
/* PRALINE LEDs are active-low (GPIO LOW = LED ON) */
_gpio.set(); /* Start with LED OFF (HIGH) */
// No-op: GPIO direction and initial OFF state are already
// enforced globally at boot by pal_default_config in board.cpp.
#else
_gpio.clear();
#endif
_gpio.output();
_gpio.configure();
#endif
}
void on() const {
+6 -6
View File
@@ -337,8 +337,8 @@ enum GPIOs {
GPIO4_14,
// Power control and LED4
GPIO4_1,
GPIO8_4,
GPIO8_5,
GPIO4_4, // VBUS_IN_EN
GPIO4_5, // VIN_IN_EN
GPIO4_6,
GPIO4_7,
// RF path control
@@ -451,8 +451,8 @@ constexpr GPIO gpio[] = {
#ifdef PRALINE
[GPIO4_14] = {pins[P9_2], 4, 14, 0}, // RFFC5072 mixer data
[GPIO4_1] = {pins[P8_1], 4, 1, 0}, // VAA disable
[GPIO8_4] = {pins[P8_4], 8, 4, 0}, // VBUS_IN_EN
[GPIO8_5] = {pins[P8_5], 8, 5, 0}, // VIN_IN_EN
[GPIO4_4] = {pins[P8_4], 4, 4, 0}, // VBUS_IN_EN
[GPIO4_5] = {pins[P8_5], 4, 5, 0}, // VIN_IN_EN
[GPIO4_6] = {pins[P8_6], 4, 6, 0}, // LED4
[GPIO4_7] = {pins[P8_7], 4, 7, 0}, // 1V2 enable
[GPIO4_8] = {pins[PA_1], 4, 8, 0}, // LPF enable
@@ -470,8 +470,8 @@ constexpr GPIO gpio[] = {
// Placeholder entries for non-PRALINE builds (use P0_0 as dummy)
[GPIO4_14] = {pins[P0_0], 4, 14, 0},
[GPIO4_1] = {pins[P0_0], 4, 1, 0},
[GPIO8_4] = {pins[P0_0], 8, 4, 0},
[GPIO8_5] = {pins[P0_0], 8, 5, 0},
[GPIO4_4] = {pins[P0_0], 4, 4, 0},
[GPIO4_5] = {pins[P0_0], 4, 5, 0},
[GPIO4_6] = {pins[P0_0], 4, 6, 0},
[GPIO4_7] = {pins[P0_0], 4, 7, 0},
[GPIO4_8] = {pins[P0_0], 4, 8, 0},