From f4ff561bfaa7c59493eb9d6b99f0347db381a167 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Mar 2020 17:26:49 -0800 Subject: [PATCH] altos: add APRS 'offset' value to set APRS transmision time 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 --- src/drivers/ao_gps_ublox.c | 9 +++++++-- src/kernel/ao_config.c | 24 ++++++++++++++++++++++++ src/kernel/ao_config.h | 5 ++++- src/kernel/ao_telemetry.c | 25 ++++++++++++++++++++++++- 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/drivers/ao_gps_ublox.c b/src/drivers/ao_gps_ublox.c index a6d93083..89b1c4d2 100644 --- a/src/drivers/ao_gps_ublox.c +++ b/src/drivers/ao_gps_ublox.c @@ -615,6 +615,8 @@ ao_gps(void) uint8_t class, id; struct ao_ublox_cksum cksum; uint8_t i; + AO_TICK_TYPE packet_start_tick; + AO_TICK_TYPE solution_tick = 0; ao_gps_setup(); @@ -645,6 +647,8 @@ ao_gps(void) /* 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; @@ -657,7 +661,7 @@ ao_gps(void) 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; @@ -679,6 +683,7 @@ ao_gps(void) 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) @@ -715,7 +720,7 @@ ao_gps(void) 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; diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c index 9f329f17..bd2e95ef 100644 --- a/src/kernel/ao_config.c +++ b/src/kernel/ao_config.c @@ -238,6 +238,10 @@ _ao_config_get(void) 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; @@ -760,6 +764,24 @@ ao_config_aprs_set(void) 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 @@ -1041,6 +1063,8 @@ const struct ao_config_var ao_config_vars[] = { 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 \0APRS Offset from top of minute", + ao_config_aprs_offset_set, ao_config_aprs_offset_show }, #endif #if HAS_FIXED_PAD_BOX { "B \0Set pad box (1-99)", diff --git a/src/kernel/ao_config.h b/src/kernel/ao_config.h index 41aafcca..7e8e62f3 100644 --- a/src/kernel/ao_config.h +++ b/src/kernel/ao_config.h @@ -58,7 +58,7 @@ #endif #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 23 +#define AO_CONFIG_MINOR 24 #define AO_AES_LEN 16 @@ -123,6 +123,9 @@ struct ao_config { 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 diff --git a/src/kernel/ao_telemetry.c b/src/kernel/ao_telemetry.c index 2092c84f..c2b2eb5a 100644 --- a/src/kernel/ao_telemetry.c +++ b/src/kernel/ao_telemetry.c @@ -443,6 +443,28 @@ ao_send_companion(void) } #endif +#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) { @@ -471,6 +493,7 @@ ao_telemetry(void) #endif #if HAS_APRS ao_aprs_time = time; + ao_set_aprs_time(); #endif while (ao_telemetry_interval) { time = ao_time() + AO_SEC_TO_TICKS(100); @@ -539,7 +562,7 @@ ao_telemetry(void) #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_set_aprs_time(); ao_aprs_send(); } if ((int16_t) (time - ao_aprs_time) > 0) -- 2.30.2