Brought up gps on new hw, various bugfix, pre-calculate telemetry timer counts and more

master
Richard Meadows 2015-07-03 23:40:47 +01:00
rodzic b65216498d
commit 08e3d30c25
16 zmienionych plików z 247 dodań i 170 usunięć

Wyświetl plik

@ -8,12 +8,12 @@
||gclk7|aprs clock, fed from gclk1, div 6 / 11 ||gclk7|aprs clock, fed from gclk1, div 6 / 11
| |
|*TC*|| |*TC*||
||tc0|telemetry tick timer. 32-bit ||tc0|telemetry tick timer. 32-bit. glck1
||tc1|^^^^^ ||tc1|^^^^^
||tc2|counts cycles of tcxo. 32-bit ||tc2|counts cycles of tcxo. 32-bit. gclk1
||tc3|^^^^^ ||tc3|^^^^^
||tc4|osc8m event source ||tc4|unused (osc8m event source)
||tc5|telemetry pwm 16-bit, ALSO aprs carrier 16-bit ||tc5|telemetry pwm 16-bit glck0, ALSO aprs carrier 16-bit gclk7
| |
|*EXTINT*| |*EXTINT*|
||extint[5]|gps timepulse ||extint[5]|gps timepulse
@ -32,11 +32,11 @@
| Name | Function | Priority H(0-3)L | Notes | Name | Function | Priority H(0-3)L | Notes
| --- | --- | --- | --- | --- | --- | --- | ---
|TC0_IRQn|telemetry tick timer|0|latency critical for symbol timing. rate <= 1200Hz |TC0_IRQn|telemetry tick timer|1|latency critical for symbol timing. rate <= 1200Hz
|[GPS_SERCOM]_IRQn|gps usart rx|1|latency not so critical. rate <= 960Hz |[GPS_SERCOM]_IRQn|gps usart rx|2|latency not so critical. rate <= 960Hz
|EIC_IRQn|timepulse|2|latency not so critical. rate = 1 |EIC_IRQn|timepulse|3|latency not so critical. rate = 1
|TC2_IRQn|xosc measurement done|2|latency not critical |TC2_IRQn|xosc measurement done|3|latency not critical
|ADC_IRQn|adc measurement done|2|latency not critical |ADC_IRQn|adc measurement done|3|latency not critical

Wyświetl plik

@ -66,6 +66,7 @@
#define GPS_SERCOM_MIGO_PIN PIN_PA07 #define GPS_SERCOM_MIGO_PIN PIN_PA07
#define GPS_SERCOM_MIGO_PINMUX PINMUX_PA07D_SERCOM0_PAD3 #define GPS_SERCOM_MIGO_PINMUX PINMUX_PA07D_SERCOM0_PAD3
#define GPS_SERCOM_MUX USART_RX_3_TX_2_XCK_3 #define GPS_SERCOM_MUX USART_RX_3_TX_2_XCK_3
#define GPS_BAUD_RATE 9600
#define GPS_PLATFORM_MODEL UBX_PLATFORM_MODEL_AIRBORNE_1G #define GPS_PLATFORM_MODEL UBX_PLATFORM_MODEL_AIRBORNE_1G
#define GPS_TIMEPULSE_PIN PIN_PA05 #define GPS_TIMEPULSE_PIN PIN_PA05
#define GPS_TIMEPULSE_PINMUX PINMUX_PA05A_EIC_EXTINT5 #define GPS_TIMEPULSE_PINMUX PINMUX_PA05A_EIC_EXTINT5
@ -75,7 +76,7 @@
/** /**
* USART Loopback Testing * USART Loopback Testing
*/ */
#define USART_MUX_LOOPBACK USART_RX_0_TX_0_XCK_1 #define USART_MUX_LOOPBACK USART_RX_2_TX_2_XCK_3
/** /**
* Flash Memory * Flash Memory
@ -185,14 +186,16 @@
/** /**
* Interrupt Priority * Interrupt Priority
*/ */
#define TC0_INT_PRIO 0 /* Telemetry Tick Timer */ #define WDT_INT_PRIO 0 /* Early warning interrupt */
#define GPS_SERCOM_INT_PRIO 1 /* GPS USART Rx */ #define TC0_INT_PRIO 1 /* Telemetry Tick Timer */
#define EIC_INT_PRIO 2 /* Timepulse, telemetry */ #define GPS_SERCOM_INT_PRIO 2 /* GPS USART Rx */
#define TC2_INT_PRIO 2 /* XOSC Measure Timer */ #define EIC_INT_PRIO 3 /* Timepulse, telemetry */
#define ADC_INT_PRIO 2 /* ADC */ #define TC2_INT_PRIO 3 /* XOSC Measure Timer */
#define ADC_INT_PRIO 3 /* ADC */
#endif /* HW_CONFIG_H */ #endif /* HW_CONFIG_H */

Wyświetl plik

@ -50,15 +50,12 @@ int telemetry_start_rsid(rsid_code_t rsid);
void telemetry_aprs_set_frequency(int32_t frequency); void telemetry_aprs_set_frequency(int32_t frequency);
float telemetry_si_temperature(void); float telemetry_si_temperature(void);
float timer0_tick_init(float frequency); void timer0_tick_init(uint32_t count);
uint32_t timer0_tick_frequency(float frequency);
void timer0_tick_deinit(); void timer0_tick_deinit();
void telemetry_init();
void telemetry_gpio1_pwm_init(void); void telemetry_gpio1_pwm_init(void);
void telemetry_gpio1_pwm_duty(float duty_cycle); void telemetry_gpio1_pwm_duty(float duty_cycle);
void telemetry_gpio1_pwm_deinit(void); void telemetry_gpio1_pwm_deinit(void);
void telemetry_gpio1_init(void);
void telemetry_gpio1_set(uint8_t value);
#endif /* TELEMETRY_H */ #endif /* TELEMETRY_H */

