I have a program that stores the settings parameters for a LoRa device in the Flash of a ESP32S3 using the preferences.h library. In this way the settings of the LoRa device can be changed without re-programming the ESP32S3.
The settings are copied from Flash into a structure. When the structure was stored in Flash a CRC of the structure contents was also stored. Thus when the settings are downloaded from flash you can check that the settings are valid and not corrupted.
So I have a function that calculates the CRC of the structure in memory, the structure is called settings and an instance of it called var is created.
To call the CRC calculation I use;
CRC = CRC_structure(var, sizeof(var)); //get CRC of settings.var
And the function is;
uint16_t CRC_structure(settings &struc, uint8_t structsize)
{
It does work, the correct CRC is returned.
However note that the function needs to use the name of the structure as in the (settings &struc) bit.
Is there a way to avoid using the name of the structure (settings) in the function definition ? In that way the function could be used for any structure.
The reduced program is below;
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 30/11/24
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
#include <SPI.h>
#include <SX126XLT.h>
SX126XLT LoRa;
#include <Preferences.h>
Preferences Configurable;
#define RO_MODE true
#define RW_MODE false
struct settings
{
uint32_t LORAFREQ; //Frequency of transmissions in hertz
uint32_t LORAFREQOFF; //Offset frequency for calibration purposes
uint8_t LORASF; //LoRa spreading factor
uint8_t LORABW; //LoRa bandwidth
uint8_t LORACR; //LoRa coding rate
uint8_t LORAOPT; //Low data rate optimisation setting, normally set to auto
int8_t LORATXPOW; //LoRa transmit power in dBm
uint32_t PKTDELAY; //delay in mS betwwen packets
uint32_t MENUTIMEOUT; //timeout in mS of menu
} __attribute__((packed, aligned(1))); //remove structure padding to ensure compatibility between 8bit and 32bit micros;
struct settings var;
//structure gives a Store CRC of 0xB483
uint32_t LORAFREQ = 434000000; //Frequency of transmissions in hertz
uint32_t LORAFREQOFF = 0; //Offset frequency in hertz for calibration purposes
uint8_t LORASF = LORA_SF7; //LoRa spreading factor
uint8_t LORABW = LORA_BW_125; //LoRa bandwidth
uint8_t LORACR = LORA_CR_4_5; //LoRa coding rate
uint8_t LORAOPT = LDRO_AUTO; //Low data rate optimisation setting, normally set to auto
int8_t LORATXPOW = 10; //LoRa transmit power in dBm
uint32_t PKTDELAY = 1000; //delay between transmission of packets
uint32_t MENUTIMEOUT = 30000; //timeout in mS of menus
void loop()
{
uint16_t CRC;
Configurable.begin("Store", RW_MODE);
copy_settings_var();
print_var();
Configurable.putBytes( "Store", &var, sizeof(var));
CRC = CRC_structure(var, sizeof(var)); //get CRC of settings.var
Serial.print("var structure CRC 0x");
Serial.println(CRC, HEX);
while (1);
}
uint16_t CRC_structure(settings &struc, uint8_t structsize)
{
uint8_t index, byteread;
uint16_t i, structureCRC;
uint8_t j;
structureCRC = 0xFFFF; //start value for CRC16
Serial.println("Structure contents");
uint8_t* ptr = (uint8_t*)&struc;
for (index = 0; index < structsize; index++)
{
byteread = (*(ptr + index));
Serial.print(byteread, HEX);
Serial.print(" ");
structureCRC ^= ((uint16_t) byteread << 8);
for (j = 0; j < 8; j++)
{
if (structureCRC & 0x8000)
structureCRC = (structureCRC << 1) ^ 0x1021;
else
structureCRC <<= 1;
}
}
Serial.println();
return structureCRC;
}
void copy_settings_var()
{
//copy settings from Settings.h into variables used by program
var.LORAFREQ = LORAFREQ; //Frequency of transmissions in hertz
var.LORAFREQOFF = LORAFREQOFF; //Offset frequency for calibration purposes
var.LORASF = LORASF; //LoRa spreading factor
var.LORABW = LORABW; //LoRa bandwidth
var.LORACR = LORACR; //LoRa coding rate
var.LORAOPT = LORAOPT; //Low data rate optimisation setting, normally set to auto
var.LORATXPOW = LORATXPOW; //LoRa transmit power in dBm
var.PKTDELAY = PKTDELAY; //delay in mS between packets
var.MENUTIMEOUT = MENUTIMEOUT; //timeout in mS of menu
}
void print_var()
{
Serial.println();
Serial.println(F("Var Settings"));
Serial.println(F("------------"));
Serial.print(F("LORAFREQ,"));
Serial.print(var.LORAFREQ);
Serial.println(F("hz"));
Serial.print(F("LORAFREQOFF,"));
Serial.print(var.LORAFREQOFF);
Serial.println(F("hz"));
Serial.print(F("LORASF,"));
Serial.println(var.LORASF);
Serial.print(F("LORABW,"));
Serial.print(LoRa.returnBandwidth(var.LORABW));
Serial.println(F("hz"));
Serial.print(F("LORACR,4:"));
Serial.println(var.LORACR + 4);
Serial.print(F("LORATXPOW,"));
Serial.print(var.LORATXPOW);
Serial.println(F("dBm"));
Serial.print(F("PKTDELAY,"));
Serial.print(var.PKTDELAY);
Serial.println(F("mS"));
Serial.print(F("MENUTIMEOUT,"));
Serial.print(var.MENUTIMEOUT);
Serial.println(F("mS"));
Serial.println();
}
void setup()
{
Serial.begin(115200);
Serial.println(F("ESP32_Preferances_test starting"));
}