[STM32WLx] Implement setDio1Action / interrupts
Because this interrupt is not connected to a GPIO or even the EXTI unit, but directly to the MCU NVIC, the regular attachInterrupt flow cannot be used. Instead, this lets STM32WLx override the setDio1Action() and clearDio1Action() methods to register the radio IRQ directly. Note that it would have been nicer to implement this by overriding attachInterrupt in STM32WLx_Module, but that is never called for virtual pins (because the STM32Duino digitalPinToInterrupt() macro does not work for virtual pins). In addition, because the NVIC is level-sensitive and the code expects edge-sensitive interrupts (for GPIO, the EXTI module in front of the NVIC makes the interrupts edge-sensitive), this adds some additional handling around the user-registered interrupt callback. To prevent the ISR from triggering over and over again (and also to not require SPI transactions in the ISR to clear the IRQ flags inside the radio), the interrupt is disabled in the NVIC whenever it is trigered. Then, whenever the IRQ flags *are* cleared in the radio, the IRQ is enabled in the NVIC again. This requires making the SX126x::clearIrqStatus() method virtual so STM32WLx can override it.
This commit is contained in:
parent
5e47d94418
commit
9252cf53d3
3 changed files with 44 additions and 1 deletions
|
@ -9,6 +9,7 @@ This file is licensed under the MIT License: https://opensource.org/licenses/MIT
|
|||
#include "STM32WLx.h"
|
||||
#if !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
||||
|
||||
#include <SubGhz.h>
|
||||
|
||||
STM32WLx::STM32WLx(STM32WLx_Module* mod) : SX1262(mod) {
|
||||
}
|
||||
|
@ -72,5 +73,30 @@ int16_t STM32WLx::setOutputPower(int8_t power) {
|
|||
return(writeRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
|
||||
}
|
||||
|
||||
int16_t STM32WLx::clearIrqStatus(uint16_t clearIrqParams) {
|
||||
int16_t res = SX126x::clearIrqStatus(clearIrqParams);
|
||||
// The NVIC interrupt is level-sensitive, so clear away any pending
|
||||
// flag that is only set because the radio IRQ status was not cleared
|
||||
// in the interrupt (to prevent each IRQ triggering twice and allow
|
||||
// reading the irq status through the pending flag).
|
||||
SubGhz.clearPendingInterrupt();
|
||||
if(SubGhz.hasInterrupt())
|
||||
SubGhz.enableInterrupt();
|
||||
return(res);
|
||||
}
|
||||
|
||||
void STM32WLx::setDio1Action(void (*func)(void)) {
|
||||
SubGhz.attachInterrupt([func]() {
|
||||
// Because the interrupt is level-triggered, we disable it in the
|
||||
// NVIC (otherwise we would need an SPI command to clear the IRQ in
|
||||
// the radio, or it would trigger over and over again).
|
||||
SubGhz.disableInterrupt();
|
||||
func();
|
||||
});
|
||||
}
|
||||
|
||||
void STM32WLx::clearDio1Action() {
|
||||
SubGhz.detachInterrupt();
|
||||
}
|
||||
|
||||
#endif // !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
||||
|
|
|
@ -112,6 +112,23 @@ class STM32WLx : public SX1262 {
|
|||
// Note: This explicitly inherits this method only to override docs
|
||||
using SX126x::setRfSwitchTable;
|
||||
|
||||
/*!
|
||||
\brief Sets interrupt service routine to call when DIO1/2/3 activates.
|
||||
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setDio1Action(void (*func)(void));
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when DIO1/2/3 activates.
|
||||
*/
|
||||
void clearDio1Action();
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
protected:
|
||||
#endif
|
||||
virtual int16_t clearIrqStatus(uint16_t clearIrqParams) override;
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
|
|
|
@ -982,7 +982,7 @@ class SX126x: public PhysicalLayer {
|
|||
int16_t writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset = 0x00);
|
||||
int16_t readBuffer(uint8_t* data, uint8_t numBytes);
|
||||
int16_t setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask = RADIOLIB_SX126X_IRQ_NONE, uint16_t dio3Mask = RADIOLIB_SX126X_IRQ_NONE);
|
||||
int16_t clearIrqStatus(uint16_t clearIrqParams = RADIOLIB_SX126X_IRQ_ALL);
|
||||
virtual int16_t clearIrqStatus(uint16_t clearIrqParams = RADIOLIB_SX126X_IRQ_ALL);
|
||||
int16_t setRfFrequency(uint32_t frf);
|
||||
int16_t calibrateImage(uint8_t* data);
|
||||
uint8_t getPacketType();
|
||||
|
|
Loading…
Add table
Reference in a new issue