kopia lustrzana https://github.com/bristol-seds/pico-tracker
[New Feature] RTTY output is now double buffered, this allows GPS coordinates to be updated mid-packet
rodzic
fde2b2441a
commit
74fbfb30ad
|
@ -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();
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -25,6 +25,6 @@
|
|||
#ifndef TELEMETRY_H
|
||||
#define TELEMETRY_H
|
||||
|
||||
void set_telemetry_string(void);
|
||||
uint16_t crc_checksum(char *string);
|
||||
|
||||
#endif /* TELEMETRY_H */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue