kopia lustrzana https://github.com/bristol-seds/pico-tracker
Brought up gps on new hw, various bugfix, pre-calculate telemetry timer counts and more
rodzic
b65216498d
commit
08e3d30c25
|
@ -8,12 +8,12 @@
|
|||
||gclk7|aprs clock, fed from gclk1, div 6 / 11
|
||||
|
|
||||
|*TC*||
|
||||
||tc0|telemetry tick timer. 32-bit
|
||||
||tc0|telemetry tick timer. 32-bit. glck1
|
||||
||tc1|^^^^^
|
||||
||tc2|counts cycles of tcxo. 32-bit
|
||||
||tc2|counts cycles of tcxo. 32-bit. gclk1
|
||||
||tc3|^^^^^
|
||||
||tc4|osc8m event source
|
||||
||tc5|telemetry pwm 16-bit, ALSO aprs carrier 16-bit
|
||||
||tc4|unused (osc8m event source)
|
||||
||tc5|telemetry pwm 16-bit glck0, ALSO aprs carrier 16-bit gclk7
|
||||
|
|
||||
|*EXTINT*|
|
||||
||extint[5]|gps timepulse
|
||||
|
@ -32,11 +32,11 @@
|
|||
|
||||
| Name | Function | Priority H(0-3)L | Notes
|
||||
| --- | --- | --- | ---
|
||||
|TC0_IRQn|telemetry tick timer|0|latency critical for symbol timing. rate <= 1200Hz
|
||||
|[GPS_SERCOM]_IRQn|gps usart rx|1|latency not so critical. rate <= 960Hz
|
||||
|EIC_IRQn|timepulse|2|latency not so critical. rate = 1
|
||||
|TC2_IRQn|xosc measurement done|2|latency not critical
|
||||
|ADC_IRQn|adc measurement done|2|latency not critical
|
||||
|TC0_IRQn|telemetry tick timer|1|latency critical for symbol timing. rate <= 1200Hz
|
||||
|[GPS_SERCOM]_IRQn|gps usart rx|2|latency not so critical. rate <= 960Hz
|
||||
|EIC_IRQn|timepulse|3|latency not so critical. rate = 1
|
||||
|TC2_IRQn|xosc measurement done|3|latency not critical
|
||||
|ADC_IRQn|adc measurement done|3|latency not critical
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#define GPS_SERCOM_MIGO_PIN PIN_PA07
|
||||
#define GPS_SERCOM_MIGO_PINMUX PINMUX_PA07D_SERCOM0_PAD3
|
||||
#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_TIMEPULSE_PIN PIN_PA05
|
||||
#define GPS_TIMEPULSE_PINMUX PINMUX_PA05A_EIC_EXTINT5
|
||||
|
@ -75,7 +76,7 @@
|
|||
/**
|
||||
* 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
|
||||
|
@ -185,14 +186,16 @@
|
|||
/**
|
||||
* 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 */
|
||||
|
|
|
@ -50,15 +50,12 @@ int telemetry_start_rsid(rsid_code_t rsid);
|
|||
void telemetry_aprs_set_frequency(int32_t frequency);
|
||||
float telemetry_si_temperature(void);
|
||||
|
||||
float timer0_tick_init(float frequency);
|
||||
uint32_t timer0_tick_frequency(float frequency);
|
||||
void timer0_tick_init(uint32_t count);
|
||||
void timer0_tick_deinit();
|
||||
void telemetry_init();
|
||||
|
||||
void telemetry_gpio1_pwm_init(void);
|
||||
void telemetry_gpio1_pwm_duty(float duty_cycle);
|
||||
void telemetry_gpio1_pwm_deinit(void);
|
||||
|
||||
void telemetry_gpio1_init(void);
|
||||
void telemetry_gpio1_set(uint8_t value);
|
||||
|
||||
#endif /* TELEMETRY_H */
|
||||
|
|
|
@ -52,6 +52,7 @@ struct idle_counter {
|
|||
uint32_t wait_for_next_telemetry;
|
||||
};
|
||||
|
||||
void kick_the_watchdog(void);
|
||||
void idle(idle_wait_t idle_t);
|
||||
void watchdog_init(void);
|
||||
|
||||
|
|
|
@ -197,11 +197,6 @@ uint8_t aprs_start(void)
|
|||
telemetry
|
||||
);
|
||||
|
||||
// RTTY/434.6U8N2",
|
||||
|
||||
/* Let's actually try that out.. We can add comment etc. later */
|
||||
|
||||
|
||||
/* Transmit the frame using ax25 */
|
||||
ax25_start(addresses, addresses_len,
|
||||
information, information_len);
|
||||
|
|
|
@ -40,7 +40,8 @@ struct tracker_time time = {0};
|
|||
struct tracker_datapoint* dp;
|
||||
|
||||
/* 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 contestia_telemetry(struct tracker_datapoint* dp);
|
||||
|
@ -86,26 +87,26 @@ void do_cron(void)
|
|||
memcpy(&t, &time, sizeof(struct tracker_time));
|
||||
|
||||
/* ---- Data every 30 seconds ---- */
|
||||
if ((time.second % 30) == 0) {
|
||||
if ((t.second % 30) == 0) {
|
||||
dp = collect_data();
|
||||
memcpy(&dp->time, &t, sizeof(struct tracker_time));
|
||||
} else if ((time.second % 30) == 20) {
|
||||
memcpy(&dp->time, &time, sizeof(struct tracker_time));
|
||||
} else if ((t.second % 30) == 20) {
|
||||
collect_data_async();
|
||||
}
|
||||
|
||||
|
||||
/* ---- Telemetry output ---- */
|
||||
/* RTTY */
|
||||
if (time.second == 0 && !LOW_POWER(dp)) {
|
||||
if (t.second == 0 && !LOW_POWER(dp)) {
|
||||
rtty_telemetry(dp);
|
||||
|
||||
/* Contestia */
|
||||
} else if (time.second == 30 && !LOW_POWER(dp)) {
|
||||
} else if (t.second == 30 && !LOW_POWER(dp)) {
|
||||
contestia_telemetry(dp);
|
||||
|
||||
/* Low Power */
|
||||
} else if (time.second == 0 && LOW_POWER(dp)) {
|
||||
if ((time.minute % 2) == 0) {
|
||||
} else if (t.second == 0 && LOW_POWER(dp)) {
|
||||
if ((t.minute % 2) == 0) {
|
||||
rtty_telemetry(dp);
|
||||
} else {
|
||||
contestia_telemetry(dp);
|
||||
|
@ -113,18 +114,18 @@ void do_cron(void)
|
|||
|
||||
/* APRS */
|
||||
#ifdef APRS_ENABLE
|
||||
} else if ((time.minute % 2) == 0 && time.second == 55) {
|
||||
} else if ((t.minute % 2) == 0 && t.second == 55) {
|
||||
aprs_telemetry(dp);
|
||||
#endif
|
||||
|
||||
/* Pips */
|
||||
} else if ((time.second % 1) == 0) {
|
||||
} else if ((t.second % 1) == 0) {
|
||||
pips_telemetry();
|
||||
|
||||
}
|
||||
|
||||
/* ---- Record for backlog ---- */
|
||||
if ((time.minute == 0) && (time.second == 25)) {
|
||||
if ((t.minute % 1 == 0) && (t.second == 25)) {
|
||||
record_backlog(dp);
|
||||
}
|
||||
}
|
||||
|
@ -136,11 +137,11 @@ void cron_tick(void) {
|
|||
|
||||
/* Update time internally */
|
||||
time.epoch++; time.second++;
|
||||
if (time.second > 60) {
|
||||
if (time.second >= 60) {
|
||||
time.second = 0; time.minute++;
|
||||
if (time.minute > 60) {
|
||||
if (time.minute >= 60) {
|
||||
time.minute = 0; time.hour++;
|
||||
if (time.hour > 23) {
|
||||
if (time.hour >= 24) {
|
||||
time.hour = 0;
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +152,7 @@ void cron_tick(void) {
|
|||
if (((time.hour == 0) && (time.minute == 0) && (time.second == 5)) ||
|
||||
((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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,9 @@ void collect_data_async(void)
|
|||
{
|
||||
/* Measure XOSC against gps timepulse */
|
||||
measure_xosc(XOSC_MEASURE_TIMEPULSE, xosc_measure_callback);
|
||||
|
||||
/* Analogue Measurements */
|
||||
start_adc_conversion_sequence();
|
||||
}
|
||||
/**
|
||||
* Collect Data synchronously and return datapoint
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "util/dbuffer.h"
|
||||
#include "ubx_messages.h"
|
||||
#include "gps.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
/**
|
||||
* UBX Constants
|
||||
|
@ -264,13 +265,13 @@ void _ubx_poll(ubx_message_t* message) {
|
|||
/**
|
||||
* 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.res0 = 0;
|
||||
ubx_cfg_prt.payload.txReady = 0;
|
||||
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.outProtoMask = 0x1; /* UBX */
|
||||
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_init(GPS_SERCOM,
|
||||
|
@ -468,7 +469,7 @@ void gps_init(void)
|
|||
false, /** Enable LIN Slave Support */
|
||||
false, /** Enable start of frame dection */
|
||||
false, /** Enable collision dection */
|
||||
9600, /** USART Baud rate */
|
||||
baud_rate, /** USART Baud rate */
|
||||
true, /** Enable receiver */
|
||||
true, /** Enable transmitter */
|
||||
false, /** Sample on the rising edge of XLCK */
|
||||
|
@ -483,19 +484,34 @@ void gps_init(void)
|
|||
PINMUX_UNUSED); /** PAD3 pinmux */
|
||||
|
||||
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 */
|
||||
gps_disable_nmea();
|
||||
gps_set_io_config(GPS_BAUD_RATE);
|
||||
|
||||
/* Incoming ubx messages are handled in an irq */
|
||||
usart_register_rx_callback(GPS_SERCOM, gps_rx_callback, GPS_SERCOM_INT_PRIO);
|
||||
|
||||
kick_the_watchdog();
|
||||
|
||||
/* Set the platform model */
|
||||
gps_set_platform_model();
|
||||
|
||||
/* Set which GNSS constellation we'd like to use */
|
||||
gps_set_gnss();
|
||||
|
||||
kick_the_watchdog();
|
||||
|
||||
/* Exit powersave mode to start */
|
||||
gps_set_powersave(false);
|
||||
|
||||
|
@ -524,7 +540,7 @@ void usart_loopback_test(void)
|
|||
false, /** Enable LIN Slave Support */
|
||||
false, /** Enable start of frame dection */
|
||||
false, /** Enable collision dection */
|
||||
9600, /** USART Baud rate */
|
||||
GPS_BAUD_RATE, /** USART Baud rate */
|
||||
true, /** Enable receiver */
|
||||
true, /** Enable transmitter */
|
||||
false, /** Sample on the rising edge of XLCK */
|
||||
|
@ -532,8 +548,8 @@ void usart_loopback_test(void)
|
|||
0, /** External clock frequency in synchronous mode. */
|
||||
false, /** Run in standby */
|
||||
GCLK_GENERATOR_0, /** GCLK generator source */
|
||||
PINMUX_DEFAULT, /** PAD0 pinmux */
|
||||
PINMUX_DEFAULT, /** PAD1 pinmux */
|
||||
GPS_SERCOM_MOGI_PINMUX, /** PAD0 pinmux */
|
||||
GPS_SERCOM_MIGO_PINMUX, /** PAD1 pinmux */
|
||||
PINMUX_UNUSED, /** PAD2 pinmux */
|
||||
PINMUX_UNUSED); /** PAD3 pinmux */
|
||||
|
||||
|
@ -542,5 +558,5 @@ void usart_loopback_test(void)
|
|||
usart_write_wait(GPS_SERCOM, 0x34);
|
||||
usart_read_wait(GPS_SERCOM, &data);
|
||||
|
||||
semihost_printf("Rx'ed: 0x%02x\n", data);
|
||||
usart_disable(GPS_SERCOM);
|
||||
}
|
||||
|
|
|
@ -73,14 +73,6 @@ void init(timepulse_callback_t callback)
|
|||
led_reset();
|
||||
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
|
||||
* ---------------------------------------------------------------------------
|
||||
|
@ -100,7 +92,7 @@ void init(timepulse_callback_t callback)
|
|||
system_extint_init();
|
||||
|
||||
/* Watchdog */
|
||||
//watchdog_init();
|
||||
watchdog_init();
|
||||
|
||||
/* Configure Sleep Mode */
|
||||
//system_set_sleepmode(SYSTEM_SLEEPMODE_STANDBY);
|
||||
|
@ -120,8 +112,11 @@ void init(timepulse_callback_t callback)
|
|||
/* Enable the xosc on gclk1 */
|
||||
xosc_init();
|
||||
|
||||
/* Telemetry init depends on gclk */
|
||||
telemetry_init();
|
||||
|
||||
/* GPS init */
|
||||
// gps_init();
|
||||
gps_init();
|
||||
|
||||
/* Enable timer interrupt and event channel */
|
||||
timepulse_extint_init();
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "rf_tests.h"
|
||||
#include "data.h"
|
||||
#include "backlog.h"
|
||||
#include "pips.h"
|
||||
|
||||
#define CALLSIGN "UBSEDSx"
|
||||
#define APRS_COMMENT "RTTY/434.6U8N2"
|
||||
|
@ -50,7 +51,7 @@
|
|||
* The telemetry string starts with the specified number of dollar signs
|
||||
*/
|
||||
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 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,
|
||||
dp->battery, dp->temperature, dp->xosc_error);
|
||||
|
||||
if (reduce_char_set) {
|
||||
/* Reduce character set */
|
||||
contestiaize(telemetry_string + dollars);
|
||||
}
|
||||
|
||||
/* sprintf - checksum. don't include dollars */
|
||||
len += sprintf(telemetry_string + len,
|
||||
"*%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,
|
||||
lat_fmt, lon_fmt, altitude);
|
||||
|
||||
if (reduce_char_set) {
|
||||
/* Reduce character set */
|
||||
contestiaize(telemetry_string + dollars);
|
||||
}
|
||||
|
||||
/* sprintf - checksum. don't include dollars */
|
||||
len += sprintf(telemetry_string + len,
|
||||
"*%04X\r",
|
||||
|
@ -109,7 +120,7 @@ uint16_t format_telemetry_string(char* string, struct tracker_datapoint* dp,
|
|||
void rtty_telemetry(struct tracker_datapoint* dp) {
|
||||
uint16_t len;
|
||||
|
||||
len = format_telemetry_string(telemetry_string, dp, RTTY_DOLLARS);
|
||||
len = format_telemetry_string(telemetry_string, dp, RTTY_DOLLARS, 0);
|
||||
|
||||
/* Main telemetry */
|
||||
telemetry_start(TELEMETRY_RTTY, len);
|
||||
|
@ -126,10 +137,7 @@ void rtty_telemetry(struct tracker_datapoint* dp) {
|
|||
void contestia_telemetry(struct tracker_datapoint* dp) {
|
||||
uint16_t len;
|
||||
|
||||
len = format_telemetry_string(telemetry_string, dp, CONTESTIA_DOLLARS);
|
||||
|
||||
/* Reduce character set */
|
||||
contestiaize(telemetry_string + CONTESTIA_DOLLARS);
|
||||
len = format_telemetry_string(telemetry_string, dp, CONTESTIA_DOLLARS, 1);
|
||||
|
||||
/* RSID */
|
||||
telemetry_start_rsid(RSID_CONTESTIA_32_1000);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "telemetry.h"
|
||||
#include "aprs.h"
|
||||
#include "ax25.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
#define APRS_TEST_LAT 51.47
|
||||
#define APRS_TEST_LON -2.58
|
||||
|
@ -39,10 +40,14 @@ void telemetry_tone(void)
|
|||
{
|
||||
while (1) {
|
||||
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_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();
|
||||
}
|
||||
}
|
||||
|
@ -50,10 +55,14 @@ void aprs_tone(void)
|
|||
{
|
||||
while (1) {
|
||||
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_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();
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +84,9 @@ void aprs_high_fm_tone(void)
|
|||
|
||||
si_trx_on(SI_MODEM_MOD_TYPE_2GFSK, APRS_TEST_FREQUENCY,
|
||||
AX25_DEVIATION, APRS_POWER);
|
||||
while (1);
|
||||
while (1) {
|
||||
idle(IDLE_TELEMETRY_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,7 +103,9 @@ void aprs_test(void)
|
|||
|
||||
/* Transmit packet and wait */
|
||||
telemetry_start(TELEMETRY_APRS, 0xFFFF);
|
||||
while (telemetry_active());
|
||||
while (telemetry_active()) {
|
||||
idle(IDLE_TELEMETRY_ACTIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
/* Hardware instance */
|
||||
SercomUsart* const hw = (SercomUsart*)SERCOM1; //sercom_instance;
|
||||
SercomUsart* const hw = (SercomUsart*)sercom_instance;
|
||||
|
||||
/* Temporary variables */
|
||||
uint16_t interrupt_status;
|
||||
|
|
|
@ -421,13 +421,15 @@ void si_trx_reset(uint8_t modulation_type, uint32_t frequency,
|
|||
{
|
||||
_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 */
|
||||
for (int i = 0; i < 15*1000; i++); /* Approx. 15ms */
|
||||
|
||||
|
||||
uint16_t part_number = si_trx_get_part_info();
|
||||
|
||||
while (part_number != 17512);
|
||||
|
||||
/* Power Up */
|
||||
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_SCK_PINMUX, /\** Pinmux *\/ */
|
||||
/* PINMUX_UNUSED); /\** Pinmux *\/ */
|
||||
/* spi_enable(SI_TRX_SERCOM); */
|
||||
|
||||
/* Init loopback */
|
||||
spi_bitbang_init(SI4xxx_SERCOM_MOSI_PIN,
|
||||
|
|
|
@ -126,6 +126,8 @@ int telemetry_active(void) {
|
|||
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
|
||||
*
|
||||
|
@ -142,16 +144,16 @@ int telemetry_start(enum telemetry_t type, int32_t length) {
|
|||
/* Setup timer tick */
|
||||
switch(telemetry_type) {
|
||||
case TELEMETRY_CONTESTIA:
|
||||
timer0_tick_init(CONTESTIA_SYMBOL_RATE);
|
||||
timer0_tick_init(contestia_timer_count);
|
||||
break;
|
||||
case TELEMETRY_RTTY:
|
||||
timer0_tick_init(RTTY_BITRATE);
|
||||
timer0_tick_init(rtty_timer_count);
|
||||
break;
|
||||
case TELEMETRY_PIPS:
|
||||
timer0_tick_init(PIPS_FREQUENCY);
|
||||
timer0_tick_init(pips_timer_count);
|
||||
break;
|
||||
case TELEMETRY_APRS:
|
||||
timer0_tick_init(AX25_TICK_RATE);
|
||||
timer0_tick_init(ax25_timer_count);
|
||||
break;
|
||||
case TELEMETRY_RSID: /* Not used - see function below */
|
||||
break;
|
||||
|
@ -178,7 +180,7 @@ int telemetry_start_rsid(rsid_code_t rsid) {
|
|||
rsid_start(rsid);
|
||||
|
||||
/* Setup timer tick */
|
||||
timer0_tick_init(RSID_SYMBOL_RATE);
|
||||
timer0_tick_init(rsid_timer_count);
|
||||
|
||||
return 0; /* Success */
|
||||
} else {
|
||||
|
@ -335,10 +337,11 @@ void telemetry_tick(void) {
|
|||
radio_on = 1;
|
||||
|
||||
} else { /* Turn off */
|
||||
si_trx_off(); radio_on = 0;
|
||||
|
||||
si_trx_off(); radio_on = 0;
|
||||
telemetry_stop();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -358,12 +361,8 @@ const uint8_t tick_gclk_gen_num = 1;
|
|||
*
|
||||
* 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 */
|
||||
bool t0_capture_channel_enables[] = {false, false};
|
||||
uint32_t t0_compare_channel_values[] = {count, 0x0000};
|
||||
|
@ -390,32 +389,21 @@ float timer0_tick_init(float frequency)
|
|||
tc_enable_events(TC0, &event);
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* Enable Timer */
|
||||
tc_enable(TC0);
|
||||
tc_start_counter(TC0);
|
||||
|
||||
/* Return the frequency we actually initialised */
|
||||
return gclk_frequency / (float)count;
|
||||
}
|
||||
/**
|
||||
* Changes the timer0 frequency.
|
||||
*
|
||||
* Returns the timer count that this corresponds to.
|
||||
* Gets the count value required on timer0 for a specific frequency
|
||||
*/
|
||||
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);
|
||||
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;
|
||||
}
|
||||
/**
|
||||
|
@ -437,9 +425,28 @@ void TC0_Handler(void)
|
|||
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
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,7 +29,11 @@
|
|||
#include "hw_config.h"
|
||||
#include "system/gclk.h"
|
||||
#include "system/wdt.h"
|
||||
#include "system/interrupt.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;
|
||||
|
||||
|
@ -84,6 +88,18 @@ void clear_idle_counters(void)
|
|||
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
|
||||
*
|
||||
|
@ -112,8 +128,7 @@ void idle(idle_wait_t idle_t)
|
|||
check_idle_counters();
|
||||
|
||||
/* Kick the watchdog */
|
||||
wdt_reset_count();
|
||||
kick_external_watchdog();
|
||||
kick_the_watchdog();
|
||||
|
||||
/* And 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
|
||||
* 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
|
||||
* system back up in a clean state.
|
||||
|
@ -139,36 +154,56 @@ void watchdog_init(void)
|
|||
false); /* Powersave */
|
||||
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,
|
||||
GCLK_SOURCE_OSCULP32K, /* Source */
|
||||
false, /* High When Disabled */
|
||||
128, /* Division Factor 2^7 */
|
||||
false, /* Run in standby */
|
||||
true); /* Output Pin Enable */
|
||||
GCLK_SOURCE_OSCULP32K, /* Source */
|
||||
false, /* High When Disabled */
|
||||
128, /* Division Factor 2^7 */
|
||||
false, /* Run in standby */
|
||||
true); /* Output Pin Enable */
|
||||
system_gclk_gen_enable(WDT_GCLK);
|
||||
|
||||
/* Set the watchdog timer. On 256Hz gclk */
|
||||
wdt_set_config(true, /* Lock WDT */
|
||||
true, /* Enable WDT */
|
||||
WDT_GCLK, /* Clock Source */
|
||||
WDT_PERIOD_64CLK, /* Timeout Period div 2^6 */
|
||||
WDT_PERIOD_NONE, /* Window Period */
|
||||
WDT_PERIOD_NONE); /* Early Warning Period */
|
||||
wdt_set_config(false, /* Lock WDT */
|
||||
true, /* Enable WDT */
|
||||
WDT_GCLK, /* Clock Source */
|
||||
WDT_PERIOD_16384CLK, /* Timeout Period */
|
||||
WDT_PERIOD_NONE, /* Window 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 */
|
||||
wdt_reset_count();
|
||||
kick_external_watchdog();
|
||||
wdt_reset_count();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called for the watchdog early warning interrupt
|
||||
*/
|
||||
void WDT_Handler(void) {
|
||||
void WDT_Handler(void)
|
||||
{
|
||||
Wdt *const hw = WDT;
|
||||
|
||||
/* Bring the system into a safe state */
|
||||
si_trx_shutdown();
|
||||
|
||||
/* LED on */
|
||||
led_on();
|
||||
|
||||
/* Coredump */
|
||||
|
||||
/* Wait for the watchdog to kill us */
|
||||
while (1);
|
||||
/* Wait for the external watchdog to kill us */
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,59 +97,59 @@ void osc8m_set_calibration(struct osc8m_calibration_t calib) {
|
|||
/**
|
||||
* 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) */
|
||||
bool t4_capture_channel_enables[] = {false, false};
|
||||
uint32_t t4_compare_channel_values[] = {15625, 0x0000};
|
||||
/* Divide by 256*15625 = 1Hz events */
|
||||
tc_init(TC4,
|
||||
GCLK_GENERATOR_0,
|
||||
TC_COUNTER_SIZE_16BIT,
|
||||
TC_CLOCK_PRESCALER_DIV256,
|
||||
TC_WAVE_GENERATION_NORMAL_FREQ,
|
||||
TC_RELOAD_ACTION_GCLK,
|
||||
TC_COUNT_DIRECTION_UP,
|
||||
TC_WAVEFORM_INVERT_OUTPUT_NONE,
|
||||
false, /* Oneshot */
|
||||
false, /* Run in standby */
|
||||
0x0000, /* Initial value */
|
||||
0xFFFF, /* Top value */
|
||||
t4_capture_channel_enables, /* Capture Channel Enables */
|
||||
t4_compare_channel_values); /* Compare Channels Values */
|
||||
/* /\* Timer 4 runs on GCLK0 (4MHz) *\/ */
|
||||
/* bool t4_capture_channel_enables[] = {false, false}; */
|
||||
/* uint32_t t4_compare_channel_values[] = {15625, 0x0000}; */
|
||||
/* /\* Divide by 256*15625 = 1Hz events *\/ */
|
||||
/* tc_init(TC4, */
|
||||
/* GCLK_GENERATOR_0, */
|
||||
/* TC_COUNTER_SIZE_16BIT, */
|
||||
/* TC_CLOCK_PRESCALER_DIV256, */
|
||||
/* TC_WAVE_GENERATION_NORMAL_FREQ, */
|
||||
/* TC_RELOAD_ACTION_GCLK, */
|
||||
/* TC_COUNT_DIRECTION_UP, */
|
||||
/* TC_WAVEFORM_INVERT_OUTPUT_NONE, */
|
||||
/* false, /\* Oneshot *\/ */
|
||||
/* false, /\* Run in standby *\/ */
|
||||
/* 0x0000, /\* Initial value *\/ */
|
||||
/* 0xFFFF, /\* Top value *\/ */
|
||||
/* t4_capture_channel_enables, /\* Capture Channel Enables *\/ */
|
||||
/* t4_compare_channel_values); /\* Compare Channels Values *\/ */
|
||||
|
||||
/* Timer 4 generates an event on compare channel 0 */
|
||||
struct tc_events events;
|
||||
events.generate_event_on_compare_channel[0] = true;
|
||||
events.generate_event_on_compare_channel[1] = false;
|
||||
events.generate_event_on_overflow = false;
|
||||
events.invert_event_input = false;
|
||||
events.on_event_perform_action = true;
|
||||
events.event_action = TC_EVENT_ACTION_RETRIGGER;
|
||||
tc_enable_events(TC4, &events);
|
||||
/* /\* Timer 4 generates an event on compare channel 0 *\/ */
|
||||
/* struct tc_events events; */
|
||||
/* events.generate_event_on_compare_channel[0] = true; */
|
||||
/* events.generate_event_on_compare_channel[1] = false; */
|
||||
/* events.generate_event_on_overflow = false; */
|
||||
/* events.invert_event_input = false; */
|
||||
/* events.on_event_perform_action = true; */
|
||||
/* events.event_action = TC_EVENT_ACTION_RETRIGGER; */
|
||||
/* 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 */
|
||||
events_allocate(0,
|
||||
EVENTS_EDGE_DETECT_NONE,
|
||||
EVENTS_PATH_ASYNCHRONOUS,
|
||||
0x29, /* TC4 MC0 */
|
||||
0);
|
||||
/* /\* This event is picked up on event channel 0 *\/ */
|
||||
/* events_allocate(0, */
|
||||
/* EVENTS_EDGE_DETECT_NONE, */
|
||||
/* EVENTS_PATH_ASYNCHRONOUS, */
|
||||
/* 0x29, /\* TC4 MC0 *\/ */
|
||||
/* 0); */
|
||||
|
||||
/* This event is picked up on event channel 1 */
|
||||
events_allocate(1,
|
||||
EVENTS_EDGE_DETECT_NONE,
|
||||
EVENTS_PATH_ASYNCHRONOUS,
|
||||
0x29, /* TC4 MC0 */
|
||||
0);
|
||||
/* /\* This event is picked up on event channel 1 *\/ */
|
||||
/* events_allocate(1, */
|
||||
/* EVENTS_EDGE_DETECT_NONE, */
|
||||
/* EVENTS_PATH_ASYNCHRONOUS, */
|
||||
/* 0x29, /\* TC4 MC0 *\/ */
|
||||
/* 0); */
|
||||
|
||||
tc_enable(TC4); /* Retrigger event means counter doesn't start yet */
|
||||
tc_start_counter(TC4); /* We start it manually now */
|
||||
}
|
||||
void osc8m_event_source_disable(void) {
|
||||
tc_disable(TC4);
|
||||
}
|
||||
/* tc_enable(TC4); /\* Retrigger event means counter doesn't start yet *\/ */
|
||||
/* tc_start_counter(TC4); /\* We start it manually now *\/ */
|
||||
/* } */
|
||||
/* void osc8m_event_source_disable(void) { */
|
||||
/* tc_disable(TC4); */
|
||||
/* } */
|
||||
|
||||
/**
|
||||
* Configure the timepulse extint to generate events
|
||||
|
@ -212,7 +212,7 @@ void measure_xosc(enum xosc_measurement_t measurement_t,
|
|||
/* Configure an event source */
|
||||
switch (measurement_t) {
|
||||
case XOSC_MEASURE_OSC8M:
|
||||
osc8m_event_source(); // osc8m issues events
|
||||
// osc8m_event_source(); // osc8m issues events
|
||||
break;
|
||||
case XOSC_MEASURE_TIMEPULSE:
|
||||
timepulse_extint_event_source(); // timepulse issues events
|
||||
|
@ -227,7 +227,7 @@ void measure_xosc_disable(enum xosc_measurement_t measurement_t) {
|
|||
|
||||
switch (measurement_t) {
|
||||
case XOSC_MEASURE_OSC8M:
|
||||
osc8m_event_source_disable();
|
||||
// osc8m_event_source_disable();
|
||||
break;
|
||||
case XOSC_MEASURE_TIMEPULSE:
|
||||
timepulse_extint_event_source_disable();
|
||||
|
|
Ładowanie…
Reference in New Issue