mirror of
https://github.com/eddyem/stm32samples.git
synced 2026-01-31 20:35:06 +03:00
Add GPS-based timelapse tool.
This commit is contained in:
parent
32dbb8c35c
commit
832658cc13
263
GPS+ultrasonic/GPS.c
Normal file
263
GPS+ultrasonic/GPS.c
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* 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 "main.h"
|
||||
#include "GPS.h"
|
||||
#include "uart.h"
|
||||
|
||||
#define GPS_endline() do{GPS_send_string((uint8_t*)"\r\n");}while(0)
|
||||
#define U(arg) ((uint8_t*)arg)
|
||||
|
||||
gps_status GPS_status = GPS_WAIT;
|
||||
|
||||
void GPS_send_string(uint8_t *str){
|
||||
while(*str)
|
||||
fill_uart_buff(USART2, *str++);
|
||||
}
|
||||
|
||||
int strncmp(const uint8_t *one, const uint8_t *two, int n){
|
||||
int diff = 0;
|
||||
do{
|
||||
diff = (int)(*one++) - (int)(*two++);
|
||||
}while(--n && diff == 0);
|
||||
return diff;
|
||||
}
|
||||
|
||||
uint8_t *ustrchr(uint8_t *str, uint8_t symbol){
|
||||
// uint8_t *ptr = str;
|
||||
do{
|
||||
if(*str == symbol) return str;
|
||||
}while(*(++str));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t hex(uint8_t n){
|
||||
return ((n < 10) ? (n+'0') : (n+'A'-10));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check checksum
|
||||
*/
|
||||
int checksum_true(uint8_t *buf){
|
||||
uint8_t *eol;
|
||||
uint8_t checksum = 0, cs[3];
|
||||
if(*buf != '$' || !(eol = ustrchr(buf, '*'))){
|
||||
DBG("Wrong data: ");
|
||||
DBG(buf);
|
||||
DBG("\n");
|
||||
return 0;
|
||||
}
|
||||
while(++buf != eol)
|
||||
checksum ^= *buf;
|
||||
++buf;
|
||||
cs[0] = hex(checksum >> 4);
|
||||
cs[1] = hex(checksum & 0x0f);
|
||||
if(buf[0] == cs[0] && buf[1] == cs[1])
|
||||
return 1;
|
||||
#ifdef EBUG
|
||||
cs[2] = 0;
|
||||
P("CHS, get ");
|
||||
P(buf);
|
||||
P(" need ");
|
||||
P(cs);
|
||||
usb_send('\n');
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void send_chksum(uint8_t chs){
|
||||
fill_uart_buff(USART2, hex(chs >> 4));
|
||||
fill_uart_buff(USART2, hex(chs & 0x0f));
|
||||
}
|
||||
/**
|
||||
* Calculate checksum & write message to port
|
||||
* @param buf - command to write (with leading $ and trailing *)
|
||||
* return 0 if fails
|
||||
*/
|
||||
void write_with_checksum(uint8_t *buf){
|
||||
uint8_t checksum = 0;
|
||||
GPS_send_string(buf);
|
||||
++buf; // skip leaders
|
||||
do{
|
||||
checksum ^= *buf++;
|
||||
}while(*buf && *buf != '*');
|
||||
send_chksum(checksum);
|
||||
GPS_endline();
|
||||
}
|
||||
|
||||
/**
|
||||
* set rate for given NMEA field
|
||||
* @param field - name of NMEA field
|
||||
* @param rate - rate in seconds (0 disables field)
|
||||
* @return -1 if fails, rate if OK
|
||||
*/
|
||||
void block_field(const uint8_t *field){
|
||||
uint8_t buf[22];
|
||||
memcpy(buf, U("$PUBX,40,"), 9);
|
||||
memcpy(buf+9, field, 3);
|
||||
memcpy(buf+12, U(",0,0,0,0*"), 9);
|
||||
buf[21] = 0;
|
||||
write_with_checksum(buf);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send starting sequences (get only RMC messages)
|
||||
*/
|
||||
void GPS_send_start_seq(){
|
||||
const uint8_t *GPmsgs[5] = {U("GSV"), U("GSA"), U("GGA"), U("GLL"), U("VTG")};
|
||||
int i;
|
||||
for(i = 0; i < 5; ++i)
|
||||
block_field(GPmsgs[i]);
|
||||
}
|
||||
/*
|
||||
uint8_t *nextpos(uint8_t **buf, int pos){
|
||||
int i;
|
||||
if(pos < 1) pos = 1;
|
||||
for(i = 0; i < pos; ++i){
|
||||
*buf = ustrchr(*buf, ',');
|
||||
if(!*buf) break;
|
||||
++(*buf);
|
||||
}
|
||||
return *buf;
|
||||
}
|
||||
#define NEXT() do{if(!nextpos(&buf, 1)) goto ret;}while(0)
|
||||
#define SKIP(NPOS) do{if(!nextpos(&buf, NPOS)) goto ret;}while(0)
|
||||
*/
|
||||
/**
|
||||
* Parse answer from GPS module
|
||||
*
|
||||
* Recommended minimum specific GPS/Transit data
|
||||
* $GPRMC,hhmmss,status,latitude,N,longitude,E,spd,cog,ddmmyy,mv,mvE,mode*cs
|
||||
* 1 = UTC of position fix
|
||||
* 2 = Data status (V=navigation receiver warning)
|
||||
* 3 = Latitude of fix
|
||||
* 4 = N or S
|
||||
* 5 = Longitude of fix
|
||||
* 6 = E or W
|
||||
* 7 = Speed over ground in knots
|
||||
* 8 = Cource over ground in degrees
|
||||
* 9 = UT date
|
||||
* 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(uint8_t *buf){
|
||||
uint8_t *ptr;
|
||||
if(strncmp(buf+3, U("RMC"), 3)){ // not RMC message
|
||||
GPS_send_start_seq();
|
||||
return;
|
||||
}
|
||||
if(!checksum_true(buf)){
|
||||
DBG("Wrong chs\n");
|
||||
return; // wrong checksum
|
||||
}
|
||||
buf += 7; // skip header
|
||||
if(*buf == ','){ // time unknown
|
||||
GPS_status = GPS_WAIT;
|
||||
return;
|
||||
}
|
||||
//P("time: ");
|
||||
ptr = ustrchr(buf, ',');
|
||||
*ptr++ = 0;
|
||||
//P(buf);
|
||||
if(*ptr == 'A'){
|
||||
GPS_status = GPS_VALID;
|
||||
set_time(buf);
|
||||
}else
|
||||
GPS_status = GPS_NOT_VALID;
|
||||
// buf = ustrchr(ptr, ',');
|
||||
// P(" ");
|
||||
// P("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
void rmc(uint8_t *buf){
|
||||
//DBG("rmc: %s\n", buf);
|
||||
int H, M, LO, LA, d, m, y, getdate = 0;
|
||||
double S, longitude, lattitude, speed, track, mag;
|
||||
char varn = 'V', north = '0', east = '0', mageast = '0', mode = 'N';
|
||||
sscanf((char*)buf, "%2d%2d%lf", &H, &M, &S);
|
||||
NEXT();
|
||||
if(*buf != ',') varn = *buf;
|
||||
if(varn != 'A')
|
||||
PRINT("(data could be wrong)");
|
||||
else{
|
||||
PRINT("(data valid)");
|
||||
if(GP->date) getdate = 1; // as only we have valid data we show it to user
|
||||
}
|
||||
PRINT(" time: %02d:%02d:%05.2f", H, M, S);
|
||||
PRINT(" timediff: %g", timediff(H, M, S));
|
||||
NEXT();
|
||||
sscanf((char*)buf, "%2d%lf", &LA, &lattitude);
|
||||
NEXT();
|
||||
if(*buf != ','){
|
||||
north = *buf;
|
||||
lattitude = (double)LA + lattitude / 60.;
|
||||
if(north == 'S') lattitude = -lattitude;
|
||||
PRINT(" latt: %g", lattitude);
|
||||
Latt_mean += lattitude;
|
||||
Latt_sq += lattitude*lattitude;
|
||||
++Latt_N;
|
||||
}
|
||||
NEXT();
|
||||
sscanf((char*)buf, "%3d%lf", &LO, &longitude);
|
||||
NEXT();
|
||||
if(*buf != ','){
|
||||
east = *buf;
|
||||
longitude = (double)LO + longitude / 60.;
|
||||
if(east == 'W') longitude = -longitude;
|
||||
PRINT(" long: %g", longitude);
|
||||
Long_mean += longitude;
|
||||
Long_sq += longitude*longitude;
|
||||
++Long_N;
|
||||
}
|
||||
NEXT();
|
||||
if(*buf != ','){
|
||||
sscanf((char*)buf, "%lf", &speed);
|
||||
PRINT(" speed: %gknots", speed);
|
||||
}
|
||||
NEXT();
|
||||
if(*buf != ','){
|
||||
sscanf((char*)buf, "%lf", &track);
|
||||
PRINT(" track: %gdeg,True", track);
|
||||
}
|
||||
NEXT();
|
||||
if(sscanf((char*)buf, "%2d%2d%2d", &d, &m, &y) == 3)
|
||||
PRINT(" date(dd/mm/yy): %02d/%02d/%02d", d, m, y);
|
||||
if(getdate) show_date(H,M,S,d,m,y); // show date & exit
|
||||
NEXT();
|
||||
sscanf((char*)buf, "%lf,%c", &mag, &mageast);
|
||||
if(mageast == 'E' || mageast == 'W'){
|
||||
if(mageast == 'W') mag = -mag;
|
||||
PRINT(" magnetic var: %g", mag);
|
||||
}
|
||||
SKIP(2);
|
||||
if(*buf != ','){
|
||||
mode = *buf;
|
||||
PRINT(" mode: %c", mode);
|
||||
}
|
||||
ret:
|
||||
PRINT("\n");
|
||||
}
|
||||
*/
|
||||
37
GPS+ultrasonic/GPS.h
Normal file
37
GPS+ultrasonic/GPS.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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__
|
||||
|
||||
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(uint8_t *string);
|
||||
void GPS_send_start_seq();
|
||||
|
||||
#endif // __GPS_H__
|
||||
133
GPS+ultrasonic/Makefile
Normal file
133
GPS+ultrasonic/Makefile
Normal file
@ -0,0 +1,133 @@
|
||||
BINARY = timelapse
|
||||
BOOTPORT ?= /dev/ttyUSB0
|
||||
BOOTSPEED ?= 115200
|
||||
# change this linking script depending on particular MCU model,
|
||||
# for example, if you have STM32F103VBT6, you should write:
|
||||
LDSCRIPT = ld/stm32f103x8.ld
|
||||
LIBNAME = opencm3_stm32f1
|
||||
DEFS = -DSTM32F1 -DEBUG
|
||||
|
||||
OBJDIR = mk
|
||||
INDEPENDENT_HEADERS=
|
||||
|
||||
FP_FLAGS ?= -msoft-float
|
||||
ARCH_FLAGS = -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd
|
||||
|
||||
###############################################################################
|
||||
# Executables
|
||||
PREFIX ?= arm-none-eabi
|
||||
|
||||
RM := rm -f
|
||||
RMDIR := rmdir
|
||||
CC := $(PREFIX)-gcc
|
||||
LD := $(PREFIX)-gcc
|
||||
AR := $(PREFIX)-ar
|
||||
AS := $(PREFIX)-as
|
||||
OBJCOPY := $(PREFIX)-objcopy
|
||||
OBJDUMP := $(PREFIX)-objdump
|
||||
GDB := $(PREFIX)-gdb
|
||||
STFLASH = $(shell which st-flash)
|
||||
STBOOT = $(shell which stm32flash)
|
||||
|
||||
###############################################################################
|
||||
# Source files
|
||||
LDSCRIPT ?= $(BINARY).ld
|
||||
SRC = $(wildcard *.c)
|
||||
OBJS = $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o))
|
||||
|
||||
ifeq ($(strip $(OPENCM3_DIR)),)
|
||||
OPENCM3_DIR := /usr/local/arm-none-eabi
|
||||
$(info Using $(OPENCM3_DIR) path to library)
|
||||
endif
|
||||
|
||||
INCLUDE_DIR = $(OPENCM3_DIR)/include
|
||||
LIB_DIR = $(OPENCM3_DIR)/lib
|
||||
SCRIPT_DIR = $(OPENCM3_DIR)/scripts
|
||||
|
||||
###############################################################################
|
||||
# C flags
|
||||
CFLAGS += -Os -g
|
||||
CFLAGS += -Wall -Wextra -Wshadow -Wimplicit-function-declaration
|
||||
CFLAGS += -Wredundant-decls
|
||||
# -Wmissing-prototypes -Wstrict-prototypes
|
||||
CFLAGS += -fno-common -ffunction-sections -fdata-sections
|
||||
|
||||
###############################################################################
|
||||
# C & C++ preprocessor common flags
|
||||
CPPFLAGS += -MD
|
||||
CPPFLAGS += -Wall -Werror
|
||||
CPPFLAGS += -I$(INCLUDE_DIR) $(DEFS)
|
||||
|
||||
###############################################################################
|
||||
# Linker flags
|
||||
LDFLAGS += --static -nostartfiles
|
||||
LDFLAGS += -L$(LIB_DIR)
|
||||
LDFLAGS += -T$(LDSCRIPT)
|
||||
LDFLAGS += -Wl,-Map=$(*).map
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
|
||||
###############################################################################
|
||||
# Used libraries
|
||||
LDLIBS += -l$(LIBNAME)
|
||||
LDLIBS += -Wl,--start-group -lc -lgcc -Wl,--end-group
|
||||
|
||||
.SUFFIXES: .elf .bin .hex .srec .list .map .images
|
||||
.SECONDEXPANSION:
|
||||
.SECONDARY:
|
||||
|
||||
ELF := $(OBJDIR)/$(BINARY).elf
|
||||
LIST := $(OBJDIR)/$(BINARY).list
|
||||
BIN := $(BINARY).bin
|
||||
HEX := $(BINARY).hex
|
||||
|
||||
all: bin
|
||||
|
||||
elf: $(ELF)
|
||||
bin: $(BIN)
|
||||
hex: $(HEX)
|
||||
list: $(LIST)
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir $(OBJDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@printf " CC $<\n"
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $@ -c $<
|
||||
|
||||
$(SRC) : %.c : %.h $(INDEPENDENT_HEADERS)
|
||||
@touch $@
|
||||
|
||||
%.h: ;
|
||||
|
||||
$(BIN): $(ELF)
|
||||
@printf " OBJCOPY $(BIN)\n"
|
||||
$(OBJCOPY) -Obinary $(ELF) $(BIN)
|
||||
|
||||
$(HEX): $(ELF)
|
||||
@printf " OBJCOPY $(HEX)\n"
|
||||
$(OBJCOPY) -Oihex $(ELF) $(HEX)
|
||||
|
||||
$(LIST): $(ELF)
|
||||
@printf " OBJDUMP $(LIST)\n"
|
||||
$(OBJDUMP) -S $(ELF) > $(LIST)
|
||||
|
||||
$(ELF): $(OBJDIR) $(OBJS) $(LDSCRIPT) $(LIB_DIR)/lib$(LIBNAME).a
|
||||
@printf " LD $(ELF)\n"
|
||||
$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
|
||||
|
||||
clean:
|
||||
@printf " CLEAN\n"
|
||||
$(RM) $(OBJS) $(OBJDIR)/*.d $(ELF) $(HEX) $(LIST) $(OBJDIR)/*.map
|
||||
$(RMDIR) $(OBJDIR)
|
||||
|
||||
flash: $(BIN)
|
||||
@printf " FLASH $(BIN)\n"
|
||||
$(STFLASH) write $(BIN) 0x8000000
|
||||
|
||||
boot: $(BIN)
|
||||
@printf " LOAD $(BIN) through bootloader\n"
|
||||
$(STBOOT) -b$(BOOTSPEED) $(BOOTPORT) -w $(BIN)
|
||||
|
||||
.PHONY: clean elf hex list flash boot
|
||||
|
||||
#-include $(OBJS:.o=.d)
|
||||
8
GPS+ultrasonic/README
Normal file
8
GPS+ultrasonic/README
Normal file
@ -0,0 +1,8 @@
|
||||
GPS-based timelapse tool
|
||||
Connect up to four sensors (ultrasonic, infrared, laser and simple switch)
|
||||
and get precision (milliseconds) time of their signals
|
||||
|
||||
written for chinese devboard based on STM32F103RBT6
|
||||
|
||||
Press H for help
|
||||
|
||||
140
GPS+ultrasonic/adc.c
Normal file
140
GPS+ultrasonic/adc.c
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* adc.c - functions for Sharp 2Y0A02 distance meter & photosensor
|
||||
*
|
||||
* 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 "adc.h"
|
||||
#include "main.h"
|
||||
|
||||
uint16_t ADC_value[ADC_CHANNEL_NUMBER]; // Values of ADC
|
||||
uint16_t ADC_trig_val[ADC_CHANNEL_NUMBER]; // -//- at trigger time
|
||||
|
||||
void init_adc_sensor(){
|
||||
// we will use ADC1 channel 0 for IR sensor & ADC1 channel 1 for laser's photoresistor
|
||||
uint8_t adc_channel_array[ADC_CHANNEL_NUMBER] = {0,1};
|
||||
// Make sure the ADC doesn't run during config
|
||||
adc_off(ADC1);
|
||||
// enable ADC & PA0/PA1 clocking
|
||||
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN | RCC_APB2ENR_IOPAEN);
|
||||
rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV4);
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO0 | GPIO1);
|
||||
rcc_periph_clock_enable(RCC_DMA1); // enable DMA for ADC values storing
|
||||
// Configure ADC as continuous scan mode with DMA
|
||||
ADC1_CR1 = ADC_CR1_SCAN; // enable scan mode
|
||||
// set sample time on channels 1&2: 239.5 cycles for better results
|
||||
ADC1_SMPR2 = 0x3f;
|
||||
dma_channel_reset(DMA1, DMA_CHANNEL1);
|
||||
DMA1_CPAR1 = (uint32_t) &(ADC_DR(ADC1));
|
||||
DMA1_CMAR1 = (uint32_t) ADC_value;
|
||||
DMA1_CNDTR1 = ADC_CHANNEL_NUMBER;
|
||||
DMA1_CCR1 = DMA_CCR_MINC | DMA_CCR_PSIZE_16BIT | DMA_CCR_MSIZE_16BIT
|
||||
| DMA_CCR_CIRC | DMA_CCR_PL_HIGH | DMA_CCR_EN;
|
||||
// continuous conv, enable ADC & DMA
|
||||
ADC1_CR2 = ADC_CR2_CONT | ADC_CR2_ADON | ADC_CR2_DMA;
|
||||
// set channels
|
||||
adc_set_regular_sequence(ADC1, ADC_CHANNEL_NUMBER, adc_channel_array);
|
||||
// reset calibration registers & start calibration
|
||||
ADC1_CR2 |= ADC_CR2_RSTCAL;
|
||||
while(ADC1_CR2 & ADC_CR2_RSTCAL); // wait for registers reset
|
||||
ADC1_CR2 |= ADC_CR2_CAL;
|
||||
while(ADC1_CR2 & ADC_CR2_CAL); // wait for calibration ends
|
||||
// set threshold limits
|
||||
// ADC1_HTR = ADC_WDG_HIGH;
|
||||
// ADC1_LTR = ADC_WDG_LOW;
|
||||
// enable analog watchdog on single regular channel 0 & enable interrupt
|
||||
//ADC1_CR1 = ADC_CR1_AWDEN | ADC_CR1_AWDSGL | ADC_CR1_AWDIE;
|
||||
// enable analog watchdog on all regular channels & enable interrupt
|
||||
// ADC1_CR1 |= ADC_CR1_AWDEN | ADC_CR1_AWDIE;
|
||||
nvic_enable_irq(NVIC_ADC1_2_IRQ);
|
||||
ADC1_CR2 |= ADC_CR2_SWSTART;
|
||||
// turn on ADC - to do it we need set ADC_CR2_ADON again!
|
||||
ADC1_CR2 |= ADC_CR2_ADON;
|
||||
}
|
||||
|
||||
adwd_stat adc_status[ADC_CHANNEL_NUMBER] = {ADWD_MID, ADWD_MID};
|
||||
|
||||
/**
|
||||
* watchdog works on both channels, so we need to save status of WD events
|
||||
* to prevent repeated events on constant signal level
|
||||
*
|
||||
void adc1_2_isr(){
|
||||
int i;
|
||||
if(ADC1_SR & ADC_SR_AWD){ // analog watchdog event
|
||||
for(i = 0; i < ADC_CHANNEL_NUMBER; ++i){
|
||||
uint16_t val = ADC_value[i];
|
||||
adwd_stat st = adc_status[i];
|
||||
// if(adc_ms[i] == DIDNT_TRIGGERED){
|
||||
if(val > ADC_WDG_HIGH){ // watchdog event on high level
|
||||
if(st != ADWD_HI){
|
||||
adc_ms[i] = Timer;
|
||||
memcpy(&adc_time, ¤t_time, sizeof(curtime));
|
||||
adc_status[i] = ADWD_HI;
|
||||
ADC_trig_val[i] = val;
|
||||
}
|
||||
}else if(val < ADC_WDG_LOW){ // watchdog event on low level
|
||||
if(st != ADWD_LOW){
|
||||
adc_ms[i] = Timer;
|
||||
memcpy(&adc_time, ¤t_time, sizeof(curtime));
|
||||
adc_status[i] = ADWD_LOW;
|
||||
ADC_trig_val[i] = val;
|
||||
}
|
||||
}else if(val > ADC_WDG_LOW+ADC_WDG_THRES && val < ADC_WDG_HIGH-ADC_WDG_THRES){
|
||||
adc_status[i] = ADWD_MID;
|
||||
if(adc_ms[i] == Timer) // remove noice
|
||||
adc_ms[i] = DIDNT_TRIGGERED;
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
ADC1_SR = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// levels for thresholding
|
||||
const uint16_t ADC_lowlevel[2] = {900, 2700}; // signal if ADC value < lowlevel
|
||||
const uint16_t ADC_highlevel[2] = {2200, 5000}; // signal if ADC value > highlevel
|
||||
const uint16_t ADC_midlevel[2] = {1400, 3000}; // when transit through midlevel set status as ADWD_MID
|
||||
|
||||
void poll_ADC(){
|
||||
int i;
|
||||
for(i = 0; i < ADC_CHANNEL_NUMBER; ++i){
|
||||
uint16_t val = ADC_value[i];
|
||||
adwd_stat st = adc_status[i];
|
||||
if(val > ADC_highlevel[i]){ // watchdog event on high level
|
||||
if(st != ADWD_HI){
|
||||
adc_ms[i] = Timer;
|
||||
memcpy(&adc_time[i], ¤t_time, sizeof(curtime));
|
||||
adc_status[i] = ADWD_HI;
|
||||
ADC_trig_val[i] = val;
|
||||
}
|
||||
}else if(val < ADC_lowlevel[i]){ // watchdog event on low level
|
||||
if(st != ADWD_LOW){
|
||||
adc_ms[i] = Timer;
|
||||
memcpy(&adc_time[i], ¤t_time, sizeof(curtime));
|
||||
adc_status[i] = ADWD_LOW;
|
||||
ADC_trig_val[i] = val;
|
||||
}
|
||||
}else if((st == ADWD_HI && val < ADC_midlevel[i]) ||
|
||||
(st == ADWD_LOW && val > ADC_midlevel[i])){
|
||||
adc_status[i] = ADWD_MID;
|
||||
if(adc_ms[i] == Timer) // remove noice
|
||||
adc_ms[i] = DIDNT_TRIGGERED;
|
||||
}
|
||||
}
|
||||
}
|
||||
52
GPS+ultrasonic/adc.h
Normal file
52
GPS+ultrasonic/adc.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* adc.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 __SHARP_H__
|
||||
#define __SHARP_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint16_t ADC_value[];
|
||||
extern uint16_t ADC_trig_val[];
|
||||
|
||||
typedef enum{
|
||||
ADWD_LOW, // watchdog at low-level
|
||||
ADWD_MID, // normal state
|
||||
ADWD_HI // watchdog at high-level
|
||||
} adwd_stat;
|
||||
|
||||
extern adwd_stat adc_status[];
|
||||
|
||||
|
||||
#define ADC_CHANNEL_NUMBER (2)
|
||||
|
||||
// something near
|
||||
#define ADC_WDG_HIGH ((uint16_t)1500)
|
||||
// nothing in front of sensor
|
||||
#define ADC_WDG_LOW ((uint16_t)700)
|
||||
// threshold above levels
|
||||
#define ADC_WDG_THRES ((uint16_t)200)
|
||||
|
||||
void init_adc_sensor();
|
||||
void poll_ADC();
|
||||
|
||||
#endif // __SHARP_H__
|
||||
314
GPS+ultrasonic/cdcacm.c
Normal file
314
GPS+ultrasonic/cdcacm.c
Normal file
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
* Copyright 2014 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cdcacm.h"
|
||||
#include "user_proto.h"
|
||||
#include "main.h"
|
||||
|
||||
// Buffer for USB Tx
|
||||
static uint8_t USB_Tx_Buffer[USB_TX_DATA_SIZE];
|
||||
static uint8_t USB_Tx_ptr = 0;
|
||||
// connection flag
|
||||
uint8_t USB_connected = 0;
|
||||
static const struct usb_device_descriptor dev = {
|
||||
.bLength = USB_DT_DEVICE_SIZE,
|
||||
.bDescriptorType = USB_DT_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = USB_CLASS_CDC,
|
||||
.bDeviceSubClass = 0,
|
||||
.bDeviceProtocol = 0,
|
||||
.bMaxPacketSize0 = 64,
|
||||
.idVendor = 0x0483,
|
||||
.idProduct = 0x5740,
|
||||
.bcdDevice = 0x0200,
|
||||
.iManufacturer = 1,
|
||||
.iProduct = 2,
|
||||
.iSerialNumber = 3,
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
char usbdatabuf[USB_RX_DATA_SIZE]; // buffer for received data
|
||||
int usbdatalen = 0; // lenght of received data
|
||||
|
||||
/*
|
||||
* This notification endpoint isn't implemented. According to CDC spec its
|
||||
* optional, but its absence causes a NULL pointer dereference in Linux
|
||||
* cdc_acm driver.
|
||||
*/
|
||||
static const struct usb_endpoint_descriptor comm_endp[] = {{
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x83,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
|
||||
.wMaxPacketSize = 16,
|
||||
.bInterval = 255,
|
||||
}};
|
||||
|
||||
static const struct usb_endpoint_descriptor data_endp[] = {{
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x01,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 1,
|
||||
}, {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x82,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 1,
|
||||
}};
|
||||
|
||||
static const struct {
|
||||
struct usb_cdc_header_descriptor header;
|
||||
struct usb_cdc_call_management_descriptor call_mgmt;
|
||||
struct usb_cdc_acm_descriptor acm;
|
||||
struct usb_cdc_union_descriptor cdc_union;
|
||||
} __attribute__((packed)) cdcacm_functional_descriptors = {
|
||||
.header = {
|
||||
.bFunctionLength = sizeof(struct usb_cdc_header_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_HEADER,
|
||||
.bcdCDC = 0x0110,
|
||||
},
|
||||
.call_mgmt = {
|
||||
.bFunctionLength =
|
||||
sizeof(struct usb_cdc_call_management_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
|
||||
.bmCapabilities = 0,
|
||||
.bDataInterface = 1,
|
||||
},
|
||||
.acm = {
|
||||
.bFunctionLength = sizeof(struct usb_cdc_acm_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_ACM,
|
||||
.bmCapabilities = 0,
|
||||
},
|
||||
.cdc_union = {
|
||||
.bFunctionLength = sizeof(struct usb_cdc_union_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_UNION,
|
||||
.bControlInterface = 0,
|
||||
.bSubordinateInterface0 = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct usb_interface_descriptor comm_iface[] = {{
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 1,
|
||||
.bInterfaceClass = USB_CLASS_CDC,
|
||||
.bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
|
||||
.bInterfaceProtocol = USB_CDC_PROTOCOL_AT,
|
||||
.iInterface = 0,
|
||||
|
||||
.endpoint = comm_endp,
|
||||
|
||||
.extra = &cdcacm_functional_descriptors,
|
||||
.extralen = sizeof(cdcacm_functional_descriptors),
|
||||
}};
|
||||
|
||||
static const struct usb_interface_descriptor data_iface[] = {{
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 1,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 2,
|
||||
.bInterfaceClass = USB_CLASS_DATA,
|
||||
.bInterfaceSubClass = 0,
|
||||
.bInterfaceProtocol = 0,
|
||||
.iInterface = 0,
|
||||
|
||||
.endpoint = data_endp,
|
||||
}};
|
||||
|
||||
static const struct usb_interface ifaces[] = {{
|
||||
.num_altsetting = 1,
|
||||
.altsetting = comm_iface,
|
||||
}, {
|
||||
.num_altsetting = 1,
|
||||
.altsetting = data_iface,
|
||||
}};
|
||||
|
||||
static const struct usb_config_descriptor config = {
|
||||
.bLength = USB_DT_CONFIGURATION_SIZE,
|
||||
.bDescriptorType = USB_DT_CONFIGURATION,
|
||||
.wTotalLength = 0,
|
||||
.bNumInterfaces = 2,
|
||||
.bConfigurationValue = 1,
|
||||
.iConfiguration = 0,
|
||||
.bmAttributes = 0x80,
|
||||
.bMaxPower = 0x32,
|
||||
|
||||
.interface = ifaces,
|
||||
};
|
||||
|
||||
static const char *usb_strings[] = {
|
||||
"Organisation, author",
|
||||
"device",
|
||||
"version",
|
||||
};
|
||||
|
||||
// default line coding: B115200, 1stop, 8bits, parity none
|
||||
struct usb_cdc_line_coding linecoding = {
|
||||
.dwDTERate = 115200,
|
||||
.bCharFormat = USB_CDC_1_STOP_BITS,
|
||||
.bParityType = USB_CDC_NO_PARITY,
|
||||
.bDataBits = 8,
|
||||
};
|
||||
|
||||
/* Buffer to be used for control requests. */
|
||||
uint8_t usbd_control_buffer[128];
|
||||
|
||||
/**
|
||||
* This function runs every time it gets a request for control parameters get/set
|
||||
* parameter SET_LINE_CODING used to change USART1 parameters: if you want to
|
||||
* change them, just connect through USB with required parameters
|
||||
*/
|
||||
static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf,
|
||||
uint16_t *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req)){
|
||||
(void)complete;
|
||||
(void)buf;
|
||||
(void)usbd_dev;
|
||||
char local_buf[10];
|
||||
struct usb_cdc_line_coding lc;
|
||||
|
||||
switch (req->bRequest) {
|
||||
case SET_CONTROL_LINE_STATE:{
|
||||
if(req->wValue){ // terminal is opened
|
||||
USB_connected = 1;
|
||||
}else{ // terminal is closed
|
||||
USB_connected = 0;
|
||||
}
|
||||
/*
|
||||
* This Linux cdc_acm driver requires this to be implemented
|
||||
* even though it's optional in the CDC spec, and we don't
|
||||
* advertise it in the ACM functional descriptor.
|
||||
*/
|
||||
struct usb_cdc_notification *notif = (void *)local_buf;
|
||||
/* We echo signals back to host as notification. */
|
||||
notif->bmRequestType = 0xA1;
|
||||
notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE;
|
||||
notif->wValue = 0;
|
||||
notif->wIndex = 0;
|
||||
notif->wLength = 2;
|
||||
local_buf[8] = req->wValue & 3;
|
||||
local_buf[9] = 0;
|
||||
usbd_ep_write_packet(usbd_dev, 0x83, local_buf, 10);
|
||||
}break;
|
||||
case SET_LINE_CODING:
|
||||
if (!len || (*len != sizeof(struct usb_cdc_line_coding)))
|
||||
return 0;
|
||||
memcpy((void *)&lc, (void *)*buf, *len);
|
||||
// Mark & Space parity don't support by hardware, check it
|
||||
if(lc.bParityType == USB_CDC_MARK_PARITY || lc.bParityType == USB_CDC_SPACE_PARITY){
|
||||
return 0; // error
|
||||
}else{
|
||||
// memcpy((void *)&linecoding, (void *)&lc, sizeof(struct usb_cdc_line_coding));
|
||||
// UART_setspeed(USART1, &linecoding);
|
||||
}
|
||||
break;
|
||||
case GET_LINE_CODING: // return linecoding buffer
|
||||
if(len && *len == sizeof(struct usb_cdc_line_coding))
|
||||
memcpy((void *)*buf, (void *)&linecoding, sizeof(struct usb_cdc_line_coding));
|
||||
//usbd_ep_write_packet(usbd_dev, 0x83, (char*)&linecoding, sizeof(linecoding));
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep){
|
||||
(void)ep;
|
||||
int len = usbd_ep_read_packet(usbd_dev, 0x01, usbdatabuf + usbdatalen, USB_RX_DATA_SIZE - usbdatalen);
|
||||
usbdatalen += len;
|
||||
if(usbdatalen >= USB_RX_DATA_SIZE){ // buffer overflow - drop all its contents
|
||||
usbdatalen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void cdcacm_data_tx_cb(usbd_device *usbd_dev, uint8_t ep){
|
||||
(void)ep;
|
||||
(void)usbd_dev;
|
||||
|
||||
usb_send_buffer();
|
||||
}
|
||||
|
||||
static void cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue)
|
||||
{
|
||||
(void)wValue;
|
||||
(void)usbd_dev;
|
||||
|
||||
usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, USB_RX_DATA_SIZE, cdcacm_data_rx_cb);
|
||||
usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, USB_TX_DATA_SIZE, cdcacm_data_tx_cb);
|
||||
usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
|
||||
|
||||
usbd_register_control_callback(
|
||||
usbd_dev,
|
||||
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
|
||||
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
|
||||
cdcacm_control_request);
|
||||
}
|
||||
|
||||
static usbd_device *current_usb = NULL;
|
||||
|
||||
usbd_device *USB_init(){
|
||||
current_usb = usbd_init(&stm32f103_usb_driver, &dev, &config,
|
||||
usb_strings, 3, usbd_control_buffer, sizeof(usbd_control_buffer));
|
||||
if(!current_usb) return NULL;
|
||||
usbd_register_set_config_callback(current_usb, cdcacm_set_config);
|
||||
return current_usb;
|
||||
}
|
||||
|
||||
mutex_t send_block_mutex = MUTEX_UNLOCKED;
|
||||
/**
|
||||
* Put byte into USB buffer to send
|
||||
* @param byte - a byte to put into a buffer
|
||||
*/
|
||||
void usb_send(uint8_t byte){
|
||||
mutex_lock(&send_block_mutex);
|
||||
USB_Tx_Buffer[USB_Tx_ptr++] = byte;
|
||||
mutex_unlock(&send_block_mutex);
|
||||
if(USB_Tx_ptr == USB_TX_DATA_SIZE){ // buffer can be overflowed - send it!
|
||||
usb_send_buffer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send all data in buffer over USB
|
||||
* this function runs when buffer is full or on SysTick
|
||||
*/
|
||||
void usb_send_buffer(){
|
||||
if(MUTEX_LOCKED == mutex_trylock(&send_block_mutex)) return;
|
||||
if(USB_Tx_ptr){
|
||||
if(current_usb && USB_connected){
|
||||
// usbd_ep_write_packet return 0 if previous packet isn't transmit yet
|
||||
while(USB_Tx_ptr != usbd_ep_write_packet(current_usb, 0x82, USB_Tx_Buffer, USB_Tx_ptr));
|
||||
usbd_poll(current_usb);
|
||||
}
|
||||
USB_Tx_ptr = 0;
|
||||
}
|
||||
mutex_unlock(&send_block_mutex);
|
||||
}
|
||||
54
GPS+ultrasonic/cdcacm.h
Normal file
54
GPS+ultrasonic/cdcacm.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* ccdcacm.h
|
||||
*
|
||||
* Copyright 2014 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 __CCDCACM_H__
|
||||
#define __CCDCACM_H__
|
||||
|
||||
#include <libopencm3/usb/usbd.h>
|
||||
|
||||
// commands through EP0
|
||||
#define SEND_ENCAPSULATED_COMMAND 0x00
|
||||
#define GET_ENCAPSULATED_RESPONSE 0x01
|
||||
#define SET_COMM_FEATURE 0x02
|
||||
#define GET_COMM_FEATURE 0x03
|
||||
#define CLEAR_COMM_FEATURE 0x04
|
||||
#define SET_LINE_CODING 0x20
|
||||
#define GET_LINE_CODING 0x21
|
||||
#define SET_CONTROL_LINE_STATE 0x22
|
||||
#define SEND_BREAK 0x23
|
||||
|
||||
// Size of input/output buffers
|
||||
#define USB_TX_DATA_SIZE 64
|
||||
#define USB_RX_DATA_SIZE 64
|
||||
|
||||
// USB connection flag
|
||||
extern uint8_t USB_connected;
|
||||
extern struct usb_cdc_line_coding linecoding;
|
||||
|
||||
extern char usbdatabuf[];
|
||||
extern int usbdatalen;
|
||||
|
||||
usbd_device *USB_init();
|
||||
void usb_send(uint8_t byte);
|
||||
void usb_send_buffer();
|
||||
|
||||
#endif // __CCDCACM_H__
|
||||
121
GPS+ultrasonic/hardware_ini.c
Normal file
121
GPS+ultrasonic/hardware_ini.c
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* hardware_ini.c - functions for HW initialisation
|
||||
*
|
||||
* Copyright 2014 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* All hardware-dependent initialisation & definition should be placed here
|
||||
* and in hardware_ini.h
|
||||
*
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include "hardware_ini.h"
|
||||
|
||||
/**
|
||||
* GPIO initialisaion: clocking + pins setup
|
||||
*/
|
||||
void GPIO_init(){
|
||||
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN |
|
||||
RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN |
|
||||
RCC_APB2ENR_IOPEEN);
|
||||
/*
|
||||
* Setup EXTI on PA4 (PPS input from GPS) - pull down
|
||||
* EXTI on PA5 - also pull down (trigger for time measurement)
|
||||
*/
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO4 | GPIO5);
|
||||
//AFIO_EXTICR2 = 0;
|
||||
exti_enable_request(EXTI4 | EXTI5);
|
||||
// trigger on rising edge
|
||||
exti_set_trigger(EXTI4 | EXTI5, EXTI_TRIGGER_RISING);
|
||||
nvic_enable_irq(NVIC_EXTI4_IRQ);
|
||||
nvic_enable_irq(NVIC_EXTI9_5_IRQ);
|
||||
/*
|
||||
// Buttons: pull-up input
|
||||
gpio_set_mode(BTNS_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN,
|
||||
BTN_S2_PIN | BTN_S3_PIN);
|
||||
// turn on pull-up
|
||||
gpio_set(BTNS_PORT, BTN_S2_PIN | BTN_S3_PIN);
|
||||
// LEDS: opendrain output
|
||||
gpio_set_mode(LEDS_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN,
|
||||
LED_D1_PIN | LED_D2_PIN);
|
||||
// turn off LEDs
|
||||
gpio_set(LEDS_PORT, LED_D1_PIN | LED_D2_PIN);*/
|
||||
/*
|
||||
// USB_DISC: push-pull
|
||||
gpio_set_mode(USB_DISC_PORT, GPIO_MODE_OUTPUT_2_MHZ,
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, USB_DISC_PIN);
|
||||
// USB_POWER: open drain, externall pull down with R7 (22k)
|
||||
gpio_set_mode(USB_POWER_PORT, GPIO_MODE_INPUT,
|
||||
GPIO_CNF_INPUT_FLOAT, USB_POWER_PIN);
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* SysTick used for system timer with period of 1ms
|
||||
*/
|
||||
void SysTick_init(){
|
||||
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); // Systyck: 72/8=9MHz
|
||||
STK_RVR = STK_RVR_DEFAULT_VAL; // 9000 pulses: 1kHz
|
||||
systick_interrupt_enable();
|
||||
systick_counter_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* PA5 interrupt - print time at button/switch trigger
|
||||
*/
|
||||
void exti9_5_isr(){
|
||||
if(EXTI_PR & EXTI5){
|
||||
if(trigger_ms == DIDNT_TRIGGERED){ // prevent bounce
|
||||
trigger_ms = Timer;
|
||||
memcpy(&trigger_time, ¤t_time, sizeof(curtime));
|
||||
}
|
||||
EXTI_PR = EXTI5;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// check buttons S2/S3
|
||||
void check_btns(){
|
||||
static uint8_t oldstate[2] = {1,1}; // old buttons state
|
||||
uint8_t newstate[2], i;
|
||||
static uint32_t Old_timer[2] = {0,0};
|
||||
newstate[0] = gpio_get(BTNS_PORT, BTN_S2_PIN) ? 1 : 0;
|
||||
newstate[1] = gpio_get(BTNS_PORT, BTN_S3_PIN) ? 1 : 0;
|
||||
for(i = 0; i < 2; i++){
|
||||
uint8_t new = newstate[i];
|
||||
// pause for 60ms
|
||||
uint32_t O = Old_timer[i];
|
||||
if(O){
|
||||
if(Timer - O > 60 || O > Timer){
|
||||
P("Button S");
|
||||
usb_send('2' + i);
|
||||
if(new) P("released");
|
||||
else P("pressed");
|
||||
newline();
|
||||
oldstate[i] = new;
|
||||
Old_timer[i] = 0;
|
||||
}
|
||||
}
|
||||
else if(new != oldstate[i]){
|
||||
Old_timer[i] = Timer;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
76
GPS+ultrasonic/hardware_ini.h
Normal file
76
GPS+ultrasonic/hardware_ini.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* hardware_ini.h
|
||||
*
|
||||
* Copyright 2014 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_INI_H__
|
||||
#define __HARDWARE_INI_H__
|
||||
|
||||
/*
|
||||
* Timers:
|
||||
* SysTick - system time
|
||||
*/
|
||||
|
||||
|
||||
void GPIO_init();
|
||||
void SysTick_init();
|
||||
|
||||
/*
|
||||
* Buttons on devboard
|
||||
*/
|
||||
#define BTNS_PORT GPIOC
|
||||
// PCO -- S2
|
||||
#define BTN_S2_PIN GPIO0
|
||||
// PC1 -- S3
|
||||
#define BTN_S3_PIN GPIO1
|
||||
|
||||
/*
|
||||
* LEDS: PB9 for D1, PB8 for D2
|
||||
*/
|
||||
#define LEDS_PORT GPIOB
|
||||
#define LED_D1_PIN GPIO9
|
||||
#define LED_D2_PIN GPIO8
|
||||
|
||||
/*
|
||||
* USB interface
|
||||
* connect boot1 jumper to gnd, boot0 to gnd; and reconnect boot0 to +3.3 to boot flash
|
||||
*/
|
||||
/*
|
||||
// USB_DICS (disconnect) - PC11
|
||||
#define USB_DISC_PIN GPIO11
|
||||
#define USB_DISC_PORT GPIOC
|
||||
// USB_POWER (high level when USB connected to PC)
|
||||
#define USB_POWER_PIN GPIO10
|
||||
#define USB_POWER_PORT GPIOC
|
||||
// change signal level on USB diconnect pin
|
||||
#define usb_disc_high() gpio_set(USB_DISC_PORT, USB_DISC_PIN)
|
||||
#define usb_disc_low() gpio_clear(USB_DISC_PORT, USB_DISC_PIN)
|
||||
// in case of n-channel FET on 1.5k pull-up change on/off disconnect means low level
|
||||
// in case of pnp bipolar transistor or p-channel FET on 1.5k pull-up disconnect means high level
|
||||
#define usb_disconnect() usb_disc_high()
|
||||
#define usb_connect() usb_disc_low()
|
||||
*/
|
||||
// my simple devboard have no variants for programmed connection/disconnection of USB
|
||||
#define usb_disconnect()
|
||||
#define usb_connect()
|
||||
|
||||
void check_btns();
|
||||
|
||||
#endif // __HARDWARE_INI_H__
|
||||
9
GPS+ultrasonic/ld/devices.data
Normal file
9
GPS+ultrasonic/ld/devices.data
Normal file
@ -0,0 +1,9 @@
|
||||
stm32f103?4* stm32f1 ROM=16K RAM=6K
|
||||
stm32f103?6* stm32f1 ROM=32K RAM=10K
|
||||
stm32f103?8* stm32f1 ROM=64K RAM=20K
|
||||
stm32f103?b* stm32f1 ROM=128K RAM=20K
|
||||
stm32f103?c* stm32f1 ROM=256K RAM=48K
|
||||
stm32f103?d* stm32f1 ROM=384K RAM=64K
|
||||
stm32f103?e* stm32f1 ROM=512K RAM=64K
|
||||
stm32f103?f* stm32f1 ROM=768K RAM=96K
|
||||
stm32f103?g* stm32f1 ROM=1024K RAM=96K
|
||||
31
GPS+ultrasonic/ld/stm32f103x4.ld
Normal file
31
GPS+ultrasonic/ld/stm32f103x4.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 16K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 6K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
GPS+ultrasonic/ld/stm32f103x6.ld
Normal file
31
GPS+ultrasonic/ld/stm32f103x6.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 32K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 10K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
GPS+ultrasonic/ld/stm32f103x8.ld
Normal file
31
GPS+ultrasonic/ld/stm32f103x8.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 64K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
GPS+ultrasonic/ld/stm32f103xB.ld
Normal file
31
GPS+ultrasonic/ld/stm32f103xB.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
GPS+ultrasonic/ld/stm32f103xC.ld
Normal file
31
GPS+ultrasonic/ld/stm32f103xC.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 256K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
GPS+ultrasonic/ld/stm32f103xD.ld
Normal file
31
GPS+ultrasonic/ld/stm32f103xD.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 384K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
GPS+ultrasonic/ld/stm32f103xE.ld
Normal file
31
GPS+ultrasonic/ld/stm32f103xE.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
GPS+ultrasonic/ld/stm32f103xF.ld
Normal file
31
GPS+ultrasonic/ld/stm32f103xF.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 768K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
GPS+ultrasonic/ld/stm32f103xG.ld
Normal file
31
GPS+ultrasonic/ld/stm32f103xG.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
271
GPS+ultrasonic/main.c
Normal file
271
GPS+ultrasonic/main.c
Normal file
@ -0,0 +1,271 @@
|
||||
/*
|
||||
* main.c
|
||||
*
|
||||
* Copyright 2014 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 "main.h"
|
||||
#include "hardware_ini.h"
|
||||
#include "cdcacm.h"
|
||||
#include "uart.h"
|
||||
#include "GPS.h"
|
||||
#include "ultrasonic.h"
|
||||
#include "adc.h"
|
||||
|
||||
volatile uint32_t Timer = 0; // milliseconds
|
||||
volatile uint32_t msctr = 0; // global milliseconds for different purposes
|
||||
usbd_device *usbd_dev;
|
||||
volatile int32_t systick_val = 0;
|
||||
volatile int32_t timer_val = 0;
|
||||
volatile int clear_ST_on_connect = 1;
|
||||
|
||||
volatile int need_sync = 1;
|
||||
|
||||
volatile uint32_t last_corr_time = 0; // time of last PPS correction (seconds from midnight)
|
||||
|
||||
// STK_CVR values for all milliseconds (RVR0) and last millisecond (RVR1)
|
||||
volatile uint32_t RVR0 = STK_RVR_DEFAULT_VAL, RVR1 = STK_RVR_DEFAULT_VAL;
|
||||
|
||||
curtime current_time = {25,61,61};
|
||||
|
||||
curtime trigger_time = {25, 61, 61};
|
||||
curtime adc_time[ADC_CHANNEL_NUMBER] = {{25, 61, 61}, {25, 61, 61}};
|
||||
curtime ultrasonic_time = {25, 61, 61};
|
||||
uint32_t trigger_ms = DIDNT_TRIGGERED, adc_ms[ADC_CHANNEL_NUMBER] = {DIDNT_TRIGGERED, DIDNT_TRIGGERED},
|
||||
ultrasonic_ms = DIDNT_TRIGGERED;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(){
|
||||
uint8_t *string;
|
||||
int i;
|
||||
// RCC clocking: 8MHz oscillator -> 72MHz system
|
||||
rcc_clock_setup_in_hse_8mhz_out_72mhz();
|
||||
|
||||
GPIO_init();
|
||||
|
||||
usb_disconnect(); // turn off USB while initializing all
|
||||
|
||||
// USB
|
||||
usbd_dev = USB_init();
|
||||
|
||||
// SysTick is a system timer with 1ms period
|
||||
SysTick_init();
|
||||
UART_init(USART2); // init GPS UART
|
||||
|
||||
tim2_init();
|
||||
// wait a little and then turn on USB pullup
|
||||
// for (i = 0; i < 0x800000; i++)
|
||||
// __asm__("nop");
|
||||
|
||||
usb_connect(); // turn on USB
|
||||
|
||||
GPS_send_start_seq();
|
||||
init_adc_sensor();
|
||||
|
||||
uint32_t trigrtm = 0, adctm[2] = {0, 0}, ultrasonictm = 0;
|
||||
while(1){
|
||||
usbd_poll(usbd_dev);
|
||||
poll_ultrasonic();
|
||||
poll_ADC();
|
||||
if(usbdatalen){ // there's something in USB buffer
|
||||
usbdatalen = parce_incoming_buf(usbdatabuf, usbdatalen);
|
||||
}
|
||||
if((string = check_UART2())){
|
||||
// P(string);
|
||||
GPS_parse_answer(string);
|
||||
}
|
||||
if(systick_val > 1000){
|
||||
P("Systick differs by ");
|
||||
print_int(systick_val);
|
||||
systick_val = 0;
|
||||
P(", timer value: ");
|
||||
print_int(timer_val);
|
||||
P(", RVR0 = ");
|
||||
print_int(RVR0);
|
||||
P(", RVR1 = ");
|
||||
print_int(RVR1);
|
||||
P("\n");
|
||||
print_curtime();
|
||||
}
|
||||
if(trigger_ms != DIDNT_TRIGGERED && trigger_ms != Timer){
|
||||
if(msctr - trigrtm > 500 || trigrtm > msctr){
|
||||
trigrtm = msctr;
|
||||
P("Trigger time: ");
|
||||
print_time(&trigger_time, trigger_ms);
|
||||
}
|
||||
trigger_ms = DIDNT_TRIGGERED;
|
||||
}
|
||||
for(i = 0; i < ADC_CHANNEL_NUMBER; ++i){
|
||||
if(adc_ms[i] != DIDNT_TRIGGERED && adc_ms[i] != Timer){
|
||||
if(msctr - adctm[i] > 500 || adctm[i] > msctr){
|
||||
/*int16_t diff = ADC_trig_val[i] - ADC_value[i];
|
||||
if(diff < 0) diff = -diff;
|
||||
if(diff < ADC_WDG_THRES/2){ // omit noice
|
||||
*/
|
||||
adctm[i] = msctr;
|
||||
P("ADC");
|
||||
usb_send('0'+i);
|
||||
if(adc_status[i] == ADWD_HI) P("hi");
|
||||
else if(adc_status[i] == ADWD_LOW) P("lo");
|
||||
P(": value = ");
|
||||
print_int(ADC_trig_val[i]);
|
||||
P(" (now: ");
|
||||
print_int(ADC_value[i]);
|
||||
P("), time = ");
|
||||
print_time(&adc_time[i], adc_ms[i]);
|
||||
//}
|
||||
}
|
||||
adc_ms[i] = DIDNT_TRIGGERED;
|
||||
}
|
||||
}
|
||||
if(ultrasonic_ms != DIDNT_TRIGGERED && ultrasonic_ms != Timer){
|
||||
if(msctr - ultrasonictm > 500 || ultrasonictm > msctr){
|
||||
ultrasonictm = msctr;
|
||||
P("Ultrasonic time: ");
|
||||
print_time(&ultrasonic_time, ultrasonic_ms);
|
||||
}
|
||||
ultrasonic_ms = DIDNT_TRIGGERED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* SysTick interrupt: increment global time & send data buffer through USB
|
||||
*/
|
||||
void sys_tick_handler(){
|
||||
++Timer;
|
||||
++msctr;
|
||||
if(Timer == 999){
|
||||
STK_RVR = RVR1;
|
||||
}else if(Timer == 1000){
|
||||
STK_RVR = RVR0;
|
||||
time_increment();
|
||||
}
|
||||
usb_send_buffer();
|
||||
}
|
||||
// STK_CVR - current systick val
|
||||
// STK_RVR - ticks till interrupt - 1
|
||||
|
||||
// PA4 interrupt - PPS signal
|
||||
void exti4_isr(){
|
||||
uint32_t t = 0, ticks;
|
||||
static uint32_t ticksavr = 0, N = 0;
|
||||
if(EXTI_PR & EXTI4){
|
||||
// correct
|
||||
systick_val = STK_CVR;
|
||||
STK_CVR = RVR0;
|
||||
timer_val = Timer;
|
||||
Timer = 0;
|
||||
systick_val = STK_RVR + 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 = STK_RVR_DEFAULT_VAL;
|
||||
STK_RVR = 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(clear_ST_on_connect){
|
||||
clear_ST_on_connect = 0;
|
||||
}else{
|
||||
// || (last_corr_time == 86399 && t == 0)
|
||||
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
|
||||
STK_RVR = 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;
|
||||
EXTI_PR = EXTI4;
|
||||
}
|
||||
}
|
||||
|
||||
// pause function, delay in ms
|
||||
void Delay(uint16_t time){
|
||||
uint32_t waitto = msctr + time;
|
||||
while(msctr != waitto);
|
||||
}
|
||||
|
||||
/**
|
||||
* set current time by buffer hhmmss
|
||||
*/
|
||||
void set_time(uint8_t *buf){
|
||||
inline uint8_t atou(uint8_t *b){
|
||||
return (b[0]-'0')*10 + b[1]-'0';
|
||||
}
|
||||
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]);
|
||||
}
|
||||
|
||||
/**
|
||||
* print time: Tm - time structure, T - milliseconds
|
||||
*/
|
||||
void print_time(curtime *Tm, uint32_t T){
|
||||
int S = Tm->S, M = Tm->M, H = Tm->H;
|
||||
if(H < 10) usb_send('0');
|
||||
print_int(H); usb_send(':');
|
||||
if(M < 10) usb_send('0');
|
||||
print_int(M); usb_send(':');
|
||||
if(S < 10) usb_send('0');
|
||||
print_int(S); usb_send('.');
|
||||
if(T < 100) usb_send('0');
|
||||
if(T < 10) usb_send('0');
|
||||
print_int(T);
|
||||
if(GPS_status == GPS_NOT_VALID) P(" (not valid)");
|
||||
if(need_sync) P(" need synchronisation");
|
||||
newline();
|
||||
}
|
||||
|
||||
void print_curtime(){
|
||||
uint32_t T = Timer;
|
||||
if(current_time.H < 24 && GPS_status != GPS_WAIT){
|
||||
P("Current time: ");
|
||||
print_time(¤t_time, T);
|
||||
}else
|
||||
P("Waiting for satellites\n");
|
||||
}
|
||||
77
GPS+ultrasonic/main.h
Normal file
77
GPS+ultrasonic/main.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* main.h
|
||||
*
|
||||
* Copyright 2014 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 __MAIN_H__
|
||||
#define __MAIN_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <libopencm3/stm32/exti.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/usart.h>
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/usb/cdc.h>
|
||||
#include <libopencm3/usb/usbd.h>
|
||||
#include <libopencm3/cm3/systick.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/adc.h>
|
||||
#include <libopencm3/stm32/dma.h>
|
||||
#include <libopencm3/stm32/spi.h>
|
||||
|
||||
#include "sync.h" // mutexes
|
||||
#include "user_proto.h"
|
||||
|
||||
extern void *memcpy(void *dest, const void *src, int n);
|
||||
|
||||
#define _U_ __attribute__((__unused__))
|
||||
#define U8(x) ((uint8_t) x)
|
||||
#define U16(x) ((uint16_t) x)
|
||||
#define U32(x) ((uint32_t) x)
|
||||
|
||||
#define STK_RVR_DEFAULT_VAL (8999)
|
||||
#define TIMEZONE_GMT_PLUS (3)
|
||||
|
||||
#define DIDNT_TRIGGERED (2000)
|
||||
|
||||
typedef struct{
|
||||
uint8_t H;
|
||||
uint8_t M;
|
||||
uint8_t S;
|
||||
} curtime;
|
||||
|
||||
extern curtime current_time;
|
||||
extern volatile uint32_t Timer; // global timer (milliseconds)
|
||||
extern volatile int clear_ST_on_connect; // flag for clearing Systick counter on next PPS
|
||||
|
||||
extern curtime trigger_time, adc_time[], ultrasonic_time;
|
||||
extern uint32_t trigger_ms, adc_ms[], ultrasonic_ms;
|
||||
|
||||
extern volatile int need_sync;
|
||||
|
||||
void Delay(uint16_t time);
|
||||
void set_time(uint8_t *buf);
|
||||
|
||||
void print_time(curtime *T, uint32_t m);
|
||||
void print_curtime();
|
||||
|
||||
#endif // __MAIN_H__
|
||||
|
||||
93
GPS+ultrasonic/sync.c
Normal file
93
GPS+ultrasonic/sync.c
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* implement mutexes for other type of MCU (which doesn't have strex & ldrex)
|
||||
*/
|
||||
|
||||
#include <libopencm3/cm3/sync.h>
|
||||
|
||||
/* DMB is supported on CM0 */
|
||||
void __dmb()
|
||||
{
|
||||
__asm__ volatile ("dmb");
|
||||
}
|
||||
|
||||
/* Those are defined only on CM3 or CM4 */
|
||||
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
|
||||
uint32_t __ldrex(volatile uint32_t *addr)
|
||||
{
|
||||
uint32_t res;
|
||||
__asm__ volatile ("ldrex %0, [%1]" : "=r" (res) : "r" (addr));
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t __strex(uint32_t val, volatile uint32_t *addr)
|
||||
{
|
||||
uint32_t res;
|
||||
__asm__ volatile ("strex %0, %2, [%1]"
|
||||
: "=&r" (res) : "r" (addr), "r" (val));
|
||||
return res;
|
||||
}
|
||||
|
||||
void mutex_lock(mutex_t *m)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
|
||||
do {
|
||||
/* Wait until the mutex is unlocked. */
|
||||
while (__ldrex(m) != MUTEX_UNLOCKED);
|
||||
|
||||
/* Try to acquire it. */
|
||||
status = __strex(MUTEX_LOCKED, m);
|
||||
|
||||
/* Did we get it? If not then try again. */
|
||||
} while (status != 0);
|
||||
|
||||
/* Execute the mysterious Data Memory Barrier instruction! */
|
||||
__dmb();
|
||||
}
|
||||
|
||||
void mutex_unlock(mutex_t *m)
|
||||
{
|
||||
/* Ensure accesses to protected resource are finished */
|
||||
__dmb();
|
||||
|
||||
/* Free the lock. */
|
||||
*m = MUTEX_UNLOCKED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to lock mutex
|
||||
* if it's already locked or there was error in STREX, return MUTEX_LOCKED
|
||||
* else return MUTEX_UNLOCKED
|
||||
*/
|
||||
mutex_t mutex_trylock(mutex_t *m){
|
||||
uint32_t status = 0;
|
||||
mutex_t old_lock = __ldrex(m); // get mutex value
|
||||
// set mutex
|
||||
status = __strex(MUTEX_LOCKED, m);
|
||||
if(status == 0) __dmb();
|
||||
else old_lock = MUTEX_LOCKED;
|
||||
return old_lock;
|
||||
}
|
||||
|
||||
#endif
|
||||
53
GPS+ultrasonic/sync.h
Normal file
53
GPS+ultrasonic/sync.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBOPENCM3_CM3_SYNC_H
|
||||
#define LIBOPENCM3_CM3_SYNC_H
|
||||
|
||||
void __dmb(void);
|
||||
|
||||
/* Implements synchronisation primitives as discussed in the ARM document
|
||||
* DHT0008A (ID081709) "ARM Synchronization Primitives" and the ARM v7-M
|
||||
* Architecture Reference Manual.
|
||||
*/
|
||||
|
||||
/* --- Exclusive load and store instructions ------------------------------- */
|
||||
|
||||
/* Those are defined only on CM3 or CM4 */
|
||||
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
|
||||
uint32_t __ldrex(volatile uint32_t *addr);
|
||||
uint32_t __strex(uint32_t val, volatile uint32_t *addr);
|
||||
|
||||
/* --- Convenience functions ----------------------------------------------- */
|
||||
|
||||
/* Here we implement some simple synchronisation primitives. */
|
||||
|
||||
typedef uint32_t mutex_t;
|
||||
|
||||
#define MUTEX_UNLOCKED 0
|
||||
#define MUTEX_LOCKED 1
|
||||
|
||||
void mutex_lock(mutex_t *m);
|
||||
void mutex_unlock(mutex_t *m);
|
||||
mutex_t mutex_trylock(mutex_t *m);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
BIN
GPS+ultrasonic/timelapse.bin
Executable file
BIN
GPS+ultrasonic/timelapse.bin
Executable file
Binary file not shown.
262
GPS+ultrasonic/uart.c
Normal file
262
GPS+ultrasonic/uart.c
Normal file
@ -0,0 +1,262 @@
|
||||
/*
|
||||
* uart.c - functions to work with UART
|
||||
*
|
||||
* Copyright 2014 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 "main.h"
|
||||
#include "uart.h"
|
||||
#include "cdcacm.h"
|
||||
#include "hardware_ini.h"
|
||||
|
||||
// Buffers for Tx
|
||||
static UART_buff TX_buffer[2]; // Tx buffers for all three ports
|
||||
static UART_buff RX_buffer[2]; // Rx buffers for all three ports
|
||||
|
||||
void fill_uart_RXbuff(uint32_t UART, uint8_t byte);
|
||||
|
||||
/**
|
||||
* Set UART speed
|
||||
* @param lc - UART parameters or NULL for value from cdcacm.c (started - B115200,8,N,1)
|
||||
*/
|
||||
void UART_setspeed(uint32_t UART){
|
||||
usart_set_baudrate(UART, 9600);
|
||||
usart_set_databits(UART, 8);
|
||||
usart_set_stopbits(UART, USART_STOPBITS_1);
|
||||
usart_set_parity(UART, USART_PARITY_NONE);
|
||||
usart_set_flow_control(UART, USART_FLOWCONTROL_NONE);
|
||||
usart_set_mode(UART, USART_MODE_TX_RX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup UART
|
||||
*/
|
||||
void UART_init(uint32_t UART){
|
||||
uint32_t irq, rcc, rccgpio, gpioport, gpiopin;
|
||||
switch(UART){
|
||||
case USART2: // GPS UART
|
||||
irq = NVIC_USART2_IRQ; // interrupt for given USART
|
||||
rcc = RCC_USART2; // RCC timing of USART
|
||||
rccgpio = RCC_GPIOA; // RCC timing of GPIO pin (for output)
|
||||
TX_buffer[1].end = 0; // reset counters
|
||||
TX_buffer[1].start = 0;
|
||||
RX_buffer[1].end = 0;
|
||||
RX_buffer[1].start = 0;
|
||||
// output pin setup
|
||||
gpioport = GPIO_BANK_USART2_TX;
|
||||
gpiopin = GPIO_USART2_TX;
|
||||
break;
|
||||
case USART1:
|
||||
default:
|
||||
irq = NVIC_USART1_IRQ;
|
||||
rcc = RCC_USART1;
|
||||
rccgpio = RCC_GPIOA;
|
||||
TX_buffer[0].end = 0;
|
||||
TX_buffer[0].start = 0;
|
||||
RX_buffer[0].end = 0;
|
||||
RX_buffer[0].start = 0;
|
||||
gpioport = GPIO_BANK_USART1_TX;
|
||||
gpiopin = GPIO_USART1_TX;
|
||||
}
|
||||
// enable clocking
|
||||
rcc_periph_clock_enable(RCC_AFIO); // alternate functions
|
||||
rcc_periph_clock_enable(rcc); // USART
|
||||
rcc_periph_clock_enable(rccgpio); // GPIO pins
|
||||
// enable output pin
|
||||
gpio_set_mode(gpioport, GPIO_MODE_OUTPUT_50_MHZ,
|
||||
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, gpiopin);
|
||||
// enable IRQ
|
||||
nvic_enable_irq(irq);
|
||||
UART_setspeed(UART);
|
||||
// Enable UART receive interrupt
|
||||
USART_CR1(UART) |= USART_CR1_RXNEIE;
|
||||
// Enable UART
|
||||
usart_enable(UART);
|
||||
}
|
||||
|
||||
/*
|
||||
* UART interrupts
|
||||
*/
|
||||
// common
|
||||
void UART_isr(uint32_t UART){
|
||||
uint8_t bufidx = 0, data;
|
||||
UART_buff *curbuff;
|
||||
// Check if we were called because of RXNE
|
||||
if(USART_SR(UART) & USART_SR_RXNE){
|
||||
// parce incoming byte
|
||||
data = usart_recv(UART);
|
||||
fill_uart_RXbuff(UART, data);
|
||||
}
|
||||
// Check if we were called because of TXE -> send next byte in buffer
|
||||
if((USART_CR1(UART) & USART_CR1_TXEIE) && (USART_SR(UART) & USART_SR_TXE)){
|
||||
switch(UART){
|
||||
case USART1:
|
||||
bufidx = 0;
|
||||
break;
|
||||
case USART2:
|
||||
bufidx = 1;
|
||||
break;
|
||||
default: // error - return
|
||||
return;
|
||||
}
|
||||
curbuff = &TX_buffer[bufidx];
|
||||
bufidx = curbuff->start; // start of data in buffer
|
||||
if(bufidx != curbuff->end){ // there's data in buffer
|
||||
// Put data into the transmit register
|
||||
usart_send(UART, curbuff->buf[bufidx]);
|
||||
if(++(curbuff->start) == UART_BUF_DATA_SIZE){ // reload start
|
||||
curbuff->start = 0;
|
||||
}
|
||||
}else{ // Disable the TXE interrupt, it's no longer needed
|
||||
USART_CR1(UART) &= ~USART_CR1_TXEIE;
|
||||
// empty indexes
|
||||
curbuff->start = 0;
|
||||
curbuff->end = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// particular interrupt handlers
|
||||
void usart1_isr(){
|
||||
UART_isr(USART1);
|
||||
}
|
||||
void usart2_isr(){
|
||||
UART_isr(USART2);
|
||||
}
|
||||
|
||||
// put byte into Tx buffer
|
||||
void fill_uart_buff(uint32_t UART, uint8_t byte){
|
||||
UART_buff *curbuff;
|
||||
uint8_t bufidx = 0, endidx;
|
||||
if(!(USART_CR1(UART) & USART_CR1_UE)) return; // UART disabled
|
||||
USART_CR1(UART) &= ~USART_CR1_TXEIE; // disable TX interrupt while buffer filling
|
||||
while ((USART_SR(UART) & USART_SR_TXE) == 0); // wait until last byte send
|
||||
switch(UART){
|
||||
case USART1:
|
||||
bufidx = 0;
|
||||
break;
|
||||
case USART2:
|
||||
bufidx = 1;
|
||||
break;
|
||||
default: // error - return
|
||||
return;
|
||||
}
|
||||
curbuff = &TX_buffer[bufidx];
|
||||
bufidx = curbuff->start; // start of data in buffer
|
||||
endidx = curbuff->end; // end of data
|
||||
curbuff->buf[endidx++] = byte; // put byte into buffer
|
||||
// now check indexes
|
||||
if(endidx != bufidx && endidx != UART_BUF_DATA_SIZE){ // all OK - there's enough place for data
|
||||
(curbuff->end)++; // just increment index in buffer
|
||||
}else{ // dangerous situation: possible overflow
|
||||
if(endidx == UART_BUF_DATA_SIZE){ // end of buffer
|
||||
if(bufidx != 0){ // no overflow
|
||||
curbuff->end = 0;
|
||||
goto end_of_fn;
|
||||
}
|
||||
}
|
||||
// overflow: purge all data
|
||||
bufidx = curbuff->start; // refresh data index
|
||||
for(endidx = bufidx; endidx < UART_BUF_DATA_SIZE; endidx++) // first data porion
|
||||
usart_send(UART, curbuff->buf[endidx]);
|
||||
for(endidx = 0; endidx < bufidx; endidx++) // rest of data
|
||||
usart_send(UART, curbuff->buf[endidx]);
|
||||
curbuff->start = 0;
|
||||
curbuff->end = 0;
|
||||
return;
|
||||
}
|
||||
end_of_fn:
|
||||
// enable interrupts to send data from buffer
|
||||
USART_CR1(UART) |= USART_CR1_TXEIE;
|
||||
}
|
||||
|
||||
/**
|
||||
* send data over UART - one function for each uart
|
||||
* @param byte - one byte to put in UART queue
|
||||
*/
|
||||
void uart1_send(uint8_t byte){
|
||||
fill_uart_buff(USART1, byte);
|
||||
}
|
||||
void uart2_send(uint8_t byte){
|
||||
fill_uart_buff(USART2, byte);
|
||||
}
|
||||
/*
|
||||
UART_buff *get_uart_buffer(uint32_t UART){
|
||||
switch(UART){
|
||||
case USART1:
|
||||
return &RX_buffer[0];
|
||||
break;
|
||||
case USART2:
|
||||
return &RX_buffer[1];
|
||||
break;
|
||||
default: // error - return
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}*/
|
||||
|
||||
|
||||
/**
|
||||
* Check whether UART2 have a full text line
|
||||
* @return string with data if data ready or NULL
|
||||
*/
|
||||
uint8_t *check_UART2(){
|
||||
static int oldlen = 0;
|
||||
static uint8_t buf[UART_BUF_DATA_SIZE+1];
|
||||
UART_buff *curbuff = &RX_buffer[1];
|
||||
uint8_t datalen = curbuff->end; // length of data in buffer - here we use param "end"
|
||||
if(!datalen) return NULL; // buffer is empty
|
||||
if(oldlen != datalen){
|
||||
if(curbuff->buf[curbuff->end-1] != '\n'){ // string not full
|
||||
oldlen = datalen;
|
||||
return NULL;
|
||||
}else{ // full string - copy it to buffer & clear indexes
|
||||
memcpy(buf, curbuff->buf, datalen);
|
||||
buf[datalen] = 0;
|
||||
oldlen = curbuff->end = 0;
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill data in RX buffer to prepare it for further work
|
||||
* we don't use "start" parameter here, it's 0 always
|
||||
* @param UART - device to fill buffer
|
||||
* @param byte - data byte
|
||||
*/
|
||||
void fill_uart_RXbuff(uint32_t UART, uint8_t byte){
|
||||
UART_buff *curbuff;
|
||||
uint8_t bufidx;
|
||||
switch(UART){
|
||||
case USART1:
|
||||
bufidx = 0;
|
||||
break;
|
||||
case USART2:
|
||||
bufidx = 1;
|
||||
break;
|
||||
default: // error - return
|
||||
return;
|
||||
}
|
||||
curbuff = &RX_buffer[bufidx];
|
||||
if(curbuff->end == UART_BUF_DATA_SIZE){ // end of buffer - forget about data
|
||||
curbuff->end = 0;
|
||||
return;
|
||||
}
|
||||
curbuff->buf[curbuff->end++] = byte; // put byte into buffer
|
||||
}
|
||||
46
GPS+ultrasonic/uart.h
Normal file
46
GPS+ultrasonic/uart.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* uart.h
|
||||
*
|
||||
* Copyright 2014 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 __UART_H__
|
||||
#define __UART_H__
|
||||
|
||||
// Size of buffers
|
||||
#define UART_BUF_DATA_SIZE 128
|
||||
|
||||
typedef struct {
|
||||
uint8_t buf[UART_BUF_DATA_SIZE];
|
||||
uint8_t start; // index from where to start reading
|
||||
uint8_t end; // index from where to start writing
|
||||
} UART_buff;
|
||||
|
||||
void UART_init(uint32_t UART);
|
||||
void UART_setspeed(uint32_t UART);
|
||||
|
||||
void fill_uart_buff(uint32_t UART, uint8_t byte);
|
||||
void uart1_send(uint8_t byte);
|
||||
void uart2_send(uint8_t byte);
|
||||
|
||||
uint8_t *check_UART2();
|
||||
|
||||
UART_buff *get_uart_buffer(uint32_t UART);
|
||||
|
||||
#endif // __UART_H__
|
||||
199
GPS+ultrasonic/ultrasonic.c
Normal file
199
GPS+ultrasonic/ultrasonic.c
Normal file
@ -0,0 +1,199 @@
|
||||
/*
|
||||
* ultrasonic.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 <libopencm3/stm32/timer.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
|
||||
#include "ultrasonic.h"
|
||||
#include "user_proto.h"
|
||||
#include "main.h"
|
||||
|
||||
static usmode US_mode = US_MODE_OFF;
|
||||
static int overcapture = 0;
|
||||
|
||||
#ifndef TIM_CCMR2_CC3S_IN_TI4
|
||||
#define TIM_CCMR2_CC3S_IN_TI4 (2)
|
||||
#endif
|
||||
#ifndef TIM_CCMR2_CC4S_IN_TI4
|
||||
#define TIM_CCMR2_CC4S_IN_TI4 (1 << 8)
|
||||
#endif
|
||||
/**
|
||||
* Init timer 2 (&remap channels 3&4 to five-tolerant ports)
|
||||
*/
|
||||
void tim2_init(){
|
||||
// Turn off JTAG & SWD, remap TIM2_CH3/TIM2_CH4 to PB10/PB11 (five tolerant)
|
||||
// don't forget about AFIO clock & PB clock!
|
||||
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPBEN);
|
||||
gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF, AFIO_MAPR_TIM2_REMAP_PARTIAL_REMAP2);
|
||||
// setup PB10 & PB11
|
||||
// PB10 - Trig output - push/pull
|
||||
gpio_set_mode(GPIO_BANK_TIM2_PR2_CH3, GPIO_MODE_OUTPUT_10_MHZ,
|
||||
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_TIM2_PR2_CH3);
|
||||
// gpio_set_mode(GPIO_BANK_TIM2_CH3, GPIO_MODE_OUTPUT_10_MHZ,
|
||||
// GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_TIM2_CH3);
|
||||
// PB11 - Echo input - floating
|
||||
// gpio_set_mode(GPIO_BANK_TIM2_PR2_CH4, GPIO_MODE_INPUT,
|
||||
// GPIO_CNF_INPUT_FLOAT, GPIO_TIM2_PR2_CH4);
|
||||
rcc_periph_clock_enable(RCC_TIM2);
|
||||
timer_reset(TIM2);
|
||||
// timers have frequency of 1MHz -- 1us for one step
|
||||
// 36MHz of APB1
|
||||
timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
|
||||
// 72MHz div 72 = 1MHz
|
||||
TIM2_PSC = 71; // prescaler is (div - 1)
|
||||
TIM2_ARR = TRIG_T;
|
||||
TIM2_CCR3 = TRIG_L;
|
||||
// DBG("Timer configured\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send Trig signal
|
||||
* return 0 if another measurement still in process
|
||||
*/
|
||||
void start_ultrasonic(){
|
||||
overcapture = 0;
|
||||
TIM2_CR1 = 0;
|
||||
//TIM2_CR1 = TIM_CR1_URS; // Turn off timer to reconfigure, dusable UEV by UG set
|
||||
TIM2_CCER = 0;
|
||||
TIM2_CCMR2 = 0;
|
||||
TIM2_DIER = 0;
|
||||
TIM2_SR = 0; // clear all flags
|
||||
TIM2_ARR = TRIG_T;
|
||||
TIM2_CCR3 = TRIG_L;
|
||||
// PWM_OUT for TIM2_CH3
|
||||
TIM2_CCMR2 = TIM_CCMR2_CC3S_OUT | TIM_CCMR2_OC3M_PWM1;
|
||||
// start measurement, active is high
|
||||
TIM2_CCER = TIM_CCER_CC3E;
|
||||
// enable CC3 IRQ
|
||||
TIM2_DIER = TIM_DIER_CC3IE;
|
||||
nvic_enable_irq(NVIC_TIM2_IRQ);
|
||||
US_mode = US_MODE_TRIG;
|
||||
// start timer in one-pulse mode without update event
|
||||
TIM2_CR1 = TIM_CR1_OPM | TIM_CR1_CEN | TIM_CR1_UDIS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start measurement:
|
||||
* TIM2_CH3 will capture high level & TIM2_CH4 will capture low
|
||||
* The timer configured to 65536us to detect signal lost
|
||||
*/
|
||||
inline void run_measrmnt(){
|
||||
US_mode = US_MODE_WAIT;
|
||||
TIM2_CR1 = 0; // Turn off timer to reconfigure
|
||||
TIM2_DIER = 0;
|
||||
TIM2_CCER = 0;
|
||||
TIM2_CCMR2 = 0;
|
||||
//DBG("triggered\n");
|
||||
TIM2_SR = 0; // clear all flags
|
||||
TIM2_ARR = MAX_MSRMNT_LEN;
|
||||
// TIM2_CH3 & TIM2_CH4 configured as inputs, TIM2_CH3 connected to CH4
|
||||
TIM2_CCMR2 = TIM_CCMR2_CC3S_IN_TI4 | TIM_CCMR2_CC4S_IN_TI4;
|
||||
// start
|
||||
TIM2_CCER = TIM_CCER_CC4P | TIM_CCER_CC4E | TIM_CCER_CC3E;
|
||||
// enable interrupts CH3, CH4 & update
|
||||
TIM2_DIER = TIM_DIER_CC3IE | TIM_DIER_CC4IE | TIM_DIER_UIE;
|
||||
// start timer in one-pulse mode
|
||||
TIM2_CR1 = TIM_CR1_OPM | TIM_CR1_CEN;
|
||||
}
|
||||
|
||||
void tim2_isr(){
|
||||
// No signal
|
||||
if(TIM2_SR & TIM_SR_UIF){ // update interrupt
|
||||
TIM2_SR = 0;
|
||||
overcapture = 1;
|
||||
nvic_disable_irq(NVIC_TIM2_IRQ);
|
||||
TIM2_DIER = 0;
|
||||
US_mode = US_MODE_READY;
|
||||
//DBG("overcaptured\n");
|
||||
}
|
||||
// end of Trig pulse or start of measurements
|
||||
if(TIM2_SR & TIM_SR_CC3IF){ // CCR ch3 interrupt
|
||||
if(US_mode == US_MODE_TRIG){ // triggered - run measurement
|
||||
run_measrmnt();
|
||||
}else if(US_mode == US_MODE_WAIT){
|
||||
US_mode = US_MODE_MEASUREMENT;
|
||||
}
|
||||
TIM2_SR &= ~TIM_SR_CC3IF;
|
||||
}
|
||||
if(TIM2_SR & TIM_SR_CC4IF){
|
||||
if(US_mode == US_MODE_MEASUREMENT){
|
||||
US_mode = US_MODE_READY;
|
||||
nvic_disable_irq(NVIC_TIM2_IRQ);
|
||||
TIM2_DIER = 0;
|
||||
TIM2_CR1 = 0; // turn off timer - we don't need it more
|
||||
}
|
||||
TIM2_SR &= ~TIM_SR_CC3IF;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Measure distance
|
||||
* return 1 if measurements done
|
||||
* set L to distance (in mm) or 0 in case of overcapture (no signal)
|
||||
*/
|
||||
int ultrasonic_get(uint32_t *L){
|
||||
uint32_t D;
|
||||
if(US_mode != US_MODE_READY)
|
||||
return 0;
|
||||
US_mode = US_MODE_DONE;
|
||||
if(!overcapture){
|
||||
D = ((uint32_t)(TIM2_CCR4 - TIM2_CCR3)) * 170;
|
||||
*L = D / 1000;
|
||||
}else *L = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t last_us_val = 0;
|
||||
void poll_ultrasonic(){
|
||||
uint32_t L;
|
||||
if(US_mode == US_MODE_OFF){
|
||||
start_ultrasonic();
|
||||
return;
|
||||
}//else if(ultrasonic_ms != DIDNT_TRIGGERED) return;
|
||||
if(ultrasonic_get(&L)){ // measurements done, check event
|
||||
if(!overcapture){
|
||||
if(!last_us_val){
|
||||
last_us_val = L;
|
||||
}else{
|
||||
uint32_t diff = (last_us_val > L) ? last_us_val - L : L - last_us_val;
|
||||
if(diff > MAX_LEN_DIFF){
|
||||
if(last_us_val > L){ // someone move in front of sensor
|
||||
ultrasonic_ms = Timer;
|
||||
memcpy(&ultrasonic_time, ¤t_time, sizeof(curtime));
|
||||
P("Pass! Was: ");
|
||||
print_int(last_us_val);
|
||||
P(", become: ");
|
||||
print_int(L);
|
||||
P("!!!\n");
|
||||
}else{ // free space - check for noices (signal should be at least 10ms)
|
||||
diff = (ultrasonic_ms < Timer) ? Timer - ultrasonic_ms : ultrasonic_ms - Timer;
|
||||
if(diff < ULTRASONIC_TIMEOUT)
|
||||
ultrasonic_ms = DIDNT_TRIGGERED;
|
||||
}
|
||||
last_us_val = L;
|
||||
}
|
||||
}
|
||||
}
|
||||
start_ultrasonic();
|
||||
}
|
||||
}
|
||||
53
GPS+ultrasonic/ultrasonic.h
Normal file
53
GPS+ultrasonic/ultrasonic.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* ultrasonic.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 __ULTRASONIC_H__
|
||||
#define __ULTRASONIC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void tim2_init();
|
||||
int ultrasonic_get(uint32_t *L);
|
||||
void poll_ultrasonic();
|
||||
extern uint32_t last_us_val;
|
||||
|
||||
// Sensor mode
|
||||
typedef enum{
|
||||
US_MODE_OFF // sensor is off
|
||||
,US_MODE_DONE // measurement done, ready for next
|
||||
,US_MODE_TRIG // sensor triggered
|
||||
,US_MODE_WAIT // wait for pulse
|
||||
,US_MODE_MEASUREMENT // measurement in process
|
||||
,US_MODE_READY // measurements done
|
||||
} usmode;
|
||||
|
||||
// trigger time: after trigger event ends, timer will be configured for capture - 20us
|
||||
#define TRIG_T (200)
|
||||
// trigger length - 10us
|
||||
#define TRIG_L (10)
|
||||
// max length of measurement (to detect signal absence)
|
||||
#define MAX_MSRMNT_LEN (65535)
|
||||
// max difference of measured len for pass detection
|
||||
#define MAX_LEN_DIFF (300)
|
||||
// minimal length of signal in ms
|
||||
#define ULTRASONIC_TIMEOUT (10)
|
||||
#endif // __ULTRASONIC_H__
|
||||
221
GPS+ultrasonic/user_proto.c
Normal file
221
GPS+ultrasonic/user_proto.c
Normal file
@ -0,0 +1,221 @@
|
||||
/*
|
||||
* user_proto.c
|
||||
*
|
||||
* Copyright 2014 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 "cdcacm.h"
|
||||
#include "main.h"
|
||||
#include "hardware_ini.h"
|
||||
#include "GPS.h"
|
||||
#include "ultrasonic.h"
|
||||
#include "adc.h"
|
||||
|
||||
// integer value given by user
|
||||
static volatile int32_t User_value = 0;
|
||||
enum{
|
||||
UVAL_START, // user start to write integer value
|
||||
UVAL_ENTERED, // value entered but not printed
|
||||
UVAL_BAD // entered bad value
|
||||
};
|
||||
uint8_t Uval_ready = UVAL_BAD;
|
||||
|
||||
int read_int(char *buf, int cnt);
|
||||
|
||||
intfun I = NULL; // function to process entered integer
|
||||
|
||||
#define READINT() do{i += read_int(&buf[i+1], len-i-1);}while(0)
|
||||
|
||||
void help(){
|
||||
P("A\tshow ADC values\n");
|
||||
P("C\tclear SysTick on PPS\n");
|
||||
P("H\tshow this help\n");
|
||||
P("I\tInit ADC sensors\n");
|
||||
P("S\tSend GPS starting sequence\n");
|
||||
P("T\tshow current approx. time\n");
|
||||
P("U\tshow last measured distance by US\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* show entered integer value
|
||||
*/
|
||||
uint8_t show_int(int32_t v){
|
||||
newline();
|
||||
print_int(v);
|
||||
newline();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* parce command buffer buf with length len
|
||||
* return 0 if buffer processed or len if there's not enough data in buffer
|
||||
*/
|
||||
int parce_incoming_buf(char *buf, int len){
|
||||
uint8_t command;
|
||||
//uint32_t utmp;
|
||||
int i = 0, j;
|
||||
if(Uval_ready == UVAL_START){ // we are in process of user's value reading
|
||||
i += read_int(buf, len);
|
||||
}
|
||||
if(Uval_ready == UVAL_ENTERED){
|
||||
//print_int(User_value); // printout readed integer value for error control
|
||||
Uval_ready = UVAL_BAD; // clear Uval
|
||||
I(User_value);
|
||||
return 0;
|
||||
}
|
||||
for(; i < len; i++){
|
||||
command = buf[i];
|
||||
if(!command) continue; // omit zero
|
||||
switch (command){
|
||||
case 'A':
|
||||
for(j=0; j<ADC_CHANNEL_NUMBER; ++j){
|
||||
P("ADC");
|
||||
usb_send('0'+j);
|
||||
P(" val = ");
|
||||
print_int(ADC_value[j]);
|
||||
newline();
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
clear_ST_on_connect = 1;
|
||||
break;
|
||||
case 'H': // show help
|
||||
help();
|
||||
break;
|
||||
case 'I': // enter integer & show its value
|
||||
init_adc_sensor();
|
||||
break;
|
||||
case 'S':
|
||||
GPS_send_start_seq();
|
||||
break;
|
||||
case 'T':
|
||||
print_curtime();
|
||||
break;
|
||||
case 'U':
|
||||
P("Ultra: ");
|
||||
print_int(last_us_val);
|
||||
newline();
|
||||
break;
|
||||
case '\n': // show newline, space and tab as is
|
||||
case '\r':
|
||||
case ' ':
|
||||
case '\t':
|
||||
break;
|
||||
default:
|
||||
command = '?'; // echo '?' on unknown command in byte mode
|
||||
}
|
||||
usb_send(command); // echo readed byte
|
||||
}
|
||||
return 0; // all data processed - 0 bytes leave in buffer
|
||||
}
|
||||
|
||||
/**
|
||||
* Send char array wrd thru USB or UART
|
||||
*/
|
||||
void prnt(uint8_t *wrd){
|
||||
if(!wrd) return;
|
||||
while(*wrd) usb_send(*wrd++);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from TTY integer value given by user (in DEC).
|
||||
* Reading stops on first non-numeric symbol.
|
||||
* To work with symbol terminals reading don't stops on buffer's end,
|
||||
* it waits for first non-numeric char.
|
||||
* When working on string terminals, terminate string by '\n', 0 or any other symbol
|
||||
* @param buf - buffer to read from
|
||||
* @param cnt - buffer length
|
||||
* @return amount of readed symbols
|
||||
*/
|
||||
int read_int(char *buf, int cnt){
|
||||
int readed = 0, i;
|
||||
static int enteredDigits; // amount of entered digits
|
||||
static int sign; // sign of readed value
|
||||
if(Uval_ready){ // this is first run
|
||||
Uval_ready = UVAL_START; // clear flag
|
||||
enteredDigits = 0; // 0 digits entered
|
||||
User_value = 0; // clear value
|
||||
sign = 1; // clear sign
|
||||
}
|
||||
if(!cnt) return 0;
|
||||
for(i = 0; i < cnt; i++, readed++){
|
||||
uint8_t chr = buf[i];
|
||||
if(chr == '-'){
|
||||
if(enteredDigits == 0){ // sign should be first
|
||||
sign = -1;
|
||||
continue;
|
||||
}else{ // '-' after number - reject entered value
|
||||
Uval_ready = UVAL_BAD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(chr < '0' || chr > '9'){
|
||||
if(enteredDigits)
|
||||
Uval_ready = UVAL_ENTERED;
|
||||
else
|
||||
Uval_ready = UVAL_BAD; // bad symbol
|
||||
break;
|
||||
}
|
||||
User_value = User_value * 10 + (int32_t)(chr - '0');
|
||||
enteredDigits++;
|
||||
}
|
||||
if(Uval_ready == UVAL_ENTERED) // reading has met an non-numeric character
|
||||
User_value *= sign;
|
||||
return readed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print buff as hex values
|
||||
* @param buf - buffer to print
|
||||
* @param l - buf length
|
||||
* @param s - function to send a byte
|
||||
*/
|
||||
void print_hex(uint8_t *buff, uint8_t l){
|
||||
void putc(uint8_t c){
|
||||
if(c < 10)
|
||||
usb_send(c + '0');
|
||||
else
|
||||
usb_send(c + 'a' - 10);
|
||||
}
|
||||
usb_send('0'); usb_send('x'); // prefix 0x
|
||||
while(l--){
|
||||
putc(buff[l] >> 4);
|
||||
putc(buff[l] & 0x0f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print decimal integer value
|
||||
* @param N - value to print
|
||||
* @param s - function to send a byte
|
||||
*/
|
||||
void print_int(int32_t N){
|
||||
uint8_t buf[10], L = 0;
|
||||
if(N < 0){
|
||||
usb_send('-');
|
||||
N = -N;
|
||||
}
|
||||
if(N){
|
||||
while(N){
|
||||
buf[L++] = N % 10 + '0';
|
||||
N /= 10;
|
||||
}
|
||||
while(L--) usb_send(buf[L]);
|
||||
}else usb_send('0');
|
||||
}
|
||||
|
||||
47
GPS+ultrasonic/user_proto.h
Normal file
47
GPS+ultrasonic/user_proto.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* user_proto.h
|
||||
*
|
||||
* Copyright 2014 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 __USER_PROTO_H__
|
||||
#define __USER_PROTO_H__
|
||||
|
||||
#include "cdcacm.h"
|
||||
|
||||
// shorthand for prnt
|
||||
#define P(arg) do{prnt((uint8_t*)arg);}while(0)
|
||||
// debug message - over USB
|
||||
#ifdef EBUG
|
||||
#define DBG(a) do{prnt((uint8_t*)a);}while(0)
|
||||
#else
|
||||
#define DBG(a)
|
||||
#endif
|
||||
|
||||
typedef uint8_t (*intfun)(int32_t);
|
||||
|
||||
void prnt(uint8_t *wrd);
|
||||
#define newline() usb_send('\n')
|
||||
|
||||
void print_int(int32_t N);
|
||||
void print_hex(uint8_t *buff, uint8_t l);
|
||||
|
||||
int parce_incoming_buf(char *buf, int len);
|
||||
|
||||
#endif // __USER_PROTO_H__
|
||||
133
ultrasonic/Makefile
Normal file
133
ultrasonic/Makefile
Normal file
@ -0,0 +1,133 @@
|
||||
BINARY = ultrasonic
|
||||
BOOTPORT ?= /dev/ttyUSB0
|
||||
BOOTSPEED ?= 115200
|
||||
# change this linking script depending on particular MCU model,
|
||||
# for example, if you have STM32F103VBT6, you should write:
|
||||
LDSCRIPT = ld/stm32f103x8.ld
|
||||
LIBNAME = opencm3_stm32f1
|
||||
DEFS = -DSTM32F1 -DEBUG
|
||||
|
||||
OBJDIR = mk
|
||||
INDEPENDENT_HEADERS=
|
||||
|
||||
FP_FLAGS ?= -msoft-float
|
||||
ARCH_FLAGS = -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd
|
||||
|
||||
###############################################################################
|
||||
# Executables
|
||||
PREFIX ?= arm-none-eabi
|
||||
|
||||
RM := rm -f
|
||||
RMDIR := rmdir
|
||||
CC := $(PREFIX)-gcc
|
||||
LD := $(PREFIX)-gcc
|
||||
AR := $(PREFIX)-ar
|
||||
AS := $(PREFIX)-as
|
||||
OBJCOPY := $(PREFIX)-objcopy
|
||||
OBJDUMP := $(PREFIX)-objdump
|
||||
GDB := $(PREFIX)-gdb
|
||||
STFLASH = $(shell which st-flash)
|
||||
STBOOT = $(shell which stm32flash)
|
||||
|
||||
###############################################################################
|
||||
# Source files
|
||||
LDSCRIPT ?= $(BINARY).ld
|
||||
SRC = $(wildcard *.c)
|
||||
OBJS = $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o))
|
||||
|
||||
ifeq ($(strip $(OPENCM3_DIR)),)
|
||||
OPENCM3_DIR := /usr/local/arm-none-eabi
|
||||
$(info Using $(OPENCM3_DIR) path to library)
|
||||
endif
|
||||
|
||||
INCLUDE_DIR = $(OPENCM3_DIR)/include
|
||||
LIB_DIR = $(OPENCM3_DIR)/lib
|
||||
SCRIPT_DIR = $(OPENCM3_DIR)/scripts
|
||||
|
||||
###############################################################################
|
||||
# C flags
|
||||
CFLAGS += -Os -g
|
||||
CFLAGS += -Wall -Wextra -Wshadow -Wimplicit-function-declaration
|
||||
CFLAGS += -Wredundant-decls
|
||||
# -Wmissing-prototypes -Wstrict-prototypes
|
||||
CFLAGS += -fno-common -ffunction-sections -fdata-sections
|
||||
|
||||
###############################################################################
|
||||
# C & C++ preprocessor common flags
|
||||
CPPFLAGS += -MD
|
||||
CPPFLAGS += -Wall -Werror
|
||||
CPPFLAGS += -I$(INCLUDE_DIR) $(DEFS)
|
||||
|
||||
###############################################################################
|
||||
# Linker flags
|
||||
LDFLAGS += --static -nostartfiles
|
||||
LDFLAGS += -L$(LIB_DIR)
|
||||
LDFLAGS += -T$(LDSCRIPT)
|
||||
LDFLAGS += -Wl,-Map=$(*).map
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
|
||||
###############################################################################
|
||||
# Used libraries
|
||||
LDLIBS += -l$(LIBNAME)
|
||||
LDLIBS += -Wl,--start-group -lc -lgcc -Wl,--end-group
|
||||
|
||||
.SUFFIXES: .elf .bin .hex .srec .list .map .images
|
||||
.SECONDEXPANSION:
|
||||
.SECONDARY:
|
||||
|
||||
ELF := $(OBJDIR)/$(BINARY).elf
|
||||
LIST := $(OBJDIR)/$(BINARY).list
|
||||
BIN := $(BINARY).bin
|
||||
HEX := $(BINARY).hex
|
||||
|
||||
all: bin
|
||||
|
||||
elf: $(ELF)
|
||||
bin: $(BIN)
|
||||
hex: $(HEX)
|
||||
list: $(LIST)
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir $(OBJDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@printf " CC $<\n"
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $@ -c $<
|
||||
|
||||
$(SRC) : %.c : %.h $(INDEPENDENT_HEADERS)
|
||||
@touch $@
|
||||
|
||||
%.h: ;
|
||||
|
||||
$(BIN): $(ELF)
|
||||
@printf " OBJCOPY $(BIN)\n"
|
||||
$(OBJCOPY) -Obinary $(ELF) $(BIN)
|
||||
|
||||
$(HEX): $(ELF)
|
||||
@printf " OBJCOPY $(HEX)\n"
|
||||
$(OBJCOPY) -Oihex $(ELF) $(HEX)
|
||||
|
||||
$(LIST): $(ELF)
|
||||
@printf " OBJDUMP $(LIST)\n"
|
||||
$(OBJDUMP) -S $(ELF) > $(LIST)
|
||||
|
||||
$(ELF): $(OBJDIR) $(OBJS) $(LDSCRIPT) $(LIB_DIR)/lib$(LIBNAME).a
|
||||
@printf " LD $(ELF)\n"
|
||||
$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
|
||||
|
||||
clean:
|
||||
@printf " CLEAN\n"
|
||||
$(RM) $(OBJS) $(OBJDIR)/*.d $(ELF) $(HEX) $(LIST) $(OBJDIR)/*.map
|
||||
$(RMDIR) $(OBJDIR)
|
||||
|
||||
flash: $(BIN)
|
||||
@printf " FLASH $(BIN)\n"
|
||||
$(STFLASH) write $(BIN) 0x8000000
|
||||
|
||||
boot: $(BIN)
|
||||
@printf " LOAD $(BIN) through bootloader\n"
|
||||
$(STBOOT) -b$(BOOTSPEED) $(BOOTPORT) -w $(BIN)
|
||||
|
||||
.PHONY: clean elf hex list flash boot
|
||||
|
||||
#-include $(OBJS:.o=.d)
|
||||
6
ultrasonic/Readme.md
Normal file
6
ultrasonic/Readme.md
Normal file
@ -0,0 +1,6 @@
|
||||
### Distance meter based on ultrasonic sensor HC-SR04 & Sharp 2Y0A02 IR sensor
|
||||
|
||||
The same on STM8: [livejournal](http://eddy-em.livejournal.com/66122.html) (on russian), [github](https://sourceforge.net/p/stm8samples/code/ci/default/tree/distance_meter/).
|
||||
|
||||
Allow not only to measure distance by ultrasonic distance-meter but also check transits
|
||||
(Sharp sensor works at analog watchdog)
|
||||
314
ultrasonic/cdcacm.c
Normal file
314
ultrasonic/cdcacm.c
Normal file
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
* Copyright 2014 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cdcacm.h"
|
||||
#include "user_proto.h"
|
||||
#include "main.h"
|
||||
|
||||
// Buffer for USB Tx
|
||||
static uint8_t USB_Tx_Buffer[USB_TX_DATA_SIZE];
|
||||
static uint8_t USB_Tx_ptr = 0;
|
||||
// connection flag
|
||||
uint8_t USB_connected = 0;
|
||||
static const struct usb_device_descriptor dev = {
|
||||
.bLength = USB_DT_DEVICE_SIZE,
|
||||
.bDescriptorType = USB_DT_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
.bDeviceClass = USB_CLASS_CDC,
|
||||
.bDeviceSubClass = 0,
|
||||
.bDeviceProtocol = 0,
|
||||
.bMaxPacketSize0 = 64,
|
||||
.idVendor = 0x0483,
|
||||
.idProduct = 0x5740,
|
||||
.bcdDevice = 0x0200,
|
||||
.iManufacturer = 1,
|
||||
.iProduct = 2,
|
||||
.iSerialNumber = 3,
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
char usbdatabuf[USB_RX_DATA_SIZE]; // buffer for received data
|
||||
int usbdatalen = 0; // lenght of received data
|
||||
|
||||
/*
|
||||
* This notification endpoint isn't implemented. According to CDC spec its
|
||||
* optional, but its absence causes a NULL pointer dereference in Linux
|
||||
* cdc_acm driver.
|
||||
*/
|
||||
static const struct usb_endpoint_descriptor comm_endp[] = {{
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x83,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
|
||||
.wMaxPacketSize = 16,
|
||||
.bInterval = 255,
|
||||
}};
|
||||
|
||||
static const struct usb_endpoint_descriptor data_endp[] = {{
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x01,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 1,
|
||||
}, {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = 0x82,
|
||||
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
|
||||
.wMaxPacketSize = 64,
|
||||
.bInterval = 1,
|
||||
}};
|
||||
|
||||
static const struct {
|
||||
struct usb_cdc_header_descriptor header;
|
||||
struct usb_cdc_call_management_descriptor call_mgmt;
|
||||
struct usb_cdc_acm_descriptor acm;
|
||||
struct usb_cdc_union_descriptor cdc_union;
|
||||
} __attribute__((packed)) cdcacm_functional_descriptors = {
|
||||
.header = {
|
||||
.bFunctionLength = sizeof(struct usb_cdc_header_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_HEADER,
|
||||
.bcdCDC = 0x0110,
|
||||
},
|
||||
.call_mgmt = {
|
||||
.bFunctionLength =
|
||||
sizeof(struct usb_cdc_call_management_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
|
||||
.bmCapabilities = 0,
|
||||
.bDataInterface = 1,
|
||||
},
|
||||
.acm = {
|
||||
.bFunctionLength = sizeof(struct usb_cdc_acm_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_ACM,
|
||||
.bmCapabilities = 0,
|
||||
},
|
||||
.cdc_union = {
|
||||
.bFunctionLength = sizeof(struct usb_cdc_union_descriptor),
|
||||
.bDescriptorType = CS_INTERFACE,
|
||||
.bDescriptorSubtype = USB_CDC_TYPE_UNION,
|
||||
.bControlInterface = 0,
|
||||
.bSubordinateInterface0 = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct usb_interface_descriptor comm_iface[] = {{
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 1,
|
||||
.bInterfaceClass = USB_CLASS_CDC,
|
||||
.bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
|
||||
.bInterfaceProtocol = USB_CDC_PROTOCOL_AT,
|
||||
.iInterface = 0,
|
||||
|
||||
.endpoint = comm_endp,
|
||||
|
||||
.extra = &cdcacm_functional_descriptors,
|
||||
.extralen = sizeof(cdcacm_functional_descriptors),
|
||||
}};
|
||||
|
||||
static const struct usb_interface_descriptor data_iface[] = {{
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 1,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 2,
|
||||
.bInterfaceClass = USB_CLASS_DATA,
|
||||
.bInterfaceSubClass = 0,
|
||||
.bInterfaceProtocol = 0,
|
||||
.iInterface = 0,
|
||||
|
||||
.endpoint = data_endp,
|
||||
}};
|
||||
|
||||
static const struct usb_interface ifaces[] = {{
|
||||
.num_altsetting = 1,
|
||||
.altsetting = comm_iface,
|
||||
}, {
|
||||
.num_altsetting = 1,
|
||||
.altsetting = data_iface,
|
||||
}};
|
||||
|
||||
static const struct usb_config_descriptor config = {
|
||||
.bLength = USB_DT_CONFIGURATION_SIZE,
|
||||
.bDescriptorType = USB_DT_CONFIGURATION,
|
||||
.wTotalLength = 0,
|
||||
.bNumInterfaces = 2,
|
||||
.bConfigurationValue = 1,
|
||||
.iConfiguration = 0,
|
||||
.bmAttributes = 0x80,
|
||||
.bMaxPower = 0x32,
|
||||
|
||||
.interface = ifaces,
|
||||
};
|
||||
|
||||
static const char *usb_strings[] = {
|
||||
"Organisation, author",
|
||||
"device",
|
||||
"version",
|
||||
};
|
||||
|
||||
// default line coding: B115200, 1stop, 8bits, parity none
|
||||
struct usb_cdc_line_coding linecoding = {
|
||||
.dwDTERate = 115200,
|
||||
.bCharFormat = USB_CDC_1_STOP_BITS,
|
||||
.bParityType = USB_CDC_NO_PARITY,
|
||||
.bDataBits = 8,
|
||||
};
|
||||
|
||||
/* Buffer to be used for control requests. */
|
||||
uint8_t usbd_control_buffer[128];
|
||||
|
||||
/**
|
||||
* This function runs every time it gets a request for control parameters get/set
|
||||
* parameter SET_LINE_CODING used to change USART1 parameters: if you want to
|
||||
* change them, just connect through USB with required parameters
|
||||
*/
|
||||
static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf,
|
||||
uint16_t *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req)){
|
||||
(void)complete;
|
||||
(void)buf;
|
||||
(void)usbd_dev;
|
||||
char local_buf[10];
|
||||
struct usb_cdc_line_coding lc;
|
||||
|
||||
switch (req->bRequest) {
|
||||
case SET_CONTROL_LINE_STATE:{
|
||||
if(req->wValue){ // terminal is opened
|
||||
USB_connected = 1;
|
||||
}else{ // terminal is closed
|
||||
USB_connected = 0;
|
||||
}
|
||||
/*
|
||||
* This Linux cdc_acm driver requires this to be implemented
|
||||
* even though it's optional in the CDC spec, and we don't
|
||||
* advertise it in the ACM functional descriptor.
|
||||
*/
|
||||
struct usb_cdc_notification *notif = (void *)local_buf;
|
||||
/* We echo signals back to host as notification. */
|
||||
notif->bmRequestType = 0xA1;
|
||||
notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE;
|
||||
notif->wValue = 0;
|
||||
notif->wIndex = 0;
|
||||
notif->wLength = 2;
|
||||
local_buf[8] = req->wValue & 3;
|
||||
local_buf[9] = 0;
|
||||
usbd_ep_write_packet(usbd_dev, 0x83, local_buf, 10);
|
||||
}break;
|
||||
case SET_LINE_CODING:
|
||||
if (!len || (*len != sizeof(struct usb_cdc_line_coding)))
|
||||
return 0;
|
||||
memcpy((void *)&lc, (void *)*buf, *len);
|
||||
// Mark & Space parity don't support by hardware, check it
|
||||
if(lc.bParityType == USB_CDC_MARK_PARITY || lc.bParityType == USB_CDC_SPACE_PARITY){
|
||||
return 0; // error
|
||||
}else{
|
||||
// memcpy((void *)&linecoding, (void *)&lc, sizeof(struct usb_cdc_line_coding));
|
||||
// UART_setspeed(USART1, &linecoding);
|
||||
}
|
||||
break;
|
||||
case GET_LINE_CODING: // return linecoding buffer
|
||||
if(len && *len == sizeof(struct usb_cdc_line_coding))
|
||||
memcpy((void *)*buf, (void *)&linecoding, sizeof(struct usb_cdc_line_coding));
|
||||
//usbd_ep_write_packet(usbd_dev, 0x83, (char*)&linecoding, sizeof(linecoding));
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep){
|
||||
(void)ep;
|
||||
int len = usbd_ep_read_packet(usbd_dev, 0x01, usbdatabuf + usbdatalen, USB_RX_DATA_SIZE - usbdatalen);
|
||||
usbdatalen += len;
|
||||
if(usbdatalen >= USB_RX_DATA_SIZE){ // buffer overflow - drop all its contents
|
||||
usbdatalen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void cdcacm_data_tx_cb(usbd_device *usbd_dev, uint8_t ep){
|
||||
(void)ep;
|
||||
(void)usbd_dev;
|
||||
|
||||
usb_send_buffer();
|
||||
}
|
||||
|
||||
static void cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue)
|
||||
{
|
||||
(void)wValue;
|
||||
(void)usbd_dev;
|
||||
|
||||
usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, USB_RX_DATA_SIZE, cdcacm_data_rx_cb);
|
||||
usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, USB_TX_DATA_SIZE, cdcacm_data_tx_cb);
|
||||
usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
|
||||
|
||||
usbd_register_control_callback(
|
||||
usbd_dev,
|
||||
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
|
||||
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
|
||||
cdcacm_control_request);
|
||||
}
|
||||
|
||||
static usbd_device *current_usb = NULL;
|
||||
|
||||
usbd_device *USB_init(){
|
||||
current_usb = usbd_init(&stm32f103_usb_driver, &dev, &config,
|
||||
usb_strings, 3, usbd_control_buffer, sizeof(usbd_control_buffer));
|
||||
if(!current_usb) return NULL;
|
||||
usbd_register_set_config_callback(current_usb, cdcacm_set_config);
|
||||
return current_usb;
|
||||
}
|
||||
|
||||
mutex_t send_block_mutex = MUTEX_UNLOCKED;
|
||||
/**
|
||||
* Put byte into USB buffer to send
|
||||
* @param byte - a byte to put into a buffer
|
||||
*/
|
||||
void usb_send(uint8_t byte){
|
||||
mutex_lock(&send_block_mutex);
|
||||
USB_Tx_Buffer[USB_Tx_ptr++] = byte;
|
||||
mutex_unlock(&send_block_mutex);
|
||||
if(USB_Tx_ptr == USB_TX_DATA_SIZE){ // buffer can be overflowed - send it!
|
||||
usb_send_buffer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send all data in buffer over USB
|
||||
* this function runs when buffer is full or on SysTick
|
||||
*/
|
||||
void usb_send_buffer(){
|
||||
if(MUTEX_LOCKED == mutex_trylock(&send_block_mutex)) return;
|
||||
if(USB_Tx_ptr){
|
||||
if(current_usb && USB_connected){
|
||||
// usbd_ep_write_packet return 0 if previous packet isn't transmit yet
|
||||
while(USB_Tx_ptr != usbd_ep_write_packet(current_usb, 0x82, USB_Tx_Buffer, USB_Tx_ptr));
|
||||
usbd_poll(current_usb);
|
||||
}
|
||||
USB_Tx_ptr = 0;
|
||||
}
|
||||
mutex_unlock(&send_block_mutex);
|
||||
}
|
||||
54
ultrasonic/cdcacm.h
Normal file
54
ultrasonic/cdcacm.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* ccdcacm.h
|
||||
*
|
||||
* Copyright 2014 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 __CCDCACM_H__
|
||||
#define __CCDCACM_H__
|
||||
|
||||
#include <libopencm3/usb/usbd.h>
|
||||
|
||||
// commands through EP0
|
||||
#define SEND_ENCAPSULATED_COMMAND 0x00
|
||||
#define GET_ENCAPSULATED_RESPONSE 0x01
|
||||
#define SET_COMM_FEATURE 0x02
|
||||
#define GET_COMM_FEATURE 0x03
|
||||
#define CLEAR_COMM_FEATURE 0x04
|
||||
#define SET_LINE_CODING 0x20
|
||||
#define GET_LINE_CODING 0x21
|
||||
#define SET_CONTROL_LINE_STATE 0x22
|
||||
#define SEND_BREAK 0x23
|
||||
|
||||
// Size of input/output buffers
|
||||
#define USB_TX_DATA_SIZE 64
|
||||
#define USB_RX_DATA_SIZE 64
|
||||
|
||||
// USB connection flag
|
||||
extern uint8_t USB_connected;
|
||||
extern struct usb_cdc_line_coding linecoding;
|
||||
|
||||
extern char usbdatabuf[];
|
||||
extern int usbdatalen;
|
||||
|
||||
usbd_device *USB_init();
|
||||
void usb_send(uint8_t byte);
|
||||
void usb_send_buffer();
|
||||
|
||||
#endif // __CCDCACM_H__
|
||||
57
ultrasonic/hardware_ini.c
Normal file
57
ultrasonic/hardware_ini.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* hardware_ini.c - functions for HW initialisation
|
||||
*
|
||||
* Copyright 2014 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* All hardware-dependent initialisation & definition should be placed here
|
||||
* and in hardware_ini.h
|
||||
*
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include "hardware_ini.h"
|
||||
|
||||
/**
|
||||
* GPIO initialisaion: clocking + pins setup
|
||||
*/
|
||||
void GPIO_init(){
|
||||
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN |
|
||||
RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN |
|
||||
RCC_APB2ENR_IOPEEN);
|
||||
/*
|
||||
// USB_DISC: push-pull
|
||||
gpio_set_mode(USB_DISC_PORT, GPIO_MODE_OUTPUT_2_MHZ,
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, USB_DISC_PIN);
|
||||
// USB_POWER: open drain, externall pull down with R7 (22k)
|
||||
gpio_set_mode(USB_POWER_PORT, GPIO_MODE_INPUT,
|
||||
GPIO_CNF_INPUT_FLOAT, USB_POWER_PIN);
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* SysTick used for system timer with period of 1ms
|
||||
*/
|
||||
void SysTick_init(){
|
||||
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); // Systyck: 72/8=9MHz
|
||||
systick_set_reload(8999); // 9000 pulses: 1kHz
|
||||
systick_interrupt_enable();
|
||||
systick_counter_enable();
|
||||
}
|
||||
|
||||
60
ultrasonic/hardware_ini.h
Normal file
60
ultrasonic/hardware_ini.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* hardware_ini.h
|
||||
*
|
||||
* Copyright 2014 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_INI_H__
|
||||
#define __HARDWARE_INI_H__
|
||||
|
||||
#include "ultrasonic.h"
|
||||
|
||||
/*
|
||||
* Timers:
|
||||
* SysTick - system time
|
||||
*/
|
||||
|
||||
|
||||
void GPIO_init();
|
||||
void SysTick_init();
|
||||
|
||||
/*
|
||||
* USB interface
|
||||
* connect boot1 jumper to gnd, boot0 to gnd; and reconnect boot0 to +3.3 to boot flash
|
||||
*/
|
||||
/*
|
||||
// USB_DICS (disconnect) - PC11
|
||||
#define USB_DISC_PIN GPIO11
|
||||
#define USB_DISC_PORT GPIOC
|
||||
// USB_POWER (high level when USB connected to PC)
|
||||
#define USB_POWER_PIN GPIO10
|
||||
#define USB_POWER_PORT GPIOC
|
||||
// change signal level on USB diconnect pin
|
||||
#define usb_disc_high() gpio_set(USB_DISC_PORT, USB_DISC_PIN)
|
||||
#define usb_disc_low() gpio_clear(USB_DISC_PORT, USB_DISC_PIN)
|
||||
// in case of n-channel FET on 1.5k pull-up change on/off disconnect means low level
|
||||
// in case of pnp bipolar transistor or p-channel FET on 1.5k pull-up disconnect means high level
|
||||
#define usb_disconnect() usb_disc_high()
|
||||
#define usb_connect() usb_disc_low()
|
||||
*/
|
||||
// my simple devboard have no variants for programmed connection/disconnection of USB
|
||||
#define usb_disconnect()
|
||||
#define usb_connect()
|
||||
|
||||
#endif // __HARDWARE_INI_H__
|
||||
9
ultrasonic/ld/devices.data
Normal file
9
ultrasonic/ld/devices.data
Normal file
@ -0,0 +1,9 @@
|
||||
stm32f103?4* stm32f1 ROM=16K RAM=6K
|
||||
stm32f103?6* stm32f1 ROM=32K RAM=10K
|
||||
stm32f103?8* stm32f1 ROM=64K RAM=20K
|
||||
stm32f103?b* stm32f1 ROM=128K RAM=20K
|
||||
stm32f103?c* stm32f1 ROM=256K RAM=48K
|
||||
stm32f103?d* stm32f1 ROM=384K RAM=64K
|
||||
stm32f103?e* stm32f1 ROM=512K RAM=64K
|
||||
stm32f103?f* stm32f1 ROM=768K RAM=96K
|
||||
stm32f103?g* stm32f1 ROM=1024K RAM=96K
|
||||
31
ultrasonic/ld/stm32f103x4.ld
Normal file
31
ultrasonic/ld/stm32f103x4.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 16K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 6K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
ultrasonic/ld/stm32f103x6.ld
Normal file
31
ultrasonic/ld/stm32f103x6.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 32K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 10K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
ultrasonic/ld/stm32f103x8.ld
Normal file
31
ultrasonic/ld/stm32f103x8.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 64K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
ultrasonic/ld/stm32f103xB.ld
Normal file
31
ultrasonic/ld/stm32f103xB.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
ultrasonic/ld/stm32f103xC.ld
Normal file
31
ultrasonic/ld/stm32f103xC.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 256K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
ultrasonic/ld/stm32f103xD.ld
Normal file
31
ultrasonic/ld/stm32f103xD.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 384K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
ultrasonic/ld/stm32f103xE.ld
Normal file
31
ultrasonic/ld/stm32f103xE.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
ultrasonic/ld/stm32f103xF.ld
Normal file
31
ultrasonic/ld/stm32f103xF.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 768K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
31
ultrasonic/ld/stm32f103xG.ld
Normal file
31
ultrasonic/ld/stm32f103xG.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||
|
||||
/* Define memory regions. */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_stm32f1.ld
|
||||
|
||||
120
ultrasonic/main.c
Normal file
120
ultrasonic/main.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* main.c
|
||||
*
|
||||
* Copyright 2014 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 "main.h"
|
||||
#include "hardware_ini.h"
|
||||
#include "cdcacm.h"
|
||||
#include "sharp.h"
|
||||
|
||||
volatile uint32_t Timer = 0; // global timer (milliseconds)
|
||||
usbd_device *usbd_dev;
|
||||
|
||||
int main(){
|
||||
uint32_t Old_timer = 0;
|
||||
|
||||
// RCC clocking: 8MHz oscillator -> 72MHz system
|
||||
rcc_clock_setup_in_hse_8mhz_out_72mhz();
|
||||
|
||||
GPIO_init();
|
||||
|
||||
usb_disconnect(); // turn off USB while initializing all
|
||||
|
||||
// USB
|
||||
usbd_dev = USB_init();
|
||||
|
||||
// SysTick is a system timer with 1ms period
|
||||
SysTick_init();
|
||||
tim2_init();
|
||||
//init_sharp_sensor();
|
||||
|
||||
// wait a little and then turn on USB pullup
|
||||
// for (i = 0; i < 0x800000; i++)
|
||||
// __asm__("nop");
|
||||
|
||||
usb_connect(); // turn on USB
|
||||
|
||||
uint32_t oldL = 0;
|
||||
while(1){
|
||||
uint32_t L;
|
||||
usbd_poll(usbd_dev);
|
||||
if(usbdatalen){ // there's something in USB buffer
|
||||
usbdatalen = parce_incoming_buf(usbdatabuf, usbdatalen);
|
||||
}
|
||||
if(AWD_flag){
|
||||
P("Int, value = ");
|
||||
print_int(AWD_value);
|
||||
P(" ADU\n");
|
||||
AWD_flag = 0;
|
||||
}
|
||||
if(ultrasonic_get(&L)){
|
||||
if(!cont){
|
||||
P("Measured length: ");
|
||||
print_int(L);
|
||||
P("mm\n");
|
||||
oldL = 0;
|
||||
}else{
|
||||
if(!oldL){
|
||||
oldL = L;
|
||||
}else{
|
||||
uint32_t diff = (oldL > L) ? oldL - L : L - oldL;
|
||||
if(diff > MAX_LEN_DIFF){
|
||||
P("Pass! Was: ");
|
||||
print_int(oldL);
|
||||
P(", become: ");
|
||||
print_int(L);
|
||||
P("!!!\n");
|
||||
oldL = L;
|
||||
}
|
||||
}
|
||||
start_ultrasonic();
|
||||
}
|
||||
}
|
||||
if(Timer - Old_timer > 999){ // one-second cycle
|
||||
Old_timer += 1000;
|
||||
}else if(Timer < Old_timer){ // Timer overflow
|
||||
Old_timer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* SysTick interrupt: increment global time & send data buffer through USB
|
||||
*/
|
||||
void sys_tick_handler(){
|
||||
Timer++;
|
||||
usbd_poll(usbd_dev);
|
||||
usb_send_buffer();
|
||||
}
|
||||
|
||||
// pause function, delay in ms
|
||||
void Delay(uint16_t _U_ time){
|
||||
uint32_t waitto = Timer + time;
|
||||
while(Timer < waitto);
|
||||
}
|
||||
|
||||
/**
|
||||
* print current time in milliseconds: 4 bytes for ovrvlow + 4 bytes for time
|
||||
* with ' ' as delimeter
|
||||
*/
|
||||
void print_time(){
|
||||
print_int(Timer);
|
||||
}
|
||||
57
ultrasonic/main.h
Normal file
57
ultrasonic/main.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* main.h
|
||||
*
|
||||
* Copyright 2014 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 __MAIN_H__
|
||||
#define __MAIN_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h> // memcpy
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/usart.h>
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/usb/cdc.h>
|
||||
#include <libopencm3/usb/usbd.h>
|
||||
#include <libopencm3/cm3/systick.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/adc.h>
|
||||
#include <libopencm3/stm32/dma.h>
|
||||
#include <libopencm3/stm32/spi.h>
|
||||
|
||||
#define ADC_CHANNELS_NUMBER (10)
|
||||
|
||||
#include "sync.h" // mutexes
|
||||
#include "user_proto.h"
|
||||
|
||||
#define _U_ __attribute__((__unused__))
|
||||
#define U8(x) ((uint8_t) x)
|
||||
#define U16(x) ((uint16_t) x)
|
||||
#define U32(x) ((uint32_t) x)
|
||||
|
||||
extern volatile uint32_t Timer; // global timer (milliseconds)
|
||||
void Delay(uint16_t time);
|
||||
|
||||
// max diff in continuous measurements - 100mm
|
||||
#define MAX_LEN_DIFF (100)
|
||||
|
||||
#endif // __MAIN_H__
|
||||
|
||||
72
ultrasonic/sharp.c
Normal file
72
ultrasonic/sharp.c
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* sharp.c - functions for Sharp 2Y0A02 distance meter
|
||||
*
|
||||
* 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 "sharp.h"
|
||||
#include "main.h"
|
||||
|
||||
int AWD_flag = 0;
|
||||
uint16_t AWD_value = 0;
|
||||
|
||||
void init_sharp_sensor(){
|
||||
// Make sure the ADC doesn't run during config
|
||||
adc_off(ADC1);
|
||||
// enable ADC & PA0 clocking
|
||||
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN | RCC_APB2ENR_IOPAEN);
|
||||
rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV4);
|
||||
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO0);
|
||||
// set sample time: 239.5 cycles for better results
|
||||
ADC1_SMPR2 = 7;
|
||||
// continuous conv, enable
|
||||
ADC1_CR2 = ADC_CR2_CONT | ADC_CR2_ADON;
|
||||
// reset calibration registers & start calibration
|
||||
ADC1_CR2 |= ADC_CR2_RSTCAL;
|
||||
while(ADC1_CR2 & ADC_CR2_RSTCAL); // wait for registers reset
|
||||
ADC1_CR2 |= ADC_CR2_CAL;
|
||||
while(ADC1_CR2 & ADC_CR2_CAL); // wait for calibration ends
|
||||
// set threshold limits
|
||||
ADC1_HTR = ADC_WDG_HIGH;
|
||||
ADC1_LTR = ADC_WDG_LOW;
|
||||
// enable analog watchdog on single regular channel 0 & enable interrupt
|
||||
ADC1_CR1 = ADC_CR1_AWDEN | ADC_CR1_AWDSGL | ADC_CR1_AWDIE;
|
||||
nvic_enable_irq(NVIC_ADC1_2_IRQ);
|
||||
ADC1_CR2 |= ADC_CR2_SWSTART;
|
||||
// start - to do it we need set ADC_CR2_ADON again!
|
||||
ADC1_CR2 |= ADC_CR2_ADON;
|
||||
DBG("ADC started\n");
|
||||
}
|
||||
|
||||
void adc1_2_isr(){
|
||||
AWD_value = ADC1_DR;
|
||||
if(ADC1_SR & ADC_SR_AWD){ // analog watchdog event
|
||||
AWD_flag = 1;
|
||||
// ADC1_CR1 &= ~(ADC_CR1_AWDIE | ADC_CR1_AWDEN);
|
||||
// nvic_disable_irq(NVIC_ADC1_2_IRQ);
|
||||
if(AWD_value >= ADC_WDG_HIGH){ // high threshold
|
||||
ADC1_HTR = 0x0fff; // remove high threshold, only wait for LOW
|
||||
ADC1_LTR = ADC_WDG_LOW;
|
||||
}else{
|
||||
ADC1_HTR = ADC_WDG_HIGH;
|
||||
ADC1_LTR = 0;
|
||||
}
|
||||
//ADC1_CR1 |= ADC_CR1_AWDIE;
|
||||
}
|
||||
ADC1_SR = 0;
|
||||
}
|
||||
38
ultrasonic/sharp.h
Normal file
38
ultrasonic/sharp.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* sharp.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 __SHARP_H__
|
||||
#define __SHARP_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern int AWD_flag;
|
||||
extern uint16_t AWD_value;
|
||||
|
||||
// > 2.5V - something nearest 1m
|
||||
#define ADC_WDG_HIGH ((uint16_t)3000)
|
||||
// < 0.6V - nothing in front of sensor
|
||||
#define ADC_WDG_LOW ((uint16_t)750)
|
||||
|
||||
void init_sharp_sensor();
|
||||
|
||||
#endif // __SHARP_H__
|
||||
93
ultrasonic/sync.c
Normal file
93
ultrasonic/sync.c
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* implement mutexes for other type of MCU (which doesn't have strex & ldrex)
|
||||
*/
|
||||
|
||||
#include <libopencm3/cm3/sync.h>
|
||||
|
||||
/* DMB is supported on CM0 */
|
||||
void __dmb()
|
||||
{
|
||||
__asm__ volatile ("dmb");
|
||||
}
|
||||
|
||||
/* Those are defined only on CM3 or CM4 */
|
||||
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
|
||||
uint32_t __ldrex(volatile uint32_t *addr)
|
||||
{
|
||||
uint32_t res;
|
||||
__asm__ volatile ("ldrex %0, [%1]" : "=r" (res) : "r" (addr));
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t __strex(uint32_t val, volatile uint32_t *addr)
|
||||
{
|
||||
uint32_t res;
|
||||
__asm__ volatile ("strex %0, %2, [%1]"
|
||||
: "=&r" (res) : "r" (addr), "r" (val));
|
||||
return res;
|
||||
}
|
||||
|
||||
void mutex_lock(mutex_t *m)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
|
||||
do {
|
||||
/* Wait until the mutex is unlocked. */
|
||||
while (__ldrex(m) != MUTEX_UNLOCKED);
|
||||
|
||||
/* Try to acquire it. */
|
||||
status = __strex(MUTEX_LOCKED, m);
|
||||
|
||||
/* Did we get it? If not then try again. */
|
||||
} while (status != 0);
|
||||
|
||||
/* Execute the mysterious Data Memory Barrier instruction! */
|
||||
__dmb();
|
||||
}
|
||||
|
||||
void mutex_unlock(mutex_t *m)
|
||||
{
|
||||
/* Ensure accesses to protected resource are finished */
|
||||
__dmb();
|
||||
|
||||
/* Free the lock. */
|
||||
*m = MUTEX_UNLOCKED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to lock mutex
|
||||
* if it's already locked or there was error in STREX, return MUTEX_LOCKED
|
||||
* else return MUTEX_UNLOCKED
|
||||
*/
|
||||
mutex_t mutex_trylock(mutex_t *m){
|
||||
uint32_t status = 0;
|
||||
mutex_t old_lock = __ldrex(m); // get mutex value
|
||||
// set mutex
|
||||
status = __strex(MUTEX_LOCKED, m);
|
||||
if(status == 0) __dmb();
|
||||
else old_lock = MUTEX_LOCKED;
|
||||
return old_lock;
|
||||
}
|
||||
|
||||
#endif
|
||||
53
ultrasonic/sync.h
Normal file
53
ultrasonic/sync.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBOPENCM3_CM3_SYNC_H
|
||||
#define LIBOPENCM3_CM3_SYNC_H
|
||||
|
||||
void __dmb(void);
|
||||
|
||||
/* Implements synchronisation primitives as discussed in the ARM document
|
||||
* DHT0008A (ID081709) "ARM Synchronization Primitives" and the ARM v7-M
|
||||
* Architecture Reference Manual.
|
||||
*/
|
||||
|
||||
/* --- Exclusive load and store instructions ------------------------------- */
|
||||
|
||||
/* Those are defined only on CM3 or CM4 */
|
||||
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
|
||||
uint32_t __ldrex(volatile uint32_t *addr);
|
||||
uint32_t __strex(uint32_t val, volatile uint32_t *addr);
|
||||
|
||||
/* --- Convenience functions ----------------------------------------------- */
|
||||
|
||||
/* Here we implement some simple synchronisation primitives. */
|
||||
|
||||
typedef uint32_t mutex_t;
|
||||
|
||||
#define MUTEX_UNLOCKED 0
|
||||
#define MUTEX_LOCKED 1
|
||||
|
||||
void mutex_lock(mutex_t *m);
|
||||
void mutex_unlock(mutex_t *m);
|
||||
mutex_t mutex_trylock(mutex_t *m);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
BIN
ultrasonic/ultrasonic.bin
Executable file
BIN
ultrasonic/ultrasonic.bin
Executable file
Binary file not shown.
165
ultrasonic/ultrasonic.c
Normal file
165
ultrasonic/ultrasonic.c
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* ultrasonic.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 <libopencm3/stm32/timer.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
|
||||
#include "ultrasonic.h"
|
||||
#include "user_proto.h"
|
||||
|
||||
static usmode US_mode = US_MODE_OFF;
|
||||
static int overcapture = 0;
|
||||
|
||||
#ifndef TIM_CCMR2_CC3S_IN_TI4
|
||||
#define TIM_CCMR2_CC3S_IN_TI4 (2)
|
||||
#endif
|
||||
#ifndef TIM_CCMR2_CC4S_IN_TI4
|
||||
#define TIM_CCMR2_CC4S_IN_TI4 (1 << 8)
|
||||
#endif
|
||||
/**
|
||||
* Init timer 2 (&remap channels 3&4 to five-tolerant ports)
|
||||
*/
|
||||
void tim2_init(){
|
||||
// Turn off JTAG & SWD, remap TIM2_CH3/TIM2_CH4 to PB10/PB11 (five tolerant)
|
||||
// don't forget about AFIO clock & PB clock!
|
||||
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPBEN);
|
||||
gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF, AFIO_MAPR_TIM2_REMAP_PARTIAL_REMAP2);
|
||||
// setup PB10 & PB11
|
||||
// PB10 - Trig output - push/pull
|
||||
gpio_set_mode(GPIO_BANK_TIM2_PR2_CH3, GPIO_MODE_OUTPUT_10_MHZ,
|
||||
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_TIM2_PR2_CH3);
|
||||
// gpio_set_mode(GPIO_BANK_TIM2_CH3, GPIO_MODE_OUTPUT_10_MHZ,
|
||||
// GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_TIM2_CH3);
|
||||
// PB11 - Echo input - floating
|
||||
// gpio_set_mode(GPIO_BANK_TIM2_PR2_CH4, GPIO_MODE_INPUT,
|
||||
// GPIO_CNF_INPUT_FLOAT, GPIO_TIM2_PR2_CH4);
|
||||
rcc_periph_clock_enable(RCC_TIM2);
|
||||
timer_reset(TIM2);
|
||||
// timers have frequency of 1MHz -- 1us for one step
|
||||
// 36MHz of APB1
|
||||
timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
|
||||
// 72MHz div 72 = 1MHz
|
||||
TIM2_PSC = 71; // prescaler is (div - 1)
|
||||
TIM2_ARR = TRIG_T;
|
||||
TIM2_CCR3 = TRIG_L;
|
||||
// DBG("Timer configured\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send Trig signal
|
||||
* return 0 if another measurement still in process
|
||||
*/
|
||||
int start_ultrasonic(){
|
||||
if(US_mode != US_MODE_OFF && US_mode != US_MODE_READY) return 0;
|
||||
overcapture = 0;
|
||||
TIM2_CR1 = 0;
|
||||
//TIM2_CR1 = TIM_CR1_URS; // Turn off timer to reconfigure, dusable UEV by UG set
|
||||
TIM2_CCER = 0;
|
||||
TIM2_CCMR2 = 0;
|
||||
TIM2_DIER = 0;
|
||||
TIM2_SR = 0; // clear all flags
|
||||
TIM2_ARR = TRIG_T;
|
||||
TIM2_CCR3 = TRIG_L;
|
||||
// PWM_OUT for TIM2_CH3
|
||||
TIM2_CCMR2 = TIM_CCMR2_CC3S_OUT | TIM_CCMR2_OC3M_PWM1;
|
||||
// start measurement, active is high
|
||||
TIM2_CCER = TIM_CCER_CC3E;
|
||||
// enable CC3 IRQ
|
||||
TIM2_DIER = TIM_DIER_CC3IE;
|
||||
nvic_enable_irq(NVIC_TIM2_IRQ);
|
||||
US_mode = US_MODE_TRIG;
|
||||
// start timer in one-pulse mode without update event
|
||||
TIM2_CR1 = TIM_CR1_OPM | TIM_CR1_CEN | TIM_CR1_UDIS;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start measurement:
|
||||
* TIM2_CH3 will capture high level & TIM2_CH4 will capture low
|
||||
* The timer configured to 65536us to detect signal lost
|
||||
*/
|
||||
inline void run_measrmnt(){
|
||||
US_mode = US_MODE_WAIT;
|
||||
TIM2_CR1 = 0; // Turn off timer to reconfigure
|
||||
TIM2_DIER = 0;
|
||||
TIM2_CCER = 0;
|
||||
TIM2_CCMR2 = 0;
|
||||
//DBG("triggered\n");
|
||||
TIM2_SR = 0; // clear all flags
|
||||
TIM2_ARR = MAX_MSRMNT_LEN;
|
||||
// TIM2_CH3 & TIM2_CH4 configured as inputs, TIM2_CH3 connected to CH4
|
||||
TIM2_CCMR2 = TIM_CCMR2_CC3S_IN_TI4 | TIM_CCMR2_CC4S_IN_TI4;
|
||||
// start
|
||||
TIM2_CCER = TIM_CCER_CC4P | TIM_CCER_CC4E | TIM_CCER_CC3E;
|
||||
// enable interrupts CH3, CH4 & update
|
||||
TIM2_DIER = TIM_DIER_CC3IE | TIM_DIER_CC4IE | TIM_DIER_UIE;
|
||||
// start timer in one-pulse mode
|
||||
TIM2_CR1 = TIM_CR1_OPM | TIM_CR1_CEN;
|
||||
}
|
||||
|
||||
void tim2_isr(){
|
||||
// No signal
|
||||
if(TIM2_SR & TIM_SR_UIF){ // update interrupt
|
||||
TIM2_SR = 0;
|
||||
overcapture = 1;
|
||||
nvic_disable_irq(NVIC_TIM2_IRQ);
|
||||
TIM2_DIER = 0;
|
||||
US_mode = US_MODE_READY;
|
||||
DBG("overcaptured\n");
|
||||
}
|
||||
// end of Trig pulse or start of measurements
|
||||
if(TIM2_SR & TIM_SR_CC3IF){ // CCR ch3 interrupt
|
||||
if(US_mode == US_MODE_TRIG){ // triggered - run measurement
|
||||
run_measrmnt();
|
||||
}else if(US_mode == US_MODE_WAIT){
|
||||
US_mode = US_MODE_MEASUREMENT;
|
||||
}
|
||||
TIM2_SR &= ~TIM_SR_CC3IF;
|
||||
}
|
||||
if(TIM2_SR & TIM_SR_CC4IF){
|
||||
if(US_mode == US_MODE_MEASUREMENT){
|
||||
US_mode = US_MODE_READY;
|
||||
nvic_disable_irq(NVIC_TIM2_IRQ);
|
||||
TIM2_DIER = 0;
|
||||
TIM2_CR1 = 0; // turn off timer - we don't need it more
|
||||
}
|
||||
TIM2_SR &= ~TIM_SR_CC3IF;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Measure distance
|
||||
* return 1 if measurements done
|
||||
* set L to distance (in mm) or 0 in case of overcapture (no signal)
|
||||
*/
|
||||
int ultrasonic_get(uint32_t *L){
|
||||
uint32_t D;
|
||||
if(US_mode != US_MODE_READY)
|
||||
return 0;
|
||||
US_mode = US_MODE_OFF;
|
||||
if(!overcapture){
|
||||
D = ((uint32_t)(TIM2_CCR4 - TIM2_CCR3)) * 170;
|
||||
*L = D / 1000;
|
||||
}else *L = 0;
|
||||
return 1;
|
||||
}
|
||||
52
ultrasonic/ultrasonic.geany
Normal file
52
ultrasonic/ultrasonic.geany
Normal file
@ -0,0 +1,52 @@
|
||||
[file_prefs]
|
||||
final_new_line=true
|
||||
ensure_convert_new_lines=true
|
||||
strip_trailing_spaces=true
|
||||
replace_tabs=false
|
||||
|
||||
[indentation]
|
||||
indent_width=4
|
||||
indent_type=1
|
||||
indent_hard_tab_width=4
|
||||
detect_indent=false
|
||||
detect_indent_width=false
|
||||
indent_mode=3
|
||||
|
||||
[project]
|
||||
name=ultrasonic
|
||||
base_path=/home/eddy/Docs/SAO/ELECTRONICS/STM32/c8t6/ultrasonic/
|
||||
description=
|
||||
|
||||
[long line marker]
|
||||
long_line_behaviour=1
|
||||
long_line_column=80
|
||||
|
||||
[files]
|
||||
current_page=8
|
||||
FILE_NAME_0=4955;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2Fultrasonic%2Fultrasonic.c;0;4
|
||||
FILE_NAME_1=1405;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2Fultrasonic%2Fultrasonic.h;0;4
|
||||
FILE_NAME_2=1366;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2Fultrasonic%2Fuser_proto.c;0;4
|
||||
FILE_NAME_3=1108;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2Fultrasonic%2Fuser_proto.h;0;4
|
||||
FILE_NAME_4=1778;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2Fultrasonic%2Fmain.c;0;4
|
||||
FILE_NAME_5=1205;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2Fultrasonic%2Fmain.h;0;4
|
||||
FILE_NAME_6=1157;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2Fultrasonic%2Fhardware_ini.c;0;4
|
||||
FILE_NAME_7=925;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2Fultrasonic%2Fhardware_ini.h;0;4
|
||||
FILE_NAME_8=870;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2Fultrasonic%2Fsharp.c;0;4
|
||||
FILE_NAME_9=909;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2Fultrasonic%2Fsharp.h;0;4
|
||||
FILE_NAME_10=0;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fopenstm32%2Flibopencm3%2Finclude%2Flibopencm3%2Fstm32%2Ff1%2Ftimer.h;0;4
|
||||
FILE_NAME_11=9634;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fopenstm32%2Flibopencm3%2Finclude%2Flibopencm3%2Fstm32%2Fcommon%2Ftimer_common_all.h;0;4
|
||||
FILE_NAME_12=0;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fopenstm32%2Flibopencm3%2Finclude%2Flibopencm3%2Fstm32%2Fcommon%2Fgpio_common_all.h;0;4
|
||||
FILE_NAME_13=28941;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fopenstm32%2Flibopencm3%2Finclude%2Flibopencm3%2Fstm32%2Ff1%2Fgpio.h;0;4
|
||||
FILE_NAME_14=0;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fopenstm32%2Flibopencm3%2Flib%2Fstm32%2Ff1%2Fgpio.c;0;4
|
||||
FILE_NAME_15=1639;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fopenstm32%2Flibopencm3%2Finclude%2Flibopencm3%2Fstm32%2Ff1%2Fadc.h;0;4
|
||||
FILE_NAME_16=11790;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fopenstm32%2Flibopencm3%2Finclude%2Flibopencm3%2Fstm32%2Fcommon%2Fadc_common_v1.h;0;4
|
||||
FILE_NAME_17=22482;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fopenstm32%2Flibopencm3%2Flib%2Fstm32%2Fcommon%2Fadc_common_v1.c;0;4
|
||||
FILE_NAME_18=4646;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fopenstm32%2Flibopencm3%2Flib%2Fstm32%2Ff1%2Fadc.c;0;4
|
||||
FILE_NAME_19=9093;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2FWORK%2FIR-controller%2Fwith_opencm3%2Fhardware_ini.c;0;4
|
||||
FILE_NAME_20=3059;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fopenstm32%2Flibopencm3%2Finclude%2Flibopencm3%2Fstm32%2Ff1%2Fnvic.h;0;4
|
||||
FILE_NAME_21=0;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fopenstm32%2Flibopencm3%2Flib%2Fstm32%2Ff1%2Frcc.c;0;4
|
||||
FILE_NAME_22=4504;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fopenstm32%2Flibopencm3%2Flib%2Fstm32%2Fcommon%2Frcc_common_all.c;0;4
|
||||
FILE_NAME_23=2498;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fopenstm32%2Flibopencm3%2Finclude%2Flibopencmsis%2Fcore_cm3.h;0;4
|
||||
|
||||
[VTE]
|
||||
last_dir=/home/eddy/Docs/SAO/Cameras/FLI_camera/my/Mytakepic
|
||||
49
ultrasonic/ultrasonic.h
Normal file
49
ultrasonic/ultrasonic.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* ultrasonic.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 __ULTRASONIC_H__
|
||||
#define __ULTRASONIC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void tim2_init();
|
||||
int start_ultrasonic();
|
||||
int ultrasonic_get(uint32_t *L);
|
||||
|
||||
|
||||
// Sensor mode
|
||||
typedef enum{
|
||||
US_MODE_OFF // sensor is off
|
||||
,US_MODE_TRIG // sensor triggered
|
||||
,US_MODE_WAIT // wait for pulse
|
||||
,US_MODE_MEASUREMENT // measurement in process
|
||||
,US_MODE_READY // measurements done
|
||||
} usmode;
|
||||
|
||||
// trigger time: after trigger event ends, timer will be configured for capture - 20us
|
||||
#define TRIG_T (200)
|
||||
// trigger length - 10us
|
||||
#define TRIG_L (10)
|
||||
// max length of measurement (to detect signal absence)
|
||||
#define MAX_MSRMNT_LEN (65535)
|
||||
|
||||
#endif // __ULTRASONIC_H__
|
||||
213
ultrasonic/user_proto.c
Normal file
213
ultrasonic/user_proto.c
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* user_proto.c
|
||||
*
|
||||
* Copyright 2014 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 "cdcacm.h"
|
||||
#include "main.h"
|
||||
#include "hardware_ini.h"
|
||||
#include "sharp.h"
|
||||
|
||||
// integer value given by user
|
||||
static volatile int32_t User_value = 0;
|
||||
enum{
|
||||
UVAL_START, // user start to write integer value
|
||||
UVAL_ENTERED, // value entered but not printed
|
||||
UVAL_BAD // entered bad value
|
||||
};
|
||||
uint8_t Uval_ready = UVAL_BAD, cont = 0;
|
||||
|
||||
int read_int(char *buf, int cnt);
|
||||
|
||||
intfun I = NULL; // function to process entered integer
|
||||
|
||||
#define READINT() do{i += read_int(&buf[i+1], len-i-1);}while(0)
|
||||
|
||||
void help(){
|
||||
P("A\tshow ADC value\n");
|
||||
P("H\tshow this help\n");
|
||||
P("D\tmeasure distance\n");
|
||||
P("I\tinit sharp\n");
|
||||
P("T\tshow timer value\n");
|
||||
P("S\tstart/stop continuous measurement\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* show entered integer value
|
||||
*/
|
||||
uint8_t show_int(int32_t v){
|
||||
newline();
|
||||
print_int(v);
|
||||
newline();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* parce command buffer buf with length len
|
||||
* return 0 if buffer processed or len if there's not enough data in buffer
|
||||
*/
|
||||
int parce_incoming_buf(char *buf, int len){
|
||||
uint8_t command;
|
||||
//uint32_t utmp;
|
||||
int i = 0;
|
||||
if(Uval_ready == UVAL_START){ // we are in process of user's value reading
|
||||
i += read_int(buf, len);
|
||||
}
|
||||
if(Uval_ready == UVAL_ENTERED){
|
||||
//print_int(User_value); // printout readed integer value for error control
|
||||
Uval_ready = UVAL_BAD; // clear Uval
|
||||
I(User_value);
|
||||
return 0;
|
||||
}
|
||||
for(; i < len; i++){
|
||||
command = buf[i];
|
||||
if(!command) continue; // omit zero
|
||||
switch (command){
|
||||
case 'A':
|
||||
P("ADC: ");
|
||||
print_int(ADC1_DR);
|
||||
P("ADU\n");
|
||||
break;
|
||||
case 'D':
|
||||
if(!start_ultrasonic())
|
||||
P("Can't start: another measurement is in process!\n");
|
||||
break;
|
||||
case 'H': // show help
|
||||
help();
|
||||
break;
|
||||
case 'I':
|
||||
init_sharp_sensor();
|
||||
break;
|
||||
case 'S':
|
||||
cont = !cont;
|
||||
if(cont) start_ultrasonic();
|
||||
break;
|
||||
case 'T':
|
||||
newline();
|
||||
print_int(Timer); // be careful for Time >= 2^{31}!!!
|
||||
newline();
|
||||
break;
|
||||
case '\n': // show newline, space and tab as is
|
||||
case '\r':
|
||||
case ' ':
|
||||
case '\t':
|
||||
break;
|
||||
default:
|
||||
command = '?'; // echo '?' on unknown command in byte mode
|
||||
}
|
||||
usb_send(command); // echo readed byte
|
||||
}
|
||||
return 0; // all data processed - 0 bytes leave in buffer
|
||||
}
|
||||
|
||||
/**
|
||||
* Send char array wrd thru USB or UART
|
||||
*/
|
||||
void prnt(uint8_t *wrd){
|
||||
if(!wrd) return;
|
||||
while(*wrd) usb_send(*wrd++);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from TTY integer value given by user (in DEC).
|
||||
* Reading stops on first non-numeric symbol.
|
||||
* To work with symbol terminals reading don't stops on buffer's end,
|
||||
* it waits for first non-numeric char.
|
||||
* When working on string terminals, terminate string by '\n', 0 or any other symbol
|
||||
* @param buf - buffer to read from
|
||||
* @param cnt - buffer length
|
||||
* @return amount of readed symbols
|
||||
*/
|
||||
int read_int(char *buf, int cnt){
|
||||
int readed = 0, i;
|
||||
static int enteredDigits; // amount of entered digits
|
||||
static int sign; // sign of readed value
|
||||
if(Uval_ready){ // this is first run
|
||||
Uval_ready = UVAL_START; // clear flag
|
||||
enteredDigits = 0; // 0 digits entered
|
||||
User_value = 0; // clear value
|
||||
sign = 1; // clear sign
|
||||
}
|
||||
if(!cnt) return 0;
|
||||
for(i = 0; i < cnt; i++, readed++){
|
||||
uint8_t chr = buf[i];
|
||||
if(chr == '-'){
|
||||
if(enteredDigits == 0){ // sign should be first
|
||||
sign = -1;
|
||||
continue;
|
||||
}else{ // '-' after number - reject entered value
|
||||
Uval_ready = UVAL_BAD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(chr < '0' || chr > '9'){
|
||||
if(enteredDigits)
|
||||
Uval_ready = UVAL_ENTERED;
|
||||
else
|
||||
Uval_ready = UVAL_BAD; // bad symbol
|
||||
break;
|
||||
}
|
||||
User_value = User_value * 10 + (int32_t)(chr - '0');
|
||||
enteredDigits++;
|
||||
}
|
||||
if(Uval_ready == UVAL_ENTERED) // reading has met an non-numeric character
|
||||
User_value *= sign;
|
||||
return readed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print buff as hex values
|
||||
* @param buf - buffer to print
|
||||
* @param l - buf length
|
||||
* @param s - function to send a byte
|
||||
*/
|
||||
void print_hex(uint8_t *buff, uint8_t l){
|
||||
void putc(uint8_t c){
|
||||
if(c < 10)
|
||||
usb_send(c + '0');
|
||||
else
|
||||
usb_send(c + 'a' - 10);
|
||||
}
|
||||
usb_send('0'); usb_send('x'); // prefix 0x
|
||||
while(l--){
|
||||
putc(buff[l] >> 4);
|
||||
putc(buff[l] & 0x0f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print decimal integer value
|
||||
* @param N - value to print
|
||||
* @param s - function to send a byte
|
||||
*/
|
||||
void print_int(int32_t N){
|
||||
uint8_t buf[10], L = 0;
|
||||
if(N < 0){
|
||||
usb_send('-');
|
||||
N = -N;
|
||||
}
|
||||
if(N){
|
||||
while(N){
|
||||
buf[L++] = N % 10 + '0';
|
||||
N /= 10;
|
||||
}
|
||||
while(L--) usb_send(buf[L]);
|
||||
}else usb_send('0');
|
||||
}
|
||||
|
||||
49
ultrasonic/user_proto.h
Normal file
49
ultrasonic/user_proto.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* user_proto.h
|
||||
*
|
||||
* Copyright 2014 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 __USER_PROTO_H__
|
||||
#define __USER_PROTO_H__
|
||||
|
||||
#include "cdcacm.h"
|
||||
|
||||
// shorthand for prnt
|
||||
#define P(arg) do{prnt((uint8_t*)arg);}while(0)
|
||||
// debug message - over USB
|
||||
#ifdef EBUG
|
||||
#define DBG(a) do{prnt((uint8_t*)a);}while(0)
|
||||
#else
|
||||
#define DBG(a)
|
||||
#endif
|
||||
|
||||
extern uint8_t cont;
|
||||
|
||||
typedef uint8_t (*intfun)(int32_t);
|
||||
|
||||
void prnt(uint8_t *wrd);
|
||||
#define newline() usb_send('\n')
|
||||
|
||||
void print_int(int32_t N);
|
||||
void print_hex(uint8_t *buff, uint8_t l);
|
||||
|
||||
int parce_incoming_buf(char *buf, int len);
|
||||
|
||||
#endif // __USER_PROTO_H__
|
||||
Loading…
x
Reference in New Issue
Block a user