Skip to content

Commit

Permalink
Fix & optimize FW version parsing and checking
Browse files Browse the repository at this point in the history
PFW-1433
  • Loading branch information
D.R.racer authored and DRracer committed Nov 23, 2022
1 parent c815791 commit fea1520
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 87 deletions.
188 changes: 112 additions & 76 deletions Firmware/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,24 @@

// Allocate the version string in the program memory. Otherwise the string lands either on the stack or in the global RAM.
static const char FW_VERSION_STR[] PROGMEM = FW_VERSION;
static const uint16_t FW_VERSION_NR[4] PROGMEM = { FW_MAJOR, FW_MINOR, FW_REVISION, FW_COMMIT_NR };
static const uint16_t FW_VERSION_NR[4] PROGMEM = {
FW_MAJOR,
FW_MINOR,
FW_REVISION,
#ifndef FW_FLAVOR
FW_COMMIT_NR
#else
# if FW_DEV_VERSION == FW_VERSION_ALPHA
FIRMWARE_REVISION_ALPHA + FW_FLAVERSION
# elif FW_DEV_VERSION == FW_VERSION_BETA
FIRMWARE_REVISION_BETA + FW_FLAVERSION
# elif FW_DEV_VERSION == FW_VERSION_RC
FIRMWARE_REVISION_RC + FW_FLAVERSION
# elif FW_DEV_VERSION == FW_VERSION_GOLD
0
# endif
#endif
};

const char* FW_VERSION_STR_P()
{
Expand All @@ -24,10 +41,10 @@ const char* FW_PRUSA3D_MAGIC_STR_P()
return FW_PRUSA3D_MAGIC_STR;
}

const char STR_REVISION_DEV [] PROGMEM = "dev";
const char STR_REVISION_ALPHA[] PROGMEM = "alpha";
const char STR_REVISION_BETA [] PROGMEM = "beta";
const char STR_REVISION_RC [] PROGMEM = "rc";
const char STR_REVISION_DEV [] PROGMEM = "DEV";
const char STR_REVISION_ALPHA[] PROGMEM = "ALPHA";
const char STR_REVISION_BETA [] PROGMEM = "BETA";
const char STR_REVISION_RC [] PROGMEM = "RC";

inline bool is_whitespace_or_nl(char c)
{
Expand All @@ -44,78 +61,84 @@ inline bool is_digit(char c)
return c >= '0' && c <= '9';
}

char const * __attribute__((noinline)) Number(char const *str, uint16_t *v){
*v = 0;
while(is_digit(*str)){
*v *= 10;
*v += *str - '0';
++str;
}
return str;
}

bool __attribute__((noinline)) Tag(const char *str, const char *tag_P, uint8_t tagSize, uint16_t tagMask, uint16_t *v){
if( ! strncmp_P(str, tag_P, tagSize) ){
Number(str + tagSize, v);
*v |= tagMask;
return true;
}
return false;
}

