Added support for half-hour timezones, moved datetime_t struct fields from bitfields to full 8-bit variables, added function to adjust the off-range fields of a datetime_t struct.

md1702
Silvano Seva 2022-10-31 11:41:54 +01:00
rodzic f26afc42e5
commit ce1dc202ae
5 zmienionych plików z 177 dodań i 54 usunięć

Wyświetl plik

@ -35,14 +35,13 @@ extern "C" {
*/ */
typedef struct typedef struct
{ {
uint8_t hour : 5; // Hours (0-23) int8_t hour; // Hours (0-23)
uint8_t minute : 6; // Minutes (0-59) int8_t minute; // Minutes (0-59)
uint8_t second : 6; // Seconds (0-59) int8_t second; // Seconds (0-59)
uint8_t day : 3; // Day of the week (1-7) int8_t day; // Day of the week (1-7)
uint8_t date : 5; // Day of the month (1-31) int8_t date; // Day of the month (1-31)
uint8_t month : 4; // Month (1-12) int8_t month; // Month (1-12)
uint8_t year : 7; // Year (0-99) uint8_t year; // Year (0-99)
uint8_t : 4; // Padding to 40 bits
} }
datetime_t; datetime_t;
@ -64,6 +63,14 @@ datetime_t utcToLocalTime(const datetime_t utc_time, const int8_t timezone);
*/ */
datetime_t localTimeToUtc(const datetime_t local_time, const int8_t timezone); datetime_t localTimeToUtc(const datetime_t local_time, const int8_t timezone);
/**
* Adjust the values of the members of datetime_t if they are off-range or if
* they have values that do not match the date described by the other members.
*
* @param time: pointer to a datetime_t struct.
*/
void realignTimeInfo(datetime_t *time);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

Wyświetl plik

@ -51,14 +51,14 @@ typedef struct
uint8_t contrast; // Display contrast uint8_t contrast; // Display contrast
uint8_t sqlLevel; // Squelch level uint8_t sqlLevel; // Squelch level
uint8_t voxLevel; // Vox level uint8_t voxLevel; // Vox level
int8_t utc_timezone; // Timezone int8_t utc_timezone; // Timezone, in units of half hours
bool gps_enabled; // GPS active bool gps_enabled; // GPS active
char callsign[10]; // Plaintext callsign, for future use char callsign[10]; // Plaintext callsign, for future use
uint8_t display_timer : 4, // Standby timer uint8_t display_timer : 4, // Standby timer
not_in_use : 4; _ununsed : 4;
uint8_t vpLevel : 3, uint8_t vpLevel : 3, // Voice prompt level
vpPhoneticSpell : 1, vpPhoneticSpell : 1, // Phonetic spell enabled
vpReserved : 4; // reserved for voice rate on the fly. _reserved : 4;
} }
__attribute__((packed)) settings_t; __attribute__((packed)) settings_t;
@ -78,10 +78,10 @@ static const settings_t default_settings =
false, // GPS enabled false, // GPS enabled
"", // Empty callsign "", // Empty callsign
TIMER_30S, // 30 seconds TIMER_30S, // 30 seconds
0, // not in use 0, // not used
0, // vpOff, 0, // Voice prompts off
0, // phonetic spell off, 0, // Phonetic spell off
0 // not in use. 0 // not used
}; };
#endif /* SETTINGS_H */ #endif /* SETTINGS_H */

Wyświetl plik

