[New Feature] RTTY output is now double buffered, this allows GPS coordinates to be updated mid-packet

rocketry
Richard Eoin Meadows 2014-10-25 18:26:47 +01:00
rodzic fde2b2441a
commit 74fbfb30ad
7 zmienionych plików z 197 dodań i 122 usunięć

Wyświetl plik

@ -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();

Wyświetl plik

@ -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 */

Wyświetl plik

@ -25,6 +25,6 @@
#ifndef TELEMETRY_H
#define TELEMETRY_H
void set_telemetry_string(void);
uint16_t crc_checksum(char *string);
#endif /* TELEMETRY_H */

Wyświetl plik

@ -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

Wyświetl plik

@ -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();
}
}

Wyświetl plik

@ -25,6 +25,7 @@
#include <string.h>
#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 {

Wyświetl plik

@ -26,16 +26,6 @@
#include <string.h>
#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));
}