mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 10:45:11 +03:00
Fixed chronometer
This commit is contained in:
parent
876eb82698
commit
e8bc0aba21
0
F0-nolib/Chiller/chiller.bin
Executable file → Normal file
0
F0-nolib/Chiller/chiller.bin
Executable file → Normal file
0
F0-nolib/F0_testbrd/pl2303.bin
Executable file → Normal file
0
F0-nolib/F0_testbrd/pl2303.bin
Executable file → Normal file
0
F0-nolib/QuadEncoder/encoder.bin
Executable file → Normal file
0
F0-nolib/QuadEncoder/encoder.bin
Executable file → Normal file
0
F0-nolib/Servo/servo.bin
Executable file → Normal file
0
F0-nolib/Servo/servo.bin
Executable file → Normal file
0
F0-nolib/TM1637/tm1637.bin
Executable file → Normal file
0
F0-nolib/TM1637/tm1637.bin
Executable file → Normal file
0
F0-nolib/USBHID/usbhid.bin
Executable file → Normal file
0
F0-nolib/USBHID/usbhid.bin
Executable file → Normal file
0
F0-nolib/blink/blink.bin
Executable file → Normal file
0
F0-nolib/blink/blink.bin
Executable file → Normal file
0
F0-nolib/canbus/src/canbus.bin
Executable file → Normal file
0
F0-nolib/canbus/src/canbus.bin
Executable file → Normal file
0
F0-nolib/htu21d_nucleo/usart.bin
Executable file → Normal file
0
F0-nolib/htu21d_nucleo/usart.bin
Executable file → Normal file
0
F0-nolib/morze/morze.bin
Executable file → Normal file
0
F0-nolib/morze/morze.bin
Executable file → Normal file
0
F0-nolib/pl2303/pl2303.bin
Executable file → Normal file
0
F0-nolib/pl2303/pl2303.bin
Executable file → Normal file
0
F0-nolib/tsys01_nucleo/tsys01.bin
Executable file → Normal file
0
F0-nolib/tsys01_nucleo/tsys01.bin
Executable file → Normal file
0
F0-nolib/uart_blink/uartblink.bin
Executable file → Normal file
0
F0-nolib/uart_blink/uartblink.bin
Executable file → Normal file
0
F0-nolib/uart_blink_dma/uartblink.bin
Executable file → Normal file
0
F0-nolib/uart_blink_dma/uartblink.bin
Executable file → Normal file
0
F0-nolib/uart_nucleo/usart.bin
Executable file → Normal file
0
F0-nolib/uart_nucleo/usart.bin
Executable file → Normal file
0
F0-nolib/usbcdc/usbcan.bin
Executable file → Normal file
0
F0-nolib/usbcdc/usbcan.bin
Executable file → Normal file
0
F0/blink/blink.bin
Executable file → Normal file
0
F0/blink/blink.bin
Executable file → Normal file
0
F0/uart/uart.bin
Executable file → Normal file
0
F0/uart/uart.bin
Executable file → Normal file
0
F1-nolib/CDC_ACM/cdcacm.bin
Executable file → Normal file
0
F1-nolib/CDC_ACM/cdcacm.bin
Executable file → Normal file
0
F1-nolib/F1_testbrd/pl2303.bin
Executable file → Normal file
0
F1-nolib/F1_testbrd/pl2303.bin
Executable file → Normal file
0
F1-nolib/LED_Screen/LEDscreen.bin
Executable file → Normal file
0
F1-nolib/LED_Screen/LEDscreen.bin
Executable file → Normal file
0
F1-nolib/LED_Screen/genlist
Executable file → Normal file
0
F1-nolib/LED_Screen/genlist
Executable file → Normal file
0
F1-nolib/LED_Screen/scrtest/scrtest
Executable file → Normal file
0
F1-nolib/LED_Screen/scrtest/scrtest
Executable file → Normal file
0
F1-nolib/PL2303/pl2303.bin
Executable file → Normal file
0
F1-nolib/PL2303/pl2303.bin
Executable file → Normal file
0
F1-nolib/SPI/SPI.bin
Executable file → Normal file
0
F1-nolib/SPI/SPI.bin
Executable file → Normal file
0
F1-nolib/USB_HID/usbhid103.bin
Executable file → Normal file
0
F1-nolib/USB_HID/usbhid103.bin
Executable file → Normal file
@ -27,7 +27,6 @@
|
|||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include <string.h> // memcpy
|
#include <string.h> // memcpy
|
||||||
|
|
||||||
#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)
|
#define GPS_send_string(str) do{usart_send(GPS_USART, str);}while(0)
|
||||||
|
|
||||||
gps_status GPS_status = GPS_NOTFOUND;
|
gps_status GPS_status = GPS_NOTFOUND;
|
||||||
@ -58,40 +57,34 @@ static int checksum_true(const char *buf){
|
|||||||
|
|
||||||
static void send_chksum(uint8_t chs){
|
static void send_chksum(uint8_t chs){
|
||||||
usart_putchar(GPS_USART, hex(chs >> 4));
|
usart_putchar(GPS_USART, hex(chs >> 4));
|
||||||
//usart_putchar(1, hex(chs >> 4));
|
|
||||||
usart_putchar(GPS_USART, hex(chs & 0x0f));
|
usart_putchar(GPS_USART, hex(chs & 0x0f));
|
||||||
//usart_putchar(1, hex(chs & 0x0f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate checksum & write message to port
|
* Calculate checksum & write message to port
|
||||||
* @param buf - command to write (without leading $ and trailing *)
|
* @param buf - command to write (without leading $ and trailing *)
|
||||||
* return 0 if fails
|
* return 0 if fails
|
||||||
*/
|
*/
|
||||||
static void write_with_checksum(const char *buf){
|
static void write_with_checksum(const char *buf){
|
||||||
char *txt = NULL;
|
/*
|
||||||
// clear old buffer data
|
|
||||||
for(int i = 0; i < 10000; ++i){
|
for(int i = 0; i < 10000; ++i){
|
||||||
|
char *txt = NULL;
|
||||||
if(usartrx(GPS_USART)){
|
if(usartrx(GPS_USART)){
|
||||||
usart_getline(GPS_USART, &txt);
|
usart_getline(GPS_USART, &txt);
|
||||||
DBG("Old data");
|
DBG("Old data");
|
||||||
GPS_parse_answer(txt);
|
GPS_parse_answer(txt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
//DBG("Send:");
|
|
||||||
uint8_t checksum = 0;
|
uint8_t checksum = 0;
|
||||||
usart_putchar(GPS_USART, '$');
|
usart_putchar(GPS_USART, '$');
|
||||||
//usart_putchar(1, '$');
|
|
||||||
GPS_send_string(buf);
|
GPS_send_string(buf);
|
||||||
//SEND(buf);
|
|
||||||
do{
|
do{
|
||||||
checksum ^= *buf++;
|
checksum ^= *buf++;
|
||||||
}while(*buf);
|
}while(*buf);
|
||||||
usart_putchar(GPS_USART, '*');
|
usart_putchar(GPS_USART, '*');
|
||||||
//usart_putchar(1, '*');
|
|
||||||
send_chksum(checksum);
|
send_chksum(checksum);
|
||||||
//newline();
|
newline(GPS_USART);
|
||||||
GPS_endline();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -157,7 +150,7 @@ void GPS_parse_answer(const char *buf){
|
|||||||
char *ptr;
|
char *ptr;
|
||||||
if(buf[1] == 'P') return; // answers to proprietary messages
|
if(buf[1] == 'P') return; // answers to proprietary messages
|
||||||
if(cmpstr(buf+3, "RMC", 3)){ // not RMC message
|
if(cmpstr(buf+3, "RMC", 3)){ // not RMC message
|
||||||
need2startseq = 1;
|
//need2startseq = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!checksum_true(buf)){
|
if(!checksum_true(buf)){
|
||||||
@ -165,7 +158,7 @@ void GPS_parse_answer(const char *buf){
|
|||||||
}
|
}
|
||||||
if(showGPSstr){
|
if(showGPSstr){
|
||||||
showGPSstr = 0;
|
showGPSstr = 0;
|
||||||
USB_send(buf);
|
sendstring(buf);
|
||||||
}
|
}
|
||||||
buf += 7; // skip header
|
buf += 7; // skip header
|
||||||
if(*buf == ','){ // time unknown
|
if(*buf == ','){ // time unknown
|
||||||
|
|||||||
@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* GPS.h
|
|
||||||
*
|
|
||||||
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef __GPS_H__
|
|
||||||
#define __GPS_H__
|
|
||||||
|
|
||||||
#include "stm32f1.h"
|
|
||||||
|
|
||||||
extern int need2startseq;
|
|
||||||
|
|
||||||
typedef enum{
|
|
||||||
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;
|
|
||||||
|
|
||||||
extern gps_status GPS_status;
|
|
||||||
|
|
||||||
void GPS_parse_answer(const char *string);
|
|
||||||
void GPS_send_start_seq();
|
|
||||||
void GPS_send_FullColdStart();
|
|
||||||
|
|
||||||
#endif // __GPS_H__
|
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
# make debug adds -DEBUG -Werror
|
||||||
|
# make ADDEFS="additional defs"
|
||||||
BINARY = chrono
|
BINARY = chrono
|
||||||
BOOTPORT ?= /dev/ttyUSB0
|
BOOTPORT ?= /dev/ttyUSB0
|
||||||
BOOTSPEED ?= 115200
|
BOOTSPEED ?= 115200
|
||||||
@ -9,13 +11,10 @@ MCU ?= F103x8
|
|||||||
DENSITY ?= MD
|
DENSITY ?= MD
|
||||||
# change this linking script depending on particular MCU model,
|
# change this linking script depending on particular MCU model,
|
||||||
LDSCRIPT ?= stm32F103xB.ld
|
LDSCRIPT ?= stm32F103xB.ld
|
||||||
DEFS = -DVERSION=\"0.0.2\"
|
DEFS = ${ADDEFS} -DVERSION=\"0.1.0\"
|
||||||
# debug
|
TARGET := RELEASE
|
||||||
#DEFS += -DEBUG
|
|
||||||
# proxy GPS output over USART1
|
# proxy GPS output over USART1
|
||||||
DEFS += -DUSART1PROXY
|
#DEFS += -DUSART1PROXY
|
||||||
|
|
||||||
INDEPENDENT_HEADERS=
|
|
||||||
|
|
||||||
FP_FLAGS ?= -msoft-float -mfloat-abi=soft
|
FP_FLAGS ?= -msoft-float -mfloat-abi=soft
|
||||||
ASM_FLAGS ?= -mthumb -mcpu=cortex-m3 -mfix-cortex-m3-ldrd
|
ASM_FLAGS ?= -mthumb -mcpu=cortex-m3 -mfix-cortex-m3-ldrd
|
||||||
@ -60,13 +59,13 @@ LIB_DIR := $(INC_DIR)/ld
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
# C flags
|
# C flags
|
||||||
CFLAGS += -O2 -g -D__thumb2__=1 -MD
|
CFLAGS += -O2 -g -D__thumb2__=1 -MD
|
||||||
CFLAGS += -Wall -Werror -Wextra -Wshadow
|
CFLAGS += -Wall -Wextra -Wshadow
|
||||||
CFLAGS += -fno-common -ffunction-sections -fdata-sections -fno-stack-protector
|
CFLAGS += -fno-common -ffunction-sections -fdata-sections -fno-stack-protector
|
||||||
CFLAGS += $(ARCH_FLAGS)
|
CFLAGS += $(ARCH_FLAGS)
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Linker flags
|
# Linker flags
|
||||||
LDFLAGS += -nostartfiles --static -nostdlibs
|
LDFLAGS += --static -nostartfiles -nostdlibs
|
||||||
LDFLAGS += -L$(LIB_DIR) -L$(TOOLCHLIB)
|
LDFLAGS += -L$(LIB_DIR) -L$(TOOLCHLIB)
|
||||||
LDFLAGS += -T$(LDSCRIPT)
|
LDFLAGS += -T$(LDSCRIPT)
|
||||||
|
|
||||||
@ -81,7 +80,24 @@ LIST := $(OBJDIR)/$(BINARY).list
|
|||||||
BIN := $(BINARY).bin
|
BIN := $(BINARY).bin
|
||||||
HEX := $(BINARY).hex
|
HEX := $(BINARY).hex
|
||||||
|
|
||||||
all: bin list size
|
all: $(OBJDIR)/RELEASE bin list size
|
||||||
|
release: all
|
||||||
|
|
||||||
|
debug: CFLAGS += -DEBUG -Werror
|
||||||
|
debug: $(OBJDIR)/DEBUG bin list size
|
||||||
|
|
||||||
|
$(OBJDIR)/DEBUG:
|
||||||
|
@rm -rf $(OBJDIR)
|
||||||
|
@mkdir $(OBJDIR)
|
||||||
|
@> $(OBJDIR)/DEBUG
|
||||||
|
@echo "TARGET: DEBUG"
|
||||||
|
echo "CFLAGS += -DEBUG -Werror" > $(OBJDIR)/CFLAGS
|
||||||
|
$(OBJDIR)/RELEASE:
|
||||||
|
@rm -rf $(OBJDIR)
|
||||||
|
@mkdir $(OBJDIR)
|
||||||
|
@> $(OBJDIR)/RELEASE
|
||||||
|
@echo "TARGET: RELEASE"
|
||||||
|
echo "" > $(OBJDIR)/CFLAGS
|
||||||
|
|
||||||
elf: $(ELF)
|
elf: $(ELF)
|
||||||
bin: $(BIN)
|
bin: $(BIN)
|
||||||
@ -90,6 +106,7 @@ list: $(LIST)
|
|||||||
|
|
||||||
ifneq ($(MAKECMDGOALS),clean)
|
ifneq ($(MAKECMDGOALS),clean)
|
||||||
-include $(DEPS)
|
-include $(DEPS)
|
||||||
|
-include $(OBJDIR)/CFLAGS
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(OBJDIR):
|
$(OBJDIR):
|
||||||
@ -114,7 +131,7 @@ $(LIST): $(ELF)
|
|||||||
@echo " OBJDUMP $(LIST)"
|
@echo " OBJDUMP $(LIST)"
|
||||||
$(OBJDUMP) -S $(ELF) > $(LIST)
|
$(OBJDUMP) -S $(ELF) > $(LIST)
|
||||||
|
|
||||||
$(ELF): $(OBJDIR) $(OBJS)
|
$(ELF): $(OBJDIR) $(OBJS) $(LDSCRIPT)
|
||||||
@echo " LD $(ELF)"
|
@echo " LD $(ELF)"
|
||||||
$(LD) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
|
$(LD) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
|
||||||
|
|
||||||
@ -123,13 +140,13 @@ size: $(ELF)
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
@echo " CLEAN"
|
@echo " CLEAN"
|
||||||
$(RM) $(OBJS) $(DEPS) $(ELF) $(HEX) $(LIST)
|
@$(RM) $(HEX)
|
||||||
@rmdir $(OBJDIR) 2>/dev/null || true
|
@$(RM) -rf $(OBJDIR) 2>/dev/null || true
|
||||||
|
|
||||||
|
|
||||||
flash: $(BIN)
|
flash: $(BIN)
|
||||||
@echo " FLASH $(BIN)"
|
@echo " FLASH $(BIN)"
|
||||||
$(STFLASH) write $(BIN) 0x8000000
|
$(STFLASH) --reset write $(BIN) 0x8000000
|
||||||
|
|
||||||
boot: $(BIN)
|
boot: $(BIN)
|
||||||
@echo " LOAD $(BIN) through bootloader"
|
@echo " LOAD $(BIN) through bootloader"
|
||||||
|
|||||||
@ -1,33 +0,0 @@
|
|||||||
Chronometer for downhill competitions
|
|
||||||
=====================================
|
|
||||||
|
|
||||||
## Pinout
|
|
||||||
|
|
||||||
- PA11/12 - USB
|
|
||||||
- PA9(Tx),PA10 (debug mode) - USART1 - debug console
|
|
||||||
- PA2(Tx), PA3 - USART2 - GPS
|
|
||||||
- PB10(Tx), PB11 - USART3 - LIDAR - TRIG3
|
|
||||||
|
|
||||||
- PA1 - PPS signal from GPS (EXTI)
|
|
||||||
|
|
||||||
- PA4 - TRIG2 - 12V trigger (EXTI)
|
|
||||||
- PA13 - TRIG0 - button0 (EXTI)
|
|
||||||
- PA14 - TRIG1 - button1/laser/etc (EXTI)
|
|
||||||
- PA15 - USB pullup
|
|
||||||
|
|
||||||
- PB8, PB9 - onboard LEDs (0/1)
|
|
||||||
|
|
||||||
- PC13 - buzzer
|
|
||||||
|
|
||||||
## LEDS
|
|
||||||
|
|
||||||
- LED0 - shining when there's no PPS signal, fades for 0.25s on PPS
|
|
||||||
- LED1 - don't shines if no GPS found, shines when time not valid, blinks when time valid
|
|
||||||
|
|
||||||
### Not implemented yet:
|
|
||||||
|
|
||||||
- PA5,6,7 (SCK, MISO, MOSI) - SPI
|
|
||||||
- PB0 - TRIG4 - ADC channel 8
|
|
||||||
- PB6/7 (SCL, SDA) - I2C
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
Дополнено выводом времени на LED screen.
|
||||||
|
|
||||||
!!! инвертировать USB_PU
|
!!! инвертировать USB_PU
|
||||||
|
|
||||||
|
|
||||||
@ -5,34 +7,33 @@
|
|||||||
|
|
||||||
=== Интерфейсы I/O ===
|
=== Интерфейсы I/O ===
|
||||||
- PA11/12 - USB
|
- PA11/12 - USB
|
||||||
- PA9(Tx), PA10(Rx) - USART1 - прокси RMC-сообщений GPS.
|
- PA9(Tx), PA10(Rx) - USART1 - консоль отладки / прокси RMC-сообщений GPS (опт. - bluetooth).
|
||||||
- PA2(Tx), PA3(Rx) - USART2 - подключение GPS-приемника.
|
- PA2(Tx), PA3(Rx) - USART2 - подключение GPS-приемника.
|
||||||
- PB10(Tx), PB11(Rx) - USART3 - подключение лидара.
|
- PB10(Tx), PB11(Rx) - USART3 - подключение лидара или другой консоли.
|
||||||
|
|
||||||
=== Остальные порты ===
|
=== Остальные порты ===
|
||||||
- PA1 - PPS сигнал от GPS; сюда можно подключать любой дополнительный высокоомный вход напрямую.
|
- PA1 - PPS сигнал от GPS; сюда можно подключать любой дополнительный высокоомный вход напрямую.
|
||||||
- PA4 - TRIG2 - подключен к каналу 12В.
|
- PB0 - TRIG0 - (замыкать на землю).
|
||||||
- PA13 - TRIG0 - кнопка или створ, замыкающий контакты.
|
- PB1 - TRIG1 - подключен к 12В.
|
||||||
- PA14 - TRIG1 - так же, как и вход TRIG0.
|
- PB3 - TRIG2 - (замыкать на землю).
|
||||||
- PA15 - подтяжка USB.
|
- PA15 - подтяжка USB.
|
||||||
- PB0 - TRIG4 - триггер по АЦП.
|
- PA8 - (еще не реализовано) - bluetooth "state"
|
||||||
- PB8, PB9 - индикаторные светодиоды.
|
- PB8, PB9 - индикаторные светодиоды (LED1, LED0 соответственно).
|
||||||
- PC13 - пищалка.
|
- PC13 - пищалка.
|
||||||
|
|
||||||
=== Светодиоды ===
|
=== Светодиоды ===
|
||||||
- LED0 (зеленый) - при отсутствии сигнала PPS просто горит, если PPS появляется - мигает (затухает на 0.25с на каждый сигнал).
|
- LED0 - при отсутствии сигнала PPS просто горит, если PPS появляется - мигает (затухает на 0.25с на каждый сигнал).
|
||||||
- LED1 (красный) - индикатор GPS: не горит, если приемник не обнаружен, горит, если неуверенный прием времени (буква "V" во второй позиции RMC-сообщения), мигает при уверенном приеме (буква "A" во второй позиции).
|
- LED1 - индикатор GPS: не горит, если приемник не обнаружен; горит постоянно, если неуверенный прием времени
|
||||||
|
(буква "V" во второй позиции RMC-сообщения); мигает при уверенном приеме (буква "A" во второй позиции).
|
||||||
Судя по эксперименту, даже через час после пропадания сигнала точность определения события - не хуже 1мс. Сам GPS-приемник выдает
|
Судя по эксперименту, даже через час после пропадания сигнала точность определения события - не хуже 1мс. Сам GPS-приемник выдает
|
||||||
PPS даже при отсутствии спутников - лишь бы он успел "подхватить" точное время и начать генерировать pps. Начинать работу можно сразу,
|
PPS даже при отсутствии спутников - лишь бы он успел "подхватить" точное время и начать генерировать pps. Начинать работу можно сразу,
|
||||||
как только замигает зеленый светодиод после мигающего красного.
|
как только замигает LED0.
|
||||||
|
|
||||||
|
|
||||||
****** Триггеры ******
|
****** Триггеры ******
|
||||||
На прототипе распаяно два входа на триггеры: TRIG0 и TRIG2. К TRIG2 нужно подключать 12-вольтный сигнал, ток не меньше 10мА.
|
К TRIG0/TRIG2 подключается кнопка, педаль, иной створ, замыкающий контакты. Никакого внешнего напряжения здесь быть не должно!
|
||||||
Если створ имеет открытый коллектор, то выход створа подключается к минусу TRIG2, а к плюсу подключается 12В с источника питания.
|
К TRIG1 нужно подключать 12-вольтный сигнал, ток не меньше 10мА. Если створ имеет открытый коллектор, то выход створа подключается
|
||||||
TRIG0 предназначен для подключения кнопки или концевика, просто замыкающего контакты. Никакого внешнего напряжения там быть не должно!
|
к минусу TRIG2, а к плюсу подключается 12В с источника питания.
|
||||||
|
|
||||||
TRIG4 - аналоговый вход. Если будут ложные срабатывания на девбордах, порт PB0 нужно напрямую или через резистор до 10кОм посадить на землю.
|
|
||||||
|
|
||||||
Иногда бывают ложные срабатывания триггеров TRIG0..TRIG2, связанные с мощными источниками искр (зажигание, искрящиеся обмотки и т.п.).
|
Иногда бывают ложные срабатывания триггеров TRIG0..TRIG2, связанные с мощными источниками искр (зажигание, искрящиеся обмотки и т.п.).
|
||||||
В случае таких ложных срабатываний рекомендуется заземлить катод источника питания хронометра.
|
В случае таких ложных срабатываний рекомендуется заземлить катод источника питания хронометра.
|
||||||
@ -41,26 +42,13 @@ TRIG4 -
|
|||||||
|
|
||||||
|
|
||||||
****** Подключение ******
|
****** Подключение ******
|
||||||
Хронометр эмулирует "китайский" преобразователь PL2303. В линуксе нужно, чтобы был скомпилирован соответствующий модуль ядра.
|
Хронометр эмулирует "китайский" преобразователь PL2303.
|
||||||
В андроиде работает "из коробки". В мастдайке новые драйвера PL2303 имеют защиту от подделок (те просто не работают с этими дровами),
|
|
||||||
поэтому для нормальной работы необходимо найти и установить старые драйвера.
|
|
||||||
|
|
||||||
К выходам PA9/PA10 можно подключить преобразователь USART<>USB или накинуть их напрямую на ноги Rx/Tx "малинки" (не забыв соединить
|
К выходам PA9/PA10 можно подключить преобразователь USART<>USB или накинуть их напрямую на ноги Rx/Tx "малинки" (не забыв соединить
|
||||||
земли хронометра и малинки): PA9(Tx) соединить с Rx, PA10(Rx) - с Tx. Этот USART проксирует RMC-сообщения GPS-приемника (уже после
|
земли хронометра и малинки): PA9(Tx) соединить с Rx, PA10(Rx) - с Tx. Этот USART проксирует RMC-сообщения GPS-приемника (уже после
|
||||||
обработки микроконтроллером, поэтому если МК выключен, а приемник включен, сигнала все равно не будет).
|
обработки микроконтроллером, поэтому если МК выключен, а приемник включен, сигнала все равно не будет).
|
||||||
|
|
||||||
Для подключения PPS сигнала к "малинке" нужно напрямую соединить соответствующую ногу GPIO "малинки" с портом PA1 девборды.
|
Для подключения PPS сигнала к "малинке" выведен соответствующий разъем.
|
||||||
На прототипе нужно подпаяться к дорожке, выходящей с ноги PPS (отмечено маркером).
|
|
||||||
|
|
||||||
Подтяжка USB есть лишь на прототипе, на девбордах ее нет. Поэтому в случае перезагрузки микроконтроллера девборды для возобновления
|
|
||||||
соединения необходимо переткнуть шнурок USB. В этом плане прототип надежней: сбросить МК можно независимо от питания GPS.
|
|
||||||
|
|
||||||
На прототипе и девбордах отсутствует подсоединение пищалки. На девбордах при желании можно накинуть на PC13 что-нибудь для индикации
|
|
||||||
срабатывания створа (активный выход - "1" в течение 0.3с).
|
|
||||||
|
|
||||||
На девбордах не распаяны светодиодные индикаторы. Особого смысла в них нет, но если понадобится подключить, нагрузка должна висеть на
|
|
||||||
PB8/PB9. Активный выход - низкий. Нога МК настроена в режиме open-drain, но внешняя подтяжка не должна быть выше +3.5В. И потребление
|
|
||||||
не больше 5мА на ногу.
|
|
||||||
|
|
||||||
|
|
||||||
****** Конфигурация ******
|
****** Конфигурация ******
|
||||||
@ -133,15 +121,3 @@ vdd - Vdd value
|
|||||||
После изменения конфигурации и ее сохранения необходимо нажатием на reset или отключением/включением питания перезагрузить МК,
|
После изменения конфигурации и ее сохранения необходимо нажатием на reset или отключением/включением питания перезагрузить МК,
|
||||||
т.к. некоторые параметры активируются лишь при старте.
|
т.к. некоторые параметры активируются лишь при старте.
|
||||||
|
|
||||||
|
|
||||||
****** Девборды и плата-прототип ******
|
|
||||||
На платках из девборд два канала опторазвязок подключены к триггерам TRIG0 и TRIG1.
|
|
||||||
Синий провод - земля, красные - +12В для каждого канала. Т.е. схема рассчитана на срабатывание по появлению плюса на одном из каналов.
|
|
||||||
|
|
||||||
В случае необходимости срабатывания по подтяжке к земле, нужно разорвать землю на входах опторазвязок и, наоборот, объединить плюсы.
|
|
||||||
На плюсы подать +12В, минусы подключить к сигнальным выходам створов.
|
|
||||||
|
|
||||||
На прототипе распаяны развязки только на два канала: TRIG0 - для подключения чего-то, замыкающего контакты, и TRIG2 - для подключения
|
|
||||||
чего-то, выдающего 12В. Я оставил такую конфигурацию: к TRIG0 можно подключить нормально замкнутую кнопку (triglevel01), а TRIG2
|
|
||||||
сработает при поступлении туда 12В (triglevel21).
|
|
||||||
|
|
||||||
|
|||||||
@ -36,8 +36,8 @@ uint16_t ADC_array[NUMBER_OF_ADC_CHANNELS*9];
|
|||||||
uint16_t getADCval(int nch){
|
uint16_t getADCval(int nch){
|
||||||
int i, addr = nch;
|
int i, addr = nch;
|
||||||
register uint16_t temp;
|
register uint16_t temp;
|
||||||
#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); }
|
#define PIX_SORT(a,b) do{ if ((a)>(b)) PIX_SWAP((a),(b)); }while(0)
|
||||||
#define PIX_SWAP(a,b) { temp=(a);(a)=(b);(b)=temp; }
|
#define PIX_SWAP(a,b) do{ temp=(a);(a)=(b);(b)=temp; }while(0)
|
||||||
uint16_t p[9];
|
uint16_t p[9];
|
||||||
for(i = 0; i < 9; ++i, addr += NUMBER_OF_ADC_CHANNELS) // first we should prepare array for optmed
|
for(i = 0; i < 9; ++i, addr += NUMBER_OF_ADC_CHANNELS) // first we should prepare array for optmed
|
||||||
p[i] = ADC_array[addr];
|
p[i] = ADC_array[addr];
|
||||||
@ -57,8 +57,8 @@ uint16_t getADCval(int nch){
|
|||||||
int32_t getMCUtemp(){
|
int32_t getMCUtemp(){
|
||||||
// Temp = (V25 - Vsense)/Avg_Slope + 25
|
// Temp = (V25 - Vsense)/Avg_Slope + 25
|
||||||
// V_25 = 1.45V, Slope = 4.3e-3
|
// V_25 = 1.45V, Slope = 4.3e-3
|
||||||
int32_t Vsense = getVdd() * getADCval(1);
|
uint32_t Vsense = getVdd() * getADCval(ADC_TMCU_CHANNEL);
|
||||||
int32_t temperature = 593920 - Vsense; // 593920 == 145*4096
|
int32_t temperature = 593920 - (int32_t)Vsense; // 593920 == 145*4096
|
||||||
temperature /= 172; // == /(4096*10*4.3e-3), 10 - to convert from *100 to *10
|
temperature /= 172; // == /(4096*10*4.3e-3), 10 - to convert from *100 to *10
|
||||||
temperature += 250;
|
temperature += 250;
|
||||||
return(temperature);
|
return(temperature);
|
||||||
@ -67,27 +67,6 @@ int32_t getMCUtemp(){
|
|||||||
// return Vdd * 100 (V)
|
// return Vdd * 100 (V)
|
||||||
uint32_t getVdd(){
|
uint32_t getVdd(){
|
||||||
uint32_t vdd = 120 * 4096; // 1.2V
|
uint32_t vdd = 120 * 4096; // 1.2V
|
||||||
vdd /= getADCval(2);
|
vdd /= getADCval(ADC_VDD_CHANNEL);
|
||||||
return vdd;
|
return vdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief chkADCtrigger - check ADC trigger state
|
|
||||||
* @return value of `triggered`
|
|
||||||
*/
|
|
||||||
uint8_t chkADCtrigger(){
|
|
||||||
static uint8_t triggered = 0;
|
|
||||||
savetrigtime();
|
|
||||||
int16_t val = getADCval(0);
|
|
||||||
if(triggered){ // check untriggered action
|
|
||||||
if(val < (int16_t)the_conf.ADC_min - ADC_THRESHOLD || val > (int16_t)the_conf.ADC_max + ADC_THRESHOLD){
|
|
||||||
triggered = 0;
|
|
||||||
}
|
|
||||||
}else{ // check if thigger shot
|
|
||||||
if(val > (int16_t)the_conf.ADC_min + ADC_THRESHOLD && val < (int16_t)the_conf.ADC_max - ADC_THRESHOLD){
|
|
||||||
triggered = 1;
|
|
||||||
fillshotms(ADC_TRIGGER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return triggered;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -19,8 +19,6 @@
|
|||||||
#define ADC_H
|
#define ADC_H
|
||||||
#include "stm32f1.h"
|
#include "stm32f1.h"
|
||||||
|
|
||||||
#define NUMBER_OF_ADC_CHANNELS (3)
|
|
||||||
|
|
||||||
// interval of trigger's shot (>min && <max), maybe negative
|
// interval of trigger's shot (>min && <max), maybe negative
|
||||||
#define ADC_MIN_VAL (1024)
|
#define ADC_MIN_VAL (1024)
|
||||||
#define ADC_MAX_VAL (3072)
|
#define ADC_MAX_VAL (3072)
|
||||||
@ -31,5 +29,4 @@ extern uint16_t ADC_array[];
|
|||||||
int32_t getMCUtemp();
|
int32_t getMCUtemp();
|
||||||
uint32_t getVdd();
|
uint32_t getVdd();
|
||||||
uint16_t getADCval(int nch);
|
uint16_t getADCval(int nch);
|
||||||
uint8_t chkADCtrigger();
|
|
||||||
#endif // ADC_H
|
#endif // ADC_H
|
||||||
|
|||||||
Binary file not shown.
@ -1,177 +0,0 @@
|
|||||||
/*
|
|
||||||
* GPS.c
|
|
||||||
*
|
|
||||||
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "GPS.h"
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "time.h"
|
|
||||||
#include "usart.h"
|
|
||||||
#include "str.h"
|
|
||||||
#include <string.h> // memcpy
|
|
||||||
|
|
||||||
#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;
|
|
||||||
int need2startseq = 1;
|
|
||||||
|
|
||||||
static uint8_t hex(uint8_t n){
|
|
||||||
return ((n < 10) ? (n+'0') : (n+'A'-10));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check checksum
|
|
||||||
*/
|
|
||||||
static int checksum_true(const char *buf){
|
|
||||||
char *eol;
|
|
||||||
uint8_t checksum = 0, cs[3];
|
|
||||||
if(*buf != '$' || !(eol = getchr(buf, '*'))){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
while(++buf != eol)
|
|
||||||
checksum ^= (uint8_t)*buf;
|
|
||||||
++buf;
|
|
||||||
cs[0] = hex(checksum >> 4);
|
|
||||||
cs[1] = hex(checksum & 0x0f);
|
|
||||||
if(buf[0] == cs[0] && buf[1] == cs[1])
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void send_chksum(uint8_t chs){
|
|
||||||
usart_putchar(GPS_USART, hex(chs >> 4));
|
|
||||||
usart_putchar(1, hex(chs >> 4));
|
|
||||||
usart_putchar(GPS_USART, hex(chs & 0x0f));
|
|
||||||
usart_putchar(1, hex(chs & 0x0f));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Calculate checksum & write message to port
|
|
||||||
* @param buf - command to write (without leading $ and trailing *)
|
|
||||||
* return 0 if fails
|
|
||||||
*/
|
|
||||||
static void write_with_checksum(const char *buf){
|
|
||||||
char *txt = NULL;
|
|
||||||
// clear old buffer data
|
|
||||||
for(int i = 0; i < 10000; ++i){
|
|
||||||
if(usartrx(GPS_USART)){
|
|
||||||
usart_getline(GPS_USART, &txt);
|
|
||||||
DBG("Old data");
|
|
||||||
GPS_parse_answer(txt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DBG("Send:");
|
|
||||||
uint8_t checksum = 0;
|
|
||||||
usart_putchar(GPS_USART, '$');
|
|
||||||
usart_putchar(1, '$');
|
|
||||||
GPS_send_string(buf);
|
|
||||||
SEND(buf);
|
|
||||||
do{
|
|
||||||
checksum ^= *buf++;
|
|
||||||
}while(*buf);
|
|
||||||
usart_putchar(GPS_USART, '*');
|
|
||||||
usart_putchar(1, '*');
|
|
||||||
send_chksum(checksum);
|
|
||||||
newline();
|
|
||||||
GPS_endline();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MTK fields format:
|
|
||||||
* $PMTKxxx,yyy,zzz*2E
|
|
||||||
* P - proprietary, MTK - always this, xxx - packet type, yyy,zzz - packet data
|
|
||||||
* Packet types:
|
|
||||||
* 220 - PMTK_SET_POS_FIX, data - position fix interval (msec, > 200)
|
|
||||||
* 255 - PMTK_SET_SYNC_PPS_NMEA - turn on/off (def - off) PPS, data = 0/1 -> "$PMTK255,1" turn ON
|
|
||||||
* 285 - PMTK_SET_PPS_CONFIG - set PPS configuration, data fields:
|
|
||||||
* 1st - 0-disable, 1-after 1st fix, 2-3D only, 3-2D/3D only, 4-always
|
|
||||||
* 2nd - 2..998 - pulse width
|
|
||||||
* 314 - PMTK_API_SET_NMEA_OUTPUT - set output messages, N== N fixes per output,
|
|
||||||
* order of messages: GLL,RMC,VTG,GGA,GSA,GSV,GRS,GST, only RMC per every pos fix:
|
|
||||||
* $PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
||||||
* 386 - PMTK_API_SET_STATIC_NAV_THD speed threshold (m/s) for static navigation
|
|
||||||
* $PMTK386,1.5
|
|
||||||
* ;
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send starting sequences (get only RMC messages)
|
|
||||||
*/
|
|
||||||
void GPS_send_start_seq(){
|
|
||||||
DBG("Send start seq");
|
|
||||||
// turn ON PPS:
|
|
||||||
write_with_checksum("PMTK255,1");
|
|
||||||
// set pulse width to 10ms with working after 1st fix
|
|
||||||
write_with_checksum("PMTK285,1,10");
|
|
||||||
// set only RMC:
|
|
||||||
write_with_checksum("PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
|
|
||||||
// set static speed threshold
|
|
||||||
write_with_checksum("PMTK386,1.5");
|
|
||||||
need2startseq = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse answer from GPS module
|
|
||||||
*
|
|
||||||
* Recommended minimum specific GPS/Transit data
|
|
||||||
* $GPRMC,hhmmss.sss,status,latitude,N,longitude,E,spd,cog,ddmmyy,mv,mvE,mode*cs
|
|
||||||
* 1 = UTC of position fix
|
|
||||||
* 2 = Data status (V=valid, A=invalid)
|
|
||||||
* 3 = Latitude (ddmm.mmmm)
|
|
||||||
* 4 = N or S
|
|
||||||
* 5 = Longitude (dddmm.mmmm)
|
|
||||||
* 6 = E or W
|
|
||||||
* 7 = Speed over ground in knots
|
|
||||||
* 8 = Cource over ground in degrees
|
|
||||||
* 9 = UT date (ddmmyy)
|
|
||||||
* 10 = Magnetic variation degrees (Easterly var. subtracts from true course)
|
|
||||||
* 11 = E or W
|
|
||||||
* 12 = Mode: N(bad), E(approx), A(auto), D(diff)
|
|
||||||
* 213457.00,A,4340.59415,N,04127.47560,E,2.494,,290615,,,A*7B
|
|
||||||
*/
|
|
||||||
void GPS_parse_answer(const char *buf){
|
|
||||||
char *ptr;
|
|
||||||
#if defined USART1PROXY
|
|
||||||
usart_send(1, buf); newline();
|
|
||||||
#endif
|
|
||||||
if(buf[1] == 'P') return; // answers to proprietary messages
|
|
||||||
if(cmpstr(buf+3, "RMC", 3)){ // not RMC message
|
|
||||||
need2startseq = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(!checksum_true(buf)){
|
|
||||||
return; // wrong checksum
|
|
||||||
}
|
|
||||||
buf += 7; // skip header
|
|
||||||
if(*buf == ','){ // time unknown
|
|
||||||
GPS_status = GPS_WAIT;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ptr = getchr(buf, ',');
|
|
||||||
if(!ptr ) return;
|
|
||||||
*ptr++ = 0;
|
|
||||||
if(*ptr == 'A'){
|
|
||||||
GPS_status = GPS_VALID;
|
|
||||||
set_time(buf);
|
|
||||||
}else{
|
|
||||||
GPS_status = GPS_NOT_VALID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* GPS.h
|
|
||||||
*
|
|
||||||
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef __GPS_H__
|
|
||||||
#define __GPS_H__
|
|
||||||
|
|
||||||
#include "stm32f1.h"
|
|
||||||
|
|
||||||
extern int need2startseq;
|
|
||||||
|
|
||||||
typedef enum{
|
|
||||||
GPS_WAIT // wait for satellites
|
|
||||||
,GPS_NOT_VALID // time known, but not valid
|
|
||||||
,GPS_VALID
|
|
||||||
} gps_status;
|
|
||||||
|
|
||||||
extern gps_status GPS_status;
|
|
||||||
|
|
||||||
void GPS_parse_answer(const char *string);
|
|
||||||
void GPS_send_start_seq();
|
|
||||||
|
|
||||||
#endif // __GPS_H__
|
|
||||||
@ -1,142 +0,0 @@
|
|||||||
BINARY = chrono
|
|
||||||
BOOTPORT ?= /dev/ttyUSB0
|
|
||||||
BOOTSPEED ?= 115200
|
|
||||||
# MCU FAMILY
|
|
||||||
FAMILY ?= F1
|
|
||||||
# MCU code
|
|
||||||
MCU ?= F103x8
|
|
||||||
# density (stm32f10x.h, lines 70-84)
|
|
||||||
DENSITY ?= MD
|
|
||||||
# change this linking script depending on particular MCU model,
|
|
||||||
LDSCRIPT ?= stm32f103x8.ld
|
|
||||||
DEFS = -DVERSION=\"0.0.1\"
|
|
||||||
# debug
|
|
||||||
DEFS += -DEBUG
|
|
||||||
# proxy GPS output over USART1
|
|
||||||
DEFS += -DUSART1PROXY
|
|
||||||
|
|
||||||
INDEPENDENT_HEADERS=
|
|
||||||
|
|
||||||
FP_FLAGS ?= -msoft-float -mfloat-abi=soft
|
|
||||||
ASM_FLAGS ?= -mthumb -mcpu=cortex-m3 -mfix-cortex-m3-ldrd
|
|
||||||
ARCH_FLAGS = $(ASM_FLAGS) $(FP_FLAGS)
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Executables
|
|
||||||
#PREFIX ?= arm-none-eabi
|
|
||||||
# gcc from arm web site
|
|
||||||
PREFIX ?= /opt/bin/arm-none-eabi
|
|
||||||
TOOLCHLIB ?= /opt/arm-none-eabi/lib
|
|
||||||
RM := rm -f
|
|
||||||
RMDIR := rmdir
|
|
||||||
CC := $(PREFIX)-gcc
|
|
||||||
# don't replace ld with gcc: the binary size would be much greater!!
|
|
||||||
LD := $(PREFIX)-ld
|
|
||||||
AR := $(PREFIX)-ar
|
|
||||||
AS := $(PREFIX)-as
|
|
||||||
SIZE := $(PREFIX)-size
|
|
||||||
OBJCOPY := $(PREFIX)-objcopy
|
|
||||||
OBJDUMP := $(PREFIX)-objdump
|
|
||||||
GDB := $(PREFIX)-gdb
|
|
||||||
STFLASH := $(shell which st-flash)
|
|
||||||
STBOOT := $(shell which stm32flash)
|
|
||||||
DFUUTIL := $(shell which dfu-util)
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Source files
|
|
||||||
OBJDIR = mk
|
|
||||||
SRC := $(wildcard *.c)
|
|
||||||
OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o))
|
|
||||||
STARTUP = $(OBJDIR)/startup.o
|
|
||||||
OBJS += $(STARTUP)
|
|
||||||
# dependencies: we need them to recompile files if their headers-dependencies changed
|
|
||||||
DEPS := $(OBJS:.o=.d)
|
|
||||||
|
|
||||||
INC_DIR ?= ../inc
|
|
||||||
|
|
||||||
INCLUDE := -I$(INC_DIR)/Fx -I$(INC_DIR)/cm
|
|
||||||
LIB_DIR := $(INC_DIR)/ld
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# C flags
|
|
||||||
CFLAGS += -O2 -g -D__thumb2__=1 -MD
|
|
||||||
CFLAGS += -Wall -Werror -Wextra -Wshadow
|
|
||||||
CFLAGS += -fno-common -ffunction-sections -fdata-sections -fno-stack-protector
|
|
||||||
CFLAGS += $(ARCH_FLAGS)
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Linker flags
|
|
||||||
LDFLAGS += -nostartfiles --static -nostdlibs
|
|
||||||
LDFLAGS += -L$(LIB_DIR) -L$(TOOLCHLIB)
|
|
||||||
LDFLAGS += -T$(LDSCRIPT)
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Used libraries
|
|
||||||
LDLIBS += -lc $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
|
|
||||||
|
|
||||||
DEFS += -DSTM32$(FAMILY) -DSTM32$(MCU) -DSTM32F10X_$(DENSITY)
|
|
||||||
|
|
||||||
ELF := $(OBJDIR)/$(BINARY).elf
|
|
||||||
LIST := $(OBJDIR)/$(BINARY).list
|
|
||||||
BIN := $(BINARY).bin
|
|
||||||
HEX := $(BINARY).hex
|
|
||||||
|
|
||||||
all: bin list size
|
|
||||||
|
|
||||||
elf: $(ELF)
|
|
||||||
bin: $(BIN)
|
|
||||||
hex: $(HEX)
|
|
||||||
list: $(LIST)
|
|
||||||
|
|
||||||
ifneq ($(MAKECMDGOALS),clean)
|
|
||||||
-include $(DEPS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
$(OBJDIR):
|
|
||||||
mkdir $(OBJDIR)
|
|
||||||
|
|
||||||
$(STARTUP): $(INC_DIR)/startup/vector.c
|
|
||||||
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) -o $@ -c $<
|
|
||||||
|
|
||||||
$(OBJDIR)/%.o: %.c
|
|
||||||
@echo " CC $<"
|
|
||||||
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) -o $@ -c $<
|
|
||||||
|
|
||||||
$(BIN): $(ELF)
|
|
||||||
@echo " OBJCOPY $(BIN)"
|
|
||||||
$(OBJCOPY) -Obinary $(ELF) $(BIN)
|
|
||||||
|
|
||||||
$(HEX): $(ELF)
|
|
||||||
@echo " OBJCOPY $(HEX)"
|
|
||||||
$(OBJCOPY) -Oihex $(ELF) $(HEX)
|
|
||||||
|
|
||||||
$(LIST): $(ELF)
|
|
||||||
@echo " OBJDUMP $(LIST)"
|
|
||||||
$(OBJDUMP) -S $(ELF) > $(LIST)
|
|
||||||
|
|
||||||
$(ELF): $(OBJDIR) $(OBJS)
|
|
||||||
@echo " LD $(ELF)"
|
|
||||||
$(LD) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
|
|
||||||
|
|
||||||
size: $(ELF)
|
|
||||||
$(SIZE) $(ELF)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
@echo " CLEAN"
|
|
||||||
$(RM) $(OBJS) $(DEPS) $(ELF) $(HEX) $(LIST)
|
|
||||||
@rmdir $(OBJDIR) 2>/dev/null || true
|
|
||||||
|
|
||||||
|
|
||||||
flash: $(BIN)
|
|
||||||
@echo " FLASH $(BIN)"
|
|
||||||
$(STFLASH) write $(BIN) 0x8000000
|
|
||||||
|
|
||||||
boot: $(BIN)
|
|
||||||
@echo " LOAD $(BIN) through bootloader"
|
|
||||||
$(STBOOT) -b$(BOOTSPEED) $(BOOTPORT) -w $(BIN)
|
|
||||||
|
|
||||||
dfuboot: $(BIN)
|
|
||||||
@echo " LOAD $(BIN) THROUGH DFU"
|
|
||||||
$(DFUUTIL) -a0 -D $(BIN) -s 0x08000000
|
|
||||||
|
|
||||||
.PHONY: clean flash boot
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
Chronometer for downhill competitions
|
|
||||||
=====================================
|
|
||||||
|
|
||||||
## Pinout
|
|
||||||
|
|
||||||
- PA9(Tx),PA10 (debug mode) - USART1 - debug console
|
|
||||||
- PA2(Tx), PA3 - USART2 - GPS
|
|
||||||
- PB10(Tx), PB11 - USART3 - LIDAR
|
|
||||||
|
|
||||||
- PA1 - PPS signal from GPS (EXTI)
|
|
||||||
|
|
||||||
- PB8, PB9 - onboard LEDs
|
|
||||||
|
|
||||||
- PA4 - TRIG2 - 12V trigger (EXTI) -- not implemented yet
|
|
||||||
- PA13 - TRIG0 - button0 (EXTI)
|
|
||||||
- PA14 - TRIG1 - button1/laser/etc (EXTI)
|
|
||||||
- PA15 - USB pullup
|
|
||||||
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the chronometer project.
|
|
||||||
* Copyright 2018 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "adc.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief ADC_array - array for ADC channels with median filtering:
|
|
||||||
* 0 - Rvar
|
|
||||||
* 1 - internal Tsens
|
|
||||||
* 2 - Vref
|
|
||||||
*/
|
|
||||||
uint16_t ADC_array[NUMBER_OF_ADC_CHANNELS*9];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief getADCval - calculate median value for `nch` channel
|
|
||||||
* @param nch - number of channel
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
uint16_t getADCval(int nch){
|
|
||||||
int i, addr = nch;
|
|
||||||
register uint16_t temp;
|
|
||||||
#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); }
|
|
||||||
#define PIX_SWAP(a,b) { temp=(a);(a)=(b);(b)=temp; }
|
|
||||||
uint16_t p[9];
|
|
||||||
for(i = 0; i < 9; ++i, addr += NUMBER_OF_ADC_CHANNELS) // first we should prepare array for optmed
|
|
||||||
p[i] = ADC_array[addr];
|
|
||||||
PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ;
|
|
||||||
PIX_SORT(p[0], p[1]) ; PIX_SORT(p[3], p[4]) ; PIX_SORT(p[6], p[7]) ;
|
|
||||||
PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ;
|
|
||||||
PIX_SORT(p[0], p[3]) ; PIX_SORT(p[5], p[8]) ; PIX_SORT(p[4], p[7]) ;
|
|
||||||
PIX_SORT(p[3], p[6]) ; PIX_SORT(p[1], p[4]) ; PIX_SORT(p[2], p[5]) ;
|
|
||||||
PIX_SORT(p[4], p[7]) ; PIX_SORT(p[4], p[2]) ; PIX_SORT(p[6], p[4]) ;
|
|
||||||
PIX_SORT(p[4], p[2]) ;
|
|
||||||
return p[4];
|
|
||||||
#undef PIX_SORT
|
|
||||||
#undef PIX_SWAP
|
|
||||||
}
|
|
||||||
|
|
||||||
// return MCU temperature (degrees of celsius * 10)
|
|
||||||
int32_t getMCUtemp(){
|
|
||||||
// Temp = (V25 - Vsense)/Avg_Slope + 25
|
|
||||||
// V_25 = 1.45V, Slope = 4.3e-3
|
|
||||||
int32_t Vsense = getVdd() * getADCval(1);
|
|
||||||
int32_t temperature = 593920 - Vsense; // 593920 == 145*4096
|
|
||||||
temperature /= 172; // == /(4096*10*4.3e-3), 10 - to convert from *100 to *10
|
|
||||||
temperature += 250;
|
|
||||||
return(temperature);
|
|
||||||
}
|
|
||||||
|
|
||||||
// return Vdd * 100 (V)
|
|
||||||
uint32_t getVdd(){
|
|
||||||
uint32_t vdd = 120 * 4096; // 1.2V
|
|
||||||
vdd /= getADCval(2);
|
|
||||||
return vdd;
|
|
||||||
}
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the chronometer project.
|
|
||||||
* Copyright 2018 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#ifndef ADC_H
|
|
||||||
#define ADC_H
|
|
||||||
#include "stm32f1.h"
|
|
||||||
|
|
||||||
#define NUMBER_OF_ADC_CHANNELS (3)
|
|
||||||
|
|
||||||
extern uint16_t ADC_array[];
|
|
||||||
int32_t getMCUtemp();
|
|
||||||
uint32_t getVdd();
|
|
||||||
uint16_t getADCval(int nch);
|
|
||||||
|
|
||||||
#endif // ADC_H
|
|
||||||
Binary file not shown.
@ -1 +0,0 @@
|
|||||||
-std=c17
|
|
||||||
@ -1 +0,0 @@
|
|||||||
-std=c++17
|
|
||||||
@ -1,240 +0,0 @@
|
|||||||
/*
|
|
||||||
* geany_encoding=koi8-r
|
|
||||||
* flash.c
|
|
||||||
*
|
|
||||||
* Copyright 2017 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
ATTENTION!!
|
|
||||||
This things works only if you will add next section:
|
|
||||||
|
|
||||||
.myvars :
|
|
||||||
{
|
|
||||||
. = ALIGN(1024);
|
|
||||||
KEEP(*(.myvars))
|
|
||||||
} > rom
|
|
||||||
|
|
||||||
after section .data
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "stm32f1.h"
|
|
||||||
#include <string.h> // memcpy
|
|
||||||
|
|
||||||
#include "flash.h"
|
|
||||||
#include "lidar.h"
|
|
||||||
#ifdef EBUG
|
|
||||||
#include "usart.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern uint32_t _edata, _etext, _sdata;
|
|
||||||
static int maxnum = FLASH_BLOCK_SIZE / sizeof(user_conf);
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
const user_conf all_stored;
|
|
||||||
} flash_storage;
|
|
||||||
|
|
||||||
#define USERCONF_INITIALIZER { \
|
|
||||||
.userconf_sz = sizeof(user_conf) \
|
|
||||||
,.dist_min = LIDAR_MIN_DIST \
|
|
||||||
,.dist_max = LIDAR_MAX_DIST \
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((section(".myvars"))) static const flash_storage Flash_Storage = {
|
|
||||||
.all_stored = USERCONF_INITIALIZER
|
|
||||||
};
|
|
||||||
|
|
||||||
static const user_conf *Flash_Data = &Flash_Storage.all_stored;
|
|
||||||
|
|
||||||
user_conf the_conf = USERCONF_INITIALIZER;
|
|
||||||
|
|
||||||
static int erase_flash();
|
|
||||||
|
|
||||||
static int currentconfidx = -1; // index of current configuration
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief binarySearch - binary search in flash for last non-empty cell
|
|
||||||
* @param l - left index
|
|
||||||
* @param r - right index (should be @1 less than last index!)
|
|
||||||
* @return index of non-empty cell or -1
|
|
||||||
*/
|
|
||||||
static int binarySearch(int l, int r){
|
|
||||||
while(r >= l){
|
|
||||||
int mid = l + (r - l) / 2;
|
|
||||||
// If the element is present at the middle
|
|
||||||
// itself
|
|
||||||
uint16_t sz = Flash_Data[mid].userconf_sz;
|
|
||||||
if(sz == sizeof(user_conf)){
|
|
||||||
if(Flash_Data[mid+1].userconf_sz == 0xffff){
|
|
||||||
#if 0
|
|
||||||
SEND("Found at "); printu(1, mid); newline();
|
|
||||||
#endif
|
|
||||||
return mid;
|
|
||||||
}else{ // element is to the right
|
|
||||||
l = mid + 1;
|
|
||||||
#if 0
|
|
||||||
SEND("To the right, L="); printu(1, l); newline();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}else{ // element is to the left
|
|
||||||
r = mid - 1;
|
|
||||||
#if 0
|
|
||||||
SEND("To the left, R="); printu(1, r); newline();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DBG("Not found!");
|
|
||||||
return -1; // not found
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_gooddata(){
|
|
||||||
static uint8_t firstrun = 1;
|
|
||||||
if(firstrun){
|
|
||||||
firstrun = 0;
|
|
||||||
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
|
|
||||||
uint32_t flsz = FLASH_SIZE * 1024; // size in bytes
|
|
||||||
flsz -= (uint32_t)Flash_Data - FLASH_BASE;
|
|
||||||
#if 0
|
|
||||||
SEND("All size: "); printu(1, flsz); newline();
|
|
||||||
#endif
|
|
||||||
uint32_t usz = (sizeof(user_conf) + 1) / 2;
|
|
||||||
maxnum = flsz / 2 / usz;
|
|
||||||
#if 0
|
|
||||||
SEND("Maxnum: "); printu(1, maxnum); newline();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return binarySearch(0, maxnum-2); // -1 if there's no data at all & flash is clear; maxnum-1 if flash is full
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_userconf(){
|
|
||||||
const user_conf *c = Flash_Data;
|
|
||||||
int idx = get_gooddata();
|
|
||||||
if(idx < 0) return; // no data stored
|
|
||||||
currentconfidx = idx;
|
|
||||||
memcpy(&the_conf, &c[idx], sizeof(user_conf));
|
|
||||||
}
|
|
||||||
|
|
||||||
// store new configuration
|
|
||||||
// @return 0 if all OK
|
|
||||||
int store_userconf(){
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
|
||||||
int ret = 0;
|
|
||||||
const user_conf *c = Flash_Data;
|
|
||||||
int idx = currentconfidx;
|
|
||||||
// maxnum - 3 means that there always should be at least one empty record after last data
|
|
||||||
if(idx < 0 || idx > maxnum - 3){ // data corruption or there's no more place
|
|
||||||
idx = 0;
|
|
||||||
DBG("Need to erase flash!");
|
|
||||||
if(erase_flash()) return 1;
|
|
||||||
}else ++idx; // take next data position
|
|
||||||
currentconfidx = idx;
|
|
||||||
if (FLASH->CR & FLASH_CR_LOCK){ // unloch flash
|
|
||||||
FLASH->KEYR = FLASH_KEY1;
|
|
||||||
FLASH->KEYR = FLASH_KEY2;
|
|
||||||
}
|
|
||||||
while (FLASH->SR & FLASH_SR_BSY);
|
|
||||||
if(FLASH->SR & FLASH_SR_WRPRTERR) return 1; // write protection
|
|
||||||
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; // clear all flags
|
|
||||||
FLASH->CR |= FLASH_CR_PG;
|
|
||||||
uint16_t *data = (uint16_t*) &the_conf;
|
|
||||||
uint16_t *address = (uint16_t*) &c[idx];
|
|
||||||
uint32_t i, count = (sizeof(user_conf) + 1) / 2;
|
|
||||||
for (i = 0; i < count; ++i){
|
|
||||||
*(volatile uint16_t*)(address + i) = data[i];
|
|
||||||
while (FLASH->SR & FLASH_SR_BSY);
|
|
||||||
if(FLASH->SR & FLASH_SR_PGERR) ret = 1; // program error - meet not 0xffff
|
|
||||||
else while (!(FLASH->SR & FLASH_SR_EOP));
|
|
||||||
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR;
|
|
||||||
}
|
|
||||||
FLASH->CR &= ~(FLASH_CR_PG);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int erase_flash(){
|
|
||||||
int ret = 0;
|
|
||||||
uint32_t nblocks = 1;
|
|
||||||
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
|
|
||||||
uint32_t flsz = FLASH_SIZE * 1024; // size in bytes
|
|
||||||
flsz -= (uint32_t)Flash_Data - FLASH_BASE;
|
|
||||||
nblocks = flsz / FLASH_BLOCK_SIZE;
|
|
||||||
#if 0
|
|
||||||
SEND("N blocks:"); printu(1, nblocks); newline();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
for(uint32_t i = 0; i < nblocks; ++i){
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
|
||||||
/* (1) Wait till no operation is on going */
|
|
||||||
/* (2) Clear error & EOP bits */
|
|
||||||
/* (3) Check that the Flash is unlocked */
|
|
||||||
/* (4) Perform unlock sequence */
|
|
||||||
while ((FLASH->SR & FLASH_SR_BSY) != 0){} /* (1) */
|
|
||||||
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; /* (2) */
|
|
||||||
/* if (FLASH->SR & FLASH_SR_EOP){
|
|
||||||
FLASH->SR |= FLASH_SR_EOP;
|
|
||||||
}*/
|
|
||||||
if ((FLASH->CR & FLASH_CR_LOCK) != 0){ /* (3) */
|
|
||||||
FLASH->KEYR = FLASH_KEY1; /* (4) */
|
|
||||||
FLASH->KEYR = FLASH_KEY2;
|
|
||||||
}
|
|
||||||
/* (1) Set the PER bit in the FLASH_CR register to enable page erasing */
|
|
||||||
/* (2) Program the FLASH_AR register to select a page to erase */
|
|
||||||
/* (3) Set the STRT bit in the FLASH_CR register to start the erasing */
|
|
||||||
/* (4) Wait until the EOP flag in the FLASH_SR register set */
|
|
||||||
/* (5) Clear EOP flag by software by writing EOP at 1 */
|
|
||||||
/* (6) Reset the PER Bit to disable the page erase */
|
|
||||||
FLASH->CR |= FLASH_CR_PER; /* (1) */
|
|
||||||
#if 0
|
|
||||||
SEND("Delete block number "); printu(1, i); newline();
|
|
||||||
#endif
|
|
||||||
FLASH->AR = (uint32_t)Flash_Data + i*FLASH_BLOCK_SIZE; /* (2) */
|
|
||||||
FLASH->CR |= FLASH_CR_STRT; /* (3) */
|
|
||||||
while(!(FLASH->SR & FLASH_SR_EOP));
|
|
||||||
FLASH->SR |= FLASH_SR_EOP; /* (5)*/
|
|
||||||
if(FLASH->SR & FLASH_SR_WRPRTERR){ /* Check Write protection error */
|
|
||||||
ret = 1;
|
|
||||||
DBG("Write protection error!");
|
|
||||||
FLASH->SR |= FLASH_SR_WRPRTERR; /* Clear the flag by software by writing it at 1*/
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
FLASH->CR &= ~FLASH_CR_PER; /* (6) */
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#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();
|
|
||||||
}
|
|
||||||
|
|
||||||
void addNrecs(int N){
|
|
||||||
SEND("Try to store userconf for "); printu(1, N); SEND(" times\n");
|
|
||||||
for(int i = 0; i < N; ++i){
|
|
||||||
if(store_userconf()){
|
|
||||||
SEND("Error @ "); printu(1, i); newline();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SEND("Curr idx: "); printu(1, currentconfidx); newline();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* flash.h
|
|
||||||
*
|
|
||||||
* Copyright 2017 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef __FLASH_H__
|
|
||||||
#define __FLASH_H__
|
|
||||||
|
|
||||||
#include <stm32f1.h>
|
|
||||||
|
|
||||||
#define FLASH_BLOCK_SIZE (1024)
|
|
||||||
#define FLASH_SIZE_REG ((uint32_t)0x1FFFF7E0)
|
|
||||||
#define FLASH_SIZE *((uint16_t*)FLASH_SIZE_REG)
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
uint16_t userconf_sz; // "magick number"
|
|
||||||
uint32_t dist_min; // minimal distance for LIDAR
|
|
||||||
uint32_t dist_max; // maximal -//-
|
|
||||||
} user_conf;
|
|
||||||
|
|
||||||
extern user_conf the_conf;
|
|
||||||
|
|
||||||
void get_userconf();
|
|
||||||
int store_userconf();
|
|
||||||
#ifdef EBUG
|
|
||||||
void dump_userconf();
|
|
||||||
void addNrecs(int N);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // __FLASH_H__
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
/*
|
|
||||||
* geany_encoding=koi8-r
|
|
||||||
* hardware.c - hardware-dependent macros & functions
|
|
||||||
*
|
|
||||||
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "adc.h"
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "time.h"
|
|
||||||
#include "usart.h"
|
|
||||||
|
|
||||||
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);
|
|
||||||
// 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);
|
|
||||||
// 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->RTSR = EXTI_RTSR_TR1; // rising trigger
|
|
||||||
EXTI->FTSR = EXTI_FTSR_TR13 | EXTI_FTSR_TR14; // falling trigger
|
|
||||||
NVIC_EnableIRQ(EXTI15_10_IRQn);
|
|
||||||
NVIC_EnableIRQ(EXTI1_IRQn);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void adc_setup(){
|
|
||||||
GPIOB->CRL |= CRL(0, CNF_ANALOG|MODE_INPUT);
|
|
||||||
uint32_t ctr = 0;
|
|
||||||
// Enable clocking
|
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
|
|
||||||
RCC->CFGR &= ~(RCC_CFGR_ADCPRE);
|
|
||||||
RCC->CFGR |= RCC_CFGR_ADCPRE_DIV8; // ADC clock = RCC / 8
|
|
||||||
// sampling time - 239.5 cycles for channels 8, 16 and 17
|
|
||||||
ADC1->SMPR2 = ADC_SMPR2_SMP8;
|
|
||||||
ADC1->SMPR1 = ADC_SMPR1_SMP16 | ADC_SMPR1_SMP17;
|
|
||||||
// we have three conversions in group -> ADC1->SQR1[L] = 2, order: 8->16->17
|
|
||||||
ADC1->SQR3 = 8 | (16<<5) | (17<<10);
|
|
||||||
ADC1->SQR1 = ADC_SQR1_L_1;
|
|
||||||
ADC1->CR1 |= ADC_CR1_SCAN; // scan mode
|
|
||||||
// DMA configuration
|
|
||||||
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
|
|
||||||
DMA1_Channel1->CPAR = (uint32_t) (&(ADC1->DR));
|
|
||||||
DMA1_Channel1->CMAR = (uint32_t)(ADC_array);
|
|
||||||
DMA1_Channel1->CNDTR = NUMBER_OF_ADC_CHANNELS * 9;
|
|
||||||
DMA1_Channel1->CCR |= DMA_CCR_MINC | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0
|
|
||||||
| DMA_CCR_CIRC | DMA_CCR_PL | DMA_CCR_EN;
|
|
||||||
// continuous mode & DMA; enable vref & Tsens; wake up ADC
|
|
||||||
ADC1->CR2 |= ADC_CR2_DMA | ADC_CR2_TSVREFE | ADC_CR2_CONT | ADC_CR2_ADON;
|
|
||||||
// wait for Tstab - at least 1us
|
|
||||||
while(++ctr < 0xff) nop();
|
|
||||||
// calibration
|
|
||||||
ADC1->CR2 |= ADC_CR2_RSTCAL;
|
|
||||||
ctr = 0; while((ADC1->CR2 & ADC_CR2_RSTCAL) && ++ctr < 0xfffff);
|
|
||||||
ADC1->CR2 |= ADC_CR2_CAL;
|
|
||||||
ctr = 0; while((ADC1->CR2 & ADC_CR2_CAL) && ++ctr < 0xfffff);
|
|
||||||
// turn ON ADC
|
|
||||||
ADC1->CR2 |= ADC_CR2_ADON;
|
|
||||||
}
|
|
||||||
|
|
||||||
void hw_setup(){
|
|
||||||
gpio_setup();
|
|
||||||
//adc_setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void exti1_isr(){ // PPS - PA1
|
|
||||||
systick_correction();
|
|
||||||
DBG("exti1");
|
|
||||||
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], ¤t_time, sizeof(curtime));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
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], ¤t_time, sizeof(curtime));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
DBG("exti14");
|
|
||||||
EXTI->PR = EXTI_PR_PR14;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* geany_encoding=koi8-r
|
|
||||||
* hardware.h
|
|
||||||
*
|
|
||||||
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
#ifndef __HARDWARE_H__
|
|
||||||
#define __HARDWARE_H__
|
|
||||||
|
|
||||||
#include "stm32f1.h"
|
|
||||||
|
|
||||||
// onboard LEDs - PB8/PB9
|
|
||||||
#define LED0_port GPIOB
|
|
||||||
#define LED0_pin (1<<8)
|
|
||||||
#define LED1_port GPIOB
|
|
||||||
#define LED1_pin (1<<9)
|
|
||||||
|
|
||||||
// PPS pin - PA1
|
|
||||||
#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)
|
|
||||||
#define GET_PPS() ((GPIOA->IDR & (1<<1)) ? 1 : 0)
|
|
||||||
|
|
||||||
// USB pullup - PA15
|
|
||||||
#define USBPU_port GPIOA
|
|
||||||
#define USBPU_pin (1<<15)
|
|
||||||
#define USBPU_ON() pin_clear(USBPU_port, USBPU_pin)
|
|
||||||
#define USBPU_OFF() pin_set(USBPU_port, USBPU_pin)
|
|
||||||
|
|
||||||
#define LED_blink() pin_toggle(LED0_port, LED0_pin)
|
|
||||||
#define LED_on() pin_clear(LED0_port, LED0_pin)
|
|
||||||
#define LED_off() pin_set(LED0_port, LED0_pin)
|
|
||||||
#define LED1_blink() pin_toggle(LED1_port, LED1_pin)
|
|
||||||
#define LED1_on() pin_clear(LED1_port, LED1_pin)
|
|
||||||
#define LED1_off() pin_set(LED1_port, LED1_pin)
|
|
||||||
|
|
||||||
// GPS USART == USART2, LIDAR USART == USART3
|
|
||||||
#define GPS_USART (2)
|
|
||||||
#define LIDAR_USART (3)
|
|
||||||
|
|
||||||
void hw_setup();
|
|
||||||
|
|
||||||
#endif // __HARDWARE_H__
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the chronometer project.
|
|
||||||
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "flash.h"
|
|
||||||
#include "lidar.h"
|
|
||||||
#include "usart.h"
|
|
||||||
|
|
||||||
uint16_t last_lidar_dist = 0;
|
|
||||||
uint16_t last_lidar_stren = 0;
|
|
||||||
uint16_t lidar_triggered_dist = 0;
|
|
||||||
|
|
||||||
void parse_lidar_data(char *txt){
|
|
||||||
static int triggered = 0;
|
|
||||||
last_lidar_dist = txt[2] | (txt[3] << 8);
|
|
||||||
last_lidar_stren = txt[4] | (txt[5] << 8);
|
|
||||||
if(last_lidar_stren < LIDAR_LOWER_STREN) return; // weak signal
|
|
||||||
if(!lidar_triggered_dist){ // first run
|
|
||||||
lidar_triggered_dist = last_lidar_dist;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
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){
|
|
||||||
triggered = 0;
|
|
||||||
#ifdef EBUG
|
|
||||||
SEND("Untriggered! distance=");
|
|
||||||
printu(1, last_lidar_dist);
|
|
||||||
SEND(" signal=");
|
|
||||||
printu(1, last_lidar_stren);
|
|
||||||
newline();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
if(last_lidar_dist > the_conf.dist_min && last_lidar_dist < the_conf.dist_max){
|
|
||||||
triggered = 1;
|
|
||||||
lidar_triggered_dist = last_lidar_dist;
|
|
||||||
#ifdef EBUG
|
|
||||||
SEND("Triggered! distance=");
|
|
||||||
printu(1, last_lidar_dist);
|
|
||||||
SEND(" signal=");
|
|
||||||
printu(1, last_lidar_stren);
|
|
||||||
newline();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the chronometer project.
|
|
||||||
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
#ifndef LIDAR_H__
|
|
||||||
#define LIDAR_H__
|
|
||||||
#include <stm32f1.h>
|
|
||||||
|
|
||||||
#define LIDAR_FRAME_LEN (9)
|
|
||||||
// frame header
|
|
||||||
#define LIDAR_FRAME_HEADER (0x59)
|
|
||||||
// lower strength limit
|
|
||||||
#define LIDAR_LOWER_STREN (10)
|
|
||||||
// triggered distance threshold - 1 meter
|
|
||||||
#define LIDAR_DIST_THRES (100)
|
|
||||||
#define LIDAR_MIN_DIST (50)
|
|
||||||
#define LIDAR_MAX_DIST (1000)
|
|
||||||
|
|
||||||
extern uint16_t last_lidar_dist;
|
|
||||||
extern uint16_t lidar_triggered_dist;
|
|
||||||
extern uint16_t last_lidar_stren;
|
|
||||||
|
|
||||||
void parse_lidar_data(char *txt);
|
|
||||||
|
|
||||||
#endif // LIDAR_H__
|
|
||||||
@ -1,272 +0,0 @@
|
|||||||
/*
|
|
||||||
* main.c
|
|
||||||
*
|
|
||||||
* Copyright 2017 Edward V. Emelianoff <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//#include "adc.h"
|
|
||||||
#include "GPS.h"
|
|
||||||
#include "flash.h"
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "lidar.h"
|
|
||||||
#include "str.h"
|
|
||||||
#include "time.h"
|
|
||||||
#include "usart.h"
|
|
||||||
#include "usb.h"
|
|
||||||
#include "usb_lib.h"
|
|
||||||
|
|
||||||
#ifndef VERSION
|
|
||||||
#define VERSION "0.0.0"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// global pseudo-milliseconds counter
|
|
||||||
volatile uint32_t Tms = 0;
|
|
||||||
|
|
||||||
/* Called when systick fires */
|
|
||||||
void sys_tick_handler(void){
|
|
||||||
++Tms; // increment pseudo-milliseconds counter
|
|
||||||
if(++Timer == 1000){ // increment milliseconds counter
|
|
||||||
time_increment();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void iwdg_setup(){
|
|
||||||
uint32_t tmout = 16000000;
|
|
||||||
/* Enable the peripheral clock RTC */
|
|
||||||
/* (1) Enable the LSI (40kHz) */
|
|
||||||
/* (2) Wait while it is not ready */
|
|
||||||
RCC->CSR |= RCC_CSR_LSION; /* (1) */
|
|
||||||
while((RCC->CSR & RCC_CSR_LSIRDY) != RCC_CSR_LSIRDY){if(--tmout == 0) break;} /* (2) */
|
|
||||||
/* Configure IWDG */
|
|
||||||
/* (1) Activate IWDG (not needed if done in option bytes) */
|
|
||||||
/* (2) Enable write access to IWDG registers */
|
|
||||||
/* (3) Set prescaler by 64 (1.6ms for each tick) */
|
|
||||||
/* (4) Set reload value to have a rollover each 2s */
|
|
||||||
/* (5) Check if flags are reset */
|
|
||||||
/* (6) Refresh counter */
|
|
||||||
IWDG->KR = IWDG_START; /* (1) */
|
|
||||||
IWDG->KR = IWDG_WRITE_ACCESS; /* (2) */
|
|
||||||
IWDG->PR = IWDG_PR_PR_1; /* (3) */
|
|
||||||
IWDG->RLR = 1250; /* (4) */
|
|
||||||
tmout = 16000000;
|
|
||||||
while(IWDG->SR){if(--tmout == 0) break;} /* (5) */
|
|
||||||
IWDG->KR = IWDG_REFRESH; /* (6) */
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef EBUG
|
|
||||||
char *parse_cmd(char *buf){
|
|
||||||
int32_t N;
|
|
||||||
static char btns[] = "BTN0=0, BTN1=0, PPS=0\n";
|
|
||||||
switch(*buf){
|
|
||||||
case '0':
|
|
||||||
LED_off();
|
|
||||||
break;
|
|
||||||
case '1':
|
|
||||||
LED_on();
|
|
||||||
break;
|
|
||||||
case 'b':
|
|
||||||
btns[5] = GET_BTN0() + '0';
|
|
||||||
btns[13] = GET_BTN1() + '0';
|
|
||||||
btns[20] = GET_PPS() + '0';
|
|
||||||
return btns;
|
|
||||||
break;
|
|
||||||
case 'C':
|
|
||||||
if(getnum(&buf[1], &N)){
|
|
||||||
SEND("Need a number!\n");
|
|
||||||
}else{
|
|
||||||
addNrecs(N);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
dump_userconf();
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
pin_toggle(USBPU_port, USBPU_pin);
|
|
||||||
SEND("USB pullup is ");
|
|
||||||
if(pin_read(USBPU_port, USBPU_pin)) SEND("off");
|
|
||||||
else SEND("on");
|
|
||||||
newline();
|
|
||||||
break;
|
|
||||||
case 'G':
|
|
||||||
SEND("LIDAR_DIST=");
|
|
||||||
printu(1, last_lidar_dist);
|
|
||||||
SEND(", LIDAR_STREN=");
|
|
||||||
printu(1, last_lidar_stren);
|
|
||||||
newline();
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
USB_send("Very long test string for USB (it's length is more than 64 bytes).\n"
|
|
||||||
"This is another part of the string! Can you see all of this?\n");
|
|
||||||
return "Long test sent\n";
|
|
||||||
break;
|
|
||||||
case 'R':
|
|
||||||
USB_send("Soft reset\n");
|
|
||||||
SEND("Soft reset\n");
|
|
||||||
NVIC_SystemReset();
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
USB_send("Test string for USB\n");
|
|
||||||
return "Short test sent\n";
|
|
||||||
break;
|
|
||||||
case 'T':
|
|
||||||
SEND(get_time(¤t_time, get_millis()));
|
|
||||||
break;
|
|
||||||
case 'W':
|
|
||||||
USB_send("Wait for reboot\n");
|
|
||||||
SEND("Wait for reboot\n");
|
|
||||||
while(1){nop();};
|
|
||||||
break;
|
|
||||||
default: // help
|
|
||||||
if(buf[1] != '\n') return buf;
|
|
||||||
return
|
|
||||||
"0/1 - turn on/off LED1\n"
|
|
||||||
"'b' - get buttons's state\n"
|
|
||||||
"'d' - dump current user conf\n"
|
|
||||||
"'p' - toggle USB pullup\n"
|
|
||||||
"'C' - store userconf for N times\n"
|
|
||||||
"'G' - get last LIDAR distance\n"
|
|
||||||
"'L' - send long string over USB\n"
|
|
||||||
"'R' - software reset\n"
|
|
||||||
"'S' - send short string over USB\n"
|
|
||||||
"'T' - show current GPS time\n"
|
|
||||||
"'W' - test watchdog\n"
|
|
||||||
;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// usb getline
|
|
||||||
static char *get_USB(){
|
|
||||||
static char tmpbuf[512], *curptr = tmpbuf;
|
|
||||||
static int rest = 511;
|
|
||||||
int x = USB_receive(curptr, rest);
|
|
||||||
curptr[x] = 0;
|
|
||||||
if(!x) return NULL;
|
|
||||||
if(curptr[x-1] == '\n'){
|
|
||||||
curptr = tmpbuf;
|
|
||||||
rest = 511;
|
|
||||||
return tmpbuf;
|
|
||||||
}
|
|
||||||
curptr += x; rest -= x;
|
|
||||||
if(rest <= 0){ // buffer overflow
|
|
||||||
SEND("USB buffer overflow!\n");
|
|
||||||
curptr = tmpbuf;
|
|
||||||
rest = 511;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
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!
|
|
||||||
SEND("Chronometer version " VERSION ".\n");
|
|
||||||
if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured
|
|
||||||
SEND("WDGRESET=1\n");
|
|
||||||
}
|
|
||||||
if(RCC->CSR & RCC_CSR_SFTRSTF){ // software reset occured
|
|
||||||
SEND("SOFTRESET=1\n");
|
|
||||||
}
|
|
||||||
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
|
|
||||||
|
|
||||||
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
|
|
||||||
if(lastT > Tms || Tms - lastT > 499){
|
|
||||||
if(need2startseq) GPS_send_start_seq();
|
|
||||||
LED_blink();
|
|
||||||
if(GPS_status != GPS_VALID) LED1_blink();
|
|
||||||
else LED1_on();
|
|
||||||
lastT = Tms;
|
|
||||||
if(usartrx(LIDAR_USART)){
|
|
||||||
char *txt;
|
|
||||||
if(usart_getline(LIDAR_USART, &txt)){
|
|
||||||
DBG("LIDAR:");
|
|
||||||
DBG(txt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if defined EBUG || defined USART1PROXY
|
|
||||||
transmit_tbuf(1); // non-blocking transmission of data from UART buffer every 0.5s
|
|
||||||
#endif
|
|
||||||
transmit_tbuf(GPS_USART);
|
|
||||||
transmit_tbuf(LIDAR_USART);
|
|
||||||
}
|
|
||||||
usb_proc();
|
|
||||||
int r = 0;
|
|
||||||
char *txt;
|
|
||||||
if((txt = get_USB())){
|
|
||||||
DBG("Received data over USB:");
|
|
||||||
DBG(txt);
|
|
||||||
if(parse_USBCMD(txt))
|
|
||||||
USB_send(txt); // echo back non-commands data
|
|
||||||
}
|
|
||||||
#if defined EBUG || defined USART1PROXY
|
|
||||||
if(usartrx(1)){ // usart1 received data, store in in buffer
|
|
||||||
r = usart_getline(1, &txt);
|
|
||||||
if(r){
|
|
||||||
txt[r] = 0;
|
|
||||||
#ifdef EBUG
|
|
||||||
char *ans = parse_cmd(txt);
|
|
||||||
if(ans){
|
|
||||||
transmit_tbuf(1);
|
|
||||||
usart_send(1, ans);
|
|
||||||
transmit_tbuf(1);
|
|
||||||
}
|
|
||||||
#else // USART1PROXY - send received data to GPS
|
|
||||||
usart_send(GPS_USART, txt);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(usartrx(GPS_USART)){
|
|
||||||
r = usart_getline(GPS_USART, &txt);
|
|
||||||
if(r){
|
|
||||||
txt[r] = 0;
|
|
||||||
GPS_parse_answer(txt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(usartrx(LIDAR_USART)){
|
|
||||||
r = usart_getline(LIDAR_USART, &txt);
|
|
||||||
if(r){
|
|
||||||
parse_lidar_data(txt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the chronometer project.
|
|
||||||
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "flash.h"
|
|
||||||
#include "str.h"
|
|
||||||
#include "time.h"
|
|
||||||
#include "usart.h"
|
|
||||||
#include "usb.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief cmpstr - the same as strncmp
|
|
||||||
* @param s1,s2 - strings to compare
|
|
||||||
* @param n - max symbols amount
|
|
||||||
* @return 0 if strings equal or 1/-1
|
|
||||||
*/
|
|
||||||
int cmpstr(const char *s1, const char *s2, int n){
|
|
||||||
int ret = 0;
|
|
||||||
while(--n){
|
|
||||||
ret = *s1 - *s2;
|
|
||||||
if(ret == 0 && *s1 && *s2){
|
|
||||||
++s1; ++s2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief getchr - analog of strchr
|
|
||||||
* @param str - string to search
|
|
||||||
* @param symbol - searching symbol
|
|
||||||
* @return pointer to symbol found or NULL
|
|
||||||
*/
|
|
||||||
char *getchr(const char *str, char symbol){
|
|
||||||
do{
|
|
||||||
if(*str == symbol) return (char*)str;
|
|
||||||
}while(*(++str));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief parse_USBCMD - parsing of string buffer got by USB
|
|
||||||
* @param cmd - buffer with commands
|
|
||||||
* @return 0 if got command, 1 if command not recognized
|
|
||||||
*/
|
|
||||||
int parse_USBCMD(char *cmd){
|
|
||||||
#define CMP(a,b) cmpstr(a, b, sizeof(b)-1)
|
|
||||||
#define GETNUM(x) if(getnum(cmd+sizeof(x)-1, &N)) goto bad_number;
|
|
||||||
static uint8_t conf_modified = 0;
|
|
||||||
uint8_t succeed = 0;
|
|
||||||
int32_t N;
|
|
||||||
if(!cmd || !*cmd) return 0;
|
|
||||||
if(*cmd == '?'){ // help
|
|
||||||
USB_send("Commands:\n"
|
|
||||||
CMD_DISTMIN " - min distance threshold (cm)\n"
|
|
||||||
CMD_DISTMAX " - max distance threshold (cm)\n"
|
|
||||||
CMD_PRINTTIME " - print time\n"
|
|
||||||
CMD_STORECONF " - store new configuration in flash\n"
|
|
||||||
);
|
|
||||||
}else if(CMP(cmd, CMD_PRINTTIME) == 0){
|
|
||||||
USB_send(get_time(¤t_time, get_millis()));
|
|
||||||
}else if(CMP(cmd, CMD_DISTMIN) == 0){ // set low limit
|
|
||||||
DBG("CMD_DISTMIN");
|
|
||||||
GETNUM(CMD_DISTMIN);
|
|
||||||
if(N < 0 || N > 0xffff) goto bad_number;
|
|
||||||
if(the_conf.dist_min != (uint16_t)N){
|
|
||||||
conf_modified = 1;
|
|
||||||
the_conf.dist_min = (uint16_t) N;
|
|
||||||
succeed = 1;
|
|
||||||
}
|
|
||||||
}else if(CMP(cmd, CMD_DISTMAX) == 0){ // set low limit
|
|
||||||
DBG("CMD_DISTMAX");
|
|
||||||
GETNUM(CMD_DISTMAX);
|
|
||||||
if(N < 0 || N > 0xffff) goto bad_number;
|
|
||||||
if(the_conf.dist_max != (uint16_t)N){
|
|
||||||
conf_modified = 1;
|
|
||||||
the_conf.dist_max = (uint16_t) N;
|
|
||||||
succeed = 1;
|
|
||||||
}
|
|
||||||
}else if(CMP(cmd, CMD_STORECONF) == 0){ // store everything
|
|
||||||
DBG("Store");
|
|
||||||
if(conf_modified){
|
|
||||||
if(store_userconf()){
|
|
||||||
USB_send("Error: can't save data!\n");
|
|
||||||
}else{
|
|
||||||
conf_modified = 0;
|
|
||||||
succeed = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else return 1;
|
|
||||||
if(succeed) USB_send("Success!\n");
|
|
||||||
return 0;
|
|
||||||
bad_number:
|
|
||||||
USB_send("Error: bad number!\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the chronometer project.
|
|
||||||
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
#ifndef STR_H__
|
|
||||||
#define STR_H__
|
|
||||||
|
|
||||||
// usb commands
|
|
||||||
// lower and upper limits to capture
|
|
||||||
#define CMD_DISTMIN "distmin"
|
|
||||||
#define CMD_DISTMAX "distmax"
|
|
||||||
#define CMD_ADC1MIN "adc1min"
|
|
||||||
#define CMD_ADC2MIN "adc2min"
|
|
||||||
#define CMD_ADC1MAX "adc1max"
|
|
||||||
#define CMD_ADC2MAX "adc2max"
|
|
||||||
#define CMD_PRINTTIME "time"
|
|
||||||
#define CMD_STORECONF "store"
|
|
||||||
|
|
||||||
int cmpstr(const char *s1, const char *s2, int n);
|
|
||||||
char *getchr(const char *str, char symbol);
|
|
||||||
int parse_USBCMD(char *cmd);
|
|
||||||
#endif // STR_H__
|
|
||||||
@ -1,189 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the chronometer project.
|
|
||||||
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "GPS.h"
|
|
||||||
#include "time.h"
|
|
||||||
#ifdef EBUG
|
|
||||||
#include "usart.h"
|
|
||||||
#endif
|
|
||||||
#include "usb.h"
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
volatile uint32_t Timer; // milliseconds counter
|
|
||||||
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){
|
|
||||||
return (b[0]-'0')*10 + b[1]-'0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief set_time - set current time from GPS data
|
|
||||||
* @param buf - buffer with time data (HHMMSS)
|
|
||||||
*/
|
|
||||||
void set_time(const char *buf){
|
|
||||||
uint8_t H = atou(buf) + TIMEZONE_GMT_PLUS;
|
|
||||||
if(H > 23) H -= 24;
|
|
||||||
current_time.H = H;
|
|
||||||
current_time.M = atou(&buf[2]);
|
|
||||||
current_time.S = atou(&buf[4]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief time_increment - increment system timer by systick
|
|
||||||
*/
|
|
||||||
void time_increment(){
|
|
||||||
Timer = 0;
|
|
||||||
if(current_time.H == 25) return; // Time not initialized
|
|
||||||
if(++current_time.S == 60){
|
|
||||||
current_time.S = 0;
|
|
||||||
if(++current_time.M == 60){
|
|
||||||
current_time.M = 0;
|
|
||||||
if(++current_time.H == 24)
|
|
||||||
current_time.H = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef EBUG
|
|
||||||
SEND("time_increment(): ");
|
|
||||||
SEND(get_time(¤t_time, 0));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* print time: Tm - time structure, T - milliseconds
|
|
||||||
*/
|
|
||||||
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(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';
|
|
||||||
while(S){
|
|
||||||
*(--bstart) = S%10 + '0';
|
|
||||||
S /= 10;
|
|
||||||
}
|
|
||||||
// now bstart is buffer starting index; bptr points to decimal point
|
|
||||||
*bptr++ = '.';
|
|
||||||
if(T > 99){
|
|
||||||
*bptr++ = T/100 + '0';
|
|
||||||
T %= 100;
|
|
||||||
}else *bptr++ = '0';
|
|
||||||
if(T > 9){
|
|
||||||
*bptr++ = T/10 + '0';
|
|
||||||
T %= 10;
|
|
||||||
}else *bptr++ = '0';
|
|
||||||
*bptr++ = T + '0';
|
|
||||||
if(GPS_status == GPS_NOT_VALID){
|
|
||||||
strcpy(bptr, " (not valid)");
|
|
||||||
bptr += 12;
|
|
||||||
}
|
|
||||||
if(Tms - last_corr_time > 1000){
|
|
||||||
strcpy(bptr, " need PPS sync");
|
|
||||||
bptr += 14;
|
|
||||||
}
|
|
||||||
*bptr++ = '\n';
|
|
||||||
*bptr = 0;
|
|
||||||
return bstart;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief systick_correction
|
|
||||||
* Makes correction of system timer
|
|
||||||
* The default frequency of timer is 1kHz - 72000 clocks per interrupt
|
|
||||||
* So we check how much ticks there was for last one second - between PPS interrupts
|
|
||||||
* Their amount equal to M = `Timer` value x (SysTick->LOAD+1) + (SysTick->LOAD+1 - SysTick->VAL)
|
|
||||||
* if `Timer` is very small, add 1000 to its value.
|
|
||||||
* We need 1000xN ticks instead of M
|
|
||||||
* if L = LOAD+1, then
|
|
||||||
* M = Timer*L + L - VAL; newL = L + D = M/1000
|
|
||||||
* 1000*D = M - 1000*L = L(Timer+1-1000) - VAL ->
|
|
||||||
* D = [L*(Timer-999) - VAL]/1000
|
|
||||||
* So correction equal to
|
|
||||||
* [ (SysTick->LOAD + 1) * (Timer - 999) - SysTick->VAL ] / 1000
|
|
||||||
*/
|
|
||||||
void systick_correction(){
|
|
||||||
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // stop systick for a while
|
|
||||||
int32_t systick_val = SysTick->VAL, L = SysTick->LOAD + 1, timer_val = Timer;
|
|
||||||
SysTick->VAL = SysTick->LOAD;
|
|
||||||
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // start it again
|
|
||||||
Timer = 0;
|
|
||||||
if(Tms - last_corr_time < 2000){ // calculate corrections only if Timer was zeroed last time
|
|
||||||
if(timer_val < 500) timer_val += 1000; // timer already incremented in SysTick interrupt
|
|
||||||
else time_increment(); // counter less than 1000 -> need to increment time
|
|
||||||
int32_t D = L * (timer_val - 999) - systick_val;
|
|
||||||
D /= 1000;
|
|
||||||
#ifdef EBUG
|
|
||||||
SEND("Delta: "); if(D < 0){usart_putchar(1, '-'); printu(1, -D);} else printu(1, D); newline();
|
|
||||||
SEND(get_time(¤t_time, 0));
|
|
||||||
#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{
|
|
||||||
N = 0;
|
|
||||||
ticksavr = 0;
|
|
||||||
}
|
|
||||||
theend:
|
|
||||||
last_corr_time = t;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the chronometer project.
|
|
||||||
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
#ifndef TIME_H__
|
|
||||||
#define TIME_H__
|
|
||||||
|
|
||||||
#include <stm32f1.h>
|
|
||||||
|
|
||||||
// default value for systick_config
|
|
||||||
#define SYSTICK_DEFCONF (72000)
|
|
||||||
// defaul for systick->load
|
|
||||||
#define SYSTICK_DEFLOAD (SYSTICK_DEFCONF - 1)
|
|
||||||
#define TIMEZONE_GMT_PLUS (3)
|
|
||||||
|
|
||||||
#define DIDNT_TRIGGERED (2000)
|
|
||||||
|
|
||||||
// debounce delay: .4s
|
|
||||||
#define TRIGGER_DELAY (400)
|
|
||||||
|
|
||||||
#define TMNOTINI {25,61,61}
|
|
||||||
|
|
||||||
// current milliseconds
|
|
||||||
#define get_millis() (Timer)
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
uint8_t H;
|
|
||||||
uint8_t M;
|
|
||||||
uint8_t S;
|
|
||||||
} curtime;
|
|
||||||
|
|
||||||
extern volatile uint32_t Tms;
|
|
||||||
extern volatile uint32_t Timer;
|
|
||||||
extern curtime current_time;
|
|
||||||
|
|
||||||
extern curtime trigger_time[];
|
|
||||||
extern uint32_t trigger_ms[];
|
|
||||||
|
|
||||||
extern volatile int need_sync;
|
|
||||||
|
|
||||||
char *get_time(curtime *T, uint32_t m);
|
|
||||||
void set_time(const char *buf);
|
|
||||||
void time_increment();
|
|
||||||
void systick_correction();
|
|
||||||
|
|
||||||
#endif // TIME_H__
|
|
||||||
@ -1,365 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the chronometer project.
|
|
||||||
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "stm32f1.h"
|
|
||||||
#include "usart.h"
|
|
||||||
#include "lidar.h"
|
|
||||||
|
|
||||||
extern volatile uint32_t Tms;
|
|
||||||
static volatile int idatalen[4][2] = {0}; // received data line length (including '\n')
|
|
||||||
static volatile int odatalen[4][2] = {0};
|
|
||||||
|
|
||||||
volatile int linerdy[4] = {0}, // received data ready
|
|
||||||
dlen[4] = {0}, // length of data (including '\n') in current buffer
|
|
||||||
bufovr[4] = {0}, // input buffer overfull
|
|
||||||
txrdy[4] = {0,1,1,1} // transmission done
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
int rbufno[4] = {0}, tbufno[4] = {0}; // current rbuf/tbuf numbers
|
|
||||||
static char rbuf[4][2][UARTBUFSZ], tbuf[4][2][UARTBUFSZ]; // receive & transmit buffers
|
|
||||||
static char *recvdata[4] = {0};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* return length of received data (without trailing zero)
|
|
||||||
*/
|
|
||||||
int usart_getline(int n, char **line){
|
|
||||||
if(bufovr[n]){
|
|
||||||
bufovr[n] = 0;
|
|
||||||
linerdy[n] = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*line = recvdata[n];
|
|
||||||
linerdy[n] = 0;
|
|
||||||
return dlen[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
// transmit current tbuf and swap buffers
|
|
||||||
void transmit_tbuf(int n){
|
|
||||||
if(n < 1 || n > 3) return;
|
|
||||||
uint32_t tmout = 72000;
|
|
||||||
while(!txrdy[n]){if(--tmout == 0) return;}; // wait for previos buffer transmission
|
|
||||||
register int l = odatalen[n][tbufno[n]];
|
|
||||||
if(!l) return;
|
|
||||||
txrdy[n] = 0;
|
|
||||||
odatalen[n][tbufno[n]] = 0;
|
|
||||||
DMA_Channel_TypeDef *DMA;
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
|
||||||
switch(n){
|
|
||||||
case 1:
|
|
||||||
DMA = DMA1_Channel4;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
DMA = DMA1_Channel7;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
DMA = DMA1_Channel2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
DMA->CCR &= ~DMA_CCR_EN;
|
|
||||||
DMA->CMAR = (uint32_t) tbuf[n][tbufno[n]]; // mem
|
|
||||||
DMA->CNDTR = l;
|
|
||||||
DMA->CCR |= DMA_CCR_EN;
|
|
||||||
tbufno[n] = !tbufno[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
void usart_putchar(int n, char ch){
|
|
||||||
for(int i = 0; odatalen[n][tbufno[n]] == UARTBUFSZ && i < 1024; ++i) transmit_tbuf(n);
|
|
||||||
tbuf[n][tbufno[n]][odatalen[n][tbufno[n]]++] = ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
void usart_send(int n, const char *str){
|
|
||||||
uint32_t x = 512;
|
|
||||||
while(*str && --x){
|
|
||||||
if(odatalen[n][tbufno[n]] == UARTBUFSZ){
|
|
||||||
transmit_tbuf(n);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
tbuf[n][tbufno[n]][odatalen[n][tbufno[n]]++] = *str++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if defined EBUG || defined USART1PROXY
|
|
||||||
// only for USART1
|
|
||||||
void newline(){
|
|
||||||
usart_putchar(1, '\n');
|
|
||||||
transmit_tbuf(1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* USART speed: baudrate = Fck/(USARTDIV)
|
|
||||||
* USARTDIV stored in USART->BRR
|
|
||||||
*
|
|
||||||
* for 72MHz USARTDIV=72000/f(kboud); so for 115200 USARTDIV=72000/115.2=625 -> BRR=0x271
|
|
||||||
* 9600: BRR = 7500 (0x1D4C)
|
|
||||||
*/
|
|
||||||
static void usart_setup(int n, uint32_t BRR){
|
|
||||||
DMA_Channel_TypeDef *DMA;
|
|
||||||
IRQn_Type DMAirqN, USARTirqN;
|
|
||||||
USART_TypeDef *USART;
|
|
||||||
switch(n){
|
|
||||||
case 1:
|
|
||||||
// USART1 Tx DMA - Channel4 (Rx - channel 5)
|
|
||||||
DMA = DMA1_Channel4;
|
|
||||||
DMAirqN = DMA1_Channel4_IRQn;
|
|
||||||
USARTirqN = USART1_IRQn;
|
|
||||||
// PA9 - Tx, PA10 - Rx
|
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN;
|
|
||||||
GPIOA->CRH |= CRH(9, CNF_AFPP|MODE_NORMAL) | CRH(10, CNF_FLINPUT|MODE_INPUT);
|
|
||||||
USART = USART1;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
// USART2 Tx DMA - Channel7
|
|
||||||
DMA = DMA1_Channel7;
|
|
||||||
DMAirqN = DMA1_Channel7_IRQn;
|
|
||||||
USARTirqN = USART2_IRQn;
|
|
||||||
// PA2 - Tx, PA3 - Rx
|
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
|
|
||||||
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
|
|
||||||
GPIOA->CRL |= CRL(2, CNF_AFPP|MODE_NORMAL) | CRL(3, CNF_FLINPUT|MODE_INPUT);
|
|
||||||
USART = USART2;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
// USART3 Tx DMA - Channel2
|
|
||||||
DMA = DMA1_Channel2;
|
|
||||||
DMAirqN = DMA1_Channel2_IRQn;
|
|
||||||
USARTirqN = USART3_IRQn;
|
|
||||||
// PB10 - Tx, PB11 - Rx
|
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
|
|
||||||
RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
|
|
||||||
GPIOB->CRH |= CRH(10, CNF_AFPP|MODE_NORMAL) | CRH(11, CNF_FLINPUT|MODE_INPUT);
|
|
||||||
USART = USART3;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DMA->CPAR = (uint32_t) &USART->DR; // periph
|
|
||||||
DMA->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq
|
|
||||||
// setup usart(n)
|
|
||||||
USART->BRR = BRR;
|
|
||||||
USART->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART
|
|
||||||
uint32_t tmout = 16000000;
|
|
||||||
while(!(USART->SR & USART_SR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission
|
|
||||||
USART->SR = 0; // clear flags
|
|
||||||
USART->CR1 |= USART_CR1_RXNEIE; // allow Rx IRQ
|
|
||||||
USART->CR3 = USART_CR3_DMAT; // enable DMA Tx
|
|
||||||
// Tx CNDTR set @ each transmission due to data size
|
|
||||||
NVIC_SetPriority(DMAirqN, n);
|
|
||||||
NVIC_EnableIRQ(DMAirqN);
|
|
||||||
NVIC_SetPriority(USARTirqN, n);
|
|
||||||
NVIC_EnableIRQ(USARTirqN);
|
|
||||||
}
|
|
||||||
|
|
||||||
void usarts_setup(){
|
|
||||||
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
|
|
||||||
#if defined EBUG || defined USART1PROXY
|
|
||||||
usart_setup(1, 72000000 / 115200); // debug console or GPS proxy
|
|
||||||
#endif
|
|
||||||
usart_setup(2, 36000000 / 9600); // GPS
|
|
||||||
usart_setup(3, 36000000 / 115200); // LIDAR
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void usart_isr(int n, USART_TypeDef *USART){
|
|
||||||
#ifdef CHECK_TMOUT
|
|
||||||
static uint32_t tmout[n] = 0;
|
|
||||||
#endif
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
|
||||||
if(USART->SR & USART_SR_RXNE){ // RX not emty - receive next char
|
|
||||||
#ifdef CHECK_TMOUT
|
|
||||||
if(tmout[n] && Tms >= tmout[n]){ // set overflow flag
|
|
||||||
bufovr[n] = 1;
|
|
||||||
idatalen[n][rbufno[n]] = 0;
|
|
||||||
}
|
|
||||||
tmout[n] = Tms + TIMEOUT_MS;
|
|
||||||
if(!tmout[n]) tmout[n] = 1; // prevent 0
|
|
||||||
#endif
|
|
||||||
uint8_t rb = USART->DR;
|
|
||||||
if(idatalen[n][rbufno[n]] < UARTBUFSZ){ // put next char into buf
|
|
||||||
rbuf[n][rbufno[n]][idatalen[n][rbufno[n]]++] = rb;
|
|
||||||
if(rb == '\n'){ // got newline - line ready
|
|
||||||
linerdy[n] = 1;
|
|
||||||
dlen[n] = idatalen[n][rbufno[n]];
|
|
||||||
recvdata[n] = rbuf[n][rbufno[n]];
|
|
||||||
// prepare other buffer
|
|
||||||
rbufno[n] = !rbufno[n];
|
|
||||||
idatalen[n][rbufno[n]] = 0;
|
|
||||||
#ifdef CHECK_TMOUT
|
|
||||||
// clear timeout at line end
|
|
||||||
tmout[n] = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}else{ // buffer overrun
|
|
||||||
bufovr[n] = 1;
|
|
||||||
idatalen[n][rbufno[n]] = 0;
|
|
||||||
#ifdef CHECK_TMOUT
|
|
||||||
tmout[n] = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined EBUG || defined USART1PROXY
|
|
||||||
void usart1_isr(){
|
|
||||||
usart_isr(1, USART1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// GPS_USART
|
|
||||||
void usart2_isr(){
|
|
||||||
usart_isr(2, USART2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// LIDAR_USART
|
|
||||||
void usart3_isr(){
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
|
||||||
if(USART3->SR & USART_SR_RXNE){ // RX not emty - receive next char
|
|
||||||
uint8_t rb = USART3->DR, L = idatalen[3][rbufno[3]];
|
|
||||||
if(rb != LIDAR_FRAME_HEADER && (L == 0 || L == 1)){ // bad starting sequence
|
|
||||||
idatalen[3][rbufno[3]] = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(L < LIDAR_FRAME_LEN){ // put next char into buf
|
|
||||||
rbuf[3][rbufno[3]][idatalen[3][rbufno[3]]++] = rb;
|
|
||||||
if(L == LIDAR_FRAME_LEN-1){ // got LIDAR_FRAME_LEN bytes - line ready
|
|
||||||
linerdy[3] = 1;
|
|
||||||
dlen[3] = idatalen[3][rbufno[3]];
|
|
||||||
recvdata[3] = rbuf[3][rbufno[3]];
|
|
||||||
// prepare other buffer
|
|
||||||
rbufno[3] = !rbufno[3];
|
|
||||||
idatalen[3][rbufno[3]] = 0;
|
|
||||||
}
|
|
||||||
}else{ // buffer overrun
|
|
||||||
idatalen[3][rbufno[3]] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// return string buffer with val
|
|
||||||
char *u2str(uint32_t val){
|
|
||||||
static char bufa[11];
|
|
||||||
char bufb[10];
|
|
||||||
int l = 0, bpos = 0;
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
|
||||||
if(!val){
|
|
||||||
bufa[0] = '0';
|
|
||||||
l = 1;
|
|
||||||
}else{
|
|
||||||
while(val){
|
|
||||||
bufb[l++] = val % 10 + '0';
|
|
||||||
val /= 10;
|
|
||||||
}
|
|
||||||
int i;
|
|
||||||
bpos += l;
|
|
||||||
for(i = 0; i < l; ++i){
|
|
||||||
bufa[--bpos] = bufb[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bufa[l + bpos] = 0;
|
|
||||||
return bufa;
|
|
||||||
}
|
|
||||||
// print 32bit unsigned int
|
|
||||||
void printu(int n, uint32_t val){
|
|
||||||
usart_send(n, u2str(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
// print 32bit unsigned int as hex
|
|
||||||
void printuhex(int n, uint32_t val){
|
|
||||||
usart_send(n, "0x");
|
|
||||||
uint8_t *ptr = (uint8_t*)&val + 3;
|
|
||||||
int i, j;
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
|
||||||
for(i = 0; i < 4; ++i, --ptr){
|
|
||||||
for(j = 1; j > -1; --j){
|
|
||||||
register uint8_t half = (*ptr >> (4*j)) & 0x0f;
|
|
||||||
if(half < 10) usart_putchar(n, half + '0');
|
|
||||||
else usart_putchar(n, half - 10 + 'a');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef EBUG
|
|
||||||
// dump memory buffer
|
|
||||||
void hexdump(uint8_t *arr, uint16_t len){
|
|
||||||
for(uint16_t l = 0; l < len; ++l, ++arr){
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
|
||||||
for(int16_t j = 1; j > -1; --j){
|
|
||||||
register uint8_t half = (*arr >> (4*j)) & 0x0f;
|
|
||||||
if(half < 10) usart_putchar(1, half + '0');
|
|
||||||
else usart_putchar(1, half - 10 + 'a');
|
|
||||||
}
|
|
||||||
if(l % 16 == 15) usart_putchar(1, '\n');
|
|
||||||
else if((l & 3) == 3) usart_putchar(1, ' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined EBUG || defined USART1PROXY
|
|
||||||
void dma1_channel4_isr(){ // USART1
|
|
||||||
if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx
|
|
||||||
DMA1->IFCR = DMA_IFCR_CTCIF4; // clear TC flag
|
|
||||||
txrdy[1] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void dma1_channel7_isr(){ // USART2
|
|
||||||
if(DMA1->ISR & DMA_ISR_TCIF7){ // Tx
|
|
||||||
DMA1->IFCR = DMA_IFCR_CTCIF7; // clear TC flag
|
|
||||||
txrdy[2] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dma1_channel2_isr(){ // USART3
|
|
||||||
if(DMA1->ISR & DMA_ISR_TCIF2){ // Tx
|
|
||||||
DMA1->IFCR = DMA_IFCR_CTCIF2; // clear TC flag
|
|
||||||
txrdy[3] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// read `buf` and get first integer `N` in it
|
|
||||||
// @return 0 if all OK or 1 if there's not a number; omit spaces and '='
|
|
||||||
int getnum(const char *buf, int32_t *N){
|
|
||||||
char c;
|
|
||||||
int positive = -1;
|
|
||||||
int32_t val = 0;
|
|
||||||
while((c = *buf++)){
|
|
||||||
if(c == '\t' || c == ' ' || c == '='){
|
|
||||||
if(positive < 0) continue; // beginning spaces
|
|
||||||
else break; // spaces after number
|
|
||||||
}
|
|
||||||
if(c == '-'){
|
|
||||||
if(positive < 0){
|
|
||||||
positive = 0;
|
|
||||||
continue;
|
|
||||||
}else break; // there already was `-` or number
|
|
||||||
}
|
|
||||||
if(c < '0' || c > '9') break;
|
|
||||||
if(positive < 0) positive = 1;
|
|
||||||
val = val * 10 + (int32_t)(c - '0');
|
|
||||||
}
|
|
||||||
if(positive != -1){
|
|
||||||
if(positive == 0){
|
|
||||||
if(val == 0) return 1; // single '-'
|
|
||||||
val = -val;
|
|
||||||
}
|
|
||||||
*N = val;
|
|
||||||
}else return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the chronometer project.
|
|
||||||
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef __USART_H__
|
|
||||||
#define __USART_H__
|
|
||||||
|
|
||||||
#include <stm32f1.h>
|
|
||||||
|
|
||||||
// input and output buffers size
|
|
||||||
#define UARTBUFSZ (128)
|
|
||||||
// timeout between data bytes
|
|
||||||
#ifndef TIMEOUT_MS
|
|
||||||
#define TIMEOUT_MS (1500)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define STR_HELPER(s) #s
|
|
||||||
#define STR(s) STR_HELPER(s)
|
|
||||||
|
|
||||||
#ifdef EBUG
|
|
||||||
#define SEND(str) usart_send(1, str)
|
|
||||||
#define MSG(str) do{SEND(__FILE__ " (L" STR(__LINE__) "): " str);}while(0)
|
|
||||||
#define DBG(str) do{SEND(str); newline(); }while(0)
|
|
||||||
#else
|
|
||||||
#define SEND(str)
|
|
||||||
#define MSG(str)
|
|
||||||
#define DBG(str)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define usartrx(n) (linerdy[n])
|
|
||||||
#define usartovr(n) (bufovr[n])
|
|
||||||
|
|
||||||
extern volatile int linerdy[4], bufovr[4], txrdy[4];
|
|
||||||
|
|
||||||
void transmit_tbuf(int n);
|
|
||||||
void usarts_setup();
|
|
||||||
int usart_getline(int n, char **line);
|
|
||||||
void usart_send(int n, const char *str);
|
|
||||||
void usart_putchar(int n, char ch);
|
|
||||||
char *u2str(uint32_t val);
|
|
||||||
void printu(int n, uint32_t val);
|
|
||||||
void printuhex(int n, uint32_t val);
|
|
||||||
int getnum(const char *buf, int32_t *N);
|
|
||||||
|
|
||||||
#if defined EBUG || defined USART1PROXY
|
|
||||||
void newline();
|
|
||||||
#endif
|
|
||||||
#ifdef EBUG
|
|
||||||
void hexdump(uint8_t *arr, uint16_t len);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // __USART_H__
|
|
||||||
@ -1,157 +0,0 @@
|
|||||||
/*
|
|
||||||
* geany_encoding=koi8-r
|
|
||||||
* usb.c - base functions for different USB types
|
|
||||||
*
|
|
||||||
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#include "usb.h"
|
|
||||||
#include "usb_lib.h"
|
|
||||||
#include "usart.h"
|
|
||||||
|
|
||||||
// incoming buffer size
|
|
||||||
#define IDATASZ (256)
|
|
||||||
static uint8_t incoming_data[IDATASZ];
|
|
||||||
static uint8_t ovfl = 0;
|
|
||||||
static uint16_t idatalen = 0;
|
|
||||||
static volatile uint8_t tx_succesfull = 0;
|
|
||||||
static int8_t usbON = 0; // ==1 when USB fully configured
|
|
||||||
|
|
||||||
// interrupt IN handler (never used?)
|
|
||||||
static uint16_t EP1_Handler(ep_t ep){
|
|
||||||
if (ep.rx_flag){
|
|
||||||
ep.status = SET_VALID_TX(ep.status);
|
|
||||||
ep.status = KEEP_STAT_RX(ep.status);
|
|
||||||
}else if (ep.tx_flag){
|
|
||||||
ep.status = SET_VALID_RX(ep.status);
|
|
||||||
ep.status = SET_STALL_TX(ep.status);
|
|
||||||
}
|
|
||||||
return ep.status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// data IN/OUT handler
|
|
||||||
static uint16_t EP23_Handler(ep_t ep){
|
|
||||||
if(ep.rx_flag){
|
|
||||||
int rd = ep.rx_cnt, rest = IDATASZ - idatalen;
|
|
||||||
if(rd){
|
|
||||||
if(rd <= rest){
|
|
||||||
idatalen += EP_Read(2, (uint16_t*)&incoming_data[idatalen]);
|
|
||||||
ovfl = 0;
|
|
||||||
}else{
|
|
||||||
ep.status = SET_NAK_RX(ep.status);
|
|
||||||
ovfl = 1;
|
|
||||||
return ep.status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// end of transaction: clear DTOGs
|
|
||||||
ep.status = CLEAR_DTOG_RX(ep.status);
|
|
||||||
ep.status = CLEAR_DTOG_TX(ep.status);
|
|
||||||
ep.status = SET_STALL_TX(ep.status);
|
|
||||||
}else if (ep.tx_flag){
|
|
||||||
ep.status = KEEP_STAT_TX(ep.status);
|
|
||||||
tx_succesfull = 1;
|
|
||||||
}
|
|
||||||
ep.status = SET_VALID_RX(ep.status);
|
|
||||||
return ep.status;
|
|
||||||
}
|
|
||||||
|
|
||||||
void USB_setup(){
|
|
||||||
NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
|
|
||||||
NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn);
|
|
||||||
RCC->APB1ENR |= RCC_APB1ENR_USBEN;
|
|
||||||
USB->CNTR = USB_CNTR_FRES; // Force USB Reset
|
|
||||||
for(uint32_t ctr = 0; ctr < 72000; ++ctr) nop(); // wait >1ms
|
|
||||||
//uint32_t ctr = 0;
|
|
||||||
USB->CNTR = 0;
|
|
||||||
USB->BTABLE = 0;
|
|
||||||
USB->DADDR = 0;
|
|
||||||
USB->ISTR = 0;
|
|
||||||
USB->CNTR = USB_CNTR_RESETM | USB_CNTR_WKUPM; // allow only wakeup & reset interrupts
|
|
||||||
NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
|
|
||||||
NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn );
|
|
||||||
}
|
|
||||||
|
|
||||||
void usb_proc(){
|
|
||||||
if(USB_GetState() == USB_CONFIGURE_STATE){ // USB configured - activate other endpoints
|
|
||||||
if(!usbON){ // endpoints not activated
|
|
||||||
// make new BULK endpoint
|
|
||||||
// Buffer have 1024 bytes, but last 256 we use for CAN bus (30.2 of RM: USB main features)
|
|
||||||
EP_Init(1, EP_TYPE_INTERRUPT, 10, 0, EP1_Handler); // IN1 - transmit
|
|
||||||
EP_Init(2, EP_TYPE_BULK, 0, USB_RXBUFSZ, EP23_Handler); // OUT2 - receive data
|
|
||||||
EP_Init(3, EP_TYPE_BULK, USB_TXBUFSZ, 0, EP23_Handler); // IN3 - transmit data
|
|
||||||
usbON = 1;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
usbON = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void USB_send(char *buf){
|
|
||||||
if(!USB_configured()){
|
|
||||||
DBG("USB not configured");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint16_t l = 0, ctr = 0;
|
|
||||||
char *p = buf;
|
|
||||||
while(*p++) ++l;
|
|
||||||
while(l){
|
|
||||||
uint16_t s = (l > USB_TXBUFSZ) ? USB_TXBUFSZ : l;
|
|
||||||
tx_succesfull = 0;
|
|
||||||
EP_Write(3, (uint8_t*)&buf[ctr], s);
|
|
||||||
uint32_t ctra = 1000000;
|
|
||||||
while(--ctra && tx_succesfull == 0);
|
|
||||||
l -= s;
|
|
||||||
ctr += s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief USB_receive
|
|
||||||
* @param buf (i) - buffer for received data
|
|
||||||
* @param bufsize - its size
|
|
||||||
* @return amount of received bytes
|
|
||||||
*/
|
|
||||||
int USB_receive(char *buf, int bufsize){
|
|
||||||
if(!bufsize || !idatalen) return 0;
|
|
||||||
USB->CNTR = 0;
|
|
||||||
int sz = (idatalen > bufsize) ? bufsize : idatalen, rest = idatalen - sz;
|
|
||||||
for(int i = 0; i < sz; ++i) buf[i] = incoming_data[i];
|
|
||||||
if(rest > 0){
|
|
||||||
uint8_t *ptr = &incoming_data[sz];
|
|
||||||
for(int i = 0; i < rest; ++i) incoming_data[i] = *ptr++;
|
|
||||||
//memmove(incoming_data, &incoming_data[sz], rest); - hardfault on memcpy&memmove
|
|
||||||
idatalen = rest;
|
|
||||||
}else idatalen = 0;
|
|
||||||
if(ovfl){
|
|
||||||
EP23_Handler(endpoints[2]);
|
|
||||||
uint16_t epstatus = USB->EPnR[2];
|
|
||||||
epstatus = CLEAR_DTOG_RX(epstatus);
|
|
||||||
epstatus = SET_VALID_RX(epstatus);
|
|
||||||
USB->EPnR[2] = epstatus;
|
|
||||||
}
|
|
||||||
USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM;
|
|
||||||
return sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief USB_configured
|
|
||||||
* @return 1 if USB is in configured state
|
|
||||||
*/
|
|
||||||
int USB_configured(){
|
|
||||||
return usbON;
|
|
||||||
}
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* geany_encoding=koi8-r
|
|
||||||
* usb.h
|
|
||||||
*
|
|
||||||
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
#ifndef __USB_H__
|
|
||||||
#define __USB_H__
|
|
||||||
|
|
||||||
#include "hardware.h"
|
|
||||||
|
|
||||||
#define BUFFSIZE (64)
|
|
||||||
|
|
||||||
void USB_setup();
|
|
||||||
void usb_proc();
|
|
||||||
void USB_send(char *buf);
|
|
||||||
int USB_receive(char *buf, int bufsize);
|
|
||||||
int USB_configured();
|
|
||||||
|
|
||||||
#endif // __USB_H__
|
|
||||||
@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* geany_encoding=koi8-r
|
|
||||||
* usb_defs.h
|
|
||||||
*
|
|
||||||
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef __USB_DEFS_H__
|
|
||||||
#define __USB_DEFS_H__
|
|
||||||
|
|
||||||
#include <stm32f1.h>
|
|
||||||
|
|
||||||
// max endpoints number
|
|
||||||
#define STM32ENDPOINTS 8
|
|
||||||
/**
|
|
||||||
* Buffers size definition
|
|
||||||
**/
|
|
||||||
#define USB_BTABLE_SIZE 512
|
|
||||||
// first 64 bytes of USB_BTABLE are registers!
|
|
||||||
//#define USB_EP0_BASEADDR 64
|
|
||||||
// for USB FS EP0 buffers are from 8 to 64 bytes long (64 for PL2303)
|
|
||||||
#define USB_EP0_BUFSZ 64
|
|
||||||
// USB transmit buffer size (64 for PL2303)
|
|
||||||
#define USB_TXBUFSZ 64
|
|
||||||
// USB receive buffer size (64 for PL2303)
|
|
||||||
#define USB_RXBUFSZ 64
|
|
||||||
|
|
||||||
#define USB_BTABLE_BASE 0x40006000
|
|
||||||
#define USB_BASE ((uint32_t)0x40005C00)
|
|
||||||
#define USB ((USB_TypeDef *) USB_BASE)
|
|
||||||
|
|
||||||
#ifdef USB_BTABLE
|
|
||||||
#undef USB_BTABLE
|
|
||||||
#endif
|
|
||||||
#define USB_BTABLE ((USB_BtableDef *)(USB_BTABLE_BASE))
|
|
||||||
#define USB_ISTR_EPID 0x0000000F
|
|
||||||
#define USB_FNR_LSOF_0 0x00000800
|
|
||||||
#define USB_FNR_lSOF_1 0x00001000
|
|
||||||
#define USB_LPMCSR_BESL_0 0x00000010
|
|
||||||
#define USB_LPMCSR_BESL_1 0x00000020
|
|
||||||
#define USB_LPMCSR_BESL_2 0x00000040
|
|
||||||
#define USB_LPMCSR_BESL_3 0x00000080
|
|
||||||
#define USB_EPnR_CTR_RX 0x00008000
|
|
||||||
#define USB_EPnR_DTOG_RX 0x00004000
|
|
||||||
#define USB_EPnR_STAT_RX 0x00003000
|
|
||||||
#define USB_EPnR_STAT_RX_0 0x00001000
|
|
||||||
#define USB_EPnR_STAT_RX_1 0x00002000
|
|
||||||
#define USB_EPnR_SETUP 0x00000800
|
|
||||||
#define USB_EPnR_EP_TYPE 0x00000600
|
|
||||||
#define USB_EPnR_EP_TYPE_0 0x00000200
|
|
||||||
#define USB_EPnR_EP_TYPE_1 0x00000400
|
|
||||||
#define USB_EPnR_EP_KIND 0x00000100
|
|
||||||
#define USB_EPnR_CTR_TX 0x00000080
|
|
||||||
#define USB_EPnR_DTOG_TX 0x00000040
|
|
||||||
#define USB_EPnR_STAT_TX 0x00000030
|
|
||||||
#define USB_EPnR_STAT_TX_0 0x00000010
|
|
||||||
#define USB_EPnR_STAT_TX_1 0x00000020
|
|
||||||
#define USB_EPnR_EA 0x0000000F
|
|
||||||
#define USB_COUNTn_RX_BLSIZE 0x00008000
|
|
||||||
#define USB_COUNTn_NUM_BLOCK 0x00007C00
|
|
||||||
#define USB_COUNTn_RX 0x0000003F
|
|
||||||
|
|
||||||
#ifdef USB_TypeDef
|
|
||||||
#define USB_TypeDef USB_TypeDef_custom
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
__IO uint32_t EPnR[STM32ENDPOINTS];
|
|
||||||
__IO uint32_t RESERVED[STM32ENDPOINTS];
|
|
||||||
__IO uint32_t CNTR;
|
|
||||||
__IO uint32_t ISTR;
|
|
||||||
__IO uint32_t FNR;
|
|
||||||
__IO uint32_t DADDR;
|
|
||||||
__IO uint32_t BTABLE;
|
|
||||||
} USB_TypeDef;
|
|
||||||
|
|
||||||
/*
|
|
||||||
typedef struct{
|
|
||||||
__IO uint16_t USB_ADDR_TX;
|
|
||||||
__IO uint16_t res1;
|
|
||||||
__IO uint16_t USB_COUNT_TX;
|
|
||||||
__IO uint16_t res2;
|
|
||||||
__IO uint16_t USB_ADDR_RX;
|
|
||||||
__IO uint16_t res3;
|
|
||||||
__IO uint16_t USB_COUNT_RX;
|
|
||||||
__IO uint16_t res4;
|
|
||||||
} USB_EPDATA_TypeDef;*/
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
__IO uint32_t USB_ADDR_TX;
|
|
||||||
__IO uint32_t USB_COUNT_TX;
|
|
||||||
__IO uint32_t USB_ADDR_RX;
|
|
||||||
__IO uint32_t USB_COUNT_RX;
|
|
||||||
} USB_EPDATA_TypeDef;
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
__IO USB_EPDATA_TypeDef EP[STM32ENDPOINTS];
|
|
||||||
} USB_BtableDef;
|
|
||||||
|
|
||||||
#endif // __USB_DEFS_H__
|
|
||||||
@ -1,521 +0,0 @@
|
|||||||
/*
|
|
||||||
* geany_encoding=koi8-r
|
|
||||||
* usb_lib.c
|
|
||||||
*
|
|
||||||
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "usb_lib.h"
|
|
||||||
#include "usart.h"
|
|
||||||
|
|
||||||
ep_t endpoints[STM32ENDPOINTS];
|
|
||||||
|
|
||||||
static usb_dev_t USB_Dev;
|
|
||||||
static usb_LineCoding lineCoding = {115200, 0, 0, 8};
|
|
||||||
config_pack_t setup_packet;
|
|
||||||
static uint8_t ep0databuf[EP0DATABUF_SIZE];
|
|
||||||
static uint8_t ep0dbuflen = 0;
|
|
||||||
|
|
||||||
usb_LineCoding getLineCoding(){return lineCoding;}
|
|
||||||
|
|
||||||
// definition of parts common for USB_DeviceDescriptor & USB_DeviceQualifierDescriptor
|
|
||||||
#define bcdUSB_L 0x10
|
|
||||||
#define bcdUSB_H 0x01
|
|
||||||
#define bDeviceClass 0
|
|
||||||
#define bDeviceSubClass 0
|
|
||||||
#define bDeviceProtocol 0
|
|
||||||
#define bNumConfigurations 1
|
|
||||||
|
|
||||||
static const uint8_t USB_DeviceDescriptor[] = {
|
|
||||||
18, // bLength
|
|
||||||
0x01, // bDescriptorType - Device descriptor
|
|
||||||
bcdUSB_L, // bcdUSB_L - 1.10
|
|
||||||
bcdUSB_H, // bcdUSB_H
|
|
||||||
bDeviceClass, // bDeviceClass - USB_COMM
|
|
||||||
bDeviceSubClass, // bDeviceSubClass
|
|
||||||
bDeviceProtocol, // bDeviceProtocol
|
|
||||||
USB_EP0_BUFSZ, // bMaxPacketSize
|
|
||||||
0x7b, // idVendor_L PL2303: VID=0x067b, PID=0x2303
|
|
||||||
0x06, // idVendor_H
|
|
||||||
0x03, // idProduct_L
|
|
||||||
0x23, // idProduct_H
|
|
||||||
0x00, // bcdDevice_Ver_L
|
|
||||||
0x03, // bcdDevice_Ver_H
|
|
||||||
0x01, // iManufacturer
|
|
||||||
0x02, // iProduct
|
|
||||||
0x00, // iSerialNumber
|
|
||||||
bNumConfigurations // bNumConfigurations
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t USB_DeviceQualifierDescriptor[] = {
|
|
||||||
10, //bLength
|
|
||||||
0x06, // bDescriptorType - Device qualifier
|
|
||||||
bcdUSB_L, // bcdUSB_L
|
|
||||||
bcdUSB_H, // bcdUSB_H
|
|
||||||
bDeviceClass, // bDeviceClass
|
|
||||||
bDeviceSubClass, // bDeviceSubClass
|
|
||||||
bDeviceProtocol, // bDeviceProtocol
|
|
||||||
USB_EP0_BUFSZ, // bMaxPacketSize0
|
|
||||||
bNumConfigurations, // bNumConfigurations
|
|
||||||
0x00 // Reserved
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t USB_ConfigDescriptor[] = {
|
|
||||||
/*Configuration Descriptor*/
|
|
||||||
0x09, /* bLength: Configuration Descriptor size */
|
|
||||||
0x02, /* bDescriptorType: Configuration */
|
|
||||||
39, /* wTotalLength:no of returned bytes */
|
|
||||||
0x00,
|
|
||||||
0x01, /* bNumInterfaces: 1 interface */
|
|
||||||
0x01, /* bConfigurationValue: Configuration value */
|
|
||||||
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
|
|
||||||
0xa0, /* bmAttributes - Bus powered, Remote wakeup */
|
|
||||||
0x32, /* MaxPower 100 mA */
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/*Interface Descriptor */
|
|
||||||
0x09, /* bLength: Interface Descriptor size */
|
|
||||||
0x04, /* bDescriptorType: Interface */
|
|
||||||
0x00, /* bInterfaceNumber: Number of Interface */
|
|
||||||
0x00, /* bAlternateSetting: Alternate setting */
|
|
||||||
0x03, /* bNumEndpoints: 3 endpoints used */
|
|
||||||
0xff, /* bInterfaceClass */
|
|
||||||
0x00, /* bInterfaceSubClass */
|
|
||||||
0x00, /* bInterfaceProtocol */
|
|
||||||
0x00, /* iInterface: */
|
|
||||||
///////////////////////////////////////////////////
|
|
||||||
/*Endpoint 1 Descriptor*/
|
|
||||||
0x07, /* bLength: Endpoint Descriptor size */
|
|
||||||
0x05, /* bDescriptorType: Endpoint */
|
|
||||||
0x81, /* bEndpointAddress IN1 */
|
|
||||||
0x03, /* bmAttributes: Interrupt */
|
|
||||||
0x0a, /* wMaxPacketSize LO: */
|
|
||||||
0x00, /* wMaxPacketSize HI: */
|
|
||||||
0x01, /* bInterval: */
|
|
||||||
|
|
||||||
/*Endpoint OUT2 Descriptor*/
|
|
||||||
0x07, /* bLength: Endpoint Descriptor size */
|
|
||||||
0x05, /* bDescriptorType: Endpoint */
|
|
||||||
0x02, /* bEndpointAddress: OUT2 */
|
|
||||||
0x02, /* bmAttributes: Bulk */
|
|
||||||
(USB_RXBUFSZ & 0xff), /* wMaxPacketSize: 64 */
|
|
||||||
(USB_RXBUFSZ >> 8),
|
|
||||||
0x00, /* bInterval: ignore for Bulk transfer */
|
|
||||||
|
|
||||||
/*Endpoint IN3 Descriptor*/
|
|
||||||
0x07, /* bLength: Endpoint Descriptor size */
|
|
||||||
0x05, /* bDescriptorType: Endpoint */
|
|
||||||
0x83, /* bEndpointAddress IN3 */
|
|
||||||
0x02, /* bmAttributes: Bulk */
|
|
||||||
(USB_TXBUFSZ & 0xff), /* wMaxPacketSize: 64 */
|
|
||||||
(USB_TXBUFSZ >> 8),
|
|
||||||
0x00, /* bInterval: ignore for Bulk transfer */
|
|
||||||
};
|
|
||||||
|
|
||||||
_USB_LANG_ID_(USB_StringLangDescriptor, LANG_US);
|
|
||||||
// these descriptors are not used in PL2303 emulator!
|
|
||||||
_USB_STRING_(USB_StringSerialDescriptor, u"0");
|
|
||||||
_USB_STRING_(USB_StringManufacturingDescriptor, u"Prolific Technology Inc.");
|
|
||||||
_USB_STRING_(USB_StringProdDescriptor, u"USB-Serial Controller");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* default handlers
|
|
||||||
*/
|
|
||||||
// SET_LINE_CODING
|
|
||||||
void WEAK linecoding_handler(usb_LineCoding __attribute__((unused)) *lc){
|
|
||||||
}
|
|
||||||
|
|
||||||
// SET_CONTROL_LINE_STATE
|
|
||||||
void WEAK clstate_handler(uint16_t __attribute__((unused)) val){
|
|
||||||
}
|
|
||||||
|
|
||||||
// SEND_BREAK
|
|
||||||
void WEAK break_handler(){
|
|
||||||
}
|
|
||||||
|
|
||||||
// handler of vendor requests
|
|
||||||
void WEAK vendor_handler(config_pack_t *packet){
|
|
||||||
if(packet->bmRequestType & 0x80){ // read
|
|
||||||
uint8_t c;
|
|
||||||
switch(packet->wValue){
|
|
||||||
case 0x8484:
|
|
||||||
c = 2;
|
|
||||||
break;
|
|
||||||
case 0x0080:
|
|
||||||
c = 1;
|
|
||||||
break;
|
|
||||||
case 0x8686:
|
|
||||||
c = 0xaa;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
c = 0;
|
|
||||||
}
|
|
||||||
EP_WriteIRQ(0, &c, 1);
|
|
||||||
}else{ // write ZLP
|
|
||||||
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void wr0(const uint8_t *buf, uint16_t size){
|
|
||||||
if(setup_packet.wLength < size) size = setup_packet.wLength;
|
|
||||||
EP_WriteIRQ(0, buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void get_descriptor(){
|
|
||||||
switch(setup_packet.wValue){
|
|
||||||
case DEVICE_DESCRIPTOR:
|
|
||||||
wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor));
|
|
||||||
break;
|
|
||||||
case CONFIGURATION_DESCRIPTOR:
|
|
||||||
wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor));
|
|
||||||
break;
|
|
||||||
case STRING_LANG_DESCRIPTOR:
|
|
||||||
wr0((const uint8_t *)&USB_StringLangDescriptor, STRING_LANG_DESCRIPTOR_SIZE_BYTE);
|
|
||||||
break;
|
|
||||||
case STRING_MAN_DESCRIPTOR:
|
|
||||||
wr0((const uint8_t *)&USB_StringManufacturingDescriptor, USB_StringManufacturingDescriptor.bLength);
|
|
||||||
break;
|
|
||||||
case STRING_PROD_DESCRIPTOR:
|
|
||||||
wr0((const uint8_t *)&USB_StringProdDescriptor, USB_StringProdDescriptor.bLength);
|
|
||||||
break;
|
|
||||||
case STRING_SN_DESCRIPTOR:
|
|
||||||
wr0((const uint8_t *)&USB_StringSerialDescriptor, USB_StringSerialDescriptor.bLength);
|
|
||||||
break;
|
|
||||||
case DEVICE_QUALIFIER_DESCRIPTOR:
|
|
||||||
wr0(USB_DeviceQualifierDescriptor, USB_DeviceQualifierDescriptor[0]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured)
|
|
||||||
static inline void std_d2h_req(){
|
|
||||||
uint16_t status = 0; // bus powered
|
|
||||||
switch(setup_packet.bRequest){
|
|
||||||
case GET_DESCRIPTOR:
|
|
||||||
get_descriptor();
|
|
||||||
break;
|
|
||||||
case GET_STATUS:
|
|
||||||
EP_WriteIRQ(0, (uint8_t *)&status, 2); // send status: Bus Powered
|
|
||||||
break;
|
|
||||||
case GET_CONFIGURATION:
|
|
||||||
EP_WriteIRQ(0, &configuration, 1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void std_h2d_req(){
|
|
||||||
switch(setup_packet.bRequest){
|
|
||||||
case SET_ADDRESS:
|
|
||||||
// new address will be assigned later - after acknowlegement or request to host
|
|
||||||
USB_Dev.USB_Addr = setup_packet.wValue;
|
|
||||||
break;
|
|
||||||
case SET_CONFIGURATION:
|
|
||||||
// Now device configured
|
|
||||||
USB_Dev.USB_Status = USB_CONFIGURE_STATE;
|
|
||||||
configuration = setup_packet.wValue;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
bmRequestType: 76543210
|
|
||||||
7 direction: 0 - host->device, 1 - device->host
|
|
||||||
65 type: 0 - standard, 1 - class, 2 - vendor
|
|
||||||
4..0 getter: 0 - device, 1 - interface, 2 - endpoint, 3 - other
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Endpoint0 (control) handler
|
|
||||||
* @param ep - endpoint state
|
|
||||||
* @return data written to EP0R
|
|
||||||
*/
|
|
||||||
static uint16_t EP0_Handler(ep_t ep){
|
|
||||||
uint16_t epstatus = ep.status; // EP0R on input -> return this value after modifications
|
|
||||||
uint8_t reqtype = setup_packet.bmRequestType & 0x7f;
|
|
||||||
uint8_t dev2host = (setup_packet.bmRequestType & 0x80) ? 1 : 0;
|
|
||||||
if ((ep.rx_flag) && (ep.setup_flag)){
|
|
||||||
switch(reqtype){
|
|
||||||
case STANDARD_DEVICE_REQUEST_TYPE: // standard device request
|
|
||||||
if(dev2host){
|
|
||||||
std_d2h_req();
|
|
||||||
}else{
|
|
||||||
std_h2d_req();
|
|
||||||
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
|
||||||
}
|
|
||||||
epstatus = SET_NAK_RX(epstatus);
|
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
|
||||||
break;
|
|
||||||
case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request
|
|
||||||
if(setup_packet.bRequest == CLEAR_FEATURE){
|
|
||||||
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
|
||||||
epstatus = SET_NAK_RX(epstatus);
|
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case VENDOR_REQUEST_TYPE:
|
|
||||||
vendor_handler(&setup_packet);
|
|
||||||
epstatus = SET_NAK_RX(epstatus);
|
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
|
||||||
break;
|
|
||||||
case CONTROL_REQUEST_TYPE:
|
|
||||||
switch(setup_packet.bRequest){
|
|
||||||
case GET_LINE_CODING:
|
|
||||||
EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding));
|
|
||||||
break;
|
|
||||||
case SET_LINE_CODING: // omit this for next stage, when data will come
|
|
||||||
break;
|
|
||||||
case SET_CONTROL_LINE_STATE:
|
|
||||||
clstate_handler(setup_packet.wValue);
|
|
||||||
break;
|
|
||||||
case SEND_BREAK:
|
|
||||||
break_handler();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!dev2host) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement
|
|
||||||
epstatus = SET_VALID_RX(epstatus);
|
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
|
||||||
epstatus = SET_NAK_RX(epstatus);
|
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
|
||||||
}
|
|
||||||
}else if (ep.rx_flag){ // got data over EP0 or host acknowlegement
|
|
||||||
if(ep.rx_cnt){
|
|
||||||
//EP_WriteIRQ(0, (uint8_t *)0, 0);
|
|
||||||
if(setup_packet.bRequest == SET_LINE_CODING){
|
|
||||||
linecoding_handler((usb_LineCoding*)ep0databuf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// wait for new data from host
|
|
||||||
epstatus = SET_VALID_RX(epstatus);
|
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
|
||||||
} else if (ep.tx_flag){ // package transmitted
|
|
||||||
// now we can change address after enumeration
|
|
||||||
if ((USB->DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){
|
|
||||||
USB->DADDR = USB_DADDR_EF | USB_Dev.USB_Addr;
|
|
||||||
// change state to ADRESSED
|
|
||||||
USB_Dev.USB_Status = USB_ADRESSED_STATE;
|
|
||||||
}
|
|
||||||
// end of transaction
|
|
||||||
epstatus = CLEAR_DTOG_RX(epstatus);
|
|
||||||
epstatus = CLEAR_DTOG_TX(epstatus);
|
|
||||||
epstatus = SET_VALID_RX(epstatus);
|
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
|
||||||
}
|
|
||||||
return epstatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t lastaddr = LASTADDR_DEFAULT;
|
|
||||||
/**
|
|
||||||
* Endpoint initialisation
|
|
||||||
* @param number - EP num (0...7)
|
|
||||||
* @param type - EP type (EP_TYPE_BULK, EP_TYPE_CONTROL, EP_TYPE_ISO, EP_TYPE_INTERRUPT)
|
|
||||||
* @param txsz - transmission buffer size @ USB/CAN buffer
|
|
||||||
* @param rxsz - reception buffer size @ USB/CAN buffer
|
|
||||||
* @param uint16_t (*func)(ep_t *ep) - EP handler function
|
|
||||||
* @return 0 if all OK
|
|
||||||
*/
|
|
||||||
int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t (*func)(ep_t ep)){
|
|
||||||
if(number >= STM32ENDPOINTS) return 4; // out of configured amount
|
|
||||||
if(txsz > USB_BTABLE_SIZE || rxsz > USB_BTABLE_SIZE) return 1; // buffer too large
|
|
||||||
if(lastaddr + txsz + rxsz >= USB_BTABLE_SIZE) return 2; // out of btable
|
|
||||||
USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA);
|
|
||||||
USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX_1;
|
|
||||||
if(rxsz & 1 || rxsz > 512) return 3; // wrong rx buffer size
|
|
||||||
uint16_t countrx = 0;
|
|
||||||
if(rxsz < 64) countrx = rxsz / 2;
|
|
||||||
else{
|
|
||||||
if(rxsz & 0x1f) return 3; // should be multiple of 32
|
|
||||||
countrx = 31 + rxsz / 32;
|
|
||||||
}
|
|
||||||
USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr;
|
|
||||||
endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr*2);
|
|
||||||
lastaddr += txsz;
|
|
||||||
USB_BTABLE->EP[number].USB_COUNT_TX = 0;
|
|
||||||
USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr;
|
|
||||||
endpoints[number].rx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr*2);
|
|
||||||
lastaddr += rxsz;
|
|
||||||
USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10;
|
|
||||||
endpoints[number].func = func;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//extern int8_t dump;
|
|
||||||
// standard IRQ handler
|
|
||||||
void usb_isr(){
|
|
||||||
if (USB->ISTR & USB_ISTR_RESET){
|
|
||||||
// Reinit registers
|
|
||||||
USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM;
|
|
||||||
USB->ISTR = 0;
|
|
||||||
// Endpoint 0 - CONTROL
|
|
||||||
// ON USB LS size of EP0 may be 8 bytes, but on FS it should be 64 bytes!
|
|
||||||
lastaddr = LASTADDR_DEFAULT;
|
|
||||||
if(EP_Init(0, EP_TYPE_CONTROL, USB_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler)){
|
|
||||||
DBG("Err init EP0");
|
|
||||||
}
|
|
||||||
// clear address, leave only enable bit
|
|
||||||
USB->DADDR = USB_DADDR_EF;
|
|
||||||
// state is default - wait for enumeration
|
|
||||||
USB_Dev.USB_Status = USB_DEFAULT_STATE;
|
|
||||||
}
|
|
||||||
if(USB->ISTR & USB_ISTR_CTR){
|
|
||||||
// EP number
|
|
||||||
uint8_t n = USB->ISTR & USB_ISTR_EPID;
|
|
||||||
// copy status register
|
|
||||||
uint16_t epstatus = USB->EPnR[n];
|
|
||||||
// dump = 1;
|
|
||||||
// Calculate flags
|
|
||||||
endpoints[n].rx_flag = (epstatus & USB_EPnR_CTR_RX) ? 1 : 0;
|
|
||||||
endpoints[n].setup_flag = (epstatus & USB_EPnR_SETUP) ? 1 : 0;
|
|
||||||
endpoints[n].tx_flag = (epstatus & USB_EPnR_CTR_TX) ? 1 : 0;
|
|
||||||
// copy received bytes amount
|
|
||||||
endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX & 0x3FF; // low 10 bits is counter
|
|
||||||
// check direction
|
|
||||||
if(USB->ISTR & USB_ISTR_DIR){ // OUT interrupt - receive data, CTR_RX==1 (if CTR_TX == 1 - two pending transactions: receive following by transmit)
|
|
||||||
if(n == 0){ // control endpoint
|
|
||||||
if(epstatus & USB_EPnR_SETUP){ // setup packet -> copy data to conf_pack
|
|
||||||
EP_Read(0, (uint16_t*)&setup_packet);
|
|
||||||
ep0dbuflen = 0;
|
|
||||||
// interrupt handler will be called later
|
|
||||||
}else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf
|
|
||||||
ep0dbuflen = endpoints[0].rx_cnt;
|
|
||||||
EP_Read(0, (uint16_t*)&ep0databuf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else{ // IN interrupt - transmit data, only CTR_TX == 1
|
|
||||||
// enumeration end could be here (if EP0)
|
|
||||||
}
|
|
||||||
// prepare status field for EP handler
|
|
||||||
endpoints[n].status = epstatus;
|
|
||||||
// call EP handler (even if it will change EPnR, it should return new status)
|
|
||||||
epstatus = endpoints[n].func(endpoints[n]);
|
|
||||||
// keep DTOG state
|
|
||||||
epstatus = KEEP_DTOG_TX(epstatus);
|
|
||||||
epstatus = KEEP_DTOG_RX(epstatus);
|
|
||||||
// clear all RX/TX flags
|
|
||||||
epstatus = CLEAR_CTR_RX(epstatus);
|
|
||||||
epstatus = CLEAR_CTR_TX(epstatus);
|
|
||||||
// refresh EPnR
|
|
||||||
USB->EPnR[n] = epstatus;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (USB->ISTR & USB_ISTR_PMAOVR) {
|
|
||||||
MSG("PMAOVR\n");
|
|
||||||
// Handle PMAOVR status
|
|
||||||
}
|
|
||||||
if (USB->ISTR & USB_ISTR_SUSP) {
|
|
||||||
MSG("SUSP\n");
|
|
||||||
if (USB->DADDR & 0x7f) {
|
|
||||||
USB->DADDR = 0;
|
|
||||||
USB->CNTR &= ~ 0x800;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (USB->ISTR & USB_ISTR_ERR) {
|
|
||||||
MSG("ERR\n");
|
|
||||||
// Handle Error
|
|
||||||
}
|
|
||||||
if (USB->ISTR & USB_ISTR_WKUP) {
|
|
||||||
MSG("WKUP\n");
|
|
||||||
// Handle Wakeup
|
|
||||||
}
|
|
||||||
if (USB->ISTR & USB_ISTR_SOF) {
|
|
||||||
MSG("SOF\n");
|
|
||||||
// Handle SOF
|
|
||||||
}
|
|
||||||
if (USB->ISTR & USB_ISTR_ESOF) {
|
|
||||||
MSG("ESOF\n");
|
|
||||||
// Handle ESOF
|
|
||||||
}
|
|
||||||
USB->ISTR = 0;
|
|
||||||
*/
|
|
||||||
|
|
||||||
void usb_lp_can_rx0_isr(){
|
|
||||||
usb_isr();
|
|
||||||
}
|
|
||||||
|
|
||||||
void usb_hp_can_tx_isr(){
|
|
||||||
usb_isr();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write data to EP buffer (called from IRQ handler)
|
|
||||||
* @param number - EP number
|
|
||||||
* @param *buf - array with data
|
|
||||||
* @param size - its size
|
|
||||||
*/
|
|
||||||
void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){
|
|
||||||
uint8_t i;
|
|
||||||
if(size > USB_TXBUFSZ) size = USB_TXBUFSZ;
|
|
||||||
uint16_t N2 = (size + 1) >> 1;
|
|
||||||
// the buffer is 16-bit, so we should copy data as it would be uint16_t
|
|
||||||
uint16_t *buf16 = (uint16_t *)buf;
|
|
||||||
uint32_t *out = (uint32_t *)endpoints[number].tx_buf;
|
|
||||||
for(i = 0; i < N2; ++i, ++out){
|
|
||||||
*out = buf16[i];
|
|
||||||
}
|
|
||||||
USB_BTABLE->EP[number].USB_COUNT_TX = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write data to EP buffer (called outside IRQ handler)
|
|
||||||
* @param number - EP number
|
|
||||||
* @param *buf - array with data
|
|
||||||
* @param size - its size
|
|
||||||
*/
|
|
||||||
void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){
|
|
||||||
uint16_t status = USB->EPnR[number];
|
|
||||||
EP_WriteIRQ(number, buf, size);
|
|
||||||
status = SET_NAK_RX(status);
|
|
||||||
status = SET_VALID_TX(status);
|
|
||||||
status = KEEP_DTOG_TX(status);
|
|
||||||
status = KEEP_DTOG_RX(status);
|
|
||||||
USB->EPnR[number] = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy data from EP buffer into user buffer area
|
|
||||||
* @param *buf - user array for data
|
|
||||||
* @return amount of data read
|
|
||||||
*/
|
|
||||||
int EP_Read(uint8_t number, uint16_t *buf){
|
|
||||||
int n = (endpoints[number].rx_cnt + 1) >> 1;
|
|
||||||
uint32_t *in = (uint32_t *)endpoints[number].rx_buf;
|
|
||||||
if(n){
|
|
||||||
for(int i = 0; i < n; ++i, ++in)
|
|
||||||
buf[i] = *(uint16_t*)in;
|
|
||||||
}
|
|
||||||
return endpoints[number].rx_cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// USB status
|
|
||||||
uint8_t USB_GetState(){
|
|
||||||
return USB_Dev.USB_Status;
|
|
||||||
}
|
|
||||||
@ -1,202 +0,0 @@
|
|||||||
/*
|
|
||||||
* geany_encoding=koi8-r
|
|
||||||
* usb_lib.h
|
|
||||||
*
|
|
||||||
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef __USB_LIB_H__
|
|
||||||
#define __USB_LIB_H__
|
|
||||||
|
|
||||||
#include <wchar.h>
|
|
||||||
#include "usb_defs.h"
|
|
||||||
|
|
||||||
#define EP0DATABUF_SIZE (64)
|
|
||||||
#define LASTADDR_DEFAULT (STM32ENDPOINTS * 8)
|
|
||||||
|
|
||||||
// Max EP amount (EP0 + other used)
|
|
||||||
//#define ENDPOINTS_NUM 4
|
|
||||||
// bmRequestType & 0x7f
|
|
||||||
#define STANDARD_DEVICE_REQUEST_TYPE 0
|
|
||||||
#define STANDARD_ENDPOINT_REQUEST_TYPE 2
|
|
||||||
#define VENDOR_REQUEST_TYPE 0x40
|
|
||||||
#define CONTROL_REQUEST_TYPE 0x21
|
|
||||||
// bRequest, standard; for bmRequestType == 0x80
|
|
||||||
#define GET_STATUS 0x00
|
|
||||||
#define GET_DESCRIPTOR 0x06
|
|
||||||
#define GET_CONFIGURATION 0x08
|
|
||||||
// for bmRequestType == 0
|
|
||||||
#define CLEAR_FEATURE 0x01
|
|
||||||
#define SET_FEATURE 0x03 // unused
|
|
||||||
#define SET_ADDRESS 0x05
|
|
||||||
#define SET_DESCRIPTOR 0x07 // unused
|
|
||||||
#define SET_CONFIGURATION 0x09
|
|
||||||
// for bmRequestType == 0x81, 1 or 0xB2
|
|
||||||
#define GET_INTERFACE 0x0A // unused
|
|
||||||
#define SET_INTERFACE 0x0B // unused
|
|
||||||
#define SYNC_FRAME 0x0C // unused
|
|
||||||
#define VENDOR_REQUEST 0x01 // unused
|
|
||||||
|
|
||||||
// Class-Specific Control Requests
|
|
||||||
#define SEND_ENCAPSULATED_COMMAND 0x00 // unused
|
|
||||||
#define GET_ENCAPSULATED_RESPONSE 0x01 // unused
|
|
||||||
#define SET_COMM_FEATURE 0x02 // unused
|
|
||||||
#define GET_COMM_FEATURE 0x03 // unused
|
|
||||||
#define CLEAR_COMM_FEATURE 0x04 // unused
|
|
||||||
#define SET_LINE_CODING 0x20
|
|
||||||
#define GET_LINE_CODING 0x21
|
|
||||||
#define SET_CONTROL_LINE_STATE 0x22
|
|
||||||
#define SEND_BREAK 0x23
|
|
||||||
|
|
||||||
// control line states
|
|
||||||
#define CONTROL_DTR 0x01
|
|
||||||
#define CONTROL_RTS 0x02
|
|
||||||
|
|
||||||
// wValue
|
|
||||||
#define DEVICE_DESCRIPTOR 0x100
|
|
||||||
#define CONFIGURATION_DESCRIPTOR 0x200
|
|
||||||
#define STRING_LANG_DESCRIPTOR 0x300
|
|
||||||
#define STRING_MAN_DESCRIPTOR 0x301
|
|
||||||
#define STRING_PROD_DESCRIPTOR 0x302
|
|
||||||
#define STRING_SN_DESCRIPTOR 0x303
|
|
||||||
#define DEVICE_QUALIFIER_DESCRIPTOR 0x600
|
|
||||||
|
|
||||||
// EPnR bits manipulation
|
|
||||||
#define CLEAR_DTOG_RX(R) (R & USB_EPnR_DTOG_RX) ? R : (R & (~USB_EPnR_DTOG_RX))
|
|
||||||
#define SET_DTOG_RX(R) (R & USB_EPnR_DTOG_RX) ? (R & (~USB_EPnR_DTOG_RX)) : R
|
|
||||||
#define TOGGLE_DTOG_RX(R) (R | USB_EPnR_DTOG_RX)
|
|
||||||
#define KEEP_DTOG_RX(R) (R & (~USB_EPnR_DTOG_RX))
|
|
||||||
#define CLEAR_DTOG_TX(R) (R & USB_EPnR_DTOG_TX) ? R : (R & (~USB_EPnR_DTOG_TX))
|
|
||||||
#define SET_DTOG_TX(R) (R & USB_EPnR_DTOG_TX) ? (R & (~USB_EPnR_DTOG_TX)) : R
|
|
||||||
#define TOGGLE_DTOG_TX(R) (R | USB_EPnR_DTOG_TX)
|
|
||||||
#define KEEP_DTOG_TX(R) (R & (~USB_EPnR_DTOG_TX))
|
|
||||||
#define SET_VALID_RX(R) ((R & USB_EPnR_STAT_RX) ^ USB_EPnR_STAT_RX) | (R & (~USB_EPnR_STAT_RX))
|
|
||||||
#define SET_NAK_RX(R) ((R & USB_EPnR_STAT_RX) ^ USB_EPnR_STAT_RX_1) | (R & (~USB_EPnR_STAT_RX))
|
|
||||||
#define SET_STALL_RX(R) ((R & USB_EPnR_STAT_RX) ^ USB_EPnR_STAT_RX_0) | (R & (~USB_EPnR_STAT_RX))
|
|
||||||
#define KEEP_STAT_RX(R) (R & (~USB_EPnR_STAT_RX))
|
|
||||||
#define SET_VALID_TX(R) ((R & USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_TX) | (R & (~USB_EPnR_STAT_TX))
|
|
||||||
#define SET_NAK_TX(R) ((R & USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_TX_1) | (R & (~USB_EPnR_STAT_TX))
|
|
||||||
#define SET_STALL_TX(R) ((R & USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_TX_0) | (R & (~USB_EPnR_STAT_TX))
|
|
||||||
#define KEEP_STAT_TX(R) (R & (~USB_EPnR_STAT_TX))
|
|
||||||
#define CLEAR_CTR_RX(R) (R & (~USB_EPnR_CTR_RX))
|
|
||||||
#define CLEAR_CTR_TX(R) (R & (~USB_EPnR_CTR_TX))
|
|
||||||
#define CLEAR_CTR_RX_TX(R) (R & (~(USB_EPnR_CTR_TX | USB_EPnR_CTR_RX)))
|
|
||||||
|
|
||||||
// USB state: uninitialized, addressed, ready for use
|
|
||||||
#define USB_DEFAULT_STATE 0
|
|
||||||
#define USB_ADRESSED_STATE 1
|
|
||||||
#define USB_CONFIGURE_STATE 2
|
|
||||||
|
|
||||||
// EP types
|
|
||||||
#define EP_TYPE_BULK 0x00
|
|
||||||
#define EP_TYPE_CONTROL 0x01
|
|
||||||
#define EP_TYPE_ISO 0x02
|
|
||||||
#define EP_TYPE_INTERRUPT 0x03
|
|
||||||
|
|
||||||
#define LANG_US (uint16_t)0x0409
|
|
||||||
|
|
||||||
#define _USB_STRING_(name, str) \
|
|
||||||
static const struct name \
|
|
||||||
{ \
|
|
||||||
uint8_t bLength; \
|
|
||||||
uint8_t bDescriptorType; \
|
|
||||||
uint16_t bString[(sizeof(str) - 2) / 2]; \
|
|
||||||
\
|
|
||||||
} \
|
|
||||||
name = {sizeof(name), 0x03, str}
|
|
||||||
|
|
||||||
#define _USB_LANG_ID_(name, lng_id) \
|
|
||||||
\
|
|
||||||
static const struct name \
|
|
||||||
{ \
|
|
||||||
uint8_t bLength; \
|
|
||||||
uint8_t bDescriptorType; \
|
|
||||||
uint16_t bString; \
|
|
||||||
\
|
|
||||||
} \
|
|
||||||
name = {0x04, 0x03, lng_id}
|
|
||||||
#define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4)
|
|
||||||
|
|
||||||
// EP0 configuration packet
|
|
||||||
typedef struct {
|
|
||||||
uint8_t bmRequestType;
|
|
||||||
uint8_t bRequest;
|
|
||||||
uint16_t wValue;
|
|
||||||
uint16_t wIndex;
|
|
||||||
uint16_t wLength;
|
|
||||||
} config_pack_t;
|
|
||||||
|
|
||||||
// endpoints state
|
|
||||||
typedef struct __ep_t{
|
|
||||||
uint16_t *tx_buf; // transmission buffer address
|
|
||||||
uint16_t *rx_buf; // reception buffer address
|
|
||||||
uint16_t (*func)(); // endpoint action function
|
|
||||||
uint16_t status; // status flags
|
|
||||||
unsigned rx_cnt : 10; // received data counter
|
|
||||||
unsigned tx_flag : 1; // transmission flag
|
|
||||||
unsigned rx_flag : 1; // reception flag
|
|
||||||
unsigned setup_flag : 1; // this is setup packet (only for EP0)
|
|
||||||
} ep_t;
|
|
||||||
|
|
||||||
// USB status & its address
|
|
||||||
typedef struct {
|
|
||||||
uint8_t USB_Status;
|
|
||||||
uint16_t USB_Addr;
|
|
||||||
}usb_dev_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t dwDTERate;
|
|
||||||
uint8_t bCharFormat;
|
|
||||||
#define USB_CDC_1_STOP_BITS 0
|
|
||||||
#define USB_CDC_1_5_STOP_BITS 1
|
|
||||||
#define USB_CDC_2_STOP_BITS 2
|
|
||||||
uint8_t bParityType;
|
|
||||||
#define USB_CDC_NO_PARITY 0
|
|
||||||
#define USB_CDC_ODD_PARITY 1
|
|
||||||
#define USB_CDC_EVEN_PARITY 2
|
|
||||||
#define USB_CDC_MARK_PARITY 3
|
|
||||||
#define USB_CDC_SPACE_PARITY 4
|
|
||||||
uint8_t bDataBits;
|
|
||||||
} __attribute__ ((packed)) usb_LineCoding;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t bmRequestType;
|
|
||||||
uint8_t bNotificationType;
|
|
||||||
uint16_t wValue;
|
|
||||||
uint16_t wIndex;
|
|
||||||
uint16_t wLength;
|
|
||||||
} __attribute__ ((packed)) usb_cdc_notification;
|
|
||||||
|
|
||||||
extern ep_t endpoints[];
|
|
||||||
|
|
||||||
void USB_Init();
|
|
||||||
uint8_t USB_GetState();
|
|
||||||
int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t (*func)(ep_t ep));
|
|
||||||
void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size);
|
|
||||||
void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size);
|
|
||||||
int EP_Read(uint8_t number, uint16_t *buf);
|
|
||||||
usb_LineCoding getLineCoding();
|
|
||||||
|
|
||||||
void WEAK linecoding_handler(usb_LineCoding *lc);
|
|
||||||
void WEAK clstate_handler(uint16_t val);
|
|
||||||
void WEAK break_handler();
|
|
||||||
void WEAK vendor_handler(config_pack_t *packet);
|
|
||||||
|
|
||||||
#endif // __USB_LIB_H__
|
|
||||||
@ -45,8 +45,8 @@
|
|||||||
#include <string.h> // memcpy
|
#include <string.h> // memcpy
|
||||||
|
|
||||||
// max amount of records stored: Config & Logs
|
// max amount of records stored: Config & Logs
|
||||||
int maxCnum = FLASH_BLOCK_SIZE / sizeof(user_conf);
|
uint32_t maxCnum = FLASH_BLOCK_SIZE / sizeof(user_conf);
|
||||||
int maxLnum = FLASH_BLOCK_SIZE / sizeof(user_conf);
|
uint32_t maxLnum = FLASH_BLOCK_SIZE / sizeof(user_conf);
|
||||||
|
|
||||||
// common structure for all datatypes stored
|
// common structure for all datatypes stored
|
||||||
/*typedef struct {
|
/*typedef struct {
|
||||||
@ -54,15 +54,13 @@ int maxLnum = FLASH_BLOCK_SIZE / sizeof(user_conf);
|
|||||||
} flash_storage;*/
|
} flash_storage;*/
|
||||||
|
|
||||||
#define USERCONF_INITIALIZER { \
|
#define USERCONF_INITIALIZER { \
|
||||||
/* .magick = 0xAB, */ \
|
|
||||||
.userconf_sz = sizeof(user_conf) \
|
.userconf_sz = sizeof(user_conf) \
|
||||||
,.dist_min = LIDAR_MIN_DIST \
|
,.dist_min = LIDAR_MIN_DIST \
|
||||||
,.dist_max = LIDAR_MAX_DIST \
|
,.dist_max = LIDAR_MAX_DIST \
|
||||||
,.trigstate = 0 \
|
,.trigstate = 0 \
|
||||||
,.trigpause = {400, 400, 400, 300, 300} \
|
,.trigpause = {400, 400, 400, 300} \
|
||||||
,.ADC_min = ADC_MIN_VAL \
|
|
||||||
,.ADC_max = ADC_MAX_VAL \
|
|
||||||
,.USART_speed = USART1_DEFAULT_SPEED \
|
,.USART_speed = USART1_DEFAULT_SPEED \
|
||||||
|
,.LIDAR_speed = LIDAR_DEFAULT_SPEED \
|
||||||
,.defflags = 0 \
|
,.defflags = 0 \
|
||||||
,.NLfreeWarn = 100 \
|
,.NLfreeWarn = 100 \
|
||||||
}
|
}
|
||||||
@ -74,10 +72,11 @@ __attribute__ ((section(".myvars"))) const user_conf *Flash_Data;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static int erase_flash(const void*, const void*);
|
static int erase_flash(const void*, const void*);
|
||||||
static int write2flash(const void*, const void*, int);
|
static int write2flash(const void*, const void*, uint32_t);
|
||||||
|
|
||||||
const user_conf *Flash_Data = (const user_conf *)&__varsstart;
|
const user_conf *Flash_Data = (const user_conf *)&__varsstart;
|
||||||
const event_log *logsstart = (event_log*) &__logsstart;
|
const event_log *logsstart = (event_log*) &__logsstart;
|
||||||
|
TODO("Add to event_log a comment - up to 8 chars")
|
||||||
|
|
||||||
user_conf the_conf = USERCONF_INITIALIZER;
|
user_conf the_conf = USERCONF_INITIALIZER;
|
||||||
|
|
||||||
@ -93,15 +92,13 @@ static int currentlogidx = -1; // index of current logs record
|
|||||||
* @param stor_size - size of structure to search
|
* @param stor_size - size of structure to search
|
||||||
* @return index of non-empty cell or -1
|
* @return index of non-empty cell or -1
|
||||||
*/
|
*/
|
||||||
static int binarySearch(int l, int r, uint8_t *start, int stor_size){
|
static int binarySearch(int r, const uint8_t *start, int stor_size){
|
||||||
/*DBG("start: "); printuhex(1, (uint32_t)start);
|
int l = 0;
|
||||||
DBG("\nsizeof: "); printu(1, stor_size);
|
|
||||||
newline();*/
|
|
||||||
while(r >= l){
|
while(r >= l){
|
||||||
int mid = l + (r - l) / 2;
|
int mid = l + (r - l) / 2;
|
||||||
uint8_t *s = start + mid * stor_size;
|
const uint8_t *s = start + mid * stor_size;
|
||||||
if(*((uint16_t*)s) == stor_size){
|
if(*((const uint16_t*)s) == stor_size){
|
||||||
if(*((uint16_t*)(s + stor_size)) == 0xffff){
|
if(*((const uint16_t*)(s + stor_size)) == 0xffff){
|
||||||
return mid;
|
return mid;
|
||||||
}else{ // element is to the right
|
}else{ // element is to the right
|
||||||
l = mid + 1;
|
l = mid + 1;
|
||||||
@ -127,11 +124,11 @@ void flashstorage_init(){
|
|||||||
//SEND("\nmaxLnum="); printu(1, maxLnum);
|
//SEND("\nmaxLnum="); printu(1, maxLnum);
|
||||||
}
|
}
|
||||||
// -1 if there's no data at all & flash is clear; maxnum-1 if flash is full
|
// -1 if there's no data at all & flash is clear; maxnum-1 if flash is full
|
||||||
currentconfidx = binarySearch(0, maxCnum-2, (uint8_t*)Flash_Data, sizeof(user_conf));
|
currentconfidx = binarySearch((int)maxCnum-2, (const uint8_t*)Flash_Data, sizeof(user_conf));
|
||||||
if(currentconfidx > -1){
|
if(currentconfidx > -1){
|
||||||
memcpy(&the_conf, &Flash_Data[currentconfidx], sizeof(user_conf));
|
memcpy(&the_conf, &Flash_Data[currentconfidx], sizeof(user_conf));
|
||||||
}
|
}
|
||||||
currentlogidx = binarySearch(0, maxLnum-2, (uint8_t*)logsstart, sizeof(event_log));
|
currentlogidx = binarySearch((int)maxLnum-2, (const uint8_t*)logsstart, sizeof(event_log));
|
||||||
}
|
}
|
||||||
|
|
||||||
// store new configuration
|
// store new configuration
|
||||||
@ -139,12 +136,12 @@ void flashstorage_init(){
|
|||||||
int store_userconf(){
|
int store_userconf(){
|
||||||
// maxnum - 3 means that there always should be at least one empty record after last data
|
// maxnum - 3 means that there always should be at least one empty record after last data
|
||||||
// for binarySearch() checking that there's nothing more after it!
|
// for binarySearch() checking that there's nothing more after it!
|
||||||
if(currentconfidx > maxCnum - 3){ // there's no more place
|
if(currentconfidx > (int)maxCnum - 3){ // there's no more place
|
||||||
currentconfidx = 0;
|
currentconfidx = 0;
|
||||||
DBG("Need to erase flash!");
|
DBG("Need to erase flash!");
|
||||||
if(erase_flash(Flash_Data, logsstart)) return 1;
|
if(erase_flash(Flash_Data, logsstart)) return 1;
|
||||||
}else ++currentconfidx; // take next data position (0 - within first run after firmware flashing)
|
}else ++currentconfidx; // take next data position (0 - within first run after firmware flashing)
|
||||||
return write2flash(&Flash_Data[currentconfidx], &the_conf, sizeof(the_conf));
|
return write2flash((const void*)&Flash_Data[currentconfidx], &the_conf, sizeof(the_conf));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -157,27 +154,21 @@ int store_log(event_log *L){
|
|||||||
currentlogidx = -1;
|
currentlogidx = -1;
|
||||||
return erase_flash(logsstart, NULL);
|
return erase_flash(logsstart, NULL);
|
||||||
}
|
}
|
||||||
if(currentlogidx > maxLnum - 3){ // there's no more place
|
if(currentlogidx > (int)maxLnum - 3){ // there's no more place
|
||||||
/*currentlogidx = 0;
|
/*currentlogidx = 0;
|
||||||
DBG("Need to erase flash!");
|
DBG("Need to erase flash!");
|
||||||
if(erase_flash(logsstart, NULL)) return 1;*/
|
if(erase_flash(logsstart, NULL)) return 1;*/
|
||||||
// prevent automatic logs erasing!
|
// prevent automatic logs erasing!
|
||||||
USB_send("\n\nERROR!\nCan't save logs: delete old manually!!!\n");
|
sendstring("\n\nERROR!\nCan't save logs: delete old manually!!!\n");
|
||||||
return 1;
|
return 1;
|
||||||
}else ++currentlogidx; // take next data position (0 - within first run after firmware flashing)
|
}else ++currentlogidx; // take next data position (0 - within first run after firmware flashing)
|
||||||
// put warning if there's little space
|
// put warning if there's little space
|
||||||
if(currentlogidx + the_conf.NLfreeWarn > maxLnum - 3){
|
if(currentlogidx + the_conf.NLfreeWarn > (int)maxLnum - 3){
|
||||||
uint32_t nfree = maxLnum - 2 - currentlogidx;
|
uint32_t nfree = maxLnum - 2 - (uint32_t)currentlogidx;
|
||||||
USB_send("\n\nWARNING!\nCan store only ");
|
sendstring("\n\nWARNING!\nCan store only ");
|
||||||
USB_send(u2str(nfree));
|
sendstring(u2str(nfree));
|
||||||
USB_send(" logs!\n\n");
|
sendstring(" logs!\n\n");
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
USB_send("Stored #"); USB_send(u2str(currentlogidx));
|
|
||||||
USB_send(", max="); USB_send(u2str(maxLnum));
|
|
||||||
USB_send(", warn="); USB_send(u2str(the_conf.NLfreeWarn));
|
|
||||||
USB_send("\n");
|
|
||||||
*/
|
|
||||||
return write2flash(&logsstart[currentlogidx], L, sizeof(event_log));
|
return write2flash(&logsstart[currentlogidx], L, sizeof(event_log));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,30 +194,36 @@ int dump_log(int start, int Nlogs){
|
|||||||
const event_log *l = logsstart + start;
|
const event_log *l = logsstart + start;
|
||||||
for(int i = start; i < nlast; ++i, ++l){
|
for(int i = start; i < nlast; ++i, ++l){
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
USB_send(get_trigger_shot(i, l));
|
sendstring(get_trigger_shot(i, l));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write2flash(const void *start, const void *wrdata, int stor_size){
|
static int write2flash(const void *start, const void *wrdata, uint32_t stor_size){
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if (FLASH->CR & FLASH_CR_LOCK){ // unloch flash
|
if (FLASH->CR & FLASH_CR_LOCK){ // unloch flash
|
||||||
FLASH->KEYR = FLASH_KEY1;
|
FLASH->KEYR = FLASH_KEY1;
|
||||||
FLASH->KEYR = FLASH_KEY2;
|
FLASH->KEYR = FLASH_KEY2;
|
||||||
}
|
}
|
||||||
while (FLASH->SR & FLASH_SR_BSY);
|
while (FLASH->SR & FLASH_SR_BSY);
|
||||||
if(FLASH->SR & FLASH_SR_WRPRTERR) return 1; // write protection
|
if(FLASH->SR & FLASH_SR_WRPRTERR){
|
||||||
|
DBG("Can't remove write protection");
|
||||||
|
return 1; // write protection
|
||||||
|
}
|
||||||
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; // clear all flags
|
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; // clear all flags
|
||||||
FLASH->CR |= FLASH_CR_PG;
|
FLASH->CR |= FLASH_CR_PG;
|
||||||
uint16_t *data = (uint16_t*) wrdata;
|
const uint16_t *data = (const uint16_t*) wrdata;
|
||||||
uint16_t *address = (uint16_t*) start;
|
volatile uint16_t *address = (volatile uint16_t*) start;
|
||||||
uint32_t i, count = (stor_size + 1) / 2;
|
uint32_t i, count = (stor_size + 1) / 2;
|
||||||
for (i = 0; i < count; ++i){
|
for (i = 0; i < count; ++i){
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
*(volatile uint16_t*)(address + i) = data[i];
|
*(volatile uint16_t*)(address + i) = data[i];
|
||||||
while (FLASH->SR & FLASH_SR_BSY);
|
while (FLASH->SR & FLASH_SR_BSY);
|
||||||
if(FLASH->SR & FLASH_SR_PGERR) ret = 1; // program error - meet not 0xffff
|
if(FLASH->SR & FLASH_SR_PGERR){
|
||||||
else while (!(FLASH->SR & FLASH_SR_EOP));
|
ret = 1; // program error - meet not 0xffff
|
||||||
|
DBG("FLASH_SR_PGERR");
|
||||||
|
break;
|
||||||
|
}else while (!(FLASH->SR & FLASH_SR_EOP));
|
||||||
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR;
|
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR;
|
||||||
}
|
}
|
||||||
FLASH->CR &= ~(FLASH_CR_PG);
|
FLASH->CR &= ~(FLASH_CR_PG);
|
||||||
@ -254,7 +251,7 @@ static int erase_flash(const void *start, const void *end){
|
|||||||
if(nblocks == 0 || nblocks >= FLASH_SIZE) return 1;
|
if(nblocks == 0 || nblocks >= FLASH_SIZE) return 1;
|
||||||
for(uint32_t i = 0; i < nblocks; ++i){
|
for(uint32_t i = 0; i < nblocks; ++i){
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
SEND("Try to erase page #"); printu(1,i); newline();
|
SEND("Try to erase page #"); printu(1,i); newline(1);
|
||||||
#endif
|
#endif
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
/* (1) Wait till no operation is on going */
|
/* (1) Wait till no operation is on going */
|
||||||
@ -311,11 +308,11 @@ void addNrecs(int N){
|
|||||||
SEND("Try to store userconf for "); printu(1, N); SEND(" times\n");
|
SEND("Try to store userconf for "); printu(1, N); SEND(" times\n");
|
||||||
for(int i = 0; i < N; ++i){
|
for(int i = 0; i < N; ++i){
|
||||||
if(store_userconf()){
|
if(store_userconf()){
|
||||||
SEND("Error @ "); printu(1, i); newline();
|
SEND("Error @ "); printu(1, i); newline(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SEND("Curr idx: "); printu(1, currentconfidx); newline();
|
SEND("Curr idx: "); printu(1, currentconfidx); newline(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -37,14 +37,13 @@
|
|||||||
typedef struct __attribute__((packed, aligned(4))){
|
typedef struct __attribute__((packed, aligned(4))){
|
||||||
uint16_t userconf_sz; // "magick number"
|
uint16_t userconf_sz; // "magick number"
|
||||||
uint16_t NLfreeWarn; // warn user when there's less free log records than NLfreeWarn
|
uint16_t NLfreeWarn; // warn user when there's less free log records than NLfreeWarn
|
||||||
int16_t ADC_min; // min&max values of ADC (shot when ADval > ADC_min && < ADC_max)
|
|
||||||
int16_t ADC_max; // !!! BOTH ARE SIGNED! so you can include 0 & 4096
|
|
||||||
uint8_t trigstate; // level in `triggered` state
|
uint8_t trigstate; // level in `triggered` state
|
||||||
uint8_t defflags; // default flags
|
uint8_t defflags; // default flags
|
||||||
uint32_t dist_min; // minimal distance for LIDAR
|
uint16_t dist_min; // minimal distance for LIDAR
|
||||||
uint32_t dist_max; // maximal -//-
|
uint16_t dist_max; // maximal -//-
|
||||||
uint32_t USART_speed; // USART1 speed (115200 by default)
|
uint32_t USART_speed; // USART1 speed (115200 by default)
|
||||||
int32_t trigpause[TRIGGERS_AMOUNT]; // pause (ms) for false shots
|
uint32_t LIDAR_speed; // USART3 speed (115200 by default)
|
||||||
|
uint16_t trigpause[TRIGGERS_AMOUNT]; // pause (ms) for false shots
|
||||||
} user_conf;
|
} user_conf;
|
||||||
|
|
||||||
// values for user_conf.defflags:
|
// values for user_conf.defflags:
|
||||||
@ -54,7 +53,8 @@ typedef struct __attribute__((packed, aligned(4))){
|
|||||||
#define FLAG_STRENDRN (1 << 1)
|
#define FLAG_STRENDRN (1 << 1)
|
||||||
// proxy GPS messages over USART1
|
// proxy GPS messages over USART1
|
||||||
#define FLAG_GPSPROXY (1 << 2)
|
#define FLAG_GPSPROXY (1 << 2)
|
||||||
|
// USART3 works as regular TTY instead of LIDAR
|
||||||
|
#define FLAG_NOLIDAR (1 << 3)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* struct to save events logs
|
* struct to save events logs
|
||||||
@ -70,7 +70,7 @@ typedef struct __attribute__((packed, aligned(4))){
|
|||||||
extern user_conf the_conf;
|
extern user_conf the_conf;
|
||||||
extern const user_conf *Flash_Data;
|
extern const user_conf *Flash_Data;
|
||||||
extern const event_log *logsstart;
|
extern const event_log *logsstart;
|
||||||
extern int maxCnum, maxLnum;
|
extern uint32_t maxCnum, maxLnum;
|
||||||
// data from ld-file
|
// data from ld-file
|
||||||
extern uint32_t _varslen, __varsstart, __logsstart;
|
extern uint32_t _varslen, __varsstart, __logsstart;
|
||||||
|
|
||||||
|
|||||||
@ -22,8 +22,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "hardware.h"
|
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
|
#include "hardware.h"
|
||||||
#include "lidar.h"
|
#include "lidar.h"
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
@ -53,29 +53,30 @@ static inline void gpio_setup(){
|
|||||||
LED_on(); // turn ON LED0 @start
|
LED_on(); // turn ON LED0 @start
|
||||||
LED1_off(); // turn off LED1 @start
|
LED1_off(); // turn off LED1 @start
|
||||||
USBPU_OFF(); // turn off USB pullup @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 enable EXTI & so on
|
||||||
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<<1)|(1<<15);
|
||||||
// buzzer (PC13): pushpull output
|
// buzzer (PC13): pushpull output
|
||||||
GPIOC->CRH = CRH(13, CNF_PPOUTPUT|MODE_SLOW);
|
GPIOC->CRH = CRH(13, CNF_PPOUTPUT|MODE_SLOW);
|
||||||
// Set leds (PB8) as opendrain output
|
// Set leds (PB8/9) 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
|
||||||
GPIOA->CRL = CRL(1, CNF_PUDINPUT|MODE_INPUT);
|
GPIOA->CRL = CRL(1, CNF_PUDINPUT|MODE_INPUT);
|
||||||
// Set USB pullup (PA15) - opendrain output
|
// Set USB pullup (PA15) - opendrain output
|
||||||
GPIOA->CRH = CRH(15, CNF_ODOUTPUT|MODE_SLOW);
|
GPIOA->CRH = CRH(15, CNF_ODOUTPUT|MODE_SLOW);
|
||||||
// ---------------------> config-depengent block, interrupts & pullup inputs:
|
// Trigger inputs
|
||||||
GPIOA->CRH |= CRH(13, CNF_PUDINPUT|MODE_INPUT) | CRH(14, CNF_PUDINPUT|MODE_INPUT);
|
GPIOA->CRH |= CRH(13, CNF_PUDINPUT|MODE_INPUT) | CRH(14, CNF_PUDINPUT|MODE_INPUT);
|
||||||
GPIOA->CRL |= CRL(4, CNF_PUDINPUT|MODE_INPUT);
|
GPIOA->CRL |= CRL(4, CNF_PUDINPUT|MODE_INPUT);
|
||||||
// <---------------------
|
|
||||||
// EXTI: all three EXTI are on PA -> AFIO_EXTICRx = 0
|
// EXTI: all three EXTI are on PA -> AFIO_EXTICRx = 0
|
||||||
// interrupt on pulse front: buttons - 1->0, PPS - 0->1
|
// interrupt on pulse front: buttons - 1->0, PPS - 0->1
|
||||||
EXTI->IMR = EXTI_IMR_MR1;
|
EXTI->IMR = EXTI_IMR_MR1; // mask PA1
|
||||||
EXTI->RTSR = EXTI_RTSR_TR1; // rising trigger
|
// interrupt on pulse front: buttons - 1->0, PPS - 0->1
|
||||||
// PA4/PA13/PA14 - buttons
|
EXTI->RTSR = EXTI_RTSR_TR1; // rising trigger for PPS
|
||||||
|
// PA4/PA13/PA14 - triggers
|
||||||
for(int i = 0; i < DIGTRIG_AMOUNT; ++i){
|
for(int i = 0; i < DIGTRIG_AMOUNT; ++i){
|
||||||
uint16_t pin = trigpin[i];
|
uint16_t pin = trigpin[i];
|
||||||
// fill trigstate array
|
// fill trigstate array
|
||||||
@ -89,12 +90,9 @@ static inline void gpio_setup(){
|
|||||||
EXTI->FTSR |= pin;
|
EXTI->FTSR |= pin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ---------------------> config-depengent block, interrupts & pullup inputs:
|
|
||||||
// !!! change AFIO_EXTICRx if some triggers not @GPIOA
|
|
||||||
NVIC_EnableIRQ(EXTI4_IRQn);
|
NVIC_EnableIRQ(EXTI4_IRQn);
|
||||||
NVIC_EnableIRQ(EXTI15_10_IRQn);
|
NVIC_EnableIRQ(EXTI15_10_IRQn);
|
||||||
// <---------------------
|
NVIC_EnableIRQ(EXTI1_IRQn); // enable PPS interrupt
|
||||||
NVIC_EnableIRQ(EXTI1_IRQn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void adc_setup(){
|
static inline void adc_setup(){
|
||||||
@ -104,12 +102,12 @@ static inline void adc_setup(){
|
|||||||
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
|
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
|
||||||
RCC->CFGR &= ~(RCC_CFGR_ADCPRE);
|
RCC->CFGR &= ~(RCC_CFGR_ADCPRE);
|
||||||
RCC->CFGR |= RCC_CFGR_ADCPRE_DIV8; // ADC clock = RCC / 8
|
RCC->CFGR |= RCC_CFGR_ADCPRE_DIV8; // ADC clock = RCC / 8
|
||||||
// sampling time - 239.5 cycles for channels 8, 16 and 17
|
// sampling time - 239.5 cycles for channels 16 and 17
|
||||||
ADC1->SMPR2 = ADC_SMPR2_SMP8;
|
|
||||||
ADC1->SMPR1 = ADC_SMPR1_SMP16 | ADC_SMPR1_SMP17;
|
ADC1->SMPR1 = ADC_SMPR1_SMP16 | ADC_SMPR1_SMP17;
|
||||||
// we have three conversions in group -> ADC1->SQR1[L] = 2, order: 8->16->17
|
// we have three conversions in group -> ADC1->SQR1[L] = 2, order: 16->17
|
||||||
ADC1->SQR3 = 8 | (16<<5) | (17<<10);
|
// Tsens == 16, Vdd == 17
|
||||||
ADC1->SQR1 = ADC_SQR1_L_1;
|
ADC1->SQR3 = (16<<0) | (17<<5);
|
||||||
|
ADC1->SQR1 = ADC_SQR1_L_0; // 2 conversions
|
||||||
ADC1->CR1 |= ADC_CR1_SCAN; // scan mode
|
ADC1->CR1 |= ADC_CR1_SCAN; // scan mode
|
||||||
// DMA configuration
|
// DMA configuration
|
||||||
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
|
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
|
||||||
@ -136,12 +134,6 @@ void hw_setup(){
|
|||||||
adc_setup();
|
adc_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void exti1_isr(){ // PPS - PA1
|
|
||||||
systick_correction();
|
|
||||||
LED_off(); // turn off LED0 @ each PPS
|
|
||||||
EXTI->PR = EXTI_PR_PR1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static trigtime trgtm;
|
static trigtime trgtm;
|
||||||
void savetrigtime(){
|
void savetrigtime(){
|
||||||
trgtm.millis = Timer;
|
trgtm.millis = Timer;
|
||||||
@ -177,11 +169,9 @@ void fillunshotms(){
|
|||||||
if(len > MAX_TRIG_LEN){
|
if(len > MAX_TRIG_LEN){
|
||||||
triglen[i] = -1;
|
triglen[i] = -1;
|
||||||
rdy = 1;
|
rdy = 1;
|
||||||
}else triglen[i] = (uint16_t) len;
|
}else triglen[i] = (int16_t) len;
|
||||||
if(i == LIDAR_TRIGGER){
|
if(i == LIDAR_TRIGGER){
|
||||||
if(!parse_lidar_data(NULL)) rdy = 1;
|
if(!parse_lidar_data(NULL)) rdy = 1;
|
||||||
}else if(i == ADC_TRIGGER){
|
|
||||||
if(!chkADCtrigger()) rdy = 1;
|
|
||||||
}else{
|
}else{
|
||||||
uint8_t pinval = (trigport[i]->IDR & trigpin[i]) ? 1 : 0;
|
uint8_t pinval = (trigport[i]->IDR & trigpin[i]) ? 1 : 0;
|
||||||
if(pinval != trigstate[i]) rdy = 1; // trigger is OFF
|
if(pinval != trigstate[i]) rdy = 1; // trigger is OFF
|
||||||
@ -195,6 +185,12 @@ void fillunshotms(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void exti1_isr(){ // PPS - PA1
|
||||||
|
systick_correction();
|
||||||
|
LED_off(); // turn off LED0 @ each PPS
|
||||||
|
EXTI->PR = EXTI_PR_PR1;
|
||||||
|
}
|
||||||
|
|
||||||
void exti4_isr(){ // PA4 - trigger[2]
|
void exti4_isr(){ // PA4 - trigger[2]
|
||||||
savetrigtime();
|
savetrigtime();
|
||||||
fillshotms(2);
|
fillshotms(2);
|
||||||
|
|||||||
@ -27,11 +27,23 @@
|
|||||||
#include "stm32f1.h"
|
#include "stm32f1.h"
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
|
|
||||||
|
#ifdef EBUG
|
||||||
|
#define DO_PRAGMA(x) _Pragma (#x)
|
||||||
|
#define TODO(x) DO_PRAGMA(message #x)
|
||||||
|
#else
|
||||||
|
#define TODO(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// only 2 ADC channels used: Tmcu and Vdd
|
||||||
|
#define NUMBER_OF_ADC_CHANNELS (2)
|
||||||
|
#define ADC_TMCU_CHANNEL (0)
|
||||||
|
#define ADC_VDD_CHANNEL (1)
|
||||||
|
|
||||||
// onboard LEDs - PB8/PB9
|
// onboard LEDs - PB8/PB9
|
||||||
#define LED0_port GPIOB
|
#define LED0_port GPIOB
|
||||||
#define LED0_pin (1<<8)
|
#define LED0_pin (1<<9)
|
||||||
#define LED1_port GPIOB
|
#define LED1_port GPIOB
|
||||||
#define LED1_pin (1<<9)
|
#define LED1_pin (1<<8)
|
||||||
|
|
||||||
// buzzer (1 - active) - PC13
|
// buzzer (1 - active) - PC13
|
||||||
extern uint8_t buzzer_on;
|
extern uint8_t buzzer_on;
|
||||||
@ -48,12 +60,10 @@ extern uint8_t buzzer_on;
|
|||||||
#define PPS_pin (1<<1)
|
#define PPS_pin (1<<1)
|
||||||
|
|
||||||
// PPS and triggers state
|
// PPS and triggers state
|
||||||
// amount of triggers, should be less than 9; 5 - 0..2 - switches, 3 - LIDAR, 4 - ADC
|
// amount of triggers, should be less than 9; 4 - 0..2 - switches, 3 - LIDAR
|
||||||
#define TRIGGERS_AMOUNT 5
|
#define TRIGGERS_AMOUNT 4
|
||||||
// number of LIDAR trigger
|
// number of LIDAR trigger
|
||||||
#define LIDAR_TRIGGER 3
|
#define LIDAR_TRIGGER 3
|
||||||
// number of ADC trigger
|
|
||||||
#define ADC_TRIGGER 4
|
|
||||||
// amount of digital triggers (on interrupts)
|
// amount of digital triggers (on interrupts)
|
||||||
#define DIGTRIG_AMOUNT 3
|
#define DIGTRIG_AMOUNT 3
|
||||||
// max length of trigger event (ms)
|
// max length of trigger event (ms)
|
||||||
@ -97,6 +107,8 @@ extern trigtime shottime[TRIGGERS_AMOUNT];
|
|||||||
extern int16_t triglen[TRIGGERS_AMOUNT];
|
extern int16_t triglen[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;
|
||||||
|
// Tms value when they shot
|
||||||
|
extern uint32_t shotms[TRIGGERS_AMOUNT];
|
||||||
|
|
||||||
void chk_buzzer();
|
void chk_buzzer();
|
||||||
void hw_setup();
|
void hw_setup();
|
||||||
|
|||||||
@ -1,127 +0,0 @@
|
|||||||
"Source:","/home/eddy/Docs/SAO/ELECTRONICS/STM32/F1-srcs/chronometer/kicad/chrono/chrono.sch"
|
|
||||||
"Date:","÷Ô 09 ÉÀÌ 2019 08:40:12"
|
|
||||||
"Tool:","Eeschema (6.0.0-rc1-dev-1613-ga55d9819b)"
|
|
||||||
"Generator:","/usr/local/share/kicad/plugins/bom_csv_grouped_by_value.py"
|
|
||||||
"Component Count:","68"
|
|
||||||
|
|
||||||
"Individual Components:"
|
|
||||||
|
|
||||||
"Item","Qty","Reference(s)","Value","LibPart","Footprint","Datasheet","Manufacturer"
|
|
||||||
"","","BZ1","Buzzer","Device:Buzzer","Buzzer_Beeper:Buzzer_12x9.5RM7.6","~",""
|
|
||||||
"","","C1","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","C2","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","C3","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","C4","47u","stm32-rescue:CP","Capacitor_Tantalum_SMD:CP_EIA-3216-18_Kemet-A_Pad1.58x1.35mm_HandSolder","",""
|
|
||||||
"","","C5","10u","Device:C","Capacitor_SMD:C_1206_3216Metric_Pad1.42x1.75mm_HandSolder","~",""
|
|
||||||
"","","C6","100u","stm32-rescue:CP","Capacitor_THT:CP_Radial_D8.0mm_P3.50mm","",""
|
|
||||||
"","","C7","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","C8","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","C9","47u","stm32-rescue:CP","Capacitor_Tantalum_SMD:CP_EIA-3216-18_Kemet-A_Pad1.58x1.35mm_HandSolder","",""
|
|
||||||
"","","C10","12","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","C11","12","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","C12","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","C13","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","C14","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","C15","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","D1","MM3Z7V5","Device:D_Zener","Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~",""
|
|
||||||
"","","D2","SS14","Device:D_Schottky","Diode_SMD:D_SMA_Handsoldering","~",""
|
|
||||||
"","","D3","1n5822","stm32-rescue:D","Diode_THT:D_DO-201_P12.70mm_Horizontal","",""
|
|
||||||
"","","D4","LED0","stm32-rescue:LED-RESCUE-stm32","LED_THT:LED_D5.0mm","",""
|
|
||||||
"","","D5","LED1","stm32-rescue:LED-RESCUE-stm32","LED_THT:LED_D5.0mm","",""
|
|
||||||
"","","J1","Power 12V","Connector_Generic:Conn_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2-5.08_1x02_P5.08mm_Horizontal","~",""
|
|
||||||
"","","J2","+5Vout","Connector_Generic:Conn_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2-5.08_1x02_P5.08mm_Horizontal","~",""
|
|
||||||
"","","J3","Ext_trig0","Connector_Generic:Conn_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2-5.08_1x02_P5.08mm_Horizontal","~",""
|
|
||||||
"","","J4","LIDAR","Connector:Conn_01x04_Female","Connector_PinSocket_2.54mm:PinSocket_1x04_P2.54mm_Vertical","~",""
|
|
||||||
"","","J5","Ext_trig1","Connector_Generic:Conn_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2-5.08_1x02_P5.08mm_Horizontal","~",""
|
|
||||||
"","","J6","Ext_trig2","Connector_Generic:Conn_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2-5.08_1x02_P5.08mm_Horizontal","~",""
|
|
||||||
"","","J7","USART1","Connector:Conn_01x03_Female","Connector_PinSocket_2.54mm:PinSocket_1x03_P2.54mm_Vertical","~",""
|
|
||||||
"","","J8","SPI","Connector:Conn_01x05_Female","Connector_PinSocket_2.54mm:PinSocket_1x05_P2.54mm_Vertical","~",""
|
|
||||||
"","","J9","I2C1","Connector:Conn_01x04_Female","Connector_PinSocket_2.54mm:PinSocket_1x04_P2.54mm_Vertical","~",""
|
|
||||||
"","","L1","100u","stm32-rescue:L","Inductor_SMD:L_12x12mm_H4.5mm","",""
|
|
||||||
"","","P1","USB_B","stm32-rescue:USB_A-RESCUE-stm32","Connectors_USB:USB_B_OST_USB-B1HSxx_Horizontal","",""
|
|
||||||
"","","Q1","AO3407","stm32-rescue:Q_PMOS_GSD","TO_SOT_Packages_SMD:SOT-23_Handsoldering","",""
|
|
||||||
"","","Q2","DTA114Y","Transistor_BJT:DTA114Y","TO_SOT_Packages_SMD:SOT-323_SC-70_Handsoldering","",""
|
|
||||||
"","","Q3","Q_NMOS_GSD","Device:Q_NMOS_GSD","Package_TO_SOT_SMD:SOT-23","~",""
|
|
||||||
"","","R1","10k","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","R2","510","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~",""
|
|
||||||
"","","R3","22","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","R4","22","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","R5","10k","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","R6","1k5","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","R7","22","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~",""
|
|
||||||
"","","R8","330","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","R9","330","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","R10","330","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~",""
|
|
||||||
"","","R11","4k7","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~",""
|
|
||||||
"","","R12","4k7","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~",""
|
|
||||||
"","","R13","100k","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","R14","330","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~",""
|
|
||||||
"","","R15","4k7","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~",""
|
|
||||||
"","","R16","4k7","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~",""
|
|
||||||
"","","R17","2k2","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~",""
|
|
||||||
"","","R18","100k","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"","","R19","4k7","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~",""
|
|
||||||
"","","R20","4k7","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~",""
|
|
||||||
"","","R21","10k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~",""
|
|
||||||
"","","RV1","R_POT","Device:R_POT","Potentiometer_THT:Potentiometer_Bourns_3296W_Vertical","~",""
|
|
||||||
"","","SW1","Reset","Switch:SW_Push","Buttons_Switches_SMD:SW_SPST_FSMSM","",""
|
|
||||||
"","","SW2","Boot","Switch:SW_Push","Buttons_Switches_SMD:SW_SPST_FSMSM","",""
|
|
||||||
"","","U1","USBLC6-2SC6","Power_Protection:USBLC6-2SC6","TO_SOT_Packages_SMD:SOT-23-6_Handsoldering","http://www2.st.com/resource/en/datasheet/CD00050750.pdf",""
|
|
||||||
"","","U2","LM2576ADJ","stm32-rescue:LM2576HV","TO_SOT_Packages_THT:TO-220-5_P3.4x3.7mm_StaggerEven_Lead3.8mm_Vertical","","Texas Instruments"
|
|
||||||
"","","U3","L80-R","Chrono:L80-R","chrono:L80-R","",""
|
|
||||||
"","","U4","LM1117-3.3","stm32-rescue:LM1117-3.3-RESCUE-stm32","TO_SOT_Packages_SMD:SOT-223","",""
|
|
||||||
"","","U5","PC817","Isolator:PC817","Package_DIP:DIP-4_W7.62mm","http://www.soselectronic.cz/a_info/resource/d/pc817.pdf",""
|
|
||||||
"","","U6","PC817","Isolator:PC817","Package_DIP:DIP-4_W7.62mm","http://www.soselectronic.cz/a_info/resource/d/pc817.pdf",""
|
|
||||||
"","","U7","STM32F103C6Tx","MCU_ST_STM32F1:STM32F103C6Tx","Package_QFP:LQFP-48_7x7mm_P0.5mm","http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/CD00210843.pdf",""
|
|
||||||
"","","U8","PC817","Isolator:PC817","Package_DIP:DIP-4_W7.62mm","http://www.soselectronic.cz/a_info/resource/d/pc817.pdf",""
|
|
||||||
"","","Y1","8MHz","Device:Crystal","Crystal:Crystal_HC49-U_Vertical","~",""
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"Collated Components:"
|
|
||||||
|
|
||||||
"Item","Qty","Reference(s)","Value","LibPart","Footprint","Datasheet","Manufacturer"
|
|
||||||
"1","1","BZ1","Buzzer","Device:Buzzer","Buzzer_Beeper:Buzzer_12x9.5RM7.6","~",""
|
|
||||||
"2","9","C1, C2, C3, C7, C8, C12, C13, C14, C15","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"3","2","C4, C9","47u","stm32-rescue:CP","Capacitor_Tantalum_SMD:CP_EIA-3216-18_Kemet-A_Pad1.58x1.35mm_HandSolder","",""
|
|
||||||
"4","1","C5","10u","Device:C","Capacitor_SMD:C_1206_3216Metric_Pad1.42x1.75mm_HandSolder","~",""
|
|
||||||
"5","1","C6","100u","stm32-rescue:CP","Capacitor_THT:CP_Radial_D8.0mm_P3.50mm","",""
|
|
||||||
"6","2","C10, C11","12","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"7","1","D1","MM3Z7V5","Device:D_Zener","Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~",""
|
|
||||||
"8","1","D2","SS14","Device:D_Schottky","Diode_SMD:D_SMA_Handsoldering","~",""
|
|
||||||
"9","1","D3","1n5822","stm32-rescue:D","Diode_THT:D_DO-201_P12.70mm_Horizontal","",""
|
|
||||||
"10","1","D4","LED0","stm32-rescue:LED-RESCUE-stm32","LED_THT:LED_D5.0mm","",""
|
|
||||||
"11","1","D5","LED1","stm32-rescue:LED-RESCUE-stm32","LED_THT:LED_D5.0mm","",""
|
|
||||||
"12","1","J1","Power 12V","Connector_Generic:Conn_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2-5.08_1x02_P5.08mm_Horizontal","~",""
|
|
||||||
"13","1","J2","+5Vout","Connector_Generic:Conn_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2-5.08_1x02_P5.08mm_Horizontal","~",""
|
|
||||||
"14","1","J3","Ext_trig0","Connector_Generic:Conn_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2-5.08_1x02_P5.08mm_Horizontal","~",""
|
|
||||||
"15","1","J4","LIDAR","Connector:Conn_01x04_Female","Connector_PinSocket_2.54mm:PinSocket_1x04_P2.54mm_Vertical","~",""
|
|
||||||
"16","1","J5","Ext_trig1","Connector_Generic:Conn_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2-5.08_1x02_P5.08mm_Horizontal","~",""
|
|
||||||
"17","1","J6","Ext_trig2","Connector_Generic:Conn_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2-5.08_1x02_P5.08mm_Horizontal","~",""
|
|
||||||
"18","1","J7","USART1","Connector:Conn_01x03_Female","Connector_PinSocket_2.54mm:PinSocket_1x03_P2.54mm_Vertical","~",""
|
|
||||||
"19","1","J8","SPI","Connector:Conn_01x05_Female","Connector_PinSocket_2.54mm:PinSocket_1x05_P2.54mm_Vertical","~",""
|
|
||||||
"20","1","J9","I2C1","Connector:Conn_01x04_Female","Connector_PinSocket_2.54mm:PinSocket_1x04_P2.54mm_Vertical","~",""
|
|
||||||
"21","1","L1","100u","stm32-rescue:L","Inductor_SMD:L_12x12mm_H4.5mm","",""
|
|
||||||
"22","1","P1","USB_B","stm32-rescue:USB_A-RESCUE-stm32","Connectors_USB:USB_B_OST_USB-B1HSxx_Horizontal","",""
|
|
||||||
"23","1","Q1","AO3407","stm32-rescue:Q_PMOS_GSD","TO_SOT_Packages_SMD:SOT-23_Handsoldering","",""
|
|
||||||
"24","1","Q2","DTA114Y","Transistor_BJT:DTA114Y","TO_SOT_Packages_SMD:SOT-323_SC-70_Handsoldering","",""
|
|
||||||
"25","1","Q3","Q_NMOS_GSD","Device:Q_NMOS_GSD","Package_TO_SOT_SMD:SOT-23","~",""
|
|
||||||
"26","3","R1, R5, R21","10k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~",""
|
|
||||||
"27","1","R2","510","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~",""
|
|
||||||
"28","3","R3, R4, R7","22","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~",""
|
|
||||||
"29","1","R6","1k5","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"30","2","R8, R9","330","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"31","2","R10, R14","330","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~",""
|
|
||||||
"32","6","R11, R12, R15, R16, R19, R20","4k7","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~",""
|
|
||||||
"33","2","R13, R18","100k","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","",""
|
|
||||||
"34","1","R17","2k2","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~",""
|
|
||||||
"35","1","RV1","R_POT","Device:R_POT","Potentiometer_THT:Potentiometer_Bourns_3296W_Vertical","~",""
|
|
||||||
"36","1","SW1","Reset","Switch:SW_Push","Buttons_Switches_SMD:SW_SPST_FSMSM","",""
|
|
||||||
"37","1","SW2","Boot","Switch:SW_Push","Buttons_Switches_SMD:SW_SPST_FSMSM","",""
|
|
||||||
"38","1","U1","USBLC6-2SC6","Power_Protection:USBLC6-2SC6","TO_SOT_Packages_SMD:SOT-23-6_Handsoldering","http://www2.st.com/resource/en/datasheet/CD00050750.pdf",""
|
|
||||||
"39","1","U2","LM2576ADJ","stm32-rescue:LM2576HV","TO_SOT_Packages_THT:TO-220-5_P3.4x3.7mm_StaggerEven_Lead3.8mm_Vertical","","Texas Instruments"
|
|
||||||
"40","1","U3","L80-R","Chrono:L80-R","chrono:L80-R","",""
|
|
||||||
"41","1","U4","LM1117-3.3","stm32-rescue:LM1117-3.3-RESCUE-stm32","TO_SOT_Packages_SMD:SOT-223","",""
|
|
||||||
"42","3","U5, U6, U8","PC817","Isolator:PC817","Package_DIP:DIP-4_W7.62mm","http://www.soselectronic.cz/a_info/resource/d/pc817.pdf",""
|
|
||||||
"43","1","U7","STM32F103C6Tx","MCU_ST_STM32F1:STM32F103C6Tx","Package_QFP:LQFP-48_7x7mm_P0.5mm","http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/CD00210843.pdf",""
|
|
||||||
"44","1","Y1","8MHz","Device:Crystal","Crystal:Crystal_HC49-U_Vertical","~",""
|
|
||||||
|
Can't render this file because it has a wrong number of fields in line 7.
|
@ -1,31 +0,0 @@
|
|||||||
EESchema-LIBRARY Version 2.4
|
|
||||||
#encoding utf-8
|
|
||||||
#
|
|
||||||
# L80-R
|
|
||||||
#
|
|
||||||
DEF L80-R U 0 40 Y Y 1 F N
|
|
||||||
F0 "U" 0 -375 50 H V C CNN
|
|
||||||
F1 "L80-R" 0 425 50 H V C CNN
|
|
||||||
F2 "chrono:L80-R" 0 0 50 H I C CNN
|
|
||||||
F3 "" -550 -50 50 H I C CNN
|
|
||||||
$FPLIST
|
|
||||||
L80-R
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
S -250 350 250 -325 0 1 0 N
|
|
||||||
X RXD 1 -450 250 200 R 50 50 1 1 P
|
|
||||||
X RESET 10 450 50 200 L 50 50 1 1 P
|
|
||||||
X Res 11 450 150 200 L 50 50 1 1 P
|
|
||||||
X Gnd 12 450 250 200 L 50 50 1 1 P
|
|
||||||
X TXD 2 -450 150 200 R 50 50 1 1 P
|
|
||||||
X Gnd 3 -450 50 200 R 50 50 1 1 P
|
|
||||||
X Vcc 4 -450 -50 200 R 50 50 1 1 P
|
|
||||||
X V_BKP 5 -450 -150 200 R 50 50 1 1 P
|
|
||||||
X PPS 6 -450 -250 200 R 50 50 1 1 P
|
|
||||||
X Res 7 450 -250 200 L 50 50 1 1 P
|
|
||||||
X Res 8 450 -150 200 L 50 50 1 1 P
|
|
||||||
X NC 9 450 -50 200 L 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
#End Library
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,54 +0,0 @@
|
|||||||
(module L80-R (layer F.Cu) (tedit 5D162F3C)
|
|
||||||
(fp_text reference U3 (at 0 4) (layer F.SilkS)
|
|
||||||
(effects (font (size 1 1) (thickness 0.15)))
|
|
||||||
)
|
|
||||||
(fp_text value L80-R (at 0 -15) (layer F.Fab)
|
|
||||||
(effects (font (size 1 1) (thickness 0.15)))
|
|
||||||
)
|
|
||||||
(fp_line (start -8 -14) (end -8 3) (layer F.SilkS) (width 0.15))
|
|
||||||
(fp_line (start -8 3) (end 8 3) (layer F.SilkS) (width 0.15))
|
|
||||||
(fp_line (start 8 3) (end 8 -14) (layer F.SilkS) (width 0.15))
|
|
||||||
(fp_line (start 8 -14) (end -8 -14) (layer F.SilkS) (width 0.15))
|
|
||||||
(fp_text user 1 (at 10 3) (layer F.SilkS)
|
|
||||||
(effects (font (size 2.5 2.5) (thickness 0.15)))
|
|
||||||
)
|
|
||||||
(fp_line (start -4 3) (end -4 1) (layer F.SilkS) (width 0.15))
|
|
||||||
(fp_line (start -4 1) (end -8 1) (layer F.SilkS) (width 0.15))
|
|
||||||
(fp_line (start 8 2) (end 7 3) (layer F.SilkS) (width 0.15))
|
|
||||||
(fp_text user Keepout (at 0 -8) (layer F.SilkS)
|
|
||||||
(effects (font (size 1 1) (thickness 0.15)))
|
|
||||||
)
|
|
||||||
(fp_text user area (at 0 -3.5) (layer F.SilkS)
|
|
||||||
(effects (font (size 1 1) (thickness 0.15)))
|
|
||||||
)
|
|
||||||
(fp_line (start -18 -24) (end -18 13) (layer F.SilkS) (width 0.15))
|
|
||||||
(fp_line (start -18 13) (end 18 13) (layer F.SilkS) (width 0.15))
|
|
||||||
(fp_line (start 18 13) (end 18 -24) (layer F.SilkS) (width 0.15))
|
|
||||||
(fp_line (start 18 -24) (end -18 -24) (layer F.SilkS) (width 0.15))
|
|
||||||
(fp_text user "Clear area" (at 0 -22) (layer F.SilkS)
|
|
||||||
(effects (font (size 1 1) (thickness 0.15)))
|
|
||||||
)
|
|
||||||
(fp_text user "Clear area" (at 0 -22) (layer B.SilkS)
|
|
||||||
(effects (font (size 1 1) (thickness 0.15)) (justify mirror))
|
|
||||||
)
|
|
||||||
(fp_line (start -18 -24) (end -18 13) (layer B.SilkS) (width 0.15))
|
|
||||||
(fp_line (start -18 13) (end 18 13) (layer B.SilkS) (width 0.15))
|
|
||||||
(fp_line (start 18 13) (end 18 -24) (layer B.SilkS) (width 0.15))
|
|
||||||
(fp_line (start 18 -24) (end -18 -24) (layer B.SilkS) (width 0.15))
|
|
||||||
(pad 1 smd rect (at 8 0) (size 4 2) (layers F.Cu F.Paste F.Mask))
|
|
||||||
(pad 2 smd rect (at 8 -2.54) (size 4 2) (layers F.Cu F.Paste F.Mask))
|
|
||||||
(pad 3 smd rect (at 8 -5.08) (size 4 2) (layers F.Cu F.Paste F.Mask))
|
|
||||||
(pad 4 smd rect (at 8 -7.62) (size 4 2) (layers F.Cu F.Paste F.Mask))
|
|
||||||
(pad 5 smd rect (at 8 -10.16) (size 4 2) (layers F.Cu F.Paste F.Mask))
|
|
||||||
(pad 6 smd rect (at 8 -12.7) (size 4 2) (layers F.Cu F.Paste F.Mask))
|
|
||||||
(pad 12 smd rect (at -8 0) (size 4 2) (layers F.Cu F.Paste F.Mask))
|
|
||||||
(pad 11 smd rect (at -8 -2.54) (size 4 2) (layers F.Cu F.Paste F.Mask))
|
|
||||||
(pad 10 smd rect (at -8 -5.08) (size 4 2) (layers F.Cu F.Paste F.Mask))
|
|
||||||
(pad 9 smd rect (at -8 -7.62) (size 4 2) (layers F.Cu F.Paste F.Mask))
|
|
||||||
(pad 8 smd rect (at -8 -10.16) (size 4 2) (layers F.Cu F.Paste F.Mask))
|
|
||||||
(pad 7 smd rect (at -8 -12.7) (size 4 2) (layers F.Cu F.Paste F.Mask))
|
|
||||||
(pad ~ smd circle (at 0 -5.5) (size 0.1 0.1) (layers B.Cu)
|
|
||||||
(solder_mask_margin 1.5) (solder_paste_margin 1.5) (clearance 1.3) (zone_connect 0))
|
|
||||||
(pad ~ smd circle (at 0 -5.5) (size 0.1 0.1) (layers F.Cu)
|
|
||||||
(solder_mask_margin 1.5) (solder_paste_margin 1.5) (clearance 1.3) (zone_connect 0))
|
|
||||||
)
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
update=Пн 08 июл 2019 22:10:21
|
|
||||||
version=1
|
|
||||||
last_client=kicad
|
|
||||||
[general]
|
|
||||||
version=1
|
|
||||||
RootSch=
|
|
||||||
BoardNm=
|
|
||||||
[cvpcb]
|
|
||||||
version=1
|
|
||||||
NetIExt=net
|
|
||||||
[eeschema]
|
|
||||||
version=1
|
|
||||||
LibDir=
|
|
||||||
[eeschema/libraries]
|
|
||||||
[pcbnew]
|
|
||||||
version=1
|
|
||||||
PageLayoutDescrFile=
|
|
||||||
LastNetListRead=chrono.net
|
|
||||||
CopperLayerCount=2
|
|
||||||
BoardThickness=1.6
|
|
||||||
AllowMicroVias=0
|
|
||||||
AllowBlindVias=0
|
|
||||||
RequireCourtyardDefinitions=0
|
|
||||||
ProhibitOverlappingCourtyards=1
|
|
||||||
MinTrackWidth=0.2
|
|
||||||
MinViaDiameter=0.4
|
|
||||||
MinViaDrill=0.3
|
|
||||||
MinMicroViaDiameter=0.2
|
|
||||||
MinMicroViaDrill=0.09999999999999999
|
|
||||||
MinHoleToHole=0.25
|
|
||||||
TrackWidth1=0.25
|
|
||||||
TrackWidth2=0.25
|
|
||||||
TrackWidth3=0.5
|
|
||||||
TrackWidth4=1
|
|
||||||
ViaDiameter1=0.8
|
|
||||||
ViaDrill1=0.5
|
|
||||||
ViaDiameter2=0.8
|
|
||||||
ViaDrill2=0.5
|
|
||||||
ViaDiameter3=1.2
|
|
||||||
ViaDrill3=0.6
|
|
||||||
dPairWidth1=0.2
|
|
||||||
dPairGap1=0.25
|
|
||||||
dPairViaGap1=0.25
|
|
||||||
SilkLineWidth=0.12
|
|
||||||
SilkTextSizeV=1
|
|
||||||
SilkTextSizeH=1
|
|
||||||
SilkTextSizeThickness=0.15
|
|
||||||
SilkTextItalic=0
|
|
||||||
SilkTextUpright=1
|
|
||||||
CopperLineWidth=0.2
|
|
||||||
CopperTextSizeV=1.5
|
|
||||||
CopperTextSizeH=1.5
|
|
||||||
CopperTextThickness=0.3
|
|
||||||
CopperTextItalic=0
|
|
||||||
CopperTextUpright=1
|
|
||||||
EdgeCutLineWidth=0.05
|
|
||||||
CourtyardLineWidth=0.05
|
|
||||||
OthersLineWidth=0.15
|
|
||||||
OthersTextSizeV=1
|
|
||||||
OthersTextSizeH=1
|
|
||||||
OthersTextSizeThickness=0.15
|
|
||||||
OthersTextItalic=0
|
|
||||||
OthersTextUpright=1
|
|
||||||
SolderMaskClearance=0.051
|
|
||||||
SolderMaskMinWidth=0.25
|
|
||||||
SolderPasteClearance=0
|
|
||||||
SolderPasteRatio=-0
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,7 +0,0 @@
|
|||||||
(fp_lib_table
|
|
||||||
(lib (name chrono)(type KiCad)(uri ${KIPRJMOD}/chrono.pretty)(options "")(descr ""))
|
|
||||||
(lib (name TerminalBlock_Phoenix)(type KiCad)(uri ${KISYSMOD}/TerminalBlock_Phoenix.pretty)(options "")(descr ""))
|
|
||||||
(lib (name Inductor_SMD)(type KiCad)(uri ${KISYSMOD}/Inductor_SMD.pretty)(options "")(descr ""))
|
|
||||||
(lib (name LED_THT)(type KiCad)(uri ${KISYSMOD}/LED_THT.pretty)(options "")(descr ""))
|
|
||||||
(lib (name Crystal)(type KiCad)(uri ${KISYSMOD}/Crystal.pretty)(options "")(descr ""))
|
|
||||||
)
|
|
||||||
@ -1,694 +0,0 @@
|
|||||||
EESchema-LIBRARY Version 2.4
|
|
||||||
#encoding utf-8
|
|
||||||
#
|
|
||||||
# +3.3V
|
|
||||||
#
|
|
||||||
DEF +3.3V #PWR 0 0 Y Y 1 F P
|
|
||||||
F0 "#PWR" 0 -150 50 H I C CNN
|
|
||||||
F1 "+3.3V" 0 140 50 H V C CNN
|
|
||||||
F2 "" 0 0 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
DRAW
|
|
||||||
P 2 0 1 0 -30 50 0 100 N
|
|
||||||
P 2 0 1 0 0 0 0 100 N
|
|
||||||
P 2 0 1 0 0 100 30 50 N
|
|
||||||
X +3V3 1 0 0 0 U 50 50 1 1 W N
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# +5V
|
|
||||||
#
|
|
||||||
DEF +5V #PWR 0 0 Y Y 1 F P
|
|
||||||
F0 "#PWR" 0 -150 50 H I C CNN
|
|
||||||
F1 "+5V" 0 140 50 H V C CNN
|
|
||||||
F2 "" 0 0 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
DRAW
|
|
||||||
P 2 0 1 0 -30 50 0 100 N
|
|
||||||
P 2 0 1 0 0 0 0 100 N
|
|
||||||
P 2 0 1 0 0 100 30 50 N
|
|
||||||
X +5V 1 0 0 0 U 50 50 1 1 W N
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# 74HC4051
|
|
||||||
#
|
|
||||||
DEF 74HC4051 U 0 10 Y Y 1 F N
|
|
||||||
F0 "U" 0 0 50 H V C CNN
|
|
||||||
F1 "74HC4051" 0 -150 50 H V C CNN
|
|
||||||
F2 "" 0 0 50 H V C CNN
|
|
||||||
F3 "" 0 0 50 H V C CNN
|
|
||||||
$FPLIST
|
|
||||||
SO16
|
|
||||||
TSSOP16
|
|
||||||
SSOP16
|
|
||||||
DHVQFN16
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
S -400 450 400 -450 0 1 0 N
|
|
||||||
X Y4 1 700 -50 300 L 50 50 1 1 B
|
|
||||||
X S1 10 -700 250 300 R 50 50 1 1 I
|
|
||||||
X S0 11 -700 350 300 R 50 50 1 1 I
|
|
||||||
X Y3 12 700 50 300 L 50 50 1 1 B
|
|
||||||
X Y0 13 700 350 300 L 50 50 1 1 B
|
|
||||||
X Y1 14 700 250 300 L 50 50 1 1 B
|
|
||||||
X Y2 15 700 150 300 L 50 50 1 1 B
|
|
||||||
X VCC 16 -700 -100 300 R 50 50 1 1 W
|
|
||||||
X Y6 2 700 -250 300 L 50 50 1 1 B
|
|
||||||
X Z 3 0 -750 300 U 50 50 1 1 B
|
|
||||||
X Y7 4 700 -350 300 L 50 50 1 1 B
|
|
||||||
X Y5 5 700 -150 300 L 50 50 1 1 B
|
|
||||||
X ~E 6 -700 -350 300 R 50 50 1 1 I I
|
|
||||||
X VEE 7 -700 0 300 R 50 50 1 1 W
|
|
||||||
X GND 8 -700 -200 300 R 50 50 1 1 W
|
|
||||||
X S2 9 -700 150 300 R 50 50 1 1 I
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# C
|
|
||||||
#
|
|
||||||
DEF C C 0 10 N Y 1 F N
|
|
||||||
F0 "C" 25 100 50 H V L CNN
|
|
||||||
F1 "C" 25 -100 50 H V L CNN
|
|
||||||
F2 "" 38 -150 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
$FPLIST
|
|
||||||
C_*
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
P 2 0 1 20 -80 -30 80 -30 N
|
|
||||||
P 2 0 1 20 -80 30 80 30 N
|
|
||||||
X ~ 1 0 150 110 D 50 50 1 1 P
|
|
||||||
X ~ 2 0 -150 110 U 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# CONN_01X01
|
|
||||||
#
|
|
||||||
DEF CONN_01X01 J 0 40 Y N 1 F N
|
|
||||||
F0 "J" 0 100 50 H V C CNN
|
|
||||||
F1 "CONN_01X01" 100 0 50 V V C CNN
|
|
||||||
F2 "" 0 0 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
$FPLIST
|
|
||||||
Pin_Header_Straight_1X*
|
|
||||||
Pin_Header_Angled_1X*
|
|
||||||
Socket_Strip_Straight_1X*
|
|
||||||
Socket_Strip_Angled_1X*
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
S -50 5 10 -5 0 1 0 N
|
|
||||||
S -50 50 50 -50 0 1 0 N
|
|
||||||
X P1 1 -200 0 150 R 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# CONN_01X03
|
|
||||||
#
|
|
||||||
DEF CONN_01X03 J 0 40 Y N 1 F N
|
|
||||||
F0 "J" 0 200 50 H V C CNN
|
|
||||||
F1 "CONN_01X03" 100 0 50 V V C CNN
|
|
||||||
F2 "" 0 0 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
$FPLIST
|
|
||||||
Pin_Header_Straight_1X*
|
|
||||||
Pin_Header_Angled_1X*
|
|
||||||
Socket_Strip_Straight_1X*
|
|
||||||
Socket_Strip_Angled_1X*
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
S -50 -95 10 -105 0 1 0 N
|
|
||||||
S -50 5 10 -5 0 1 0 N
|
|
||||||
S -50 105 10 95 0 1 0 N
|
|
||||||
S -50 150 50 -150 0 1 0 N
|
|
||||||
X P1 1 -200 100 150 R 50 50 1 1 P
|
|
||||||
X P2 2 -200 0 150 R 50 50 1 1 P
|
|
||||||
X P3 3 -200 -100 150 R 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# CONN_01X04
|
|
||||||
#
|
|
||||||
DEF CONN_01X04 J 0 40 Y N 1 F N
|
|
||||||
F0 "J" 0 250 50 H V C CNN
|
|
||||||
F1 "CONN_01X04" 100 0 50 V V C CNN
|
|
||||||
F2 "" 0 0 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
$FPLIST
|
|
||||||
Pin_Header_Straight_1X*
|
|
||||||
Pin_Header_Angled_1X*
|
|
||||||
Socket_Strip_Straight_1X*
|
|
||||||
Socket_Strip_Angled_1X*
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
S -50 -145 10 -155 0 1 0 N
|
|
||||||
S -50 -45 10 -55 0 1 0 N
|
|
||||||
S -50 55 10 45 0 1 0 N
|
|
||||||
S -50 155 10 145 0 1 0 N
|
|
||||||
S -50 200 50 -200 0 1 0 N
|
|
||||||
X P1 1 -200 150 150 R 50 50 1 1 P
|
|
||||||
X P2 2 -200 50 150 R 50 50 1 1 P
|
|
||||||
X P3 3 -200 -50 150 R 50 50 1 1 P
|
|
||||||
X P4 4 -200 -150 150 R 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# CONN_01X08
|
|
||||||
#
|
|
||||||
DEF CONN_01X08 J 0 40 Y N 1 F N
|
|
||||||
F0 "J" 0 450 50 H V C CNN
|
|
||||||
F1 "CONN_01X08" 100 0 50 V V C CNN
|
|
||||||
F2 "" 0 0 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
$FPLIST
|
|
||||||
Pin_Header_Straight_1X*
|
|
||||||
Pin_Header_Angled_1X*
|
|
||||||
Socket_Strip_Straight_1X*
|
|
||||||
Socket_Strip_Angled_1X*
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
S -50 -400 50 400 0 1 0 N
|
|
||||||
S -50 -345 10 -355 0 1 0 N
|
|
||||||
S -50 -245 10 -255 0 1 0 N
|
|
||||||
S -50 -145 10 -155 0 1 0 N
|
|
||||||
S -50 -45 10 -55 0 1 0 N
|
|
||||||
S -50 55 10 45 0 1 0 N
|
|
||||||
S -50 155 10 145 0 1 0 N
|
|
||||||
S -50 255 10 245 0 1 0 N
|
|
||||||
S -50 355 10 345 0 1 0 N
|
|
||||||
X P1 1 -200 350 150 R 50 50 1 1 P
|
|
||||||
X P2 2 -200 250 150 R 50 50 1 1 P
|
|
||||||
X P3 3 -200 150 150 R 50 50 1 1 P
|
|
||||||
X P4 4 -200 50 150 R 50 50 1 1 P
|
|
||||||
X P5 5 -200 -50 150 R 50 50 1 1 P
|
|
||||||
X P6 6 -200 -150 150 R 50 50 1 1 P
|
|
||||||
X P7 7 -200 -250 150 R 50 50 1 1 P
|
|
||||||
X P8 8 -200 -350 150 R 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# CP
|
|
||||||
#
|
|
||||||
DEF CP C 0 10 N Y 1 F N
|
|
||||||
F0 "C" 25 100 50 H V L CNN
|
|
||||||
F1 "CP" 25 -100 50 H V L CNN
|
|
||||||
F2 "" 38 -150 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
$FPLIST
|
|
||||||
CP_*
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
S -90 20 -90 40 0 1 0 N
|
|
||||||
S -90 20 90 20 0 1 0 N
|
|
||||||
S 90 -20 -90 -40 0 1 0 F
|
|
||||||
S 90 40 -90 40 0 1 0 N
|
|
||||||
S 90 40 90 20 0 1 0 N
|
|
||||||
P 2 0 1 0 -70 90 -30 90 N
|
|
||||||
P 2 0 1 0 -50 110 -50 70 N
|
|
||||||
X ~ 1 0 150 110 D 50 50 1 1 P
|
|
||||||
X ~ 2 0 -150 110 U 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# D
|
|
||||||
#
|
|
||||||
DEF D D 0 40 N N 1 F N
|
|
||||||
F0 "D" 0 100 50 H V C CNN
|
|
||||||
F1 "D" 0 -100 50 H V C CNN
|
|
||||||
F2 "" 0 0 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
$FPLIST
|
|
||||||
TO-???*
|
|
||||||
*SingleDiode
|
|
||||||
*_Diode_*
|
|
||||||
*SingleDiode*
|
|
||||||
D_*
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
P 2 0 1 8 -50 50 -50 -50 N
|
|
||||||
P 2 0 1 0 50 0 -50 0 N
|
|
||||||
P 4 0 1 8 50 50 50 -50 -50 0 50 50 N
|
|
||||||
X K 1 -150 0 100 R 50 50 1 1 P
|
|
||||||
X A 2 150 0 100 L 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# D_Schottky
|
|
||||||
#
|
|
||||||
DEF D_Schottky D 0 40 N N 1 F N
|
|
||||||
F0 "D" 0 100 50 H V C CNN
|
|
||||||
F1 "D_Schottky" 0 -100 50 H V C CNN
|
|
||||||
F2 "" 0 0 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
$FPLIST
|
|
||||||
TO-???*
|
|
||||||
*SingleDiode
|
|
||||||
*_Diode_*
|
|
||||||
*SingleDiode*
|
|
||||||
D_*
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
P 2 0 1 0 50 0 -50 0 N
|
|
||||||
P 4 0 1 8 50 50 50 -50 -50 0 50 50 N
|
|
||||||
P 6 0 1 8 -75 25 -75 50 -50 50 -50 -50 -25 -50 -25 -25 N
|
|
||||||
X K 1 -150 0 100 R 50 50 1 1 P
|
|
||||||
X A 2 150 0 100 L 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# D_Zener
|
|
||||||
#
|
|
||||||
DEF D_Zener D 0 40 N N 1 F N
|
|
||||||
F0 "D" 0 100 50 H V C CNN
|
|
||||||
F1 "D_Zener" 0 -100 50 H V C CNN
|
|
||||||
F2 "" 0 0 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
$FPLIST
|
|
||||||
TO-???*
|
|
||||||
*SingleDiode
|
|
||||||
*_Diode_*
|
|
||||||
*SingleDiode*
|
|
||||||
D_*
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
P 2 0 1 0 50 0 -50 0 N
|
|
||||||
P 3 0 1 8 -50 -50 -50 50 -30 50 N
|
|
||||||
P 4 0 1 8 50 -50 50 50 -50 0 50 -50 N
|
|
||||||
X K 1 -150 0 100 R 50 50 1 1 P
|
|
||||||
X A 2 150 0 100 L 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# GND
|
|
||||||
#
|
|
||||||
DEF GND #PWR 0 0 Y Y 1 F P
|
|
||||||
F0 "#PWR" 0 -250 50 H I C CNN
|
|
||||||
F1 "GND" 0 -150 50 H V C CNN
|
|
||||||
F2 "" 0 0 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
DRAW
|
|
||||||
P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N
|
|
||||||
X GND 1 0 0 0 D 50 50 1 1 W N
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# Jumper_NO_Small
|
|
||||||
#
|
|
||||||
DEF Jumper_NO_Small JP 0 30 N N 1 F N
|
|
||||||
F0 "JP" 0 80 50 H V C CNN
|
|
||||||
F1 "Jumper_NO_Small" 10 -60 50 H V C CNN
|
|
||||||
F2 "" 0 0 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
DRAW
|
|
||||||
C -40 0 20 0 1 0 N
|
|
||||||
C 40 0 20 0 1 0 N
|
|
||||||
X 1 1 -100 0 40 R 50 50 0 1 P
|
|
||||||
X 2 2 100 0 40 L 50 50 0 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# L
|
|
||||||
#
|
|
||||||
DEF L L 0 40 N N 1 F N
|
|
||||||
F0 "L" -50 0 50 V V C CNN
|
|
||||||
F1 "L" 75 0 50 V V C CNN
|
|
||||||
F2 "" 0 0 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
$FPLIST
|
|
||||||
Choke_*
|
|
||||||
*Coil*
|
|
||||||
Inductor_*
|
|
||||||
L_*
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
A 0 -75 25 -899 899 0 1 0 N 0 -100 0 -50
|
|
||||||
A 0 -25 25 -899 899 0 1 0 N 0 -50 0 0
|
|
||||||
A 0 25 25 -899 899 0 1 0 N 0 0 0 50
|
|
||||||
A 0 75 25 -899 899 0 1 0 N 0 50 0 100
|
|
||||||
X 1 1 0 150 50 D 50 50 1 1 P
|
|
||||||
X 2 2 0 -150 50 U 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# LED-RESCUE-stm32
|
|
||||||
#
|
|
||||||
DEF LED-RESCUE-stm32 D 0 40 Y N 1 F N
|
|
||||||
F0 "D" 0 100 50 H V C CNN
|
|
||||||
F1 "LED-RESCUE-stm32" 0 -100 50 H V C CNN
|
|
||||||
F2 "" 0 0 50 H V C CNN
|
|
||||||
F3 "" 0 0 50 H V C CNN
|
|
||||||
$FPLIST
|
|
||||||
LED*
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
P 2 0 1 8 -50 -50 -50 50 N
|
|
||||||
P 2 0 1 0 -50 0 50 0 N
|
|
||||||
P 4 0 1 8 50 -50 50 50 -50 0 50 -50 N
|
|
||||||
P 5 0 1 0 -120 -30 -180 -90 -150 -90 -180 -90 -180 -60 N
|
|
||||||
P 5 0 1 0 -70 -30 -130 -90 -100 -90 -130 -90 -130 -60 N
|
|
||||||
X K 1 -150 0 100 R 50 50 1 1 P
|
|
||||||
X A 2 150 0 100 L 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# LM1117-3.3-RESCUE-stm32
|
|
||||||
#
|
|
||||||
DEF LM1117-3.3-RESCUE-stm32 U 0 30 Y Y 1 F N
|
|
||||||
F0 "U" 100 -250 50 H V C CNN
|
|
||||||
F1 "LM1117-3.3-RESCUE-stm32" 0 250 50 H V C CNN
|
|
||||||
F2 "" 0 0 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
$FPLIST
|
|
||||||
SOT-223*
|
|
||||||
TO-263*
|
|
||||||
TO-252*
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
S -200 -200 200 200 0 1 10 f
|
|
||||||
X GND/ADJ 1 0 -300 100 U 50 50 1 1 W
|
|
||||||
X VO 2 300 50 100 L 50 50 1 1 P
|
|
||||||
X VI 3 -300 0 100 R 50 50 1 1 W
|
|
||||||
X VO 4 300 -50 100 L 50 50 1 1 w
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# LM2576HV
|
|
||||||
#
|
|
||||||
DEF LM2576HV U 0 40 Y Y 1 F N
|
|
||||||
F0 "U" -350 250 60 H V C CNN
|
|
||||||
F1 "LM2576HV" 250 250 60 H V C CNN
|
|
||||||
F2 "" 0 0 60 H I C CNN
|
|
||||||
F3 "" 0 0 60 H I C CNN
|
|
||||||
F4 "Texas Instruments" 0 350 60 H I C CNN "Manufacturer"
|
|
||||||
$FPLIST
|
|
||||||
*DIP8
|
|
||||||
SOIC8
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
S -400 200 400 -250 0 1 0 N
|
|
||||||
X VIN 1 -700 100 300 R 50 50 1 1 W
|
|
||||||
X VOUT 2 700 -100 300 L 50 50 1 1 w
|
|
||||||
X GND 3 100 -550 300 U 50 50 1 1 W
|
|
||||||
X FB 4 700 100 300 L 50 50 1 1 I
|
|
||||||
X ON/OFF 5 -100 -550 300 U 50 50 1 1 I I
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# MAX471-RESCUE-stm32
|
|
||||||
#
|
|
||||||
DEF MAX471-RESCUE-stm32 U 0 40 Y Y 1 F N
|
|
||||||
F0 "U" -300 350 50 H V L CNN
|
|
||||||
F1 "MAX471-RESCUE-stm32" -300 -350 50 H V L CNN
|
|
||||||
F2 "" 0 0 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
DRAW
|
|
||||||
S -300 300 300 -300 0 1 10 f
|
|
||||||
X SHDN 1 -400 -100 100 R 50 50 1 1 I
|
|
||||||
X RS+ 2 -400 200 100 R 50 50 1 1 W
|
|
||||||
X RS+ 3 -400 100 100 R 50 50 1 1 P
|
|
||||||
X GND 4 -400 -200 100 R 50 50 1 1 W
|
|
||||||
X SIGN 5 400 -100 100 L 50 50 1 1 C
|
|
||||||
X RS- 6 400 200 100 L 50 50 1 1 w
|
|
||||||
X RS- 7 400 100 100 L 50 50 1 1 P
|
|
||||||
X OUT 8 400 -200 100 L 50 50 1 1 O
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# MCP2551-I_SN
|
|
||||||
#
|
|
||||||
DEF MCP2551-I_SN U 0 40 Y Y 1 F N
|
|
||||||
F0 "U" -400 350 50 H V L CNN
|
|
||||||
F1 "MCP2551-I_SN" 100 350 50 H V L CNN
|
|
||||||
F2 "Housings_SOIC:SOIC-8_3.9x4.9mm_Pitch1.27mm" 0 -500 50 H I C CIN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
$FPLIST
|
|
||||||
SOIC*Pitch1.27mm*
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
S -400 300 400 -300 0 1 10 f
|
|
||||||
X TXD 1 -500 200 100 R 50 50 1 1 I
|
|
||||||
X VSS 2 0 -400 100 U 50 50 1 1 W
|
|
||||||
X VDD 3 0 400 100 D 50 50 1 1 W
|
|
||||||
X RXD 4 -500 100 100 R 50 50 1 1 O
|
|
||||||
X Vref 5 -500 -100 100 R 50 50 1 1 w
|
|
||||||
X CANL 6 500 -100 100 L 50 50 1 1 B
|
|
||||||
X CANH 7 500 100 100 L 50 50 1 1 B
|
|
||||||
X Rs 8 -500 -200 100 R 50 50 1 1 I
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# PESD1CAN
|
|
||||||
#
|
|
||||||
DEF PESD1CAN D 0 30 Y N 1 F N
|
|
||||||
F0 "D" 0 -350 50 H V C CNN
|
|
||||||
F1 "PESD1CAN" 50 150 50 H V C CNN
|
|
||||||
F2 "" 0 0 50 H V C CNN
|
|
||||||
F3 "" 0 0 50 H V C CNN
|
|
||||||
$FPLIST
|
|
||||||
SOT23
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
S -200 100 300 -300 0 1 0 N
|
|
||||||
P 2 0 1 0 -140 -200 150 -200 N
|
|
||||||
P 2 0 1 0 -140 0 150 0 N
|
|
||||||
P 3 0 1 8 -150 -150 -150 -250 -150 -250 N
|
|
||||||
P 3 0 1 8 -150 50 -150 -50 -150 -50 N
|
|
||||||
P 3 0 1 8 150 -150 150 -250 150 -250 N
|
|
||||||
P 3 0 1 8 150 50 150 -50 150 -50 N
|
|
||||||
P 4 0 1 8 -150 -150 -170 -150 -170 -160 -170 -160 N
|
|
||||||
P 4 0 1 8 -150 50 -170 50 -170 40 -170 40 N
|
|
||||||
P 4 0 1 8 150 -250 170 -250 170 -240 170 -240 N
|
|
||||||
P 4 0 1 8 150 -150 130 -150 130 -160 130 -160 N
|
|
||||||
P 4 0 1 8 150 -50 170 -50 170 -40 170 -40 N
|
|
||||||
P 4 0 1 0 150 0 250 0 250 -200 150 -200 N
|
|
||||||
P 4 0 1 8 150 50 130 50 130 40 130 40 N
|
|
||||||
P 5 0 1 8 -130 -240 -130 -250 -150 -250 -150 -250 -150 -250 N
|
|
||||||
P 5 0 1 8 -130 -40 -130 -50 -150 -50 -150 -50 -150 -50 N
|
|
||||||
P 6 0 1 8 -50 -250 -150 -200 -50 -150 -50 -250 -50 -250 -50 -250 N
|
|
||||||
P 6 0 1 8 -50 -50 -150 0 -50 50 -50 -50 -50 -50 -50 -50 N
|
|
||||||
P 6 0 1 8 50 -150 150 -200 50 -250 50 -150 50 -150 50 -150 N
|
|
||||||
P 6 0 1 8 50 50 150 0 50 -50 50 50 50 50 50 50 N
|
|
||||||
X K 1 -300 0 150 R 50 50 0 1 P
|
|
||||||
X K 2 -300 -200 150 R 50 50 0 1 P
|
|
||||||
X O 3 400 -100 150 L 50 50 0 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# PWR_FLAG
|
|
||||||
#
|
|
||||||
DEF PWR_FLAG #FLG 0 0 N N 1 F P
|
|
||||||
F0 "#FLG" 0 75 50 H I C CNN
|
|
||||||
F1 "PWR_FLAG" 0 150 50 H V C CNN
|
|
||||||
F2 "" 0 0 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
DRAW
|
|
||||||
P 6 0 1 0 0 0 0 50 -40 75 0 100 40 75 0 50 N
|
|
||||||
X pwr 1 0 0 0 U 50 50 0 0 w
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# Q_PMOS_GSD
|
|
||||||
#
|
|
||||||
DEF Q_PMOS_GSD Q 0 0 Y N 1 F N
|
|
||||||
F0 "Q" 200 50 50 H V L CNN
|
|
||||||
F1 "Q_PMOS_GSD" 200 -50 50 H V L CNN
|
|
||||||
F2 "" 200 100 50 H I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
DRAW
|
|
||||||
C 65 0 111 0 1 10 N
|
|
||||||
C 100 -70 11 0 1 0 F
|
|
||||||
C 100 70 11 0 1 0 F
|
|
||||||
P 2 0 1 0 2 0 10 0 N
|
|
||||||
P 2 0 1 0 30 -70 100 -70 N
|
|
||||||
P 2 0 1 10 30 -50 30 -90 N
|
|
||||||
P 2 0 1 0 30 0 100 0 N
|
|
||||||
P 2 0 1 10 30 20 30 -20 N
|
|
||||||
P 2 0 1 0 30 70 100 70 N
|
|
||||||
P 2 0 1 10 30 90 30 50 N
|
|
||||||
P 2 0 1 0 100 -70 100 -100 N
|
|
||||||
P 2 0 1 0 100 -70 100 0 N
|
|
||||||
P 2 0 1 0 100 100 100 70 N
|
|
||||||
P 3 0 1 10 10 75 10 -75 10 -75 N
|
|
||||||
P 4 0 1 0 90 0 50 -15 50 15 90 0 F
|
|
||||||
P 4 0 1 0 100 -70 130 -70 130 70 100 70 N
|
|
||||||
P 4 0 1 0 110 -20 115 -15 145 -15 150 -10 N
|
|
||||||
P 4 0 1 0 130 -15 115 10 145 10 130 -15 N
|
|
||||||
X G 1 -200 0 200 R 50 50 1 1 I
|
|
||||||
X S 2 100 -200 100 U 50 50 1 1 P
|
|
||||||
X D 3 100 200 100 D 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# R
|
|
||||||
#
|
|
||||||
DEF R R 0 0 N Y 1 F N
|
|
||||||
F0 "R" 80 0 50 V V C CNN
|
|
||||||
F1 "R" 0 0 50 V V C CNN
|
|
||||||
F2 "" -70 0 50 V I C CNN
|
|
||||||
F3 "" 0 0 50 H I C CNN
|
|
||||||
$FPLIST
|
|
||||||
R_*
|
|
||||||
R_*
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
S -40 -100 40 100 0 1 10 N
|
|
||||||
X ~ 1 0 150 50 D 50 50 1 1 P
|
|
||||||
X ~ 2 0 -150 50 U 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# STM32F042C6Tx
|
|
||||||
#
|
|
||||||
DEF STM32F042C6Tx U 0 40 Y Y 1 L N
|
|
||||||
F0 "U" -3000 1725 50 H V L BNN
|
|
||||||
F1 "STM32F042C6Tx" 3000 1725 50 H V R BNN
|
|
||||||
F2 "LQFP48" 3000 1675 50 H V R TNN
|
|
||||||
F3 "" 0 0 50 H V C CNN
|
|
||||||
DRAW
|
|
||||||
S -3000 -1700 3000 1700 0 1 10 f
|
|
||||||
X VBAT 1 -3100 1100 100 R 50 50 1 1 W
|
|
||||||
X ADC_IN0/RTC_TAMP2/SYS_WKUP1/TIM2_CH1/TIM2_ETR/TSC_G1_IO1/USART2_CTS/PA0 10 3100 100 100 L 50 50 1 1 B
|
|
||||||
X ADC_IN1/TIM2_CH2/TSC_G1_IO2/USART2_DE/USART2_RTS/PA1 11 3100 0 100 L 50 50 1 1 B
|
|
||||||
X ADC_IN2/SYS_WKUP4/TIM2_CH3/TSC_G1_IO3/USART2_TX/PA2 12 3100 -100 100 L 50 50 1 1 B
|
|
||||||
X ADC_IN3/TIM2_CH4/TSC_G1_IO4/USART2_RX/PA3 13 3100 -200 100 L 50 50 1 1 B
|
|
||||||
X ADC_IN4/I2S1_WS/SPI1_NSS/TIM14_CH1/TSC_G2_IO1/USART2_CK/USB_OE/PA4 14 3100 -300 100 L 50 50 1 1 B
|
|
||||||
X ADC_IN5/CEC/I2S1_CK/SPI1_SCK/TIM2_CH1/TIM2_ETR/TSC_G2_IO2/PA5 15 3100 -400 100 L 50 50 1 1 B
|
|
||||||
X ADC_IN6/I2S1_MCK/SPI1_MISO/TIM16_CH1/TIM1_BKIN/TIM3_CH1/TSC_G2_IO3/PA6 16 3100 -500 100 L 50 50 1 1 B
|
|
||||||
X ADC_IN7/I2S1_SD/SPI1_MOSI/TIM14_CH1/TIM17_CH1/TIM1_CH1N/TIM3_CH2/TSC_G2_IO4/PA7 17 3100 -600 100 L 50 50 1 1 B
|
|
||||||
X PB0/ADC_IN8/TIM1_CH2N/TIM3_CH3/TSC_G3_IO2 18 -3100 100 100 R 50 50 1 1 B
|
|
||||||
X PB1/ADC_IN9/TIM14_CH1/TIM1_CH3N/TIM3_CH4/TSC_G3_IO3 19 -3100 0 100 R 50 50 1 1 B
|
|
||||||
X PC13/RTC_OUT_ALARM/RTC_OUT_CALIB/RTC_TAMP1/RTC_TS/SYS_WKUP2 2 -3100 500 100 R 50 50 1 1 B
|
|
||||||
X PB2/TSC_G3_IO4 20 -3100 -100 100 R 50 50 1 1 B
|
|
||||||
X PB10/CEC/I2C1_SCL/SPI2_SCK/TIM2_CH3/TSC_SYNC 21 -3100 -900 100 R 50 50 1 1 B
|
|
||||||
X PB11/I2C1_SDA/TIM2_CH4 22 -3100 -1000 100 R 50 50 1 1 B
|
|
||||||
X VSS 23 -200 -1800 100 U 50 50 1 1 W
|
|
||||||
X VDD 24 -200 1800 100 D 50 50 1 1 W
|
|
||||||
X PB12/SPI2_NSS/TIM1_BKIN 25 -3100 -1100 100 R 50 50 1 1 B
|
|
||||||
X PB13/I2C1_SCL/SPI2_SCK/TIM1_CH1N 26 -3100 -1200 100 R 50 50 1 1 B
|
|
||||||
X PB14/I2C1_SDA/SPI2_MISO/TIM1_CH2N 27 -3100 -1300 100 R 50 50 1 1 B
|
|
||||||
X PB15/RTC_REFIN/SPI2_MOSI/SYS_WKUP7/TIM1_CH3N 28 -3100 -1400 100 R 50 50 1 1 B
|
|
||||||
X CRS_SYNC/RCC_MCO/TIM1_CH1/USART1_CK/PA8 29 3100 -700 100 L 50 50 1 1 B
|
|
||||||
X PC14/RCC_OSC32_IN 3 -3100 400 100 R 50 50 1 1 B
|
|
||||||
X I2C1_SCL/TIM1_CH2/TSC_G4_IO1/USART1_TX/PA9 30 3100 -800 100 L 50 50 1 1 B
|
|
||||||
X I2C1_SDA/TIM17_BKIN/TIM1_CH3/TSC_G4_IO2/USART1_RX/PA10 31 3100 -900 100 L 50 50 1 1 B
|
|
||||||
X CAN_RX/I2C1_SCL/TIM1_CH4/TSC_G4_IO3/USART1_CTS/USB_DM/PA11 32 3100 -1000 100 L 50 50 1 1 B
|
|
||||||
X CAN_TX/I2C1_SDA/TIM1_ETR/TSC_G4_IO4/USART1_DE/USART1_RTS/USB_DP/PA12 33 3100 -1100 100 L 50 50 1 1 B
|
|
||||||
X IR_OUT/SYS_SWDIO/USB_OE/PA13 34 3100 -1200 100 L 50 50 1 1 B
|
|
||||||
X VSS 35 -100 -1800 100 U 50 50 1 1 W
|
|
||||||
X VDDIO2 36 100 1800 100 D 50 50 1 1 W
|
|
||||||
X SYS_SWCLK/USART2_TX/PA14 37 3100 -1300 100 L 50 50 1 1 B
|
|
||||||
X I2S1_WS/SPI1_NSS/TIM2_CH1/TIM2_ETR/USART2_RX/USB_OE/PA15 38 3100 -1400 100 L 50 50 1 1 B
|
|
||||||
X PB3/I2S1_CK/SPI1_SCK/TIM2_CH2/TSC_G5_IO1 39 -3100 -200 100 R 50 50 1 1 B
|
|
||||||
X PC15/RCC_OSC32_OUT 4 -3100 300 100 R 50 50 1 1 B
|
|
||||||
X PB4/I2S1_MCK/SPI1_MISO/TIM17_BKIN/TIM3_CH1/TSC_G5_IO2 40 -3100 -300 100 R 50 50 1 1 B
|
|
||||||
X PB5/I2C1_SMBA/I2S1_SD/SPI1_MOSI/SYS_WKUP6/TIM16_BKIN/TIM3_CH2 41 -3100 -400 100 R 50 50 1 1 B
|
|
||||||
X PB6/I2C1_SCL/TIM16_CH1N/TSC_G5_IO3/USART1_TX 42 -3100 -500 100 R 50 50 1 1 B
|
|
||||||
X PB7/I2C1_SDA/TIM17_CH1N/TSC_G5_IO4/USART1_RX 43 -3100 -600 100 R 50 50 1 1 B
|
|
||||||
X PF11 44 -3100 700 100 R 50 50 1 1 B
|
|
||||||
X PB8/CAN_RX/CEC/I2C1_SCL/TIM16_CH1/TSC_SYNC 45 -3100 -700 100 R 50 50 1 1 B
|
|
||||||
X PB9/CAN_TX/I2C1_SDA/IR_OUT/SPI2_NSS/TIM17_CH1 46 -3100 -800 100 R 50 50 1 1 B
|
|
||||||
X VSS 47 0 -1800 100 U 50 50 1 1 W
|
|
||||||
X VDD 48 -100 1800 100 D 50 50 1 1 W
|
|
||||||
X PF0/CRS_SYNC/I2C1_SDA/RCC_OSC_IN 5 -3100 900 100 R 50 50 1 1 I
|
|
||||||
X PF1/I2C1_SCL/RCC_OSC_OUT 6 -3100 800 100 R 50 50 1 1 I
|
|
||||||
X NRST 7 -3100 1300 100 R 50 50 1 1 I
|
|
||||||
X VSSA 8 100 -1800 100 U 50 50 1 1 W
|
|
||||||
X VDDA 9 0 1800 100 D 50 50 1 1 W
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# TPS2051
|
|
||||||
#
|
|
||||||
DEF TPS2051 U 0 40 Y Y 1 F N
|
|
||||||
F0 "U" 0 -300 60 H V C CNN
|
|
||||||
F1 "TPS2051" 0 300 60 H V C CNN
|
|
||||||
F2 "" 0 0 60 H I C CNN
|
|
||||||
F3 "" 0 0 60 H I C CNN
|
|
||||||
DRAW
|
|
||||||
S -250 250 250 -250 0 1 0 N
|
|
||||||
X GND 1 -450 150 200 R 50 50 1 1 W
|
|
||||||
X IN 2 -450 50 200 R 50 50 1 1 W
|
|
||||||
X IN 3 -450 -50 200 R 50 50 1 1 P
|
|
||||||
X EN 4 -450 -150 200 R 50 50 1 1 I
|
|
||||||
X ~OC 5 450 -150 200 L 50 50 1 1 O
|
|
||||||
X OUT 6 450 -50 200 L 50 50 1 1 P
|
|
||||||
X OUT 7 450 50 200 L 50 50 1 1 P
|
|
||||||
X OUT 8 450 150 200 L 50 50 1 1 w
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# USB6B1
|
|
||||||
#
|
|
||||||
DEF USB6B1 D 0 30 Y N 1 F N
|
|
||||||
F0 "D" 0 -450 50 H V C CNN
|
|
||||||
F1 "USB6B1" 0 400 50 H V C CNN
|
|
||||||
F2 "" 200 -100 50 V V C CNN
|
|
||||||
F3 "" 200 -100 50 V V C CNN
|
|
||||||
$FPLIST
|
|
||||||
SO8
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
C -150 -300 7 0 1 0 N
|
|
||||||
C -150 100 7 0 1 0 N
|
|
||||||
C -150 300 7 0 1 0 N
|
|
||||||
C 0 -300 7 0 1 0 N
|
|
||||||
C 0 -100 7 0 1 0 N
|
|
||||||
C 0 300 7 0 1 0 N
|
|
||||||
C 200 -300 7 0 1 0 N
|
|
||||||
C 200 300 7 0 1 0 N
|
|
||||||
S -300 -100 300 -100 0 1 0 N
|
|
||||||
S -300 300 300 300 0 1 0 N
|
|
||||||
S -200 -150 -100 -150 0 1 0 N
|
|
||||||
S -200 250 -100 250 0 1 0 N
|
|
||||||
S -150 300 -150 -300 0 1 0 N
|
|
||||||
S -50 -150 50 -150 0 1 0 N
|
|
||||||
S -50 250 50 250 0 1 0 N
|
|
||||||
S 0 300 0 -300 0 1 0 N
|
|
||||||
S 200 300 200 -300 0 1 0 N
|
|
||||||
S 300 -300 -300 -300 0 1 0 N
|
|
||||||
S 300 100 -300 100 0 1 0 N
|
|
||||||
P 3 0 1 8 150 50 250 50 250 50 N
|
|
||||||
P 4 0 1 8 150 50 150 30 160 30 160 30 N
|
|
||||||
P 4 0 1 8 250 50 250 70 240 70 240 70 N
|
|
||||||
P 5 0 1 0 -250 350 300 350 300 -350 -250 -350 -250 350 N
|
|
||||||
P 6 0 1 8 -200 -250 -150 -150 -100 -250 -200 -250 -200 -250 -200 -250 N
|
|
||||||
P 6 0 1 8 -200 150 -150 250 -100 150 -200 150 -200 150 -200 150 N
|
|
||||||
P 6 0 1 8 -50 -250 0 -150 50 -250 -50 -250 -50 -250 -50 -250 N
|
|
||||||
P 6 0 1 8 -50 150 0 250 50 150 -50 150 -50 150 -50 150 N
|
|
||||||
P 6 0 1 8 150 -50 200 50 250 -50 150 -50 150 -50 150 -50 N
|
|
||||||
X VCC 1 -500 300 200 R 50 50 1 1 P
|
|
||||||
X I/O1 2 -500 100 200 R 50 50 1 1 P
|
|
||||||
X I/O2 3 -500 -100 200 R 50 50 1 1 P
|
|
||||||
X GND 4 -500 -300 200 R 50 50 1 1 P
|
|
||||||
X GND 5 500 -300 200 L 50 50 1 1 P
|
|
||||||
X I/O2 6 500 -100 200 L 50 50 1 1 P
|
|
||||||
X I/O1 7 500 100 200 L 50 50 1 1 P
|
|
||||||
X VCC 8 500 300 200 L 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
# USB_A-RESCUE-stm32
|
|
||||||
#
|
|
||||||
DEF USB_A-RESCUE-stm32 P 0 40 Y Y 1 F N
|
|
||||||
F0 "P" 200 -200 50 H V C CNN
|
|
||||||
F1 "USB_A-RESCUE-stm32" -50 200 50 H V C CNN
|
|
||||||
F2 "" -50 -100 50 V V C CNN
|
|
||||||
F3 "" -50 -100 50 V V C CNN
|
|
||||||
$FPLIST
|
|
||||||
USB*
|
|
||||||
$ENDFPLIST
|
|
||||||
DRAW
|
|
||||||
S -250 -150 150 150 0 1 0 N
|
|
||||||
S -205 -150 -195 -120 0 1 0 N
|
|
||||||
S -105 -150 -95 -120 0 1 0 N
|
|
||||||
S -5 -150 5 -120 0 1 0 N
|
|
||||||
S 95 -150 105 -120 0 1 0 N
|
|
||||||
X VBUS 1 -200 -300 150 U 50 50 1 1 W
|
|
||||||
X D- 2 -100 -300 150 U 50 50 1 1 P
|
|
||||||
X D+ 3 0 -300 150 U 50 50 1 1 P
|
|
||||||
X GND 4 100 -300 150 U 50 50 1 1 W
|
|
||||||
X shield 5 300 100 150 L 50 50 1 1 P
|
|
||||||
ENDDRAW
|
|
||||||
ENDDEF
|
|
||||||
#
|
|
||||||
#End Library
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
(sym_lib_table
|
|
||||||
(lib (name Chrono)(type Legacy)(uri ${KIPRJMOD}/Chrono.lib)(options "")(descr ""))
|
|
||||||
(lib (name stm32-rescue)(type Legacy)(uri ${KIPRJMOD}/stm32-rescue.lib)(options "")(descr ""))
|
|
||||||
)
|
|
||||||
@ -59,7 +59,7 @@ uint8_t parse_lidar_data(char *txt){
|
|||||||
printu(1, last_lidar_dist);
|
printu(1, last_lidar_dist);
|
||||||
SEND(" signal=");
|
SEND(" signal=");
|
||||||
printu(1, last_lidar_stren);
|
printu(1, last_lidar_stren);
|
||||||
newline();
|
newline(1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@ -73,7 +73,7 @@ uint8_t parse_lidar_data(char *txt){
|
|||||||
printu(1, last_lidar_dist);
|
printu(1, last_lidar_dist);
|
||||||
SEND(" signal=");
|
SEND(" signal=");
|
||||||
printu(1, last_lidar_stren);
|
printu(1, last_lidar_stren);
|
||||||
newline();
|
newline(1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the chronometer project.
|
|
||||||
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
#ifndef LIDAR_H__
|
|
||||||
#define LIDAR_H__
|
|
||||||
#include <stm32f1.h>
|
|
||||||
|
|
||||||
#define LIDAR_FRAME_LEN (9)
|
|
||||||
// frame header
|
|
||||||
#define LIDAR_FRAME_HEADER (0x59)
|
|
||||||
// lower strength limit
|
|
||||||
#define LIDAR_LOWER_STREN (10)
|
|
||||||
// triggered distance threshold - 1 meter
|
|
||||||
#define LIDAR_DIST_THRES (100)
|
|
||||||
#define LIDAR_MIN_DIST (50)
|
|
||||||
#define LIDAR_MAX_DIST (1000)
|
|
||||||
|
|
||||||
extern uint16_t last_lidar_dist;
|
|
||||||
extern uint16_t lidar_triggered_dist;
|
|
||||||
extern uint16_t last_lidar_stren;
|
|
||||||
|
|
||||||
uint8_t parse_lidar_data(char *txt);
|
|
||||||
|
|
||||||
#endif // LIDAR_H__
|
|
||||||
@ -68,17 +68,17 @@ void iwdg_setup(){
|
|||||||
IWDG->KR = IWDG_REFRESH; /* (6) */
|
IWDG->KR = IWDG_REFRESH; /* (6) */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EBUG
|
#if 0
|
||||||
char *parse_cmd(char *buf){
|
char *parse_cmd(char *buf){
|
||||||
int32_t N;
|
int32_t N;
|
||||||
static char btns[] = "BTN0=0, BTN1=0, BTN2=0, PPS=0\n";
|
static char btns[] = "BTN0=0, BTN1=0, BTN2=0, PPS=0\n";
|
||||||
event_log l = {.elog_sz = sizeof(event_log), .trigno = 2};
|
event_log l = {.elog_sz = sizeof(event_log), .trigno = 2};
|
||||||
switch(*buf){
|
switch(*buf){
|
||||||
case '0':
|
case '0':
|
||||||
LED_off(); // LED0 off @dbg
|
LED1_off(); // LED1 off @dbg
|
||||||
break;
|
break;
|
||||||
case '1':
|
case '1':
|
||||||
LED_on(); // LED0 on @dbg
|
LED1_on(); // LED1 on @dbg
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
l.shottime.Time = current_time;
|
l.shottime.Time = current_time;
|
||||||
@ -86,7 +86,7 @@ char *parse_cmd(char *buf){
|
|||||||
l.triglen = getADCval(1);
|
l.triglen = getADCval(1);
|
||||||
if(store_log(&l)) SEND("Error storing");
|
if(store_log(&l)) SEND("Error storing");
|
||||||
else SEND("Store OK");
|
else SEND("Store OK");
|
||||||
newline();
|
newline(1);
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
btns[5] = gettrig(0) + '0';
|
btns[5] = gettrig(0) + '0';
|
||||||
@ -117,36 +117,36 @@ char *parse_cmd(char *buf){
|
|||||||
SEND("USB pullup is ");
|
SEND("USB pullup is ");
|
||||||
if(pin_read(USBPU_port, USBPU_pin)) SEND("off");
|
if(pin_read(USBPU_port, USBPU_pin)) SEND("off");
|
||||||
else SEND("on");
|
else SEND("on");
|
||||||
newline();
|
newline(1);
|
||||||
break;
|
break;
|
||||||
case 'G':
|
case 'G':
|
||||||
SEND("LIDAR_DIST=");
|
SEND("LIDAR_DIST=");
|
||||||
printu(1, last_lidar_dist);
|
printu(1, last_lidar_dist);
|
||||||
SEND(", LIDAR_STREN=");
|
SEND(", LIDAR_STREN=");
|
||||||
printu(1, last_lidar_stren);
|
printu(1, last_lidar_stren);
|
||||||
newline();
|
newline(1);
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
USB_send("Very long test string for USB (it's length is more than 64 bytes).\n"
|
sendstring("Very long test string for USB (it's length is more than 64 bytes).\n"
|
||||||
"This is another part of the string! Can you see all of this?\n");
|
"This is another part of the string! Can you see all of this?\n");
|
||||||
return "Long test sent\n";
|
return "Long test sent\n";
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
USB_send("Soft reset\n");
|
sendstring("Soft reset\n");
|
||||||
SEND("Soft reset\n");
|
SEND("Soft reset\n");
|
||||||
NVIC_SystemReset();
|
NVIC_SystemReset();
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
USB_send("Test string for USB\n");
|
sendstring("Test string for USB\n");
|
||||||
return "Short test sent\n";
|
return "Short test sent\n";
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
SEND(get_time(¤t_time, get_millis()));
|
SEND(get_time(¤t_time, get_millis()));
|
||||||
break;
|
break;
|
||||||
case 'W':
|
case 'W':
|
||||||
USB_send("Wait for reboot\n");
|
sendstring("Wait for reboot\n");
|
||||||
SEND("Wait for reboot\n");
|
SEND("Wait for reboot\n");
|
||||||
while(1){nop();};
|
while(1){nop();}
|
||||||
break;
|
break;
|
||||||
default: // help
|
default: // help
|
||||||
if(buf[1] != '\n') return buf;
|
if(buf[1] != '\n') return buf;
|
||||||
@ -180,9 +180,14 @@ static char *get_USB(){
|
|||||||
int x = USB_receive(curptr, rest);
|
int x = USB_receive(curptr, rest);
|
||||||
if(!x) return NULL;
|
if(!x) return NULL;
|
||||||
curptr[x] = 0;
|
curptr[x] = 0;
|
||||||
|
if(x == 1 && *curptr == 0x7f){ // backspace
|
||||||
|
if(curptr > tmpbuf){
|
||||||
|
--curptr;
|
||||||
|
USB_send("\b \b");
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
USB_send(curptr); // echo
|
USB_send(curptr); // echo
|
||||||
//USB_send("ENDOINPUT\n");
|
|
||||||
//if(x == 1 && *curptr < 32){USB_send("\n"); USB_send(u2str(*curptr)); USB_send("\n");}
|
|
||||||
if(curptr[x-1] == '\n'){ // || curptr[x-1] == '\r'){
|
if(curptr[x-1] == '\n'){ // || curptr[x-1] == '\r'){
|
||||||
curptr = tmpbuf;
|
curptr = tmpbuf;
|
||||||
rest = USBBUF;
|
rest = USBBUF;
|
||||||
@ -194,7 +199,7 @@ static char *get_USB(){
|
|||||||
}
|
}
|
||||||
curptr += x; rest -= x;
|
curptr += x; rest -= x;
|
||||||
if(rest <= 0){ // buffer overflow
|
if(rest <= 0){ // buffer overflow
|
||||||
//SEND("USB buffer overflow!\n");
|
sendstring("\nUSB buffer overflow!\n");
|
||||||
curptr = tmpbuf;
|
curptr = tmpbuf;
|
||||||
rest = USBBUF;
|
rest = USBBUF;
|
||||||
}
|
}
|
||||||
@ -203,47 +208,46 @@ static char *get_USB(){
|
|||||||
|
|
||||||
void linecoding_handler(usb_LineCoding __attribute__((unused)) *lc){ // get/set line coding
|
void linecoding_handler(usb_LineCoding __attribute__((unused)) *lc){ // get/set line coding
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
SEND("Change speed to");
|
SEND("Change speed to ");
|
||||||
printu(1, lc->dwDTERate);
|
printu(1, lc->dwDTERate);
|
||||||
newline();
|
newline(1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static volatile uint8_t USBconn = 0;
|
static volatile uint8_t USBconn = 0;
|
||||||
|
uint8_t USB_connected = 0; // need for usb.c
|
||||||
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
|
||||||
USBconn = 1;
|
USBconn = 1; // if == 1 -> send welcome message
|
||||||
#ifdef EBUG
|
USB_connected = 1;
|
||||||
|
#if 0
|
||||||
if(val & 2){
|
if(val & 2){
|
||||||
DBG("RTS set");
|
DBG("RTS set");
|
||||||
USB_send("RTS set\n");
|
sendstring("RTS set\n");
|
||||||
}
|
}
|
||||||
if(val & 1){
|
if(val & 1){
|
||||||
DBG("DTR set");
|
DBG("DTR set");
|
||||||
USB_send("DTR set\n");
|
sendstring("DTR set\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void break_handler(){ // client disconnected
|
void break_handler(){ // client disconnected
|
||||||
DBG("Disconnected");
|
DBG("Disconnected");
|
||||||
|
USB_connected = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EBUG
|
|
||||||
extern int32_t ticksdiff, timecntr, timerval, Tms1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main(void){
|
int main(void){
|
||||||
uint32_t lastT = 0;
|
uint32_t lastT = 0;
|
||||||
sysreset();
|
sysreset();
|
||||||
StartHSE();
|
StartHSE();
|
||||||
SysTick_Config(SYSTICK_DEFCONF); // function SysTick_Config decrements argument!
|
SysTick_Config(SYSTICK_DEFCONF); // function SysTick_Config decrements argument!
|
||||||
|
// read data stored in flash - before all pins/ports setup!!!
|
||||||
|
flashstorage_init();
|
||||||
// !!! hw_setup() should be the first in setup stage
|
// !!! hw_setup() should be the first in setup stage
|
||||||
hw_setup();
|
hw_setup();
|
||||||
USB_setup();
|
USB_setup();
|
||||||
flashstorage_init();
|
|
||||||
USBPU_ON();
|
USBPU_ON();
|
||||||
usarts_setup();
|
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
SEND("This is 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
|
||||||
@ -254,7 +258,7 @@ int main(void){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
|
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
|
||||||
// read data stored in flash
|
usarts_setup(); // setup usarts after reading configuration
|
||||||
iwdg_setup();
|
iwdg_setup();
|
||||||
|
|
||||||
while (1){
|
while (1){
|
||||||
@ -262,7 +266,7 @@ int main(void){
|
|||||||
if(Timer > 499) LED_on(); // turn ON LED0 over 0.25s after PPS pulse
|
if(Timer > 499) LED_on(); // turn ON LED0 over 0.25s after PPS pulse
|
||||||
if(USBconn && Tms > 100){ // USB connection
|
if(USBconn && Tms > 100){ // USB connection
|
||||||
USBconn = 0;
|
USBconn = 0;
|
||||||
USB_send("Chronometer version " VERSION ".\n");
|
sendstring("Chronometer version " VERSION ".\n");
|
||||||
}
|
}
|
||||||
// check if triggers that was recently shot are off now
|
// check if triggers that was recently shot are off now
|
||||||
fillunshotms();
|
fillunshotms();
|
||||||
@ -280,21 +284,14 @@ int main(void){
|
|||||||
LED1_off(); // turn off LED1 if GPS not found or time unknown
|
LED1_off(); // turn off LED1 if GPS not found or time unknown
|
||||||
}
|
}
|
||||||
lastT = Tms;
|
lastT = Tms;
|
||||||
/*if(usartrx(LIDAR_USART)){
|
|
||||||
char *txt;
|
|
||||||
if(usart_getline(LIDAR_USART, &txt)){
|
|
||||||
DBG("LIDAR:");
|
|
||||||
DBG(txt);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
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
|
||||||
transmit_tbuf(GPS_USART);
|
transmit_tbuf(GPS_USART);
|
||||||
transmit_tbuf(LIDAR_USART);
|
transmit_tbuf(LIDAR_USART);
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
static uint8_t x = 1;
|
static int32_t oldctr = 0;
|
||||||
if(timecntr){
|
if(timecntr && timecntr != oldctr){
|
||||||
if(x){
|
oldctr = timecntr;
|
||||||
SEND("ticksdiff=");
|
SEND("ticksdiff=");
|
||||||
if(ticksdiff < 0){
|
if(ticksdiff < 0){
|
||||||
SEND("-");
|
SEND("-");
|
||||||
@ -310,9 +307,8 @@ int main(void){
|
|||||||
printu(1, timerval);
|
printu(1, timerval);
|
||||||
SEND(", LOAD=");
|
SEND(", LOAD=");
|
||||||
printu(1, SysTick->LOAD);
|
printu(1, SysTick->LOAD);
|
||||||
newline();
|
usart_putchar(1, '\n');
|
||||||
}
|
newline(1);
|
||||||
x = !x;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -322,33 +318,21 @@ int main(void){
|
|||||||
int r = 0;
|
int r = 0;
|
||||||
char *txt = NULL;
|
char *txt = NULL;
|
||||||
if((txt = get_USB())){
|
if((txt = get_USB())){
|
||||||
DBG("Received data over USB:");
|
|
||||||
DBG(txt);
|
|
||||||
if(parse_USBCMD(txt)){
|
|
||||||
USB_send("Bad command: ");
|
|
||||||
USB_send(txt);
|
|
||||||
USB_send("\n");
|
|
||||||
}
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
|
parse_CMD(txt);
|
||||||
}
|
}
|
||||||
if(usartrx(1)){ // usart1 received data, store in in buffer
|
if(usartrx(1)){ // usart1 received data, store it in buffer
|
||||||
r = usart_getline(1, &txt);
|
r = usart_getline(1, &txt);
|
||||||
|
IWDG->KR = IWDG_REFRESH;
|
||||||
if(r){
|
if(r){
|
||||||
txt[r] = 0;
|
txt[r] = 0;
|
||||||
#ifdef EBUG
|
|
||||||
char *ans = parse_cmd(txt);
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
|
||||||
if(ans){
|
|
||||||
transmit_tbuf(1);
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
|
||||||
usart_send(1, ans);
|
|
||||||
transmit_tbuf(1);
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(the_conf.defflags & FLAG_GPSPROXY){
|
if(the_conf.defflags & FLAG_GPSPROXY){
|
||||||
usart_send(GPS_USART, txt);
|
usart_send(GPS_USART, txt);
|
||||||
IWDG->KR = IWDG_REFRESH;
|
}else{ // UART1 is additive serial/bluetooth console
|
||||||
|
usart_send(1, txt);
|
||||||
|
if(*txt != '\n'){
|
||||||
|
parse_CMD(txt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -365,6 +349,12 @@ int main(void){
|
|||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
r = usart_getline(LIDAR_USART, &txt);
|
r = usart_getline(LIDAR_USART, &txt);
|
||||||
if(r){
|
if(r){
|
||||||
|
if(the_conf.defflags & FLAG_NOLIDAR){
|
||||||
|
usart_send(LIDAR_USART, txt);
|
||||||
|
if(*txt != '\n'){
|
||||||
|
parse_CMD(txt);
|
||||||
|
}
|
||||||
|
}else
|
||||||
parse_lidar_data(txt);
|
parse_lidar_data(txt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
********************************************************************************
|
|
||||||
* *
|
|
||||||
* Copyright (c) 2017 Andrea Loi *
|
|
||||||
* *
|
|
||||||
* 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. *
|
|
||||||
* *
|
|
||||||
********************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
MEMORY
|
|
||||||
{
|
|
||||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
|
||||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
/* DON'T EDIT THIS FILE UNLESS YOU KNOW WHAT YOU'RE DOING! */
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
/* _isrvectors_tend = 0x00000150; - different for different series */
|
|
||||||
|
|
||||||
ENTRY(reset_handler)
|
|
||||||
|
|
||||||
SECTIONS {
|
|
||||||
.vector_table 0x08000000 :
|
|
||||||
{
|
|
||||||
_sisrvectors = .;
|
|
||||||
KEEP(*(.vector_table))
|
|
||||||
/* ASSERT(. == _isrvectors_tend, "The vector table needs to be 84 elements long!"); */
|
|
||||||
_eisrvectors = .;
|
|
||||||
} >rom
|
|
||||||
|
|
||||||
.text :
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
_stext = .;
|
|
||||||
*(.text*)
|
|
||||||
*(.rodata*)
|
|
||||||
. = ALIGN(4);
|
|
||||||
_etext = .;
|
|
||||||
} >rom
|
|
||||||
|
|
||||||
.ARM.extab :
|
|
||||||
{
|
|
||||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
|
||||||
} >rom
|
|
||||||
|
|
||||||
.ARM : {
|
|
||||||
*(.ARM.exidx*)
|
|
||||||
} >rom
|
|
||||||
|
|
||||||
.data :
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
_sdata = .;
|
|
||||||
*(.data*)
|
|
||||||
. = ALIGN(4);
|
|
||||||
_edata = .;
|
|
||||||
} >ram AT >rom
|
|
||||||
|
|
||||||
.myvars :
|
|
||||||
{
|
|
||||||
. = ALIGN(1024);
|
|
||||||
__varsstart = ABSOLUTE(.);
|
|
||||||
KEEP(*(.myvars));
|
|
||||||
. = . + 2000;
|
|
||||||
. = ALIGN(1024);
|
|
||||||
__varsend = ABSOLUTE(.);
|
|
||||||
} > rom
|
|
||||||
|
|
||||||
.logs :
|
|
||||||
{
|
|
||||||
. = ALIGN(1024);
|
|
||||||
__logsstart = ABSOLUTE(.);
|
|
||||||
KEEP(*(.logs))
|
|
||||||
} > rom
|
|
||||||
|
|
||||||
_ldata = LOADADDR(.data);
|
|
||||||
|
|
||||||
.bss :
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
_sbss = .;
|
|
||||||
*(.bss*)
|
|
||||||
*(COMMON)
|
|
||||||
. = ALIGN(4);
|
|
||||||
_ebss = .;
|
|
||||||
} >ram
|
|
||||||
}
|
|
||||||
|
|
||||||
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));
|
|
||||||
PROVIDE(_varslen = __varsend - __varsstart);
|
|
||||||
@ -16,6 +16,8 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Commands parser
|
||||||
|
|
||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "GPS.h"
|
#include "GPS.h"
|
||||||
#include "lidar.h"
|
#include "lidar.h"
|
||||||
@ -32,7 +34,7 @@ extern uint32_t shotms[];
|
|||||||
/**
|
/**
|
||||||
* @brief cmpstr - the same as strncmp
|
* @brief cmpstr - the same as strncmp
|
||||||
* @param s1,s2 - strings to compare
|
* @param s1,s2 - strings to compare
|
||||||
* @param n - max symbols amount
|
* @param n - max symbols amount + 1 (!!!!)
|
||||||
* @return 0 if strings equal or 1/-1
|
* @return 0 if strings equal or 1/-1
|
||||||
*/
|
*/
|
||||||
int cmpstr(const char *s1, const char *s2, int n){
|
int cmpstr(const char *s1, const char *s2, int n){
|
||||||
@ -61,45 +63,50 @@ char *getchr(const char *str, char symbol){
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define sendu(x) do{USB_send(u2str(x));}while(0)
|
#define sendu(x) do{sendstring(u2str(x));}while(0)
|
||||||
|
|
||||||
|
/*
|
||||||
static void sendi(int32_t I){
|
static void sendi(int32_t I){
|
||||||
if(I < 0){
|
if(I < 0){
|
||||||
USB_send("-");
|
sendchar('-');
|
||||||
I = -I;
|
I = -I;
|
||||||
}
|
}
|
||||||
USB_send(u2str((uint32_t)I));
|
sendstring(u2str((uint32_t)I));
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// echo '1' if true or '0' if false
|
||||||
|
static void checkflag(uint8_t f){
|
||||||
|
if(f) sendchar('1');
|
||||||
|
else sendchar('0');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief showuserconf - show configuration over USB
|
* @brief showuserconf - show configuration over USB
|
||||||
*/
|
*/
|
||||||
static void showuserconf(){
|
static void showuserconf(){
|
||||||
USB_send("DISTMIN="); sendu(the_conf.dist_min);
|
sendstring("DISTMIN="); sendu(the_conf.dist_min);
|
||||||
USB_send("\nDISTMAX="); sendu(the_conf.dist_max);
|
sendstring("\nDISTMAX="); sendu(the_conf.dist_max);
|
||||||
USB_send("\nADCMIN="); sendi(the_conf.ADC_min);
|
sendstring("\nTRIGLVL="); sendu(the_conf.trigstate);
|
||||||
USB_send("\nADCMAX="); sendi(the_conf.ADC_max);
|
sendstring("\nTRIGPAUSE={");
|
||||||
USB_send("\nTRIGLVL="); sendu(the_conf.trigstate);
|
|
||||||
USB_send("\nTRIGPAUSE={");
|
|
||||||
for(int i = 0; i < TRIGGERS_AMOUNT; ++i){
|
for(int i = 0; i < TRIGGERS_AMOUNT; ++i){
|
||||||
if(i) USB_send(", ");
|
if(i) sendstring(", ");
|
||||||
sendu(the_conf.trigpause[i]);
|
sendu(the_conf.trigpause[i]);
|
||||||
}
|
}
|
||||||
USB_send("}");
|
sendstring("}\nUSART1SPD="); sendu(the_conf.USART_speed);
|
||||||
USB_send("\nUSART1SPD="); sendu(the_conf.USART_speed);
|
sendstring("\nLIDARSPD="); sendu(the_conf.LIDAR_speed);
|
||||||
USB_send("\nSTREND=");
|
sendstring("\nNFREE=");
|
||||||
if(the_conf.defflags & FLAG_STRENDRN) USB_send("RN");
|
|
||||||
else USB_send("N");
|
|
||||||
uint8_t f = the_conf.defflags;
|
|
||||||
USB_send("\nSAVE_EVENTS=");
|
|
||||||
if(f & FLAG_SAVE_EVENTS) USB_send("1");
|
|
||||||
else USB_send("0");
|
|
||||||
USB_send("\nGPSPROXY=");
|
|
||||||
if(f & FLAG_GPSPROXY) USB_send("1");
|
|
||||||
else USB_send("0");
|
|
||||||
USB_send("\nNFREE=");
|
|
||||||
sendu(the_conf.NLfreeWarn);
|
sendu(the_conf.NLfreeWarn);
|
||||||
USB_send("\n");
|
sendstring("\nSTREND=");
|
||||||
|
if(the_conf.defflags & FLAG_STRENDRN) sendstring("RN");
|
||||||
|
else sendchar('N');
|
||||||
|
uint8_t f = the_conf.defflags;
|
||||||
|
sendstring("\nSAVE_EVENTS=");
|
||||||
|
checkflag(f & FLAG_SAVE_EVENTS);
|
||||||
|
sendstring("\nGPSPROXY=");
|
||||||
|
checkflag(f & FLAG_GPSPROXY);
|
||||||
|
sendstring("\nLIDAR=");
|
||||||
|
checkflag(!(f & FLAG_NOLIDAR));
|
||||||
|
sendstring("\n"); // <-- sendstring @ the end to initialize data transmission
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,19 +114,17 @@ static void showuserconf(){
|
|||||||
* @param cmd - buffer with commands
|
* @param cmd - buffer with commands
|
||||||
* @return 0 if got command, 1 if command not recognized
|
* @return 0 if got command, 1 if command not recognized
|
||||||
*/
|
*/
|
||||||
int parse_USBCMD(char *cmd){
|
void parse_CMD(char *cmd){
|
||||||
|
char *oldcmd = cmd;
|
||||||
#define CMP(a,b) cmpstr(a, b, sizeof(b))
|
#define CMP(a,b) cmpstr(a, b, sizeof(b))
|
||||||
#define GETNUM(x) if(getnum(cmd+sizeof(x)-1, &N)) goto bad_number;
|
#define GETNUM(x) do{if(getnum(cmd+sizeof(x)-1, &N)) goto bad_number;}while(0)
|
||||||
static uint8_t conf_modified = 0;
|
static uint8_t conf_modified = 0;
|
||||||
uint8_t succeed = 0;
|
uint8_t succeed = 0;
|
||||||
int32_t N;
|
int32_t N;
|
||||||
if(!cmd || !*cmd) return 0;
|
if(!cmd || !*cmd) return;
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
if(*cmd == '?'){ // help
|
if(*cmd == '?' || CMP(cmd, "help") == 0){ // help
|
||||||
USB_send("Commands:\n"
|
sendstring("Commands:\n"
|
||||||
CMD_ADCMAX " - max ADC value treshold for trigger\n"
|
|
||||||
CMD_ADCMIN " - min -//- (triggered when ADval>min & <max)\n"
|
|
||||||
CMD_GETADCVAL " - get ADC value\n"
|
|
||||||
CMD_BUZZER "S - turn buzzer ON/OFF\n"
|
CMD_BUZZER "S - turn buzzer ON/OFF\n"
|
||||||
CMD_CURDIST " - show current LIDAR distance\n"
|
CMD_CURDIST " - show current LIDAR distance\n"
|
||||||
CMD_DELLOGS " - delete logs from flash memory\n"
|
CMD_DELLOGS " - delete logs from flash memory\n"
|
||||||
@ -132,9 +137,10 @@ int parse_USBCMD(char *cmd){
|
|||||||
CMD_GPSSTAT " - get GPS status\n"
|
CMD_GPSSTAT " - get GPS status\n"
|
||||||
CMD_GPSSTR " - current GPS data string\n"
|
CMD_GPSSTR " - current GPS data string\n"
|
||||||
CMD_LEDS "S - turn leds on/off (1/0)\n"
|
CMD_LEDS "S - turn leds on/off (1/0)\n"
|
||||||
|
CMD_LIDAR "S - switch between LIDAR (1) or command TTY (0)\n"
|
||||||
|
CMD_LIDARSPEED "N - set LIDAR speed to N\n"
|
||||||
CMD_GETMCUTEMP " - MCU temperature\n"
|
CMD_GETMCUTEMP " - MCU temperature\n"
|
||||||
CMD_NFREE " - warn when free logs space less than this number (0 - not warn)"
|
CMD_NFREE " - warn when free logs space less than this number (0 - not warn)\n"
|
||||||
CMD_PRINTTIME " - print time\n"
|
|
||||||
CMD_RESET " - reset MCU\n"
|
CMD_RESET " - reset MCU\n"
|
||||||
CMD_SAVEEVTS "S - save/don't save (1/0) trigger events into flash\n"
|
CMD_SAVEEVTS "S - save/don't save (1/0) trigger events into flash\n"
|
||||||
CMD_SHOWCONF " - show current configuration\n"
|
CMD_SHOWCONF " - show current configuration\n"
|
||||||
@ -147,11 +153,10 @@ int parse_USBCMD(char *cmd){
|
|||||||
CMD_USARTSPD "N - set USART1 speed to N\n"
|
CMD_USARTSPD "N - set USART1 speed to N\n"
|
||||||
CMD_GETVDD " - Vdd value\n"
|
CMD_GETVDD " - Vdd value\n"
|
||||||
);
|
);
|
||||||
}else if(CMP(cmd, CMD_PRINTTIME) == 0){
|
}else if(CMP(cmd, CMD_PRINTTIME) == 0){ // print current time
|
||||||
USB_send(get_time(¤t_time, get_millis()));
|
sendstring(get_time(¤t_time, get_millis()));
|
||||||
USB_send("\n");
|
sendstring("\n");
|
||||||
}else if(CMP(cmd, CMD_DISTMIN) == 0){ // set low limit
|
}else if(CMP(cmd, CMD_DISTMIN) == 0){ // set low LIDAR limit
|
||||||
DBG("CMD_DISTMIN");
|
|
||||||
GETNUM(CMD_DISTMIN);
|
GETNUM(CMD_DISTMIN);
|
||||||
if(N < 0 || N > 0xffff) goto bad_number;
|
if(N < 0 || N > 0xffff) goto bad_number;
|
||||||
if(the_conf.dist_min != (uint16_t)N){
|
if(the_conf.dist_min != (uint16_t)N){
|
||||||
@ -159,8 +164,7 @@ int parse_USBCMD(char *cmd){
|
|||||||
the_conf.dist_min = (uint16_t) N;
|
the_conf.dist_min = (uint16_t) N;
|
||||||
}
|
}
|
||||||
succeed = 1;
|
succeed = 1;
|
||||||
}else if(CMP(cmd, CMD_DISTMAX) == 0){ // set low limit
|
}else if(CMP(cmd, CMD_DISTMAX) == 0){ // set high LIDAR limit
|
||||||
DBG("CMD_DISTMAX");
|
|
||||||
GETNUM(CMD_DISTMAX);
|
GETNUM(CMD_DISTMAX);
|
||||||
if(N < 0 || N > 0xffff) goto bad_number;
|
if(N < 0 || N > 0xffff) goto bad_number;
|
||||||
if(the_conf.dist_max != (uint16_t)N){
|
if(the_conf.dist_max != (uint16_t)N){
|
||||||
@ -168,11 +172,10 @@ int parse_USBCMD(char *cmd){
|
|||||||
the_conf.dist_max = (uint16_t) N;
|
the_conf.dist_max = (uint16_t) N;
|
||||||
}
|
}
|
||||||
succeed = 1;
|
succeed = 1;
|
||||||
}else if(CMP(cmd, CMD_STORECONF) == 0){ // store everything
|
}else if(CMP(cmd, CMD_STORECONF) == 0){ // store everything in flash
|
||||||
DBG("Store");
|
|
||||||
if(conf_modified){
|
if(conf_modified){
|
||||||
if(store_userconf()){
|
if(store_userconf()){
|
||||||
USB_send("Error: can't save data!\n");
|
sendstring("Error: can't save data!\n");
|
||||||
}else{
|
}else{
|
||||||
conf_modified = 0;
|
conf_modified = 0;
|
||||||
succeed = 1;
|
succeed = 1;
|
||||||
@ -180,107 +183,84 @@ int parse_USBCMD(char *cmd){
|
|||||||
}
|
}
|
||||||
}else if(CMP(cmd, CMD_GPSSTR) == 0){ // show GPS status string
|
}else if(CMP(cmd, CMD_GPSSTR) == 0){ // show GPS status string
|
||||||
showGPSstr = 1;
|
showGPSstr = 1;
|
||||||
}else if(CMP(cmd, CMD_TRIGLVL) == 0){
|
}else if(CMP(cmd, CMD_TRIGLVL) == 0){ // trigger levels: 0->1 or 1->0
|
||||||
DBG("Trig levels");
|
|
||||||
cmd += sizeof(CMD_TRIGLVL) - 1;
|
cmd += sizeof(CMD_TRIGLVL) - 1;
|
||||||
uint8_t Nt = *cmd++ - '0';
|
uint8_t Nt = (uint8_t)(*cmd++ - '0');
|
||||||
if(Nt > TRIGGERS_AMOUNT - 1) goto bad_number;
|
if(Nt > TRIGGERS_AMOUNT - 1) goto bad_number;
|
||||||
uint8_t state = *cmd -'0';
|
uint8_t state = (uint8_t)(*cmd -'0');
|
||||||
if(state > 1) goto bad_number;
|
if(state > 1) goto bad_number;
|
||||||
uint8_t oldval = the_conf.trigstate;
|
uint8_t oldval = the_conf.trigstate;
|
||||||
if(!state) the_conf.trigstate = oldval & ~(1<<Nt);
|
if(!state) the_conf.trigstate = oldval & ~(1<<Nt);
|
||||||
else the_conf.trigstate = oldval | (1<<Nt);
|
else the_conf.trigstate = (uint8_t)(oldval | (1<<Nt));
|
||||||
if(oldval != the_conf.trigstate) conf_modified = 1;
|
if(oldval != the_conf.trigstate) conf_modified = 1;
|
||||||
succeed = 1;
|
succeed = 1;
|
||||||
}else if(CMP(cmd, CMD_SHOWCONF) == 0){
|
}else if(CMP(cmd, CMD_SHOWCONF) == 0){ // print current configuration
|
||||||
showuserconf();
|
showuserconf();
|
||||||
}else if(CMP(cmd, CMD_TRGPAUSE) == 0){
|
}else if(CMP(cmd, CMD_TRGPAUSE) == 0){ // pause after Nth trigger
|
||||||
DBG("Trigger pause");
|
|
||||||
cmd += sizeof(CMD_TRGPAUSE) - 1;
|
cmd += sizeof(CMD_TRGPAUSE) - 1;
|
||||||
uint8_t Nt = *cmd++ - '0';
|
uint8_t Nt = (uint8_t)(*cmd++ - '0');
|
||||||
if(Nt > TRIGGERS_AMOUNT - 1) goto bad_number;
|
if(Nt > TRIGGERS_AMOUNT - 1) goto bad_number;
|
||||||
if(getnum(cmd, &N)) goto bad_number;
|
if(getnum(cmd, &N)) goto bad_number;
|
||||||
if(N < 0 || N > 10000) goto bad_number;
|
if(N < 0 || N > 10000) goto bad_number;
|
||||||
if(the_conf.trigpause[Nt] != N){
|
if(the_conf.trigpause[Nt] != (uint16_t)N){
|
||||||
conf_modified = 1;
|
conf_modified = 1;
|
||||||
the_conf.trigpause[Nt] = N;
|
the_conf.trigpause[Nt] = (uint16_t)N;
|
||||||
}
|
}
|
||||||
succeed = 1;
|
succeed = 1;
|
||||||
}else if(CMP(cmd, CMD_TRGTIME) == 0){
|
}else if(CMP(cmd, CMD_TRGTIME) == 0){ // last trigger time
|
||||||
DBG("Trigger time");
|
|
||||||
cmd += sizeof(CMD_TRGTIME) - 1;
|
cmd += sizeof(CMD_TRGTIME) - 1;
|
||||||
uint8_t Nt = *cmd++ - '0';
|
uint8_t Nt = (uint8_t)(*cmd++ - '0');
|
||||||
if(Nt > TRIGGERS_AMOUNT - 1) goto bad_number;
|
if(Nt > TRIGGERS_AMOUNT - 1) goto bad_number;
|
||||||
show_trigger_shot((uint8_t)1<<Nt);
|
show_trigger_shot((uint8_t)(1<<Nt));
|
||||||
}else if(CMP(cmd, CMD_GETVDD) == 0){
|
}else if(CMP(cmd, CMD_GETVDD) == 0){ // Vdd
|
||||||
USB_send("VDD=");
|
sendstring("VDD=");
|
||||||
uint32_t vdd = getVdd();
|
uint32_t vdd = getVdd();
|
||||||
sendu(vdd/100);
|
sendu(vdd/100);
|
||||||
vdd %= 100;
|
vdd %= 100;
|
||||||
if(vdd < 10) USB_send(".0");
|
if(vdd < 10) sendstring(".0");
|
||||||
else USB_send(".");
|
else sendstring(".");
|
||||||
sendu(vdd);
|
sendu(vdd);
|
||||||
USB_send("\n");
|
sendstring("\n");
|
||||||
}else if(CMP(cmd, CMD_GETMCUTEMP) == 0){
|
}else if(CMP(cmd, CMD_GETMCUTEMP) == 0){ // ~Tmcu
|
||||||
int32_t t = getMCUtemp();
|
int32_t t = getMCUtemp();
|
||||||
USB_send("MCUTEMP=");
|
sendstring("MCUTEMP=");
|
||||||
if(t < 0){
|
if(t < 0){
|
||||||
t = -t;
|
t = -t;
|
||||||
USB_send("-");
|
sendstring("-");
|
||||||
}
|
}
|
||||||
sendu(t/10);
|
sendu(t/10);
|
||||||
USB_send(".");
|
sendstring(".");
|
||||||
sendu(t%10);
|
sendu(t%10);
|
||||||
USB_send("\n");
|
sendstring("\n");
|
||||||
}else if(CMP(cmd, CMD_GETADCVAL) == 0){
|
}else if(CMP(cmd, CMD_LEDS) == 0){ // turn LEDs on/off
|
||||||
USB_send("ADCVAL=");
|
uint8_t Nt = (uint8_t)(cmd[sizeof(CMD_LEDS) - 1] - '0');
|
||||||
sendu(getADCval(0));
|
|
||||||
USB_send("\n");
|
|
||||||
}else if(CMP(cmd, CMD_LEDS) == 0){
|
|
||||||
uint8_t Nt = cmd[sizeof(CMD_LEDS) - 1] - '0';
|
|
||||||
if(Nt > 1) goto bad_number;
|
if(Nt > 1) goto bad_number;
|
||||||
USB_send("LEDS=");
|
sendstring("LEDS=");
|
||||||
if(Nt){
|
if(Nt){
|
||||||
LEDSon = 1;
|
LEDSon = 1;
|
||||||
USB_send("ON\n");
|
sendstring("ON\n");
|
||||||
}else{
|
}else{
|
||||||
LED_off(); // turn off LEDS
|
LED_off(); // turn off LEDS
|
||||||
LED1_off(); // by user request
|
LED1_off(); // by user request
|
||||||
LEDSon = 0;
|
LEDSon = 0;
|
||||||
USB_send("OFF\n");
|
sendstring("OFF\n");
|
||||||
}
|
}
|
||||||
}else if(CMP(cmd, CMD_ADCMAX) == 0){ // set low limit
|
}else if(CMP(cmd, CMD_GPSRESTART) == 0){ // restart GPS
|
||||||
GETNUM(CMD_ADCMAX);
|
sendstring("Send full cold restart to GPS\n");
|
||||||
if(N < -4096 || N > 4096) goto bad_number;
|
|
||||||
if(the_conf.ADC_max != (int16_t)N){
|
|
||||||
conf_modified = 1;
|
|
||||||
the_conf.ADC_max = (int16_t) N;
|
|
||||||
}
|
|
||||||
succeed = 1;
|
|
||||||
}else if(CMP(cmd, CMD_ADCMIN) == 0){ // set low limit
|
|
||||||
GETNUM(CMD_ADCMIN);
|
|
||||||
if(N < -4096 || N > 4096) goto bad_number;
|
|
||||||
if(the_conf.ADC_min != (int16_t)N){
|
|
||||||
conf_modified = 1;
|
|
||||||
the_conf.ADC_min = (int16_t) N;
|
|
||||||
}
|
|
||||||
succeed = 1;
|
|
||||||
}else if(CMP(cmd, CMD_GPSRESTART) == 0){
|
|
||||||
USB_send("Send full cold restart to GPS\n");
|
|
||||||
GPS_send_FullColdStart();
|
GPS_send_FullColdStart();
|
||||||
}else if(CMP(cmd, CMD_BUZZER) == 0){
|
}else if(CMP(cmd, CMD_BUZZER) == 0){
|
||||||
uint8_t Nt = cmd[sizeof(CMD_BUZZER) - 1] - '0';
|
uint8_t Nt = (uint8_t)(cmd[sizeof(CMD_BUZZER) - 1] - '0');
|
||||||
if(Nt > 1) goto bad_number;
|
if(Nt > 1) goto bad_number;
|
||||||
USB_send("BUZZER=");
|
sendstring("BUZZER=");
|
||||||
if(Nt){
|
if(Nt){
|
||||||
buzzer_on = 1;
|
buzzer_on = 1;
|
||||||
USB_send("ON\n");
|
sendstring("ON\n");
|
||||||
}else{
|
}else{
|
||||||
buzzer_on = 0;
|
buzzer_on = 0;
|
||||||
USB_send("OFF\n");
|
sendstring("OFF\n");
|
||||||
}
|
}
|
||||||
}else if(CMP(cmd, CMD_GPSSTAT) == 0){
|
}else if(CMP(cmd, CMD_GPSSTAT) == 0){ // GPS status
|
||||||
USB_send("GPS status: ");
|
sendstring("GPS status: ");
|
||||||
const char *str = "unknown";
|
const char *str = "unknown";
|
||||||
switch(GPS_status){
|
switch(GPS_status){
|
||||||
case GPS_NOTFOUND:
|
case GPS_NOTFOUND:
|
||||||
@ -296,12 +276,12 @@ int parse_USBCMD(char *cmd){
|
|||||||
str = "valid time";
|
str = "valid time";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
USB_send(str);
|
sendstring(str);
|
||||||
if(Tms - last_corr_time < 1500)
|
if(Tms - last_corr_time < 1500)
|
||||||
USB_send(", PPS working\n");
|
sendstring(", PPS working\n");
|
||||||
else
|
else
|
||||||
USB_send(", no PPS\n");
|
sendstring(", no PPS\n");
|
||||||
}else if(CMP(cmd, CMD_USARTSPD) == 0){
|
}else if(CMP(cmd, CMD_USARTSPD) == 0){ // USART speed
|
||||||
GETNUM(CMD_USARTSPD);
|
GETNUM(CMD_USARTSPD);
|
||||||
if(N < 400 || N > 3000000) goto bad_number;
|
if(N < 400 || N > 3000000) goto bad_number;
|
||||||
if(the_conf.USART_speed != (uint32_t)N){
|
if(the_conf.USART_speed != (uint32_t)N){
|
||||||
@ -309,10 +289,18 @@ int parse_USBCMD(char *cmd){
|
|||||||
conf_modified = 1;
|
conf_modified = 1;
|
||||||
}
|
}
|
||||||
succeed = 1;
|
succeed = 1;
|
||||||
}else if(CMP(cmd, CMD_RESET) == 0){
|
}else if(CMP(cmd, CMD_LIDARSPEED) == 0){ // LIDAR speed
|
||||||
USB_send("Soft reset\n");
|
GETNUM(CMD_LIDARSPEED);
|
||||||
|
if(N < 400 || N > 3000000) goto bad_number;
|
||||||
|
if(the_conf.LIDAR_speed != (uint32_t)N){
|
||||||
|
the_conf.LIDAR_speed = (uint32_t)N;
|
||||||
|
conf_modified = 1;
|
||||||
|
}
|
||||||
|
succeed = 1;
|
||||||
|
}else if(CMP(cmd, CMD_RESET) == 0){ // Reset MCU
|
||||||
|
sendstring("Soft reset\n");
|
||||||
NVIC_SystemReset();
|
NVIC_SystemReset();
|
||||||
}else if(CMP(cmd, CMD_STREND) == 0){
|
}else if(CMP(cmd, CMD_STREND) == 0){ // string ends in '\n' or "\r\n"
|
||||||
char c = cmd[sizeof(CMD_STREND) - 1];
|
char c = cmd[sizeof(CMD_STREND) - 1];
|
||||||
succeed = 1;
|
succeed = 1;
|
||||||
if(c == 'n' || c == 'N'){
|
if(c == 'n' || c == 'N'){
|
||||||
@ -327,29 +315,29 @@ int parse_USBCMD(char *cmd){
|
|||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
succeed = 0;
|
succeed = 0;
|
||||||
USB_send("Bad letter, should be 'n' or 'r'\n");
|
sendstring("Bad letter, should be 'n' or 'r'\n");
|
||||||
}
|
}
|
||||||
}else if(CMP(cmd, CMD_FLASH) == 0){ // show flash size
|
}else if(CMP(cmd, CMD_FLASH) == 0){ // show flash size
|
||||||
USB_send("FLASHSIZE=");
|
sendstring("FLASHSIZE=");
|
||||||
sendu(FLASH_SIZE);
|
sendu(FLASH_SIZE);
|
||||||
USB_send("kB\nFLASH_BASE=");
|
sendstring("kB\nFLASH_BASE=");
|
||||||
USB_send(u2hex(FLASH_BASE));
|
sendstring(u2hex(FLASH_BASE));
|
||||||
USB_send("\nFlash_Data=");
|
sendstring("\nFlash_Data=");
|
||||||
USB_send(u2hex((uint32_t)Flash_Data));
|
sendstring(u2hex((uint32_t)Flash_Data));
|
||||||
USB_send("\nvarslen=");
|
sendstring("\nvarslen=");
|
||||||
sendu((uint32_t)&_varslen);
|
sendu((uint32_t)&_varslen);
|
||||||
USB_send("\nCONFsize=");
|
sendstring("\nCONFsize=");
|
||||||
sendu(sizeof(user_conf));
|
sendu(sizeof(user_conf));
|
||||||
USB_send("\nNconf_records=");
|
sendstring("\nNconf_records=");
|
||||||
sendu(maxCnum - 1);
|
sendu(maxCnum - 1);
|
||||||
USB_send("\nlogsstart=");
|
sendstring("\nlogsstart=");
|
||||||
USB_send(u2hex((uint32_t)logsstart));
|
sendstring(u2hex((uint32_t)logsstart));
|
||||||
USB_send("\nLOGsize=");
|
sendstring("\nLOGsize=");
|
||||||
sendu(sizeof(event_log));
|
sendu(sizeof(event_log));
|
||||||
USB_send("\nNlogs_records=");
|
sendstring("\nNlogs_records=");
|
||||||
sendu(maxLnum - 1);
|
sendu(maxLnum - 1);
|
||||||
USB_send("\n");
|
sendstring("\n");
|
||||||
}else if(CMP(cmd, CMD_SAVEEVTS) == 0){
|
}else if(CMP(cmd, CMD_SAVEEVTS) == 0){ // save all events
|
||||||
if('0' == cmd[sizeof(CMD_SAVEEVTS) - 1]){
|
if('0' == cmd[sizeof(CMD_SAVEEVTS) - 1]){
|
||||||
if(the_conf.defflags & FLAG_SAVE_EVENTS){
|
if(the_conf.defflags & FLAG_SAVE_EVENTS){
|
||||||
conf_modified = 1;
|
conf_modified = 1;
|
||||||
@ -362,12 +350,12 @@ int parse_USBCMD(char *cmd){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
succeed = 1;
|
succeed = 1;
|
||||||
}else if(CMP(cmd, CMD_DUMP) == 0){
|
}else if(CMP(cmd, CMD_DUMP) == 0){ // dump N last events
|
||||||
if(getnum(cmd+sizeof(CMD_DUMP)-1, &N)) N = -20; // default - without N
|
if(getnum(cmd+sizeof(CMD_DUMP)-1, &N)) N = -20; // default - without N
|
||||||
else N = -N;
|
else N = -N;
|
||||||
if(N > 0) N = 0;
|
if(N > 0) N = 0;
|
||||||
if(dump_log(N, -1)) USB_send("Event log empty!\n");
|
if(dump_log(N, -1)) sendstring("Event log empty!\n");
|
||||||
}else if(CMP(cmd, CMD_NFREE) == 0){
|
}else if(CMP(cmd, CMD_NFREE) == 0){ // warn if there's less than N free cells for logs in flash
|
||||||
GETNUM(CMD_NFREE);
|
GETNUM(CMD_NFREE);
|
||||||
if(N < 0 || N > 0xffff) goto bad_number;
|
if(N < 0 || N > 0xffff) goto bad_number;
|
||||||
if(the_conf.NLfreeWarn != (uint16_t)N){
|
if(the_conf.NLfreeWarn != (uint16_t)N){
|
||||||
@ -375,10 +363,10 @@ int parse_USBCMD(char *cmd){
|
|||||||
the_conf.NLfreeWarn = (uint16_t)N;
|
the_conf.NLfreeWarn = (uint16_t)N;
|
||||||
}
|
}
|
||||||
succeed = 1;
|
succeed = 1;
|
||||||
}else if(CMP(cmd, CMD_DELLOGS) == 0){
|
}else if(CMP(cmd, CMD_DELLOGS) == 0){ // delete all logs
|
||||||
if(store_log(NULL)) USB_send("Error during erasing flash\n");
|
if(store_log(NULL)) sendstring("Error during erasing flash\n");
|
||||||
else USB_send("All logs erased\n");
|
else sendstring("All logs erased\n");
|
||||||
}else if(CMP(cmd, CMD_GPSPROXY) == 0){
|
}else if(CMP(cmd, CMD_GPSPROXY) == 0){ // proxy GPS data over USART1
|
||||||
if(cmd[sizeof(CMD_GPSPROXY) - 1] == '0'){
|
if(cmd[sizeof(CMD_GPSPROXY) - 1] == '0'){
|
||||||
if(the_conf.defflags & FLAG_GPSPROXY){
|
if(the_conf.defflags & FLAG_GPSPROXY){
|
||||||
conf_modified = 1;
|
conf_modified = 1;
|
||||||
@ -391,29 +379,46 @@ int parse_USBCMD(char *cmd){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
succeed = 1;
|
succeed = 1;
|
||||||
}else if(CMP(cmd, CMD_CURDIST) == 0){
|
}else if(CMP(cmd, CMD_CURDIST) == 0){ // current LIDAR distance
|
||||||
USB_send("DIST=");
|
sendstring("DIST=");
|
||||||
sendu(last_lidar_dist);
|
sendu(last_lidar_dist);
|
||||||
USB_send("\nSTREN=");
|
sendstring("\nSTREN=");
|
||||||
sendu(last_lidar_stren);
|
sendu(last_lidar_stren);
|
||||||
USB_send("\nTRIGDIST=");
|
sendstring("\nTRIGDIST=");
|
||||||
sendu(lidar_triggered_dist);
|
sendu(lidar_triggered_dist);
|
||||||
USB_send("\nTms=");
|
sendstring("\nTms=");
|
||||||
sendu(Tms);
|
sendu(Tms);
|
||||||
USB_send("\nshotms=");
|
sendstring("\nshotms=");
|
||||||
sendu(shotms[LIDAR_TRIGGER]);
|
sendu(shotms[LIDAR_TRIGGER]);
|
||||||
USB_send("\n");
|
sendstring("\n");
|
||||||
}else return 1;
|
}else if(CMP(cmd, CMD_LIDAR) == 0){ // turn LIDAR on/off
|
||||||
|
if(cmd[sizeof(CMD_LIDAR) - 1] == '0'){
|
||||||
|
if(!(the_conf.defflags & FLAG_NOLIDAR)){
|
||||||
|
conf_modified = 1;
|
||||||
|
the_conf.defflags |= FLAG_NOLIDAR;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(the_conf.defflags & FLAG_NOLIDAR){
|
||||||
|
conf_modified = 1;
|
||||||
|
the_conf.defflags &= ~FLAG_NOLIDAR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
succeed = 1;
|
||||||
|
}else{
|
||||||
|
sendstring("Bad command: ");
|
||||||
|
sendstring(oldcmd);
|
||||||
|
sendstring("\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
/*else if(CMP(cmd, CMD_) == 0){
|
/*else if(CMP(cmd, CMD_) == 0){
|
||||||
;
|
;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
if(succeed) USB_send("Success!\n");
|
if(succeed) sendstring("Success!\n");
|
||||||
return 0;
|
return;
|
||||||
bad_number:
|
bad_number:
|
||||||
USB_send("Error: bad number!\n");
|
sendstring("Error: bad number!\n");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -453,7 +458,7 @@ char *get_trigger_shot(int number, const event_log *logdata){
|
|||||||
*/
|
*/
|
||||||
void show_trigger_shot(uint8_t tshot){
|
void show_trigger_shot(uint8_t tshot){
|
||||||
uint8_t X = 1;
|
uint8_t X = 1;
|
||||||
for(int i = 0; i < TRIGGERS_AMOUNT && tshot; ++i, X <<= 1){
|
for(uint8_t i = 0; i < TRIGGERS_AMOUNT && tshot; ++i, X <<= 1){
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
if(tshot & X) tshot &= ~X;
|
if(tshot & X) tshot &= ~X;
|
||||||
else continue;
|
else continue;
|
||||||
@ -463,9 +468,9 @@ void show_trigger_shot(uint8_t tshot){
|
|||||||
if(i == LIDAR_TRIGGER) l.lidar_dist = lidar_triggered_dist;
|
if(i == LIDAR_TRIGGER) l.lidar_dist = lidar_triggered_dist;
|
||||||
l.shottime = shottime[i];
|
l.shottime = shottime[i];
|
||||||
l.triglen = triglen[i];
|
l.triglen = triglen[i];
|
||||||
USB_send(get_trigger_shot(-1, &l));
|
sendstring(get_trigger_shot(-1, &l));
|
||||||
if(the_conf.defflags & FLAG_SAVE_EVENTS){
|
if(the_conf.defflags & FLAG_SAVE_EVENTS){
|
||||||
if(store_log(&l)) USB_send("\n\nError saving event!\n\n");
|
if(store_log(&l)) sendstring("\n\nError saving event!\n\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -560,3 +565,33 @@ char *u2hex(uint32_t val){
|
|||||||
*bufptr = 0;
|
*bufptr = 0;
|
||||||
return strbuf;
|
return strbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char localbuffer[LOCBUFSZ];
|
||||||
|
static uint8_t bufidx = 0;
|
||||||
|
static void transmitlocbuf(){
|
||||||
|
localbuffer[bufidx] = 0;
|
||||||
|
USB_send(localbuffer);
|
||||||
|
if(!(the_conf.defflags & FLAG_GPSPROXY)){ // USART1 isn't a GPS proxy
|
||||||
|
usart_send(1, localbuffer);
|
||||||
|
transmit_tbuf(1);
|
||||||
|
}
|
||||||
|
if(the_conf.defflags & FLAG_NOLIDAR){ // USART3 isn't a LIDAR
|
||||||
|
usart_send(LIDAR_USART, localbuffer);
|
||||||
|
transmit_tbuf(LIDAR_USART);
|
||||||
|
}
|
||||||
|
bufidx = 0;
|
||||||
|
}
|
||||||
|
// add char to buf
|
||||||
|
void sendchar(char ch){
|
||||||
|
localbuffer[bufidx++] = ch;
|
||||||
|
if(bufidx >= LOCBUFSZ-1) transmitlocbuf();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief addtobuf - add to local buffer any zero-terminated substring
|
||||||
|
* @param str - string to add
|
||||||
|
* it sends data to USB and (due to setup) USART1 when buffer will be full or when meet '\n' at the end of str
|
||||||
|
*/
|
||||||
|
void sendstring(const char *str){
|
||||||
|
while(*str) sendchar(*str++);
|
||||||
|
if(str[-1] == '\n') transmitlocbuf();
|
||||||
|
}
|
||||||
|
|||||||
@ -23,36 +23,37 @@
|
|||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
|
|
||||||
// usb commands
|
// local buffer size (chars)
|
||||||
// lower and upper limits to capture
|
#define LOCBUFSZ 128
|
||||||
#define CMD_DISTMIN "distmin"
|
|
||||||
|
// TTY commands
|
||||||
|
#define CMD_BUZZER "buzzer"
|
||||||
|
#define CMD_CURDIST "curdist"
|
||||||
|
#define CMD_DELLOGS "deletelogs"
|
||||||
#define CMD_DISTMAX "distmax"
|
#define CMD_DISTMAX "distmax"
|
||||||
#define CMD_ADCMIN "adcmin"
|
#define CMD_DISTMIN "distmin"
|
||||||
#define CMD_ADCMAX "adcmax"
|
#define CMD_DUMP "dump"
|
||||||
#define CMD_PRINTTIME "time"
|
#define CMD_FLASH "flash"
|
||||||
#define CMD_STORECONF "store"
|
#define CMD_GETMCUTEMP "mcutemp"
|
||||||
|
#define CMD_GETVDD "vdd"
|
||||||
|
#define CMD_GPSPROXY "gpsproxy"
|
||||||
|
#define CMD_GPSRESTART "gpsrestart"
|
||||||
|
#define CMD_GPSSTAT "gpsstat"
|
||||||
#define CMD_GPSSTR "gpsstring"
|
#define CMD_GPSSTR "gpsstring"
|
||||||
|
#define CMD_LEDS "leds"
|
||||||
|
#define CMD_LIDAR "lidar"
|
||||||
|
#define CMD_LIDARSPEED "lidspd"
|
||||||
|
#define CMD_NFREE "nfree"
|
||||||
|
#define CMD_PRINTTIME "time"
|
||||||
|
#define CMD_RESET "reset"
|
||||||
|
#define CMD_SAVEEVTS "se"
|
||||||
#define CMD_SHOWCONF "showconf"
|
#define CMD_SHOWCONF "showconf"
|
||||||
#define CMD_TRIGLVL "triglevel"
|
#define CMD_STORECONF "store"
|
||||||
|
#define CMD_STREND "strend"
|
||||||
#define CMD_TRGPAUSE "trigpause"
|
#define CMD_TRGPAUSE "trigpause"
|
||||||
#define CMD_TRGTIME "trigtime"
|
#define CMD_TRGTIME "trigtime"
|
||||||
#define CMD_GETVDD "vdd"
|
#define CMD_TRIGLVL "triglevel"
|
||||||
#define CMD_GETMCUTEMP "mcutemp"
|
|
||||||
#define CMD_GETADCVAL "adcval"
|
|
||||||
#define CMD_LEDS "leds"
|
|
||||||
#define CMD_GPSRESTART "gpsrestart"
|
|
||||||
#define CMD_BUZZER "buzzer"
|
|
||||||
#define CMD_GPSSTAT "gpsstat"
|
|
||||||
#define CMD_USARTSPD "usartspd"
|
#define CMD_USARTSPD "usartspd"
|
||||||
#define CMD_RESET "reset"
|
|
||||||
#define CMD_STREND "strend"
|
|
||||||
#define CMD_FLASH "flash"
|
|
||||||
#define CMD_SAVEEVTS "se"
|
|
||||||
#define CMD_DUMP "dump"
|
|
||||||
#define CMD_NFREE "nfree"
|
|
||||||
#define CMD_DELLOGS "deletelogs"
|
|
||||||
#define CMD_GPSPROXY "gpsproxy"
|
|
||||||
#define CMD_CURDIST "curdist"
|
|
||||||
|
|
||||||
extern uint8_t showGPSstr;
|
extern uint8_t showGPSstr;
|
||||||
|
|
||||||
@ -64,7 +65,9 @@ int strln(const char *s);
|
|||||||
char *strcp(char* dst, const char *src);
|
char *strcp(char* dst, const char *src);
|
||||||
int cmpstr(const char *s1, const char *s2, int n);
|
int cmpstr(const char *s1, const char *s2, int n);
|
||||||
char *getchr(const char *str, char symbol);
|
char *getchr(const char *str, char symbol);
|
||||||
int parse_USBCMD(char *cmd);
|
void parse_CMD(char *cmd);
|
||||||
char *get_trigger_shot(int number, const event_log *logdata);
|
char *get_trigger_shot(int number, const event_log *logdata);
|
||||||
void show_trigger_shot(uint8_t trigger_shot);
|
void show_trigger_shot(uint8_t trigger_shot);
|
||||||
|
void sendstring(const char *str);
|
||||||
|
void sendchar(char ch);
|
||||||
#endif // STR_H__
|
#endif // STR_H__
|
||||||
|
|||||||
@ -27,8 +27,9 @@
|
|||||||
volatile uint32_t Timer; // milliseconds counter
|
volatile uint32_t Timer; // milliseconds counter
|
||||||
curtime current_time = TMNOTINI;
|
curtime current_time = TMNOTINI;
|
||||||
|
|
||||||
|
// convert two-digit decimal string into number
|
||||||
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 (uint8_t)((b[0]-'0')*10 + b[1]-'0');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,11 +42,13 @@ void set_time(const char *buf){
|
|||||||
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
|
#ifdef EBUG
|
||||||
SEND("set_time, Tms: "); printu(1, Tms);
|
SEND("set_time, Tms: "); printu(1, Tms);
|
||||||
SEND("; Timer: "); printu(1, Timer);
|
SEND("; Timer: "); printu(1, Timer);
|
||||||
newline();
|
newline(1);
|
||||||
#endif
|
#endif
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,12 +65,6 @@ void time_increment(){
|
|||||||
current_time.H = 0;
|
current_time.H = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
#ifdef EBUG
|
|
||||||
SEND("time_increment(): ");
|
|
||||||
SEND(get_time(¤t_time, 0));
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *puttwo(uint8_t N, char *buf){
|
static char *puttwo(uint8_t N, char *buf){
|
||||||
@ -77,7 +74,7 @@ static char *puttwo(uint8_t N, char *buf){
|
|||||||
*buf++ = N/10 + '0';
|
*buf++ = N/10 + '0';
|
||||||
N %= 10;
|
N %= 10;
|
||||||
}
|
}
|
||||||
*buf++ = N + '0';
|
*buf++ = (char)(N + '0');
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,14 +87,14 @@ static void ms2str(char **str, uint32_t T){
|
|||||||
char *bptr = *str;
|
char *bptr = *str;
|
||||||
*bptr++ = '.';
|
*bptr++ = '.';
|
||||||
if(T > 99){
|
if(T > 99){
|
||||||
*bptr++ = T/100 + '0';
|
*bptr++ = (char)(T/100 + '0');
|
||||||
T %= 100;
|
T %= 100;
|
||||||
}else *bptr++ = '0';
|
}else *bptr++ = '0';
|
||||||
if(T > 9){
|
if(T > 9){
|
||||||
*bptr++ = T/10 + '0';
|
*bptr++ = (char)(T/10 + '0');
|
||||||
T %= 10;
|
T %= 10;
|
||||||
}else *bptr++ = '0';
|
}else *bptr++ = '0';
|
||||||
*bptr++ = T + '0';
|
*bptr++ = (char)(T + '0');
|
||||||
*str = bptr;
|
*str = bptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,10 +132,11 @@ char *get_time(const curtime *Tm, uint32_t T){
|
|||||||
|
|
||||||
|
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
int32_t timerval, Tms1;
|
uint32_t timerval, Tms1;
|
||||||
#endif
|
|
||||||
int32_t timecntr=0, ticksdiff=0;
|
int32_t timecntr=0, ticksdiff=0;
|
||||||
|
#else
|
||||||
|
static int32_t timecntr=0, ticksdiff=0;
|
||||||
|
#endif
|
||||||
uint32_t last_corr_time = 0;
|
uint32_t last_corr_time = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,8 +156,8 @@ uint32_t last_corr_time = 0;
|
|||||||
*/
|
*/
|
||||||
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
|
||||||
uint32_t systick_val = SysTick->VAL, L = SysTick->LOAD + 1;
|
int32_t systick_val = (int32_t)SysTick->VAL, L = (int32_t)SysTick->LOAD + 1;
|
||||||
int32_t timer_val = Timer;
|
uint32_t timer_val = Timer;
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
timerval = Timer;
|
timerval = Timer;
|
||||||
Tms1 = Tms;
|
Tms1 = Tms;
|
||||||
@ -170,20 +168,18 @@ void systick_correction(){
|
|||||||
// if(systick_val != SysTick->LOAD) ++Tms;
|
// if(systick_val != SysTick->LOAD) ++Tms;
|
||||||
if(timer_val > 500) time_increment(); // counter greater than 500 -> need to increment time
|
if(timer_val > 500) time_increment(); // counter greater than 500 -> need to increment time
|
||||||
if(last_corr_time){
|
if(last_corr_time){
|
||||||
if(Tms - last_corr_time < 1500){ // there was perevious PPS signal
|
uint32_t Tdiff = Tms - last_corr_time;
|
||||||
int32_t D = L * (Tms - 1000 - last_corr_time) + (SysTick->LOAD - systick_val); // amount of spare ticks
|
if(Tdiff < 1500 && Tdiff > 700){ // there was perevious PPS signal ~1s ago
|
||||||
#ifdef EBUG
|
int32_t D = L * ((int32_t)(Tms - 1000 - last_corr_time)) + ((int32_t)SysTick->LOAD - systick_val); // amount of spare ticks
|
||||||
++timecntr;
|
++timecntr;
|
||||||
#endif
|
|
||||||
ticksdiff += D;
|
ticksdiff += D;
|
||||||
uint32_t ticksabs = (ticksdiff < 0) ? -ticksdiff : ticksdiff;
|
uint32_t ticksabs = (ticksdiff < 0) ? (uint32_t)-ticksdiff : (uint32_t)ticksdiff;
|
||||||
// 10000 == 30 seconds * 1000 interrupts per second
|
// 30000 == 30 seconds * 1000 interrupts per second
|
||||||
if(ticksabs > 30000 && timecntr > 30){ // need correction (not more often than each 10s)
|
if(ticksabs > 30000 && timecntr > 10){ // need correction (not more often than each 10s)
|
||||||
ticksdiff /= timecntr * 1000; // correction per one interrupt
|
ticksdiff /= timecntr * 1000; // correction per one interrupt
|
||||||
SysTick->LOAD += ticksdiff;
|
SysTick->LOAD = (uint32_t)(ticksdiff + (int32_t)SysTick->LOAD);
|
||||||
timecntr = 0;
|
timecntr = 0;
|
||||||
ticksdiff = 0;
|
ticksdiff = 0;
|
||||||
last_corr_time = 0;
|
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
SEND("Correction\n");
|
SEND("Correction\n");
|
||||||
#endif
|
#endif
|
||||||
@ -191,7 +187,6 @@ void systick_correction(){
|
|||||||
}else{
|
}else{
|
||||||
timecntr = 0;
|
timecntr = 0;
|
||||||
ticksdiff = 0;
|
ticksdiff = 0;
|
||||||
last_corr_time = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last_corr_time = Tms;
|
last_corr_time = Tms;
|
||||||
|
|||||||
@ -43,6 +43,10 @@ typedef struct{
|
|||||||
uint8_t S;
|
uint8_t S;
|
||||||
} curtime;
|
} curtime;
|
||||||
|
|
||||||
|
#ifdef EBUG
|
||||||
|
extern int32_t ticksdiff, timecntr;
|
||||||
|
extern uint32_t timerval, Tms1;
|
||||||
|
#endif
|
||||||
extern volatile uint32_t Tms;
|
extern volatile uint32_t Tms;
|
||||||
extern volatile uint32_t Timer;
|
extern volatile uint32_t Timer;
|
||||||
extern curtime current_time;
|
extern curtime current_time;
|
||||||
|
|||||||
@ -24,17 +24,18 @@
|
|||||||
#include "usart.h"
|
#include "usart.h"
|
||||||
|
|
||||||
extern volatile uint32_t Tms;
|
extern volatile uint32_t Tms;
|
||||||
static volatile int idatalen[4][2] = {0}; // received data line length (including '\n')
|
static volatile uint8_t idatalen[4][2] = {{0}}; // received data line length (including '\n')
|
||||||
static volatile int odatalen[4][2] = {0};
|
static volatile uint8_t odatalen[4][2] = {{0}};
|
||||||
|
|
||||||
volatile int linerdy[4] = {0}, // received data ready
|
static volatile uint8_t dlen[4] = {0}; // length of data (including '\n') in current buffer
|
||||||
dlen[4] = {0}, // length of data (including '\n') in current buffer
|
|
||||||
|
volatile uint8_t linerdy[4] = {0}, // received data ready
|
||||||
bufovr[4] = {0}, // input buffer overfull
|
bufovr[4] = {0}, // input buffer overfull
|
||||||
txrdy[4] = {0,1,1,1} // transmission done
|
txrdy[4] = {0,1,1,1} // transmission done
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
int rbufno[4] = {0}, tbufno[4] = {0}; // current rbuf/tbuf numbers
|
static uint8_t rbufno[4] = {0}, tbufno[4] = {0}; // current rbuf/tbuf numbers
|
||||||
static char rbuf[4][2][UARTBUFSZ], tbuf[4][2][UARTBUFSZ]; // receive & transmit buffers
|
static char rbuf[4][2][UARTBUFSZ], tbuf[4][2][UARTBUFSZ]; // receive & transmit buffers
|
||||||
static char *recvdata[4] = {0};
|
static char *recvdata[4] = {0};
|
||||||
|
|
||||||
@ -53,17 +54,9 @@ int usart_getline(int n, char **line){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// transmit current tbuf and swap buffers
|
// transmit current tbuf and swap buffers
|
||||||
void transmit_tbuf(int n){
|
void transmit_tbuf(uint8_t n){
|
||||||
if(n < 1 || n > 3) return;
|
|
||||||
uint32_t tmout = 72000;
|
|
||||||
while(!txrdy[n]){if(--tmout == 0) return;}; // wait for previos buffer transmission
|
|
||||||
register int l = odatalen[n][tbufno[n]];
|
|
||||||
if(!l) return;
|
|
||||||
txrdy[n] = 0;
|
|
||||||
odatalen[n][tbufno[n]] = 0;
|
|
||||||
DMA_Channel_TypeDef *DMA;
|
DMA_Channel_TypeDef *DMA;
|
||||||
IWDG->KR = IWDG_REFRESH;
|
switch(n){ // also check if n wrong
|
||||||
switch(n){
|
|
||||||
case 1:
|
case 1:
|
||||||
DMA = DMA1_Channel4;
|
DMA = DMA1_Channel4;
|
||||||
break;
|
break;
|
||||||
@ -73,7 +66,15 @@ void transmit_tbuf(int n){
|
|||||||
case 3:
|
case 3:
|
||||||
DMA = DMA1_Channel2;
|
DMA = DMA1_Channel2;
|
||||||
break;
|
break;
|
||||||
|
default: return;
|
||||||
}
|
}
|
||||||
|
uint32_t tmout = 72000;
|
||||||
|
while(!txrdy[n]){if(--tmout == 0) return;} // wait for previos buffer transmission
|
||||||
|
register uint32_t l = odatalen[n][tbufno[n]];
|
||||||
|
if(!l) return;
|
||||||
|
txrdy[n] = 0;
|
||||||
|
odatalen[n][tbufno[n]] = 0;
|
||||||
|
IWDG->KR = IWDG_REFRESH;
|
||||||
DMA->CCR &= ~DMA_CCR_EN;
|
DMA->CCR &= ~DMA_CCR_EN;
|
||||||
DMA->CMAR = (uint32_t) tbuf[n][tbufno[n]]; // mem
|
DMA->CMAR = (uint32_t) tbuf[n][tbufno[n]]; // mem
|
||||||
DMA->CNDTR = l;
|
DMA->CNDTR = l;
|
||||||
@ -81,12 +82,14 @@ void transmit_tbuf(int n){
|
|||||||
tbufno[n] = !tbufno[n];
|
tbufno[n] = !tbufno[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
void usart_putchar(int n, char ch){
|
void usart_putchar(uint8_t n, char ch){
|
||||||
|
if(!n || n > USART_LAST+1) return;
|
||||||
for(int i = 0; odatalen[n][tbufno[n]] == UARTBUFSZ && i < 1024; ++i) transmit_tbuf(n);
|
for(int i = 0; odatalen[n][tbufno[n]] == UARTBUFSZ && i < 1024; ++i) transmit_tbuf(n);
|
||||||
tbuf[n][tbufno[n]][odatalen[n][tbufno[n]]++] = ch;
|
tbuf[n][tbufno[n]][odatalen[n][tbufno[n]]++] = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usart_send(int n, const char *str){
|
void usart_send(uint8_t n, const char *str){
|
||||||
|
if(!n || n > USART_LAST+1) return;
|
||||||
uint32_t x = 512;
|
uint32_t x = 512;
|
||||||
while(*str && --x){
|
while(*str && --x){
|
||||||
if(odatalen[n][tbufno[n]] == UARTBUFSZ){
|
if(odatalen[n][tbufno[n]] == UARTBUFSZ){
|
||||||
@ -96,13 +99,15 @@ void usart_send(int n, const char *str){
|
|||||||
tbuf[n][tbufno[n]][odatalen[n][tbufno[n]]++] = *str++;
|
tbuf[n][tbufno[n]][odatalen[n][tbufno[n]]++] = *str++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if defined EBUG
|
|
||||||
// only for USART1
|
// send newline ("\r" or "\r\n") and transmit whole buffer
|
||||||
void newline(){
|
// for GPS_USART endline always is "\r\n"
|
||||||
usart_putchar(1, '\n');
|
// @param n - USART number
|
||||||
transmit_tbuf(1);
|
void newline(uint8_t n){
|
||||||
|
if((the_conf.defflags & FLAG_STRENDRN) || n == GPS_USART) usart_putchar(n, '\r');
|
||||||
|
usart_putchar(n, '\n');
|
||||||
|
transmit_tbuf(n);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* USART speed: baudrate = Fck/(USARTDIV)
|
* USART speed: baudrate = Fck/(USARTDIV)
|
||||||
@ -111,7 +116,7 @@ void newline(){
|
|||||||
* for 72MHz USARTDIV=72000/f(kboud); so for 115200 USARTDIV=72000/115.2=625 -> BRR=0x271
|
* for 72MHz USARTDIV=72000/f(kboud); so for 115200 USARTDIV=72000/115.2=625 -> BRR=0x271
|
||||||
* 9600: BRR = 7500 (0x1D4C)
|
* 9600: BRR = 7500 (0x1D4C)
|
||||||
*/
|
*/
|
||||||
static void usart_setup(int n, uint32_t BRR){
|
static void usart_setup(uint8_t n, uint16_t BRR){
|
||||||
DMA_Channel_TypeDef *DMA;
|
DMA_Channel_TypeDef *DMA;
|
||||||
IRQn_Type DMAirqN, USARTirqN;
|
IRQn_Type DMAirqN, USARTirqN;
|
||||||
USART_TypeDef *USART;
|
USART_TypeDef *USART;
|
||||||
@ -171,12 +176,12 @@ static void usart_setup(int n, uint32_t BRR){
|
|||||||
void usarts_setup(){
|
void usarts_setup(){
|
||||||
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
|
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
|
||||||
usart_setup(1, 72000000 / the_conf.USART_speed); // debug console or GPS proxy
|
usart_setup(1, 72000000 / the_conf.USART_speed); // debug console or GPS proxy
|
||||||
usart_setup(2, 36000000 / 9600); // GPS
|
usart_setup(GPS_USART, 36000000 / GPS_DEFAULT_SPEED); // GPS
|
||||||
usart_setup(3, 36000000 / 115200); // LIDAR
|
usart_setup(LIDAR_USART, 36000000 / the_conf.LIDAR_speed); // LIDAR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void usart_isr(int n, USART_TypeDef *USART){
|
static void usart_isr(uint8_t n, USART_TypeDef *USART){
|
||||||
#ifdef CHECK_TMOUT
|
#ifdef CHECK_TMOUT
|
||||||
static uint32_t tmout[n] = 0;
|
static uint32_t tmout[n] = 0;
|
||||||
#endif
|
#endif
|
||||||
@ -190,12 +195,13 @@ void usart_isr(int n, USART_TypeDef *USART){
|
|||||||
tmout[n] = Tms + TIMEOUT_MS;
|
tmout[n] = Tms + TIMEOUT_MS;
|
||||||
if(!tmout[n]) tmout[n] = 1; // prevent 0
|
if(!tmout[n]) tmout[n] = 1; // prevent 0
|
||||||
#endif
|
#endif
|
||||||
uint8_t rb = USART->DR;
|
char rb = (char)USART->DR;
|
||||||
if(idatalen[n][rbufno[n]] < UARTBUFSZ){ // put next char into buf
|
if(idatalen[n][rbufno[n]] < UARTBUFSZ){ // put next char into buf
|
||||||
rbuf[n][rbufno[n]][idatalen[n][rbufno[n]]++] = rb;
|
if(rb != '\r') rbuf[n][rbufno[n]][idatalen[n][rbufno[n]]++] = rb; // omit '\r'
|
||||||
if(rb == '\n'){ // got newline - line ready
|
if(rb == '\n'){ // got newline - line ready
|
||||||
linerdy[n] = 1;
|
linerdy[n] = 1;
|
||||||
dlen[n] = idatalen[n][rbufno[n]];
|
dlen[n] = idatalen[n][rbufno[n]];
|
||||||
|
rbuf[n][rbufno[n]][dlen[n]] = 0;
|
||||||
recvdata[n] = rbuf[n][rbufno[n]];
|
recvdata[n] = rbuf[n][rbufno[n]];
|
||||||
// prepare other buffer
|
// prepare other buffer
|
||||||
rbufno[n] = !rbufno[n];
|
rbufno[n] = !rbufno[n];
|
||||||
@ -226,9 +232,15 @@ void usart2_isr(){
|
|||||||
|
|
||||||
// LIDAR_USART
|
// LIDAR_USART
|
||||||
void usart3_isr(){
|
void usart3_isr(){
|
||||||
|
if(the_conf.defflags & FLAG_NOLIDAR){ // regular TTY
|
||||||
|
usart_isr(3, USART3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// LIDAR - check for different things
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
if(USART3->SR & USART_SR_RXNE){ // RX not emty - receive next char
|
if(USART3->SR & USART_SR_RXNE){ // RX not emty - receive next char
|
||||||
uint8_t rb = USART3->DR, L = idatalen[3][rbufno[3]];
|
char rb = (char)USART3->DR;
|
||||||
|
uint8_t L = idatalen[3][rbufno[3]];
|
||||||
if(rb != LIDAR_FRAME_HEADER && (L == 0 || L == 1)){ // bad starting sequence
|
if(rb != LIDAR_FRAME_HEADER && (L == 0 || L == 1)){ // bad starting sequence
|
||||||
idatalen[3][rbufno[3]] = 0;
|
idatalen[3][rbufno[3]] = 0;
|
||||||
return;
|
return;
|
||||||
@ -250,12 +262,12 @@ void usart3_isr(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// print 32bit unsigned int
|
// print 32bit unsigned int
|
||||||
void printu(int n, uint32_t val){
|
void printu(uint8_t n, uint32_t val){
|
||||||
usart_send(n, u2str(val));
|
usart_send(n, u2str(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
// print 32bit unsigned int as hex
|
// print 32bit unsigned int as hex
|
||||||
void printuhex(int n, uint32_t val){
|
void printuhex(uint8_t n, uint32_t val){
|
||||||
usart_send(n, u2hex(val));
|
usart_send(n, u2hex(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,15 +22,22 @@
|
|||||||
|
|
||||||
#include <stm32f1.h>
|
#include <stm32f1.h>
|
||||||
|
|
||||||
// input and output buffers size
|
// input and output buffers size (should be less than 256!!!)
|
||||||
#define UARTBUFSZ (128)
|
#define UARTBUFSZ (128)
|
||||||
// timeout between data bytes
|
// timeout between data bytes
|
||||||
#ifndef TIMEOUT_MS
|
#ifndef TIMEOUT_MS
|
||||||
#define TIMEOUT_MS (1500)
|
#define TIMEOUT_MS (1500)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// number of last USART used
|
||||||
|
#define USART_LAST 3
|
||||||
|
|
||||||
// USART1 default speed
|
// USART1 default speed
|
||||||
#define USART1_DEFAULT_SPEED (115200)
|
#define USART1_DEFAULT_SPEED (115200)
|
||||||
|
// LIDAR default speed
|
||||||
|
#define LIDAR_DEFAULT_SPEED (115200)
|
||||||
|
// GPS default speed
|
||||||
|
#define GPS_DEFAULT_SPEED (9600)
|
||||||
|
|
||||||
#define STR_HELPER(s) #s
|
#define STR_HELPER(s) #s
|
||||||
#define STR(s) STR_HELPER(s)
|
#define STR(s) STR_HELPER(s)
|
||||||
@ -38,7 +45,7 @@
|
|||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
#define SEND(str) usart_send(1, str)
|
#define SEND(str) usart_send(1, str)
|
||||||
#define MSG(str) do{SEND(__FILE__ " (L" STR(__LINE__) "): " str);}while(0)
|
#define MSG(str) do{SEND(__FILE__ " (L" STR(__LINE__) "): " str);}while(0)
|
||||||
#define DBG(str) do{SEND(str); newline(); }while(0)
|
#define DBG(str) do{SEND(str); newline(1); }while(0)
|
||||||
#else
|
#else
|
||||||
#define SEND(str)
|
#define SEND(str)
|
||||||
#define MSG(str)
|
#define MSG(str)
|
||||||
@ -48,19 +55,17 @@
|
|||||||
#define usartrx(n) (linerdy[n])
|
#define usartrx(n) (linerdy[n])
|
||||||
#define usartovr(n) (bufovr[n])
|
#define usartovr(n) (bufovr[n])
|
||||||
|
|
||||||
extern volatile int linerdy[], bufovr[], txrdy[];
|
extern volatile uint8_t linerdy[], bufovr[], txrdy[];
|
||||||
|
|
||||||
void transmit_tbuf(int n);
|
void transmit_tbuf(uint8_t n);
|
||||||
void usarts_setup();
|
void usarts_setup();
|
||||||
int usart_getline(int n, char **line);
|
int usart_getline(int n, char **line);
|
||||||
void usart_send(int n, const char *str);
|
void usart_send(uint8_t n, const char *str);
|
||||||
void usart_putchar(int n, char ch);
|
void usart_putchar(uint8_t n, char ch);
|
||||||
void printu(int n, uint32_t val);
|
void printu(uint8_t n, uint32_t val);
|
||||||
void printuhex(int n, uint32_t val);
|
void printuhex(uint8_t n, uint32_t val);
|
||||||
|
void newline(uint8_t n);
|
||||||
|
|
||||||
#if defined EBUG || defined USART1PROXY
|
|
||||||
void newline();
|
|
||||||
#endif
|
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
void hexdump(uint8_t *arr, uint16_t len);
|
void hexdump(uint8_t *arr, uint16_t len);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -102,11 +102,13 @@ void usb_proc(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern uint8_t USB_connected;
|
||||||
void USB_send(const char *buf){
|
void USB_send(const char *buf){
|
||||||
if(!USB_configured()){
|
if(!USB_configured()){
|
||||||
DBG("USB not configured");
|
DBG("USB not configured");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(!USB_connected) return; // no connection -> no need to send data into nothing
|
||||||
char tmpbuf[USB_TXBUFSZ];
|
char tmpbuf[USB_TXBUFSZ];
|
||||||
uint16_t l = 0, ctr = 0;
|
uint16_t l = 0, ctr = 0;
|
||||||
const char *p = buf;
|
const char *p = buf;
|
||||||
@ -119,7 +121,9 @@ void USB_send(const char *buf){
|
|||||||
tmpbuf[i++] = '\r';
|
tmpbuf[i++] = '\r';
|
||||||
if(i == s) ++s;
|
if(i == s) ++s;
|
||||||
}
|
}
|
||||||
tmpbuf[i] = c;
|
if(c == 0x1B) tmpbuf[i] = 'E'; // ESC
|
||||||
|
else if(c == 0x7F) tmpbuf[i] = 'B'; // Backspace
|
||||||
|
else tmpbuf[i] = c;
|
||||||
}
|
}
|
||||||
tx_succesfull = 0;
|
tx_succesfull = 0;
|
||||||
EP_Write(3, (uint8_t*)tmpbuf, s);
|
EP_Write(3, (uint8_t*)tmpbuf, s);
|
||||||
@ -165,3 +169,45 @@ int USB_receive(char *buf, int bufsize){
|
|||||||
int USB_configured(){
|
int USB_configured(){
|
||||||
return usbON;
|
return usbON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* default handlers
|
||||||
|
*
|
||||||
|
// SET_LINE_CODING
|
||||||
|
void WEAK linecoding_handler(usb_LineCoding __attribute__((unused)) *lc){
|
||||||
|
DBG("WEAK LH");
|
||||||
|
}
|
||||||
|
|
||||||
|
// SET_CONTROL_LINE_STATE
|
||||||
|
void WEAK clstate_handler(uint16_t __attribute__((unused)) val){
|
||||||
|
DBG("WEAK CLSH");
|
||||||
|
}
|
||||||
|
|
||||||
|
// SEND_BREAK
|
||||||
|
void WEAK break_handler(){
|
||||||
|
DBG("WEAK BH");
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// handler of vendor requests
|
||||||
|
void WEAK vendor_handler(config_pack_t *packet){
|
||||||
|
if(packet->bmRequestType & 0x80){ // read
|
||||||
|
uint8_t c;
|
||||||
|
switch(packet->wValue){
|
||||||
|
case 0x8484:
|
||||||
|
c = 2;
|
||||||
|
break;
|
||||||
|
case 0x0080:
|
||||||
|
c = 1;
|
||||||
|
break;
|
||||||
|
case 0x8686:
|
||||||
|
c = 0xaa;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
EP_WriteIRQ(0, &c, 1);
|
||||||
|
}else{ // write ZLP
|
||||||
|
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* geany_encoding=koi8-r
|
|
||||||
* usb.h
|
|
||||||
*
|
|
||||||
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
#ifndef __USB_H__
|
|
||||||
#define __USB_H__
|
|
||||||
|
|
||||||
#include "hardware.h"
|
|
||||||
|
|
||||||
#define BUFFSIZE (64)
|
|
||||||
|
|
||||||
void USB_setup();
|
|
||||||
void usb_proc();
|
|
||||||
void USB_send(const char *buf);
|
|
||||||
int USB_receive(char *buf, int bufsize);
|
|
||||||
int USB_configured();
|
|
||||||
|
|
||||||
#endif // __USB_H__
|
|
||||||
@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* geany_encoding=koi8-r
|
|
||||||
* usb_defs.h
|
|
||||||
*
|
|
||||||
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef __USB_DEFS_H__
|
|
||||||
#define __USB_DEFS_H__
|
|
||||||
|
|
||||||
#include <stm32f1.h>
|
|
||||||
|
|
||||||
// max endpoints number
|
|
||||||
#define STM32ENDPOINTS 8
|
|
||||||
/**
|
|
||||||
* Buffers size definition
|
|
||||||
**/
|
|
||||||
#define USB_BTABLE_SIZE 512
|
|
||||||
// first 64 bytes of USB_BTABLE are registers!
|
|
||||||
//#define USB_EP0_BASEADDR 64
|
|
||||||
// for USB FS EP0 buffers are from 8 to 64 bytes long (64 for PL2303)
|
|
||||||
#define USB_EP0_BUFSZ 64
|
|
||||||
// USB transmit buffer size (64 for PL2303)
|
|
||||||
#define USB_TXBUFSZ 64
|
|
||||||
// USB receive buffer size (64 for PL2303)
|
|
||||||
#define USB_RXBUFSZ 64
|
|
||||||
|
|
||||||
#define USB_BTABLE_BASE 0x40006000
|
|
||||||
#define USB_BASE ((uint32_t)0x40005C00)
|
|
||||||
#define USB ((USB_TypeDef *) USB_BASE)
|
|
||||||
|
|
||||||
#ifdef USB_BTABLE
|
|
||||||
#undef USB_BTABLE
|
|
||||||
#endif
|
|
||||||
#define USB_BTABLE ((USB_BtableDef *)(USB_BTABLE_BASE))
|
|
||||||
#define USB_ISTR_EPID 0x0000000F
|
|
||||||
#define USB_FNR_LSOF_0 0x00000800
|
|
||||||
#define USB_FNR_lSOF_1 0x00001000
|
|
||||||
#define USB_LPMCSR_BESL_0 0x00000010
|
|
||||||
#define USB_LPMCSR_BESL_1 0x00000020
|
|
||||||
#define USB_LPMCSR_BESL_2 0x00000040
|
|
||||||
#define USB_LPMCSR_BESL_3 0x00000080
|
|
||||||
#define USB_EPnR_CTR_RX 0x00008000
|
|
||||||
#define USB_EPnR_DTOG_RX 0x00004000
|
|
||||||
#define USB_EPnR_STAT_RX 0x00003000
|
|
||||||
#define USB_EPnR_STAT_RX_0 0x00001000
|
|
||||||
#define USB_EPnR_STAT_RX_1 0x00002000
|
|
||||||
#define USB_EPnR_SETUP 0x00000800
|
|
||||||
#define USB_EPnR_EP_TYPE 0x00000600
|
|
||||||
#define USB_EPnR_EP_TYPE_0 0x00000200
|
|
||||||
#define USB_EPnR_EP_TYPE_1 0x00000400
|
|
||||||
#define USB_EPnR_EP_KIND 0x00000100
|
|
||||||
#define USB_EPnR_CTR_TX 0x00000080
|
|
||||||
#define USB_EPnR_DTOG_TX 0x00000040
|
|
||||||
#define USB_EPnR_STAT_TX 0x00000030
|
|
||||||
#define USB_EPnR_STAT_TX_0 0x00000010
|
|
||||||
#define USB_EPnR_STAT_TX_1 0x00000020
|
|
||||||
#define USB_EPnR_EA 0x0000000F
|
|
||||||
#define USB_COUNTn_RX_BLSIZE 0x00008000
|
|
||||||
#define USB_COUNTn_NUM_BLOCK 0x00007C00
|
|
||||||
#define USB_COUNTn_RX 0x0000003F
|
|
||||||
|
|
||||||
#ifdef USB_TypeDef
|
|
||||||
#define USB_TypeDef USB_TypeDef_custom
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
__IO uint32_t EPnR[STM32ENDPOINTS];
|
|
||||||
__IO uint32_t RESERVED[STM32ENDPOINTS];
|
|
||||||
__IO uint32_t CNTR;
|
|
||||||
__IO uint32_t ISTR;
|
|
||||||
__IO uint32_t FNR;
|
|
||||||
__IO uint32_t DADDR;
|
|
||||||
__IO uint32_t BTABLE;
|
|
||||||
} USB_TypeDef;
|
|
||||||
|
|
||||||
/*
|
|
||||||
typedef struct{
|
|
||||||
__IO uint16_t USB_ADDR_TX;
|
|
||||||
__IO uint16_t res1;
|
|
||||||
__IO uint16_t USB_COUNT_TX;
|
|
||||||
__IO uint16_t res2;
|
|
||||||
__IO uint16_t USB_ADDR_RX;
|
|
||||||
__IO uint16_t res3;
|
|
||||||
__IO uint16_t USB_COUNT_RX;
|
|
||||||
__IO uint16_t res4;
|
|
||||||
} USB_EPDATA_TypeDef;*/
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
__IO uint32_t USB_ADDR_TX;
|
|
||||||
__IO uint32_t USB_COUNT_TX;
|
|
||||||
__IO uint32_t USB_ADDR_RX;
|
|
||||||
__IO uint32_t USB_COUNT_RX;
|
|
||||||
} USB_EPDATA_TypeDef;
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
__IO USB_EPDATA_TypeDef EP[STM32ENDPOINTS];
|
|
||||||
} USB_BtableDef;
|
|
||||||
|
|
||||||
#endif // __USB_DEFS_H__
|
|
||||||
@ -29,7 +29,7 @@ ep_t endpoints[STM32ENDPOINTS];
|
|||||||
|
|
||||||
static usb_dev_t USB_Dev;
|
static usb_dev_t USB_Dev;
|
||||||
static usb_LineCoding lineCoding = {115200, 0, 0, 8};
|
static usb_LineCoding lineCoding = {115200, 0, 0, 8};
|
||||||
config_pack_t setup_packet;
|
static config_pack_t setup_packet;
|
||||||
static uint8_t ep0databuf[EP0DATABUF_SIZE];
|
static uint8_t ep0databuf[EP0DATABUF_SIZE];
|
||||||
static uint8_t ep0dbuflen = 0;
|
static uint8_t ep0dbuflen = 0;
|
||||||
|
|
||||||
@ -136,44 +136,6 @@ _USB_STRING_(USB_StringSerialDescriptor, u"0");
|
|||||||
_USB_STRING_(USB_StringManufacturingDescriptor, u"Prolific Technology Inc.");
|
_USB_STRING_(USB_StringManufacturingDescriptor, u"Prolific Technology Inc.");
|
||||||
_USB_STRING_(USB_StringProdDescriptor, u"USB-Serial Controller");
|
_USB_STRING_(USB_StringProdDescriptor, u"USB-Serial Controller");
|
||||||
|
|
||||||
/*
|
|
||||||
* default handlers
|
|
||||||
*/
|
|
||||||
// SET_LINE_CODING
|
|
||||||
void WEAK linecoding_handler(usb_LineCoding __attribute__((unused)) *lc){
|
|
||||||
}
|
|
||||||
|
|
||||||
// SET_CONTROL_LINE_STATE
|
|
||||||
void WEAK clstate_handler(uint16_t __attribute__((unused)) val){
|
|
||||||
}
|
|
||||||
|
|
||||||
// SEND_BREAK
|
|
||||||
void WEAK break_handler(){
|
|
||||||
}
|
|
||||||
|
|
||||||
// handler of vendor requests
|
|
||||||
void WEAK vendor_handler(config_pack_t *packet){
|
|
||||||
if(packet->bmRequestType & 0x80){ // read
|
|
||||||
uint8_t c;
|
|
||||||
switch(packet->wValue){
|
|
||||||
case 0x8484:
|
|
||||||
c = 2;
|
|
||||||
break;
|
|
||||||
case 0x0080:
|
|
||||||
c = 1;
|
|
||||||
break;
|
|
||||||
case 0x8686:
|
|
||||||
c = 0xaa;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
c = 0;
|
|
||||||
}
|
|
||||||
EP_WriteIRQ(0, &c, 1);
|
|
||||||
}else{ // write ZLP
|
|
||||||
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void wr0(const uint8_t *buf, uint16_t size){
|
static void wr0(const uint8_t *buf, uint16_t size){
|
||||||
if(setup_packet.wLength < size) size = setup_packet.wLength;
|
if(setup_packet.wLength < size) size = setup_packet.wLength;
|
||||||
EP_WriteIRQ(0, buf, size);
|
EP_WriteIRQ(0, buf, size);
|
||||||
@ -265,20 +227,20 @@ static uint16_t EP0_Handler(ep_t ep){
|
|||||||
std_h2d_req();
|
std_h2d_req();
|
||||||
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
||||||
}
|
}
|
||||||
epstatus = SET_NAK_RX(epstatus);
|
//epstatus = SET_NAK_RX(epstatus);
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
//epstatus = SET_VALID_TX(epstatus);
|
||||||
break;
|
break;
|
||||||
case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request
|
case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request
|
||||||
if(setup_packet.bRequest == CLEAR_FEATURE){
|
if(setup_packet.bRequest == CLEAR_FEATURE){
|
||||||
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
||||||
epstatus = SET_NAK_RX(epstatus);
|
//epstatus = SET_NAK_RX(epstatus);
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
//epstatus = SET_VALID_TX(epstatus);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VENDOR_REQUEST_TYPE:
|
case VENDOR_REQUEST_TYPE:
|
||||||
vendor_handler(&setup_packet);
|
vendor_handler(&setup_packet);
|
||||||
epstatus = SET_NAK_RX(epstatus);
|
//epstatus = SET_NAK_RX(epstatus);
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
//epstatus = SET_VALID_TX(epstatus);
|
||||||
break;
|
break;
|
||||||
case CONTROL_REQUEST_TYPE:
|
case CONTROL_REQUEST_TYPE:
|
||||||
switch(setup_packet.bRequest){
|
switch(setup_packet.bRequest){
|
||||||
@ -300,13 +262,13 @@ static uint16_t EP0_Handler(ep_t ep){
|
|||||||
//if(!dev2host)
|
//if(!dev2host)
|
||||||
if(setup_packet.bRequest != GET_LINE_CODING)
|
if(setup_packet.bRequest != GET_LINE_CODING)
|
||||||
EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement
|
EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement
|
||||||
epstatus = SET_VALID_RX(epstatus);
|
//epstatus = SET_VALID_RX(epstatus);
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
//epstatus = SET_VALID_TX(epstatus);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
||||||
epstatus = SET_NAK_RX(epstatus);
|
//epstatus = SET_NAK_RX(epstatus);
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
//epstatus = SET_VALID_TX(epstatus);
|
||||||
}
|
}
|
||||||
}else if (ep.rx_flag){ // got data over EP0 or host acknowlegement
|
}else if (ep.rx_flag){ // got data over EP0 or host acknowlegement
|
||||||
if(ep.rx_cnt){
|
if(ep.rx_cnt){
|
||||||
@ -316,8 +278,8 @@ static uint16_t EP0_Handler(ep_t ep){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// wait for new data from host
|
// wait for new data from host
|
||||||
epstatus = SET_VALID_RX(epstatus);
|
//epstatus = SET_VALID_RX(epstatus);
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
//epstatus = SET_VALID_TX(epstatus);
|
||||||
} else if (ep.tx_flag){ // package transmitted
|
} else if (ep.tx_flag){ // package transmitted
|
||||||
// now we can change address after enumeration
|
// now we can change address after enumeration
|
||||||
if ((USB->DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){
|
if ((USB->DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){
|
||||||
@ -328,9 +290,11 @@ static uint16_t EP0_Handler(ep_t ep){
|
|||||||
// end of transaction
|
// end of transaction
|
||||||
epstatus = CLEAR_DTOG_RX(epstatus);
|
epstatus = CLEAR_DTOG_RX(epstatus);
|
||||||
epstatus = CLEAR_DTOG_TX(epstatus);
|
epstatus = CLEAR_DTOG_TX(epstatus);
|
||||||
|
//epstatus = SET_VALID_RX(epstatus);
|
||||||
|
//epstatus = SET_VALID_TX(epstatus);
|
||||||
|
}
|
||||||
epstatus = SET_VALID_RX(epstatus);
|
epstatus = SET_VALID_RX(epstatus);
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
epstatus = SET_VALID_TX(epstatus);
|
||||||
}
|
|
||||||
return epstatus;
|
return epstatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,202 +0,0 @@
|
|||||||
/*
|
|
||||||
* geany_encoding=koi8-r
|
|
||||||
* usb_lib.h
|
|
||||||
*
|
|
||||||
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef __USB_LIB_H__
|
|
||||||
#define __USB_LIB_H__
|
|
||||||
|
|
||||||
#include <wchar.h>
|
|
||||||
#include "usb_defs.h"
|
|
||||||
|
|
||||||
#define EP0DATABUF_SIZE (64)
|
|
||||||
#define LASTADDR_DEFAULT (STM32ENDPOINTS * 8)
|
|
||||||
|
|
||||||
// Max EP amount (EP0 + other used)
|
|
||||||
//#define ENDPOINTS_NUM 4
|
|
||||||
// bmRequestType & 0x7f
|
|
||||||
#define STANDARD_DEVICE_REQUEST_TYPE 0
|
|
||||||
#define STANDARD_ENDPOINT_REQUEST_TYPE 2
|
|
||||||
#define VENDOR_REQUEST_TYPE 0x40
|
|
||||||
#define CONTROL_REQUEST_TYPE 0x21
|
|
||||||
// bRequest, standard; for bmRequestType == 0x80
|
|
||||||
#define GET_STATUS 0x00
|
|
||||||
#define GET_DESCRIPTOR 0x06
|
|
||||||
#define GET_CONFIGURATION 0x08
|
|
||||||
// for bmRequestType == 0
|
|
||||||
#define CLEAR_FEATURE 0x01
|
|
||||||
#define SET_FEATURE 0x03 // unused
|
|
||||||
#define SET_ADDRESS 0x05
|
|
||||||
#define SET_DESCRIPTOR 0x07 // unused
|
|
||||||
#define SET_CONFIGURATION 0x09
|
|
||||||
// for bmRequestType == 0x81, 1 or 0xB2
|
|
||||||
#define GET_INTERFACE 0x0A // unused
|
|
||||||
#define SET_INTERFACE 0x0B // unused
|
|
||||||
#define SYNC_FRAME 0x0C // unused
|
|
||||||
#define VENDOR_REQUEST 0x01 // unused
|
|
||||||
|
|
||||||
// Class-Specific Control Requests
|
|
||||||
#define SEND_ENCAPSULATED_COMMAND 0x00 // unused
|
|
||||||
#define GET_ENCAPSULATED_RESPONSE 0x01 // unused
|
|
||||||
#define SET_COMM_FEATURE 0x02 // unused
|
|
||||||
#define GET_COMM_FEATURE 0x03 // unused
|
|
||||||
#define CLEAR_COMM_FEATURE 0x04 // unused
|
|
||||||
#define SET_LINE_CODING 0x20
|
|
||||||
#define GET_LINE_CODING 0x21
|
|
||||||
#define SET_CONTROL_LINE_STATE 0x22
|
|
||||||
#define SEND_BREAK 0x23
|
|
||||||
|
|
||||||
// control line states
|
|
||||||
#define CONTROL_DTR 0x01
|
|
||||||
#define CONTROL_RTS 0x02
|
|
||||||
|
|
||||||
// wValue
|
|
||||||
#define DEVICE_DESCRIPTOR 0x100
|
|
||||||
#define CONFIGURATION_DESCRIPTOR 0x200
|
|
||||||
#define STRING_LANG_DESCRIPTOR 0x300
|
|
||||||
#define STRING_MAN_DESCRIPTOR 0x301
|
|
||||||
#define STRING_PROD_DESCRIPTOR 0x302
|
|
||||||
#define STRING_SN_DESCRIPTOR 0x303
|
|
||||||
#define DEVICE_QUALIFIER_DESCRIPTOR 0x600
|
|
||||||
|
|
||||||
// EPnR bits manipulation
|
|
||||||
#define CLEAR_DTOG_RX(R) (R & USB_EPnR_DTOG_RX) ? R : (R & (~USB_EPnR_DTOG_RX))
|
|
||||||
#define SET_DTOG_RX(R) (R & USB_EPnR_DTOG_RX) ? (R & (~USB_EPnR_DTOG_RX)) : R
|
|
||||||
#define TOGGLE_DTOG_RX(R) (R | USB_EPnR_DTOG_RX)
|
|
||||||
#define KEEP_DTOG_RX(R) (R & (~USB_EPnR_DTOG_RX))
|
|
||||||
#define CLEAR_DTOG_TX(R) (R & USB_EPnR_DTOG_TX) ? R : (R & (~USB_EPnR_DTOG_TX))
|
|
||||||
#define SET_DTOG_TX(R) (R & USB_EPnR_DTOG_TX) ? (R & (~USB_EPnR_DTOG_TX)) : R
|
|
||||||
#define TOGGLE_DTOG_TX(R) (R | USB_EPnR_DTOG_TX)
|
|
||||||
#define KEEP_DTOG_TX(R) (R & (~USB_EPnR_DTOG_TX))
|
|
||||||
#define SET_VALID_RX(R) ((R & USB_EPnR_STAT_RX) ^ USB_EPnR_STAT_RX) | (R & (~USB_EPnR_STAT_RX))
|
|
||||||
#define SET_NAK_RX(R) ((R & USB_EPnR_STAT_RX) ^ USB_EPnR_STAT_RX_1) | (R & (~USB_EPnR_STAT_RX))
|
|
||||||
#define SET_STALL_RX(R) ((R & USB_EPnR_STAT_RX) ^ USB_EPnR_STAT_RX_0) | (R & (~USB_EPnR_STAT_RX))
|
|
||||||
#define KEEP_STAT_RX(R) (R & (~USB_EPnR_STAT_RX))
|
|
||||||
#define SET_VALID_TX(R) ((R & USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_TX) | (R & (~USB_EPnR_STAT_TX))
|
|
||||||
#define SET_NAK_TX(R) ((R & USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_TX_1) | (R & (~USB_EPnR_STAT_TX))
|
|
||||||
#define SET_STALL_TX(R) ((R & USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_TX_0) | (R & (~USB_EPnR_STAT_TX))
|
|
||||||
#define KEEP_STAT_TX(R) (R & (~USB_EPnR_STAT_TX))
|
|
||||||
#define CLEAR_CTR_RX(R) (R & (~USB_EPnR_CTR_RX))
|
|
||||||
#define CLEAR_CTR_TX(R) (R & (~USB_EPnR_CTR_TX))
|
|
||||||
#define CLEAR_CTR_RX_TX(R) (R & (~(USB_EPnR_CTR_TX | USB_EPnR_CTR_RX)))
|
|
||||||
|
|
||||||
// USB state: uninitialized, addressed, ready for use
|
|
||||||
#define USB_DEFAULT_STATE 0
|
|
||||||
#define USB_ADRESSED_STATE 1
|
|
||||||
#define USB_CONFIGURE_STATE 2
|
|
||||||
|
|
||||||
// EP types
|
|
||||||
#define EP_TYPE_BULK 0x00
|
|
||||||
#define EP_TYPE_CONTROL 0x01
|
|
||||||
#define EP_TYPE_ISO 0x02
|
|
||||||
#define EP_TYPE_INTERRUPT 0x03
|
|
||||||
|
|
||||||
#define LANG_US (uint16_t)0x0409
|
|
||||||
|
|
||||||
#define _USB_STRING_(name, str) \
|
|
||||||
static const struct name \
|
|
||||||
{ \
|
|
||||||
uint8_t bLength; \
|
|
||||||
uint8_t bDescriptorType; \
|
|
||||||
uint16_t bString[(sizeof(str) - 2) / 2]; \
|
|
||||||
\
|
|
||||||
} \
|
|
||||||
name = {sizeof(name), 0x03, str}
|
|
||||||
|
|
||||||
#define _USB_LANG_ID_(name, lng_id) \
|
|
||||||
\
|
|
||||||
static const struct name \
|
|
||||||
{ \
|
|
||||||
uint8_t bLength; \
|
|
||||||
uint8_t bDescriptorType; \
|
|
||||||
uint16_t bString; \
|
|
||||||
\
|
|
||||||
} \
|
|
||||||
name = {0x04, 0x03, lng_id}
|
|
||||||
#define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4)
|
|
||||||
|
|
||||||
// EP0 configuration packet
|
|
||||||
typedef struct {
|
|
||||||
uint8_t bmRequestType;
|
|
||||||
uint8_t bRequest;
|
|
||||||
uint16_t wValue;
|
|
||||||
uint16_t wIndex;
|
|
||||||
uint16_t wLength;
|
|
||||||
} config_pack_t;
|
|
||||||
|
|
||||||
// endpoints state
|
|
||||||
typedef struct __ep_t{
|
|
||||||
uint16_t *tx_buf; // transmission buffer address
|
|
||||||
uint16_t *rx_buf; // reception buffer address
|
|
||||||
uint16_t (*func)(); // endpoint action function
|
|
||||||
uint16_t status; // status flags
|
|
||||||
unsigned rx_cnt : 10; // received data counter
|
|
||||||
unsigned tx_flag : 1; // transmission flag
|
|
||||||
unsigned rx_flag : 1; // reception flag
|
|
||||||
unsigned setup_flag : 1; // this is setup packet (only for EP0)
|
|
||||||
} ep_t;
|
|
||||||
|
|
||||||
// USB status & its address
|
|
||||||
typedef struct {
|
|
||||||
uint8_t USB_Status;
|
|
||||||
uint16_t USB_Addr;
|
|
||||||
}usb_dev_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t dwDTERate;
|
|
||||||
uint8_t bCharFormat;
|
|
||||||
#define USB_CDC_1_STOP_BITS 0
|
|
||||||
#define USB_CDC_1_5_STOP_BITS 1
|
|
||||||
#define USB_CDC_2_STOP_BITS 2
|
|
||||||
uint8_t bParityType;
|
|
||||||
#define USB_CDC_NO_PARITY 0
|
|
||||||
#define USB_CDC_ODD_PARITY 1
|
|
||||||
#define USB_CDC_EVEN_PARITY 2
|
|
||||||
#define USB_CDC_MARK_PARITY 3
|
|
||||||
#define USB_CDC_SPACE_PARITY 4
|
|
||||||
uint8_t bDataBits;
|
|
||||||
} __attribute__ ((packed)) usb_LineCoding;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t bmRequestType;
|
|
||||||
uint8_t bNotificationType;
|
|
||||||
uint16_t wValue;
|
|
||||||
uint16_t wIndex;
|
|
||||||
uint16_t wLength;
|
|
||||||
} __attribute__ ((packed)) usb_cdc_notification;
|
|
||||||
|
|
||||||
extern ep_t endpoints[];
|
|
||||||
|
|
||||||
void USB_Init();
|
|
||||||
uint8_t USB_GetState();
|
|
||||||
int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t (*func)(ep_t ep));
|
|
||||||
void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size);
|
|
||||||
void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size);
|
|
||||||
int EP_Read(uint8_t number, uint16_t *buf);
|
|
||||||
usb_LineCoding getLineCoding();
|
|
||||||
|
|
||||||
void WEAK linecoding_handler(usb_LineCoding *lc);
|
|
||||||
void WEAK clstate_handler(uint16_t val);
|
|
||||||
void WEAK break_handler();
|
|
||||||
void WEAK vendor_handler(config_pack_t *packet);
|
|
||||||
|
|
||||||
#endif // __USB_LIB_H__
|
|
||||||
0
F1-nolib/chronometer_v2/chrono.bin
Executable file → Normal file
0
F1-nolib/chronometer_v2/chrono.bin
Executable file → Normal file
@ -227,20 +227,20 @@ static uint16_t EP0_Handler(ep_t ep){
|
|||||||
std_h2d_req();
|
std_h2d_req();
|
||||||
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
||||||
}
|
}
|
||||||
epstatus = SET_NAK_RX(epstatus);
|
//epstatus = SET_NAK_RX(epstatus);
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
//epstatus = SET_VALID_TX(epstatus);
|
||||||
break;
|
break;
|
||||||
case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request
|
case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request
|
||||||
if(setup_packet.bRequest == CLEAR_FEATURE){
|
if(setup_packet.bRequest == CLEAR_FEATURE){
|
||||||
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
||||||
epstatus = SET_NAK_RX(epstatus);
|
//epstatus = SET_NAK_RX(epstatus);
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
//epstatus = SET_VALID_TX(epstatus);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VENDOR_REQUEST_TYPE:
|
case VENDOR_REQUEST_TYPE:
|
||||||
vendor_handler(&setup_packet);
|
vendor_handler(&setup_packet);
|
||||||
epstatus = SET_NAK_RX(epstatus);
|
//epstatus = SET_NAK_RX(epstatus);
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
//epstatus = SET_VALID_TX(epstatus);
|
||||||
break;
|
break;
|
||||||
case CONTROL_REQUEST_TYPE:
|
case CONTROL_REQUEST_TYPE:
|
||||||
switch(setup_packet.bRequest){
|
switch(setup_packet.bRequest){
|
||||||
@ -262,13 +262,13 @@ static uint16_t EP0_Handler(ep_t ep){
|
|||||||
//if(!dev2host)
|
//if(!dev2host)
|
||||||
if(setup_packet.bRequest != GET_LINE_CODING)
|
if(setup_packet.bRequest != GET_LINE_CODING)
|
||||||
EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement
|
EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement
|
||||||
epstatus = SET_VALID_RX(epstatus);
|
//epstatus = SET_VALID_RX(epstatus);
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
//epstatus = SET_VALID_TX(epstatus);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
||||||
epstatus = SET_NAK_RX(epstatus);
|
//epstatus = SET_NAK_RX(epstatus);
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
//epstatus = SET_VALID_TX(epstatus);
|
||||||
}
|
}
|
||||||
}else if (ep.rx_flag){ // got data over EP0 or host acknowlegement
|
}else if (ep.rx_flag){ // got data over EP0 or host acknowlegement
|
||||||
if(ep.rx_cnt){
|
if(ep.rx_cnt){
|
||||||
@ -278,8 +278,8 @@ static uint16_t EP0_Handler(ep_t ep){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// wait for new data from host
|
// wait for new data from host
|
||||||
epstatus = SET_VALID_RX(epstatus);
|
//epstatus = SET_VALID_RX(epstatus);
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
//epstatus = SET_VALID_TX(epstatus);
|
||||||
} else if (ep.tx_flag){ // package transmitted
|
} else if (ep.tx_flag){ // package transmitted
|
||||||
// now we can change address after enumeration
|
// now we can change address after enumeration
|
||||||
if ((USB->DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){
|
if ((USB->DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){
|
||||||
@ -290,9 +290,11 @@ static uint16_t EP0_Handler(ep_t ep){
|
|||||||
// end of transaction
|
// end of transaction
|
||||||
epstatus = CLEAR_DTOG_RX(epstatus);
|
epstatus = CLEAR_DTOG_RX(epstatus);
|
||||||
epstatus = CLEAR_DTOG_TX(epstatus);
|
epstatus = CLEAR_DTOG_TX(epstatus);
|
||||||
|
//epstatus = SET_VALID_RX(epstatus);
|
||||||
|
//epstatus = SET_VALID_TX(epstatus);
|
||||||
|
}
|
||||||
epstatus = SET_VALID_RX(epstatus);
|
epstatus = SET_VALID_RX(epstatus);
|
||||||
epstatus = SET_VALID_TX(epstatus);
|
epstatus = SET_VALID_TX(epstatus);
|
||||||
}
|
|
||||||
return epstatus;
|
return epstatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
0
F1-nolib/led_blink/blink.bin
Executable file → Normal file
0
F1-nolib/led_blink/blink.bin
Executable file → Normal file
0
F1-nolib/uart/uart.bin
Executable file → Normal file
0
F1-nolib/uart/uart.bin
Executable file → Normal file
0
F1/1_wire/onewire.bin
Executable file → Normal file
0
F1/1_wire/onewire.bin
Executable file → Normal file
0
F1/2.8TFT/dma_gpio.bin
Executable file → Normal file
0
F1/2.8TFT/dma_gpio.bin
Executable file → Normal file
0
F1/DMA_GPIO/dma_gpio.bin
Executable file → Normal file
0
F1/DMA_GPIO/dma_gpio.bin
Executable file → Normal file
0
F1/GPIO_TIM/tim_gpio.bin
Executable file → Normal file
0
F1/GPIO_TIM/tim_gpio.bin
Executable file → Normal file
0
F1/GPS+ultrasonic/timelapse.bin
Executable file → Normal file
0
F1/GPS+ultrasonic/timelapse.bin
Executable file → Normal file
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user