kopia lustrzana https://github.com/bristol-seds/pico-tracker
[drift] Testing compensation of xosc drift against the lftimer. Doesn't work awfully well so disabled.
The lftimer isn't stable enough, compensation would be possible over a longer timescale maybe.main-solar-only
rodzic
236d47c301
commit
2d7defaf42
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Monitors xosc drift while transmitting
|
||||||
|
* Copyright (C) 2016 Richard Meadows <richardeoin>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DRIFT_H
|
||||||
|
#define DRIFT_H
|
||||||
|
|
||||||
|
#include "samd20.h"
|
||||||
|
#include "si_trx.h"
|
||||||
|
|
||||||
|
int16_t drift_get_channel_offset(void);
|
||||||
|
void drift_set_fconfig(struct si_frequency_configuration* config);
|
||||||
|
void drift_measure_start(void);
|
||||||
|
void drift_measure_stop(void);
|
||||||
|
|
||||||
|
#endif /* DRIFT_H */
|
|
@ -28,8 +28,8 @@
|
||||||
#include "samd20.h"
|
#include "samd20.h"
|
||||||
|
|
||||||
enum xosc_measurement_t {
|
enum xosc_measurement_t {
|
||||||
XOSC_MEASURE_GCLK0,
|
|
||||||
XOSC_MEASURE_TIMEPULSE,
|
XOSC_MEASURE_TIMEPULSE,
|
||||||
|
XOSC_MEASURE_LFTIMER,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*measurement_result_t)(uint32_t result);
|
typedef void (*measurement_result_t)(uint32_t result);
|
||||||
|
@ -54,7 +54,8 @@ void gclk1_init(void);
|
||||||
void gclk2_init(void);
|
void gclk2_init(void);
|
||||||
|
|
||||||
/** Measurement */
|
/** Measurement */
|
||||||
void measure_xosc(enum xosc_measurement_t measurement_t, measurement_result_t callback);
|
void measure_xosc(enum xosc_measurement_t measurement_t, measurement_result_t callback, uint8_t oneshot);
|
||||||
|
void measure_xosc_disable(enum xosc_measurement_t measurement_t);
|
||||||
|
|
||||||
/** LF Timer */
|
/** LF Timer */
|
||||||
void lf_tick_start(void);
|
void lf_tick_start(void);
|
||||||
|
|
|
@ -55,8 +55,9 @@ void collect_data_async(void)
|
||||||
#endif /* GPS_TYPE_UBX */
|
#endif /* GPS_TYPE_UBX */
|
||||||
|
|
||||||
/* Measure XOSC against gps timepulse */
|
/* Measure XOSC against gps timepulse */
|
||||||
//measure_xosc(XOSC_MEASURE_TIMEPULSE, xosc_measure_callback);
|
/* single shot, ongoing until two rising edges on GPS TIMEPULSE */
|
||||||
/* NOT IN USE CURRENTLY */
|
/* NOT IN USE CURRENTLY */
|
||||||
|
//measure_xosc(XOSC_MEASURE_TIMEPULSE, xosc_measure_callback, 1);
|
||||||
|
|
||||||
/* Analogue Measurements */
|
/* Analogue Measurements */
|
||||||
start_adc_sequence();
|
start_adc_sequence();
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
* Monitors xosc drift while transmitting
|
||||||
|
* Copyright (C) 2016 Richard Meadows <richardeoin>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "samd20.h"
|
||||||
|
#include "hw_config.h"
|
||||||
|
#include "si_trx.h"
|
||||||
|
#include "xosc.h"
|
||||||
|
#include "drift.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initial reference, in Hz
|
||||||
|
*/
|
||||||
|
uint32_t initial_xosc_frequency;
|
||||||
|
/**
|
||||||
|
* Current offset, in Hz at the xosc output
|
||||||
|
* +ve if xosc too fast, -ve if xosc too slow
|
||||||
|
*/
|
||||||
|
float current_frequency_offset;
|
||||||
|
/**
|
||||||
|
* Current frequency configuration
|
||||||
|
*/
|
||||||
|
struct si_frequency_configuration* _fconfig = NULL;
|
||||||
|
/**
|
||||||
|
* Current offset, in rf channels for the current frequency configuration
|
||||||
|
* +ve if xosc too fast, -ve if xosc too slow
|
||||||
|
*/
|
||||||
|
volatile int16_t current_channel_offset;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moving average
|
||||||
|
*/
|
||||||
|
#define MOVING_AVERAGE_N (8)
|
||||||
|
int32_t frequency_moving_average[MOVING_AVERAGE_N];
|
||||||
|
uint32_t frequency_moving_average_index = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The result is the xosc frequency in Hz
|
||||||
|
*/
|
||||||
|
void xosc_drift_measure_callback(uint32_t result)
|
||||||
|
{
|
||||||
|
int32_t offset;
|
||||||
|
|
||||||
|
if (initial_xosc_frequency == 0) { /* Initial reference */
|
||||||
|
initial_xosc_frequency = result;
|
||||||
|
offset = 0;
|
||||||
|
frequency_moving_average[0] = 0;
|
||||||
|
frequency_moving_average_index++;
|
||||||
|
} else {
|
||||||
|
offset = result - initial_xosc_frequency;
|
||||||
|
|
||||||
|
/* add to moving average */
|
||||||
|
frequency_moving_average[(frequency_moving_average_index % 8)] = offset;
|
||||||
|
|
||||||
|
/* calculate average */
|
||||||
|
uint32_t n = (frequency_moving_average_index > 8) ? 8: frequency_moving_average_index;
|
||||||
|
float sum = 0;
|
||||||
|
for (uint32_t i = 0; i < n; i++) {
|
||||||
|
sum += frequency_moving_average[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* record result */
|
||||||
|
current_frequency_offset = sum / n;
|
||||||
|
frequency_moving_average_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_fconfig != NULL) { /* if we seem to have a fconfig */
|
||||||
|
float rfband_offset_hz = ((float)current_frequency_offset * _fconfig->frequency)
|
||||||
|
/ XOSC_FREQUENCY;
|
||||||
|
|
||||||
|
float channel_offset_f = rfband_offset_hz / _fconfig->lsb_tuning_resolution;
|
||||||
|
current_channel_offset = (int16_t)round(channel_offset_f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current channel delta caused by drift.
|
||||||
|
*
|
||||||
|
* The subtract this from the intended channel to compensate.
|
||||||
|
*/
|
||||||
|
int16_t drift_get_channel_offset(void)
|
||||||
|
{
|
||||||
|
return current_channel_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current frequency configuration.
|
||||||
|
*
|
||||||
|
* drift_get_channel_offset will always return zero if this is not set
|
||||||
|
*/
|
||||||
|
void drift_set_fconfig(struct si_frequency_configuration* config)
|
||||||
|
{
|
||||||
|
_fconfig = config;
|
||||||
|
current_channel_offset = 0;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Start xosc drift measurements
|
||||||
|
*/
|
||||||
|
void drift_measure_start(void)
|
||||||
|
{
|
||||||
|
initial_xosc_frequency = 0;
|
||||||
|
current_frequency_offset = 0;
|
||||||
|
current_channel_offset = 0;
|
||||||
|
frequency_moving_average_index = 0;
|
||||||
|
|
||||||
|
/* start ontinuous measurement (oneshot=0) */
|
||||||
|
measure_xosc(XOSC_MEASURE_LFTIMER, xosc_drift_measure_callback, 0);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Stop xosc drift measurements
|
||||||
|
*/
|
||||||
|
void drift_measure_stop(void)
|
||||||
|
{
|
||||||
|
/* clear offsets to zero while we're stopped */
|
||||||
|
initial_xosc_frequency = 0;
|
||||||
|
current_frequency_offset = 0;
|
||||||
|
current_channel_offset = 0;
|
||||||
|
|
||||||
|
/* stop measurement */
|
||||||
|
measure_xosc_disable(XOSC_MEASURE_LFTIMER);
|
||||||
|
}
|
|
@ -111,7 +111,6 @@ void init(enum init_type init_t)
|
||||||
gclk0_to_hf_clock(); /* and switch, clock at 8MHz */
|
gclk0_to_hf_clock(); /* and switch, clock at 8MHz */
|
||||||
gclk1_init();
|
gclk1_init();
|
||||||
gclk2_init();
|
gclk2_init();
|
||||||
rtc_init();
|
|
||||||
|
|
||||||
/* Clock up to 14MHz with 0 wait states */
|
/* Clock up to 14MHz with 0 wait states */
|
||||||
system_flash_set_waitstates(SYSTEM_WAIT_STATE_1_8V_14MHZ);
|
system_flash_set_waitstates(SYSTEM_WAIT_STATE_1_8V_14MHZ);
|
||||||
|
|
|
@ -46,7 +46,7 @@ void rtc_init(void)
|
||||||
for (uint8_t i = 0; i < RTC_NUM_OF_COMP16; i++) {
|
for (uint8_t i = 0; i < RTC_NUM_OF_COMP16; i++) {
|
||||||
config_events.generate_event_on_compare[i] = false;
|
config_events.generate_event_on_compare[i] = false;
|
||||||
}
|
}
|
||||||
for (uint8_t i = 0; i < 7; i++) {
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
config_events.generate_event_on_periodic[i] = false;
|
config_events.generate_event_on_periodic[i] = false;
|
||||||
}
|
}
|
||||||
config_events.generate_event_on_periodic[7] = true;
|
config_events.generate_event_on_periodic[7] = true;
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "aprs.h"
|
#include "aprs.h"
|
||||||
#include "ax25.h"
|
#include "ax25.h"
|
||||||
#include "pips.h"
|
#include "pips.h"
|
||||||
|
#include "drift.h"
|
||||||
#include "si_trx.h"
|
#include "si_trx.h"
|
||||||
#include "si_trx_defs.h"
|
#include "si_trx_defs.h"
|
||||||
#include "system/gclk.h"
|
#include "system/gclk.h"
|
||||||
|
@ -455,6 +456,9 @@ void telemetry_init(void)
|
||||||
|
|
||||||
/* Setup fconfig for telemetry. This is static */
|
/* Setup fconfig for telemetry. This is static */
|
||||||
si_trx_get_frequency_configuration(&telemetry_fconfig, TELEMETRY_FREQUENCY);
|
si_trx_get_frequency_configuration(&telemetry_fconfig, TELEMETRY_FREQUENCY);
|
||||||
|
|
||||||
|
/* We only compensate drift for telemetry, set fconfig for this */
|
||||||
|
drift_set_fconfig(&telemetry_fconfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "tc/tc_driver.h"
|
#include "tc/tc_driver.h"
|
||||||
#include "hw_config.h"
|
#include "hw_config.h"
|
||||||
#include "xosc.h"
|
#include "xosc.h"
|
||||||
|
#include "rtc.h"
|
||||||
#include "watchdog.h"
|
#include "watchdog.h"
|
||||||
|
|
||||||
enum measure_state_t {
|
enum measure_state_t {
|
||||||
|
@ -42,6 +43,7 @@ enum measure_state_t {
|
||||||
MEASURE_MEASUREMENT,
|
MEASURE_MEASUREMENT,
|
||||||
} measure_state = MEASURE_WAIT_FOR_FIRST_EVENT;
|
} measure_state = MEASURE_WAIT_FOR_FIRST_EVENT;
|
||||||
enum xosc_measurement_t _measurement_t;
|
enum xosc_measurement_t _measurement_t;
|
||||||
|
uint8_t _measurement_oneshot;
|
||||||
measurement_result_t _callback;
|
measurement_result_t _callback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -358,17 +360,38 @@ void timepulse_extint_event_source_disable(void) {
|
||||||
extint_disable();
|
extint_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure 1Hz events from the LF Timer
|
||||||
|
*/
|
||||||
|
void lftimer_event_source(void)
|
||||||
|
{
|
||||||
|
/* Start the RTC */
|
||||||
|
rtc_init();
|
||||||
|
|
||||||
|
/* Route the RTC PER7 event to event channel 0 */
|
||||||
|
events_allocate(0,
|
||||||
|
EVENTS_EDGE_DETECT_NONE, /* Don't care for async path */
|
||||||
|
EVENTS_PATH_ASYNCHRONOUS,
|
||||||
|
0xB, /* RTC PER7 event */
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
void lftimer_event_source_disable(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers a measurements the number of cycles on XOSC
|
* Triggers a measurements the number of cycles on XOSC
|
||||||
*
|
*
|
||||||
* A callback from the timer interrupt is available. Obviously don't dwell here too long.
|
* A callback from the timer interrupt is available. Obviously don't dwell here too long.
|
||||||
*/
|
*/
|
||||||
void measure_xosc(enum xosc_measurement_t measurement_t,
|
void measure_xosc(enum xosc_measurement_t measurement_t,
|
||||||
measurement_result_t callback) {
|
measurement_result_t callback, uint8_t oneshot) {
|
||||||
|
|
||||||
measure_state = MEASURE_WAIT_FOR_FIRST_EVENT;
|
measure_state = MEASURE_WAIT_FOR_FIRST_EVENT;
|
||||||
_measurement_t = measurement_t;
|
_measurement_t = measurement_t;
|
||||||
_callback = callback;
|
_callback = callback;
|
||||||
|
_measurement_oneshot = oneshot;
|
||||||
|
|
||||||
/* Timer 2 runs on GLCK1 */
|
/* Timer 2 runs on GLCK1 */
|
||||||
bool t2_capture_channel_enables[] = {true, true};
|
bool t2_capture_channel_enables[] = {true, true};
|
||||||
|
@ -408,11 +431,11 @@ 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_GCLK0:
|
|
||||||
// osc8m_event_source(); // osc8m issues events
|
|
||||||
break;
|
|
||||||
case XOSC_MEASURE_TIMEPULSE:
|
case XOSC_MEASURE_TIMEPULSE:
|
||||||
timepulse_extint_event_source(); // timepulse issues events
|
timepulse_extint_event_source(); /* timepulse issues events at 1Hz */
|
||||||
|
break;
|
||||||
|
case XOSC_MEASURE_LFTIMER:
|
||||||
|
lftimer_event_source(); /* lftier issues events at 1Hz */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,12 +446,12 @@ void measure_xosc_disable(enum xosc_measurement_t measurement_t) {
|
||||||
tc_disable(TC2);
|
tc_disable(TC2);
|
||||||
|
|
||||||
switch (measurement_t) {
|
switch (measurement_t) {
|
||||||
case XOSC_MEASURE_GCLK0:
|
|
||||||
// osc8m_event_source_disable();
|
|
||||||
break;
|
|
||||||
case XOSC_MEASURE_TIMEPULSE:
|
case XOSC_MEASURE_TIMEPULSE:
|
||||||
timepulse_extint_event_source_disable();
|
timepulse_extint_event_source_disable();
|
||||||
break;
|
break;
|
||||||
|
case XOSC_MEASURE_LFTIMER:
|
||||||
|
lftimer_event_source_disable();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,17 +472,17 @@ void TC2_Handler(void) {
|
||||||
measure_state = MEASURE_MEASUREMENT; /* Start measurement */
|
measure_state = MEASURE_MEASUREMENT; /* Start measurement */
|
||||||
break;
|
break;
|
||||||
case MEASURE_MEASUREMENT:
|
case MEASURE_MEASUREMENT:
|
||||||
/* Measurement done. Read off data */
|
/* Measurement made. Read off data */
|
||||||
capture_value = tc_get_capture_value(TC2, 0);
|
capture_value = tc_get_capture_value(TC2, 0);
|
||||||
|
|
||||||
/* Calcuate the frequency of GLCK1 relative to this source */
|
/* Calcuate the frequency of GLCK1 relative to this source */
|
||||||
switch (_measurement_t) {
|
switch (_measurement_t) {
|
||||||
case XOSC_MEASURE_GCLK0:
|
|
||||||
source_freq = capture_value * XOSC_GCLK_DIVIDE;
|
|
||||||
break;
|
|
||||||
case XOSC_MEASURE_TIMEPULSE:
|
case XOSC_MEASURE_TIMEPULSE:
|
||||||
source_freq = capture_value * XOSC_GCLK_DIVIDE * GPS_TIMEPULSE_FREQ;
|
source_freq = capture_value * XOSC_GCLK_DIVIDE * GPS_TIMEPULSE_FREQ;
|
||||||
break;
|
break;
|
||||||
|
case XOSC_MEASURE_LFTIMER:
|
||||||
|
source_freq = capture_value * XOSC_GCLK_DIVIDE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback if we have one */
|
/* Callback if we have one */
|
||||||
|
@ -467,8 +490,10 @@ void TC2_Handler(void) {
|
||||||
_callback(source_freq);
|
_callback(source_freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable measurement system */
|
if (_measurement_oneshot != 0) { /* single shot */
|
||||||
measure_xosc_disable(_measurement_t);
|
/* Disable measurement system */
|
||||||
|
measure_xosc_disable(_measurement_t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue