From 532e4847be6c63bc798f283c21c0ae8c68a4cc49 Mon Sep 17 00:00:00 2001 From: Richard Meadows Date: Tue, 12 May 2015 21:51:26 +0100 Subject: [PATCH] Added aprs variable frequency, location functions for aprs --- firmware/inc/hw_config.h | 1 + firmware/inc/location.h | 6 ++++ firmware/inc/telemetry.h | 1 + firmware/src/location.c | 66 +++++++++++++++++++++++++++-------- firmware/src/main.c | 75 +++++++++++++++++++++++++++++++++------- firmware/src/telemetry.c | 22 ++++++++++-- firmware/src/timer.c | 13 ++----- 7 files changed, 143 insertions(+), 41 deletions(-) diff --git a/firmware/inc/hw_config.h b/firmware/inc/hw_config.h index 681e91f..eb1065d 100644 --- a/firmware/inc/hw_config.h +++ b/firmware/inc/hw_config.h @@ -130,6 +130,7 @@ */ #define TELEMETRY_FREQUENCY 434600000 #define TELEMETRY_INTERVAL 30 +#define APRS_INTERVAL 180 /** * Watchdog Timer diff --git a/firmware/inc/location.h b/firmware/inc/location.h index f8133e0..9522c62 100644 --- a/firmware/inc/location.h +++ b/firmware/inc/location.h @@ -25,7 +25,13 @@ #ifndef LOCATION_H #define LOCATION_H +#include bool latlon_in_aprs_zone(int32_t aprs_zone, int32_t aprs_zone_outline, float lon, float lat); +bool aprs_location_tx_allow(void); +int32_t aprs_location_frequency(void); + +void aprs_location_update(float lon, float lat); + #endif /* LOCATION_H */ diff --git a/firmware/inc/telemetry.h b/firmware/inc/telemetry.h index be8bafa..0161be6 100644 --- a/firmware/inc/telemetry.h +++ b/firmware/inc/telemetry.h @@ -47,6 +47,7 @@ char telemetry_string[TELEMETRY_STRING_MAX]; int telemetry_active(void); int telemetry_start(enum telemetry_t type, int32_t length); int telemetry_start_rsid(rsid_code_t rsid); +void telemetry_aprs_set_frequency(int32_t frequency); void telemetry_stop(void); float telemetry_si_temperature(void); diff --git a/firmware/src/location.c b/firmware/src/location.c index 05faa18..c89761b 100644 --- a/firmware/src/location.c +++ b/firmware/src/location.c @@ -29,6 +29,7 @@ #include "samd20.h" #include "geofence_aprs.h" +int32_t current_aprs_zone = -2, current_aprs_zone_outline = -2; #define polyX(i) (poly[(i*2)+0]) #define polyY(i) (poly[(i*2)+1]) @@ -47,7 +48,7 @@ * Note that division by zero is avoided because the division is * protected by the "if" clause which surrounds it. */ -bool point_in_polygon(int32_t* poly, uint32_t points, int32_t x, int32_t y) { +bool point_in_polygon(const int32_t* poly, uint32_t points, int32_t x, int32_t y) { uint32_t i, j = points-1; bool oddNodes = false; @@ -70,7 +71,7 @@ bool point_in_polygon(int32_t* poly, uint32_t points, int32_t x, int32_t y) { /** * Returns if a latitude and longitude is in a polygon */ -bool latlon_in_polygon(int32_t* poly, uint32_t points, float lon, float lat) { +bool latlon_in_polygon(const int32_t* poly, uint32_t points, float lon, float lat) { int32_t x = (int32_t)round(lon * 1000 * 1000); // longitude: µdegrees int32_t y = (int32_t)round(lat * 1000 * 1000); // latitude: µdegrees @@ -80,8 +81,6 @@ bool latlon_in_polygon(int32_t* poly, uint32_t points, float lon, float lat) { -int32_t current_aprs_zone, current_aprs_zone_outline; - /** * Returns if a latitude and longitude is in a given aprs zone outline */ @@ -92,27 +91,64 @@ bool latlon_in_aprs_zone(int32_t aprs_zone, int32_t aprs_zone_outline, float lon lon, lat); } + +/** + * Returns if aprs should be transmitted in the current zone + */ +bool aprs_location_tx_allow(void) { + + /* Not in any zone, or in a zone other than Alpha */ + return (current_aprs_zone == -1) || (current_aprs_zone > 0); +} +/** + * Returns the aprs frequency in the current zone. + * + * Where aprs is not allowed this function is unspecified + */ +int32_t aprs_location_frequency(void) { + + if (current_aprs_zone >= 0) { + return aprs_zones[current_aprs_zone].frequency; + } + + return 144800000; +} + + /** * Updates the aprs location based on the current lat/lon */ -void update_aprs_location(float lon, float lat) { +void aprs_location_update(float lon, float lat) { + + uint32_t z, outline; /* Were we in an aprs zone last time? */ + if (current_aprs_zone >= 0 && current_aprs_zone_outline >= 0) { - - if (0) { - - /* Are we still in the same outline? */ - - if (1) { /* Still in outline */ + /* Are we still in the outline? */ + if (latlon_in_aprs_zone(current_aprs_zone, + current_aprs_zone_outline, + lon, lat)) { /* Still in outline */ return; } } /* Find which aprs zone we are in and save it */ -} + for (z = 0; z < 12; z++) { /* For each zone */ -void aprs_location_init(float lon, float lat) { - current_aprs_zone = -1; current_aprs_zone_outline = -1; - update_aprs_location(lon, lat); + for (outline = 0; outline < sizeof(aprs_zones[z].outline_lengths); outline++) { + + if (latlon_in_aprs_zone(z, outline, lon, lat)) { /* If we're in this zone */ + + /* Record the current zone */ + current_aprs_zone = z; + current_aprs_zone_outline = outline; + + return; /* Go home. We return the first zone we match */ + } + } + } + + /* We're not in a zone */ + current_aprs_zone = -1; } diff --git a/firmware/src/main.c b/firmware/src/main.c index d638d3d..8884df2 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -44,6 +44,8 @@ #include "timer.h" #include "contestia.h" #include "rsid.h" +#include "aprs.h" +#include "location.h" #include "si_trx.h" #include "si_trx_defs.h" #include "analogue.h" @@ -236,9 +238,35 @@ void output_telemetry_string(enum telemetry_t type) while (telemetry_active()) { system_sleep(); } +} - /* Pips */ - telemetry_start(TELEMETRY_PIPS, 0xFFFF); +void aprs_telemetry(void) { + + if (!gps_is_locked()) return; /* Don't bother with no GPS */ + + struct ubx_nav_posllh pos = gps_get_nav_posllh(); + float lat = (float)pos.payload.lat / 10000000.0; + float lon = (float)pos.payload.lon / 10000000.0; + uint32_t altitude = pos.payload.height / 1000; + + /* Update location */ + aprs_location_update(lon, lat); + + /* aprs okay here? */ + if (aprs_location_tx_allow()) { + + /* Set location */ + aprs_set_location(lat, lon, altitude); + + /* Set frequency */ + telemetry_aprs_set_frequency(aprs_location_frequency()); + + /* Transmit packet and wait */ + telemetry_start(TELEMETRY_APRS, 0xFFFF); + while (telemetry_active()) { + system_sleep(); + } + } } /** @@ -304,10 +332,30 @@ void xosc_measure_callback(uint32_t result) _xosc_error = result - XOSC_FREQUENCY; } +uint32_t telemetry_interval_count = TELEMETRY_INTERVAL; +uint32_t aprs_interval_count = 0; uint8_t telemetry_trigger_flag = 0; +uint8_t aprs_trigger_flag = 0; + +/** + * Called by the timer at 1Hz + */ void timepulse_callback(uint32_t sequence) { - telemetry_trigger_flag = 1; + telemetry_interval_count++; + aprs_interval_count++; + + /* Runs at the rate of telemetry packets */ + if (telemetry_interval_count >= TELEMETRY_INTERVAL) { + telemetry_interval_count = 0; + telemetry_trigger_flag = 1; + } + + /* Runs at the rate of aprs packets */ + if (aprs_interval_count >= APRS_INTERVAL) { + aprs_interval_count = 0; + aprs_trigger_flag = 1; + } } /** @@ -323,16 +371,6 @@ int main(void) led_on(); - /* while (1) { */ - /* telemetry_start(TELEMETRY_APRS, 0xFFFF); */ - - /* while (telemetry_active()) { */ - /* system_sleep(); */ - /* } */ - - /* for (int i = 0; i < 1000*1000; i++); */ - /* } */ - while (1) { /* Sleep wait for next telemetry */ @@ -355,6 +393,17 @@ int main(void) TELEMETRY_CONTESTIA : TELEMETRY_RTTY); + + /* Maybe aprs? */ + if (aprs_trigger_flag) { + aprs_telemetry(); + } + aprs_trigger_flag = 0; + + + /* Pips */ + telemetry_start(TELEMETRY_PIPS, 0xFFFF); + /* Measure XOSC against gps timepulse */ measure_xosc(XOSC_MEASURE_TIMEPULSE, xosc_measure_callback); } diff --git a/firmware/src/telemetry.c b/firmware/src/telemetry.c index 54e18f9..3f6585e 100644 --- a/firmware/src/telemetry.c +++ b/firmware/src/telemetry.c @@ -118,7 +118,10 @@ uint8_t radio_on = 0; * Temperature */ float _si_temperature = 128.0; - +/** + * APRS frequency + */ +int32_t _aprs_frequency = 0; /** * Returns 1 if we're currently outputting. @@ -187,6 +190,13 @@ int telemetry_start_rsid(rsid_code_t rsid) { return 1; /* Already active */ } } +/** + * Setter for the APRS frequency + */ +void telemetry_aprs_set_frequency(int32_t frequency) { + _aprs_frequency = frequency; +} + /** * Stops the ongoing telemetry at the earliest possible moment (end of * symbol / block). @@ -310,8 +320,14 @@ void telemetry_tick(void) { /* APRS: We use pwm to control gpio1 */ aprs_start(); - si_trx_on(SI_MODEM_MOD_TYPE_2GFSK, 144888000, 400); - radio_on = 1; +// if (_aprs_frequency) { TODO configurable frequency +// si_trx_on(SI_MODEM_MOD_TYPE_2GFSK, _aprs_frequency, 400); +// radio_on = 1; +// } + + si_trx_on(SI_MODEM_MOD_TYPE_2GFSK, 144800000, 400); + radio_on = 1; + } if (!aprs_tick()) { diff --git a/firmware/src/timer.c b/firmware/src/timer.c index c0dd7b2..67d7252 100644 --- a/firmware/src/timer.c +++ b/firmware/src/timer.c @@ -32,7 +32,6 @@ #include "system/interrupt.h" uint32_t gps_timepulse_count = 0; -uint32_t telemetry_interval_count = TELEMETRY_INTERVAL; uint32_t timepulse_sequence = 0; timepulse_callback_t _timer_callback; @@ -89,15 +88,9 @@ void EIC_Handler(void) { if (gps_timepulse_count >= GPS_TIMEPULSE_FREQ) { gps_timepulse_count = 0; - telemetry_interval_count++; - /* Runs at the rate of telemetry packets */ - if (telemetry_interval_count >= TELEMETRY_INTERVAL) { - telemetry_interval_count = 0; - - /* Make the callback if we have one */ - if (_timer_callback) { - _timer_callback(timepulse_sequence++); - } + /* Make the callback if we have one */ + if (_timer_callback) { + _timer_callback(timepulse_sequence++); } } }