Wyświetl plik

@ -52,6 +52,7 @@ struct idle_counter {
uint32_t wait_for_next_telemetry; uint32_t wait_for_next_telemetry;
}; };
void kick_the_watchdog(void);
void idle(idle_wait_t idle_t); void idle(idle_wait_t idle_t);
void watchdog_init(void); void watchdog_init(void);

Wyświetl plik

@ -197,11 +197,6 @@ uint8_t aprs_start(void)
telemetry telemetry
); );
// RTTY/434.6U8N2",
/* Let's actually try that out.. We can add comment etc. later */
/* Transmit the frame using ax25 */ /* Transmit the frame using ax25 */
ax25_start(addresses, addresses_len, ax25_start(addresses, addresses_len,
information, information_len); information, information_len);

Wyświetl plik

@ -40,7 +40,8 @@ struct tracker_time time = {0};
struct tracker_datapoint* dp; struct tracker_datapoint* dp;
/* Low Power Mode */ /* Low Power Mode */
#define LOW_POWER(d) (d->solar < 0.2) #define LOW_POWER(d) (0)
//(d->solar < 0.2)
void rtty_telemetry(struct tracker_datapoint* dp); void rtty_telemetry(struct tracker_datapoint* dp);
void contestia_telemetry(struct tracker_datapoint* dp); void contestia_telemetry(struct tracker_datapoint* dp);
@ -86,26 +87,26 @@ void do_cron(void)
memcpy(&t, &time, sizeof(struct tracker_time)); memcpy(&t, &time, sizeof(struct tracker_time));
/* ---- Data every 30 seconds ---- */ /* ---- Data every 30 seconds ---- */
if ((time.second % 30) == 0) { if ((t.second % 30) == 0) {
dp = collect_data(); dp = collect_data();
memcpy(&dp->time, &t, sizeof(struct tracker_time)); memcpy(&dp->time, &time, sizeof(struct tracker_time));
} else if ((time.second % 30) == 20) { } else if ((t.second % 30) == 20) {
collect_data_async(); collect_data_async();
} }
/* ---- Telemetry output ---- */ /* ---- Telemetry output ---- */
/* RTTY */ /* RTTY */
if (time.second == 0 && !LOW_POWER(dp)) { if (t.second == 0 && !LOW_POWER(dp)) {
rtty_telemetry(dp); rtty_telemetry(dp);
/* Contestia */ /* Contestia */
} else if (time.second == 30 && !LOW_POWER(dp)) { } else if (t.second == 30 && !LOW_POWER(dp)) {
contestia_telemetry(dp); contestia_telemetry(dp);
/* Low Power */ /* Low Power */
} else if (time.second == 0 && LOW_POWER(dp)) { } else if (t.second == 0 && LOW_POWER(dp)) {
if ((time.minute % 2) == 0) { if ((t.minute % 2) == 0) {
rtty_telemetry(dp); rtty_telemetry(dp);
} else { } else {
contestia_telemetry(dp); contestia_telemetry(dp);
@ -113,18 +114,18 @@ void do_cron(void)
/* APRS */ /* APRS */
#ifdef APRS_ENABLE #ifdef APRS_ENABLE
} else if ((time.minute % 2) == 0 && time.second == 55) { } else if ((t.minute % 2) == 0 && t.second == 55) {
aprs_telemetry(dp); aprs_telemetry(dp);
#endif #endif
/* Pips */ /* Pips */
} else if ((time.second % 1) == 0) { } else if ((t.second % 1) == 0) {
pips_telemetry(); pips_telemetry();
} }
/* ---- Record for backlog ---- */ /* ---- Record for backlog ---- */
if ((time.minute == 0) && (time.second == 25)) { if ((t.minute % 1 == 0) && (t.second == 25)) {
record_backlog(dp); record_backlog(dp);
} }
} }
@ -136,11 +137,11 @@ void cron_tick(void) {
/* Update time internally */ /* Update time internally */
time.epoch++; time.second++; time.epoch++; time.second++;
if (time.second > 60) { if (time.second >= 60) {
time.second = 0; time.minute++; time.second = 0; time.minute++;
if (time.minute > 60) { if (time.minute >= 60) {
time.minute = 0; time.hour++; time.minute = 0; time.hour++;
if (time.hour > 23) { if (time.hour >= 24) {
time.hour = 0; time.hour = 0;
} }
} }
@ -151,7 +152,7 @@ void cron_tick(void) {
if (((time.hour == 0) && (time.minute == 0) && (time.second == 5)) || if (((time.hour == 0) && (time.minute == 0) && (time.second == 5)) ||
((time.second == 5) && !(time.valid & UBX_TIMEUTC_VALID_UTC))) { ((time.second == 5) && !(time.valid & UBX_TIMEUTC_VALID_UTC))) {
/* Be careful not a call this while the collect_data function is running */ /* Be careful not to call this while the collect_data function is running */
read_gps_time(); read_gps_time();
} }
} }

Wyświetl plik

@ -49,6 +49,9 @@ void collect_data_async(void)
{ {
/* Measure XOSC against gps timepulse */ /* Measure XOSC against gps timepulse */
measure_xosc(XOSC_MEASURE_TIMEPULSE, xosc_measure_callback); measure_xosc(XOSC_MEASURE_TIMEPULSE, xosc_measure_callback);
/* Analogue Measurements */
start_adc_conversion_sequence();
} }
/** /**
* Collect Data synchronously and return datapoint * Collect Data synchronously and return datapoint

Wyświetl plik

@ -35,6 +35,7 @@
#include "util/dbuffer.h" #include "util/dbuffer.h"
#include "ubx_messages.h" #include "ubx_messages.h"
#include "gps.h" #include "gps.h"
#include "watchdog.h"
/** /**
* UBX Constants * UBX Constants
@ -264,13 +265,13 @@ void _ubx_poll(ubx_message_t* message) {
/** /**
* Disable NMEA messages on the uBlox * Disable NMEA messages on the uBlox
*/ */
void gps_disable_nmea(void) void gps_set_io_config(uint32_t baud_rate)
{ {
ubx_cfg_prt.payload.portID = 1; ubx_cfg_prt.payload.portID = 1;
ubx_cfg_prt.payload.res0 = 0; ubx_cfg_prt.payload.res0 = 0;
ubx_cfg_prt.payload.txReady = 0; ubx_cfg_prt.payload.txReady = 0;
ubx_cfg_prt.payload.mode = 0x08D0; /* 8 bit, No Parity */ ubx_cfg_prt.payload.mode = 0x08D0; /* 8 bit, No Parity */
ubx_cfg_prt.payload.baudRate = 9600; ubx_cfg_prt.payload.baudRate = baud_rate;
ubx_cfg_prt.payload.inProtoMask = 0x7; /* UBX */ ubx_cfg_prt.payload.inProtoMask = 0x7; /* UBX */
ubx_cfg_prt.payload.outProtoMask = 0x1; /* UBX */ ubx_cfg_prt.payload.outProtoMask = 0x1; /* UBX */
ubx_cfg_prt.payload.flags = 0; ubx_cfg_prt.payload.flags = 0;
@ -450,9 +451,9 @@ void gps_set_powersave_auto(void)
} }
/** /**
* Init * Init + enable for the usart at the given baud rate
*/ */
void gps_init(void) void gps_usart_init_enable(uint32_t baud_rate)
{ {
/* USART */ /* USART */
usart_init(GPS_SERCOM, usart_init(GPS_SERCOM,
@ -468,7 +469,7 @@ void gps_init(void)
false, /** Enable LIN Slave Support */ false, /** Enable LIN Slave Support */
false, /** Enable start of frame dection */ false, /** Enable start of frame dection */
false, /** Enable collision dection */ false, /** Enable collision dection */
9600, /** USART Baud rate */ baud_rate, /** USART Baud rate */
true, /** Enable receiver */ true, /** Enable receiver */
true, /** Enable transmitter */ true, /** Enable transmitter */
false, /** Sample on the rising edge of XLCK */ false, /** Sample on the rising edge of XLCK */
@ -483,19 +484,34 @@ void gps_init(void)
PINMUX_UNUSED); /** PAD3 pinmux */ PINMUX_UNUSED); /** PAD3 pinmux */
usart_enable(GPS_SERCOM); usart_enable(GPS_SERCOM);
}
/**
* Init
*/
void gps_init(void)
{
/* Enable usart */
gps_usart_init_enable(GPS_BAUD_RATE);
kick_the_watchdog();
/* We use ubx protocol */ /* We use ubx protocol */
gps_disable_nmea(); gps_set_io_config(GPS_BAUD_RATE);
/* Incoming ubx messages are handled in an irq */ /* Incoming ubx messages are handled in an irq */
usart_register_rx_callback(GPS_SERCOM, gps_rx_callback, GPS_SERCOM_INT_PRIO); usart_register_rx_callback(GPS_SERCOM, gps_rx_callback, GPS_SERCOM_INT_PRIO);
kick_the_watchdog();
/* Set the platform model */ /* Set the platform model */
gps_set_platform_model(); gps_set_platform_model();
/* Set which GNSS constellation we'd like to use */ /* Set which GNSS constellation we'd like to use */
gps_set_gnss(); gps_set_gnss();
kick_the_watchdog();
/* Exit powersave mode to start */ /* Exit powersave mode to start */
gps_set_powersave(false); gps_set_powersave(false);
@ -524,7 +540,7 @@ void usart_loopback_test(void)
false, /** Enable LIN Slave Support */ false, /** Enable LIN Slave Support */
false, /** Enable start of frame dection */ false, /** Enable start of frame dection */
false, /** Enable collision dection */ false, /** Enable collision dection */
9600, /** USART Baud rate */ GPS_BAUD_RATE, /** USART Baud rate */
true, /** Enable receiver */ true, /** Enable receiver */
true, /** Enable transmitter */ true, /** Enable transmitter */
false, /** Sample on the rising edge of XLCK */ false, /** Sample on the rising edge of XLCK */
@ -532,8 +548,8 @@ void usart_loopback_test(void)
0, /** External clock frequency in synchronous mode. */ 0, /** External clock frequency in synchronous mode. */
false, /** Run in standby */ false, /** Run in standby */
GCLK_GENERATOR_0, /** GCLK generator source */ GCLK_GENERATOR_0, /** GCLK generator source */
PINMUX_DEFAULT, /** PAD0 pinmux */ GPS_SERCOM_MOGI_PINMUX, /** PAD0 pinmux */
PINMUX_DEFAULT, /** PAD1 pinmux */ GPS_SERCOM_MIGO_PINMUX, /** PAD1 pinmux */
PINMUX_UNUSED, /** PAD2 pinmux */ PINMUX_UNUSED, /** PAD2 pinmux */
PINMUX_UNUSED); /** PAD3 pinmux */ PINMUX_UNUSED); /** PAD3 pinmux */
@ -542,5 +558,5 @@ void usart_loopback_test(void)
usart_write_wait(GPS_SERCOM, 0x34); usart_write_wait(GPS_SERCOM, 0x34);
usart_read_wait(GPS_SERCOM, &data); usart_read_wait(GPS_SERCOM, &data);
semihost_printf("Rx'ed: 0x%02x\n", data); usart_disable(GPS_SERCOM);
} }

