Merge pull request #62 from kd2eat/dfm17

Added a timepulse routine for DFM17 and also a millis() routine.
dfm17
Mikael Nousiainen 2023-10-14 11:07:59 +03:00 zatwierdzone przez GitHub
commit 61e428789a
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
16 zmienionych plików z 297 dodań i 14 usunięć

Wyświetl plik

@ -30,7 +30,7 @@ size_t aprs_generate_position(uint8_t *payload, size_t length, telemetry_data *d
return snprintf((char *) payload,
length,
("%s%02d%02d.%02u%c%c%03d%02u.%02u%c%c%03d/%03d/A=%06d/P%dS%dT%02dV%04dC%02d%s"),
("%s%02d%02d.%02u%c%c%03d%02u.%02u%c%c%03d/%03d/A=%06d/P%dS%dT%02dV%04dC%02dR%02dU%02d%s"),
timestamp,
abs(la_degrees), la_minutes, la_h_minutes,
la_degrees > 0 ? 'N' : 'S',
@ -46,6 +46,8 @@ size_t aprs_generate_position(uint8_t *payload, size_t length, telemetry_data *d
(int) data->internal_temperature_celsius_100 / 100,
data->battery_voltage_millivolts,
(int16_t) ((float) data->gps.climb_cm_per_second / 100.0f),
data->clock_calibration,
data->clock_calibration_count,
comment
);
}

Wyświetl plik

@ -69,6 +69,9 @@
#define BANK_GREEN_LED GPIOC
#define PIN_GREEN_LED GPIO_Pin_6
#define BANK_YELLOW_LED GPIOC
#define PIN_YELLOW_LED GPIO_Pin_7
#define BANK_MOSI GPIOA
#define PIN_MOSI GPIO_Pin_7
#define BANK_SCK GPIOA

Wyświetl plik

@ -34,8 +34,8 @@ void data_timer_init(uint32_t baud_rate)
NVIC_InitTypeDef nvic_init;
nvic_init.NVIC_IRQChannel = TIM2_IRQn;
nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
nvic_init.NVIC_IRQChannelSubPriority = 1;
nvic_init.NVIC_IRQChannelPreemptionPriority = 2;
nvic_init.NVIC_IRQChannelSubPriority = 2;
nvic_init.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_init);
@ -48,8 +48,8 @@ void data_timer_uninit()
NVIC_InitTypeDef nvic_init;
nvic_init.NVIC_IRQChannel = TIM2_IRQn;
nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
nvic_init.NVIC_IRQChannelSubPriority = 1;
nvic_init.NVIC_IRQChannelPreemptionPriority = 2;
nvic_init.NVIC_IRQChannelSubPriority = 2;
nvic_init.NVIC_IRQChannelCmd = DISABLE;
NVIC_Init(&nvic_init);

Wyświetl plik

@ -31,7 +31,7 @@ void delay_init()
NVIC_InitTypeDef nvic_init;
nvic_init.NVIC_IRQChannel = TIM3_IRQn;
nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
nvic_init.NVIC_IRQChannelPreemptionPriority = 1;
nvic_init.NVIC_IRQChannelSubPriority = 1;
nvic_init.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_init);

67
src/hal/millis.c 100644
Wyświetl plik

@ -0,0 +1,67 @@
#include <stm32f10x_rcc.h>
#include <stm32f10x_tim.h>
#include <misc.h>
#include "src/hal/millis.h"
static uint32_t millis_counter;
void millis_timer_init(void)
{
TIM_DeInit(TIM7);
TIM_TimeBaseInitTypeDef tim_init;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB1Periph_TIM7, DISABLE);
// The data timer assumes a 24 MHz clock source
tim_init.TIM_Prescaler = 24 - 1; // tick every 1/1000000 s
tim_init.TIM_CounterMode = TIM_CounterMode_Up;
tim_init.TIM_Period = (uint16_t) (1000 - 1); // Timer pop 1/millisec
tim_init.TIM_ClockDivision = TIM_CKD_DIV1;
tim_init.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM7, &tim_init);
TIM_ClearITPendingBit(TIM7, TIM_IT_Update);
TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE);
NVIC_InitTypeDef nvic_init;
nvic_init.NVIC_IRQChannel = TIM7_IRQn;
nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
nvic_init.NVIC_IRQChannelSubPriority = 1;
nvic_init.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_init);
TIM_Cmd(TIM7, ENABLE);
}
void millis_timer_uninit()
{
TIM_Cmd(TIM7, DISABLE);
NVIC_InitTypeDef nvic_init;
nvic_init.NVIC_IRQChannel = TIM7_IRQn;
nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
nvic_init.NVIC_IRQChannelSubPriority = 1;
nvic_init.NVIC_IRQChannelCmd = DISABLE;
NVIC_Init(&nvic_init);
TIM_ITConfig(TIM7, TIM_IT_Update, DISABLE);
TIM_ClearITPendingBit(TIM7, TIM_IT_Update);
}
void TIM7_IRQHandler(void)
{
if (TIM_GetITStatus(TIM7, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM7, TIM_IT_Update);
millis_counter++;
}
}
uint32_t millis(void)
{
return millis_counter;
}

