altos: add APRS 'offset' value to set APRS transmision time
authorKeith Packard <keithp@keithp.com>
Thu, 5 Mar 2020 01:26:49 +0000 (17:26 -0800)
committerKeith Packard <keithp@keithp.com>
Thu, 5 Mar 2020 02:53:05 +0000 (18:53 -0800)
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>
src/drivers/ao_gps_ublox.c
src/kernel/ao_config.c
src/kernel/ao_config.h
src/kernel/ao_telemetry.c

index a6d930835baed49a70d619073b84349242b0a806..89b1c4d2c2da20374b30e4bdc3a34f58db0c6af3 100644 (file)
@@ -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;
index 9f329f17554b57e1271e94f788b51ccc3761c2f5..bd2e95ef6a56f1feeb260beb410f527482f092a8 100644 (file)
@@ -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 <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)",
index 41aafcca8cb5ae4151920bf7aeec34f6b514de0e..7e8e62f31a5ff6652588d6cb61b872f5c102de13 100644 (file)
@@ -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
index 2092c84f403cd65606eeb78078a3d64d7f689ab6..c2b2eb5a1bad0569d909481c21caf20773269457 100644 (file)
@@ -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)