Wyświetl plik

@ -73,14 +73,6 @@ void init(timepulse_callback_t callback)
led_reset(); led_reset();
si_trx_shutdown(); si_trx_shutdown();
/* If the reset was caused by the internal watchdog... */
if (PM->RCAUSE.reg & PM_RCAUSE_WDT) {
/* External hardware is in an undefined state. Wait here for the
external watchdog to trigger an external reset */
while (1);
}
/** /**
* Internal initialisation * Internal initialisation
* --------------------------------------------------------------------------- * ---------------------------------------------------------------------------
@ -100,7 +92,7 @@ void init(timepulse_callback_t callback)
system_extint_init(); system_extint_init();
/* Watchdog */ /* Watchdog */
//watchdog_init(); watchdog_init();
/* Configure Sleep Mode */ /* Configure Sleep Mode */
//system_set_sleepmode(SYSTEM_SLEEPMODE_STANDBY); //system_set_sleepmode(SYSTEM_SLEEPMODE_STANDBY);
@ -120,8 +112,11 @@ void init(timepulse_callback_t callback)
/* Enable the xosc on gclk1 */ /* Enable the xosc on gclk1 */
xosc_init(); xosc_init();
/* Telemetry init depends on gclk */
telemetry_init();
/* GPS init */ /* GPS init */
// gps_init(); gps_init();
/* Enable timer interrupt and event channel */ /* Enable timer interrupt and event channel */
timepulse_extint_init(); timepulse_extint_init();

