added version markers to settings, option to disable INI comments
This commit is contained in:
+120
-93
@@ -2,6 +2,7 @@
|
||||
// Created by MightyPork on 2017/11/26.
|
||||
//
|
||||
|
||||
#include <utils/avrlibc.h>
|
||||
#include "platform.h"
|
||||
#include "utils/hexdump.h"
|
||||
#include "settings.h"
|
||||
@@ -9,9 +10,13 @@
|
||||
#include "system_settings.h"
|
||||
#include "utils/str_utils.h"
|
||||
|
||||
// pre-declarations
|
||||
static void savebuf_flush(PayloadBuilder *pb, bool final);
|
||||
static bool savebuf_ovhandler(PayloadBuilder *pb, uint32_t more);
|
||||
|
||||
// This is the first entry in a valid config.
|
||||
// Change with each breaking change to force config reset.
|
||||
#define CONFIG_MARKER 0xA55C
|
||||
#define CONFIG_MARKER 0xA55D
|
||||
|
||||
void settings_load(void)
|
||||
{
|
||||
@@ -32,16 +37,22 @@ void settings_load(void)
|
||||
return;
|
||||
}
|
||||
|
||||
// System section
|
||||
if (!systemsettings_load(&pp)) {
|
||||
dbg("!! System settings failed to load");
|
||||
return;
|
||||
}
|
||||
uint8_t version = pp_u8(&pp); // top level settings format version
|
||||
|
||||
if (!ureg_load_units(&pp)) {
|
||||
dbg("!! Unit settings failed to load");
|
||||
return;
|
||||
}
|
||||
{ // Settings
|
||||
(void)version; // Conditional choices based on version
|
||||
|
||||
// System section
|
||||
if (!systemsettings_load(&pp)) {
|
||||
dbg("!! System settings failed to load");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ureg_load_units(&pp)) {
|
||||
dbg("!! Unit settings failed to load");
|
||||
return;
|
||||
}
|
||||
} // End settings
|
||||
|
||||
dbg("System settings loaded OK");
|
||||
}
|
||||
@@ -56,6 +67,89 @@ static uint32_t save_addr;
|
||||
#define fls_printf(fmt, ...) do {} while (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Save buffer overflow handler.
|
||||
* This should flush whatever is in the buffer and let CWPack continue
|
||||
*
|
||||
* @param pb - buffer
|
||||
* @param more - how many more bytes are needed (this is meant for realloc / buffer expanding)
|
||||
* @return - success code
|
||||
*/
|
||||
static bool savebuf_ovhandler(PayloadBuilder *pb, uint32_t more)
|
||||
{
|
||||
if (more > FLASH_SAVE_BUF_LEN) return false;
|
||||
savebuf_flush(pb, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Save settings to flash */
|
||||
void settings_save(void)
|
||||
{
|
||||
HAL_StatusTypeDef hst;
|
||||
PayloadBuilder pb = pb_start(save_buffer, FLASH_SAVE_BUF_LEN, savebuf_ovhandler);
|
||||
|
||||
save_addr = SETTINGS_FLASH_ADDR;
|
||||
|
||||
fls_printf("--- Starting flash write... ---\r\n");
|
||||
hst = HAL_FLASH_Unlock();
|
||||
assert_param(hst == HAL_OK);
|
||||
{
|
||||
fls_printf("ERASE flash pages for settings storage...\r\n");
|
||||
// We have to first erase the pages
|
||||
FLASH_EraseInitTypeDef erase;
|
||||
|
||||
#if PLAT_FLASHBANKS
|
||||
erase.Banks = FLASH_BANK_1; // TODO ?????
|
||||
#endif
|
||||
|
||||
#if defined(GEX_PLAT_F407_DISCOVERY)
|
||||
// specialty for F4 with too much flash
|
||||
erase.NbSectors = 1;
|
||||
erase.Sector = SETTINGS_FLASH_SECTOR;
|
||||
erase.TypeErase = FLASH_TYPEERASE_SECTORS;
|
||||
erase.VoltageRange = FLASH_VOLTAGE_RANGE_3;
|
||||
erase.Banks = FLASH_BANK_1; // unused for sector erase
|
||||
#else
|
||||
erase.NbPages = SETTINGS_BLOCK_SIZE/FLASH_PAGE_SIZE;
|
||||
erase.PageAddress = SETTINGS_FLASH_ADDR;
|
||||
erase.TypeErase = FLASH_TYPEERASE_PAGES;
|
||||
#endif
|
||||
uint32_t pgerror = 0;
|
||||
hst = HAL_FLASHEx_Erase(&erase, &pgerror);
|
||||
assert_param(pgerror == 0xFFFFFFFFU);
|
||||
assert_param(hst == HAL_OK);
|
||||
|
||||
// and now we can start writing...
|
||||
|
||||
fls_printf("Beginning settings collect\r\n");
|
||||
|
||||
// Marker that this is a valid save
|
||||
pb_u16(&pb, CONFIG_MARKER);
|
||||
pb_u8(&pb, 0); // Settings format version
|
||||
|
||||
{ // Settings
|
||||
fls_printf("Saving system settings\r\n");
|
||||
systemsettings_save(&pb);
|
||||
|
||||
fls_printf("Saving units\r\n");
|
||||
ureg_save_units(&pb);
|
||||
} // End settings
|
||||
|
||||
fls_printf("Final flush\r\n");
|
||||
savebuf_flush(&pb, true);
|
||||
}
|
||||
|
||||
fls_printf("Locking flash...\r\n");
|
||||
hst = HAL_FLASH_Lock();
|
||||
assert_param(hst == HAL_OK);
|
||||
fls_printf("--- Flash done ---\r\n");
|
||||
|
||||
#if DEBUG_FLASH_WRITE
|
||||
dbg("written @ %p", (void*)SETTINGS_FLASH_ADDR);
|
||||
hexDump("Flash", (void*)SETTINGS_FLASH_ADDR, 64);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the save buffer to flash, moving leftovers from uneven half-words
|
||||
* to the beginning and adjusting the CWPack curent pointer accordingly.
|
||||
@@ -115,96 +209,21 @@ static void savebuf_flush(PayloadBuilder *pb, bool final)
|
||||
fls_printf("\r\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Save buffer overflow handler.
|
||||
* This should flush whatever is in the buffer and let CWPack continue
|
||||
*
|
||||
* @param pb - buffer
|
||||
* @param more - how many more bytes are needed (this is meant for realloc / buffer expanding)
|
||||
* @return - success code
|
||||
*/
|
||||
static bool savebuf_ovhandler(PayloadBuilder *pb, uint32_t more)
|
||||
{
|
||||
if (more > FLASH_SAVE_BUF_LEN) return false;
|
||||
savebuf_flush(pb, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Save settings to flash
|
||||
void settings_save(void)
|
||||
{
|
||||
HAL_StatusTypeDef hst;
|
||||
PayloadBuilder pb = pb_start(save_buffer, FLASH_SAVE_BUF_LEN, savebuf_ovhandler);
|
||||
|
||||
save_addr = SETTINGS_FLASH_ADDR;
|
||||
|
||||
fls_printf("--- Starting flash write... ---\r\n");
|
||||
hst = HAL_FLASH_Unlock();
|
||||
assert_param(hst == HAL_OK);
|
||||
{
|
||||
fls_printf("ERASE flash pages for settings storage...\r\n");
|
||||
// We have to first erase the pages
|
||||
FLASH_EraseInitTypeDef erase;
|
||||
|
||||
#if PLAT_FLASHBANKS
|
||||
erase.Banks = FLASH_BANK_1; // TODO ?????
|
||||
#endif
|
||||
|
||||
#if defined(GEX_PLAT_F407_DISCOVERY)
|
||||
// specialty for F4 with too much flash
|
||||
erase.NbSectors = 1;
|
||||
erase.Sector = SETTINGS_FLASH_SECTOR;
|
||||
erase.TypeErase = FLASH_TYPEERASE_SECTORS;
|
||||
erase.VoltageRange = FLASH_VOLTAGE_RANGE_3;
|
||||
erase.Banks = FLASH_BANK_1; // unused for sector erase
|
||||
#else
|
||||
erase.NbPages = SETTINGS_BLOCK_SIZE/FLASH_PAGE_SIZE;
|
||||
erase.PageAddress = SETTINGS_FLASH_ADDR;
|
||||
erase.TypeErase = FLASH_TYPEERASE_PAGES;
|
||||
#endif
|
||||
uint32_t pgerror = 0;
|
||||
hst = HAL_FLASHEx_Erase(&erase, &pgerror);
|
||||
assert_param(pgerror == 0xFFFFFFFFU);
|
||||
assert_param(hst == HAL_OK);
|
||||
|
||||
// and now we can start writing...
|
||||
|
||||
fls_printf("Beginning settings collect\r\n");
|
||||
|
||||
// Marker that this is a valid save
|
||||
pb_u16(&pb, CONFIG_MARKER);
|
||||
fls_printf("Saving system settings\r\n");
|
||||
systemsettings_save(&pb);
|
||||
fls_printf("Saving units\r\n");
|
||||
ureg_save_units(&pb);
|
||||
|
||||
fls_printf("Final flush\r\n");
|
||||
savebuf_flush(&pb, true);
|
||||
}
|
||||
|
||||
fls_printf("Locking flash...\r\n");
|
||||
hst = HAL_FLASH_Lock();
|
||||
assert_param(hst == HAL_OK);
|
||||
fls_printf("--- Flash done ---\r\n");
|
||||
|
||||
#if DEBUG_FLASH_WRITE
|
||||
dbg("written @ %p", (void*)SETTINGS_FLASH_ADDR);
|
||||
hexDump("Flash", (void*)SETTINGS_FLASH_ADDR, 64);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Write system settings to INI (without section)
|
||||
*/
|
||||
void settings_build_ini(IniWriter *iw)
|
||||
{
|
||||
// File header
|
||||
iw_comment(iw, "CONFIG.INI");
|
||||
iw_hdr_comment(iw, "CONFIG.INI");
|
||||
iw_hdr_comment(iw, "GEX v%s on %s", GEX_VERSION, GEX_PLATFORM);
|
||||
iw_hdr_comment(iw, "built %s at %s", __DATE__, __TIME__);
|
||||
iw_cmt_newline(iw);
|
||||
|
||||
iw_comment(iw, "Overwrite this file to change settings.");
|
||||
iw_comment(iw, "Close the LOCK jumper to save them to Flash.");
|
||||
|
||||
systemsettings_build_ini(iw);
|
||||
iw_newline(iw);
|
||||
|
||||
ureg_build_ini(iw);
|
||||
}
|
||||
@@ -221,7 +240,8 @@ void settings_load_ini_begin(void)
|
||||
|
||||
void settings_load_ini_key(const char *restrict section, const char *restrict key, const char *restrict value)
|
||||
{
|
||||
// dbg("[%s] %s = %s", section, key, value);
|
||||
dbg("[%s] %s = %s", section, key, value);
|
||||
static char namebuf[INI_KEY_MAX];
|
||||
|
||||
if (streq(section, "SYSTEM")) {
|
||||
// system is always at the top
|
||||
@@ -235,8 +255,15 @@ void settings_load_ini_key(const char *restrict section, const char *restrict ke
|
||||
// not a standard section, may be some unit config
|
||||
// all unit sections contain the colon character [TYPE:NAME]
|
||||
const char *nameptr = strchr(section, ':');
|
||||
if (nameptr) {
|
||||
ureg_load_unit_ini_key(nameptr + 1, key, value);
|
||||
const char *csptr = strchr(section, '@');
|
||||
|
||||
dbg("cs = %s", csptr);
|
||||
if (nameptr && csptr) {
|
||||
strncpy(namebuf, nameptr+1, csptr - nameptr - 1);
|
||||
uint8_t cs = (uint8_t) avr_atoi(csptr + 1);
|
||||
dbg("cs is %d", cs);
|
||||
dbg("name is %s", namebuf);
|
||||
ureg_load_unit_ini_key(namebuf, key, value, cs);
|
||||
} else {
|
||||
dbg("! Bad config key: [%s] %s = %s", section, key, value);
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
//
|
||||
|
||||
#include "platform.h"
|
||||
#include "utils/str_utils.h"
|
||||
#include "system_settings.h"
|
||||
#include "utils/str_utils.h"
|
||||
#include "platform/lock_jumper.h"
|
||||
|
||||
struct system_settings SystemSettings;
|
||||
@@ -13,6 +13,7 @@ struct system_settings SystemSettings;
|
||||
void systemsettings_loadDefaults(void)
|
||||
{
|
||||
SystemSettings.visible_vcom = true;
|
||||
SystemSettings.ini_comments = true;
|
||||
}
|
||||
|
||||
/** Load defaults and init flags */
|
||||
@@ -29,14 +30,27 @@ void systemsettings_init(void)
|
||||
void systemsettings_save(PayloadBuilder *pb)
|
||||
{
|
||||
pb_char(pb, 'S');
|
||||
pb_bool(pb, SystemSettings.visible_vcom);
|
||||
pb_u8(pb, 0); // settings format version
|
||||
|
||||
{ // system settings
|
||||
pb_bool(pb, SystemSettings.visible_vcom);
|
||||
pb_bool(pb, SystemSettings.ini_comments);
|
||||
} // end system settings
|
||||
}
|
||||
|
||||
// from binary
|
||||
bool systemsettings_load(PayloadParser *pp)
|
||||
{
|
||||
if (pp_char(pp) != 'S') return false;
|
||||
SystemSettings.visible_vcom = pp_bool(pp);
|
||||
uint8_t version = pp_u8(pp);
|
||||
|
||||
{ // system settings
|
||||
SystemSettings.visible_vcom = pp_bool(pp);
|
||||
SystemSettings.ini_comments = pp_bool(pp);
|
||||
|
||||
// conditional fields based on version
|
||||
(void) version;
|
||||
} // end system settings
|
||||
|
||||
return pp->ok;
|
||||
}
|
||||
@@ -48,8 +62,12 @@ bool systemsettings_load(PayloadParser *pp)
|
||||
void systemsettings_build_ini(IniWriter *iw)
|
||||
{
|
||||
iw_section(iw, "SYSTEM");
|
||||
|
||||
iw_comment(iw, "Data link accessible as virtual comport (Y, N)");
|
||||
iw_entry(iw, "expose_vcom", str_yn(SystemSettings.visible_vcom));
|
||||
|
||||
iw_comment(iw, "Show comments in INI files (Y, N)");
|
||||
iw_entry(iw, "ini_comments", str_yn(SystemSettings.ini_comments));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,5 +81,10 @@ bool systemsettings_load_ini(const char *restrict key, const char *restrict valu
|
||||
if (suc) SystemSettings.visible_vcom = yn;
|
||||
}
|
||||
|
||||
if (streq(key, "ini_comments")) {
|
||||
bool yn = str_parse_yn(value, &suc);
|
||||
if (suc) SystemSettings.ini_comments = yn;
|
||||
}
|
||||
|
||||
return suc;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
struct system_settings {
|
||||
bool visible_vcom;
|
||||
bool ini_comments;
|
||||
|
||||
// Support flags put here for scoping, but not atcually part of the persistent settings
|
||||
volatile bool editable; //!< True if we booted with the LOCK jumper removed
|
||||
|
||||
+72
-66
@@ -2,14 +2,15 @@
|
||||
// Created by MightyPork on 2017/11/26.
|
||||
//
|
||||
|
||||
#include <utils/hexdump.h>
|
||||
#include "platform.h"
|
||||
#include "utils/hexdump.h"
|
||||
#include "utils/avrlibc.h"
|
||||
#include "comm/messages.h"
|
||||
#include "utils/ini_writer.h"
|
||||
#include "utils/str_utils.h"
|
||||
#include "utils/malloc_safe.h"
|
||||
#include "unit_registry.h"
|
||||
#include "system_settings.h"
|
||||
#include "resources.h"
|
||||
|
||||
// ** Unit repository **
|
||||
@@ -212,21 +213,27 @@ void ureg_save_units(PayloadBuilder *pb)
|
||||
uint32_t count = ureg_get_num_units();
|
||||
|
||||
pb_char(pb, 'U');
|
||||
pb_u16(pb, (uint16_t) count);
|
||||
pb_u8(pb, 0); // Format version
|
||||
|
||||
UlistEntry *le = ulist_head;
|
||||
while (le != NULL) {
|
||||
Unit *const pUnit = &le->unit;
|
||||
pb_char(pb, 'u');
|
||||
pb_string(pb, pUnit->driver->name);
|
||||
pb_string(pb, pUnit->name);
|
||||
pb_u8(pb, pUnit->callsign);
|
||||
{ // Units list
|
||||
pb_u16(pb, (uint16_t) count);
|
||||
|
||||
// Now all the rest, unit-specific
|
||||
pUnit->driver->cfgWriteBinary(pUnit, pb);
|
||||
assert_param(pb->ok);
|
||||
le = le->next;
|
||||
}
|
||||
UlistEntry *le = ulist_head;
|
||||
while (le != NULL) {
|
||||
Unit *const pUnit = &le->unit;
|
||||
pb_char(pb, 'u'); // marker
|
||||
{ // Single unit
|
||||
pb_string(pb, pUnit->driver->name);
|
||||
pb_string(pb, pUnit->name);
|
||||
pb_u8(pb, pUnit->callsign);
|
||||
|
||||
// Now all the rest, unit-specific
|
||||
pUnit->driver->cfgWriteBinary(pUnit, pb);
|
||||
assert_param(pb->ok);
|
||||
} // end single unit
|
||||
le = le->next;
|
||||
}
|
||||
} // end units list
|
||||
}
|
||||
|
||||
bool ureg_load_units(PayloadParser *pp)
|
||||
@@ -236,44 +243,53 @@ bool ureg_load_units(PayloadParser *pp)
|
||||
|
||||
assert_param(pp->ok);
|
||||
|
||||
// Check units list marker byte
|
||||
if (pp_char(pp) != 'U') return false;
|
||||
uint16_t unit_count = pp_u16(pp);
|
||||
dbg("Units to load: %d", (int)unit_count);
|
||||
uint8_t version = pp_u8(pp); // units list format version
|
||||
|
||||
for (uint32_t j = 0; j < unit_count; j++) {
|
||||
// We're now unpacking a single unit
|
||||
(void)version; // version can affect the format
|
||||
|
||||
// Marker that this is a unit - it could get out of alignment if structure changed
|
||||
if (pp_char(pp) != 'u') return false;
|
||||
{ // units list
|
||||
uint16_t unit_count = pp_u16(pp);
|
||||
dbg("Units to load: %d", (int) unit_count);
|
||||
|
||||
// TYPE
|
||||
pp_string(pp, typebuf, 16);
|
||||
Unit *const pUnit = ureg_instantiate(typebuf);
|
||||
if (!pUnit) {
|
||||
dbg("!! Unknown unit type %s, aborting load.", typebuf);
|
||||
break;
|
||||
for (uint32_t j = 0; j < unit_count; j++) {
|
||||
// We're now unpacking a single unit
|
||||
|
||||
// Marker that this is a unit - it could get out of alignment if structure changed
|
||||
if (pp_char(pp) != 'u') return false;
|
||||
|
||||
{ // Single unit
|
||||
// TYPE
|
||||
pp_string(pp, typebuf, 16);
|
||||
Unit *const pUnit = ureg_instantiate(typebuf);
|
||||
if (!pUnit) {
|
||||
dbg("!! Unknown unit type %s, aborting load.", typebuf);
|
||||
break;
|
||||
}
|
||||
|
||||
// NAME
|
||||
pp_string(pp, typebuf, 16);
|
||||
pUnit->name = strdup(typebuf);
|
||||
assert_param(pUnit->name);
|
||||
|
||||
// callsign
|
||||
pUnit->callsign = pp_u8(pp);
|
||||
assert_param(pUnit->callsign != 0);
|
||||
|
||||
// Load the rest of the unit
|
||||
pUnit->driver->cfgLoadBinary(pUnit, pp);
|
||||
assert_param(pp->ok);
|
||||
|
||||
dbg("Adding unit \"%s\" of type %s", pUnit->name, pUnit->driver->name);
|
||||
|
||||
suc = pUnit->driver->init(pUnit); // finalize the load and init the unit
|
||||
if (pUnit->status == E_LOADING) {
|
||||
pUnit->status = suc ? E_SUCCESS : E_BAD_CONFIG;
|
||||
}
|
||||
} // end unit
|
||||
}
|
||||
|
||||
// NAME
|
||||
pp_string(pp, typebuf, 16);
|
||||
pUnit->name = strdup(typebuf);
|
||||
assert_param(pUnit->name);
|
||||
|
||||
// callsign
|
||||
pUnit->callsign = pp_u8(pp);
|
||||
assert_param(pUnit->callsign != 0);
|
||||
|
||||
// Load the rest of the unit
|
||||
pUnit->driver->cfgLoadBinary(pUnit, pp);
|
||||
assert_param(pp->ok);
|
||||
|
||||
dbg("Adding unit \"%s\" of type %s", pUnit->name, pUnit->driver->name);
|
||||
|
||||
suc = pUnit->driver->init(pUnit); // finalize the load and init the unit
|
||||
if (pUnit->status == E_LOADING) {
|
||||
pUnit->status = suc ? E_SUCCESS : E_BAD_CONFIG;
|
||||
}
|
||||
}
|
||||
} // end units list
|
||||
|
||||
return pp->ok;
|
||||
}
|
||||
@@ -298,7 +314,7 @@ void ureg_remove_all_units(void)
|
||||
ulist_head = ulist_tail = NULL;
|
||||
}
|
||||
|
||||
|
||||
/** Create unit instances from the [UNITS] overview section */
|
||||
bool ureg_instantiate_by_ini(const char *restrict driver_name, const char *restrict names)
|
||||
{
|
||||
UregEntry *re = ureg_head;
|
||||
@@ -342,22 +358,18 @@ bool ureg_instantiate_by_ini(const char *restrict driver_name, const char *restr
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Load unit key-value */
|
||||
bool ureg_load_unit_ini_key(const char *restrict name,
|
||||
const char *restrict key,
|
||||
const char *restrict value)
|
||||
const char *restrict value,
|
||||
uint8_t callsign)
|
||||
{
|
||||
UlistEntry *li = ulist_head;
|
||||
while (li != NULL) {
|
||||
if (streq(li->unit.name, name)) {
|
||||
Unit *const pUnit = &li->unit;
|
||||
|
||||
if (streq(key, "callsign")) {
|
||||
// handled separately from unit data
|
||||
pUnit->callsign = (uint8_t) avr_atoi(value);
|
||||
return true;
|
||||
} else {
|
||||
return pUnit->driver->cfgLoadIni(pUnit, key, value);
|
||||
}
|
||||
pUnit->callsign = callsign;
|
||||
return pUnit->driver->cfgLoadIni(pUnit, key, value);
|
||||
}
|
||||
|
||||
li = li->next;
|
||||
@@ -365,6 +377,7 @@ bool ureg_load_unit_ini_key(const char *restrict name,
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Finalize untis init */
|
||||
bool ureg_finalize_all_init(void)
|
||||
{
|
||||
dbg("Finalizing units init...");
|
||||
@@ -404,17 +417,11 @@ static void export_unit_do(UlistEntry *li, IniWriter *iw)
|
||||
{
|
||||
Unit *const pUnit = &li->unit;
|
||||
|
||||
iw_section(iw, "%s:%s", pUnit->driver->name, pUnit->name);
|
||||
iw_section(iw, "%s:%s@%d", pUnit->driver->name, pUnit->name, (int)pUnit->callsign);
|
||||
if (pUnit->status != E_SUCCESS) {
|
||||
iw_comment(iw, "!!! %s", error_get_string(pUnit->status));
|
||||
}
|
||||
iw_newline(iw);
|
||||
|
||||
iw_comment(iw, "Unit address 1-255");
|
||||
iw_entry(iw, "callsign", "%d", pUnit->callsign);
|
||||
|
||||
pUnit->driver->cfgWriteIni(pUnit, iw);
|
||||
iw_newline(iw);
|
||||
}
|
||||
|
||||
// unit to INI
|
||||
@@ -455,7 +462,7 @@ void ureg_build_ini(IniWriter *iw)
|
||||
|
||||
const UnitDriver *const pDriver = re->driver;
|
||||
|
||||
iw_newline(iw);
|
||||
iw_cmt_newline(iw);
|
||||
iw_comment(iw, pDriver->description);
|
||||
iw_string(iw, pDriver->name);
|
||||
iw_string(iw, "=");
|
||||
@@ -474,7 +481,6 @@ void ureg_build_ini(IniWriter *iw)
|
||||
re = re->next;
|
||||
iw_newline(iw);
|
||||
}
|
||||
iw_newline(iw); // space before the unit sections
|
||||
|
||||
// Now we dump all the units
|
||||
li = ulist_head;
|
||||
|
||||
@@ -96,11 +96,13 @@ bool ureg_instantiate_by_ini(const char *restrict driver_name, const char *restr
|
||||
* @param name - unit name (for look-up)
|
||||
* @param key - property key
|
||||
* @param value - value to set as string
|
||||
* @param callsign - callsign (is part of the section string)
|
||||
* @return success
|
||||
*/
|
||||
bool ureg_load_unit_ini_key(const char *restrict name,
|
||||
const char *restrict key,
|
||||
const char *restrict value);
|
||||
const char *restrict value,
|
||||
uint8_t callsign);
|
||||
|
||||
/**
|
||||
* Run init() for all unit instances.
|
||||
|
||||
Reference in New Issue
Block a user