Rcv_Unvsl (Universal Reciever)

Mono Wireless Inc.

Rcv_Unvsl (Universal Reciever)

By running NWK_LAYERED on twe_twelite.network and NWK_SIMPLE on twe_twelite.network2 in the MWX library, packets of different types, including packets of layered tree net (TWELITE PAL, ARIA, etc) You can receive and interpret various types of packets.

However, wireless packets must be on the same CHANNEL and have the same Application ID.

main.cpp

setup(), loop(), and the callback function on_rx_packet() for incoming packets.

setup()

These objects are declared in pkt_handler.cpp and initialized by pnew() in setup(). It mainly interprets the payload (data) of the packet.

    mwx::pnew(g_pkt_pal);
    mwx::pnew(g_pkt_apptwelite);
    mwx::pnew(g_pkt_actsamples);
    mwx::pnew(g_pkt_unknown);

Two network objects are created. Be sure to NWK_LAYERED to the_twelite.network.

    auto&& nwk_ly = the_twelite.network.use<NWK_LAYERED>();
    auto&& nwk_sm = the_twelite.network2.use<NWK_SIMPLE>();

loop()

In this sample, the important part of the loop() process is the .refresh() process, which is performed about every second. Only g_pkt_apptwelite().refresh() does the duplicate checker timeout. Other objects do nothing.

    if (TickTimer.available()) {
        static unsigned t;
        if (!(++t & 0x3FF)) {
            g_pkt_pal.refresh();
            g_pkt_apptwelite.refresh();
            g_pkt_actsamples.refresh();
            g_pkt_unknown.refresh();
        }
    }

on_rx_packet()

void on_rx_packet(packet_rx& rx, bool_t &handled) {
    auto type = rx.get_network_type();
    bool b_handled = false;

    // PAL
    if (!b_handled
        && type == mwx::NETWORK::LAYERED
        && g_pkt_pal.analyze(rx, b_handled)
    ) {
        g_pkt_pal.display(rx);
    }

    // Act samples
    if (!b_handled
        && type == mwx::NETWORK::SIMPLE
        && g_pkt_actsamples.analyze(rx, b_handled)
    ) {
        g_pkt_actsamples.display(rx);
    }

    // Standard application (e.g. App_Twelite)
    if (!b_handled
        && type == mwx::NETWORK::NONE
        && g_pkt_apptwelite.analyze(rx, b_handled)
    ) {
        g_pkt_apptwelite.display(rx);
    }

    // unknown
    if (!b_handled) {
        g_pkt_unknown.analyze(rx, b_handled);
        g_pkt_unknown.display(rx);
    }
}

This is the most important part of this sample code. auto type = rx.get_network_type(); determines the packet type.

In the case of mwx::NETWORK::NONE, the MWX library does not handle duplicate checkers for the same packet that may be sent in multiple retransmissions. It is necessary to describe the handling of these. In this sample, dup_checker.hpp and dup_checker.cpp are provided.

Interpretation of the packet refers to the packet_rx& object that wraps tsRxDataApp*. The packet_rx class itself has no special functionality, it only defines a means of accessing some information obtained from tsRxDataApp* using get_psRxDataApp().

pkt_common.hpp

It is defined for the purpose of unifying the interface of the packet interpretation part.

template <class D>
struct pkt_handler {
    D& self() { return static_cast<D&>(*this); }
    bool analyze(packet_rx& rx, bool &b_handled) {
        return self().pkt.analyze(rx, b_handled);
    }
    void display(packet_rx& rx) {
        Serial
            << crlf
            << format("!PKT_%s(%03d-%08x/S=%d/L=%03d/V=%04d)"
                    , self().get_label_packet_type()
                    , self().pkt.data.u8addr_src
                    , self().pkt.data.u32addr_src
                    , rx.get_psRxDataApp()->u8Seq
                    , rx.get_lqi()
                    , self().pkt.data.u16volt
                    );

        self().disp_detail(rx);
    }
    void refresh() {
        self()._refresh();
    }
};

// packet analyzer for App_Twelite
class pkt_handler_apptwelite : public pkt_handler<pkt_handler_apptwelite> {
    friend class pkt_handler<pkt_handler_apptwelite>;
    pkt_apptwelite pkt;
    void disp_detail(packet_rx& rx);
    const char* get_label_packet_type() { return "AppTwelite"; }
    void _refresh() { pkt.refresh(); }
public:
    pkt_handler_apptwelite() : pkt() {}
};

In addition, the packet interpretation class (example pkt_handler_apptwelite above) contains a member object pkt. The actual packet interpretation part is done in pkt_???.cpp.

pkt_???.hpp, pkt_???.cpp

A packet interpretation part analyze() for each packet type and a data structure data are defined. The member data is a structure but inherits the common structure of PktDataCommon. This common part is used to concisely describe the code for serial output of the packet’s data.

pkt_pal

Corresponds to PAL-related packets; the PAL packet structure has a complex data structure. The implementation here is based on the EASTL container.

Allocate an entry in _vect_pal_sensors for each of the multiple data in a packet as they are added and store the value. Once all the data in a packet has been interpreted, a _map_pal_sensors is constructed with the sensor type as the key.

dup_checker

Implement a duplicate checker. The behavior of the checker can be customized by template arguments.

template argument

container

duplicate check

    bool check_dup(uint32_t u32ser, uint16_t u16val, uint32_t u32_timestamp) {
        // find entry by key:u32ser.
        auto r = _mmap_entries.equal_range(u32ser);

        ...
    }

To retrieve data from the multimap structure, call .equal_range(). The resulting r is an iterator that enumerates elements with the same serial number.

Each element (_dup_checker_entry) has a timestamp and sequence number. Duplicates are checked according to these values.