This value is the offset from the top of the minute for the first APRS
packet in the minute. Subsequent packets will be transmitted
'interval' seconds apart for the rest of the minute.
This allows multiple transmitters to be configured to share the same
frequency and not transmit at the same time.
Note that this offset only works when the device has GPS lock.
Signed-off-by: Keith Packard <keithp@keithp.com>
uint8_t class, id;
struct ao_ublox_cksum cksum;
uint8_t i;
uint8_t class, id;
struct ao_ublox_cksum cksum;
uint8_t i;
+ AO_TICK_TYPE packet_start_tick;
+ AO_TICK_TYPE solution_tick = 0;
/* Locate the begining of the next record */
while (ao_ublox_byte() != (uint8_t) 0xb5)
;
/* Locate the begining of the next record */
while (ao_ublox_byte() != (uint8_t) 0xb5)
;
+ packet_start_tick = ao_tick_count;
+
if (ao_ublox_byte() != (uint8_t) 0x62)
continue;
if (ao_ublox_byte() != (uint8_t) 0x62)
continue;
ao_ublox_len = header_byte();
ao_ublox_len |= header_byte() << 8;
ao_ublox_len = header_byte();
ao_ublox_len |= header_byte() << 8;
- ao_gps_dbg(DBG_PROTO, "class %02x id %02x len %d\n", class, id, ao_ublox_len);
+ ao_gps_dbg(DBG_PROTO, "%6u class %02x id %02x len %d\n", packet_start_tick, class, id, ao_ublox_len);
if (ao_ublox_len > 1023)
continue;
if (ao_ublox_len > 1023)
continue;
if (ao_ublox_len != 52)
break;
ao_ublox_parse_nav_sol();
if (ao_ublox_len != 52)
break;
ao_ublox_parse_nav_sol();
+ solution_tick = packet_start_tick;
break;
case UBLOX_NAV_SVINFO:
if (ao_ublox_len < 8)
break;
case UBLOX_NAV_SVINFO:
if (ao_ublox_len < 8)
switch (id) {
case UBLOX_NAV_TIMEUTC:
ao_mutex_get(&ao_gps_mutex);
switch (id) {
case UBLOX_NAV_TIMEUTC:
ao_mutex_get(&ao_gps_mutex);
- ao_gps_tick = ao_time();
+ ao_gps_tick = solution_tick;
ao_gps_data.flags = 0;
ao_gps_data.flags |= AO_GPS_RUNNING;
ao_gps_data.flags = 0;
ao_gps_data.flags |= AO_GPS_RUNNING;
ao_config.pad_box = 1;
if (minor < 23)
ao_config.pad_idle = 120;
ao_config.pad_box = 1;
if (minor < 23)
ao_config.pad_idle = 120;
+#endif
+#if HAS_APRS
+ if (minor < 24)
+ ao_config.aprs_offset = 0;
#endif
ao_config.minor = AO_CONFIG_MINOR;
ao_config_dirty = 1;
#endif
ao_config.minor = AO_CONFIG_MINOR;
ao_config_dirty = 1;
ao_telemetry_reset_interval();
}
ao_telemetry_reset_interval();
}
+static void
+ao_config_aprs_offset_show(void)
+{
+ printf ("APRS offset: %d\n", ao_config.aprs_offset);
+}
+
+static void
+ao_config_aprs_offset_set(void)
+{
+ uint16_t r = ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ _ao_config_edit_start();
+ ao_config.aprs_offset = r;
+ _ao_config_edit_finish();
+ ao_telemetry_reset_interval();
+}
+
#endif /* HAS_APRS */
#if HAS_RADIO_AMP
#endif /* HAS_APRS */
#if HAS_RADIO_AMP
ao_config_aprs_ssid_set, ao_config_aprs_ssid_show },
{ "C <0 compressed, 1 uncompressed>\0APRS format",
ao_config_aprs_format_set, ao_config_aprs_format_show },
ao_config_aprs_ssid_set, ao_config_aprs_ssid_show },
{ "C <0 compressed, 1 uncompressed>\0APRS format",
ao_config_aprs_format_set, ao_config_aprs_format_show },
+ { "O <aprs-offset>\0APRS Offset from top of minute",
+ ao_config_aprs_offset_set, ao_config_aprs_offset_show },
#endif
#if HAS_FIXED_PAD_BOX
{ "B <box>\0Set pad box (1-99)",
#endif
#if HAS_FIXED_PAD_BOX
{ "B <box>\0Set pad box (1-99)",
#endif
#define AO_CONFIG_MAJOR 1
#endif
#define AO_CONFIG_MAJOR 1
-#define AO_CONFIG_MINOR 23
+#define AO_CONFIG_MINOR 24
uint8_t pad_box; /* minor version 22 */
uint8_t pad_idle; /* minor version 23 */
#endif
uint8_t pad_box; /* minor version 22 */
uint8_t pad_idle; /* minor version 23 */
#endif
+#if HAS_APRS
+ uint8_t aprs_offset; /* minor version 24 */
+#endif
};
#define AO_APRS_FORMAT_COMPRESSED 0
};
#define AO_APRS_FORMAT_COMPRESSED 0
+#if HAS_APRS
+static void
+ao_set_aprs_time(void)
+{
+ uint16_t interval = ao_config.aprs_interval;
+
+ if ((ao_gps_data.flags & AO_GPS_DATE_VALID) && interval != 0) {
+ int second = (ao_gps_data.second / interval + 1) * interval + ao_config.aprs_offset;
+ int delta;
+ if (second >= 60) {
+ second = ao_config.aprs_offset;
+ delta = second + 60 - ao_gps_data.second;
+ } else {
+ delta = second - ao_gps_data.second;
+ }
+ ao_aprs_time = ao_gps_tick + AO_SEC_TO_TICKS(delta);
+ } else {
+ ao_aprs_time += AO_SEC_TO_TICKS(ao_config.aprs_interval);
+ }
+}
+#endif
+
static void
ao_telemetry(void)
{
static void
ao_telemetry(void)
{
#endif
#if HAS_APRS
ao_aprs_time = time;
#endif
#if HAS_APRS
ao_aprs_time = time;
#endif
while (ao_telemetry_interval) {
time = ao_time() + AO_SEC_TO_TICKS(100);
#endif
while (ao_telemetry_interval) {
time = ao_time() + AO_SEC_TO_TICKS(100);
#if HAS_APRS
if (ao_config.aprs_interval != 0) {
if ((int16_t) (ao_time() - ao_aprs_time) >= 0) {
#if HAS_APRS
if (ao_config.aprs_interval != 0) {
if ((int16_t) (ao_time() - ao_aprs_time) >= 0) {
- ao_aprs_time = ao_time() + AO_SEC_TO_TICKS(ao_config.aprs_interval);
ao_aprs_send();
}
if ((int16_t) (time - ao_aprs_time) > 0)
ao_aprs_send();
}
if ((int16_t) (time - ao_aprs_time) > 0)