fixed bug with systick correction

This commit is contained in:
eddyem 2019-08-07 17:16:14 +03:00
parent 57ad234091
commit abdbac3e38
10 changed files with 188 additions and 93 deletions

View File

@ -182,6 +182,8 @@ void GPS_parse_answer(const char *buf){
GPS_status = GPS_VALID; GPS_status = GPS_VALID;
set_time(buf); set_time(buf);
}else{ }else{
uint8_t goth = (buf[0]-'0')*10 + buf[1]-'0';
if(current_time.H != goth) set_time(buf); // set time once per hour even if it's not valid
GPS_status = GPS_NOT_VALID; GPS_status = GPS_NOT_VALID;
} }
} }

View File

@ -3,18 +3,24 @@ Chronometer for downhill competitions
## Pinout ## Pinout
- PA11/12 - USB
- PA9(Tx),PA10 (debug mode) - USART1 - debug console - PA9(Tx),PA10 (debug mode) - USART1 - debug console
- PA2(Tx), PA3 - USART2 - GPS - PA2(Tx), PA3 - USART2 - GPS
- PB10(Tx), PB11 - USART3 - LIDAR - PB10(Tx), PB11 - USART3 - LIDAR - TRIG3
- PA1 - PPS signal from GPS (EXTI) - PA1 - PPS signal from GPS (EXTI)
- PB8, PB9 - onboard LEDs - PA4 - TRIG2 - 12V trigger (EXTI)
- PA4 - TRIG2 - 12V trigger (EXTI) -- not implemented yet
- PA13 - TRIG0 - button0 (EXTI) - PA13 - TRIG0 - button0 (EXTI)
- PA14 - TRIG1 - button1/laser/etc (EXTI) - PA14 - TRIG1 - button1/laser/etc (EXTI)
- PA15 - USB pullup - PA15 - USB pullup
- PB0 - ADC channel 8 - PB8, PB9 - onboard LEDs (0/1)
- PB1,2 - free for other functions
- PC13 - buzzer
### Not implemented yet:
- PA5,6,7 (SCK, MISO, MOSI) - SPI
- PB0 - TRIG4 - ADC channel 8
- PB6/7 (SCL, SDA) - I2C

Binary file not shown.

View File