10
src/hal/millis.h 100644
Wyświetl plik

@ -0,0 +1,10 @@
#ifndef __MILLIS_H
#define __MILLIS_H
extern void millis_timer_init(void);
extern void millis_timer_uninit();
extern uint32_t millis();
#endif // __MILLIS_H

Wyświetl plik

@ -43,8 +43,8 @@ void pwm_data_timer_init()
NVIC_InitTypeDef nvic_init;
nvic_init.NVIC_IRQChannel = TIM2_IRQn;
nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
nvic_init.NVIC_IRQChannelSubPriority = 1;
nvic_init.NVIC_IRQChannelPreemptionPriority = 2;
nvic_init.NVIC_IRQChannelSubPriority = 2;
nvic_init.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_init);
*/
@ -117,7 +117,7 @@ void pwm_timer_init(uint32_t frequency_hz_100)
NVIC_InitTypeDef nvic_init;
nvic_init.NVIC_IRQChannel = TIM1_BRK_TIM15_IRQn;
nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
nvic_init.NVIC_IRQChannelPreemptionPriority = 2;
nvic_init.NVIC_IRQChannelSubPriority = 1;
nvic_init.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_init);
@ -164,8 +164,8 @@ void pwm_dma_init()
NVIC_InitTypeDef nvic_init;
nvic_init.NVIC_IRQChannel = DMA1_Channel2_IRQn;
nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
nvic_init.NVIC_IRQChannelSubPriority = 1;
nvic_init.NVIC_IRQChannelPreemptionPriority = 2;
nvic_init.NVIC_IRQChannelSubPriority = 0;
nvic_init.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_init);
}
@ -246,6 +246,7 @@ inline void pwm_timer_set_frequency(uint32_t pwm_period)
// TIM_CtrlPWMOutputs(TIM15, DISABLE);
// TIM_Cmd(TIM15, DISABLE);
// TIM_SetAutoreload(TIM15, pwm_period);
TIM_SetAutoreload(TIM15, pwm_period);
// TIM_SetCompare2(TIM15, pwm_period / 2);

Wyświetl plik

