Gpio modify v4 (#3266)

* Refactor GPIO handling for RFFC5072: update pin mappings and simplify initialization

* Refactor GPIO handling: replace portapack::gpio_dfu with dfu_button and clean up unused GPIOs

* Refactor MAX283x GPIO handling: update pin mappings and simplify initialization

* Refactor GPIO handling: update MAX2831 shutdown pin configuration

* Refactor GPIO handling: add MAX2831 RXHP and RXTX control, update related configurations

* Refactor MAX2831 frequency setting to include reference divider parameter and improve validation checks

* Refactor MAX2831 frequency setting to remove reference divider parameter and improve frequency validation

* copilot
This commit is contained in:
Pezsma
2026-07-10 21:37:41 +02:00
committed by GitHub
parent 87eb8e5863
commit 8561ff32b3
14 changed files with 325 additions and 286 deletions
+4 -5
View File
@@ -61,7 +61,6 @@ uint32_t blink_patterns[] = {
void config_mode_run() {
configure_pins_portapack();
portapack::gpio_dfu.input();
portapack::persistent_memory::cache::init();
if (hackrf_r9) {
@@ -80,14 +79,14 @@ void config_mode_run() {
config_mode_blink_until_dfu();
}
auto last_dfu_btn = portapack::gpio_dfu.read();
auto last_dfu_btn = dfu_button.read();
int32_t counter = 0;
int8_t blink_pattern_value = portapack::persistent_memory::config_cpld() +
(portapack::persistent_memory::config_disable_external_tcxo() ? 5 : 0);
while (true) {
auto dfu_btn = portapack::gpio_dfu.read();
auto dfu_btn = dfu_button.read();
auto dfu_clicked = last_dfu_btn == true && dfu_btn == false;
last_dfu_btn = dfu_btn;
@@ -137,7 +136,7 @@ void config_mode_blink_until_dfu() {
led_usb.setInactive();
chThdSleepMilliseconds(115);
auto dfu_btn = portapack::gpio_dfu.read();
auto dfu_btn = dfu_button.read();
if (dfu_btn)
break;
}
@@ -145,7 +144,7 @@ void config_mode_blink_until_dfu() {
while (true) {
chThdSleepMilliseconds(10);
auto dfu_btn = portapack::gpio_dfu.read();
auto dfu_btn = dfu_button.read();
if (!dfu_btn)
break;
}
+83 -20
View File
@@ -28,10 +28,15 @@
#include "max2831.hpp"
#include "portapack_adc.hpp"
#include "hackrf_hal.hpp"
#include "hackrf_gpio.hpp"
using namespace hackrf::one;
#include "gpio.hpp"
using namespace gpio_control;
#include "ch.h"
#include "hal.h"
@@ -151,7 +156,7 @@ void MAX2831::set_mode(const Mode mode) {
* RX: ENABLE=1, RXTX=0
* TX: ENABLE=1, RXTX=1
*
* Note: gpio_max2831_rx_enable is the RXTX mode select pin.
* Note: max2831_rxtx_enable is the RXTX mode select pin.
* RXTX=0 selects RX, RXTX=1 selects TX.
*/
@@ -174,26 +179,26 @@ void MAX2831::set_mode(const Mode mode) {
switch (mode) {
default:
case Mode::Shutdown:
gpio_max2831_rx_enable.write(0); /* RXTX=0 */
gpio_max283x_enable.write(0); /* ENABLE=0 */
max2831_rxtx_enable.setInactive(); /* RXTX=0 */
max283x_enable.setInactive(); /* ENABLE=0 */
set_rssi_mux(0);
break;
case Mode::Standby:
gpio_max2831_rx_enable.write(1); /* RXTX=1 */
gpio_max283x_enable.write(0); /* ENABLE=0 */
max2831_rxtx_enable.setActive(); /* RXTX=1 */
max283x_enable.setInactive(); /* ENABLE=0 */
set_rssi_mux(0);
break;
case Mode::Transmit:
case Mode::Tx_Calibration:
gpio_max2831_rx_enable.write(1); /* RXTX=1 for TX */
gpio_max283x_enable.write(1); /* ENABLE=1 */
max2831_rxtx_enable.setActive(); /* RXTX=1 for TX */
max283x_enable.setActive(); /* ENABLE=1 */
set_rssi_mux(2); // transmit power
break;
case Mode::Receive:
case Mode::Rx_Calibration:
gpio_max2831_rx_enable.write(0); /* RXTX=0 for RX */
gpio_max283x_enable.write(1); /* ENABLE=1 */
set_rssi_mux(1); // RSSI
max2831_rxtx_enable.setInactive(); /* RXTX=0 for RX */
max283x_enable.setActive(); /* ENABLE=1 */
set_rssi_mux(1); // RSSI
break;
}
@@ -227,8 +232,15 @@ void MAX2831::set_lna_gain(const int_fast8_t db) {
} else {
gain_val = REG11_LNA_GAIN_M33;
}
max2831_rxhp.setActive(); // Fast DC offset compensation
set_reg_field(11, REG11_LNA_GAIN_MASK, gain_val);
flush_reg(11);
chThdSleepMicroseconds(2);
max2831_rxhp.setInactive();
}
void MAX2831::set_vga_gain(const int_fast8_t db) {
@@ -237,10 +249,18 @@ void MAX2831::set_vga_gain(const int_fast8_t db) {
if ((db & 0x1) || db > 62) {
return; /* Invalid: must be even and <= 62 */
}
int_fast8_t db_clipped = std::max(0, std::min(62, (int)db));
uint16_t value = (db_clipped >> 1) & 0x1f;
max2831_rxhp.setActive(); // Fast DC offset compensation
set_reg_field(11, REG11_RXVGA_GAIN_MASK, value);
flush_reg(11);
chThdSleepMicroseconds(2);
max2831_rxhp.setInactive();
}
/*
@@ -365,9 +385,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
gpio_control::aa_en.setInactive(); // Disable external AA filter for wideband operations
if (_mode == Mode::Transmit || _mode == Mode::Tx_Calibration) {
set_lpf_bandwidth_internal(bandwidth_minimum);
}
@@ -461,13 +481,56 @@ void MAX2831::set_rx_buff_vcm(const size_t v) {
}
int8_t MAX2831::temp_sense() {
/* MAX2831 temperature sensor can be read via RSSI MUX.
* This would require:
* 1. Switch RSSI_MUX to temperature mode
* 2. Read the ADC
* 3. Switch back to RSSI mode
* For now, return a placeholder value. */
return 25; /* Room temperature placeholder */
bool not_in_rx = (_mode != Mode::Receive && _mode != Mode::Rx_Calibration);
if (not_in_rx) {
max2831_rxtx_enable.setInactive();
max283x_enable.setActive();
chThdSleepMilliseconds(1);
}
set_rssi_mux(3);
chThdSleepMilliseconds(5);
uint32_t saved_cr = LPC_ADC1->CR;
uint32_t cr_temp = saved_cr;
cr_temp &= ~0xFF;
cr_temp |= (1 << portapack::adc1_rssi_input);
if (((cr_temp >> 8) & 0xFF) == 0) {
cr_temp |= (0xFF << 8);
}
cr_temp &= ~(1 << 16);
cr_temp |= (1 << 21);
cr_temp &= ~(7 << 24);
cr_temp |= (1 << 24);
LPC_ADC1->CR = cr_temp;
uint32_t val;
while (((val = LPC_ADC1->DR[portapack::adc1_rssi_input]) & (1UL << 31)) == 0) {
__asm__("nop");
}
uint32_t adc_raw = (val >> 6) & 0x3FF;
LPC_ADC1->CR = saved_cr;
if (not_in_rx) {
set_mode(_mode);
} else {
set_rssi_mux(1);
}
float v_adc = (adc_raw / 1023.0f) * 3.3f;
constexpr float V_25_CELSIUS = 1.185f;
constexpr float SLOPE = 0.003f;
float temp = 25.0f + ((v_adc - V_25_CELSIUS) / SLOPE);
return static_cast<int8_t>(std::max(-128.0f, std::min(127.0f, temp)));
}
reg_t MAX2831::read(const address_t reg_num) {
+8 -19
View File
@@ -19,12 +19,17 @@
* Boston, MA 02110-1301, USA.
*/
#ifndef PRALINE // not praline
#include "max2837.hpp"
#include "hackrf_hal.hpp"
#include "hackrf_gpio.hpp"
using namespace hackrf::one;
#include "gpio.hpp"
using namespace gpio_control;
#include "ch.h"
#include "hal.h"
@@ -99,12 +104,6 @@ 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;
_map.r.tx_gain.TXVGA_GAIN_SPI = 0x00;
@@ -159,12 +158,6 @@ 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)
flush_one(Register::SPI_EN);
@@ -214,7 +207,7 @@ void MAX2837::set_mode(const Mode mode) { // We set up the 3 Logic Pins ENABLE,
_mode = mode;
Mask mask = mode_mask(mode);
gpio_max283x_enable.write(toUType(mask) & toUType(Mask::Enable));
max283x_enable.write(toUType(mask) & toUType(Mask::Enable));
gpio_max2837_rxenable.write(toUType(mask) & toUType(Mask::RxEnable));
gpio_max2837_txenable.write(toUType(mask) & toUType(Mask::TxEnable));
}
@@ -352,12 +345,6 @@ 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)
flush_one(Register::SPI_EN);
@@ -419,3 +406,5 @@ int8_t MAX2837::temp_sense() {
}
} // namespace max2837
#endif // not PRALINE
+7 -17
View File
@@ -19,6 +19,7 @@
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef PRALINE // not praline
#include "max2839.hpp"
@@ -26,6 +27,9 @@
#include "hackrf_gpio.hpp"
using namespace hackrf::one;
#include "gpio.hpp"
using namespace gpio_control;
#include "ch.h"
#include "hal.h"
@@ -100,11 +104,6 @@ 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 */
_map.r.pa_drv.TXVGA_GAIN_SPI_EN = 1;
@@ -154,11 +153,6 @@ 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)
flush_one(Register::SPI_EN);
@@ -207,7 +201,7 @@ void MAX2839::set_mode(const Mode mode) {
_mode = mode;
Mask mask = mode_mask(mode);
gpio_max283x_enable.write(toUType(mask) & toUType(Mask::Enable));
max283x_enable.write(toUType(mask) & toUType(Mask::Enable));
gpio_max2839_rxtx.write(toUType(mask) & toUType(Mask::RxTx));
}
@@ -395,11 +389,6 @@ 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)
flush_one(Register::SPI_EN);
@@ -446,4 +435,5 @@ int8_t MAX2839::temp_sense() {
return std::min(127, (int)(value * 4.31 - 40)); // reg value is 0 to 31; possible return range is -40 C to 127 C
}
} // namespace max2839
} // namespace max2839
#endif // not PRALINE
+9 -7
View File
@@ -26,9 +26,13 @@
#include "utility.hpp"
#include "hackrf_hal.hpp"
#include "hackrf_gpio.hpp"
using namespace hackrf::one;
#include "gpio.hpp"
using namespace gpio_control;
#include "hal.h"
#ifdef PRALINE
@@ -176,13 +180,11 @@ struct SynthConfig {
void RFFC507x::init() {
#ifdef PRALINE
gpio_control::rf5072_mix_en.setActive(); // RF5072_MIX_EN
rf5072_mix_en.setActive(); // RF5072_MIX_EN
#endif
gpio_rffc5072_resetx.set();
#ifndef PRALINE
gpio_rffc5072_resetx.output();
#endif
rffc5072_resetx.setInactive();
reset();
_bus.init();
@@ -195,9 +197,9 @@ void RFFC507x::reset() {
/* TODO: Is RESETB pin ignored if sdi_ctrl.sipin=1? Programming guide
* description of sdi_ctrl.sipin suggests the pin is not ignored.
*/
gpio_rffc5072_resetx.clear();
rffc5072_resetx.setActive();
halPolledDelay(ticks_during_reset);
gpio_rffc5072_resetx.set();
rffc5072_resetx.setInactive();
halPolledDelay(ticks_after_reset);
}
+13 -19
View File
@@ -23,50 +23,44 @@
#include "utility.hpp"
#include "hackrf_gpio.hpp"
using namespace hackrf::one;
#include "gpio.hpp"
using namespace gpio_control;
namespace rffc507x {
namespace spi {
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();
rffc5072_select.setInactive();
rffc5072_clock.setInactive();
rffc5072_sdata.input();
rffc5072_sdata.setInactive();
}
inline void SPI::select(const bool active) {
gpio_rffc5072_select.write(!active);
rffc5072_select.setState(active);
}
inline void SPI::direction_out() {
gpio_rffc5072_data.output();
rffc5072_sdata.output();
}
inline void SPI::direction_in() {
gpio_rffc5072_data.input();
rffc5072_sdata.input();
}
inline void SPI::write_bit(const bit_t value) {
gpio_rffc5072_data.write(value);
rffc5072_sdata.write(value);
}
inline bit_t SPI::read_bit() {
return gpio_rffc5072_data.read() & 1;
return rffc5072_sdata.read() & 1;
}
inline bit_t SPI::transfer_bit(const bit_t bit_out) {
gpio_rffc5072_clock.clear();
rffc5072_clock.setInactive();
write_bit(bit_out);
const bit_t bit_in = read_bit();
gpio_rffc5072_clock.set();
rffc5072_clock.setActive();
return bit_in;
}
+1 -3
View File
@@ -57,13 +57,13 @@ using asahi_kasei::ak4951::AK4951;
#include "battery.hpp"
#include "gpio.hpp"
using namespace gpio_control;
extern "C" {
#include "platform_detect.h"
#ifdef PRALINE
#include "fpga_bridge.h"
#include "board.h"
#endif
}
@@ -74,11 +74,9 @@ const char* init_error = nullptr;
portapack::IO io{
portapack::gpio_dir,
portapack::gpio_lcd_rdx,
portapack::gpio_lcd_wrx,
portapack::gpio_io_stbx,
portapack::gpio_addr,
portapack::gpio_lcd_te,
portapack::gpio_dfu,
};
portapack::BacklightCAT4004 backlight_cat4004;
+4 -4
View File
@@ -76,8 +76,8 @@ static constexpr uint32_t ssp_scr(
/* MAX2831 uses 9-bit SPI transfers */
static constexpr SPIConfig ssp_config_max283x = {
.end_cb = NULL,
.ssport = gpio_max283x_select.port(),
.sspad = gpio_max283x_select.pad(),
.ssport = map_max283x_select.gpio_port,
.sspad = map_max283x_select.gpio_pad,
.cr0 =
CR0_CLOCKRATE(ssp_scr(ssp1_pclk_f, ssp1_cpsr, max283x_spi_f) + 3) | CR0_FRFSPI | CR0_DSS9BIT,
.cpsr = ssp1_cpsr,
@@ -95,8 +95,8 @@ void set_rx_buff_vcm(const size_t v) {
/* MAX2837/MAX2839 use 16-bit SPI transfers */
static constexpr SPIConfig ssp_config_max283x = {
.end_cb = NULL,
.ssport = gpio_max283x_select.port(),
.sspad = gpio_max283x_select.pad(),
.ssport = map_max283x_select.gpio_port,
.sspad = map_max283x_select.gpio_pad,
.cr0 =
CR0_CLOCKRATE(ssp_scr(ssp1_pclk_f, ssp1_cpsr, max283x_spi_f) + 3) | CR0_FRFSPI | CR0_DSS16BIT,
.cpsr = ssp1_cpsr,