summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2015-03-02 21:02:31 -0800
committerKeith Packard <keithp@keithp.com>2015-03-02 21:02:31 -0800
commit2614d20b324ab215ef22f178e3635d48e757fa9b (patch)
treeb86b5592db95042b095b0991005785ae1064b7e6 /src
parent0724cc334a3bd8d81bbd4641d90a7e4040330efe (diff)
altos: Make APRS format (compressed/uncompressed) configurable
This provides a choice of compressed vs uncompressed when sending APRS packets to deal with receivers that still do not have support for the more useful compressed format. Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src')
-rw-r--r--src/drivers/ao_aprs.c98
-rw-r--r--src/kernel/ao_config.c23
-rw-r--r--src/kernel/ao_config.h9
3 files changed, 112 insertions, 18 deletions
diff --git a/src/drivers/ao_aprs.c b/src/drivers/ao_aprs.c
index 19beb78f..2e977612 100644
--- a/src/drivers/ao_aprs.c
+++ b/src/drivers/ao_aprs.c
@@ -707,8 +707,7 @@ static int tncPositionPacket(void)
static int32_t latitude;
static int32_t longitude;
static int32_t altitude;
- int32_t lat, lon, alt;
- uint8_t *buf;
+ uint8_t *buf;
if (ao_gps_data.flags & AO_GPS_VALID) {
latitude = ao_gps_data.latitude;
@@ -719,28 +718,93 @@ static int tncPositionPacket(void)
}
buf = tncBuffer;
- *buf++ = '!';
- /* Symbol table ID */
- *buf++ = '/';
+ switch (ao_config.aprs_format) {
+ case AO_APRS_FORMAT_COMPRESSED:
+ default:
+ {
+ int32_t lat, lon, alt;
+
+ *buf++ = '!';
+
+ /* Symbol table ID */
+ *buf++ = '/';
+
+ lat = ((uint64_t) 380926 * (900000000 - latitude)) / 10000000;
+ lon = ((uint64_t) 190463 * (1800000000 + longitude)) / 10000000;
+
+ alt = ao_aprs_encode_altitude(altitude);
+
+ tncCompressInt(buf, lat, 4);
+ buf += 4;
+ tncCompressInt(buf, lon, 4);
+ buf += 4;
- lat = ((uint64_t) 380926 * (900000000 - latitude)) / 10000000;
- lon = ((uint64_t) 190463 * (1800000000 + longitude)) / 10000000;
+ /* Symbol code */
+ *buf++ = '\'';
- alt = ao_aprs_encode_altitude(altitude);
+ tncCompressInt(buf, alt, 2);
+ buf += 2;
- tncCompressInt(buf, lat, 4);
- buf += 4;
- tncCompressInt(buf, lon, 4);
- buf += 4;
+ *buf++ = 33 + ((1 << 5) | (2 << 3));
- /* Symbol code */
- *buf++ = '\'';
+ break;
+ }
+ case AO_APRS_FORMAT_UNCOMPRESSED:
+ {
+ char lat_sign = 'N', lon_sign = 'E';
+ int32_t lat = latitude;
+ int32_t lon = longitude;
+ int32_t alt = altitude;
+ uint16_t lat_deg;
+ uint16_t lon_deg;
+ uint16_t lat_min;
+ uint16_t lat_frac;
+ uint16_t lon_min;
+ uint16_t lon_frac;
+
+ if (lat < 0) {
+ lat_sign = 'S';
+ lat = -lat;
+ }
- tncCompressInt(buf, alt, 2);
- buf += 2;
+ if (lon < 0) {
+ lon_sign = 'W';
+ lon = -lon;
+ }
- *buf++ = 33 + ((1 << 5) | (2 << 3));
+ /* Round latitude and longitude by 0.005 minutes */
+ lat = lat + 833;
+ if (lat > 900000000)
+ lat = 900000000;
+ lon = lon + 833;
+ if (lon > 1800000000)
+ lon = 1800000000;
+
+ lat_deg = lat / 10000000;
+ lat -= lat_deg * 10000000;
+ lat *= 60;
+ lat_min = lat / 10000000;
+ lat -= lat_min * 10000000;
+ lat_frac = lat / 100000;
+
+ lon_deg = lon / 10000000;
+ lon -= lon_deg * 10000000;
+ lon *= 60;
+ lon_min = lon / 10000000;
+ lon -= lon_min * 10000000;
+ lon_frac = lon / 100000;
+
+ /* Convert from meters to feet */
+ alt = (alt * 328 + 50) / 100;
+
+ buf += sprintf((char *) tncBuffer, "!%02u%02u.%02u%c/%03u%02u.%02u%c'/A=%06u ",
+ lat_deg, lat_min, lat_frac, lat_sign,
+ lon_deg, lon_min, lon_frac, lon_sign,
+ alt);
+ break;
+ }
+ }
buf += tncComment(buf);
diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c
index 8dab7c42..b0d3e541 100644
--- a/src/kernel/ao_config.c
+++ b/src/kernel/ao_config.c
@@ -220,6 +220,10 @@ _ao_config_get(void)
if (minor < 21)
ao_config.send_frequency = 434550;
#endif
+#if HAS_APRS
+ if (minor < 22)
+ ao_config.aprs_format = AO_CONFIG_DEFAULT_APRS_FORMAT;
+#endif
ao_config.minor = AO_CONFIG_MINOR;
ao_config_dirty = 1;
}
@@ -876,6 +880,23 @@ ao_config_aprs_ssid_set(void)
ao_config.aprs_ssid = ao_cmd_lex_i;
_ao_config_edit_finish();
}
+
+void
+ao_config_aprs_format_set(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ _ao_config_edit_start();
+ ao_config.aprs_format = ao_cmd_lex_i != 0;
+ _ao_config_edit_finish();
+}
+
+void
+ao_config_aprs_format_show(void)
+{
+ printf ("APRS format: %d\n", ao_config.aprs_format);
+}
#endif /* HAS_APRS */
struct ao_config_var {
@@ -969,6 +990,8 @@ __code struct ao_config_var ao_config_vars[] = {
#if HAS_APRS
{ "S <ssid>\0Set APRS SSID (0-15)",
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 },
#endif
{ "s\0Show",
ao_config_show, 0 },
diff --git a/src/kernel/ao_config.h b/src/kernel/ao_config.h
index 164584a5..cfe8555c 100644
--- a/src/kernel/ao_config.h
+++ b/src/kernel/ao_config.h
@@ -57,7 +57,7 @@
#endif
#define AO_CONFIG_MAJOR 1
-#define AO_CONFIG_MINOR 21
+#define AO_CONFIG_MINOR 22
#define AO_AES_LEN 16
@@ -115,8 +115,15 @@ struct ao_config {
#if HAS_RADIO_FORWARD
uint32_t send_frequency; /* minor version 21 */
#endif
+#if HAS_APRS
+ uint8_t aprs_format; /* minor version 22 */
+#endif
};
+#define AO_APRS_FORMAT_COMPRESSED 0
+#define AO_APRS_FORMAT_UNCOMPRESSED 1
+#define AO_CONFIG_DEFAULT_APRS_FORMAT AO_APRS_FORMAT_COMPRESSED
+
#if HAS_RADIO_FORWARD
extern __xdata uint32_t ao_send_radio_setting;
#endif