From ccc18f761ca767d8cf46856419613fe2349afc6f Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sat, 17 Feb 2024 12:24:12 +0100 Subject: [PATCH] Implement support for Raspberry Pi 5 using lgpio library --- RCSwitch.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++-- RCSwitch.h | 23 +++++++++++++++++++++-- 2 files changed, 66 insertions(+), 4 deletions(-) mode change 100644 => 100755 RCSwitch.cpp diff --git a/RCSwitch.cpp b/RCSwitch.cpp old mode 100644 new mode 100755 index 99d3cc1..c3be3a2 --- a/RCSwitch.cpp +++ b/RCSwitch.cpp @@ -34,7 +34,7 @@ #include "RCSwitch.h" -#ifdef RaspberryPi +#if defined( RaspberryPi ) || defined( RaspberryPi5 ) // PROGMEM and _P functions are for AVR based microprocessors, // so we must normalize these for the ARM processor: #define PROGMEM @@ -121,6 +121,12 @@ RCSwitch::RCSwitch() { #endif } +#if defined( RaspberryPi5 ) +RCSwitch::~RCSwitch() { + RCSwitch::setLgGpioHandle(0); +} +#endif + /** * Sets the protocol to send. */ @@ -174,6 +180,16 @@ void RCSwitch::setReceiveTolerance(int nPercent) { } #endif +#if defined( RaspberryPi5 ) +void RCSwitch::setLgGpioHandle(int gpiochip) { + if (gpiochip) { + RCSwitch::nLgGpioHandle = lgGpiochipOpen(gpiochip); + } else if (RCSwitch::nLgGpioHandle) { + lgGpiochipClose(RCSwitch::nLgGpioHandle); + RCSwitch::nLgGpioHandle = 0; + } +} +#endif /** * Enable transmissions @@ -182,7 +198,11 @@ void RCSwitch::setReceiveTolerance(int nPercent) { */ void RCSwitch::enableTransmit(int nTransmitterPin) { this->nTransmitterPin = nTransmitterPin; +#if defined( RaspberryPi5 ) + lgGpioClaimOutput(this->nLgGpioHandle, 0, this->nTransmitterPin, 0); +#else pinMode(this->nTransmitterPin, OUTPUT); +#endif } /** @@ -518,7 +538,11 @@ void RCSwitch::send(unsigned long code, unsigned int length) { } // Disable transmit after sending (i.e., for inverted protocols) +#if defined( RaspberryPi5 ) + lgGpioWrite(this->nLgGpioHandle, this->nTransmitterPin, LOW); +#else digitalWrite(this->nTransmitterPin, LOW); +#endif #if not defined( RCSwitchDisableReceiving ) // enable receiver again if we just disabled it @@ -535,10 +559,17 @@ void RCSwitch::transmit(HighLow pulses) { uint8_t firstLogicLevel = (this->protocol.invertedSignal) ? LOW : HIGH; uint8_t secondLogicLevel = (this->protocol.invertedSignal) ? HIGH : LOW; +#if defined( RaspberryPi5 ) + lgGpioWrite(this->nLgGpioHandle, this->nTransmitterPin, firstLogicLevel); + lguSleep( (float)this->protocol.pulseLength * pulses.high / 1000000); + lgGpioWrite(this->nLgGpioHandle, this->nTransmitterPin, secondLogicLevel); + lguSleep( (float)this->protocol.pulseLength * pulses.low / 1000000); +#else digitalWrite(this->nTransmitterPin, firstLogicLevel); delayMicroseconds( this->protocol.pulseLength * pulses.high); digitalWrite(this->nTransmitterPin, secondLogicLevel); delayMicroseconds( this->protocol.pulseLength * pulses.low); +#endif } @@ -557,6 +588,10 @@ void RCSwitch::enableReceive() { RCSwitch::nReceivedBitlength = 0; #if defined(RaspberryPi) // Raspberry Pi wiringPiISR(this->nReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt); +#elif defined(RaspberryPi5) // Raspberry Pi 5 + static int userdata = 1; + lgGpioSetAlertsFunc(this->nLgGpioHandle, this->nReceiverInterrupt, handleInterrupt, &userdata); + lgGpioClaimAlert(this->nLgGpioHandle, 0, LG_BOTH_EDGES, this->nReceiverInterrupt, -1); #else // Arduino attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE); #endif @@ -567,7 +602,7 @@ void RCSwitch::enableReceive() { * Disable receiving data */ void RCSwitch::disableReceive() { -#if not defined(RaspberryPi) // Arduino +#if not defined(RaspberryPi) and not defined(RaspberryPi5) // Arduino detachInterrupt(this->nReceiverInterrupt); #endif // For Raspberry Pi (wiringPi) you can't unregister the ISR this->nReceiverInterrupt = -1; @@ -668,13 +703,21 @@ bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCoun return false; } +#if defined( RaspberryPi5 ) +void RECEIVE_ATTR RCSwitch::handleInterrupt(int e, lgGpioAlert_p evt, void *data) { +#else void RECEIVE_ATTR RCSwitch::handleInterrupt() { +#endif static unsigned int changeCount = 0; static unsigned long lastTime = 0; static unsigned int repeatCount = 0; + #if defined( RaspberryPi5 ) + const long time = lguTimestamp(); + #else const long time = micros(); + #endif const unsigned int duration = time - lastTime; if (duration > RCSwitch::nSeparationLimit) { diff --git a/RCSwitch.h b/RCSwitch.h index b7755e0..1de5966 100644 --- a/RCSwitch.h +++ b/RCSwitch.h @@ -35,12 +35,20 @@ #elif defined(ENERGIA) // LaunchPad, FraunchPad and StellarPad specific #include "Energia.h" #elif defined(RPI) // Raspberry Pi - #define RaspberryPi - // Include libraries for RPi: #include /* memcpy */ #include /* abs */ + +#if (RPI==5) + #define RaspberryPi5 + #define LOW LG_LOW + #define HIGH LG_HIGH + #include +#else + #define RaspberryPi #include +#endif + #elif defined(SPARK) #include "application.h" #else @@ -64,6 +72,9 @@ class RCSwitch { public: RCSwitch(); +#if defined( RaspberryPi5 ) + ~RCSwitch(); +#endif void switchOn(int nGroupNumber, int nSwitchNumber); void switchOff(int nGroupNumber, int nSwitchNumber); @@ -101,6 +112,9 @@ class RCSwitch { #if not defined( RCSwitchDisableReceiving ) void setReceiveTolerance(int nPercent); #endif + #if defined( RaspberryPi5 ) + void setLgGpioHandle(int nLgGpioHandle); + #endif /** * Description of a single pule, which consists of a high signal @@ -156,7 +170,12 @@ class RCSwitch { void transmit(HighLow pulses); #if not defined( RCSwitchDisableReceiving ) + #if defined( RaspberryPi5 ) + static void handleInterrupt(int e, lgGpioAlert_p evt, void *data); + int nLgGpioHandle; + #else static void handleInterrupt(); + #endif static bool receiveProtocol(const int p, unsigned int changeCount); int nReceiverInterrupt; #endif