[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
Richard Meadows 2016-03-04 20:41:39 +00:00
rodzic 236d47c301
commit 2d7defaf42
8 zmienionych plików z 231 dodań i 19 usunięć

Wyświetl plik

@ -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 */

Wyświetl plik

@ -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);

Wyświetl plik

@ -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();

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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);

Wyświetl plik

@ -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;

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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);
}
}
}
}