@ -12,6 +12,7 @@
#include "delay.h"
#include "log.h"
#include "gpio.h"
#include "millis.h"
#define BUTTON_PRESS_LONG_COUNT SYSTEM_SCHEDULER_TIMER_TICKS_PER_SECOND
@ -126,6 +127,15 @@ static void gpio_init()
gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(BANK_RED_LED, &gpio_init);
#ifdef DFM17
// Yellow LED
gpio_init.GPIO_Pin = PIN_YELLOW_LED;
gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(BANK_YELLOW_LED, &gpio_init);
#endif //DFM17
}
/**
@ -343,6 +353,24 @@ void system_set_red_led(bool enabled)
#endif
}
void system_set_yellow_led(bool enabled)
{
#ifdef RS41
if (enabled) {
GPIO_ResetBits(BANK_YELLOW_LED, PIN_YELLOW_LED);
} else {
GPIO_SetBits(BANK_YELLOW_LED, PIN_YELLOW_LED);
}
#endif
#ifdef DFM17
if (enabled) {
GPIO_SetBits(BANK_YELLOW_LED, PIN_YELLOW_LED);
} else {
GPIO_ResetBits(BANK_YELLOW_LED, PIN_YELLOW_LED);
}
#endif
}
void system_disable_irq()
{
__disable_irq();
@ -360,7 +388,7 @@ void system_init()
gpio_init();
dma_adc_init();
delay_init();
millis_timer_init();
system_scheduler_timer_init();
RCC_ClocksTypeDef RCC_Clocks;

Wyświetl plik

@ -1,6 +1,7 @@
#ifndef __HAL_SYSTEM_H
#define __HAL_SYSTEM_H
#include "config.h"
#include "hal.h"
#define GPIO_PIN_LED_GREEN GPIO_Pin_7
@ -17,6 +18,9 @@ void system_disable_irq();
void system_enable_irq();
void system_set_green_led(bool enabled);
void system_set_red_led(bool enabled);
#ifdef DFM17
void system_set_yellow_led(bool enabled);
#endif //DFM17
uint16_t system_get_battery_voltage_millivolts();
uint16_t system_get_button_adc_value();

120
src/hal/timepulse.c 100644
Wyświetl plik

@ -0,0 +1,120 @@
#include "stm32f10x_exti.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "misc.h"
#include "config.h"
#include "system.h"
#include "millis.h"
#include "timepulse.h"
// This define copied from .../src/hal/stm_lib/src/stm32f10x_rcc.c
#define CR_HSITRIM_Mask ((uint32_t)0xFFFFFF07)
// Define below pulls the current trim register value out of the Calibration Register (CR)
// Resulting value will be between 0-31.
#define CURRENT_TRIM ((RCC->CR & ~CR_HSITRIM_Mask) >>3)
/*
On the DFM-17, PB8 is wired to the GPS Timepulse. We take advantage of this to do a
processor speed calibration. HSITRIM[4:0] allows for 32 values to adjust the HSI clock
speed. The center (16) value is "neutral". Each trim value above or below 16 adjusts
the clock by approximately 40kHZ (0.5% of the 8MHZ clock speed) (per AN2868). 0.5% is about
5ms per second, so if we detect that we're off by more than 5 millisconds between timepulses, we
will suggest a recalibration. The "calib_suggestion" variable is a static that will be maintained
by the timepulse IRQ and can be used at any time it's convenient to adjust the clock speed.
*/
int calib_suggestion = 16; // Default, but we will check it in the init routine below.
int calib_current = 16; // Default, but we will check it in the init routine below.
uint32_t old_millis = 0;
volatile int timepulsed = 0;
volatile uint32_t d_millis = 0;
bool yellowLEDstate = true;
uint16_t calib_change_count = 0;
uint8_t get_clock_calibration(void)
{
return(CURRENT_TRIM);
}
uint16_t get_calib_change_count(void)
{
return(calib_change_count);
}
void adjust_clock_calibration(void)
{
if (calib_suggestion != calib_current) {
RCC_AdjustHSICalibrationValue(calib_suggestion);
calib_current = calib_suggestion;
yellowLEDstate = !yellowLEDstate;
system_set_yellow_led(yellowLEDstate);
calib_change_count++;
}
}
void timepulse_init(void)
{
// Initialize pin PB8 as floating input
GPIO_InitTypeDef gpio_init;
gpio_init.GPIO_Pin = GPIO_Pin_8;
gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio_init.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOB, &gpio_init);
// PB8 is connected to interrupt line 8, set trigger on the configured edge and enable the interrupt
EXTI_InitTypeDef exti_init;
exti_init.EXTI_Line = EXTI_Line8;
exti_init.EXTI_Mode = EXTI_Mode_Interrupt;
exti_init.EXTI_Trigger = EXTI_Trigger_Rising;
exti_init.EXTI_LineCmd = ENABLE;
EXTI_Init(&exti_init);
// Attach interrupt line to port B
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource8);
// PB8 is connected to EXTI_Line8, which has EXTI9_5_IRQn vector. Use priority 0 for now.
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
// Pull the current calibration to start
calib_current = CURRENT_TRIM;
calib_suggestion = calib_current;
// Set the yellow LED to help identify calibration changes
system_set_yellow_led(yellowLEDstate);
}
// This handler is (at present) only being used for the Timepulse interrupt, so we shouldn't need
// to do additional testing for the cause of the interrupt.
void EXTI9_5_IRQHandler(void)
{
uint32_t m = millis();
int delta;
EXTI_ClearITPendingBit(EXTI_Line8);
timepulsed++;
if (old_millis == 0) {
old_millis = m; // First timepulse. Just store millis.
} else {
d_millis = m - old_millis; // mS since last timepulse. Ideally there were 1000.
old_millis = m;
delta = (int) (1000 - d_millis) / 5; // If too few clicks, speed up clock. If too many, slow down.
if (delta > 1) delta = 1; // Take one step at a time in case we had a bad clock tick
if (delta < -1) delta = -1;
// Don't allow calibration suggestion to go out of range
if (((delta + calib_current) >= 0) &&
((delta + calib_current <= 31)) ) {
// If the delta makes sense, apply to the suggestion. Otherwise, skip.
calib_suggestion = calib_current + delta;
}
}
}

