diff --git a/firmware/inc/gps.h b/firmware/inc/gps.h index 2c70a2d..1ade0d0 100644 --- a/firmware/inc/gps.h +++ b/firmware/inc/gps.h @@ -33,8 +33,10 @@ enum gps_error_t { GPS_ERROR_INVALID_FRAME, }; -void gps_update(void); -void gps_update_wait(void); +void gps_update_time(void); +void gps_update_position(void); +int gps_update_time_pending(void); +int gps_update_position_pending(void); struct ubx_nav_posllh gps_get_nav_posllh(); struct ubx_nav_sol gps_get_nav_sol(); diff --git a/firmware/inc/rtty.h b/firmware/inc/rtty.h index 600e323..5088927 100644 --- a/firmware/inc/rtty.h +++ b/firmware/inc/rtty.h @@ -25,8 +25,21 @@ #ifndef RTTY_H #define RTTY_H +#include "util/dbuffer.h" + +/** + * Output String + */ +#define RTTY_STRING_MAX 0x200 +/** + * It's actually a double buffer which we swap for mid-string updates + */ +ARRAY_DBUFFER_T(char, RTTY_STRING_MAX) rtty_dbuffer_string; + int rtty_active(void); -int rtty_set_string(char* string, uint32_t length); +int rtty_start(void); +int32_t rtty_get_index(void); +void rtty_set_length(int32_t length); void rtty_tick(void); #endif /* RTTY_H */ diff --git a/firmware/inc/telemetry.h b/firmware/inc/telemetry.h index 743c57d..27f3287 100644 --- a/firmware/inc/telemetry.h +++ b/firmware/inc/telemetry.h @@ -25,6 +25,6 @@ #ifndef TELEMETRY_H #define TELEMETRY_H -void set_telemetry_string(void); +uint16_t crc_checksum(char *string); #endif /* TELEMETRY_H */ diff --git a/firmware/src/gps.c b/firmware/src/gps.c index b51d08b..6f62760 100644 --- a/firmware/src/gps.c +++ b/firmware/src/gps.c @@ -281,24 +281,37 @@ void gps_disable_nmea(void) } /** - * Sends messages to the GPS to update the fields we want + * Sends messages to the GPS to update the time */ -void gps_update(void) +void gps_update_time(void) +{ + _ubx_send_message((ubx_message_t*)&ubx_nav_timeutc, NULL, 0); +}; +/** + * Sends messages to the GPS to update the position + */ +void gps_update_position(void) { _ubx_send_message((ubx_message_t*)&ubx_nav_posllh, NULL, 0); _ubx_send_message((ubx_message_t*)&ubx_nav_sol, NULL, 0); - _ubx_send_message((ubx_message_t*)&ubx_nav_timeutc, NULL, 0); - _ubx_send_message((ubx_message_t*)&ubx_nav_status, NULL, 0); + + // _ubx_send_message((ubx_message_t*)&ubx_nav_status, NULL, 0); } /** - * Waits for any pending updates from the GPS + * Indicates a pending time update from the GPS */ -void gps_update_wait(void) +int gps_update_time_pending(void) { - while (ubx_nav_posllh.state == UBX_PACKET_WAITING); - while (ubx_nav_sol.state == UBX_PACKET_WAITING); - while (ubx_nav_timeutc.state == UBX_PACKET_WAITING); - while (ubx_nav_status.state == UBX_PACKET_WAITING); + return (ubx_nav_timeutc.state == UBX_PACKET_WAITING); +} +/** + * Indicates a pending position update from the GPS + */ +int gps_update_position_pending(void) +{ + return (ubx_nav_posllh.state == UBX_PACKET_WAITING) || + (ubx_nav_sol.state == UBX_PACKET_WAITING); + //(ubx_nav_status.state == UBX_PACKET_WAITING); } /** * Return the latest received messages diff --git a/firmware/src/main.c b/firmware/src/main.c index 1290081..d25f2ca 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -34,15 +34,19 @@ #include "system/port.h" #include "tc/tc_driver.h" #include "gps.h" +#include "ubx_messages.h" #include "system/wdt.h" #include "timepulse.h" #include "telemetry.h" //#include "si406x.h" +#include "analogue.h" #include "si4060.h" #include "spi_bitbang.h" #include "rtty.h" #include "system/interrupt.h" +#define CALLSIGN "UBSEDSx" + void si4060_hw_init(void) { /* Configure the SDN pin */ @@ -177,6 +181,129 @@ void powermananger_init(void) PM_APBAMASK_RTC); /* RTC is unused */ } + +/** + * Telemetry String + * ============================================================================= + */ +void output_telemetry_string(void) +{ + double lat_fmt = 0.0; + double lon_fmt = 0.0; + uint32_t altitude = 0; + + /** + * Callsign, Time + * --------------------------------------------------------------------------- + */ + + /* GPS Time */ + gps_update_time(); + + /* Sleep Wait */ + while (gps_update_time_pending()) { + system_sleep(); + } + for (int i = 0; i < 100*1000; i++); + + /* Time */ + struct ubx_nav_timeutc time = gps_get_nav_timeutc(); + uint8_t hours = time.payload.hour; + uint8_t minutes = time.payload.min; + uint8_t seconds = time.payload.sec; + + /* init double buffers */ + ARRAY_DBUFFER_INIT(&rtty_dbuffer_string); + + /* sprintf - initial string */ + uint16_t len = sprintf(ARRAY_DBUFFER_WRITE_PTR(&rtty_dbuffer_string), + "$$UBSEDSx,%02u:%02u:%02u,", + hours, minutes, seconds); + + /* swap buffers */ + ARRAY_DBUFFER_SWAP(&rtty_dbuffer_string); + + /* start */ + rtty_start(); + + /** + * Position, Status, Analogue, Checksum + * --------------------------------------------------------------------------- + */ + + /* Analogue */ + float battery = get_battery(); + float temperature = si4060_get_temperature(); + + /* Sleep Wait */ + while (rtty_get_index() < (len - 4)) { + system_sleep(); + } + + /* Request updates from the gps */ + gps_update_position(); + if (gps_is_locked()) { + led_on(); + } else { + led_off(); + } + + /* Wait for the gps update. Move on if it's urgent */ + while (gps_update_position_pending() && rtty_get_index() < (len - 1)) { + system_sleep(); + } + + if (gps_is_locked()) { + led_off(); + } else { + led_on(); + } + + /* GPS Status */ + struct ubx_nav_sol sol = gps_get_nav_sol(); + uint8_t lock = sol.payload.gpsFix; + uint8_t satillite_count = sol.payload.numSV; + + /* GPS Position */ + if (lock == 0x2 || lock == 0x3 || lock == 0x4) { + struct ubx_nav_posllh pos = gps_get_nav_posllh(); + lat_fmt = (double)pos.payload.lat / 10000000.0; + lon_fmt = (double)pos.payload.lon / 10000000.0; + altitude = pos.payload.height / 1000; + } + + /* sprintf - full string */ + len = sprintf(ARRAY_DBUFFER_WRITE_PTR(&rtty_dbuffer_string), + "$$UBSEDSx,%02u:%02u:%02u,%02.6f,%03.6f,%ld,%u,%.2f,%.1f", + hours, minutes, seconds, lat_fmt, lon_fmt, altitude, + satillite_count, battery, temperature); + + /* sprintf - checksum */ + len += sprintf(ARRAY_DBUFFER_WRITE_PTR(&rtty_dbuffer_string) + len, + "*%04X\n", + crc_checksum(ARRAY_DBUFFER_WRITE_PTR(&rtty_dbuffer_string))); + + /* swap buffers */ + ARRAY_DBUFFER_SWAP(&rtty_dbuffer_string); + + /** + * End + * --------------------------------------------------------------------------- + */ + + /* Set the final length */ + rtty_set_length(len); + + /* Sleep Wait */ + while (rtty_active()) { + system_sleep(); + } +} + +/** + * MAIN + * ============================================================================= + */ int main(void) { /** @@ -200,7 +327,7 @@ int main(void) /* Configure Sleep Mode */ system_set_sleepmode(SYSTEM_SLEEPMODE_STANDBY); - system_set_sleepmode(SYSTEM_SLEEPMODE_IDLE_1); /* Disable CPU, AHB. APB still runs */ + system_set_sleepmode(SYSTEM_SLEEPMODE_IDLE_0); /* Disable CPU, AHB. APB still runs */ /* Configure the Power Manager */ powermananger_init(); @@ -239,36 +366,11 @@ int main(void) si4060_start_tx(0); while (1) { - /* Send the last packet */ - while (rtty_active()); - - port_pin_set_output_level(SI406X_GPIO0_PIN, 0); - /* Watchdog */ wdt_reset_count(); - gps_update(); /* Request updates from the gps */ - - if (gps_is_locked()) { - led_on(); - } else { - led_off(); - } - - gps_update_wait(); /* Wait for the gps update */ - - if (gps_is_locked()) { - led_off(); - } else { - led_on(); - } - /* Set the next packet */ - set_telemetry_string(); - - port_pin_set_output_level(SI406X_GPIO0_PIN, 1); - - system_sleep(); + output_telemetry_string(); } } diff --git a/firmware/src/rtty.c b/firmware/src/rtty.c index 5d88845..1e42b4c 100644 --- a/firmware/src/rtty.c +++ b/firmware/src/rtty.c @@ -25,6 +25,7 @@ #include #include "samd20.h" +#include "rtty.h" #include "hw_config.h" #include "system/port.h" @@ -42,11 +43,6 @@ #define ASCII_BITS 8 #define BITS_PER_CHAR 11 -/** - * Output String - */ -#define RTTY_STRING_MAX 0x200 - /** * Where we currently are in the rtty output byte * @@ -59,13 +55,12 @@ uint8_t rtty_phase; /** * Where we are in the current output string */ -uint32_t rtty_index; +int32_t rtty_index; /** * Details of the string that is currently being output */ -char rtty_string[RTTY_STRING_MAX]; -uint32_t rtty_string_length = 0; +int32_t rtty_string_length = 0; /** * Returns 1 if we're currently outputting. @@ -75,25 +70,35 @@ int rtty_active(void) { } /** - * Sets an output string. + * Starts RTTY output * - * Returns 0 on success, 1 if a string is already active or 2 if the - * specified string was too long. + * Returns 0 on success, 1 if already active */ -int rtty_set_string(char* string, uint32_t length) { - if (length > RTTY_STRING_MAX) return 2; // To long - +int rtty_start(void) { if (!rtty_active()) { - // Copy - memcpy(rtty_string, string, length); - rtty_string_length = length; - // Initialise + + /* Initialise */ + rtty_string_length = RTTY_STRING_MAX; rtty_index = 0; rtty_phase = 0; - return 0; // Success + return 0; /* Success */ } else { - return 1; // Already active + return 1; /* Already active */ + } +} +/** + * Returns the index of the current byte being outputted from the buffer + */ +int32_t rtty_get_index(void) { + return rtty_index; +} +/** + * Sets the final length of the RTTY string + */ +void rtty_set_length(int32_t length) { + if (length <= RTTY_STRING_MAX) { + rtty_string_length = length; } } @@ -110,7 +115,7 @@ void rtty_tick(void) { port_pin_set_output_level(SI406X_GPIO1_PIN, 1); } else if (rtty_phase < ASCII_BITS + 1) { // Data - if ((rtty_string[rtty_index] >> (rtty_phase - 1)) & 1) { + if ((ARRAY_DBUFFER_READ_PTR(&rtty_dbuffer_string)[rtty_index] >> (rtty_phase - 1)) & 1) { //RTTY_SET(1); port_pin_set_output_level(SI406X_GPIO1_PIN, 0); } else { diff --git a/firmware/src/telemetry.c b/firmware/src/telemetry.c index 4b7e242..189843a 100644 --- a/firmware/src/telemetry.c +++ b/firmware/src/telemetry.c @@ -26,16 +26,6 @@ #include #include "samd20.h" -#include "semihosting.h" -#include "analogue.h" -#include "gps.h" -#include "rtty.h" -#include "ubx_messages.h" -#include "si4060.h" - -//#define SEMIHOST_LOG - -char telemetry_string[0x200]; /** * CRC Function for the XMODEM protocol. @@ -77,53 +67,3 @@ uint16_t crc_checksum(char *string) return crc; } -/** - * Sets output telemetry - */ -void set_telemetry_string(void) -{ - double lat_fmt = 0.0; - double lon_fmt = 0.0; - uint32_t altitude = 0; - - /* Analogue */ - float battery = get_battery(); - float temperature = si4060_get_temperature(); - - /* Time */ - struct ubx_nav_timeutc time = gps_get_nav_timeutc(); - uint8_t hours = time.payload.hour; - uint8_t minutes = time.payload.min; - uint8_t seconds = time.payload.sec; - - /* GPS Status */ - struct ubx_nav_sol sol = gps_get_nav_sol(); - uint8_t lock = sol.payload.gpsFix; - uint8_t satillite_count = sol.payload.numSV; - - /* GPS Position */ - if (lock == 0x2 || lock == 0x3 || lock == 0x4) { - struct ubx_nav_posllh pos = gps_get_nav_posllh(); - lat_fmt = (double)pos.payload.lat / 10000000.0; - lon_fmt = (double)pos.payload.lon / 10000000.0; - altitude = pos.payload.height / 1000; - } - - -//#ifdef SEMIHOST_LOG -// semihost_printf("Batt %f, Temp %f\n", battery, temperature); -// semihost_printf("%02.7f,%03.7f,%ld\n", lat_fmt, lon_fmt, altitude); -// semihost_printf("Lock: %d Sats: %d\n", lock, satillite_count); -// semihost_printf("%02u:%02u:%02u\n", hours, minutes, seconds); -//#endif - - /* sprintf */ - uint16_t len = sprintf(telemetry_string, - "$$UBSEDSx,%02u:%02u:%02u,%02.6f,%03.6f,%ld,%u,%.2f,%.1f", - hours, minutes, seconds, lat_fmt, lon_fmt, altitude, - satillite_count, battery, temperature); - - sprintf(telemetry_string + len, "*%04X\n", crc_checksum(telemetry_string)); - - rtty_set_string(telemetry_string, strlen(telemetry_string)); -}