[Utils] Move generally useful methods to utils

This commit is contained in:
jgromes 2024-10-20 14:22:23 +01:00
parent 0f2f5fdf4a
commit 4a155b1922
11 changed files with 170 additions and 144 deletions

View file

@ -473,10 +473,10 @@
#if RADIOLIB_DEBUG
#if defined(RADIOLIB_BUILD_ARDUINO)
#define RADIOLIB_DEBUG_PRINT(...) Module::serialPrintf(__VA_ARGS__)
#define RADIOLIB_DEBUG_PRINTLN(M, ...) Module::serialPrintf(M "\n", ##__VA_ARGS__)
#define RADIOLIB_DEBUG_PRINT_LVL(LEVEL, M, ...) Module::serialPrintf(LEVEL "" M, ##__VA_ARGS__)
#define RADIOLIB_DEBUG_PRINTLN_LVL(LEVEL, M, ...) Module::serialPrintf(LEVEL "" M "\n", ##__VA_ARGS__)
#define RADIOLIB_DEBUG_PRINT(...) rlb_printf(__VA_ARGS__)
#define RADIOLIB_DEBUG_PRINTLN(M, ...) rlb_printf(M "\n", ##__VA_ARGS__)
#define RADIOLIB_DEBUG_PRINT_LVL(LEVEL, M, ...) rlb_printf(LEVEL "" M, ##__VA_ARGS__)
#define RADIOLIB_DEBUG_PRINTLN_LVL(LEVEL, M, ...) rlb_printf(LEVEL "" M "\n", ##__VA_ARGS__)
// some platforms do not support printf("%f"), so it has to be done this way
#define RADIOLIB_DEBUG_PRINT_FLOAT(LEVEL, VAL, DECIMALS) RADIOLIB_DEBUG_PRINT(LEVEL); RADIOLIB_DEBUG_PORT.print(VAL, DECIMALS)
@ -492,7 +492,7 @@
#define RADIOLIB_DEBUG_PRINT_FLOAT(LEVEL, VAL, DECIMALS) RADIOLIB_DEBUG_PRINT(LEVEL "%.3f", VAL)
#endif
#define RADIOLIB_DEBUG_HEXDUMP(LEVEL, ...) Module::hexdump(LEVEL, __VA_ARGS__)
#define RADIOLIB_DEBUG_HEXDUMP(LEVEL, ...) rlb_hexdump(LEVEL, __VA_ARGS__)
#else
#define RADIOLIB_DEBUG_PRINT(...) {}
#define RADIOLIB_DEBUG_PRINTLN(...) {}

View file

