mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-07-26 10:38:52 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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__*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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},
|
||||
|
||||
Reference in New Issue
Block a user