diff --git a/sys/include/net/loramac.h b/sys/include/net/loramac.h index d5624d4067..03dcd9e9fd 100644 --- a/sys/include/net/loramac.h +++ b/sys/include/net/loramac.h @@ -22,6 +22,7 @@ #ifndef NET_LORAMAC_H #define NET_LORAMAC_H +#include #include #include @@ -966,6 +967,54 @@ typedef enum { uint8_t dcycle; /**< Duty cycle to use on this channel (1 to 100) */ } loramac_channel_t; +/** + * @brief Compute the time on air of a LoRa packet + * + * This function uses a precomputed table to calculate time on air without + * using floating point arithmetic + * + * @param[in] pkt_len Length of a packet in bytes + * @param[in] dr Datarate used to send the packet + * @param[in] cr Coding rate used to send the packet + * @return time on air in us + */ +static inline uint32_t lora_time_on_air(size_t pkt_len, uint8_t dr, uint8_t cr) +{ + assert(dr <= LORAMAC_DR_6); + const uint8_t _K[6][4] = { + { 0, 1, 5, 5 }, /* DR0 */ + { 0, 1, 4, 5 }, /* DR1 */ + { 1, 5, 5, 5 }, /* DR2 */ + { 1, 4, 5, 4 }, /* DR3 */ + { 1, 3, 4, 4 }, /* DR4 */ + { 1, 2, 4, 3 } /* DR5 */ + }; + + uint32_t t_sym = 1 << (15 - dr); + uint32_t t_preamble = (t_sym << 3) + (t_sym << 2) + (t_sym >> 2); + + uint8_t index = (dr < LORAMAC_DR_6) ? dr : LORAMAC_DR_5; + uint8_t n0 = _K[index][0]; + uint32_t nb_symbols; + + uint8_t offset = _K[index][1]; + + if (pkt_len < offset) { + nb_symbols = 8 + n0 * (cr + 4); + } + else { + uint8_t c1 = _K[index][2]; + uint8_t c2 = _K[index][3]; + uint8_t pos = (pkt_len - offset) % (c1 + c2); + uint8_t cycle = (pkt_len - offset) / (c1 + c2); + nb_symbols = 8 + (n0 + 2 * cycle + 1 + (pos > (c1 - 1))) * (cr + 4); + } + + uint32_t t_payload = t_sym * nb_symbols; + + return t_preamble + t_payload; +} + #ifdef __cplusplus } #endif diff --git a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c index 24932d8385..6749feb75f 100644 --- a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c +++ b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c @@ -207,43 +207,6 @@ void gnrc_lorawan_radio_rx_timeout_cb(gnrc_lorawan_t *mac) _sleep_radio(mac); } -/* This function uses a precomputed table to calculate time on air without - * using floating point arithmetic */ -static uint32_t lora_time_on_air(size_t payload_size, uint8_t dr, uint8_t cr) -{ - assert(dr <= LORAMAC_DR_6); - uint8_t _K[6][4] = { { 0, 1, 5, 5 }, - { 0, 1, 4, 5 }, - { 1, 5, 5, 5 }, - { 1, 4, 5, 4 }, - { 1, 3, 4, 4 }, - { 1, 2, 4, 3 } }; - - uint32_t t_sym = 1 << (15 - dr); - uint32_t t_preamble = (t_sym << 3) + (t_sym << 2) + (t_sym >> 2); - - int index = (dr < LORAMAC_DR_6) ? dr : LORAMAC_DR_5; - uint8_t n0 = _K[index][0]; - int nb_symbols; - - uint8_t offset = _K[index][1]; - - if (payload_size < offset) { - nb_symbols = 8 + n0 * cr; - } - else { - uint8_t c1 = _K[index][2]; - uint8_t c2 = _K[index][3]; - uint8_t pos = (payload_size - offset) % (c1 + c2); - uint8_t cycle = (payload_size - offset) / (c1 + c2); - nb_symbols = 8 + (n0 + 2 * cycle + 1 + (pos > (c1 - 1))) * cr; - } - - uint32_t t_payload = t_sym * nb_symbols; - - return t_preamble + t_payload; -} - void gnrc_lorawan_send_pkt(gnrc_lorawan_t *mac, iolist_t *psdu, uint8_t dr) { netdev_t *dev = gnrc_lorawan_get_netdev(mac); @@ -260,7 +223,7 @@ void gnrc_lorawan_send_pkt(gnrc_lorawan_t *mac, iolist_t *psdu, uint8_t dr) dev->driver->get(dev, NETOPT_CODING_RATE, &cr, sizeof(cr)); - mac->toa = lora_time_on_air(iolist_size(psdu), dr, cr + 4); + mac->toa = lora_time_on_air(iolist_size(psdu), dr, cr); if (dev->driver->send(dev, psdu) == -ENOTSUP) { DEBUG("gnrc_lorawan: Cannot send: radio is still transmitting");