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: 2025-11-15 20:31:27 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[120];
      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             :     // at this point we need to start escaping "%" characters
      98             :     char* strPtr = &str[59];
      99             :     for(size_t j = 0; j < line_len; j++) {
     100             :       char c = data[i+j];
     101             :       if((c < ' ') || (c > '~')) {
     102             :         c = '.';
     103             :       } else if(c == '%') {
     104             :         *strPtr++ = '%';
     105             :       }
     106             :       sprintf(strPtr++, "%c", c);
     107             :       
     108             :     }
     109             :     for(size_t j = line_len; j < 16; j++) {
     110             :       sprintf(strPtr++, "   ");
     111             :     }
     112             :     if(level) {
     113             :       RADIOLIB_DEBUG_PRINT_LVL("", "%s", level);
     114             :     }
     115             :     RADIOLIB_DEBUG_PRINT("%s", str);
     116             :     RADIOLIB_DEBUG_PRINTLN();
     117             :     rem_len -= 16;
     118             :   }
     119             : 
     120             :   #else
     121             :   // outside of debug, this does nothing
     122             :   (void)level;
     123             :   (void)data;
     124             :   (void)len;
     125             :   (void)offset;
     126             :   (void)width;
     127             :   (void)be;
     128             : 
     129             :   #endif
     130           0 : }
     131             : 
     132             : #if RADIOLIB_DEBUG
     133             : // https://github.com/esp8266/Arduino/blob/65579d29081cb8501e4d7f786747bf12e7b37da2/cores/esp8266/Print.cpp#L50
     134             : size_t rlb_printf(bool ts, const char* format, ...) {
     135             :   va_list arg;
     136             :   va_start(arg, format);
     137             :   char temp[64];
     138             :   char* buffer = temp;
     139             :   RadioLibTime_t timestamp = rlb_time_us();
     140             :   unsigned long sec = timestamp/1000000UL;
     141             :   unsigned long usec = timestamp%1000000UL;
     142             :   size_t len_ts = 0;
     143             :   if(ts) { len_ts = snprintf(temp, sizeof(temp), "[%lu.%06lu] ", sec, usec); }
     144             :   size_t len_str = vsnprintf(&temp[len_ts], sizeof(temp) - len_ts, format, arg);
     145             :   size_t len = len_ts + len_str;
     146             :   va_end(arg);
     147             :   if (len > sizeof(temp) - 1) {
     148             :     buffer = new char[len + 1];
     149             :     if (!buffer) {
     150             :       return 0;
     151             :     }
     152             :     va_start(arg, format);
     153             :     if(ts) { len_ts = snprintf(buffer, len_ts + 1, "[%lu.%06lu] ", sec, usec); }
     154             :     vsnprintf(buffer + len_ts, len_str + 1, format, arg);
     155             :     va_end(arg);
     156             :   }
     157             :   #if defined(RADIOLIB_BUILD_ARDUINO)
     158             :   len = RADIOLIB_DEBUG_PORT.write(reinterpret_cast<const uint8_t*>(buffer), len);
     159             :   #else
     160             :   len = fwrite(buffer, sizeof(temp[0]), len, RADIOLIB_DEBUG_PORT);
     161             :   #endif
     162             :   if (buffer != temp) {
     163             :     delete[] buffer;
     164             :   }
     165             :   return len;
     166             : }
     167             : #endif

Generated by: LCOV version 1.14