mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-23 17:13:38 +00:00
Move to portduino GPIO, adding user button support
This commit is contained in:
parent
18cf8ca4fa
commit
102efd4954
@ -24,3 +24,8 @@ Lora:
|
||||
# Reset: 22
|
||||
# CS: 7
|
||||
# IRQ: 25
|
||||
|
||||
# Define GPIO buttons here:
|
||||
|
||||
GPIO:
|
||||
# User: 6
|
||||
|
@ -36,6 +36,9 @@ class ButtonThread : public concurrency::OSThread
|
||||
#endif
|
||||
#ifdef BUTTON_PIN_TOUCH
|
||||
OneButton userButtonTouch;
|
||||
#endif
|
||||
#if defined(ARCH_RASPBERRY_PI)
|
||||
OneButton userButton;
|
||||
#endif
|
||||
static bool shutdown_on_long_stop;
|
||||
|
||||
@ -45,8 +48,13 @@ class ButtonThread : public concurrency::OSThread
|
||||
// callback returns the period for the next callback invocation (or 0 if we should no longer be called)
|
||||
ButtonThread() : OSThread("Button")
|
||||
{
|
||||
#ifdef BUTTON_PIN
|
||||
#if defined(ARCH_RASPBERRY_PI)
|
||||
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
|
||||
userButton = OneButton(settingsMap[user], true, true);
|
||||
#elif defined(BUTTON_PIN)
|
||||
|
||||
userButton = OneButton(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, true, true);
|
||||
#endif
|
||||
#ifdef INPUT_PULLUP_SENSE
|
||||
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
||||
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP_SENSE);
|
||||
@ -58,6 +66,10 @@ class ButtonThread : public concurrency::OSThread
|
||||
userButton.attachMultiClick(userButtonMultiPressed);
|
||||
userButton.attachLongPressStart(userButtonPressedLongStart);
|
||||
userButton.attachLongPressStop(userButtonPressedLongStop);
|
||||
#if defined(ARCH_RASPBERRY_PI)
|
||||
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
|
||||
wakeOnIrq(settingsMap[user], FALLING);
|
||||
#else
|
||||
wakeOnIrq(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, FALLING);
|
||||
#endif
|
||||
#ifdef BUTTON_PIN_ALT
|
||||
@ -87,9 +99,14 @@ class ButtonThread : public concurrency::OSThread
|
||||
{
|
||||
canSleep = true; // Assume we should not keep the board awake
|
||||
|
||||
#ifdef BUTTON_PIN
|
||||
#if defined(BUTTON_PIN)
|
||||
userButton.tick();
|
||||
canSleep &= userButton.isIdle();
|
||||
#elif defined(ARCH_RASPBERRY_PI)
|
||||
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) {
|
||||
userButton.tick();
|
||||
canSleep &= userButton.isIdle();
|
||||
}
|
||||
#endif
|
||||
#ifdef BUTTON_PIN_ALT
|
||||
userButtonAlt.tick();
|
||||
@ -121,6 +138,13 @@ class ButtonThread : public concurrency::OSThread
|
||||
!moduleConfig.canned_message.enabled) {
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
}
|
||||
#endif
|
||||
#if defined(ARCH_RASPBERRY_PI)
|
||||
if ((settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) &&
|
||||
(settingsMap[user] != moduleConfig.canned_message.inputbroker_pin_press) ||
|
||||
!moduleConfig.canned_message.enabled) {
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
static void userButtonPressedLong()
|
||||
|
@ -75,7 +75,7 @@ NRF52Bluetooth *nrf52Bluetooth;
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
#if HAS_BUTTON
|
||||
#if HAS_BUTTON || defined(ARCH_RASPBERRY_PI)
|
||||
#include "ButtonThread.h"
|
||||
#endif
|
||||
#include "PowerFSMThread.h"
|
||||
@ -206,13 +206,13 @@ static int32_t ledBlinker()
|
||||
|
||||
uint32_t timeLastPowered = 0;
|
||||
|
||||
#if HAS_BUTTON
|
||||
#if HAS_BUTTON || defined(ARCH_RASPBERRY_PI)
|
||||
bool ButtonThread::shutdown_on_long_stop = false;
|
||||
#endif
|
||||
|
||||
static Periodic *ledPeriodic;
|
||||
static OSThread *powerFSMthread;
|
||||
#if HAS_BUTTON
|
||||
#if HAS_BUTTON || defined(ARCH_RASPBERRY_PI)
|
||||
static OSThread *buttonThread;
|
||||
uint32_t ButtonThread::longPressTime = 0;
|
||||
#endif
|
||||
@ -583,7 +583,7 @@ void setup()
|
||||
else
|
||||
router = new ReliableRouter();
|
||||
|
||||
#if HAS_BUTTON
|
||||
#if HAS_BUTTON || defined(ARCH_RASPBERRY_PI)
|
||||
// Buttons. Moved here cause we need NodeDB to be initialized
|
||||
buttonThread = new ButtonThread();
|
||||
#endif
|
||||
|
@ -7,6 +7,8 @@
|
||||
// include the library for Raspberry GPIO pins
|
||||
#include "pigpio.h"
|
||||
|
||||
#include "linux/gpio/LinuxGPIOPin.h"
|
||||
|
||||
// create a new Raspberry Pi hardware abstraction layer
|
||||
// using the pigpio library
|
||||
// the HAL must inherit from the base RadioLibHal class
|
||||
@ -54,8 +56,7 @@ class PiHal : public RadioLibHal
|
||||
if (pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpioSetMode(pin, mode);
|
||||
::pinMode(pin, RADIOLIB_ARDUINOHAL_PIN_MODE_CAST mode);
|
||||
}
|
||||
|
||||
void digitalWrite(uint32_t pin, uint32_t value) override
|
||||
@ -63,8 +64,7 @@ class PiHal : public RadioLibHal
|
||||
if (pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpioWrite(pin, value);
|
||||
::digitalWrite(pin, RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST value);
|
||||
}
|
||||
|
||||
uint32_t digitalRead(uint32_t pin) override
|
||||
@ -73,7 +73,7 @@ class PiHal : public RadioLibHal
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (gpioRead(pin));
|
||||
return (::digitalRead(pin));
|
||||
}
|
||||
|
||||
void attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) override
|
||||
@ -81,11 +81,7 @@ class PiHal : public RadioLibHal
|
||||
if (interruptNum == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
if (gpioRead(interruptNum) == 1) {
|
||||
interruptCb();
|
||||
} else {
|
||||
gpioSetAlertFunc(interruptNum, (gpioISRFunc_t)interruptCb);
|
||||
}
|
||||
::attachInterrupt(interruptNum, interruptCb, RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST mode);
|
||||
}
|
||||
|
||||
void detachInterrupt(uint32_t interruptNum) override
|
||||
@ -94,7 +90,7 @@ class PiHal : public RadioLibHal
|
||||
return;
|
||||
}
|
||||
|
||||
gpioSetAlertFunc(interruptNum, NULL);
|
||||
::detachInterrupt(interruptNum);
|
||||
}
|
||||
|
||||
void delay(unsigned long ms) override { gpioDelay(ms * 1000); }
|
||||
@ -111,19 +107,8 @@ class PiHal : public RadioLibHal
|
||||
return (0);
|
||||
}
|
||||
|
||||
this->pinMode(pin, PI_INPUT);
|
||||
uint32_t start = this->micros();
|
||||
uint32_t curtick = this->micros();
|
||||
|
||||
while (this->digitalRead(pin) == state) {
|
||||
if ((this->micros() - curtick) > timeout) {
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (this->micros() - start);
|
||||
return (::pulseIn(pin, state, timeout));
|
||||
}
|
||||
|
||||
void spiBegin()
|
||||
{
|
||||
if (_spiHandle < 0) {
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#ifdef ARCH_RASPBERRY_PI
|
||||
#include "PortduinoGlue.h"
|
||||
#include "linux/gpio/LinuxGPIOPin.h"
|
||||
#include "pigpio.h"
|
||||
#include "yaml-cpp/yaml.h"
|
||||
#include <iostream>
|
||||
@ -101,6 +102,7 @@ void portduinoSetup()
|
||||
printf("Setting up Meshtastic on Portduino...\n");
|
||||
|
||||
#ifdef ARCH_RASPBERRY_PI
|
||||
gpioInit();
|
||||
YAML::Node yamlConfig;
|
||||
|
||||
if (access("config.yaml", R_OK) == 0) {
|
||||
@ -138,6 +140,9 @@ void portduinoSetup()
|
||||
settingsMap[busy] = yamlConfig["Lora"]["Busy"].as<int>(RADIOLIB_NC);
|
||||
settingsMap[reset] = yamlConfig["Lora"]["Reset"].as<int>(RADIOLIB_NC);
|
||||
}
|
||||
if (yamlConfig["GPIO"]) {
|
||||
settingsMap[user] = yamlConfig["GPIO"]["User"].as<int>(RADIOLIB_NC);
|
||||
}
|
||||
|
||||
} catch (YAML::Exception e) {
|
||||
std::cout << "*** Exception " << e.what() << std::endl;
|
||||
@ -147,6 +152,34 @@ void portduinoSetup()
|
||||
std::cout << "Cannot read Bluetooth MAC Address. Please run as root" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Need to bind all the configured GPIO pins so they're not simulated
|
||||
if (settingsMap.count(cs) > 0 && settingsMap[cs] != RADIOLIB_NC) {
|
||||
if (initGPIOPin(settingsMap[cs]) != ERRNO_OK) {
|
||||
settingsMap[cs] = RADIOLIB_NC;
|
||||
}
|
||||
}
|
||||
if (settingsMap.count(irq) > 0 && settingsMap[irq] != RADIOLIB_NC) {
|
||||
if (initGPIOPin(settingsMap[irq]) != ERRNO_OK) {
|
||||
settingsMap[irq] = RADIOLIB_NC;
|
||||
}
|
||||
}
|
||||
if (settingsMap.count(busy) > 0 && settingsMap[busy] != RADIOLIB_NC) {
|
||||
if (initGPIOPin(settingsMap[busy]) != ERRNO_OK) {
|
||||
settingsMap[busy] = RADIOLIB_NC;
|
||||
}
|
||||
}
|
||||
if (settingsMap.count(reset) > 0 && settingsMap[reset] != RADIOLIB_NC) {
|
||||
if (initGPIOPin(settingsMap[reset]) != ERRNO_OK) {
|
||||
settingsMap[reset] = RADIOLIB_NC;
|
||||
}
|
||||
}
|
||||
if (settingsMap.count(user) > 0 && settingsMap[user] != RADIOLIB_NC) {
|
||||
if (initGPIOPin(settingsMap[user]) != ERRNO_OK) {
|
||||
settingsMap[user] = RADIOLIB_NC;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
#endif
|
||||
|
||||
@ -195,3 +228,20 @@ void portduinoSetup()
|
||||
// gpioBind((new SimGPIOPin(LORA_CS, "LORA_CS"))->setSilent());
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ARCH_RASPBERRY_PI
|
||||
int initGPIOPin(int pinNum)
|
||||
{
|
||||
std::string gpio_name = "GPIO" + std::to_string(pinNum);
|
||||
try {
|
||||
GPIOPin *csPin;
|
||||
csPin = new LinuxGPIOPin(pinNum, "gpiochip0", pinNum, gpio_name.c_str());
|
||||
csPin->setSilent();
|
||||
gpioBind(csPin);
|
||||
return ERRNO_OK;
|
||||
} catch (std::invalid_argument &e) {
|
||||
std::cout << "Warning, cannot claim pin" << gpio_name << std::endl;
|
||||
return ERRNO_DISABLED;
|
||||
}
|
||||
}
|
||||
#endif
|
@ -4,6 +4,7 @@
|
||||
|
||||
extern std::map<int, int> settingsMap;
|
||||
|
||||
enum { use_sx1262, cs, irq, busy, reset, dio2_as_rf_switch, use_rf95 };
|
||||
enum { use_sx1262, cs, irq, busy, reset, dio2_as_rf_switch, use_rf95, user };
|
||||
int initGPIOPin(int pinNum);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user