add trigger settings

This commit is contained in:
eddyem 2019-07-18 21:05:10 +03:00
parent 5f91b4eca7
commit 1242b8f9ff
12 changed files with 258 additions and 56 deletions

View File

@ -29,7 +29,7 @@
#define GPS_endline() do{usart_send(GPS_USART, "\r\n"); transmit_tbuf(GPS_USART); }while(0)
#define GPS_send_string(str) do{usart_send(GPS_USART, str);}while(0)
gps_status GPS_status = GPS_WAIT;
gps_status GPS_status = GPS_NOTFOUND;
int need2startseq = 1;
static uint8_t hex(uint8_t n){

View File

@ -28,7 +28,8 @@
extern int need2startseq;
typedef enum{
GPS_WAIT // wait for satellites
GPS_NOTFOUND // default status before first RMC message
,GPS_WAIT // wait for satellites
,GPS_NOT_VALID // time known, but not valid
,GPS_VALID
} gps_status;

View File

@ -16,3 +16,4 @@ Chronometer for downhill competitions
- PA14 - TRIG1 - button1/laser/etc (EXTI)
- PA15 - USB pullup
- PB0,1,2 - free for other functions

Binary file not shown.

View File

@ -55,6 +55,9 @@ typedef struct{
.userconf_sz = sizeof(user_conf) \
,.dist_min = LIDAR_MIN_DIST \
,.dist_max = LIDAR_MAX_DIST \
,.trig_pullups = 0xff \
,.trigstate = 0 \
,.trigpause = {400, 400, 400} \
}
__attribute__((section(".myvars"))) static const flash_storage Flash_Storage = {
@ -221,9 +224,18 @@ static int erase_flash(){
#ifdef EBUG
void dump_userconf(){
SEND("userconf_sz="); printu(1, the_conf.userconf_sz); newline();
SEND("dist_min="); printu(1, the_conf.dist_min); newline();
SEND("dist_max="); printu(1, the_conf.dist_max); newline();
SEND("userconf_sz="); printu(1, the_conf.userconf_sz);
SEND("\ndist_min="); printu(1, the_conf.dist_min);
SEND("\ndist_max="); printu(1, the_conf.dist_max);
SEND("\ntrig_pullups="); printuhex(1, the_conf.trig_pullups);
SEND("\ntrigstate="); printuhex(1, the_conf.trigstate);
SEND("\ntrigpause={");
for(int i = 0; i < TRIGGERS_AMOUNT; ++i){
if(i) SEND(", ");
printu(1, the_conf.trigpause[i]);
}
SEND("}\n");
transmit_tbuf(1);
}
void addNrecs(int N){

View File

@ -25,21 +25,26 @@
#define __FLASH_H__
#include <stm32f1.h>
#include "hardware.h"
#define FLASH_BLOCK_SIZE (1024)
#define FLASH_SIZE_REG ((uint32_t)0x1FFFF7E0)
#define FLASH_SIZE *((uint16_t*)FLASH_SIZE_REG)
typedef struct{
typedef struct __attribute__((packed)){
uint16_t userconf_sz; // "magick number"
uint32_t dist_min; // minimal distance for LIDAR
uint32_t dist_max; // maximal -//-
uint8_t trig_pullups; // trigger pullups: each bit ==0 to set OFF, ==1 to set ON pullup with given number
uint8_t trigstate; // level in `triggered` state
int32_t trigpause[TRIGGERS_AMOUNT]; // pause (ms) for false shots
} user_conf;
extern user_conf the_conf;
void get_userconf();
int store_userconf();
#ifdef EBUG
void dump_userconf();
void addNrecs(int N);

View File

@ -23,29 +23,66 @@
#include "adc.h"
#include "hardware.h"
#include "flash.h"
#include "time.h"
#include "usart.h"
#include <string.h> // memcpy
// ports of triggers
GPIO_TypeDef *trigport[TRIGGERS_AMOUNT] = {GPIOA, GPIOA, GPIOA};
// pins of triggers: PA13, PA14, PA4
uint16_t trigpin[TRIGGERS_AMOUNT] = {1<<13, 1<<14, 1<<4};
// value of pin in `triggered` state
uint8_t trigstate[TRIGGERS_AMOUNT];
// time of triggers shot
trigtime shottime[TRIGGERS_AMOUNT];
// Tms value when they shot
static uint32_t shotms[TRIGGERS_AMOUNT];
// if trigger[N] shots, the bit N will be 1
uint8_t trigger_shot = 0;
static inline void gpio_setup(){
// 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;
// turn off SWJ/JTAG
AFIO->MAPR = AFIO_MAPR_SWJ_CFG_DISABLE;
// pullups: PA1 - PPS, PA13/PA14 - buttons
GPIOA->ODR = (1<<12)|(1<<13)|(1<<14)|(1<<15);
// pullups: PA1 - PPS, PA15 - USB pullup
GPIOA->ODR = (1<<12)|(1<<15);
// Set leds (PB8) as opendrain output
GPIOB->CRH = CRH(8, CNF_ODOUTPUT|MODE_SLOW) | CRH(9, CNF_ODOUTPUT|MODE_SLOW);
// PPS pin (PA1) - input with weak pullup
GPIOA->CRL = CRL(1, CNF_PUDINPUT|MODE_INPUT);
// Set buttons (PA13/14) as inputs with weak pullups, USB pullup (PA15) - opendrain output
GPIOA->CRH = CRH(13, CNF_PUDINPUT|MODE_INPUT) | CRH(14, CNF_PUDINPUT|MODE_INPUT) |
CRH(15, CNF_ODOUTPUT|MODE_SLOW);
// Set USB pullup (PA15) - opendrain output
GPIOA->CRH = CRH(15, CNF_ODOUTPUT|MODE_SLOW);
// ---------------------> config-depengent block, interrupts & pullup inputs:
GPIOA->CRH |= CRH(13, CNF_PUDINPUT|MODE_INPUT) | CRH(14, CNF_PUDINPUT|MODE_INPUT);
GPIOA->CRL |= CRL(4, CNF_PUDINPUT|MODE_INPUT);
// <---------------------
// EXTI: all three EXTI are on PA -> AFIO_EXTICRx = 0
// interrupt on pulse front: buttons - 1->0, PPS - 0->1
EXTI->IMR = EXTI_IMR_MR1 | EXTI_IMR_MR13 | EXTI_IMR_MR14; // unmask
EXTI->IMR = EXTI_IMR_MR1;
EXTI->RTSR = EXTI_RTSR_TR1; // rising trigger
EXTI->FTSR = EXTI_FTSR_TR13 | EXTI_FTSR_TR14; // falling trigger
// PA4/PA13/PA14 - buttons
for(int i = 0; i < TRIGGERS_AMOUNT; ++i){
uint16_t pin = trigpin[i];
// fill trigstate array
uint8_t trgs = (the_conf.trigstate & (1<<i)) ? 1 : 0;
trigstate[i] = trgs;
// turn on pullups
if(the_conf.trig_pullups & (1<<i)) trigport[i]->ODR |= pin;
EXTI->IMR |= pin;
if(trgs){ // triggered @1 -> rising interrupt
EXTI->RTSR |= pin;
}else{ // falling interrupt
EXTI->FTSR |= pin;
}
}
// ---------------------> config-depengent block, interrupts & pullup inputs:
// !!! change AFIO_EXTICRx if some triggers not @GPIOA
NVIC_EnableIRQ(EXTI4_IRQn);
NVIC_EnableIRQ(EXTI15_10_IRQn);
// <---------------------
NVIC_EnableIRQ(EXTI1_IRQn);
}
@ -94,25 +131,49 @@ void exti1_isr(){ // PPS - PA1
EXTI->PR = EXTI_PR_PR1;
}
void exti15_10_isr(){ // PA13 - button0, PA14 - button1
if(EXTI->PR & EXTI_PR_PR13){
/*
if(trigger_ms[0] == DIDNT_TRIGGERED){ // prevent bounce
trigger_ms[0] = Timer;
memcpy(&trigger_time[0], &current_time, sizeof(curtime));
static trigtime trgtm;
static void savetrigtime(){
trgtm.millis = Timer;
memcpy(&trgtm.Time, &current_time, sizeof(curtime));
}
*/
static void fillshotms(int i){
if(i < 0 || i > TRIGGERS_AMOUNT) return;
if(shotms[i] - Tms > (uint32_t)the_conf.trigpause[i]){
shotms[i] = Tms;
memcpy(&shottime[i], &trgtm, sizeof(trigtime));
trigger_shot |= 1<<i;
}
}
void exti4_isr(){ // PA4 - button2
savetrigtime();
fillshotms(2);
DBG("exti4");
EXTI->PR = EXTI_PR_PR4;
}
void exti15_10_isr(){ // PA13 - button0, PA14 - button1
savetrigtime();
if(EXTI->PR & EXTI_PR_PR13){
fillshotms(0);
DBG("exti13");
EXTI->PR = EXTI_PR_PR13;
}
if(EXTI->PR & EXTI_PR_PR14){
/*
if(trigger_ms[3] == DIDNT_TRIGGERED){ // prevent bounce
trigger_ms[3] = Timer;
memcpy(&trigger_time[3], &current_time, sizeof(curtime));
}
*/
fillshotms(1);
DBG("exti14");
EXTI->PR = EXTI_PR_PR14;
}
}
/**
* @brief gettrig - get trigger state
* @return 1 if trigger active or 0
*/
uint8_t gettrig(uint8_t N){
if(N >= TRIGGERS_AMOUNT) return 0;
uint8_t curval = (trigport[N]->IDR & trigpin[N]) ? 1 : 0;
if(curval == trigstate[N]) return 1;
else return 0;
}

View File

@ -25,6 +25,7 @@
#define __HARDWARE_H__
#include "stm32f1.h"
#include "time.h"
// onboard LEDs - PB8/PB9
#define LED0_port GPIOB
@ -36,9 +37,13 @@
#define PPS_port GPIOA
#define PPS_pin (1<<1)
// Buttons' state: PA13 (0)/PA14 (1)
#define GET_BTN0() ((GPIOA->IDR & (1<<13)) ? 0 : 1)
#define GET_BTN1() ((GPIOA->IDR & (1<<14)) ? 0 : 1)
// PPS and triggers state
// amount of triggers, should be less than 9
#define TRIGGERS_AMOUNT (3)
extern GPIO_TypeDef *trigport[TRIGGERS_AMOUNT];
extern uint16_t trigpin[TRIGGERS_AMOUNT];
extern uint8_t trigstate[TRIGGERS_AMOUNT];
uint8_t gettrig(uint8_t N);
#define GET_PPS() ((GPIOA->IDR & (1<<1)) ? 1 : 0)
// USB pullup - PA15
@ -58,6 +63,16 @@
#define GPS_USART (2)
#define LIDAR_USART (3)
typedef struct{
uint32_t millis;
curtime Time;
} trigtime;
// time of triggers shot
extern trigtime shottime[TRIGGERS_AMOUNT];
// if trigger[N] shots, the bit N will be 1
extern uint8_t trigger_shot;
void hw_setup();
#endif // __HARDWARE_H__

View File

@ -71,7 +71,7 @@ void iwdg_setup(){
#ifdef EBUG
char *parse_cmd(char *buf){
int32_t N;
static char btns[] = "BTN0=0, BTN1=0, PPS=0\n";
static char btns[] = "BTN0=0, BTN1=0, BTN2=0, PPS=0\n";
switch(*buf){
case '0':
LED_off();
@ -80,9 +80,10 @@ char *parse_cmd(char *buf){
LED_on();
break;
case 'b':
btns[5] = GET_BTN0() + '0';
btns[13] = GET_BTN1() + '0';
btns[20] = GET_PPS() + '0';
btns[5] = gettrig(0) + '0';
btns[13] = gettrig(1) + '0';
btns[21] = gettrig(2) + '0';
btns[28] = GET_PPS() + '0';
return btns;
break;
case 'C':
@ -177,11 +178,14 @@ int main(void){
uint32_t lastT = 0;
sysreset();
StartHSE();
hw_setup();
LED1_off();
USBPU_OFF();
usarts_setup();
SysTick_Config(SYSTICK_DEFCONF); // function SysTick_Config decrements argument!
// read data stored in flash
get_userconf();
// !!! hw_setup() should be the first in setup stage
hw_setup();
usarts_setup();
SEND("Chronometer version " VERSION ".\n");
if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured
SEND("WDGRESET=1\n");
@ -194,17 +198,6 @@ int main(void){
USB_setup();
iwdg_setup();
USBPU_ON();
// read data stored in flash
#ifdef EBUG
SEND("Old config:\n");
dump_userconf();
#endif
//writeatend();
get_userconf();
#ifdef EBUG
SEND("New config:\n");
dump_userconf();
#endif
while (1){
IWDG->KR = IWDG_REFRESH; // refresh watchdog
@ -227,6 +220,7 @@ int main(void){
transmit_tbuf(GPS_USART);
transmit_tbuf(LIDAR_USART);
}
if(trigger_shot) show_trigger_shot(trigger_shot);
usb_proc();
int r = 0;
char *txt;
@ -258,6 +252,10 @@ int main(void){
r = usart_getline(GPS_USART, &txt);
if(r){
txt[r] = 0;
if(showGPSstr){
showGPSstr = 0;
USB_send(txt);
}
GPS_parse_answer(txt);
}
}

View File

@ -22,6 +22,9 @@
#include "usart.h"
#include "usb.h"
// flag to show new GPS message over USB
uint8_t showGPSstr = 0;
/**
* @brief cmpstr - the same as strncmp
* @param s1,s2 - strings to compare
@ -30,9 +33,14 @@
*/
int cmpstr(const char *s1, const char *s2, int n){
int ret = 0;
do{
while(--n){
ret = *s1 - *s2;
}while(*s1++ && *s2++ && --n);
if(ret == 0 && *s1 && *s2){
++s1; ++s2;
continue;
}
break;
}
return ret;
}
@ -49,6 +57,23 @@ char *getchr(const char *str, char symbol){
return NULL;
}
/**
* @brief showuserconf - show configuration over USB
*/
static void showuserconf(){
USB_send("\nCONFIG:\nDISTMIN="); USB_send(u2str(the_conf.dist_min));
USB_send("\nDISTMAX="); USB_send(u2str(the_conf.dist_max));
USB_send("\nPULLUPS="); USB_send(u2str(the_conf.trig_pullups));
USB_send("\nTRIGLVL="); USB_send(u2str(the_conf.trigstate));
USB_send("\nTRIGPAUSE={");
for(int i = 0; i < TRIGGERS_AMOUNT; ++i){
if(i) USB_send(", ");
USB_send(u2str(the_conf.trigpause[i]));
}
USB_send("}");
USB_send("\nENDCONFIG\n");
}
/**
* @brief parse_USBCMD - parsing of string buffer got by USB
* @param cmd - buffer with commands
@ -61,12 +86,19 @@ int parse_USBCMD(char *cmd){
uint8_t succeed = 0;
int32_t N;
if(!cmd || !*cmd) return 0;
IWDG->KR = IWDG_REFRESH;
if(*cmd == '?'){ // help
USB_send("Commands:\n"
CMD_DISTMIN " - min distance threshold (cm)\n"
CMD_DISTMAX " - max distance threshold (cm)\n"
CMD_GPSSTR " - current GPS data string\n"
CMD_PULLUP "NS - triggers pullups state (N - trigger No, S - 0/1 for off/on)\n"
CMD_SHOWCONF " - show current configuration\n"
CMD_PRINTTIME " - print time\n"
CMD_STORECONF " - store new configuration in flash\n"
CMD_TRIGLVL "NS - working trigger N level S\n"
CMD_TRGPAUSE "NP - pause (P, ms) after trigger N shots\n"
CMD_TRGTIME "N - show last trigger N time\n"
);
}else if(CMP(cmd, CMD_PRINTTIME) == 0){
USB_send(get_time(&current_time, get_millis()));
@ -98,10 +130,77 @@ int parse_USBCMD(char *cmd){
succeed = 1;
}
}
}else if(CMP(cmd, CMD_GPSSTR) == 0){ // show GPS status string
showGPSstr = 1;
return 0;
}else if(CMP(cmd, CMD_PULLUP) == 0){
DBG("Pullups");
cmd += sizeof(CMD_PULLUP) - 1;
uint8_t Nt = *cmd++ - '0';
if(Nt > TRIGGERS_AMOUNT - 1) goto bad_number;
uint8_t state = *cmd -'0';
if(state > 1) goto bad_number;
uint8_t oldval = the_conf.trig_pullups;
if(!state) the_conf.trig_pullups = oldval & ~(1<<Nt);
else the_conf.trig_pullups = oldval | (1<<Nt);
if(oldval != the_conf.trig_pullups) conf_modified = 1;
succeed = 1;
}else if(CMP(cmd, CMD_TRIGLVL) == 0){
DBG("Trig levels");
cmd += sizeof(CMD_TRIGLVL) - 1;
uint8_t Nt = *cmd++ - '0';
if(Nt > TRIGGERS_AMOUNT - 1) goto bad_number;
uint8_t state = *cmd -'0';
if(state > 1) goto bad_number;
uint8_t oldval = the_conf.trigstate;
if(!state) the_conf.trigstate = oldval & ~(1<<Nt);
else the_conf.trigstate = oldval | (1<<Nt);
if(oldval != the_conf.trigstate) conf_modified = 1;
succeed = 1;
}else if(CMP(cmd, CMD_SHOWCONF) == 0){
showuserconf();
return 0;
}else if(CMP(cmd, CMD_TRGPAUSE) == 0){
DBG("Trigger pause");
cmd += sizeof(CMD_TRGPAUSE) - 1;
uint8_t Nt = *cmd++ - '0';
if(Nt > TRIGGERS_AMOUNT - 1) goto bad_number;
if(getnum(cmd, &N)) goto bad_number;
if(N < 0 || N > 10000) goto bad_number;
if(the_conf.trigpause[Nt] != N) conf_modified = 1;
the_conf.trigpause[Nt] = N;
succeed = 1;
}else if(CMP(cmd, CMD_TRGTIME) == 0){
DBG("Trigger time");
cmd += sizeof(CMD_TRGTIME) - 1;
uint8_t Nt = *cmd++ - '0';
if(Nt > TRIGGERS_AMOUNT - 1) goto bad_number;
show_trigger_shot((uint8_t)1<<Nt);
return 0;
}else return 1;
IWDG->KR = IWDG_REFRESH;
if(succeed) USB_send("Success!\n");
return 0;
bad_number:
USB_send("Error: bad number!\n");
return 0;
}
/**
* @brief show_trigger_shot - print on USB message about last trigger shot time
* @param tshot - each bit consists information about trigger
*/
void show_trigger_shot(uint8_t tshot){
uint8_t X = 1;
for(int i = 0; i < TRIGGERS_AMOUNT && tshot; ++i, X <<= 1){
IWDG->KR = IWDG_REFRESH;
if(tshot & X) tshot &= ~X;
else continue;
if(trigger_shot & X) trigger_shot &= ~X;
USB_send("TRIG");
USB_send(u2str(i));
USB_send("=");
USB_send(get_time(&shottime[i].Time, shottime[i].millis));
USB_send("\n");
}
}

View File

@ -19,6 +19,9 @@
#ifndef STR_H__
#define STR_H__
#include "stm32f1.h"
#include "hardware.h"
// usb commands
// lower and upper limits to capture
#define CMD_DISTMIN "distmin"
@ -29,8 +32,18 @@
#define CMD_ADC2MAX "adc2max"
#define CMD_PRINTTIME "time"
#define CMD_STORECONF "store"
#define CMD_GPSSTR "gpsstring"
#define CMD_PULLUP "pullup"
#define CMD_SHOWCONF "showconf"
#define CMD_TRIGLVL "triglevel"
#define CMD_TRGPAUSE "trigpause"
#define CMD_TRGTIME "trigtime"
extern uint8_t showGPSstr;
int cmpstr(const char *s1, const char *s2, int n);
char *getchr(const char *str, char symbol);
int parse_USBCMD(char *cmd);
void show_trigger_shot(uint8_t trigger_shot);
#endif // STR_H__

View File

@ -72,15 +72,8 @@ void time_increment(){
char *get_time(curtime *Tm, uint32_t T){
static char buf[64];
char *bstart = &buf[5], *bptr = bstart;
/*
void putint(int i){ // put integer from 0 to 99 into buffer with leading zeros
if(i > 9){
*bptr++ = i/10 + '0';
i = i%10;
}else *bptr++ = '0';
*bptr++ = i + '0';
}*/
int S = 0;
if(T > 999) return "Wrong time";
if(Tm->S < 60 && Tm->M < 60 && Tm->H < 24)
S = Tm->S + Tm->H*3600 + Tm->M*60; // seconds from day beginning
if(!S) *(--bstart) = '0';
@ -107,6 +100,10 @@ char *get_time(curtime *Tm, uint32_t T){
strcpy(bptr, " need PPS sync");
bptr += 14;
}
if(GPS_status == GPS_NOTFOUND){
strcpy(bptr, " GPS not found");
bptr += 14;
}
*bptr++ = '\n';
*bptr = 0;
return bstart;