More RAK6421 work (#9813)

* Add Portduino Enable pins

* Add hat plus custom fields

* Punt on the GPIO device detection for now

* Simplify TX_GAIN_LORA for RAK13302

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
This commit is contained in:
Jonathan Bennett
2026-03-05 08:15:33 -06:00
committed by GitHub
parent 20f838a61e
commit afd5e29bce
7 changed files with 115 additions and 11 deletions

View File

@@ -19,6 +19,7 @@
#include <fstream>
#include <iostream>
#include <map>
#include <set>
#include <stdexcept>
#include <sys/ioctl.h>
#include <unistd.h>
@@ -277,6 +278,24 @@ void portduinoSetup()
std::cout << "autoconf: Found Pi HAT+ " << hat_vendor << " " << autoconf_product << " at /proc/device-tree/hat"
<< std::endl;
// check for custom data fields
int i = 0;
while (access(("/proc/device-tree/hat/custom_" + std::to_string(i)).c_str(), R_OK) == 0) {
std::ifstream customFieldFile(("/proc/device-tree/hat/custom_" + std::to_string(i)).c_str());
if (customFieldFile.is_open()) {
std::string customFieldName;
std::string customFieldValue;
getline(customFieldFile, customFieldName, ' ');
getline(customFieldFile, customFieldValue, ' ');
customFieldFile.close();
printf("autoconf: Found hat+ custom field %s: %s\n", customFieldName.c_str(), customFieldValue.c_str());
portduino_config.hat_plus_custom_fields[customFieldName] = customFieldValue;
}
i++;
}
// potential TODO: Validate that this is a real UUID
std::ifstream hatUUID("/proc/device-tree/hat/uuid");
char uuid[38] = {0};
@@ -496,14 +515,19 @@ void portduinoSetup()
randomSeed(time(NULL));
std::string defaultGpioChipName = gpioChipName + std::to_string(portduino_config.lora_default_gpiochip);
std::set<int> used_pins;
for (const auto *i : portduino_config.all_pins) {
if (i->enabled && i->pin > max_GPIO)
if (i->enabled && i->pin > max_GPIO) {
max_GPIO = i->pin;
}
}
for (auto i : portduino_config.extra_pins) {
if (i.enabled && i.pin > max_GPIO)
if (i.enabled && i.pin > max_GPIO) {
max_GPIO = i.pin;
}
}
gpioInit(max_GPIO + 1); // Done here so we can inform Portduino how many GPIOs we need.
@@ -517,12 +541,18 @@ void portduinoSetup()
continue;
}
if (i->enabled) {
if (initGPIOPin(i->pin, gpioChipName + std::to_string(i->gpiochip), i->line) != ERRNO_OK) {
printf("Error setting pin number %d. It may not exist, or may already be in use.\n", i->line);
exit(EXIT_FAILURE);
if (used_pins.find(i->pin) != used_pins.end()) {
printf("Pin %d is in use for multiple purposes\n", i->pin);
} else {
if (initGPIOPin(i->pin, gpioChipName + std::to_string(i->gpiochip), i->line) != ERRNO_OK) {
printf("Error setting pin number %d. It may not exist, or may already be in use.\n", i->line);
exit(EXIT_FAILURE);
}
used_pins.insert(i->pin);
}
}
}
printf("Initializing extra pins\n");
for (auto i : portduino_config.extra_pins) {
// In the case of a ch341 Lora device, we don't want to touch the system GPIO lines for Lora
// Those GPIO are handled in our usermode driver instead.
@@ -530,9 +560,14 @@ void portduinoSetup()
continue;
}
if (i.enabled) {
if (initGPIOPin(i.pin, gpioChipName + std::to_string(i.gpiochip), i.line) != ERRNO_OK) {
printf("Error setting pin number %d. It may not exist, or may already be in use.\n", i.line);
exit(EXIT_FAILURE);
if (used_pins.find(i.pin) != used_pins.end()) {
printf("Pin %d is in use for multiple purposes\n", i.pin);
} else {
if (initGPIOPin(i.pin, gpioChipName + std::to_string(i.gpiochip), i.line) != ERRNO_OK) {
printf("Error setting pin number %d. It may not exist, or may already be in use.\n", i.line);
exit(EXIT_FAILURE);
}
used_pins.insert(i.pin);
}
}
}
@@ -556,6 +591,25 @@ void portduinoSetup()
// disable bias once finished
pinMode(portduino_config.lora_pa_detect_pin.pin, INPUT);
} else if (portduino_config.hat_plus_custom_fields.find("io_slot1") != portduino_config.hat_plus_custom_fields.end()) {
printf("Hat+ io_slot1 is %s\n", portduino_config.hat_plus_custom_fields["io_slot1"].c_str());
if (portduino_config.hat_plus_custom_fields["io_slot1"] != "RAK13302") {
std::cout << "Hat+ io_slot1 is not RAK13302, skipping PA curve" << std::endl;
portduino_config.num_pa_points = 1;
portduino_config.tx_gain_lora[0] = 0;
}
}
for (auto i : portduino_config.extra_pins) {
// In the case of a ch341 Lora device, we don't want to touch the system GPIO lines for Lora
// Those GPIO are handled in our usermode driver instead.
if (i.config_section == "Lora" && portduino_config.lora_spi_dev == "ch341") {
continue;
}
if (i.enabled && i.default_high) {
pinMode(i.pin, OUTPUT);
digitalWrite(i.pin, HIGH);
}
}
// Only initialize the radio pins when dealing with real, kernel controlled SPI hardware
@@ -712,6 +766,17 @@ bool loadConfig(const char *configPath)
}
}
if (yamlConfig["Lora"]["Enable_Pins"]) {
for (auto extra_pin : yamlConfig["Lora"]["Enable_Pins"]) {
portduino_config.extra_pins.push_back(pinMapping());
portduino_config.extra_pins.back().config_section = "Lora";
portduino_config.extra_pins.back().config_name = "Enable_Pins";
portduino_config.extra_pins.back().enabled = true;
portduino_config.extra_pins.back().default_high = true;
readGPIOFromYaml(extra_pin, portduino_config.extra_pins.back());
}
}
portduino_config.spiSpeed = yamlConfig["Lora"]["spiSpeed"].as<int>(2000000);
portduino_config.lora_usb_serial_num = yamlConfig["Lora"]["USB_Serialnum"].as<std::string>("");
portduino_config.lora_usb_pid = yamlConfig["Lora"]["USB_PID"].as<int>(0x5512);