Removed support for profile handling in parameter groups.
This commit is contained in:
parent
2e4184dc6d
commit
774cae215c
|
@ -38,10 +38,7 @@ static uint16_t eepromConfigSize;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CR_CLASSICATION_SYSTEM = 0,
|
CR_CLASSICATION_SYSTEM = 0,
|
||||||
CR_CLASSICATION_PROFILE1 = 1,
|
CR_CLASSICATION_PROFILE_LAST = CR_CLASSICATION_SYSTEM,
|
||||||
CR_CLASSICATION_PROFILE2 = 2,
|
|
||||||
CR_CLASSICATION_PROFILE3 = 3,
|
|
||||||
CR_CLASSICATION_PROFILE_LAST = CR_CLASSICATION_PROFILE3,
|
|
||||||
} configRecordFlags_e;
|
} configRecordFlags_e;
|
||||||
|
|
||||||
#define CR_CLASSIFICATION_MASK (0x3)
|
#define CR_CLASSIFICATION_MASK (0x3)
|
||||||
|
@ -178,23 +175,12 @@ static const configRecord_t *findEEPROM(const pgRegistry_t *reg, configRecordFla
|
||||||
bool loadEEPROM(void)
|
bool loadEEPROM(void)
|
||||||
{
|
{
|
||||||
PG_FOREACH(reg) {
|
PG_FOREACH(reg) {
|
||||||
configRecordFlags_e cls_start, cls_end;
|
const configRecord_t *rec = findEEPROM(reg, CR_CLASSICATION_SYSTEM);
|
||||||
if (pgIsSystem(reg)) {
|
if (rec) {
|
||||||
cls_start = CR_CLASSICATION_SYSTEM;
|
// config from EEPROM is available, use it to initialize PG. pgLoad will handle version mismatch
|
||||||
cls_end = CR_CLASSICATION_SYSTEM;
|
pgLoad(reg, rec->pg, rec->size - offsetof(configRecord_t, pg), rec->version);
|
||||||
} else {
|
} else {
|
||||||
cls_start = CR_CLASSICATION_PROFILE1;
|
pgReset(reg);
|
||||||
cls_end = CR_CLASSICATION_PROFILE_LAST;
|
|
||||||
}
|
|
||||||
for (configRecordFlags_e cls = cls_start; cls <= cls_end; cls++) {
|
|
||||||
int profileIndex = cls - cls_start;
|
|
||||||
const configRecord_t *rec = findEEPROM(reg, cls);
|
|
||||||
if (rec) {
|
|
||||||
// config from EEPROM is available, use it to initialize PG. pgLoad will handle version mismatch
|
|
||||||
pgLoad(reg, profileIndex, rec->pg, rec->size - offsetof(configRecord_t, pg), rec->version);
|
|
||||||
} else {
|
|
||||||
pgReset(reg, profileIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -225,25 +211,11 @@ static bool writeSettingsToEEPROM(void)
|
||||||
.flags = 0
|
.flags = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
if (pgIsSystem(reg)) {
|
record.flags |= CR_CLASSICATION_SYSTEM;
|
||||||
// write the only instance
|
config_streamer_write(&streamer, (uint8_t *)&record, sizeof(record));
|
||||||
record.flags |= CR_CLASSICATION_SYSTEM;
|
crc = crc16_ccitt_update(crc, (uint8_t *)&record, sizeof(record));
|
||||||
config_streamer_write(&streamer, (uint8_t *)&record, sizeof(record));
|
config_streamer_write(&streamer, reg->address, regSize);
|
||||||
crc = crc16_ccitt_update(crc, (uint8_t *)&record, sizeof(record));
|
crc = crc16_ccitt_update(crc, reg->address, regSize);
|
||||||
config_streamer_write(&streamer, reg->address, regSize);
|
|
||||||
crc = crc16_ccitt_update(crc, reg->address, regSize);
|
|
||||||
} else {
|
|
||||||
// write one instance for each profile
|
|
||||||
for (uint8_t profileIndex = 0; profileIndex < PG_PROFILE_COUNT; profileIndex++) {
|
|
||||||
record.flags = 0;
|
|
||||||
record.flags |= ((profileIndex + 1) & CR_CLASSIFICATION_MASK);
|
|
||||||
config_streamer_write(&streamer, (uint8_t *)&record, sizeof(record));
|
|
||||||
crc = crc16_ccitt_update(crc, (uint8_t *)&record, sizeof(record));
|
|
||||||
const uint8_t *address = reg->address + (regSize * profileIndex);
|
|
||||||
config_streamer_write(&streamer, address, regSize);
|
|
||||||
crc = crc16_ccitt_update(crc, address, regSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configFooter_t footer = {
|
configFooter_t footer = {
|
||||||
|
|
|
@ -34,15 +34,9 @@ const pgRegistry_t* pgFind(pgn_t pgn)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t *pgOffset(const pgRegistry_t* reg, uint8_t profileIndex)
|
static uint8_t *pgOffset(const pgRegistry_t* reg)
|
||||||
{
|
{
|
||||||
const uint16_t regSize = pgSize(reg);
|
return reg->address;
|
||||||
|
|
||||||
uint8_t *base = reg->address;
|
|
||||||
if (!pgIsSystem(reg)) {
|
|
||||||
base += (regSize * profileIndex);
|
|
||||||
}
|
|
||||||
return base;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pgResetInstance(const pgRegistry_t *reg, uint8_t *base)
|
static void pgResetInstance(const pgRegistry_t *reg, uint8_t *base)
|
||||||
|
@ -59,18 +53,9 @@ static void pgResetInstance(const pgRegistry_t *reg, uint8_t *base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pgReset(const pgRegistry_t* reg, int profileIndex)
|
void pgReset(const pgRegistry_t* reg)
|
||||||
{
|
{
|
||||||
pgResetInstance(reg, pgOffset(reg, profileIndex));
|
pgResetInstance(reg, pgOffset(reg));
|
||||||
}
|
|
||||||
|
|
||||||
void pgResetCurrent(const pgRegistry_t *reg)
|
|
||||||
{
|
|
||||||
if (pgIsSystem(reg)) {
|
|
||||||
pgResetInstance(reg, reg->address);
|
|
||||||
} else {
|
|
||||||
pgResetInstance(reg, *reg->ptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pgResetCopy(void *copy, pgn_t pgn)
|
bool pgResetCopy(void *copy, pgn_t pgn)
|
||||||
|
@ -83,44 +68,26 @@ bool pgResetCopy(void *copy, pgn_t pgn)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pgLoad(const pgRegistry_t* reg, int profileIndex, const void *from, int size, int version)
|
void pgLoad(const pgRegistry_t* reg, const void *from, int size, int version)
|
||||||
{
|
{
|
||||||
pgResetInstance(reg, pgOffset(reg, profileIndex));
|
pgResetInstance(reg, pgOffset(reg));
|
||||||
// restore only matching version, keep defaults otherwise
|
// restore only matching version, keep defaults otherwise
|
||||||
if (version == pgVersion(reg)) {
|
if (version == pgVersion(reg)) {
|
||||||
const int take = MIN(size, pgSize(reg));
|
const int take = MIN(size, pgSize(reg));
|
||||||
memcpy(pgOffset(reg, profileIndex), from, take);
|
memcpy(pgOffset(reg), from, take);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int pgStore(const pgRegistry_t* reg, void *to, int size, uint8_t profileIndex)
|
int pgStore(const pgRegistry_t* reg, void *to, int size)
|
||||||
{
|
{
|
||||||
const int take = MIN(size, pgSize(reg));
|
const int take = MIN(size, pgSize(reg));
|
||||||
memcpy(to, pgOffset(reg, profileIndex), take);
|
memcpy(to, pgOffset(reg), take);
|
||||||
return take;
|
return take;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pgResetAll()
|
||||||
void pgResetAll(int profileCount)
|
|
||||||
{
|
{
|
||||||
PG_FOREACH(reg) {
|
PG_FOREACH(reg) {
|
||||||
if (pgIsSystem(reg)) {
|
pgReset(reg);
|
||||||
pgReset(reg, 0);
|
|
||||||
} else {
|
|
||||||
// reset one instance for each profile
|
|
||||||
for (int profileIndex = 0; profileIndex < profileCount; profileIndex++) {
|
|
||||||
pgReset(reg, profileIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void pgActivateProfile(int profileIndex)
|
|
||||||
{
|
|
||||||
PG_FOREACH(reg) {
|
|
||||||
if (!pgIsSystem(reg)) {
|
|
||||||
uint8_t *ptr = pgOffset(reg, profileIndex);
|
|
||||||
*(reg->ptr) = ptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,14 +34,9 @@ typedef enum {
|
||||||
PGR_PGN_MASK = 0x0fff,
|
PGR_PGN_MASK = 0x0fff,
|
||||||
PGR_PGN_VERSION_MASK = 0xf000,
|
PGR_PGN_VERSION_MASK = 0xf000,
|
||||||
PGR_SIZE_MASK = 0x0fff,
|
PGR_SIZE_MASK = 0x0fff,
|
||||||
PGR_SIZE_SYSTEM_FLAG = 0x0000, // documentary
|
PGR_SIZE_SYSTEM_FLAG = 0x0000 // documentary
|
||||||
PGR_SIZE_PROFILE_FLAG = 0x8000 // start using flags from the top bit down
|
|
||||||
} pgRegistryInternal_e;
|
} pgRegistryInternal_e;
|
||||||
|
|
||||||
enum {
|
|
||||||
PG_PROFILE_COUNT = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
// function that resets a single parameter group instance
|
// function that resets a single parameter group instance
|
||||||
typedef void (pgResetFunc)(void * /* base */, int /* size */);
|
typedef void (pgResetFunc)(void * /* base */, int /* size */);
|
||||||
|
|
||||||
|
@ -60,8 +55,6 @@ typedef struct pgRegistry_s {
|
||||||
static inline uint16_t pgN(const pgRegistry_t* reg) {return reg->pgn & PGR_PGN_MASK;}
|
static inline uint16_t pgN(const pgRegistry_t* reg) {return reg->pgn & PGR_PGN_MASK;}
|
||||||
static inline uint8_t pgVersion(const pgRegistry_t* reg) {return (uint8_t)(reg->pgn >> 12);}
|
static inline uint8_t pgVersion(const pgRegistry_t* reg) {return (uint8_t)(reg->pgn >> 12);}
|
||||||
static inline uint16_t pgSize(const pgRegistry_t* reg) {return reg->size & PGR_SIZE_MASK;}
|
static inline uint16_t pgSize(const pgRegistry_t* reg) {return reg->size & PGR_SIZE_MASK;}
|
||||||
static inline uint16_t pgIsSystem(const pgRegistry_t* reg) {return (reg->size & PGR_SIZE_PROFILE_FLAG) == 0;}
|
|
||||||
static inline uint16_t pgIsProfile(const pgRegistry_t* reg) {return (reg->size & PGR_SIZE_PROFILE_FLAG) == PGR_SIZE_PROFILE_FLAG;}
|
|
||||||
|
|
||||||
#define PG_PACKED __attribute__((packed))
|
#define PG_PACKED __attribute__((packed))
|
||||||
|
|
||||||
|
@ -89,19 +82,11 @@ extern const uint8_t __pg_resetdata_end[];
|
||||||
#define PG_FOREACH(_name) \
|
#define PG_FOREACH(_name) \
|
||||||
for (const pgRegistry_t *(_name) = __pg_registry_start; (_name) < __pg_registry_end; _name++)
|
for (const pgRegistry_t *(_name) = __pg_registry_start; (_name) < __pg_registry_end; _name++)
|
||||||
|
|
||||||
#define PG_FOREACH_PROFILE(_name) \
|
|
||||||
PG_FOREACH(_name) \
|
|
||||||
if(pgIsSystem(_name)) \
|
|
||||||
continue; \
|
|
||||||
else \
|
|
||||||
/**/
|
|
||||||
|
|
||||||
// Reset configuration to default (by name)
|
// Reset configuration to default (by name)
|
||||||
// Only current profile is reset for profile based configs
|
#define PG_RESET(_name) \
|
||||||
#define PG_RESET_CURRENT(_name) \
|
|
||||||
do { \
|
do { \
|
||||||
extern const pgRegistry_t _name ##_Registry; \
|
extern const pgRegistry_t _name ##_Registry; \
|
||||||
pgResetCurrent(&_name ## _Registry); \
|
pgReset(&_name ## _Registry); \
|
||||||
} while(0) \
|
} while(0) \
|
||||||
/**/
|
/**/
|
||||||
|
|
||||||
|
@ -124,15 +109,6 @@ extern const uint8_t __pg_resetdata_end[];
|
||||||
struct _dummy \
|
struct _dummy \
|
||||||
/**/
|
/**/
|
||||||
|
|
||||||
// Declare profile config
|
|
||||||
#define PG_DECLARE_PROFILE(_type, _name) \
|
|
||||||
extern _type *_name ## _ProfileCurrent; \
|
|
||||||
static inline const _type* _name(void) { return _name ## _ProfileCurrent; } \
|
|
||||||
static inline _type* _name ## Mutable(void) { return _name ## _ProfileCurrent; } \
|
|
||||||
struct _dummy \
|
|
||||||
/**/
|
|
||||||
|
|
||||||
|
|
||||||
// Register system config
|
// Register system config
|
||||||
#define PG_REGISTER_I(_type, _name, _pgn, _version, _reset) \
|
#define PG_REGISTER_I(_type, _name, _pgn, _version, _reset) \
|
||||||
_type _name ## _System; \
|
_type _name ## _System; \
|
||||||
|
@ -195,43 +171,6 @@ extern const uint8_t __pg_resetdata_end[];
|
||||||
/**/
|
/**/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef UNIT_TEST
|
|
||||||
# define _PG_PROFILE_CURRENT_DECL(_type, _name) \
|
|
||||||
_type *_name ## _ProfileCurrent = &_name ## _Storage[0];
|
|
||||||
#else
|
|
||||||
# define _PG_PROFILE_CURRENT_DECL(_type, _name) \
|
|
||||||
_type *_name ## _ProfileCurrent;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// register profile config
|
|
||||||
#define PG_REGISTER_PROFILE_I(_type, _name, _pgn, _version, _reset) \
|
|
||||||
STATIC_UNIT_TESTED _type _name ## _Storage[PG_PROFILE_COUNT]; \
|
|
||||||
_PG_PROFILE_CURRENT_DECL(_type, _name) \
|
|
||||||
extern const pgRegistry_t _name ## _Registry; \
|
|
||||||
const pgRegistry_t _name ## _Registry PG_REGISTER_ATTRIBUTES = { \
|
|
||||||
.pgn = _pgn | (_version << 12), \
|
|
||||||
.size = sizeof(_type) | PGR_SIZE_PROFILE_FLAG, \
|
|
||||||
.address = (uint8_t*)&_name ## _Storage, \
|
|
||||||
.ptr = (uint8_t **)&_name ## _ProfileCurrent, \
|
|
||||||
_reset, \
|
|
||||||
} \
|
|
||||||
/**/
|
|
||||||
|
|
||||||
#define PG_REGISTER_PROFILE(_type, _name, _pgn, _version) \
|
|
||||||
PG_REGISTER_PROFILE_I(_type, _name, _pgn, _version, .reset = {.ptr = 0}) \
|
|
||||||
/**/
|
|
||||||
|
|
||||||
#define PG_REGISTER_PROFILE_WITH_RESET_FN(_type, _name, _pgn, _version) \
|
|
||||||
extern void pgResetFn_ ## _name(_type *); \
|
|
||||||
PG_REGISTER_PROFILE_I(_type, _name, _pgn, _version, .reset = {.fn = (pgResetFunc*)&pgResetFn_ ## _name}) \
|
|
||||||
/**/
|
|
||||||
|
|
||||||
#define PG_REGISTER_PROFILE_WITH_RESET_TEMPLATE(_type, _name, _pgn, _version) \
|
|
||||||
extern const _type pgResetTemplate_ ## _name; \
|
|
||||||
PG_REGISTER_PROFILE_I(_type, _name, _pgn, _version, .reset = {.ptr = (void*)&pgResetTemplate_ ## _name}) \
|
|
||||||
/**/
|
|
||||||
|
|
||||||
|
|
||||||
// Emit reset defaults for config.
|
// Emit reset defaults for config.
|
||||||
// Config must be registered with PG_REGISTER_<xxx>_WITH_RESET_TEMPLATE macro
|
// Config must be registered with PG_REGISTER_<xxx>_WITH_RESET_TEMPLATE macro
|
||||||
#define PG_RESET_TEMPLATE(_type, _name, ...) \
|
#define PG_RESET_TEMPLATE(_type, _name, ...) \
|
||||||
|
@ -245,10 +184,8 @@ extern const uint8_t __pg_resetdata_end[];
|
||||||
|
|
||||||
const pgRegistry_t* pgFind(pgn_t pgn);
|
const pgRegistry_t* pgFind(pgn_t pgn);
|
||||||
|
|
||||||
void pgLoad(const pgRegistry_t* reg, int profileIndex, const void *from, int size, int version);
|
void pgLoad(const pgRegistry_t* reg, const void *from, int size, int version);
|
||||||
int pgStore(const pgRegistry_t* reg, void *to, int size, uint8_t profileIndex);
|
int pgStore(const pgRegistry_t* reg, void *to, int size);
|
||||||
void pgResetAll(int profileCount);
|
void pgResetAll();
|
||||||
void pgResetCurrent(const pgRegistry_t *reg);
|
|
||||||
bool pgResetCopy(void *copy, pgn_t pgn);
|
bool pgResetCopy(void *copy, pgn_t pgn);
|
||||||
void pgReset(const pgRegistry_t* reg, int profileIndex);
|
void pgReset(const pgRegistry_t* reg);
|
||||||
void pgActivateProfile(int profileIndex);
|
|
||||||
|
|
|
@ -2974,11 +2974,7 @@ static void backupConfigs(void)
|
||||||
{
|
{
|
||||||
// make copies of configs to do differencing
|
// make copies of configs to do differencing
|
||||||
PG_FOREACH(pg) {
|
PG_FOREACH(pg) {
|
||||||
if (pgIsProfile(pg)) {
|
memcpy(pg->copy, pg->address, pg->size);
|
||||||
//memcpy(pg->copy, pg->address, pg->size * MAX_PROFILE_COUNT);
|
|
||||||
} else {
|
|
||||||
memcpy(pg->copy, pg->address, pg->size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configIsInCopy = true;
|
configIsInCopy = true;
|
||||||
|
@ -2987,11 +2983,7 @@ static void backupConfigs(void)
|
||||||
static void restoreConfigs(void)
|
static void restoreConfigs(void)
|
||||||
{
|
{
|
||||||
PG_FOREACH(pg) {
|
PG_FOREACH(pg) {
|
||||||
if (pgIsProfile(pg)) {
|
memcpy(pg->address, pg->copy, pg->size);
|
||||||
//memcpy(pg->address, pg->copy, pg->size * MAX_PROFILE_COUNT);
|
|
||||||
} else {
|
|
||||||
memcpy(pg->address, pg->copy, pg->size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configIsInCopy = false;
|
configIsInCopy = false;
|
||||||
|
|
|
@ -312,14 +312,12 @@ uint16_t getCurrentMinthrottle(void)
|
||||||
|
|
||||||
void resetConfigs(void)
|
void resetConfigs(void)
|
||||||
{
|
{
|
||||||
pgResetAll(MAX_PROFILE_COUNT);
|
pgResetAll();
|
||||||
|
|
||||||
#if defined(TARGET_CONFIG)
|
#if defined(TARGET_CONFIG)
|
||||||
targetConfiguration();
|
targetConfiguration();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pgActivateProfile(0);
|
|
||||||
|
|
||||||
#ifndef USE_OSD_SLAVE
|
#ifndef USE_OSD_SLAVE
|
||||||
setPidProfile(0);
|
setPidProfile(0);
|
||||||
setControlRateProfile(0);
|
setControlRateProfile(0);
|
||||||
|
|
|
@ -48,7 +48,7 @@ PG_RESET_TEMPLATE(motorConfig_t, motorConfig,
|
||||||
TEST(ParameterGroupsfTest, Test_pgResetAll)
|
TEST(ParameterGroupsfTest, Test_pgResetAll)
|
||||||
{
|
{
|
||||||
memset(motorConfigMutable(), 0, sizeof(motorConfig_t));
|
memset(motorConfigMutable(), 0, sizeof(motorConfig_t));
|
||||||
pgResetAll(0);
|
pgResetAll();
|
||||||
EXPECT_EQ(1150, motorConfig()->minthrottle);
|
EXPECT_EQ(1150, motorConfig()->minthrottle);
|
||||||
EXPECT_EQ(1850, motorConfig()->maxthrottle);
|
EXPECT_EQ(1850, motorConfig()->maxthrottle);
|
||||||
EXPECT_EQ(1000, motorConfig()->mincommand);
|
EXPECT_EQ(1000, motorConfig()->mincommand);
|
||||||
|
@ -59,7 +59,7 @@ TEST(ParameterGroupsfTest, Test_pgFind)
|
||||||
{
|
{
|
||||||
memset(motorConfigMutable(), 0, sizeof(motorConfig_t));
|
memset(motorConfigMutable(), 0, sizeof(motorConfig_t));
|
||||||
const pgRegistry_t *pgRegistry = pgFind(PG_MOTOR_CONFIG);
|
const pgRegistry_t *pgRegistry = pgFind(PG_MOTOR_CONFIG);
|
||||||
pgResetCurrent(pgRegistry);
|
pgReset(pgRegistry);
|
||||||
EXPECT_EQ(1150, motorConfig()->minthrottle);
|
EXPECT_EQ(1150, motorConfig()->minthrottle);
|
||||||
EXPECT_EQ(1850, motorConfig()->maxthrottle);
|
EXPECT_EQ(1850, motorConfig()->maxthrottle);
|
||||||
EXPECT_EQ(1000, motorConfig()->mincommand);
|
EXPECT_EQ(1000, motorConfig()->mincommand);
|
||||||
|
@ -68,7 +68,7 @@ TEST(ParameterGroupsfTest, Test_pgFind)
|
||||||
motorConfig_t motorConfig2;
|
motorConfig_t motorConfig2;
|
||||||
memset(&motorConfig2, 0, sizeof(motorConfig_t));
|
memset(&motorConfig2, 0, sizeof(motorConfig_t));
|
||||||
motorConfigMutable()->dev.motorPwmRate = 500;
|
motorConfigMutable()->dev.motorPwmRate = 500;
|
||||||
pgStore(pgRegistry, &motorConfig2, sizeof(motorConfig_t), 0);
|
pgStore(pgRegistry, &motorConfig2, sizeof(motorConfig_t));
|
||||||
EXPECT_EQ(1150, motorConfig2.minthrottle);
|
EXPECT_EQ(1150, motorConfig2.minthrottle);
|
||||||
EXPECT_EQ(1850, motorConfig2.maxthrottle);
|
EXPECT_EQ(1850, motorConfig2.maxthrottle);
|
||||||
EXPECT_EQ(1000, motorConfig2.mincommand);
|
EXPECT_EQ(1000, motorConfig2.mincommand);
|
||||||
|
|
Loading…
Reference in New Issue