Wyświetl plik

@ -40,6 +40,7 @@
#include "rf_tests.h" #include "rf_tests.h"
#include "data.h" #include "data.h"
#include "backlog.h" #include "backlog.h"
#include "pips.h"
#define CALLSIGN "UBSEDSx" #define CALLSIGN "UBSEDSx"
#define APRS_COMMENT "RTTY/434.6U8N2" #define APRS_COMMENT "RTTY/434.6U8N2"
@ -50,7 +51,7 @@
* The telemetry string starts with the specified number of dollar signs * The telemetry string starts with the specified number of dollar signs
*/ */
uint16_t format_telemetry_string(char* string, struct tracker_datapoint* dp, uint16_t format_telemetry_string(char* string, struct tracker_datapoint* dp,
uint8_t dollars) uint8_t dollars, uint8_t reduce_char_set)
{ {
double lat_fmt = 0.0; double lat_fmt = 0.0;
double lon_fmt = 0.0; double lon_fmt = 0.0;
@ -73,6 +74,11 @@ uint16_t format_telemetry_string(char* string, struct tracker_datapoint* dp,
lat_fmt, lon_fmt, altitude, dp->satillite_count, lat_fmt, lon_fmt, altitude, dp->satillite_count,
dp->battery, dp->temperature, dp->xosc_error); dp->battery, dp->temperature, dp->xosc_error);
if (reduce_char_set) {
/* Reduce character set */
contestiaize(telemetry_string + dollars);
}
/* sprintf - checksum. don't include dollars */ /* sprintf - checksum. don't include dollars */
len += sprintf(telemetry_string + len, len += sprintf(telemetry_string + len,
"*%04X\r", "*%04X\r",
@ -93,6 +99,11 @@ uint16_t format_telemetry_string(char* string, struct tracker_datapoint* dp,
dp->time.hour, dp->time.minute, dp->time.second, dp->time.hour, dp->time.minute, dp->time.second,
lat_fmt, lon_fmt, altitude); lat_fmt, lon_fmt, altitude);
if (reduce_char_set) {
/* Reduce character set */
contestiaize(telemetry_string + dollars);
}
/* sprintf - checksum. don't include dollars */ /* sprintf - checksum. don't include dollars */
len += sprintf(telemetry_string + len, len += sprintf(telemetry_string + len,
"*%04X\r", "*%04X\r",
@ -109,7 +120,7 @@ uint16_t format_telemetry_string(char* string, struct tracker_datapoint* dp,
void rtty_telemetry(struct tracker_datapoint* dp) { void rtty_telemetry(struct tracker_datapoint* dp) {
uint16_t len; uint16_t len;
len = format_telemetry_string(telemetry_string, dp, RTTY_DOLLARS); len = format_telemetry_string(telemetry_string, dp, RTTY_DOLLARS, 0);
/* Main telemetry */ /* Main telemetry */
telemetry_start(TELEMETRY_RTTY, len); telemetry_start(TELEMETRY_RTTY, len);
@ -126,10 +137,7 @@ void rtty_telemetry(struct tracker_datapoint* dp) {
void contestia_telemetry(struct tracker_datapoint* dp) { void contestia_telemetry(struct tracker_datapoint* dp) {
uint16_t len; uint16_t len;
len = format_telemetry_string(telemetry_string, dp, CONTESTIA_DOLLARS); len = format_telemetry_string(telemetry_string, dp, CONTESTIA_DOLLARS, 1);
/* Reduce character set */
contestiaize(telemetry_string + CONTESTIA_DOLLARS);
/* RSID */ /* RSID */
telemetry_start_rsid(RSID_CONTESTIA_32_1000); telemetry_start_rsid(RSID_CONTESTIA_32_1000);

Wyświetl plik

@ -29,6 +29,7 @@
#include "telemetry.h" #include "telemetry.h"
#include "aprs.h" #include "aprs.h"
#include "ax25.h" #include "ax25.h"
#include "watchdog.h"
#define APRS_TEST_LAT 51.47 #define APRS_TEST_LAT 51.47
#define APRS_TEST_LON -2.58 #define APRS_TEST_LON -2.58
@ -39,10 +40,14 @@ void telemetry_tone(void)
{ {
while (1) { while (1) {
si_trx_on(SI_MODEM_MOD_TYPE_CW, TELEMETRY_FREQUENCY, 0, 36); si_trx_on(SI_MODEM_MOD_TYPE_CW, TELEMETRY_FREQUENCY, 0, 36);
for (int i = 0; i < 200*1000; i++); for (int i = 0; i < 200*1000; i++) {
idle(IDLE_TELEMETRY_ACTIVE);
}
si_trx_off(); si_trx_off();
si_trx_on(SI_MODEM_MOD_TYPE_CW, TELEMETRY_FREQUENCY, 0, 0x7f); si_trx_on(SI_MODEM_MOD_TYPE_CW, TELEMETRY_FREQUENCY, 0, 0x7f);
for (int i = 0; i < 200*1000; i++); for (int i = 0; i < 200*1000; i++) {
idle(IDLE_TELEMETRY_ACTIVE);
}
si_trx_off(); si_trx_off();
} }
} }
@ -50,10 +55,14 @@ void aprs_tone(void)
{ {
while (1) { while (1) {
si_trx_on(SI_MODEM_MOD_TYPE_CW, APRS_TEST_FREQUENCY, 0, 36); si_trx_on(SI_MODEM_MOD_TYPE_CW, APRS_TEST_FREQUENCY, 0, 36);
for (int i = 0; i < 200*1000; i++); for (int i = 0; i < 200*1000; i++) {
idle(IDLE_TELEMETRY_ACTIVE);
}
si_trx_off(); si_trx_off();
si_trx_on(SI_MODEM_MOD_TYPE_CW, APRS_TEST_FREQUENCY, 0, 0x7f); si_trx_on(SI_MODEM_MOD_TYPE_CW, APRS_TEST_FREQUENCY, 0, 0x7f);
for (int i = 0; i < 200*1000; i++); for (int i = 0; i < 200*1000; i++) {
idle(IDLE_TELEMETRY_ACTIVE);
}
si_trx_off(); si_trx_off();
} }
} }
@ -75,7 +84,9 @@ void aprs_high_fm_tone(void)
si_trx_on(SI_MODEM_MOD_TYPE_2GFSK, APRS_TEST_FREQUENCY, si_trx_on(SI_MODEM_MOD_TYPE_2GFSK, APRS_TEST_FREQUENCY,
AX25_DEVIATION, APRS_POWER); AX25_DEVIATION, APRS_POWER);
while (1); while (1) {
idle(IDLE_TELEMETRY_ACTIVE);
}
} }
/** /**
@ -92,7 +103,9 @@ void aprs_test(void)
/* Transmit packet and wait */ /* Transmit packet and wait */
telemetry_start(TELEMETRY_APRS, 0xFFFF); telemetry_start(TELEMETRY_APRS, 0xFFFF);
while (telemetry_active()); while (telemetry_active()) {
idle(IDLE_TELEMETRY_ACTIVE);
}
} }
} }

Wyświetl plik

@ -626,7 +626,7 @@ static usart_rx_callback_t _usart_rx_callbacks[SERCOM_INST_NUM] = {
void _usart_interrupt_handler(Sercom* const sercom_instance, uint8_t instance_index) void _usart_interrupt_handler(Sercom* const sercom_instance, uint8_t instance_index)
{ {
/* Hardware instance */ /* Hardware instance */
SercomUsart* const hw = (SercomUsart*)SERCOM1; //sercom_instance; SercomUsart* const hw = (SercomUsart*)sercom_instance;
/* Temporary variables */ /* Temporary variables */
uint16_t interrupt_status; uint16_t interrupt_status;

Wyświetl plik

@ -421,13 +421,15 @@ void si_trx_reset(uint8_t modulation_type, uint32_t frequency,
{ {
_si_trx_sdn_enable(); /* active high shutdown = reset */ _si_trx_sdn_enable(); /* active high shutdown = reset */
for (int i = 0; i < 15*1000; i++); /* Approx. 15ms */ for (int i = 0; i < 15*1000; i++); /* Approx. 15 */
_si_trx_sdn_disable(); /* booting */ _si_trx_sdn_disable(); /* booting */
for (int i = 0; i < 15*1000; i++); /* Approx. 15ms */ for (int i = 0; i < 15*1000; i++); /* Approx. 15ms */
uint16_t part_number = si_trx_get_part_info(); uint16_t part_number = si_trx_get_part_info();
while (part_number != 17512);
/* Power Up */ /* Power Up */
si_trx_power_up(SI_POWER_UP_TCXO, VCXO_FREQUENCY); si_trx_power_up(SI_POWER_UP_TCXO, VCXO_FREQUENCY);
@ -573,6 +575,7 @@ void spi_loopback_test(void)
/* SI4xxx_SERCOM_MISO_PINMUX, /\** Pinmux *\/ */ /* SI4xxx_SERCOM_MISO_PINMUX, /\** Pinmux *\/ */
/* SI4xxx_SERCOM_SCK_PINMUX, /\** Pinmux *\/ */ /* SI4xxx_SERCOM_SCK_PINMUX, /\** Pinmux *\/ */
/* PINMUX_UNUSED); /\** Pinmux *\/ */ /* PINMUX_UNUSED); /\** Pinmux *\/ */
/* spi_enable(SI_TRX_SERCOM); */
/* Init loopback */ /* Init loopback */
spi_bitbang_init(SI4xxx_SERCOM_MOSI_PIN, spi_bitbang_init(SI4xxx_SERCOM_MOSI_PIN,

Wyświetl plik

@ -126,6 +126,8 @@ int telemetry_active(void) {
return (telemetry_string_length > 0); return (telemetry_string_length > 0);
} }
uint32_t contestia_timer_count, rtty_timer_count;
uint32_t pips_timer_count, ax25_timer_count, rsid_timer_count;
/** /**
* Starts telemetry output * Starts telemetry output
* *
@ -142,16 +144,16 @@ int telemetry_start(enum telemetry_t type, int32_t length) {
/* Setup timer tick */ /* Setup timer tick */
switch(telemetry_type) { switch(telemetry_type) {
case TELEMETRY_CONTESTIA: case TELEMETRY_CONTESTIA:
timer0_tick_init(CONTESTIA_SYMBOL_RATE); timer0_tick_init(contestia_timer_count);
break; break;
case TELEMETRY_RTTY: case TELEMETRY_RTTY:
timer0_tick_init(RTTY_BITRATE); timer0_tick_init(rtty_timer_count);
break; break;
case TELEMETRY_PIPS: case TELEMETRY_PIPS:
timer0_tick_init(PIPS_FREQUENCY); timer0_tick_init(pips_timer_count);
break; break;
case TELEMETRY_APRS: case TELEMETRY_APRS:
timer0_tick_init(AX25_TICK_RATE); timer0_tick_init(ax25_timer_count);
break; break;
case TELEMETRY_RSID: /* Not used - see function below */ case TELEMETRY_RSID: /* Not used - see function below */
break; break;
@ -178,7 +180,7 @@ int telemetry_start_rsid(rsid_code_t rsid) {
rsid_start(rsid); rsid_start(rsid);
/* Setup timer tick */ /* Setup timer tick */
timer0_tick_init(RSID_SYMBOL_RATE); timer0_tick_init(rsid_timer_count);
return 0; /* Success */ return 0; /* Success */
} else { } else {
@ -335,10 +337,11 @@ void telemetry_tick(void) {
radio_on = 1; radio_on = 1;
} else { /* Turn off */ } else { /* Turn off */
si_trx_off(); radio_on = 0;
si_trx_off(); radio_on = 0;
telemetry_stop(); telemetry_stop();
} }
break; break;
} }
} }
@ -358,12 +361,8 @@ const uint8_t tick_gclk_gen_num = 1;
* *
* Returns the frequency we actually initialised. * Returns the frequency we actually initialised.
*/ */
float timer0_tick_init(float frequency) void timer0_tick_init(uint32_t count)
{ {
/* Calculate the wrap value for the given frequency */
float gclk_frequency = (float)system_gclk_gen_get_hz(tick_gclk_gen_num);
uint32_t count = (uint32_t)(gclk_frequency / frequency);
/* Configure Timer 0 */ /* Configure Timer 0 */
bool t0_capture_channel_enables[] = {false, false}; bool t0_capture_channel_enables[] = {false, false};
uint32_t t0_compare_channel_values[] = {count, 0x0000}; uint32_t t0_compare_channel_values[] = {count, 0x0000};
@ -390,32 +389,21 @@ float timer0_tick_init(float frequency)
tc_enable_events(TC0, &event); tc_enable_events(TC0, &event);
/* Enable Interrupt */ /* Enable Interrupt */
TC0->COUNT32.INTENSET.reg = (1 << 4); TC0->COUNT16.INTENSET.reg = TC_INTENSET_MC0;
irq_register_handler(TC0_IRQn, TC0_INT_PRIO); /* Highest Priority */ irq_register_handler(TC0_IRQn, TC0_INT_PRIO); /* Highest Priority */
/* Enable Timer */ /* Enable Timer */
tc_enable(TC0); tc_enable(TC0);
tc_start_counter(TC0); tc_start_counter(TC0);
/* Return the frequency we actually initialised */
return gclk_frequency / (float)count;
} }
/** /**
* Changes the timer0 frequency. * Gets the count value required on timer0 for a specific frequency
*
* Returns the timer count that this corresponds to.
*/ */
uint32_t timer0_tick_frequency(float frequency) uint32_t timer0_get_count_value(float frequency)
{ {
float gclk_frequency = (float)system_gclk_gen_get_hz(tick_gclk_gen_num); float gclk_frequency = (float)system_gclk_gen_get_hz(tick_gclk_gen_num);
uint32_t count = (uint32_t)(gclk_frequency / frequency); uint32_t count = (uint32_t)(gclk_frequency / frequency);
tc_set_compare_value(TC0,
TC_COMPARE_CAPTURE_CHANNEL_0,
count);
/* We need to reset the count here so it's not beyond the capture limit */
tc_set_count_value(TC0, 0);
return count; return count;
} }
/** /**
@ -437,9 +425,28 @@ void TC0_Handler(void)
telemetry_tick(); telemetry_tick();
} }
} }
/**
* Init. Mostly used for calculating timer counts. Must be called after gclk1
*/
void telemetry_init(void)
{
contestia_timer_count = timer0_get_count_value(CONTESTIA_SYMBOL_RATE);
rtty_timer_count = timer0_get_count_value(RTTY_BITRATE);
pips_timer_count = timer0_get_count_value(PIPS_FREQUENCY);
ax25_timer_count = timer0_get_count_value(AX25_TICK_RATE);
rsid_timer_count = timer0_get_count_value(RSID_SYMBOL_RATE);
}
/**
* =========== PWM
*/
#define GPIO1_PWM_STEPS 200 // ~ 2kHz on a 4 MHz clock #define GPIO1_PWM_STEPS 200 // ~ 2kHz on a 4 MHz clock
/** /**

Wyświetl plik

@ -29,7 +29,11 @@
#include "hw_config.h" #include "hw_config.h"
#include "system/gclk.h" #include "system/gclk.h"
#include "system/wdt.h" #include "system/wdt.h"
#include "system/interrupt.h"
#include "system/port.h" #include "system/port.h"
#include "tc/tc_driver.h"
#include "si_trx.h"
#include "init.h"
struct idle_counter idle_count, idle_count_max; struct idle_counter idle_count, idle_count_max;
@ -84,6 +88,18 @@ void clear_idle_counters(void)
memset(&idle_count, 0, sizeof(struct idle_counter)); memset(&idle_count, 0, sizeof(struct idle_counter));
} }
/**
* Kick
*/
void kick_the_watchdog(void)
{
/* tc_set_count_value(TC1, 0); */
/* tc_clear_status(TC1, TC_STATUS_CHANNEL_0_MATCH); */
wdt_reset_count();
kick_external_watchdog();
}
/** /**
* Called in idle loops. Kicks the watchdog * Called in idle loops. Kicks the watchdog
* *
@ -112,8 +128,7 @@ void idle(idle_wait_t idle_t)
check_idle_counters(); check_idle_counters();
/* Kick the watchdog */ /* Kick the watchdog */
wdt_reset_count(); kick_the_watchdog();
kick_external_watchdog();
/* And sleep */ /* And sleep */
system_sleep(); system_sleep();
@ -123,7 +138,7 @@ void idle(idle_wait_t idle_t)
/** /**
* The internal watchdog is used to bring the processor to a halt and * The internal watchdog is used to bring the processor to a halt and
* coredump to external memory. * coredump to external memory.
* 0.2s < tout < 0.32s * 0.4s < t_early_w < 0.64s
* *
* The external watchdog then hard resets the MCU and GPS to bring the * The external watchdog then hard resets the MCU and GPS to bring the
* system back up in a clean state. * system back up in a clean state.
@ -139,7 +154,7 @@ void watchdog_init(void)
false); /* Powersave */ false); /* Powersave */
kick_external_watchdog(); /* Kick External */ kick_external_watchdog(); /* Kick External */
/* 0.25 seconds timeout. So 2^(15-2) cycles of the 32.768kHz wdt clock */ /* /\* 0.5s early warn. So 2^(15-1) cycles of the 32.768kHz ulposc *\/ */
system_gclk_gen_set_config(WDT_GCLK, system_gclk_gen_set_config(WDT_GCLK,
GCLK_SOURCE_OSCULP32K, /* Source */ GCLK_SOURCE_OSCULP32K, /* Source */
false, /* High When Disabled */ false, /* High When Disabled */
@ -149,26 +164,46 @@ void watchdog_init(void)
system_gclk_gen_enable(WDT_GCLK); system_gclk_gen_enable(WDT_GCLK);
/* Set the watchdog timer. On 256Hz gclk */ /* Set the watchdog timer. On 256Hz gclk */
wdt_set_config(true, /* Lock WDT */ wdt_set_config(false, /* Lock WDT */
true, /* Enable WDT */ true, /* Enable WDT */
WDT_GCLK, /* Clock Source */ WDT_GCLK, /* Clock Source */
WDT_PERIOD_64CLK, /* Timeout Period div 2^6 */ WDT_PERIOD_16384CLK, /* Timeout Period */
WDT_PERIOD_NONE, /* Window Period */ WDT_PERIOD_NONE, /* Window Period */
WDT_PERIOD_NONE); /* Early Warning Period */ WDT_PERIOD_256CLK); /* Early Warning Period */
WDT->INTENSET.reg |= WDT_INTENSET_EW;
WDT->INTFLAG.reg |= WDT_INTFLAG_EW;
irq_register_handler(WDT_IRQn, 0);
/* Kick Watchdogs */ /* Kick Watchdogs */
wdt_reset_count();
kick_external_watchdog(); kick_external_watchdog();
wdt_reset_count();
} }
/** void WDT_Handler(void)
* Called for the watchdog early warning interrupt {
*/ Wdt *const hw = WDT;
void WDT_Handler(void) {
/* Bring the system into a safe state */
si_trx_shutdown();
/* LED on */
led_on();
/* Coredump */ /* Coredump */
/* Wait for the watchdog to kill us */ /* Wait for the external watchdog to kill us */
while (1); while (1) {
led_on();
for (int i = 0; i < 25*1000; i++);
led_off();
for (int i = 0; i < 25*1000; i++);
/**
* Whilst this is generally bad practice in this system we have an
* external watchdog for the actual reset.
*/
wdt_reset_count();
}
} }

Wyświetl plik

@ -97,59 +97,59 @@ void osc8m_set_calibration(struct osc8m_calibration_t calib) {
/** /**
* Configure timer 4 to generate events at 1Hz of OSC8M * Configure timer 4 to generate events at 1Hz of OSC8M
*/ */
void osc8m_event_source(void) { /* void osc8m_event_source(void) { */
/* Timer 4 runs on GCLK0 (4MHz) */ /* /\* Timer 4 runs on GCLK0 (4MHz) *\/ */
bool t4_capture_channel_enables[] = {false, false}; /* bool t4_capture_channel_enables[] = {false, false}; */
uint32_t t4_compare_channel_values[] = {15625, 0x0000}; /* uint32_t t4_compare_channel_values[] = {15625, 0x0000}; */
/* Divide by 256*15625 = 1Hz events */ /* /\* Divide by 256*15625 = 1Hz events *\/ */
tc_init(TC4, /* tc_init(TC4, */
GCLK_GENERATOR_0, /* GCLK_GENERATOR_0, */
TC_COUNTER_SIZE_16BIT, /* TC_COUNTER_SIZE_16BIT, */
TC_CLOCK_PRESCALER_DIV256, /* TC_CLOCK_PRESCALER_DIV256, */
TC_WAVE_GENERATION_NORMAL_FREQ, /* TC_WAVE_GENERATION_NORMAL_FREQ, */
TC_RELOAD_ACTION_GCLK, /* TC_RELOAD_ACTION_GCLK, */
TC_COUNT_DIRECTION_UP, /* TC_COUNT_DIRECTION_UP, */
TC_WAVEFORM_INVERT_OUTPUT_NONE, /* TC_WAVEFORM_INVERT_OUTPUT_NONE, */
false, /* Oneshot */ /* false, /\* Oneshot *\/ */
false, /* Run in standby */ /* false, /\* Run in standby *\/ */
0x0000, /* Initial value */ /* 0x0000, /\* Initial value *\/ */
0xFFFF, /* Top value */ /* 0xFFFF, /\* Top value *\/ */
t4_capture_channel_enables, /* Capture Channel Enables */ /* t4_capture_channel_enables, /\* Capture Channel Enables *\/ */
t4_compare_channel_values); /* Compare Channels Values */ /* t4_compare_channel_values); /\* Compare Channels Values *\/ */
/* Timer 4 generates an event on compare channel 0 */ /* /\* Timer 4 generates an event on compare channel 0 *\/ */
struct tc_events events; /* struct tc_events events; */
events.generate_event_on_compare_channel[0] = true; /* events.generate_event_on_compare_channel[0] = true; */
events.generate_event_on_compare_channel[1] = false; /* events.generate_event_on_compare_channel[1] = false; */
events.generate_event_on_overflow = false; /* events.generate_event_on_overflow = false; */
events.invert_event_input = false; /* events.invert_event_input = false; */
events.on_event_perform_action = true; /* events.on_event_perform_action = true; */
events.event_action = TC_EVENT_ACTION_RETRIGGER; /* events.event_action = TC_EVENT_ACTION_RETRIGGER; */
tc_enable_events(TC4, &events); /* tc_enable_events(TC4, &events); */
events_attach_user(0, 4); // Timer 4 is event user on channel 1 /* events_attach_user(0, 4); // Timer 4 is event user on channel 1 */
/* This event is picked up on event channel 0 */ /* /\* This event is picked up on event channel 0 *\/ */
events_allocate(0, /* events_allocate(0, */
EVENTS_EDGE_DETECT_NONE, /* EVENTS_EDGE_DETECT_NONE, */
EVENTS_PATH_ASYNCHRONOUS, /* EVENTS_PATH_ASYNCHRONOUS, */
0x29, /* TC4 MC0 */ /* 0x29, /\* TC4 MC0 *\/ */
0); /* 0); */
/* This event is picked up on event channel 1 */ /* /\* This event is picked up on event channel 1 *\/ */
events_allocate(1, /* events_allocate(1, */
EVENTS_EDGE_DETECT_NONE, /* EVENTS_EDGE_DETECT_NONE, */
EVENTS_PATH_ASYNCHRONOUS, /* EVENTS_PATH_ASYNCHRONOUS, */
0x29, /* TC4 MC0 */ /* 0x29, /\* TC4 MC0 *\/ */
0); /* 0); */
tc_enable(TC4); /* Retrigger event means counter doesn't start yet */ /* tc_enable(TC4); /\* Retrigger event means counter doesn't start yet *\/ */
tc_start_counter(TC4); /* We start it manually now */ /* tc_start_counter(TC4); /\* We start it manually now *\/ */
} /* } */
void osc8m_event_source_disable(void) { /* void osc8m_event_source_disable(void) { */
tc_disable(TC4); /* tc_disable(TC4); */
} /* } */
/** /**
* Configure the timepulse extint to generate events * Configure the timepulse extint to generate events
@ -212,7 +212,7 @@ void measure_xosc(enum xosc_measurement_t measurement_t,
/* Configure an event source */ /* Configure an event source */
switch (measurement_t) { switch (measurement_t) {
case XOSC_MEASURE_OSC8M: case XOSC_MEASURE_OSC8M:
osc8m_event_source(); // osc8m issues events // osc8m_event_source(); // osc8m issues events
break; break;
case XOSC_MEASURE_TIMEPULSE: case XOSC_MEASURE_TIMEPULSE:
timepulse_extint_event_source(); // timepulse issues events timepulse_extint_event_source(); // timepulse issues events
@ -227,7 +227,7 @@ void measure_xosc_disable(enum xosc_measurement_t measurement_t) {
switch (measurement_t) { switch (measurement_t) {
case XOSC_MEASURE_OSC8M: case XOSC_MEASURE_OSC8M:
osc8m_event_source_disable(); // osc8m_event_source_disable();
break; break;
case XOSC_MEASURE_TIMEPULSE: case XOSC_MEASURE_TIMEPULSE:
timepulse_extint_event_source_disable(); timepulse_extint_event_source_disable();