@ -19,26 +19,42 @@
***************************************************************************/ ***************************************************************************/
#include <datetime.h> #include <datetime.h>
#include <stdlib.h>
#include <time.h>
static const int DAYS_IN_MONTH[12] =
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
#define _DAYS_IN_MONTH(x) ((x == 2) ? days_in_feb : DAYS_IN_MONTH[x - 1])
/**
* \internal
* Return the number of days in a year by checking wheter the current year is
* a leap one or not.
*
* @param year: current year, ranging from 0 to 99.
* @return number of days in the year.
*/
static inline uint16_t daysInYear(uint16_t year)
{
year += 2000;
if( ((year % 4) == 0) && (((year % 100) != 0) || ((year % 400) == 0)))
{
return 366;
}
return 365;
}
datetime_t utcToLocalTime(const datetime_t utc_time, const int8_t timezone) datetime_t utcToLocalTime(const datetime_t utc_time, const int8_t timezone)
{ {
datetime_t local_time = utc_time; datetime_t local_time = utc_time;
if(local_time.hour + timezone >= 24) local_time.hour += (timezone / 2);
{ local_time.minute += (timezone % 2) * 30;
local_time.hour = local_time.hour - 24 + timezone; realignTimeInfo(&local_time);
local_time.date += 1;
}
else if(local_time.hour + timezone < 0)
{
local_time.hour = local_time.hour + 24 + timezone;
local_time.date -= 1;
}
else
{
local_time.hour += timezone;
}
return local_time; return local_time;
} }
@ -47,20 +63,103 @@ datetime_t localTimeToUtc(const datetime_t local_time, const int8_t timezone)
{ {
datetime_t utc_time = local_time; datetime_t utc_time = local_time;
if(utc_time.hour - timezone >= 24) utc_time.minute -= (timezone % 2) * 30;
{ utc_time.hour -= (timezone / 2);
utc_time.hour = utc_time.hour - 24 - timezone; realignTimeInfo(&utc_time);
utc_time.date += 1;
}
else if(utc_time.hour - timezone < 0)
{
utc_time.hour = utc_time.hour + 24 - timezone;
utc_time.date -= 1;
}
else
{
utc_time.hour -= timezone;
}
return utc_time; return utc_time;
} }
/*
* Function borrowed from newlib implementation of mktime, see
* https://github.com/bminor/newlib/blob/master/newlib/libc/time/mktime.c
*
* Slightly modified to remove the _DAYS_IN_YEAR macro and to handle month
* with range 1-12 instead of 0-11.
*/
void realignTimeInfo(datetime_t *time)
{
div_t res;
int days_in_feb = 28;
if((time->second < 0) || (time->second > 59))
{
res = div(time->second, 60);
time->minute += res.quot;
if ((time->second = res.rem) < 0)
{
time->second += 60;
time->minute -= 1;
}
}
if((time->minute < 0) || (time->minute > 59))
{
res = div(time->minute, 60);
time->hour += res.quot;
if((time->minute = res.rem) < 0)
{
time->minute += 60;
time->hour -= 1;
}
}
if((time->hour < 0) || (time->hour > 23))
{
res = div(time->hour, 24);
time->date += res.quot;
if((time->hour = res.rem) < 0)
{
time->hour += 24;
time->date -= 1;
}
}
if((time->month < 0) || (time->month > 12))
{
res = div (time->month, 12);
time->year += res.quot;
if((time->month = res.rem) < 0)
{
time->month += 12;
time->year -= 1;
}
}
if(daysInYear(time->year) == 366)
days_in_feb = 29;
if(time->date <= 0)
{
while(time->date <= 0)
{
time->month -= 1;
if(time->month == -1)
{
time->year -= 1;
time->month = 12;
days_in_feb = ((daysInYear(time->year) == 366) ? 29 : 28);
}
time->date += _DAYS_IN_MONTH (time->month);
}
}
else
{
while(time->date > _DAYS_IN_MONTH (time->month))
{
time->date -= _DAYS_IN_MONTH (time->month);
time->month += 1;
if (time->month > 12)
{
time->year += 1;
time->month = 1;
days_in_feb = ((daysInYear (time->year) == 366) ? 29 : 28);
}
}
}
}

Wyświetl plik

@ -1893,10 +1893,10 @@ void ui_updateFSM(bool *sync_rtx)
state.gps_set_time); state.gps_set_time);
break; break;
case G_TIMEZONE: case G_TIMEZONE:
if(msg.keys & KEY_LEFT || msg.keys & KEY_UP || if(msg.keys & KEY_LEFT || msg.keys & KEY_DOWN ||
msg.keys & KNOB_LEFT) msg.keys & KNOB_LEFT)
state.settings.utc_timezone -= 1; state.settings.utc_timezone -= 1;
else if(msg.keys & KEY_RIGHT || msg.keys & KEY_DOWN || else if(msg.keys & KEY_RIGHT || msg.keys & KEY_UP ||
msg.keys & KNOB_RIGHT) msg.keys & KNOB_RIGHT)
state.settings.utc_timezone += 1; state.settings.utc_timezone += 1;
vp_announceSettingsInt(&currentLanguage->UTCTimeZone, vp_announceSettingsInt(&currentLanguage->UTCTimeZone,

Wyświetl plik

@ -296,17 +296,34 @@ int _ui_getSettingsGPSValueName(char *buf, uint8_t max_len, uint8_t index)
switch(index) switch(index)
{ {
case G_ENABLED: case G_ENABLED:
snprintf(buf, max_len, "%s", (last_state.settings.gps_enabled) ? currentLanguage->on : currentLanguage->off); snprintf(buf, max_len, "%s", (last_state.settings.gps_enabled) ?
currentLanguage->on :
currentLanguage->off);
break; break;
case G_SET_TIME: case G_SET_TIME:
snprintf(buf, max_len, "%s", (last_state.gps_set_time) ? currentLanguage->on : currentLanguage->off); snprintf(buf, max_len, "%s", (last_state.gps_set_time) ?
currentLanguage->on :
currentLanguage->off);
break; break;
case G_TIMEZONE: case G_TIMEZONE:
// Add + prefix to positive numbers {
int8_t tz_hr = (last_state.settings.utc_timezone / 2);
int8_t tz_mn = (last_state.settings.utc_timezone % 2) * 5;
char sign = ' ';
if(last_state.settings.utc_timezone > 0) if(last_state.settings.utc_timezone > 0)
snprintf(buf, max_len, "+%d", last_state.settings.utc_timezone); {
else sign = '+';
snprintf(buf, max_len, "%d", last_state.settings.utc_timezone); }
else if(last_state.settings.utc_timezone < 0)
{
sign = '-';
tz_hr *= (-1);
tz_mn *= (-1);
}
snprintf(buf, max_len, "%c%d.%d", sign, tz_hr, tz_mn);
}
break; break;
} }
return 0; return 0;