123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- /*
- / _____) _ | |
- ( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
- (______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2019 Semtech
- Description:
- LoRa concentrator HAL auxiliary functions
- License: Revised BSD License, see LICENSE.TXT file include in the project
- */
- /* -------------------------------------------------------------------------- */
- /* --- DEPENDANCIES --------------------------------------------------------- */
- /* fix an issue between POSIX and C99 */
- #if __STDC_VERSION__ >= 199901L
- #define _XOPEN_SOURCE 600
- #else
- #define _XOPEN_SOURCE 500
- #endif
- #include <stdio.h> /* printf fprintf */
- #include <time.h> /* clock_nanosleep */
- #include <math.h> /* pow, ceil */
- #include "loragw_aux.h"
- #include "loragw_hal.h"
- /* -------------------------------------------------------------------------- */
- /* --- PRIVATE MACROS ------------------------------------------------------- */
- #if DEBUG_AUX == 1
- #define DEBUG_MSG(str) fprintf(stdout, str)
- #define DEBUG_PRINTF(fmt, args...) fprintf(stdout,"%s:%d: "fmt, __FUNCTION__, __LINE__, args)
- #else
- #define DEBUG_MSG(str)
- #define DEBUG_PRINTF(fmt, args...)
- #endif
- /* -------------------------------------------------------------------------- */
- /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
- void wait_us(unsigned long delay_us) {
- struct timespec dly;
- struct timespec rem;
- dly.tv_sec = delay_us / 1000000;
- dly.tv_nsec = (delay_us % 1000000) * 1000;
- DEBUG_PRINTF("NOTE dly: %ld sec %ld ns\n", dly.tv_sec, dly.tv_nsec);
- while ((dly.tv_sec > 0) || (dly.tv_nsec > 1000)) {
- /*
- rem is set ONLY if clock_nanosleep is interrupted (eg. by a signal).
- Must be zeroed each time or will get into an infinite loop after an IT.
- */
- rem.tv_sec = 0;
- rem.tv_nsec = 0;
- clock_nanosleep(CLOCK_MONOTONIC, 0, &dly, &rem);
- DEBUG_PRINTF("NOTE remain: %ld sec %ld ns\n", rem.tv_sec, rem.tv_nsec);
- dly = rem;
- }
- return;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- void wait_ms(unsigned long delay_ms) {
- struct timespec dly;
- struct timespec rem;
- dly.tv_sec = delay_ms / 1000;
- dly.tv_nsec = ((long)delay_ms % 1000) * 1000000;
- DEBUG_PRINTF("NOTE dly: %ld sec %ld ns\n", dly.tv_sec, dly.tv_nsec);
- if((dly.tv_sec > 0) || ((dly.tv_sec == 0) && (dly.tv_nsec > 100000))) {
- clock_nanosleep(CLOCK_MONOTONIC, 0, &dly, &rem);
- DEBUG_PRINTF("NOTE remain: %ld sec %ld ns\n", rem.tv_sec, rem.tv_nsec);
- }
- return;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- uint32_t lora_packet_time_on_air(const uint8_t bw, const uint8_t sf, const uint8_t cr, const uint16_t n_symbol_preamble,
- const bool no_header, const bool no_crc, const uint8_t size,
- double * out_nb_symbols, uint32_t * out_nb_symbols_payload, uint16_t * out_t_symbol_us) {
- uint8_t H, DE, n_bit_crc;
- uint8_t bw_pow;
- uint16_t t_symbol_us;
- double n_symbol;
- uint32_t toa_us, n_symbol_payload;
- /* Check input parameters */
- if (IS_LORA_DR(sf) == false) {
- printf("ERROR: wrong datarate - %s\n", __FUNCTION__);
- return 0;
- }
- if (IS_LORA_BW(bw) == false) {
- printf("ERROR: wrong bandwidth - %s\n", __FUNCTION__);
- return 0;
- }
- if (IS_LORA_CR(cr) == false) {
- printf("ERROR: wrong coding rate - %s\n", __FUNCTION__);
- return 0;
- }
- /* Get bandwidth 125KHz divider*/
- switch (bw) {
- case BW_125KHZ:
- bw_pow = 1;
- break;
- case BW_250KHZ:
- bw_pow = 2;
- break;
- case BW_500KHZ:
- bw_pow = 4;
- break;
- default:
- printf("ERROR: unsupported bandwith 0x%02X (%s)\n", bw, __FUNCTION__);
- return 0;
- }
- /* Duration of 1 symbol */
- t_symbol_us = (1 << sf) * 8 / bw_pow; /* 2^SF / BW , in microseconds */
- /* Packet parameters */
- H = (no_header == false) ? 1 : 0; /* header is always enabled, except for beacons */
- DE = (sf >= 11) ? 1 : 0; /* Low datarate optimization enabled for SF11 and SF12 */
- n_bit_crc = (no_crc == false) ? 16 : 0;
- /* Number of symbols in the payload */
- n_symbol_payload = ceil( MAX( (double)( 8 * size + n_bit_crc - 4*sf + ((sf >= 7) ? 8 : 0) + 20*H ), 0.0) /
- (double)( 4 * (sf - 2*DE)) )
- * ( cr + 4 ); /* Explicitely cast to double to keep precision of the division */
- /* number of symbols in packet */
- n_symbol = (double)n_symbol_preamble + ((sf >= 7) ? 4.25 : 6.25) + 8.0 + (double)n_symbol_payload;
- /* Duration of packet in microseconds */
- toa_us = (uint32_t)( (double)n_symbol * (double)t_symbol_us );
- DEBUG_PRINTF("INFO: LoRa packet ToA: %u us (n_symbol:%f, t_symbol_us:%u)\n", toa_us, n_symbol, t_symbol_us);
- /* Return details if required */
- if (out_nb_symbols != NULL) {
- *out_nb_symbols = n_symbol;
- }
- if (out_nb_symbols_payload != NULL) {
- *out_nb_symbols_payload = n_symbol_payload;
- }
- if (out_t_symbol_us != NULL) {
- *out_t_symbol_us = t_symbol_us;
- }
- return toa_us;
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- void _meas_time_start(struct timeval *tm)
- {
- #if (DEBUG_PaERF > 0) && (DEBUG_PERF <= 5)
- gettimeofday(tm, NULL);
- #endif
- }
- void _meas_time_stop(int debug_level, struct timeval start_time, const char *str)
- {
- #if (DEBUG_PERF > 0) && (DEBUG_PERF <= 5)
- struct timeval tm;
- double time_ms;
- char *indent[] = { "", " ..", " ....", " ......", " ........" };
- gettimeofday(&tm, NULL);
- time_ms = (tm.tv_sec - start_time.tv_sec) * 1000.0 + (tm.tv_usec - start_time.tv_usec) / 1000.0;
- if ((debug_level > 0) && (debug_level <= DEBUG_PERF)) {
- printf("PERF:%s %s %f ms\n", indent[debug_level - 1], str, time_ms);
- }
- #endif
- }
- #pragma GCC diagnostic pop
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- void timeout_start(struct timeval * start) {
- gettimeofday(start, NULL);
- }
- /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
- int timeout_check(struct timeval start, uint32_t timeout_ms) {
- struct timeval tm;
- struct timeval diff;
- uint32_t ms;
- gettimeofday(&tm, NULL);
- TIMER_SUB(&tm, &start, &diff);
- ms = diff.tv_sec * 1000 + diff.tv_usec / 1000;
- if (ms >= timeout_ms) {
- return -1;
- } else {
- return 0;
- }
- }
- /* --- EOF ------------------------------------------------------------------ */
|