LowPowerLab / RFM69

RFM69 library for RFM69W, RFM69HW, RFM69CW, RFM69HCW (semtech SX1231, SX1231H)
GNU General Public License v3.0
778 stars 381 forks source link

ISR callback in a user space #181

Closed strange-v closed 2 years ago

strange-v commented 2 years ago

This library works well on ESP32, and I've been using it for a couple of years to re-send data from low-power nodes to an MQTT broker. The only downside for me is that partially it relays on polling instead of being fully interrupt-driven.

I've seen a few discussions about adding an ISR callback, but it was never done. So here it is.

A few additional notes:

An example that demonstrates the usage:

SPIClass spi;
RFM69 radio(RFM_CS, RFM_INT, RFM_HW, &spi);
EventGroupHandle_t eg;
SemaphoreHandle_t semaRadio;

#define EVENT_RADIO_MESSAGE (1 << 0)

void IRAM_ATTR isrRadioMessage()
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    xEventGroupSetBitsFromISR(eg, EVENT_RADIO_MESSAGE, &xHigherPriorityTaskWoken);
}

void taskReadRadioMessage(void *pvParameters)
{
    for (;;)
    {
        xEventGroupWaitBits(eg, EVENT_RADIO_MESSAGE, pdTRUE, pdTRUE, portMAX_DELAY);

        if (xSemaphoreTake(semaRadio, portMAX_DELAY) == pdTRUE)
        {
            if (radio.receiveDone())
            {
                Serial.printf("Received from node %d\n", radio.SENDERID);
                Serial.printf("Length: %d\n", radio.DATALEN);
                Serial.printf("RSSI: %d\n", radio.RSSI);

                // Do something with payload

                if (radio.ACKRequested())
                {
                    radio.sendACK();
                    Serial.printf("ACK sent to node %d\n", radio.SENDERID);
                }
            }
            xSemaphoreGive(semaRadio);
        }
    }
}

void setup()
{
  Serial.begin(115200);
  pinMode(RFM_INT, INPUT);

  eg = xEventGroupCreate();
  semaRadio = xSemaphoreCreateMutex();

  xTaskCreatePinnedToCore(taskReadRadioMessage, "radio", TaskStack10K, NULL, Priority1, NULL, Core1);

  spi.begin(M_SCK, M_MISO, M_MOSI, RFM_CS);
  radio.initialize(RF69_868MHZ, RADIO_NODE_ID, RADIO_NETWORK_ID);
  radio.encrypt(RADIO_ENCRYPTION_KEY);
  radio.setIsrCallback(isrRadioMessage);
  radio.receiveDone();
}

void loop()
{
}

Let me know if any additional fixes are required to merge this PR. Thank you for the great library.

LowPowerLab commented 2 years ago

Thank you very much for the contribution. This adds 32bytes to the sketch size, and 4 RAM bytes.