mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-08-17 05:13:25 +00:00
Gpio modify v3 (#3238)
* Refactor GPIO mappings and definitions for improved clarity and functionality - Updated SCU_ARRAY_SIZE definitions in pal_lld.h for PRALINE and non-PRALINE configurations. - Modified pin mappings in gpio.hpp to reflect new hardware configurations, including additional control pins for RF and audio components. - Removed obsolete GPIO definitions from hackrf_gpio.hpp and streamlined the code for better maintainability. - Added new GPIO definitions for mix bypass, amplifier control, and other RF-related functionalities to enhance the system's capabilities. * Refactor GPIO mappings and update SCU_ARRAY_SIZE for LPC43xx platform - Updated SCU_ARRAY_SIZE to 80 for PRALINE configuration and 58 for others. - Added new GPIO mappings for auxiliary power control, antenna bias, and R9 clock enable signals in gpio.hpp. - Removed commented-out PPS output mapping in hackrf_gpio.hpp. - Adjusted GPIO definitions for R9 clock signals to ensure proper functionality. * Refactor RF path initialization and configuration for improved clarity and functionality * Refactor RF path configuration and GPIO mappings for improved clarity and functionality * Potential fix for pull request finding * comment * aux power polarrity * Fix formatting of pin_aux_power_enable declaration
This commit is contained in:
@@ -21,221 +21,26 @@
|
||||
|
||||
#include "rf_path.hpp"
|
||||
#include "platform.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <initializer_list>
|
||||
|
||||
#include "hackrf_gpio.hpp"
|
||||
using namespace hackrf::one;
|
||||
|
||||
#include "utility.hpp"
|
||||
#include "gpio.hpp"
|
||||
using namespace gpio_control;
|
||||
|
||||
namespace rf {
|
||||
namespace path {
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef PRALINE
|
||||
/* PRALINE uses a simplified RF path with only 5 control signals.
|
||||
* The RF path architecture is completely different from HackRF One.
|
||||
*/
|
||||
struct PralineConfig {
|
||||
bool tx_en;
|
||||
bool mix_bypass; // RF path mixer bypass (GPIO3[2])
|
||||
bool lpf_en;
|
||||
bool rf_amp_en;
|
||||
bool ant_bias_en_n; // Inverted: 0 = bias enabled
|
||||
|
||||
void apply() const {
|
||||
gpio_tx_enable.write(tx_en);
|
||||
gpio_mix_bypass.write(mix_bypass); // Control RF path mixer
|
||||
gpio_lpf_enable.write(lpf_en);
|
||||
gpio_rf_amp_enable.write(rf_amp_en);
|
||||
gpio_ant_bias_disable.write(ant_bias_en_n);
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
/* HackRF One uses 11 GPIOs for RF path control */
|
||||
using GPIOs = std::array<GPIO, 11>;
|
||||
|
||||
/* TODO: ARM GCC 4.8 2014q3 doesn't like this array inside struct Config.
|
||||
* No idea why.
|
||||
*/
|
||||
constexpr GPIOs gpios{
|
||||
gpio_mix_bypass,
|
||||
gpio_not_mix_bypass,
|
||||
gpio_tx_mix_bp,
|
||||
gpio_rx_mix_bp,
|
||||
gpio_hp,
|
||||
gpio_lp,
|
||||
gpio_amp_bypass,
|
||||
gpio_tx_amp,
|
||||
gpio_not_tx_amp_pwr,
|
||||
gpio_rx_amp,
|
||||
gpio_not_rx_amp_pwr,
|
||||
};
|
||||
|
||||
/* HackRF One Config struct - not used on PRALINE */
|
||||
struct Config {
|
||||
using base_type = uint16_t;
|
||||
|
||||
union {
|
||||
struct {
|
||||
bool tx : 1;
|
||||
bool rx : 1;
|
||||
bool mix_bypass : 1;
|
||||
bool not_mix_bypass : 1;
|
||||
bool tx_mix_bp : 1;
|
||||
bool rx_mix_bp : 1;
|
||||
bool hp : 1;
|
||||
bool lp : 1;
|
||||
bool amp_bypass : 1;
|
||||
bool tx_amp : 1;
|
||||
bool not_tx_amp : 1;
|
||||
bool rx_amp : 1;
|
||||
bool not_rx_amp : 1;
|
||||
};
|
||||
base_type w;
|
||||
};
|
||||
|
||||
constexpr Config(
|
||||
const Direction direction,
|
||||
const Band band,
|
||||
const bool amplify)
|
||||
: tx(direction == Direction::Transmit),
|
||||
rx(direction == Direction::Receive),
|
||||
mix_bypass(band == Band::Mid),
|
||||
not_mix_bypass(band != Band::Mid),
|
||||
tx_mix_bp((direction == Direction::Transmit) && (band == Band::Mid)),
|
||||
rx_mix_bp((direction == Direction::Receive) && (band == Band::Mid)),
|
||||
hp(band == Band::High),
|
||||
lp(band == Band::Low),
|
||||
amp_bypass(!amplify),
|
||||
tx_amp((direction == Direction::Transmit) && amplify),
|
||||
not_tx_amp(!tx_amp),
|
||||
rx_amp((direction == Direction::Receive) && amplify),
|
||||
not_rx_amp(!rx_amp) {
|
||||
}
|
||||
|
||||
constexpr Config()
|
||||
: Config(Direction::Receive, Band::Mid, false) {
|
||||
}
|
||||
|
||||
constexpr Config(
|
||||
const base_type w)
|
||||
: w(w) {
|
||||
}
|
||||
|
||||
constexpr Config operator^(const Config& r) const {
|
||||
return w ^ r.w;
|
||||
}
|
||||
|
||||
constexpr Config operator&(const Config& r) const {
|
||||
return w & r.w;
|
||||
}
|
||||
|
||||
constexpr bool operator[](const size_t n) const {
|
||||
return (w >> n) & 1;
|
||||
}
|
||||
|
||||
static void gpio_init() {
|
||||
if (hackrf_r9) {
|
||||
gpio_r9_rx.output();
|
||||
} else {
|
||||
gpio_og_tx.output();
|
||||
gpio_og_rx.output();
|
||||
}
|
||||
for (auto gpio : gpios) {
|
||||
gpio.output();
|
||||
}
|
||||
}
|
||||
|
||||
void apply() const {
|
||||
/* NOTE: Assumes order in gpios[] and Config bitfield match,
|
||||
* after the 'tx' and 'rx' fields which are handled specially. */
|
||||
for (size_t n = 0; n < gpios.size() + 2; n++) {
|
||||
bool value = (*this)[n];
|
||||
switch (n) {
|
||||
case 0:
|
||||
if (!hackrf_r9) {
|
||||
gpio_og_tx.write(value);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (hackrf_r9) {
|
||||
gpio_r9_rx.write(value);
|
||||
} else {
|
||||
gpio_og_rx.write(value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
gpios[n - 2].write(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* HackRF One config table - not used on PRALINE */
|
||||
using ConfigAmp = std::array<Config, 2>;
|
||||
using ConfigDirection = std::array<ConfigAmp, 2>;
|
||||
using ConfigBand = std::array<ConfigDirection, 3>;
|
||||
|
||||
constexpr ConfigAmp config_amp(
|
||||
const Direction direction,
|
||||
const Band band) {
|
||||
return {{
|
||||
Config(direction, band, false),
|
||||
Config(direction, band, true),
|
||||
}};
|
||||
}
|
||||
|
||||
constexpr ConfigDirection config_rx_tx(
|
||||
const Band band) {
|
||||
return {
|
||||
config_amp(Direction::Receive, band),
|
||||
config_amp(Direction::Transmit, band),
|
||||
};
|
||||
}
|
||||
|
||||
constexpr ConfigBand config_band() {
|
||||
return {
|
||||
config_rx_tx(Band::Low),
|
||||
config_rx_tx(Band::Mid),
|
||||
config_rx_tx(Band::High),
|
||||
};
|
||||
}
|
||||
|
||||
constexpr ConfigBand config_table = config_band();
|
||||
|
||||
static_assert(sizeof(config_table) == sizeof(Config::base_type) * 3 * 2 * 2, "rf path config table unexpected size");
|
||||
|
||||
constexpr Config get_config(
|
||||
const Direction direction,
|
||||
const Band band,
|
||||
const bool amplify) {
|
||||
return config_table[toUType(band)][toUType(direction)][amplify ? 1 : 0];
|
||||
}
|
||||
#endif /* PRALINE */
|
||||
|
||||
} /* namespace */
|
||||
|
||||
void Path::init() {
|
||||
/* Set safe initial default states */
|
||||
direction = Direction::Receive;
|
||||
rf_amp_en = false;
|
||||
ant_bias_en = false;
|
||||
|
||||
#ifdef PRALINE
|
||||
/* Set safe initial state: RX mode, mixer enabled, LPF on, amp off, no bias */
|
||||
PralineConfig config = {
|
||||
.tx_en = false,
|
||||
.mix_bypass = false, // RF path mixer bypass (GPIO3[2])
|
||||
.lpf_en = true, // LPF on for low band
|
||||
.rf_amp_en = false, // Amp off
|
||||
.ant_bias_en_n = true // Bias off (inverted)
|
||||
};
|
||||
config.apply();
|
||||
band = Band::Low;
|
||||
#else
|
||||
update();
|
||||
Config::gpio_init();
|
||||
band = Band::Mid;
|
||||
#endif
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void Path::set_direction(const Direction new_direction) {
|
||||
@@ -245,73 +50,82 @@ void Path::set_direction(const Direction new_direction) {
|
||||
|
||||
void Path::set_band(const Band new_band) {
|
||||
band = new_band;
|
||||
_band = new_band;
|
||||
update();
|
||||
}
|
||||
|
||||
void Path::set_rf_amp(const bool new_rf_amp) {
|
||||
rf_amp = new_rf_amp;
|
||||
rf_amp_en = new_rf_amp;
|
||||
update();
|
||||
}
|
||||
|
||||
void Path::set_ant_bias(const bool new_ant_bias) {
|
||||
ant_bias = new_ant_bias;
|
||||
ant_bias_en = new_ant_bias;
|
||||
update();
|
||||
}
|
||||
|
||||
bool Path::get_ant_bias() const {
|
||||
return ant_bias;
|
||||
return ant_bias_en;
|
||||
}
|
||||
|
||||
void Path::update() {
|
||||
/* 0 ^ 0 => 0 & 0 = 0 ^ 0 = 0 (no change)
|
||||
* 0 ^ 1 => 1 & 0 = 0 ^ 0 = 0 (ignore change to 1)
|
||||
* 1 ^ 0 => 1 & 1 = 1 ^ 1 = 0 (allow change to 0)
|
||||
* 1 ^ 1 => 0 & 1 = 0 ^ 1 = 1 (no change) */
|
||||
const bool is_tx = (direction == Direction::Transmit);
|
||||
|
||||
#ifdef PRALINE
|
||||
/* PRALINE RF path control:
|
||||
* - tx_en: 1 for TX, 0 for RX
|
||||
* - mix_bypass: 0 to enable RF path mixer bypass (GPIO3[2])
|
||||
* - lpf_en: 1 for low band (< 2.4 GHz), 0 for high band
|
||||
* - rf_amp_en: 1 to enable RF amplifier
|
||||
* - ant_bias_en_n: 0 to enable antenna bias (inverted)
|
||||
*/
|
||||
// const Config changed = _config ^ config_next;
|
||||
// const Config turned_off = _config & changed;
|
||||
// PRALINE specific RF path control directly applied to pins.
|
||||
// Active-low pin inversion is handled internally inside setState().
|
||||
|
||||
PralineConfig config;
|
||||
tx_enable.setState(is_tx);
|
||||
|
||||
/* In transition, ignore the bits that are turning on. So this transition phase
|
||||
* only turns off signals. It doesn't turn on signals.
|
||||
*/
|
||||
// const Config transition_config = _config ^ turned_off;
|
||||
// update_signals(transition_config);
|
||||
// On the PRALINE board, the mixer is used ONLY on the Low band.
|
||||
// Since setState() internally handles the active-low (MIX_ENABLE_N) hardware inversion,
|
||||
// we simply pass 'true' to enable the mixer on Low band, and 'false' for Mid/High bands.
|
||||
|
||||
config.tx_en = (direction == Direction::Transmit);
|
||||
mix_bypass.setState(band == Band::Low);
|
||||
|
||||
// RF path mixer bypass: 0=enabled, 1=bypassed
|
||||
config.mix_bypass = (band == Band::Mid);
|
||||
|
||||
/* Move to the final state by turning on required signals. */
|
||||
/* LPF for low band */
|
||||
|
||||
config.lpf_en = (band == Band::Low);
|
||||
|
||||
/* RF amp when amplification requested */
|
||||
config.rf_amp_en = rf_amp;
|
||||
|
||||
/* Antenna bias */
|
||||
config.ant_bias_en_n = !ant_bias;
|
||||
|
||||
config.apply();
|
||||
lpf.setState(band == Band::Low);
|
||||
rf_amp_enable.setState(rf_amp_en);
|
||||
ant_bias.setState(ant_bias_en);
|
||||
|
||||
#else
|
||||
/* HackRF One RF path control */
|
||||
const auto config = get_config(direction, band, rf_amp);
|
||||
config.apply();
|
||||
|
||||
const bool is_rx = (direction == Direction::Receive);
|
||||
|
||||
// HackRF One (OG & R9) RF path control
|
||||
const bool mix_bypass_en = (band == Band::Mid);
|
||||
const bool amplify = rf_amp_en;
|
||||
|
||||
// Primary TX/RX routing switches
|
||||
if (!hackrf_r9) {
|
||||
og_tx.setState(is_tx);
|
||||
}
|
||||
|
||||
if (hackrf_r9) {
|
||||
r9_rx.setState(is_rx); // Single pin handles directional switching on R9
|
||||
} else {
|
||||
og_rx.setState(is_rx);
|
||||
}
|
||||
|
||||
// RF path switch configuration matrix
|
||||
rx_mix_bypass.setState(mix_bypass_en);
|
||||
tx_mix_bp.setState(is_tx && mix_bypass_en);
|
||||
rx_mix_bp.setState(is_rx && mix_bypass_en);
|
||||
|
||||
hpf.setState(band == Band::High);
|
||||
lpf.setState(band == Band::Low);
|
||||
|
||||
amp_bypass.setState(!amplify);
|
||||
tx_amp.setState(is_tx && amplify);
|
||||
rx_amp.setState(is_rx && amplify);
|
||||
|
||||
tx_mix_bypass.setState(mix_bypass_en);
|
||||
tx_amp_pwr.setState(is_tx && amplify);
|
||||
rx_amp_pwr.setState(is_rx && amplify);
|
||||
|
||||
if (hackrf_r9) {
|
||||
ant_bias.setState(ant_bias_en);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace path
|
||||
} // namespace rf
|
||||
} // namespace rf
|
||||
Reference in New Issue
Block a user