LCOV - code coverage report
Current view: top level - src/utils - Utils.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 30 0.0 %
Date: 2026-11-08 19:43:08 Functions: 0 4 0.0 %

          Line data    Source code
       1             : #include "Utils.h"
       2             : #include "../Hal.h"
       3             : 
       4             : #include <stdarg.h>
       5             : #include <stdio.h>
       6             : #include <stdlib.h>
       7             : #include <string.h>
       8             : #include <inttypes.h>
       9             : 
      10           0 : uint32_t rlb_reflect(uint32_t in, uint8_t bits) {
      11           0 :   uint32_t res = 0;
      12           0 :   for(uint8_t i = 0; i < bits; i++) {
      13           0 :     res |= (((in & ((uint32_t)1 << i)) >> i) << (bits - i - 1));
      14             :   }
      15           0 :   return(res);
      16             : }
      17             : 
      18             : // fast-ish popcount function for use in calculating LFSR feedback value
      19             : // without relying on __builtin_popcount() which may or may not be available
      20             : // from https://stackoverflow.com/a/51388846
      21           0 : static uint8_t rlb_popcount(uint32_t in) {
      22           0 :   in = (in & 0x55555555UL) + ((in >> 1) & 0x55555555UL);
      23           0 :   in = (in & 0x33333333UL) + ((in >> 2) & 0x33333333UL);
      24           0 :   in = (in & 0x0F0F0F0FUL) + ((in >> 4) & 0x0F0F0F0FUL);
      25           0 :   in = (in & 0x00FF00FFUL) + ((in >> 8) & 0x00FF00FFUL);
      26           0 :   in = (in & 0x0000FFFFUL) + ((in >>16) & 0x0000FFFFUL);
      27           0 :   return(in);
      28             : }
      29             : 
      30           0 : void rlb_scrambler(uint8_t* data, size_t len, const uint32_t poly, const uint32_t init, bool scramble) {
      31           0 :   if(!poly) {
      32           0 :     return;
      33             :   }
      34             : 
      35             :   // set the inital feedback register state
      36           0 :   uint32_t lsfr = init;
      37             :   
      38             :   // now do the shifting
      39           0 :   uint8_t out = 0;
      40           0 :   for(size_t i = 0; i < len; i++) {
      41             :     // for each data byte
      42           0 :     for(int j = 7; j >= 0; j--) {
      43             :       // for each bit in each data byte, calculate the next bit
      44           0 :       uint8_t feedback = rlb_popcount(lsfr & poly) & 1UL;
      45           0 :       uint8_t inbit = (data[i] & (1UL << j)) >> j;
      46           0 :       uint32_t nextbit = feedback ^ inbit;
      47             : 
      48             :       // shift the feedback register
      49           0 :       lsfr <<= 1;
      50             :       
      51             :       // now add the next bit
      52             :       // when scrambling, it is the calculated next bit
      53             :       // when descrambling, it is the input bit
      54           0 :       lsfr |= scramble ? nextbit : inbit;
      55             : 
      56             :       // shift the output buffer and add the next bit
      57           0 :       out <<= 1;
      58           0 :       out |= nextbit;
      59             :     }
      60             :     
      61             :     // extract the new byte
      62           0 :     data[i] = out;
      63           0 :     out = 0;
      64             :   }
      65             : }
      66             : 
      67           0 : void rlb_hexdump(const char* level, const uint8_t* data, size_t len, uint32_t offset, uint8_t width, bool be) {
      68             :   #if RADIOLIB_DEBUG
      69             :   size_t rem_len = len;
      70             :   for(size_t i = 0; i < len; i+=16) {
      71             :     char str[80];
      72             :     sprintf(str, "%08" PRIx32 ": ", (uint32_t)i+offset);
      73             :     size_t line_len = 16;
      74             :     if(rem_len < line_len) {
      75             :       line_len = rem_len;
      76             :     }
      77             :     for(size_t j = 0; j < line_len; j+=width) {
      78             :       if(width > 1) {
      79             :         int m = 0;
      80             :         int step = width/2;
      81             :         if(be) {
      82             :           step *= -1;
      83             :         }
      84             :         for(int32_t k = width - 1; k >= -width + 1; k+=step) {
      85             :           sprintf(&str[10 + (j+m)*3], "%02x ", data[i+j+k+m]);
      86             :           m++;
      87             :         }
      88             :       } else {
      89             :         sprintf(&str[10 + (j)*3], "%02x ", data[i+j]);
      90             :       }
      91             :     }
      92             :     for(size_t j = line_len; j < 16; j++) {
      93             :       sprintf(&str[10 + j*3], "   ");
      94             :     }
      95             :     str[58] = ' ';
      96             : 
      97             :     for(size_t j = 0; j < line_len; j++) {
      98             :       char c = data[i+j];
      99             :       if((c < ' ') || (c > '~')) {
     100             :         c = '.';
     101             :       }
     102             :       sprintf(&str[58 + j], "%c", c);
     103             :     }
     104             :     for(size_t j = line_len; j < 16; j++) {
     105             :       sprintf(&str[58 + j], "   ");
     106             :     }
     107             :     if(level) {
     108             :       RADIOLIB_DEBUG_PRINT_LVL("", "%s", level);
     109             :     }
     110             :     
     111             :     // to print the string-ified value, use write instead of the print macro
     112             :     // this will prevent accidentally interpreting '%' characters as control sequences
     113             :     #if defined(RADIOLIB_BUILD_ARDUINO)
     114             :     (void)RADIOLIB_DEBUG_PORT.write(reinterpret_cast<const uint8_t*>(str), strlen(str));
     115             :     #else
     116             :     (void)fwrite(str, sizeof(str[0]), strlen(str), RADIOLIB_DEBUG_PORT);
     117             :     #endif
     118             :     RADIOLIB_DEBUG_PRINTLN();
     119             :     rem_len -= 16;
     120             :   }
     121             : 
     122             :   #else
     123             :   // outside of debug, this does nothing
     124             :   (void)level;
     125             :   (void)data;
     126             :   (void)len;
     127             :   (void)offset;
     128             :   (void)width;
     129             :   (void)be;
     130             : 
     131             :   #endif
     132           0 : }
     133             : 
     134             : #if RADIOLIB_DEBUG
     135             : // https://github.com/esp8266/Arduino/blob/65579d29081cb8501e4d7f786747bf12e7b37da2/cores/esp8266/Print.cpp#L50
     136             : size_t rlb_printf(bool ts, const char* format, ...) {
     137             :   va_list arg;
     138             :   va_start(arg, format);
     139             :   char temp[64];
     140             :   char* buffer = temp;
     141             :   RadioLibTime_t timestamp = rlb_time_us();
     142             :   unsigned long sec = timestamp/1000000UL;
     143             :   unsigned long usec = timestamp%1000000UL;
     144             :   size_t len_ts = 0;
     145             :   if(ts) { len_ts = snprintf(temp, sizeof(temp), "[%lu.%06lu] ", sec, usec); }
     146             :   size_t len_str = vsnprintf(&temp[len_ts], sizeof(temp) - len_ts, format, arg);
     147             :   size_t len = len_ts + len_str;
     148             :   va_end(arg);
     149             :   if (len > sizeof(temp) - 1) {
     150             :     buffer = new char[len + 1];
     151             :     if (!buffer) {
     152             :       return 0;
     153             :     }
     154             :     va_start(arg, format);
     155             :     if(ts) { len_ts = snprintf(buffer, len_ts + 1, "[%lu.%06lu] ", sec, usec); }
     156             :     vsnprintf(buffer + len_ts, len_str + 1, format, arg);
     157             :     va_end(arg);
     158             :   }
     159             :   #if defined(RADIOLIB_BUILD_ARDUINO)
     160             :   len = RADIOLIB_DEBUG_PORT.write(reinterpret_cast<const uint8_t*>(buffer), len);
     161             :   #else
     162             :   len = fwrite(buffer, sizeof(temp[0]), len, RADIOLIB_DEBUG_PORT);
     163             :   #endif
     164             :   if (buffer != temp) {
     165             :     delete[] buffer;
     166             :   }
     167             :   return len;
     168             : }
     169             : #endif

Generated by: LCOV version 1.14