vendredi 15 juillet 2022

Pass pointer of a non static member function to another non static member object

My question is simple but making a working example is difficult. I will try to explain as much well as I can. I am developing for an embedded platform. There is a radio tranceiver chip (sx1276) on my board. Here is how I use it:

  • A low level radio driver handles with the device registers (SX1276_LoRaRadio.cpp). This is provided by the manufacturer and developed exactly for the framework I am using (mbed os)
  • An API is developed by the framwork developer (arm) provides a higher level pure virtual class for abstraction (LoRaRadio.h). The low level driver inherits from this.
  • My own radio library for my application to build my own radio stack on the basis of the other two (ProtoTelecom.hpp and ProtoTelecom.cpp).

The radio has some interrupt pins which are triggered in the occurance of some events. The events are members of a struct, defined in LoRaRadio.h:

typedef struct radio_events {
    /**
     * Callback when Transmission is done.
     */
    mbed::Callback<void()> tx_done;

    /**
     * Callback when Transmission is timed out.
     */
    mbed::Callback<void()> tx_timeout;

    /**
     * Rx Done callback prototype.
     *
     *  @param payload Received buffer pointer.
     *  @param size    Received buffer size.
     *  @param rssi    RSSI value computed while receiving the frame [dBm].
     *  @param snr     Raw SNR value given by the radio hardware.
     *                     FSK : N/A (set to 0)
     *                     LoRa: SNR value in dB
     */
    mbed::Callback<void(const uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)> rx_done;

    /**
     * Callback when Reception is timed out.
     */
    mbed::Callback<void()> rx_timeout;

    /**
     * Callback when Reception ends up in error.
     */
    mbed::Callback<void()> rx_error;

    /**
     * FHSS Change Channel callback prototype.
     *
     *  @param current_channel   The index number of the current channel.
     */
    mbed::Callback<void(uint8_t current_channel)> fhss_change_channel;

    /**
     * CAD Done callback prototype.
     *
     *  @param channel_busy    True, if Channel activity detected.
     */
    mbed::Callback<void(bool channel_busy)> cad_done;
} radio_events_t;

My ProtoTelecom.hpp looks like this:

class ProtoTelecom: public manageCommands {
public:
    explicit ProtoTelecom(LoRaRadio *Radio, tcm_Manager *tcm);
    static void OnTxDone(void);
    void nonstaticTxDone(void);
    static void OnRxDone(const uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr);
    static void OnTxTimeout(void);
    static void OnRxTimeout(void);
    static void OnRxError(void);

    <other public stuff here>
private:
    static radio_events_t RadioEvents;

    <other private stuff here>
};

Then in ProtoTelecom.cpp I assign the pointers of the corresponding static member functions to the RadioEvents members:

radio_events_t ProtoTelecom::RadioEvents = {
            .tx_done = ProtoTelecom::OnTxDone,
            .tx_timeout = ProtoTelecom::OnTxTimeout,
            .rx_done = ProtoTelecom::OnRxDone,
            .rx_timeout = ProtoTelecom::OnRxTimeout,
            .rx_error = ProtoTelecom::OnRxError
};

ProtoTelecom::ProtoTelecom(LoRaRadio *Radio, c_TC_Manager *tcm) : manageCommands()
{
    <other stuff goes here>

    Radio->init_radio(&RadioEvents);
}

My problem is I have to have multiple instances of ProtoRadio. However, the radio isr functions must be static. Otherwise I cannot pass their pointers to the RadioEvents. This simply prevents me to initialize another hw because both execute the same isr functions. Also I have to initialize each one with different radio parameters but since all the other mebers are also static, I actually create a clone of the same ProtoRadio instance. So how can I pass the pointer of a non static member function to another non static member object inside the class itself? Something like this:

ProtoTelecom::ProtoTelecom(LoRaRadio *Radio, c_TC_Manager *tcm) : manageCommands()
{
    <other stuff goes here>
    RadioEvents.tx_done = nonstaticTxDone;
    Radio->init_radio(&RadioEvents);
}

I found this thread but the case is slightly different than mine and I could not manage to adapt it to my situation. The main theme of my question is the title but I know that what I am trying to achive is a bit strange and requires some tricks. So if there are other ways to achive my final goal that is also okay for me. Thanks.

Aucun commentaire:

Enregistrer un commentaire