From 37df6f19687272497327be57d13dd540f67582b9 Mon Sep 17 00:00:00 2001 From: Damjan Adamic Date: Fri, 2 Sep 2016 22:35:54 +0200 Subject: [PATCH] * GPS sensor date/time now kept in UTC (previous conversion to local time was wrong) * internal GPS sensor can now set RTC clock [Horus] --- radio/src/gps.cpp | 27 ++++++++++++++-- radio/src/rtc.cpp | 38 +++++++++++++---------- radio/src/telemetry/frsky_d.cpp | 6 ---- radio/src/telemetry/telemetry_sensors.cpp | 4 +-- 4 files changed, 47 insertions(+), 28 deletions(-) diff --git a/radio/src/gps.cpp b/radio/src/gps.cpp index 372427b03..380bb1f07 100644 --- a/radio/src/gps.cpp +++ b/radio/src/gps.cpp @@ -134,6 +134,8 @@ typedef struct gpsDataNmea_s uint16_t altitude; uint16_t speed; uint16_t groundCourse; + uint32_t date; + uint32_t time; } gpsDataNmea_t; bool gpsNewFrameNMEA(char c) @@ -166,8 +168,6 @@ bool gpsNewFrameNMEA(char c) switch (gps_frame) { case FRAME_GGA: //************* GPGGA FRAME parsing switch (param) { - // case 1: // Time information - // break; case 2: gps_Msg.latitude = GPS_coord_to_degrees(string); break; @@ -200,12 +200,18 @@ bool gpsNewFrameNMEA(char c) break; case FRAME_RMC: //************* GPRMC FRAME parsing switch (param) { + case 1: + gps_Msg.time = grab_fields(string, 0); + break; case 7: gps_Msg.speed = ((grab_fields(string, 1) * 5144L) / 1000L); // speed in cm/s added by Mis break; case 8: gps_Msg.groundCourse = (grab_fields(string, 1)); // ground course deg * 10 break; + case 9: + gps_Msg.date = grab_fields(string, 0); + break; } break; @@ -241,7 +247,22 @@ bool gpsNewFrameNMEA(char c) case FRAME_RMC: gpsData.speed = gps_Msg.speed; gpsData.groundCourse = gps_Msg.groundCourse; - break; +#if defined(RTCLOCK) + // set RTC clock if needed + if (g_eeGeneral.adjustRTC && gps_Msg.fix) { + div_t qr = div(gps_Msg.date, 100); + uint8_t year = qr.rem; + qr = div(qr.quot, 100); + uint8_t mon = qr.rem; + uint8_t day = qr.quot; + qr = div(gps_Msg.time, 100); + uint8_t sec = qr.rem; + qr = div(qr.quot, 100); + uint8_t min = qr.rem; + uint8_t hour = qr.quot; + rtcAdjust(year+2000, mon, day, hour, min, sec); + } +#endif } // end switch } else { diff --git a/radio/src/rtc.cpp b/radio/src/rtc.cpp index 3ca3dddc8..9601dd070 100644 --- a/radio/src/rtc.cpp +++ b/radio/src/rtc.cpp @@ -112,7 +112,7 @@ const unsigned short int __mon_yday[2][13] = { offset OFFSET seconds east of UTC, and store year, yday, mon, mday, wday, hour, min, sec into *TP. Return nonzero if successful. */ -int __offtime(gtime_t * t, long int offset, struct gtm * tp) +int __offtime(const gtime_t * t, long int offset, struct gtm * tp) { long int days, rem, y; const unsigned short int * ip; @@ -167,7 +167,7 @@ int __offtime(gtime_t * t, long int offset, struct gtm * tp) /* time_r function implementations */ // G: No time zones in our implementation so just do the converion from gtime_t to struct tm -struct gtm * __localtime_r(gtime_t * t, struct gtm * tp) +struct gtm * __localtime_r(const gtime_t * t, struct gtm * tp) { __offtime(t, 0, tp); return tp; @@ -243,7 +243,7 @@ static gtime_t guess_time_tm(long int year, long int yday, int hour, int min, in /* Use CONVERT to convert *T to a broken down time in *TP. If *T is out of range for conversion, adjust it so that it is the nearest in-range value and then convert that. */ -static struct gtm * ranged_convert(struct gtm *(*convert)(gtime_t *, struct gtm *), gtime_t * t, struct gtm * tp) +static struct gtm * ranged_convert(struct gtm *(*convert)(const gtime_t *, struct gtm *), gtime_t * t, struct gtm * tp) { struct gtm * r = convert(t, tp); @@ -279,7 +279,7 @@ static struct gtm * ranged_convert(struct gtm *(*convert)(gtime_t *, struct gtm If *OFFSET's guess is correct, only one CONVERT call is needed. This function is external because it is used also by timegm.c. */ gtime_t __mktime_internal(struct gtm * tp, - struct gtm *(*convert)(gtime_t *, struct gtm *), + struct gtm *(*convert)(const gtime_t *, struct gtm *), gtime_t * offset) { gtime_t t, gt, t0, t1, t2; @@ -433,7 +433,7 @@ gtime_t gmktime(struct gtm * tp) } /* Fill a (struct tm) TP* from a given gtime_t time stamp */ -gtime_t filltm(gtime_t * t, struct gtm * tp) +gtime_t filltm(const gtime_t * t, struct gtm * tp) { return __offtime(t, 0, tp); } @@ -450,7 +450,7 @@ void gettime(struct gtm * tm) #define RTC_ADJUST_PERIOD 60 // how often RTC is checked for accuracy [seconds] #define RTC_ADJUST_TRESHOLD 20 // how much clock must differ before adjustment is made [seconds] /* - Changes RTC date/time to the given date/time if: + Changes RTC date/time to the given UTC date/time if: * RTC_ADJUST_PERIOD seconds have elapsed from the last time this function adjusted the RTC clock * AND if actual RTC clock differs from the given clock by more than RTC_ADJUST_TRESHOLD seconds * Function does nothing for a minute around midnight, where date change could produce erroneous result @@ -461,22 +461,26 @@ uint8_t rtcAdjust(uint16_t year, uint8_t mon, uint8_t day, uint8_t hour, uint8_t if ((get_tmr10ms() - lastRtcAdjust) > (RTC_ADJUST_PERIOD * 100)) { lastRtcAdjust = get_tmr10ms(); - struct gtm t; - gettime(&t); if ((hour == 0 && min == 0) || (hour == 23 && min == 59)) return 0; - if (t.tm_year != (year - 1900) || t.tm_mon != (mon - 1) || t.tm_mday != day || - (abs((t.tm_hour - hour) * 3600 + (t.tm_min - min) * 60 + (t.tm_sec - sec)) > RTC_ADJUST_TRESHOLD)) { - // we adjust RTC only if difference is > 20 seconds - t.tm_year = year - 1900; - t.tm_mon = mon - 1; - t.tm_mday = day; - t.tm_hour = hour; - t.tm_min = min; - t.tm_sec = sec; + // convert given UTC time to local time (to seconds) and compare it with RTC + struct gtm t; + t.tm_year = year - 1900; + t.tm_mon = mon - 1; + t.tm_mday = day; + t.tm_hour = hour; + t.tm_min = min; + t.tm_sec = sec; + gtime_t newTime = gmktime(&t) + g_eeGeneral.timezone * 3600; + gtime_t diff = (g_rtcTime > newTime) ? (g_rtcTime - newTime) : (newTime - g_rtcTime); + TRACE("rtc: %d, new: %d, diff: %d", g_rtcTime, newTime, diff); + if (diff > RTC_ADJUST_TRESHOLD) { + // convert newTime to struct gtm and set RTC clock + filltm(&newTime, &t); g_rtcTime = gmktime(&t); // update local timestamp and get wday calculated rtcSetTime(&t); TRACE("RTC clock adjusted to %04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec); + // TODO perhaps some kind of audio notification ??? return 1; } } diff --git a/radio/src/telemetry/frsky_d.cpp b/radio/src/telemetry/frsky_d.cpp index 62c8a8680..f9b68f60a 100644 --- a/radio/src/telemetry/frsky_d.cpp +++ b/radio/src/telemetry/frsky_d.cpp @@ -178,12 +178,6 @@ void parseTelemHubByte(uint8_t byte) frskyUpdateCells(); break; -#if defined(GPS) - case offsetof(FrskyTelemetryData, hour): - telemetryData.hub.hour = ((uint8_t)(telemetryData.hub.hour + g_eeGeneral.timezone + 24)) % 24; - break; -#endif - case offsetof(FrskyTelemetryData, accelX): case offsetof(FrskyTelemetryData, accelY): case offsetof(FrskyTelemetryData, accelZ): diff --git a/radio/src/telemetry/telemetry_sensors.cpp b/radio/src/telemetry/telemetry_sensors.cpp index 374c8e062..9a13fa137 100644 --- a/radio/src/telemetry/telemetry_sensors.cpp +++ b/radio/src/telemetry/telemetry_sensors.cpp @@ -84,7 +84,7 @@ void TelemetryItem::setValue(const TelemetrySensor & sensor, int32_t val, uint32 } } else { - datetime.hour = ((uint8_t) ((data & 0xff000000) >> 24) + g_eeGeneral.timezone + 24) % 24; + datetime.hour = (uint8_t) ((data & 0xff000000) >> 24); datetime.min = (uint8_t) ((data & 0x00ff0000) >> 16); datetime.sec = (uint16_t) ((data & 0x0000ff00) >> 8); if (datetime.datestate == 1) { @@ -131,7 +131,7 @@ void TelemetryItem::setValue(const TelemetrySensor & sensor, int32_t val, uint32 } else if (unit == UNIT_DATETIME_HOUR_MIN) { uint32_t data = uint32_t(newVal); - datetime.hour = ((data & 0xFF) + g_eeGeneral.timezone + 24) % 24; + datetime.hour = (data & 0xFF); datetime.min = data >> 8; } else if (unit == UNIT_DATETIME_SEC) {