From 7e78a70aa548b91b3d79ca4b469a97f0f7d288b3 Mon Sep 17 00:00:00 2001 From: eddyem Date: Tue, 28 Jul 2015 21:37:15 +0300 Subject: [PATCH] Added distance-meters --- distance_meters/Makefile | 133 +++++++++++++ distance_meters/Readme.md | 6 + distance_meters/cdcacm.c | 314 ++++++++++++++++++++++++++++++ distance_meters/cdcacm.h | 54 +++++ distance_meters/hardware_ini.c | 57 ++++++ distance_meters/hardware_ini.h | 60 ++++++ distance_meters/ld/devices.data | 9 + distance_meters/ld/stm32f103x4.ld | 31 +++ distance_meters/ld/stm32f103x6.ld | 31 +++ distance_meters/ld/stm32f103x8.ld | 31 +++ distance_meters/ld/stm32f103xB.ld | 31 +++ distance_meters/ld/stm32f103xC.ld | 31 +++ distance_meters/ld/stm32f103xD.ld | 31 +++ distance_meters/ld/stm32f103xE.ld | 31 +++ distance_meters/ld/stm32f103xF.ld | 31 +++ distance_meters/ld/stm32f103xG.ld | 31 +++ distance_meters/main.c | 120 ++++++++++++ distance_meters/main.h | 57 ++++++ distance_meters/sharp.c | 72 +++++++ distance_meters/sharp.h | 38 ++++ distance_meters/sync.c | 93 +++++++++ distance_meters/sync.h | 53 +++++ distance_meters/ultrasonic.bin | Bin 0 -> 8124 bytes distance_meters/ultrasonic.c | 165 ++++++++++++++++ distance_meters/ultrasonic.h | 49 +++++ distance_meters/user_proto.c | 213 ++++++++++++++++++++ distance_meters/user_proto.h | 49 +++++ 27 files changed, 1821 insertions(+) create mode 100644 distance_meters/Makefile create mode 100644 distance_meters/Readme.md create mode 100644 distance_meters/cdcacm.c create mode 100644 distance_meters/cdcacm.h create mode 100644 distance_meters/hardware_ini.c create mode 100644 distance_meters/hardware_ini.h create mode 100644 distance_meters/ld/devices.data create mode 100644 distance_meters/ld/stm32f103x4.ld create mode 100644 distance_meters/ld/stm32f103x6.ld create mode 100644 distance_meters/ld/stm32f103x8.ld create mode 100644 distance_meters/ld/stm32f103xB.ld create mode 100644 distance_meters/ld/stm32f103xC.ld create mode 100644 distance_meters/ld/stm32f103xD.ld create mode 100644 distance_meters/ld/stm32f103xE.ld create mode 100644 distance_meters/ld/stm32f103xF.ld create mode 100644 distance_meters/ld/stm32f103xG.ld create mode 100644 distance_meters/main.c create mode 100644 distance_meters/main.h create mode 100644 distance_meters/sharp.c create mode 100644 distance_meters/sharp.h create mode 100644 distance_meters/sync.c create mode 100644 distance_meters/sync.h create mode 100755 distance_meters/ultrasonic.bin create mode 100644 distance_meters/ultrasonic.c create mode 100644 distance_meters/ultrasonic.h create mode 100644 distance_meters/user_proto.c create mode 100644 distance_meters/user_proto.h diff --git a/distance_meters/Makefile b/distance_meters/Makefile new file mode 100644 index 0000000..35b162d --- /dev/null +++ b/distance_meters/Makefile @@ -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) diff --git a/distance_meters/Readme.md b/distance_meters/Readme.md new file mode 100644 index 0000000..f9666de --- /dev/null +++ b/distance_meters/Readme.md @@ -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) \ No newline at end of file diff --git a/distance_meters/cdcacm.c b/distance_meters/cdcacm.c new file mode 100644 index 0000000..5f032ad --- /dev/null +++ b/distance_meters/cdcacm.c @@ -0,0 +1,314 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Gareth McMullin + * Copyright 2014 Edward V. Emelianov + * + * 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 . + */ + +#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); +} diff --git a/distance_meters/cdcacm.h b/distance_meters/cdcacm.h new file mode 100644 index 0000000..1051d83 --- /dev/null +++ b/distance_meters/cdcacm.h @@ -0,0 +1,54 @@ +/* + * ccdcacm.h + * + * Copyright 2014 Edward V. Emelianov + * + * 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 + +// 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__ diff --git a/distance_meters/hardware_ini.c b/distance_meters/hardware_ini.c new file mode 100644 index 0000000..717ab14 --- /dev/null +++ b/distance_meters/hardware_ini.c @@ -0,0 +1,57 @@ +/* + * hardware_ini.c - functions for HW initialisation + * + * Copyright 2014 Edward V. Emelianov + * + * 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(); +} + diff --git a/distance_meters/hardware_ini.h b/distance_meters/hardware_ini.h new file mode 100644 index 0000000..11fe628 --- /dev/null +++ b/distance_meters/hardware_ini.h @@ -0,0 +1,60 @@ +/* + * hardware_ini.h + * + * Copyright 2014 Edward V. Emelianov + * + * 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__ diff --git a/distance_meters/ld/devices.data b/distance_meters/ld/devices.data new file mode 100644 index 0000000..7f29538 --- /dev/null +++ b/distance_meters/ld/devices.data @@ -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 diff --git a/distance_meters/ld/stm32f103x4.ld b/distance_meters/ld/stm32f103x4.ld new file mode 100644 index 0000000..efed65e --- /dev/null +++ b/distance_meters/ld/stm32f103x4.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Karl Palsson + * + * 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 . + */ + +/* 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 + diff --git a/distance_meters/ld/stm32f103x6.ld b/distance_meters/ld/stm32f103x6.ld new file mode 100644 index 0000000..13f05f9 --- /dev/null +++ b/distance_meters/ld/stm32f103x6.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Karl Palsson + * + * 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 . + */ + +/* 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 + diff --git a/distance_meters/ld/stm32f103x8.ld b/distance_meters/ld/stm32f103x8.ld new file mode 100644 index 0000000..2c4640f --- /dev/null +++ b/distance_meters/ld/stm32f103x8.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Karl Palsson + * + * 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 . + */ + +/* 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 + diff --git a/distance_meters/ld/stm32f103xB.ld b/distance_meters/ld/stm32f103xB.ld new file mode 100644 index 0000000..138444d --- /dev/null +++ b/distance_meters/ld/stm32f103xB.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Karl Palsson + * + * 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 . + */ + +/* 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 + diff --git a/distance_meters/ld/stm32f103xC.ld b/distance_meters/ld/stm32f103xC.ld new file mode 100644 index 0000000..fda76bf --- /dev/null +++ b/distance_meters/ld/stm32f103xC.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Karl Palsson + * + * 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 . + */ + +/* 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 + diff --git a/distance_meters/ld/stm32f103xD.ld b/distance_meters/ld/stm32f103xD.ld new file mode 100644 index 0000000..0f996c2 --- /dev/null +++ b/distance_meters/ld/stm32f103xD.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Karl Palsson + * + * 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 . + */ + +/* 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 + diff --git a/distance_meters/ld/stm32f103xE.ld b/distance_meters/ld/stm32f103xE.ld new file mode 100644 index 0000000..b0fcb69 --- /dev/null +++ b/distance_meters/ld/stm32f103xE.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Karl Palsson + * + * 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 . + */ + +/* 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 + diff --git a/distance_meters/ld/stm32f103xF.ld b/distance_meters/ld/stm32f103xF.ld new file mode 100644 index 0000000..62d47db --- /dev/null +++ b/distance_meters/ld/stm32f103xF.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Karl Palsson + * + * 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 . + */ + +/* 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 + diff --git a/distance_meters/ld/stm32f103xG.ld b/distance_meters/ld/stm32f103xG.ld new file mode 100644 index 0000000..0c0c968 --- /dev/null +++ b/distance_meters/ld/stm32f103xG.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Karl Palsson + * + * 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 . + */ + +/* 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 + diff --git a/distance_meters/main.c b/distance_meters/main.c new file mode 100644 index 0000000..2fd343a --- /dev/null +++ b/distance_meters/main.c @@ -0,0 +1,120 @@ +/* + * main.c + * + * Copyright 2014 Edward V. Emelianov + * + * 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); +} diff --git a/distance_meters/main.h b/distance_meters/main.h new file mode 100644 index 0000000..5dcdafb --- /dev/null +++ b/distance_meters/main.h @@ -0,0 +1,57 @@ +/* + * main.h + * + * Copyright 2014 Edward V. Emelianov + * + * 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 +#include // memcpy +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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__ + diff --git a/distance_meters/sharp.c b/distance_meters/sharp.c new file mode 100644 index 0000000..f081aa8 --- /dev/null +++ b/distance_meters/sharp.c @@ -0,0 +1,72 @@ +/* + * sharp.c - functions for Sharp 2Y0A02 distance meter + * + * Copyright 2015 Edward V. Emelianov + * + * 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; +} diff --git a/distance_meters/sharp.h b/distance_meters/sharp.h new file mode 100644 index 0000000..c2d48bb --- /dev/null +++ b/distance_meters/sharp.h @@ -0,0 +1,38 @@ +/* + * sharp.h + * + * Copyright 2015 Edward V. Emelianov + * + * 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 + +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__ diff --git a/distance_meters/sync.c b/distance_meters/sync.c new file mode 100644 index 0000000..ba688c3 --- /dev/null +++ b/distance_meters/sync.c @@ -0,0 +1,93 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Fergus Noble + * + * 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 . + */ + +/* + * TODO: + * implement mutexes for other type of MCU (which doesn't have strex & ldrex) + */ + +#include + +/* 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 diff --git a/distance_meters/sync.h b/distance_meters/sync.h new file mode 100644 index 0000000..bfe837b --- /dev/null +++ b/distance_meters/sync.h @@ -0,0 +1,53 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Fergus Noble + * + * 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 . + */ + +#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 diff --git a/distance_meters/ultrasonic.bin b/distance_meters/ultrasonic.bin new file mode 100755 index 0000000000000000000000000000000000000000..305d3b2c511aa4d73023c8d7f11d082960ff85e3 GIT binary patch literal 8124 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 literal 0 HcmV?d00001 diff --git a/distance_meters/ultrasonic.c b/distance_meters/ultrasonic.c new file mode 100644 index 0000000..41d010c --- /dev/null +++ b/distance_meters/ultrasonic.c @@ -0,0 +1,165 @@ +/* + * ultrasonic.c + * + * Copyright 2015 Edward V. Emelianov + * + * 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 +#include +#include +#include + +#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; +} diff --git a/distance_meters/ultrasonic.h b/distance_meters/ultrasonic.h new file mode 100644 index 0000000..86432dc --- /dev/null +++ b/distance_meters/ultrasonic.h @@ -0,0 +1,49 @@ +/* + * ultrasonic.h + * + * Copyright 2015 Edward V. Emelianov + * + * 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 + +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__ diff --git a/distance_meters/user_proto.c b/distance_meters/user_proto.c new file mode 100644 index 0000000..73bd69d --- /dev/null +++ b/distance_meters/user_proto.c @@ -0,0 +1,213 @@ +/* + * user_proto.c + * + * Copyright 2014 Edward V. Emelianov + * + * 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'); +} + diff --git a/distance_meters/user_proto.h b/distance_meters/user_proto.h new file mode 100644 index 0000000..be14383 --- /dev/null +++ b/distance_meters/user_proto.h @@ -0,0 +1,49 @@ +/* + * user_proto.h + * + * Copyright 2014 Edward V. Emelianov + * + * 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__