feat: Support all current timezones for GPS (#3406)

* Support all current timezones.

* Fix function name and calculation for timezone offset.

* Allow setting any time offset value from -12 to +14 in 15 minutes increments.

* Alternate timezone editor in Companion (from elecpower).

* Fix compiler warning.

* chore: Add the T20
This commit is contained in:
philmoz
2023-07-16 14:02:27 +10:00
committed by GitHub
parent 286ae00678
commit bd92f70056
27 changed files with 223 additions and 42 deletions
+2 -1
View File
@@ -855,7 +855,8 @@ PACK(struct RadioData {
// Real attributes
NOBACKUP(uint8_t manuallyEdited:1);
NOBACKUP(int8_t spare0:7 SKIP);
int8_t timezoneMinutes:3; // -3 to +3 ==> (-45 to 45 minutes in 15 minute increments)
NOBACKUP(int8_t spare0:4 SKIP);
CUST_ATTR(semver,nullptr,w_semver);
CUST_ATTR(board,nullptr,w_board);
CalibData calib[MAX_CALIB_ANALOG_INPUTS] NO_IDX;
+12 -3
View File
@@ -599,9 +599,18 @@ void menuRadioSetup(event_t event)
#if defined(GPS)
case ITEM_RADIO_SETUP_TIMEZONE:
lcdDrawTextAlignedLeft(y, STR_TIMEZONE);
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.timezone, attr|LEFT);
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.timezone, -12, 12);
{
lcdDrawTextAlignedLeft(y, STR_TIMEZONE);
int tzIndex = timezoneIndex(g_eeGeneral.timezone, g_eeGeneral.timezoneMinutes);
lcdDrawText(RADIO_SETUP_2ND_COLUMN, y, timezoneDisplay(tzIndex).c_str(), attr);
if (attr) {
tzIndex = checkIncDec(event, tzIndex, minTimezone(), maxTimezone(), EE_GENERAL);
if (checkIncDec_Ret) {
g_eeGeneral.timezone = timezoneHour(tzIndex);
g_eeGeneral.timezoneMinutes = timezoneMinute(tzIndex);
}
}
}
break;
case ITEM_RADIO_SETUP_ADJUST_RTC:
+12 -3
View File
@@ -547,9 +547,18 @@ void menuRadioSetup(event_t event)
break;
case ITEM_RADIO_SETUP_TIMEZONE:
lcdDrawText(INDENT_WIDTH, y, STR_TIMEZONE);
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.timezone, attr|LEFT);
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.timezone, -12, 12);
{
lcdDrawText(INDENT_WIDTH, y, STR_TIMEZONE);
int tzIndex = timezoneIndex(g_eeGeneral.timezone, g_eeGeneral.timezoneMinutes);
lcdDrawText(RADIO_SETUP_2ND_COLUMN, y, timezoneDisplay(tzIndex).c_str(), attr);
if (attr) {
tzIndex = checkIncDec(event, tzIndex, minTimezone(), maxTimezone(), EE_GENERAL);
if (checkIncDec_Ret) {
g_eeGeneral.timezone = timezoneHour(tzIndex);
g_eeGeneral.timezoneMinutes = timezoneMinute(tzIndex);
}
}
}
break;
case ITEM_RADIO_SETUP_ADJUST_RTC:
+16 -1
View File
@@ -556,10 +556,22 @@ class GpsPage : public SubPage {
{
FlexGridLayout grid(col_two_dsc, row_dsc, 4);
tzIndex = timezoneIndex(g_eeGeneral.timezone, g_eeGeneral.timezoneMinutes);
auto line = body.newLine(&grid);
// Timezone
new StaticText(line, rect_t{}, STR_TIMEZONE, 0, COLOR_THEME_PRIMARY1);
new NumberEdit(line, rect_t{}, -12, 12, GET_SET_DEFAULT(g_eeGeneral.timezone));
auto tz = new NumberEdit(line, rect_t{}, minTimezone(), maxTimezone(),
GET_DEFAULT(tzIndex),
[=](int newTz) {
tzIndex = newTz;
g_eeGeneral.timezone = timezoneHour(newTz);
g_eeGeneral.timezoneMinutes = timezoneMinute(newTz);
SET_DIRTY();
});
tz->setDisplayHandler([](int32_t tz) {
return timezoneDisplay(tz);
});
line = body.newLine(&grid);
// Adjust RTC (from telemetry)
@@ -572,6 +584,9 @@ class GpsPage : public SubPage {
new Choice(line, rect_t{}, STR_GPSFORMAT, 0, 1, GET_SET_DEFAULT(g_eeGeneral.gpsFormat));
line = body.newLine(&grid);
}
protected:
int tzIndex;
};
class ViewOptionsPage : public Page
+1 -1
View File
@@ -471,7 +471,7 @@ uint8_t rtcAdjust(uint16_t year, uint8_t mon, uint8_t day, uint8_t hour, uint8_t
t.tm_hour = hour;
t.tm_min = min;
t.tm_sec = sec;
gtime_t newTime = gmktime(&t) + g_eeGeneral.timezone * 3600;
gtime_t newTime = gmktime(&t) + timezoneOffsetSeconds(g_eeGeneral.timezone, g_eeGeneral.timezoneMinutes);
gtime_t diff = (g_rtcTime > newTime) ? (g_rtcTime - newTime) : (newTime - g_rtcTime);
#if defined(DEBUG) && defined (PCBTARANIS)
@@ -263,7 +263,8 @@ static const struct YamlNode struct_CustomFunctionData[] = {
};
static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "manuallyEdited", 1 ),
YAML_PADDING( 7 ),
YAML_SIGNED( "timezoneMinutes", 3 ),
YAML_PADDING( 4 ),
YAML_CUSTOM("semver",nullptr,w_semver),
YAML_CUSTOM("board",nullptr,w_board),
YAML_ARRAY("calib", 48, 12, struct_CalibData, NULL),
@@ -293,7 +293,8 @@ static const struct YamlNode struct_OpenTxTheme__PersistentData[] = {
};
static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "manuallyEdited", 1 ),
YAML_PADDING( 7 ),
YAML_SIGNED( "timezoneMinutes", 3 ),
YAML_PADDING( 4 ),
YAML_CUSTOM("semver",nullptr,w_semver),
YAML_CUSTOM("board",nullptr,w_board),
YAML_ARRAY("calib", 48, 22, struct_CalibData, NULL),
@@ -263,7 +263,8 @@ static const struct YamlNode struct_CustomFunctionData[] = {
};
static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "manuallyEdited", 1 ),
YAML_PADDING( 7 ),
YAML_SIGNED( "timezoneMinutes", 3 ),
YAML_PADDING( 4 ),
YAML_CUSTOM("semver",nullptr,w_semver),
YAML_CUSTOM("board",nullptr,w_board),
YAML_ARRAY("calib", 48, 12, struct_CalibData, NULL),
@@ -263,7 +263,8 @@ static const struct YamlNode struct_CustomFunctionData[] = {
};
static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "manuallyEdited", 1 ),
YAML_PADDING( 7 ),
YAML_SIGNED( "timezoneMinutes", 3 ),
YAML_PADDING( 4 ),
YAML_CUSTOM("semver",nullptr,w_semver),
YAML_CUSTOM("board",nullptr,w_board),
YAML_ARRAY("calib", 48, 12, struct_CalibData, NULL),
@@ -301,7 +301,8 @@ static const struct YamlNode struct_OpenTxTheme__PersistentData[] = {
};
static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "manuallyEdited", 1 ),
YAML_PADDING( 7 ),
YAML_SIGNED( "timezoneMinutes", 3 ),
YAML_PADDING( 4 ),
YAML_CUSTOM("semver",nullptr,w_semver),
YAML_CUSTOM("board",nullptr,w_board),
YAML_ARRAY("calib", 48, 22, struct_CalibData, NULL),
@@ -301,7 +301,8 @@ static const struct YamlNode struct_OpenTxTheme__PersistentData[] = {
};
static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "manuallyEdited", 1 ),
YAML_PADDING( 7 ),
YAML_SIGNED( "timezoneMinutes", 3 ),
YAML_PADDING( 4 ),
YAML_CUSTOM("semver",nullptr,w_semver),
YAML_CUSTOM("board",nullptr,w_board),
YAML_ARRAY("calib", 48, 22, struct_CalibData, NULL),
@@ -263,7 +263,8 @@ static const struct YamlNode struct_CustomFunctionData[] = {
};
static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "manuallyEdited", 1 ),
YAML_PADDING( 7 ),
YAML_SIGNED( "timezoneMinutes", 3 ),
YAML_PADDING( 4 ),
YAML_CUSTOM("semver",nullptr,w_semver),
YAML_CUSTOM("board",nullptr,w_board),
YAML_ARRAY("calib", 48, 12, struct_CalibData, NULL),
@@ -263,7 +263,8 @@ static const struct YamlNode struct_CustomFunctionData[] = {
};
static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "manuallyEdited", 1 ),
YAML_PADDING( 7 ),
YAML_SIGNED( "timezoneMinutes", 3 ),
YAML_PADDING( 4 ),
YAML_CUSTOM("semver",nullptr,w_semver),
YAML_CUSTOM("board",nullptr,w_board),
YAML_ARRAY("calib", 48, 12, struct_CalibData, NULL),
@@ -263,7 +263,8 @@ static const struct YamlNode struct_CustomFunctionData[] = {
};
static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "manuallyEdited", 1 ),
YAML_PADDING( 7 ),
YAML_SIGNED( "timezoneMinutes", 3 ),
YAML_PADDING( 4 ),
YAML_CUSTOM("semver",nullptr,w_semver),
YAML_CUSTOM("board",nullptr,w_board),
YAML_ARRAY("calib", 48, 12, struct_CalibData, NULL),
@@ -265,7 +265,8 @@ static const struct YamlNode struct_CustomFunctionData[] = {
};
static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "manuallyEdited", 1 ),
YAML_PADDING( 7 ),
YAML_SIGNED( "timezoneMinutes", 3 ),
YAML_PADDING( 4 ),
YAML_CUSTOM("semver",nullptr,w_semver),
YAML_CUSTOM("board",nullptr,w_board),
YAML_ARRAY("calib", 48, 12, struct_CalibData, NULL),
+44
View File
@@ -1045,3 +1045,47 @@ char *strAppendDate(char *str, bool time)
#if !defined(BOOT)
#endif
// Manage timezones
// For backward compatibility timezone is stored as two separate values:
// timezone = hour value
// timezoneMinutes - minute value / 15
int8_t minTimezone()
{
return -12 * 4;
}
int8_t maxTimezone()
{
return 14 * 4;
}
std::string timezoneDisplay(int tz)
{
char s[16];
int h = abs(tz / 4);
int m = abs(tz % 4) * 15;
sprintf(s,"%s%d:%02d", (tz < 0) ? "-" : "", h, m);
return std::string(s);
}
int timezoneIndex(int8_t tzHour, int8_t tzMinute)
{
return (tzHour * 4) + tzMinute;
}
int8_t timezoneHour(int tz)
{
return tz / 4;
}
int8_t timezoneMinute(int tz)
{
return tz % 4;
}
int timezoneOffsetSeconds(int8_t tzHour, int8_t tzMinute)
{
return (tzHour * 3600) + (tzMinute * 15 * 60);
}
+9
View File
@@ -174,4 +174,13 @@ int strncasecmp(char (&s1)[L1], const char *const s2)
std::string getValueWithUnit(int val, uint8_t unit, LcdFlags flags);
std::string getGVarValue(uint8_t gvar, gvar_t value, LcdFlags flags);
// Timezone handling
extern int8_t minTimezone();
extern int8_t maxTimezone();
extern std::string timezoneDisplay(int tz);
extern int timezoneIndex(int8_t tzHour, int8_t tzMinute);
extern int8_t timezoneHour(int tz);
extern int8_t timezoneMinute(int tz);
extern int timezoneOffsetSeconds(int8_t tzHour, int8_t tzMinute);
#endif // _STRHELPERS_H_
+1 -1
View File
@@ -934,7 +934,7 @@ static void adjustTimeFromUTC(uint8_t hour, uint8_t min, uint8_t sec,
struct gtm *tp)
{
// Get current UTC date/time
__offtime(&g_rtcTime, -g_eeGeneral.timezone * 3600, tp);
__offtime(&g_rtcTime, -timezoneOffsetSeconds(g_eeGeneral.timezone, g_eeGeneral.timezoneMinutes), tp);
tp->tm_hour = hour;
tp->tm_min = min;