@ -1,15 +1,9 @@
#include "Module.h"
// the following is probably only needed on non-Arduino builds
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#if RADIOLIB_DEBUG
// needed for debug print
#include <stdarg.h>
#endif
#if defined(RADIOLIB_BUILD_ARDUINO)
#include "ArduinoHal.h"
@ -461,69 +455,7 @@ void Module::waitForMicroseconds(RadioLibTime_t start, RadioLibTime_t len) {
#endif
}
uint32_t Module::reflect(uint32_t in, uint8_t bits) {
uint32_t res = 0;
for(uint8_t i = 0; i < bits; i++) {
res |= (((in & ((uint32_t)1 << i)) >> i) << (bits - i - 1));
}
return(res);
}
#if RADIOLIB_DEBUG
void Module::hexdump(const char* level, uint8_t* data, size_t len, uint32_t offset, uint8_t width, bool be) {
size_t rem_len = len;
for(size_t i = 0; i < len; i+=16) {
char str[120];
sprintf(str, "%08" PRIx32 ": ", (uint32_t)i+offset);
size_t line_len = 16;
if(rem_len < line_len) {
line_len = rem_len;
}
for(size_t j = 0; j < line_len; j+=width) {
if(width > 1) {
int m = 0;
int step = width/2;
if(be) {
step *= -1;
}
for(int32_t k = width - 1; k >= -width + 1; k+=step) {
sprintf(&str[10 + (j+m)*3], "%02x ", data[i+j+k+m]);
m++;
}
} else {
sprintf(&str[10 + (j)*3], "%02x ", data[i+j]);
}
}
for(size_t j = line_len; j < 16; j++) {
sprintf(&str[10 + j*3], " ");
}
//str[56] = '|';
str[58] = ' ';
// at this point we need to start escaping "%" characters
char* strPtr = &str[59];
for(size_t j = 0; j < line_len; j++) {
char c = data[i+j];
if((c < ' ') || (c > '~')) {
c = '.';
} else if(c == '%') {
*strPtr++ = '%';
}
sprintf(strPtr++, "%c", c);
}
for(size_t j = line_len; j < 16; j++) {
sprintf(strPtr++, " ");
}
if(level) {
RADIOLIB_DEBUG_PRINT(level);
}
RADIOLIB_DEBUG_PRINT(str);
RADIOLIB_DEBUG_PRINTLN();
rem_len -= 16;
}
}
void Module::regdump(const char* level, uint16_t start, size_t len) {
#if RADIOLIB_STATIC_ONLY
uint8_t buff[RADIOLIB_STATIC_ARRAY_SIZE];
@ -531,39 +463,13 @@ void Module::regdump(const char* level, uint16_t start, size_t len) {
uint8_t* buff = new uint8_t[len];
#endif
SPIreadRegisterBurst(start, len, buff);
hexdump(level, buff, len, start);
rlb_hexdump(level, buff, len, start);
#if !RADIOLIB_STATIC_ONLY
delete[] buff;
#endif
}
#endif
#if RADIOLIB_DEBUG && defined(RADIOLIB_BUILD_ARDUINO)
// https://github.com/esp8266/Arduino/blob/65579d29081cb8501e4d7f786747bf12e7b37da2/cores/esp8266/Print.cpp#L50
size_t Module::serialPrintf(const char* format, ...) {
va_list arg;
va_start(arg, format);
char temp[64];
char* buffer = temp;
size_t len = vsnprintf(temp, sizeof(temp), format, arg);
va_end(arg);
if (len > sizeof(temp) - 1) {
buffer = new char[len + 1];
if (!buffer) {
return 0;
}
va_start(arg, format);
vsnprintf(buffer, len + 1, format, arg);
va_end(arg);
}
len = RADIOLIB_DEBUG_PORT.write(reinterpret_cast<const uint8_t*>(buffer), len);
if (buffer != temp) {
delete[] buffer;
}
return len;
}
#endif
void Module::setRfSwitchPins(uint32_t rxEn, uint32_t txEn) {
// This can be on the stack, setRfSwitchTable copies the contents
const uint32_t pins[] = {

View file

@ -3,6 +3,7 @@
#include "TypeDef.h"
#include "Hal.h"
#include "utils/Utils.h"
#if defined(RADIOLIB_BUILD_ARDUINO)
#include <SPI.h>
@ -505,26 +506,7 @@ class Module {
*/
void waitForMicroseconds(RadioLibTime_t start, RadioLibTime_t len);
/*!
\brief Function to reflect bits within a byte.
\param in The input to reflect.
\param bits Number of bits to reflect.
\return The reflected input.
*/
static uint32_t reflect(uint32_t in, uint8_t bits);
#if RADIOLIB_DEBUG
/*!
\brief Function to dump data as hex into the debug port.
\param level RadioLib debug level, set to NULL to not print.
\param data Data to dump.
\param len Number of bytes to dump.
\param offset Address offset to add when printing the data.
\param width Word width (1 for uint8_t, 2 for uint16_t, 4 for uint32_t).
\param be Print multi-byte data as big endian. Defaults to false.
*/
static void hexdump(const char* level, uint8_t* data, size_t len, uint32_t offset = 0, uint8_t width = 1, bool be = false);
/*!
\brief Function to dump device registers as hex into the debug port.
\param level RadioLib debug level, set to NULL to not print.
@ -534,10 +516,6 @@ class Module {
void regdump(const char* level, uint16_t start, size_t len);
#endif
#if RADIOLIB_DEBUG and defined(RADIOLIB_BUILD_ARDUINO)
static size_t serialPrintf(const char* format, ...);
#endif
#if !RADIOLIB_GODMODE
private:
#endif

View file

@ -1779,7 +1779,7 @@ int16_t LR11x0::isGnssScanCapable() {
size_t len = sz > 32 ? 32 : sz/sizeof(uint32_t);
state = this->readRegMem32(addr, buff, len);
RADIOLIB_ASSERT(state);
Module::hexdump(NULL, (uint8_t*)buff, len*sizeof(uint32_t), addr);
RADIOLIB_DEBUG_HEXDUMP(NULL, (uint8_t*)buff, len*sizeof(uint32_t), addr);
addr += len*sizeof(uint32_t);
sz -= len*sizeof(uint32_t);
}
@ -1789,7 +1789,7 @@ int16_t LR11x0::isGnssScanCapable() {
RADIOLIB_DEBUG_BASIC_PRINTLN("Almanac[%d]:", i);
state = this->gnssAlmanacReadSV(i, almanac);
RADIOLIB_ASSERT(state);
Module::hexdump(NULL, almanac, 22);
RADIOLIB_DEBUG_HEXDUMP(NULL, almanac, 22);
}
#endif

View file

@ -1,5 +1,7 @@
#include "AX25.h"
#include <string.h>
#if !RADIOLIB_EXCLUDE_AX25
AX25Frame::AX25Frame(const char* destCallsign, uint8_t destSSID, const char* srcCallsign, uint8_t srcSSID, uint8_t control)
@ -369,7 +371,7 @@ int16_t AX25Client::sendFrame(AX25Frame* frame) {
// flip bit order
for(size_t i = 0; i < frameBuffLen; i++) {
frameBuff[i] = Module::reflect(frameBuff[i], 8);
frameBuff[i] = rlb_reflect(frameBuff[i], 8);
}
// calculate

View file

@ -1,6 +1,8 @@
#include "Pager.h"
#include <string.h>
#include <math.h>
#if defined(ESP_PLATFORM)
#include "esp_attr.h"
#endif
@ -177,7 +179,7 @@ int16_t PagerClient::transmit(uint8_t* data, size_t len, uint32_t addr, uint8_t
// first insert the remainder from previous code word (if any)
if(remBits > 0) {
// this doesn't apply to BCD messages, so no need to check that here
uint8_t prev = Module::reflect(data[dataPos - 1], 8);
uint8_t prev = rlb_reflect(data[dataPos - 1], 8);
prev >>= 1;
msg[blockPos] |= (uint32_t)prev << (RADIOLIB_PAGER_CODE_WORD_LEN - 1 - remBits);
}
@ -191,7 +193,7 @@ int16_t PagerClient::transmit(uint8_t* data, size_t len, uint32_t addr, uint8_t
if(encoding == RADIOLIB_PAGER_BCD) {
symbol = encodeBCD(symbol);
}
symbol = Module::reflect(symbol, 8);
symbol = rlb_reflect(symbol, 8);
symbol >>= (8 - symbolLength);
// insert the next message symbol
@ -205,7 +207,7 @@ int16_t PagerClient::transmit(uint8_t* data, size_t len, uint32_t addr, uint8_t
uint8_t numSteps = (symbolPos - RADIOLIB_PAGER_FUNC_BITS_POS + symbolLength)/symbolLength;
for(uint8_t j = 0; j < numSteps; j++) {
symbol = encodeBCD(' ');
symbol = Module::reflect(symbol, 8);
symbol = rlb_reflect(symbol, 8);
symbol >>= (8 - symbolLength);
msg[blockPos] |= (uint32_t)symbol << symbolPos;
symbolPos -= symbolLength;
@ -428,7 +430,7 @@ int16_t PagerClient::readData(uint8_t* data, size_t* len, uint32_t* addr) {
uint32_t symbol = prevSymbol << (symbolLength - ovfBits) | currSymbol;
// finally, we can flip the bits
symbol = Module::reflect((uint8_t)symbol, 8);
symbol = rlb_reflect((uint8_t)symbol, 8);
symbol >>= (8 - symbolLength);
// decode BCD and we're done
@ -446,7 +448,7 @@ int16_t PagerClient::readData(uint8_t* data, size_t* len, uint32_t* addr) {
while(bitPos >= RADIOLIB_PAGER_MESSAGE_END_POS) {
// get the message symbol from the code word and reverse bits
uint32_t symbol = (cw & (0x7FUL << bitPos)) >> bitPos;
symbol = Module::reflect((uint8_t)symbol, 8);
symbol = rlb_reflect((uint8_t)symbol, 8);
symbol >>= (8 - symbolLength);
// decode BCD if needed

View file

@ -1,4 +1,5 @@
#include "PhysicalLayer.h"
#include <string.h>
PhysicalLayer::PhysicalLayer(float step, size_t maxLen) {
@ -481,7 +482,7 @@ void PhysicalLayer::updateDirectBuffer(uint8_t bit) {
// check complete byte
if(this->bufferBitPos == 8) {
this->buffer[this->bufferWritePos] = Module::reflect(this->buffer[this->bufferWritePos], 8);
this->buffer[this->bufferWritePos] = rlb_reflect(this->buffer[this->bufferWritePos], 8);
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("R\t%X", this->buffer[this->bufferWritePos]);
this->bufferWritePos++;

View file

@ -11,7 +11,7 @@ uint32_t RadioLibCRC::checksum(const uint8_t* buff, size_t len) {
if(i % 8 == 0) {
uint32_t in = buff[pos++];
if(this->refIn) {
in = Module::reflect(in, 8);
in = rlb_reflect(in, 8);
}
crc ^= (in << (this->size - 8));
}
@ -26,7 +26,7 @@ uint32_t RadioLibCRC::checksum(const uint8_t* buff, size_t len) {
crc ^= this->out;
if(this->refOut) {
crc = Module::reflect(crc, this->size);
crc = rlb_reflect(crc, this->size);
}
crc &= (uint32_t)0xFFFFFFFF >> (32 - this->size);
return(crc);

View file

@ -71,16 +71,6 @@ class RadioLibBCH {
// the global singleton
extern RadioLibBCH RadioLibBCHInstance;
// macros to access bits in byte array, from http://www.mathcs.emory.edu/~cheung/Courses/255/Syllabus/1-C-intro/bit-array.html
#define SET_BIT_IN_ARRAY_MSB(A, k) ( A[((k)/8)] |= (1 << ((k)%8)) )
#define CLEAR_BIT_IN_ARRAY_MSB(A, k) ( A[((k)/8)] &= ~(1 << ((k)%8)) )
#define TEST_BIT_IN_ARRAY_MSB(A, k) ( A[((k)/8)] & (1 << ((k)%8)) )
#define GET_BIT_IN_ARRAY_MSB(A, k) ( (A[((k)/8)] & (1 << ((k)%8))) ? 1 : 0 )
#define SET_BIT_IN_ARRAY_LSB(A, k) ( A[((k)/8)] |= (1 << (7 - ((k)%8))) )
#define CLEAR_BIT_IN_ARRAY_LSB(A, k) ( A[((k)/8)] &= ~(1 << (7 - ((k)%8))) )
#define TEST_BIT_IN_ARRAY_LSB(A, k) ( A[((k)/8)] & (1 << (7 - ((k)%8))) )
#define GET_BIT_IN_ARRAY_LSB(A, k) ( (A[((k)/8)] & (1 << (7 - ((k)%8)))) ? 1 : 0 )
/*!
\class RadioLibConvCode
\brief Class to perform convolutional coding with variable rates.

105
src/utils/Utils.cpp Normal file
View file

@ -0,0 +1,105 @@
#include "Utils.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
uint32_t rlb_reflect(uint32_t in, uint8_t bits) {
uint32_t res = 0;
for(uint8_t i = 0; i < bits; i++) {
res |= (((in & ((uint32_t)1 << i)) >> i) << (bits - i - 1));
}
return(res);
}
void rlb_hexdump(const char* level, uint8_t* data, size_t len, uint32_t offset, uint8_t width, bool be) {
#if RADIOLIB_DEBUG
size_t rem_len = len;
for(size_t i = 0; i < len; i+=16) {
char str[120];
sprintf(str, "%08" PRIx32 ": ", (uint32_t)i+offset);
size_t line_len = 16;
if(rem_len < line_len) {
line_len = rem_len;
}
for(size_t j = 0; j < line_len; j+=width) {
if(width > 1) {
int m = 0;
int step = width/2;
if(be) {
step *= -1;
}
for(int32_t k = width - 1; k >= -width + 1; k+=step) {
sprintf(&str[10 + (j+m)*3], "%02x ", data[i+j+k+m]);
m++;
}
} else {
sprintf(&str[10 + (j)*3], "%02x ", data[i+j]);
}
}
for(size_t j = line_len; j < 16; j++) {
sprintf(&str[10 + j*3], " ");
}
str[58] = ' ';
// at this point we need to start escaping "%" characters
char* strPtr = &str[59];
for(size_t j = 0; j < line_len; j++) {
char c = data[i+j];
if((c < ' ') || (c > '~')) {
c = '.';
} else if(c == '%') {
*strPtr++ = '%';
}
sprintf(strPtr++, "%c", c);
}
for(size_t j = line_len; j < 16; j++) {
sprintf(strPtr++, " ");
}
if(level) {
RADIOLIB_DEBUG_PRINT(level);
}
RADIOLIB_DEBUG_PRINT(str);
RADIOLIB_DEBUG_PRINTLN();
rem_len -= 16;
}
#else
// outside of debug, this does nothing
(void)level;
(void)data;
(void)len;
(void)offset;
(void)width;
(void)be;
#endif
}
#if RADIOLIB_DEBUG && defined(RADIOLIB_BUILD_ARDUINO)
// https://github.com/esp8266/Arduino/blob/65579d29081cb8501e4d7f786747bf12e7b37da2/cores/esp8266/Print.cpp#L50
size_t rlb_printf(const char* format, ...) {
va_list arg;
va_start(arg, format);
char temp[64];
char* buffer = temp;
size_t len = vsnprintf(temp, sizeof(temp), format, arg);
va_end(arg);
if (len > sizeof(temp) - 1) {
buffer = new char[len + 1];
if (!buffer) {
return 0;
}
va_start(arg, format);
vsnprintf(buffer, len + 1, format, arg);
va_end(arg);
}
len = RADIOLIB_DEBUG_PORT.write(reinterpret_cast<const uint8_t*>(buffer), len);
if (buffer != temp) {
delete[] buffer;
}
return len;
}
#endif

42
src/utils/Utils.h Normal file
View file

@ -0,0 +1,42 @@
#if !defined(_RADIOLIB_UTILS_H)
#define _RADIOLIB_UTILS_H
#include "TypeDef.h"
#include <stdint.h>
#include <stdlib.h>
// macros to access bits in byte array, from http://www.mathcs.emory.edu/~cheung/Courses/255/Syllabus/1-C-intro/bit-array.html
#define SET_BIT_IN_ARRAY_MSB(A, k) ( A[((k)/8)] |= (1 << ((k)%8)) )
#define CLEAR_BIT_IN_ARRAY_MSB(A, k) ( A[((k)/8)] &= ~(1 << ((k)%8)) )
#define TEST_BIT_IN_ARRAY_MSB(A, k) ( A[((k)/8)] & (1 << ((k)%8)) )
#define GET_BIT_IN_ARRAY_MSB(A, k) ( (A[((k)/8)] & (1 << ((k)%8))) ? 1 : 0 )
#define SET_BIT_IN_ARRAY_LSB(A, k) ( A[((k)/8)] |= (1 << (7 - ((k)%8))) )
#define CLEAR_BIT_IN_ARRAY_LSB(A, k) ( A[((k)/8)] &= ~(1 << (7 - ((k)%8))) )
#define TEST_BIT_IN_ARRAY_LSB(A, k) ( A[((k)/8)] & (1 << (7 - ((k)%8))) )
#define GET_BIT_IN_ARRAY_LSB(A, k) ( (A[((k)/8)] & (1 << (7 - ((k)%8)))) ? 1 : 0 )
/*!
\brief Function to reflect bits within a byte.
\param in The input to reflect.
\param bits Number of bits to reflect.
\return The reflected input.
*/
uint32_t rlb_reflect(uint32_t in, uint8_t bits);
/*!
\brief Function to dump data as hex into the debug port.
\param level RadioLib debug level, set to NULL to not print.
\param data Data to dump.
\param len Number of bytes to dump.
\param offset Address offset to add when printing the data.
\param width Word width (1 for uint8_t, 2 for uint16_t, 4 for uint32_t).
\param be Print multi-byte data as big endian. Defaults to false.
*/
void rlb_hexdump(const char* level, uint8_t* data, size_t len, uint32_t offset = 0, uint8_t width = 1, bool be = false);
#if RADIOLIB_DEBUG and defined(RADIOLIB_BUILD_ARDUINO)
size_t rlb_printf(const char* format, ...);
#endif
#endif