@ -29,6 +29,7 @@
#include <string.h> // memcpy #include <string.h> // memcpy
uint8_t buzzer_on = 1; // buzzer ON by default
uint8_t LEDSon = 1; // LEDS are working uint8_t LEDSon = 1; // LEDS are working
// ports of triggers // ports of triggers
static GPIO_TypeDef *trigport[DIGTRIG_AMOUNT] = {GPIOA, GPIOA, GPIOA}; static GPIO_TypeDef *trigport[DIGTRIG_AMOUNT] = {GPIOA, GPIOA, GPIOA};
@ -42,14 +43,22 @@ trigtime shottime[TRIGGERS_AMOUNT];
static uint32_t shotms[TRIGGERS_AMOUNT]; static uint32_t shotms[TRIGGERS_AMOUNT];
// if trigger[N] shots, the bit N will be 1 // if trigger[N] shots, the bit N will be 1
uint8_t trigger_shot = 0; uint8_t trigger_shot = 0;
// time when Buzzer was turned ON
uint32_t BuzzerTime = 0;
static inline void gpio_setup(){ static inline void gpio_setup(){
BUZZER_OFF(); // turn off buzzer @start
LED_on(); // turn ON LED0 @start
LED1_off(); // turn off LED1 @start
USBPU_OFF(); // turn off USB pullup @start
// Enable clocks to the GPIO subsystems (PB for ADC), turn on AFIO clocking to disable SWD/JTAG // Enable clocks to the GPIO subsystems (PB for ADC), turn on AFIO clocking to disable SWD/JTAG
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN; RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN;
// turn off SWJ/JTAG // turn off SWJ/JTAG
AFIO->MAPR = AFIO_MAPR_SWJ_CFG_DISABLE; AFIO->MAPR = AFIO_MAPR_SWJ_CFG_DISABLE;
// pullups: PA1 - PPS, PA15 - USB pullup // pullups: PA1 - PPS, PA15 - USB pullup
GPIOA->ODR = (1<<12)|(1<<15); GPIOA->ODR = (1<<12)|(1<<15);
// buzzer (PC13): pushpull output
GPIOC->CRH = CRH(13, CNF_PPOUTPUT|MODE_SLOW);
// Set leds (PB8) as opendrain output // Set leds (PB8) as opendrain output
GPIOB->CRH = CRH(8, CNF_ODOUTPUT|MODE_SLOW) | CRH(9, CNF_ODOUTPUT|MODE_SLOW); GPIOB->CRH = CRH(8, CNF_ODOUTPUT|MODE_SLOW) | CRH(9, CNF_ODOUTPUT|MODE_SLOW);
// PPS pin (PA1) - input with weak pullup // PPS pin (PA1) - input with weak pullup
@ -128,7 +137,7 @@ void hw_setup(){
void exti1_isr(){ // PPS - PA1 void exti1_isr(){ // PPS - PA1
systick_correction(); systick_correction();
DBG("exti1"); LED_off(); // turn off LED0 @ each PPS
EXTI->PR = EXTI_PR_PR1; EXTI->PR = EXTI_PR_PR1;
} }
@ -140,17 +149,18 @@ void savetrigtime(){
void fillshotms(int i){ void fillshotms(int i){
if(i < 0 || i > TRIGGERS_AMOUNT) return; if(i < 0 || i > TRIGGERS_AMOUNT) return;
if(shotms[i] - Tms > (uint32_t)the_conf.trigpause[i]){ if(Tms - shotms[i] > (uint32_t)the_conf.trigpause[i]){
shotms[i] = Tms; shotms[i] = Tms;
memcpy(&shottime[i], &trgtm, sizeof(trigtime)); memcpy(&shottime[i], &trgtm, sizeof(trigtime));
trigger_shot |= 1<<i; trigger_shot |= 1<<i;
BuzzerTime = Tms;
BUZZER_ON();
} }
} }
void exti4_isr(){ // PA4 - trigger[2] void exti4_isr(){ // PA4 - trigger[2]
savetrigtime(); savetrigtime();
fillshotms(2); fillshotms(2);
DBG("exti4");
EXTI->PR = EXTI_PR_PR4; EXTI->PR = EXTI_PR_PR4;
} }
@ -158,12 +168,10 @@ void exti15_10_isr(){ // PA13 - trigger[0], PA14 - trigger[1]
savetrigtime(); savetrigtime();
if(EXTI->PR & EXTI_PR_PR13){ if(EXTI->PR & EXTI_PR_PR13){
fillshotms(0); fillshotms(0);
DBG("exti13");
EXTI->PR = EXTI_PR_PR13; EXTI->PR = EXTI_PR_PR13;
} }
if(EXTI->PR & EXTI_PR_PR14){ if(EXTI->PR & EXTI_PR_PR14){
fillshotms(1); fillshotms(1);
DBG("exti14");
EXTI->PR = EXTI_PR_PR14; EXTI->PR = EXTI_PR_PR14;
} }
} }

View File

@ -33,6 +33,13 @@
#define LED1_port GPIOB #define LED1_port GPIOB
#define LED1_pin (1<<9) #define LED1_pin (1<<9)
// buzzer (1 - active) - PC13
extern uint8_t buzzer_on;
#define BUZZER_port GPIOC
#define BUZZER_pin (1<<13)
#define BUZZER_ON() do{if(buzzer_on)pin_set(BUZZER_port, BUZZER_pin);}while(0)
#define BUZZER_OFF() pin_clear(BUZZER_port, BUZZER_pin)
// PPS pin - PA1 // PPS pin - PA1
#define PPS_port GPIOA #define PPS_port GPIOA
#define PPS_pin (1<<1) #define PPS_pin (1<<1)
@ -56,10 +63,10 @@ void savetrigtime();
#define LED_blink() do{if(LEDSon)pin_toggle(LED0_port, LED0_pin);}while(0) #define LED_blink() do{if(LEDSon)pin_toggle(LED0_port, LED0_pin);}while(0)
#define LED_on() do{if(LEDSon)pin_clear(LED0_port, LED0_pin);}while(0) #define LED_on() do{if(LEDSon)pin_clear(LED0_port, LED0_pin);}while(0)
#define LED_off() do{if(LEDSon)pin_set(LED0_port, LED0_pin);}while(0) #define LED_off() do{pin_set(LED0_port, LED0_pin);}while(0)
#define LED1_blink() do{if(LEDSon)pin_toggle(LED1_port, LED1_pin);}while(0) #define LED1_blink() do{if(LEDSon)pin_toggle(LED1_port, LED1_pin);}while(0)
#define LED1_on() do{if(LEDSon)pin_clear(LED1_port, LED1_pin);}while(0) #define LED1_on() do{if(LEDSon)pin_clear(LED1_port, LED1_pin);}while(0)
#define LED1_off() do{if(LEDSon)pin_set(LED1_port, LED1_pin);}while(0) #define LED1_off() do{pin_set(LED1_port, LED1_pin);}while(0)
// GPS USART == USART2, LIDAR USART == USART3 // GPS USART == USART2, LIDAR USART == USART3
#define GPS_USART (2) #define GPS_USART (2)
@ -76,6 +83,8 @@ extern uint8_t LEDSon;
extern trigtime shottime[TRIGGERS_AMOUNT]; extern trigtime shottime[TRIGGERS_AMOUNT];
// if trigger[N] shots, the bit N will be 1 // if trigger[N] shots, the bit N will be 1
extern uint8_t trigger_shot; extern uint8_t trigger_shot;
// time when Buzzer was turned ON
extern uint32_t BuzzerTime;
void hw_setup(); void hw_setup();

View File

@ -33,6 +33,7 @@ void parse_lidar_data(char *txt){
lidar_triggered_dist = last_lidar_dist; lidar_triggered_dist = last_lidar_dist;
return; return;
} }
IWDG->KR = IWDG_REFRESH;
if(triggered){ // check if body gone if(triggered){ // check if body gone
if(last_lidar_dist < the_conf.dist_min || last_lidar_dist > the_conf.dist_max || last_lidar_dist > lidar_triggered_dist + LIDAR_DIST_THRES){ if(last_lidar_dist < the_conf.dist_min || last_lidar_dist > the_conf.dist_max || last_lidar_dist > lidar_triggered_dist + LIDAR_DIST_THRES){
triggered = 0; triggered = 0;

View File

@ -74,10 +74,10 @@ char *parse_cmd(char *buf){
static char btns[] = "BTN0=0, BTN1=0, BTN2=0, PPS=0\n"; static char btns[] = "BTN0=0, BTN1=0, BTN2=0, PPS=0\n";
switch(*buf){ switch(*buf){
case '0': case '0':
LED_off(); LED_off(); // LED0 off @dbg
break; break;
case '1': case '1':
LED_on(); LED_on(); // LED0 on @dbg
break; break;
case 'b': case 'b':
btns[5] = gettrig(0) + '0'; btns[5] = gettrig(0) + '0';
@ -179,12 +179,23 @@ static char *get_USB(){
return NULL; return NULL;
} }
/*
void linecoding_handler(usb_LineCoding __attribute__((unused)) *lc){ // get/set line coding void linecoding_handler(usb_LineCoding __attribute__((unused)) *lc){ // get/set line coding
DBG("linecoding_handler"); #ifdef EBUG
}*/ SEND("Change speed to");
printu(1, lc->dwDTERate);
newline();
#endif
}
void clstate_handler(uint16_t __attribute__((unused)) val){ // lesser bits of val: RTS|DTR void clstate_handler(uint16_t __attribute__((unused)) val){ // lesser bits of val: RTS|DTR
static uint32_t Tlast = 0;
SEND("Tms/Tlast: ");
printu(1, Tms);
newline();
printu(1, Tlast);
newline();
if(Tms - Tlast < 500) return;
Tlast = Tms;
USB_send("Chronometer version " VERSION ".\n"); USB_send("Chronometer version " VERSION ".\n");
#ifdef EBUG #ifdef EBUG
if(val & 2){ if(val & 2){
@ -198,17 +209,19 @@ void clstate_handler(uint16_t __attribute__((unused)) val){ // lesser bits of va
#endif #endif
} }
/*
void break_handler(){ // client disconnected void break_handler(){ // client disconnected
DBG("break_handler"); DBG("Disconnected");
}*/ }
#ifdef EBUG
extern int32_t ticksdiff, timecntr, timerval, Tms1;
extern uint32_t last_corr_time;
#endif
int main(void){ int main(void){
uint32_t lastT = 0; uint32_t lastT = 0;
sysreset(); sysreset();
StartHSE(); StartHSE();
LED1_off();
USBPU_OFF();
SysTick_Config(SYSTICK_DEFCONF); // function SysTick_Config decrements argument! SysTick_Config(SYSTICK_DEFCONF); // function SysTick_Config decrements argument!
// read data stored in flash // read data stored in flash
get_userconf(); get_userconf();
@ -218,7 +231,7 @@ int main(void){
USBPU_ON(); USBPU_ON();
usarts_setup(); usarts_setup();
#ifdef EBUG #ifdef EBUG
SEND("Chronometer version " VERSION ".\n"); SEND("This is chronometer version " VERSION ".\n");
if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured
SEND("WDGRESET=1\n"); SEND("WDGRESET=1\n");
} }
@ -227,16 +240,28 @@ int main(void){
} }
#endif #endif
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
iwdg_setup(); //iwdg_setup();
while (1){ while (1){
IWDG->KR = IWDG_REFRESH; // refresh watchdog IWDG->KR = IWDG_REFRESH; // refresh watchdog
if(Timer > 499) LED_on(); // turn ON LED0 over 0.25s after PPS pulse
if(BuzzerTime && Tms - BuzzerTime > 249){
BUZZER_OFF();
BuzzerTime = 0;
}
if(lastT > Tms || Tms - lastT > 499){ if(lastT > Tms || Tms - lastT > 499){
if(need2startseq) GPS_send_start_seq(); if(need2startseq) GPS_send_start_seq();
LED_blink(); IWDG->KR = IWDG_REFRESH;
if(GPS_status != GPS_VALID) LED1_blink(); switch(GPS_status){
else LED1_on(); case GPS_VALID:
LED1_blink(); // blink LED1 @ VALID time
break;
case GPS_NOT_VALID:
LED1_on(); // shine LED1 @ NON-VALID time
break;
default:
LED1_off(); // turn off LED1 if GPS not found or time unknown
}
lastT = Tms; lastT = Tms;
if(usartrx(LIDAR_USART)){ if(usartrx(LIDAR_USART)){
char *txt; char *txt;
@ -245,14 +270,42 @@ int main(void){
DBG(txt); DBG(txt);
} }
} }
IWDG->KR = IWDG_REFRESH;
#if defined EBUG || defined USART1PROXY #if defined EBUG || defined USART1PROXY
transmit_tbuf(1); // non-blocking transmission of data from UART buffer every 0.5s transmit_tbuf(1); // non-blocking transmission of data from UART buffer every 0.5s
#endif #endif
transmit_tbuf(GPS_USART); transmit_tbuf(GPS_USART);
transmit_tbuf(LIDAR_USART); transmit_tbuf(LIDAR_USART);
#ifdef EBUG
static uint8_t x = 1;
if(timecntr){
if(x){
SEND("ticksdiff=");
if(ticksdiff < 0){
SEND("-");
printu(1, -ticksdiff);
}else printu(1, ticksdiff);
SEND(", timecntr=");
printu(1, timecntr);
SEND("\nlast_corr_time=");
printu(1, last_corr_time);
SEND(", Tms=");
printu(1, Tms1);
SEND("\nTimer=");
printu(1, timerval);
SEND(", LOAD=");
printu(1, SysTick->LOAD);
newline();
} }
x = !x;
}
#endif
}
IWDG->KR = IWDG_REFRESH;
if(trigger_shot) show_trigger_shot(trigger_shot); if(trigger_shot) show_trigger_shot(trigger_shot);
IWDG->KR = IWDG_REFRESH;
usb_proc(); usb_proc();
IWDG->KR = IWDG_REFRESH;
int r = 0; int r = 0;
char *txt; char *txt;
if((txt = get_USB())){ if((txt = get_USB())){
@ -260,6 +313,7 @@ int main(void){
DBG(txt); DBG(txt);
if(parse_USBCMD(txt)) if(parse_USBCMD(txt))
USB_send(txt); // echo back non-commands data USB_send(txt); // echo back non-commands data
IWDG->KR = IWDG_REFRESH;
} }
#if defined EBUG || defined USART1PROXY #if defined EBUG || defined USART1PROXY
if(usartrx(1)){ // usart1 received data, store in in buffer if(usartrx(1)){ // usart1 received data, store in in buffer
@ -268,18 +322,23 @@ int main(void){
txt[r] = 0; txt[r] = 0;
#ifdef EBUG #ifdef EBUG
char *ans = parse_cmd(txt); char *ans = parse_cmd(txt);
IWDG->KR = IWDG_REFRESH;
if(ans){ if(ans){
transmit_tbuf(1); transmit_tbuf(1);
IWDG->KR = IWDG_REFRESH;
usart_send(1, ans); usart_send(1, ans);
transmit_tbuf(1); transmit_tbuf(1);
IWDG->KR = IWDG_REFRESH;
} }
#else // USART1PROXY - send received data to GPS #else // USART1PROXY - send received data to GPS
usart_send(GPS_USART, txt); usart_send(GPS_USART, txt);
IWDG->KR = IWDG_REFRESH;
#endif #endif
} }
} }
#endif #endif
if(usartrx(GPS_USART)){ if(usartrx(GPS_USART)){
IWDG->KR = IWDG_REFRESH;
r = usart_getline(GPS_USART, &txt); r = usart_getline(GPS_USART, &txt);
if(r){ if(r){
txt[r] = 0; txt[r] = 0;
@ -287,6 +346,7 @@ int main(void){
} }
} }
if(usartrx(LIDAR_USART)){ if(usartrx(LIDAR_USART)){
IWDG->KR = IWDG_REFRESH;
r = usart_getline(LIDAR_USART, &txt); r = usart_getline(LIDAR_USART, &txt);
if(r){ if(r){
parse_lidar_data(txt); parse_lidar_data(txt);

View File

@ -106,6 +106,7 @@ int parse_USBCMD(char *cmd){
CMD_ADCMAX " - max ADC value treshold for trigger\n" CMD_ADCMAX " - max ADC value treshold for trigger\n"
CMD_ADCMIN " - min -//- (triggered when ADval>min & <max\n" CMD_ADCMIN " - min -//- (triggered when ADval>min & <max\n"
CMD_GETADCVAL " - get ADC value\n" CMD_GETADCVAL " - get ADC value\n"
CMD_BUZZER "S - turn buzzer ON/OFF\n"
CMD_DISTMIN " - min distance threshold (cm)\n" CMD_DISTMIN " - min distance threshold (cm)\n"
CMD_DISTMAX " - max distance threshold (cm)\n" CMD_DISTMAX " - max distance threshold (cm)\n"
CMD_GPSRESTART " - send Full Cold Restart to GPS\n" CMD_GPSRESTART " - send Full Cold Restart to GPS\n"
@ -227,8 +228,8 @@ int parse_USBCMD(char *cmd){
LEDSon = 1; LEDSon = 1;
USB_send("ON\n"); USB_send("ON\n");
}else{ }else{
LED_off(); LED_off(); // turn off LEDS
LED1_off(); LED1_off(); // by user request
LEDSon = 0; LEDSon = 0;
USB_send("OFF\n"); USB_send("OFF\n");
} }
@ -251,6 +252,19 @@ int parse_USBCMD(char *cmd){
}else if(CMP(cmd, CMD_GPSRESTART) == 0){ }else if(CMP(cmd, CMD_GPSRESTART) == 0){
USB_send("Send full cold restart to GPS\n"); USB_send("Send full cold restart to GPS\n");
GPS_send_FullColdStart(); GPS_send_FullColdStart();
}else if(CMP(cmd, CMD_BUZZER) == 0){
uint8_t Nt = cmd[sizeof(CMD_BUZZER) - 1] - '0';
if(Nt > 1) goto bad_number;
USB_send("BUZZER=");
if(Nt){
BuzzerTime = 0;
buzzer_on = 1;
USB_send("ON\n");
}else{
BuzzerTime = 0;
buzzer_on = 0;
USB_send("OFF\n");
}
}else return 1; }else return 1;
IWDG->KR = IWDG_REFRESH; IWDG->KR = IWDG_REFRESH;
if(succeed) USB_send("Success!\n"); if(succeed) USB_send("Success!\n");

View File

@ -41,6 +41,7 @@
#define CMD_GETADCVAL "adcval" #define CMD_GETADCVAL "adcval"
#define CMD_LEDS "leds" #define CMD_LEDS "leds"
#define CMD_GPSRESTART "gpsrestart" #define CMD_GPSRESTART "gpsrestart"
#define CMD_BUZZER "buzzer"
extern uint8_t showGPSstr; extern uint8_t showGPSstr;

View File

@ -27,9 +27,6 @@
volatile uint32_t Timer; // milliseconds counter volatile uint32_t Timer; // milliseconds counter
curtime current_time = TMNOTINI; curtime current_time = TMNOTINI;
// ms counter in last correction by PPS
static uint32_t last_corr_time = 0;
static inline uint8_t atou(const char *b){ static inline uint8_t atou(const char *b){
return (b[0]-'0')*10 + b[1]-'0'; return (b[0]-'0')*10 + b[1]-'0';
} }
@ -39,11 +36,16 @@ static inline uint8_t atou(const char *b){
* @param buf - buffer with time data (HHMMSS) * @param buf - buffer with time data (HHMMSS)
*/ */
void set_time(const char *buf){ void set_time(const char *buf){
uint8_t H = atou(buf) + TIMEZONE_GMT_PLUS; uint8_t H = atou(buf);// + TIMEZONE_GMT_PLUS;
if(H > 23) H -= 24; if(H > 23) H -= 24;
current_time.H = H; current_time.H = H;
current_time.M = atou(&buf[2]); current_time.M = atou(&buf[2]);
current_time.S = atou(&buf[4]); current_time.S = atou(&buf[4]);
#ifdef EBUG
SEND("set_time, Tms: "); printu(1, Tms);
SEND("; Timer: "); printu(1, Timer);
newline();
#endif
} }
/** /**
@ -66,6 +68,17 @@ void time_increment(){
#endif #endif
} }
static char *puttwo(uint8_t N, char *buf){
if(N < 10){
*buf++ = '0';
}else{
*buf++ = N/10 + '0';
N %= 10;
}
*buf++ = N + '0';
return buf;
}
/** /**
* print time: Tm - time structure, T - milliseconds * print time: Tm - time structure, T - milliseconds
*/ */
@ -92,14 +105,11 @@ char *get_time(curtime *Tm, uint32_t T){
T %= 10; T %= 10;
}else *bptr++ = '0'; }else *bptr++ = '0';
*bptr++ = T + '0'; *bptr++ = T + '0';
if(GPS_status == GPS_NOT_VALID){ // put current time in HH:MM:SS format into buf
strcpy(bptr, " (not valid)"); *bptr++ = ' '; *bptr++ = '(';
bptr += 12; bptr = puttwo(Tm->H, bptr); *bptr++ = ':';
} bptr = puttwo(Tm->M, bptr); *bptr++ = ':';
if(Tms - last_corr_time > 1000){ bptr = puttwo(Tm->S, bptr); *bptr++ = ')';
strcpy(bptr, " need PPS sync");
bptr += 14;
}
if(GPS_status == GPS_NOTFOUND){ if(GPS_status == GPS_NOTFOUND){
strcpy(bptr, " GPS not found"); strcpy(bptr, " GPS not found");
bptr += 14; bptr += 14;
@ -109,6 +119,13 @@ char *get_time(curtime *Tm, uint32_t T){
return bstart; return bstart;
} }
#ifdef EBUG
int32_t ticksdiff=0, timecntr=0, timerval, Tms1;
#endif
uint32_t last_corr_time = 0;
/** /**
* @brief systick_correction * @brief systick_correction
* Makes correction of system timer * Makes correction of system timer
@ -126,61 +143,38 @@ char *get_time(curtime *Tm, uint32_t T){
*/ */
void systick_correction(){ void systick_correction(){
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // stop systick for a while SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // stop systick for a while
int32_t systick_val = SysTick->VAL, L = SysTick->LOAD + 1, timer_val = Timer; uint32_t systick_val = SysTick->VAL, L = SysTick->LOAD + 1;
int32_t timer_val = Timer;
timerval = Timer;
Tms1 = Tms;
Timer = 0;
SysTick->VAL = SysTick->LOAD; SysTick->VAL = SysTick->LOAD;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // start it again SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // start it again
Timer = 0; // if(systick_val != SysTick->LOAD) ++Tms;
if(Tms - last_corr_time < 2000){ // calculate corrections only if Timer was zeroed last time if(timer_val > 500) time_increment(); // counter greater than 500 -> need to increment time
if(timer_val < 500) timer_val += 1000; // timer already incremented in SysTick interrupt if(last_corr_time){
else time_increment(); // counter less than 1000 -> need to increment time if(Tms - last_corr_time < 1500){ // there was perevious PPS signal
int32_t D = L * (timer_val - 999) - systick_val; int32_t D = L * (Tms - 1000 - last_corr_time) + (SysTick->LOAD - systick_val); // amount of spare ticks
D /= 1000; ++timecntr;
ticksdiff += D;
uint32_t ticksabs = (ticksdiff < 0) ? -ticksdiff : ticksdiff;
// 10000 == 30 seconds * 1000 interrupts per second
if(ticksabs > 30000 && timecntr > 30){ // need correction (not more often than each 10s)
ticksdiff /= timecntr * 1000; // correction per one interrupt
SysTick->LOAD += ticksdiff;
timecntr = 0;
ticksdiff = 0;
last_corr_time = 0;
#ifdef EBUG #ifdef EBUG
SEND("Delta: "); if(D < 0){usart_putchar(1, '-'); printu(1, -D);} else printu(1, D); newline(); SEND("Correction\n");
SEND(get_time(&current_time, 0));
#endif #endif
SysTick->LOAD += D;
}
last_corr_time = Tms;
#if 0
uint32_t t = 0, ticks;
static uint32_t ticksavr = 0, N = 0, last_corr_time = 0;
// correct
int32_t systick_val = SysTick->VAL;
// SysTick->LOAD values for all milliseconds (RVR0) and last millisecond (RVR1)
SysTick->VAL = RVR0;
int32_t timer_val = Timer;
Timer = 0;
// RVR -> SysTick->LOAD
systick_val = SysTick->LOAD + 1 - systick_val; // Systick counts down!
if(timer_val < 10) timer_val += 1000; // our closks go faster than real
else if(timer_val < 990){ // something wrong
RVR0 = RVR1 = SYSTICK_DEFLOAD;
SysTick->LOAD = RVR0;
need_sync = 1;
goto theend;
}else
time_increment(); // ms counter less than 1000 - we need to increment time
t = current_time.H * 3600 + current_time.M * 60 + current_time.S;
if(t - last_corr_time == 1){ // PPS interval == 1s
ticks = systick_val + (timer_val-1)*(RVR0 + 1) + RVR1 + 1;
++N;
ticksavr += ticks;
if(N > 20){
ticks = ticksavr / N;
RVR0 = ticks / 1000 - 1; // main RVR value
SysTick->LOAD = RVR0;
RVR1 = RVR0 + ticks % 1000; // last millisecond RVR value (with fine correction)
N = 0;
ticksavr = 0;
need_sync = 0;
} }
}else{ }else{
N = 0; timecntr = 0;
ticksavr = 0; ticksdiff = 0;
last_corr_time = 0;
} }
theend: }
last_corr_time = t; last_corr_time = Tms;
#endif
} }