Wyświetl plik

@ -0,0 +1,11 @@
#ifndef __TIMEPULSE_H
#define __TIMEPULSE_H
extern uint8_t get_clock_calibration(void);
extern uint16_t get_calib_change_count(void);
extern void timepulse_init(void);
extern void adjust_clock_calibration(void);
extern volatile int timepulsed;
#endif // __TIMEPULSE_H

Wyświetl plik

@ -49,7 +49,7 @@ void usart_gps_init(uint32_t baud_rate, bool enable_irq)
NVIC_InitTypeDef nvic_init;
nvic_init.NVIC_IRQChannel = USART_IRQ;
nvic_init.NVIC_IRQChannelPreemptionPriority = 15;
nvic_init.NVIC_IRQChannelPreemptionPriority = 3;
nvic_init.NVIC_IRQChannelSubPriority = 2;
nvic_init.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_init);

Wyświetl plik

@ -1,3 +1,4 @@
#include "hal/stm_lib/inc/stm32f10x_rcc.h"
#include "hal/system.h"
#include "hal/spi.h"
#include "hal/usart_gps.h"
@ -12,6 +13,8 @@
#include "radio.h"
#include "config.h"
#include "log.h"
#include "hal/timepulse.h"
#include "hal/millis.h"
#ifdef RS41
#include "hal/i2c.h"
@ -74,6 +77,18 @@ void set_red_led(bool enabled)
system_set_red_led(enabled);
}
#ifdef DFM17
void set_yellow_led(bool enabled)
{
if ((LEDS_DISABLE_ALTITUDE_METERS > 0) && (current_gps_data.altitude_mm / 1000 > LEDS_DISABLE_ALTITUDE_METERS)) {
enabled = false;
}
system_set_yellow_led(enabled);
}
#endif //DFM17
int main(void)
{
bool success;
@ -115,6 +130,20 @@ int main(void)
goto gps_init;
}
#ifdef DFM17
log_info("Timepulse init\n");
timepulse_init();
/*
while (1) {
if (timepulsed != 0) {
log_info("Time Pulse. Calib: %d\n", get_clock_calibration());
timepulsed = 0;
adjust_clock_calibration();
}
}
*/
#endif //DFM17
#if defined(RS41)
log_info("Si4032 init\n");
si4032_init();
@ -175,6 +204,9 @@ int main(void)
while (true) {
radio_handle_main_loop();
#ifdef DFM17
adjust_clock_calibration();
#endif //DFM17
//NVIC_SystemLPConfig(NVIC_LP_SEVONPEND, DISABLE);
//__WFI();
}

Wyświetl plik

@ -19,7 +19,7 @@
// TODO: Add support for multiple APRS baud rates
// This delay is for DFM-17 radiosondes
#define symbol_delay_bell_202_1200bps_us 820
#define symbol_delay_bell_202_1200bps_us 821
static volatile bool radio_si4063_state_change = false;
static volatile uint32_t radio_si4063_freq = 0;

Wyświetl plik

@ -7,6 +7,7 @@
#include "locator.h"
#include "config.h"
#include "log.h"
#include "hal/timepulse.h"
#ifdef RS41
#include "drivers/si4032/si4032.h"
@ -70,6 +71,8 @@ void telemetry_collect(telemetry_data *data)
data->gps.heading_degrees_100000 = 0;
data->gps.climb_cm_per_second = 0;
}
data->clock_calibration = get_clock_calibration();
data->clock_calibration_count = get_calib_change_count();
locator_from_lonlat(data->gps.longitude_degrees_1000000, data->gps.latitude_degrees_1000000,
LOCATOR_PAIR_COUNT_FULL, data->locator);

Wyświetl plik

@ -21,6 +21,8 @@ typedef struct _telemetry_data {
gps_data gps;
char locator[LOCATOR_PAIR_COUNT_FULL * 2 + 1];
int clock_calibration;
uint16_t clock_calibration_count;
} telemetry_data;
void telemetry_collect(telemetry_data *data);