// Parse a major.minor.revision version number.
// Return true if valid.
inline bool parse_version(const char *str, uint16_t version[4])
{
#if 0
SERIAL_ECHOPGM("Parsing version string ");
SERIAL_ECHO(str);
SERIAL_ECHOLNPGM("");
#endif
bool parse_version(const char *str, uint16_t version[4]) {
for(uint8_t i = 0; i < 2; ++i){
str = Number(str, version + i);
if (*str != '.')
return false;
++str;
}
str = Number(str, version + 2);

const char *major = str;
const char *p = str;
while (is_digit(*p)) ++ p;
if (*p != '.')
return false;
const char *minor = ++ p;
while (is_digit(*p)) ++ p;
if (*p != '.')
return false;
const char *rev = ++ p;
while (is_digit(*p)) ++ p;
if (! is_whitespace_or_nl_or_eol(*p) && *p != '-')
return false;
version[3] = FIRMWARE_REVISION_RELEASED;

char *endptr = NULL;
version[0] = strtol(major, &endptr, 10);
if (endptr != minor - 1)
return false;
version[1] = strtol(minor, &endptr, 10);
if (endptr != rev - 1)
return false;
version[2] = strtol(rev, &endptr, 10);
if (endptr != p)
return false;
// skip everything else until eol or '-'
for(;;){
if(is_whitespace_or_nl_or_eol(*str)){
// speculatively reached the end of line, silently ignoring anything which is not a '-'
return true;
}
if( *str == '-'){
break; // tag expected
}
++str;
}

version[3] = FIRMWARE_REVISION_RELEASED;
if (*p ++ == '-') {
const char *q = p;
while (! is_whitespace_or_nl_or_eol(*q))
++ q;
uint8_t n = q - p;
if (n == strlen_P(STR_REVISION_DEV) && strncmp_P(p, STR_REVISION_DEV, n) == 0)
version[3] = FIRMWARE_REVISION_DEV;
else if (n == strlen_P(STR_REVISION_ALPHA) && strncmp_P(p, STR_REVISION_ALPHA, n) == 0)
version[3] = FIRMWARE_REVISION_ALPHA;
else if (n == strlen_P(STR_REVISION_BETA) && strncmp_P(p, STR_REVISION_BETA, n) == 0)
version[3] = FIRMWARE_REVISION_BETA;
else if ((n == 2 || n == 3) && (p[0] == 'r' || p[0] == 'R') && (p[1] == 'c' || p[1] == 'C')) {
if (n == 2)
version[3] = FIRMWARE_REVISION_RC;
else {
if (is_digit(p[2]))
version[3] = FIRMWARE_REVISION_RC + p[2] - '1';
else
return false;
// SERIAL_ECHOPGM("parse_version: ");
// SERIAL_ECHO(version[0]);
// SERIAL_ECHO('.');
// SERIAL_ECHO(version[1]);
// SERIAL_ECHO('.');
// SERIAL_ECHO(version[2]);
// SERIAL_ECHO('.');
// SERIAL_ECHOLN(version[3]);
if (*str++ == '-') {
switch(*str){
case 'A': // expect ALPHA
static_assert(sizeof(STR_REVISION_ALPHA) == 6);
return Tag( str, STR_REVISION_ALPHA, sizeof(STR_REVISION_ALPHA) - 1, FIRMWARE_REVISION_ALPHA, version + 3);
case 'B': // expect BETA
static_assert(sizeof(STR_REVISION_BETA) == 5);
return Tag( str, STR_REVISION_BETA, sizeof(STR_REVISION_BETA) - 1, FIRMWARE_REVISION_BETA, version + 3);
case 'D': // expect DEV
static_assert(sizeof(STR_REVISION_DEV) == 4);
return Tag( str, STR_REVISION_DEV, sizeof(STR_REVISION_DEV) - 1, FIRMWARE_REVISION_DEV, version + 3);
case 'R': // expect RC
static_assert(sizeof(STR_REVISION_RC) == 3);
return Tag( str, STR_REVISION_RC, sizeof(STR_REVISION_RC) - 1, FIRMWARE_REVISION_RC, version + 3);
default: return false; // fail everything else
}
} else
return false;
}

#if 0
SERIAL_ECHOPGM("Version parsed, major: ");
SERIAL_ECHO(version[0]);
SERIAL_ECHOPGM(", minor: ");
SERIAL_ECHO(version[1]);
SERIAL_ECHOPGM(", revision: ");
SERIAL_ECHO(version[2]);
SERIAL_ECHOPGM(", flavor: ");
SERIAL_ECHO(version[3]);
SERIAL_ECHOLNPGM("");
#endif
return true;
// SERIAL_ECHOPGM("parse_version with tag: ");
// SERIAL_ECHO(version[0]);
// SERIAL_ECHO('.');
// SERIAL_ECHO(version[1]);
// SERIAL_ECHO('.');
// SERIAL_ECHO(version[2]);
// SERIAL_ECHO('.');
// SERIAL_ECHOLN(version[3]);
return false;
}

inline bool strncmp_PP(const char *p1, const char *p2, uint8_t n)
Expand Down Expand Up @@ -357,12 +380,25 @@ void fw_version_check(const char *pVersion) {
return;
if ((nCompareValueResult < COMPARE_VALUE_EQUAL) && oCheckVersion == ClCheckVersion::_Warn)
return;
// SERIAL_ECHO_START;
// SERIAL_ECHOLNPGM("Printer FW version differs from the G-code ...");
// SERIAL_ECHOPGM("actual : ");
// SERIAL_ECHOLN(FW_VERSION);
// SERIAL_ECHOPGM("expected: ");
// SERIAL_ECHOLN(pVersion);
// SERIAL_ECHO_START;
// SERIAL_ECHOLNPGM("Printer FW version differs from the G-code ...");
// SERIAL_ECHOPGM("actual : ");
// SERIAL_ECHO(eeprom_read_word((uint16_t *)EEPROM_FIRMWARE_VERSION_MAJOR));
// SERIAL_ECHO('.');
// SERIAL_ECHO(eeprom_read_word((uint16_t *)EEPROM_FIRMWARE_VERSION_MINOR));
// SERIAL_ECHO('.');
// SERIAL_ECHO(eeprom_read_word((uint16_t *)EEPROM_FIRMWARE_VERSION_REVISION));
// SERIAL_ECHO('.');
// SERIAL_ECHO(eeprom_read_word((uint16_t *)EEPROM_FIRMWARE_VERSION_FLAVOR));
// SERIAL_ECHOPGM("\nexpected: ");
// SERIAL_ECHO(aVersion[0]);
// SERIAL_ECHO('.');
// SERIAL_ECHO(aVersion[1]);
// SERIAL_ECHO('.');
// SERIAL_ECHO(aVersion[2]);
// SERIAL_ECHO('.');
// SERIAL_ECHOLN(aVersion[3]);

switch (oCheckVersion) {
case ClCheckVersion::_Warn:
// lcd_show_fullscreen_message_and_wait_P(_i("Printer FW version differs from the G-code. Continue?"));
Expand Down
17 changes: 6 additions & 11 deletions Firmware/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,12 @@
extern const char* FW_VERSION_STR_P();

// Definition of a firmware flavor numerical values.
enum FirmwareRevisionFlavorType
{
FIRMWARE_REVISION_DEV = 0,
FIRMWARE_REVISION_ALPHA = 1,
FIRMWARE_REVISION_BETA = 2,
FIRMWARE_REVISION_RC,
FIRMWARE_REVISION_RC2,
FIRMWARE_REVISION_RC3,
FIRMWARE_REVISION_RC4,
FIRMWARE_REVISION_RC5,
FIRMWARE_REVISION_RELEASED = 127
enum FirmwareRevisionFlavorType : uint16_t {
FIRMWARE_REVISION_RELEASED = 0,
FIRMWARE_REVISION_DEV = 0x0100,
FIRMWARE_REVISION_ALPHA = 0x0200,
FIRMWARE_REVISION_BETA = 0x0300,
FIRMWARE_REVISION_RC = 0x0400
};

extern bool show_upgrade_dialog_if_version_newer(const char *version_string);
Expand Down

0 comments on commit fea1520

Please sign in to comment.