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"
|
||||
|
||||
enum xosc_measurement_t {
|
||||
XOSC_MEASURE_GCLK0,
|
||||
XOSC_MEASURE_TIMEPULSE,
|
||||
XOSC_MEASURE_LFTIMER,
|
||||
};
|
||||
|
||||
typedef void (*measurement_result_t)(uint32_t result);
|
||||
|
@ -54,7 +54,8 @@ void gclk1_init(void);
|
|||
void gclk2_init(void);
|
||||
|
||||
/** 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 */
|
||||
void lf_tick_start(void);
|
||||
|
|
|
@ -55,8 +55,9 @@ void collect_data_async(void)
|
|||
#endif /* GPS_TYPE_UBX */
|
||||
|
||||
/* 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 */
|
||||
//measure_xosc(XOSC_MEASURE_TIMEPULSE, xosc_measure_callback, 1);
|
||||
|
||||
/* Analogue Measurements */
|
||||
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 */
|
||||
gclk1_init();
|
||||
gclk2_init();
|
||||
rtc_init();
|
||||
|
||||
/* Clock up to 14MHz with 0 wait states */
|
||||
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++) {
|
||||
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[7] = true;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "aprs.h"
|
||||
#include "ax25.h"
|
||||
#include "pips.h"
|
||||
#include "drift.h"
|
||||
#include "si_trx.h"
|
||||
#include "si_trx_defs.h"
|
||||
#include "system/gclk.h"
|
||||
|
@ -455,6 +456,9 @@ void telemetry_init(void)
|
|||
|
||||
/* Setup fconfig for telemetry. This is static */
|
||||
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 "hw_config.h"
|
||||
#include "xosc.h"
|
||||
#include "rtc.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
enum measure_state_t {
|
||||
|
@ -42,6 +43,7 @@ enum measure_state_t {
|
|||
MEASURE_MEASUREMENT,
|
||||
} measure_state = MEASURE_WAIT_FOR_FIRST_EVENT;
|
||||
enum xosc_measurement_t _measurement_t;
|
||||
uint8_t _measurement_oneshot;
|
||||
measurement_result_t _callback;
|
||||
|
||||
/**
|
||||
|
@ -358,17 +360,38 @@ void timepulse_extint_event_source_disable(void) {
|
|||
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
|
||||
*
|
||||
* A callback from the timer interrupt is available. Obviously don't dwell here too long.
|
||||
*/
|
||||
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;
|
||||
_measurement_t = measurement_t;
|
||||
_callback = callback;
|
||||
_measurement_oneshot = oneshot;
|
||||
|
||||
/* Timer 2 runs on GLCK1 */
|
||||
bool t2_capture_channel_enables[] = {true, true};
|
||||
|
@ -408,11 +431,11 @@ void measure_xosc(enum xosc_measurement_t measurement_t,
|
|||
|
||||
/* Configure an event source */
|
||||
switch (measurement_t) {
|
||||
case XOSC_MEASURE_GCLK0:
|
||||
// osc8m_event_source(); // osc8m issues events
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -423,12 +446,12 @@ void measure_xosc_disable(enum xosc_measurement_t measurement_t) {
|
|||
tc_disable(TC2);
|
||||
|
||||
switch (measurement_t) {
|
||||
case XOSC_MEASURE_GCLK0:
|
||||
// osc8m_event_source_disable();
|
||||
break;
|
||||
case XOSC_MEASURE_TIMEPULSE:
|
||||
timepulse_extint_event_source_disable();
|
||||
break;
|
||||
case XOSC_MEASURE_LFTIMER:
|
||||
lftimer_event_source_disable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -449,17 +472,17 @@ void TC2_Handler(void) {
|
|||
measure_state = MEASURE_MEASUREMENT; /* Start measurement */
|
||||
break;
|
||||
case MEASURE_MEASUREMENT:
|
||||
/* Measurement done. Read off data */
|
||||
/* Measurement made. Read off data */
|
||||
capture_value = tc_get_capture_value(TC2, 0);
|
||||
|
||||
/* Calcuate the frequency of GLCK1 relative to this source */
|
||||
switch (_measurement_t) {
|
||||
case XOSC_MEASURE_GCLK0:
|
||||
source_freq = capture_value * XOSC_GCLK_DIVIDE;
|
||||
break;
|
||||
case XOSC_MEASURE_TIMEPULSE:
|
||||
source_freq = capture_value * XOSC_GCLK_DIVIDE * GPS_TIMEPULSE_FREQ;
|
||||
break;
|
||||
case XOSC_MEASURE_LFTIMER:
|
||||
source_freq = capture_value * XOSC_GCLK_DIVIDE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Callback if we have one */
|
||||
|
@ -467,8 +490,10 @@ void TC2_Handler(void) {
|
|||
_callback(source_freq);
|
||||
}
|
||||
|
||||
/* Disable measurement system */
|
||||
measure_xosc_disable(_measurement_t);
|
||||
if (_measurement_oneshot != 0) { /* single shot */
|
||||
/* Disable measurement system */
|
||||
measure_xosc_disable(_measurement_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue