From a7f16d107a82e2bff88cf8528d3f0bfac22746ef Mon Sep 17 00:00:00 2001 From: eddyem Date: Mon, 12 Sep 2016 22:13:37 +0300 Subject: [PATCH] Timelapse-ver.2.0 - only lasers --- Timelapse_keyboard_only_lasers/GPS.c | 162 +++++++++ Timelapse_keyboard_only_lasers/GPS.h | 37 +++ Timelapse_keyboard_only_lasers/Makefile | 133 ++++++++ Timelapse_keyboard_only_lasers/Readme.md | 41 +++ Timelapse_keyboard_only_lasers/adc.c | 62 ++++ Timelapse_keyboard_only_lasers/adc.h | 45 +++ Timelapse_keyboard_only_lasers/hardware_ini.c | 129 ++++++++ Timelapse_keyboard_only_lasers/hardware_ini.h | 75 +++++ Timelapse_keyboard_only_lasers/keycodes.c | 74 +++++ Timelapse_keyboard_only_lasers/keycodes.h | 138 ++++++++ .../ld/devices.data | 9 + .../ld/stm32f103x4.ld | 31 ++ .../ld/stm32f103x6.ld | 31 ++ .../ld/stm32f103x8.ld | 31 ++ .../ld/stm32f103xB.ld | 31 ++ .../ld/stm32f103xC.ld | 31 ++ .../ld/stm32f103xD.ld | 31 ++ .../ld/stm32f103xE.ld | 31 ++ .../ld/stm32f103xF.ld | 31 ++ .../ld/stm32f103xG.ld | 31 ++ Timelapse_keyboard_only_lasers/main.c | 311 ++++++++++++++++++ Timelapse_keyboard_only_lasers/main.h | 75 +++++ Timelapse_keyboard_only_lasers/timelapse.bin | Bin 0 -> 9896 bytes Timelapse_keyboard_only_lasers/uart.c | 247 ++++++++++++++ Timelapse_keyboard_only_lasers/uart.h | 46 +++ Timelapse_keyboard_only_lasers/usbkeybrd.c | 276 ++++++++++++++++ Timelapse_keyboard_only_lasers/usbkeybrd.h | 44 +++ 27 files changed, 2183 insertions(+) create mode 100644 Timelapse_keyboard_only_lasers/GPS.c create mode 100644 Timelapse_keyboard_only_lasers/GPS.h create mode 100644 Timelapse_keyboard_only_lasers/Makefile create mode 100644 Timelapse_keyboard_only_lasers/Readme.md create mode 100644 Timelapse_keyboard_only_lasers/adc.c create mode 100644 Timelapse_keyboard_only_lasers/adc.h create mode 100644 Timelapse_keyboard_only_lasers/hardware_ini.c create mode 100644 Timelapse_keyboard_only_lasers/hardware_ini.h create mode 100644 Timelapse_keyboard_only_lasers/keycodes.c create mode 100644 Timelapse_keyboard_only_lasers/keycodes.h create mode 100644 Timelapse_keyboard_only_lasers/ld/devices.data create mode 100644 Timelapse_keyboard_only_lasers/ld/stm32f103x4.ld create mode 100644 Timelapse_keyboard_only_lasers/ld/stm32f103x6.ld create mode 100644 Timelapse_keyboard_only_lasers/ld/stm32f103x8.ld create mode 100644 Timelapse_keyboard_only_lasers/ld/stm32f103xB.ld create mode 100644 Timelapse_keyboard_only_lasers/ld/stm32f103xC.ld create mode 100644 Timelapse_keyboard_only_lasers/ld/stm32f103xD.ld create mode 100644 Timelapse_keyboard_only_lasers/ld/stm32f103xE.ld create mode 100644 Timelapse_keyboard_only_lasers/ld/stm32f103xF.ld create mode 100644 Timelapse_keyboard_only_lasers/ld/stm32f103xG.ld create mode 100644 Timelapse_keyboard_only_lasers/main.c create mode 100644 Timelapse_keyboard_only_lasers/main.h create mode 100755 Timelapse_keyboard_only_lasers/timelapse.bin create mode 100644 Timelapse_keyboard_only_lasers/uart.c create mode 100644 Timelapse_keyboard_only_lasers/uart.h create mode 100644 Timelapse_keyboard_only_lasers/usbkeybrd.c create mode 100644 Timelapse_keyboard_only_lasers/usbkeybrd.h diff --git a/Timelapse_keyboard_only_lasers/GPS.c b/Timelapse_keyboard_only_lasers/GPS.c new file mode 100644 index 0000000..b684f42 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/GPS.c @@ -0,0 +1,162 @@ +/* + * GPS.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 "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, '*'))){ + 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; + 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]); +} + +/** + * 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)){ + return; // wrong checksum + } + buf += 7; // skip header + if(*buf == ','){ // time unknown + GPS_status = GPS_WAIT; + return; + } + ptr = ustrchr(buf, ','); + *ptr++ = 0; + if(*ptr == 'A'){ + GPS_status = GPS_VALID; + }else{ + GPS_status = GPS_NOT_VALID; + } + set_time(buf); +} diff --git a/Timelapse_keyboard_only_lasers/GPS.h b/Timelapse_keyboard_only_lasers/GPS.h new file mode 100644 index 0000000..d400864 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/GPS.h @@ -0,0 +1,37 @@ +/* + * GPS.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 __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__ diff --git a/Timelapse_keyboard_only_lasers/Makefile b/Timelapse_keyboard_only_lasers/Makefile new file mode 100644 index 0000000..27c1b0a --- /dev/null +++ b/Timelapse_keyboard_only_lasers/Makefile @@ -0,0 +1,133 @@ +BINARY = timelapse +BOOTPORT ?= /dev/ttyUSB0 +BOOTSPEED ?= 115200 +# change this linking script depending on particular MCU model +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/Timelapse_keyboard_only_lasers/Readme.md b/Timelapse_keyboard_only_lasers/Readme.md new file mode 100644 index 0000000..f228a41 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/Readme.md @@ -0,0 +1,41 @@ +## Time-lapse as USB HID keyboard + +This tool allow to get precision time of events: four lasers with sensors (0->1 event), pressing switch-button (1->0 event). + +Just connect board to any device with USB keyboard support, after some time +(needed to establish GPS connection and precision timer setup) it will simulate +keyboard on which somebody types time of sensors' state changing + + +#### Sensors supprorted +* four lasers or other things, catch signal 0->1 +* simple switch-button, catch signal 1->0 + +To get precision time this tool use GPS module (NEO-6M) + +#### Connection diagram +| *Pin* | *Function* | +| :---: | :-------- | +| PA0 | Laser 1 | +| PA1 | Laser 2 | +| PA2 | GPS Rx (MCU Tx) | +| PA3 | GPS Tx (MCU Rx) | +| PA4 | GPS PPS signal | +| PA5 | Trigger (button) switch | +| PA6 | Input power measurement | +| PA7 | Laser 3 | +| PA8 | Laser 4 | +| PB9 | Beeper | +| * LEDS * | +| PA13 | Yellow LED1 - Laser1/4 found | +| PA15 | Yellow LED2 - PPS event | +| PB7 | Green LED1 - Laser3 found | +| PB8 | Green LED2 - power state: ON == 12V OK, BLINK == insufficient power | +| PB6 | Red LED1 - Laser2 found | +| PB7 | Red LED2 - GPS state: OFF == not ready, BLINK == need sync, ON == ready | + + +#### Powering devices +* To power up GPS module you can use +5V or +3.3V. +* Lasers & photosensors need 10..30V of power, I connect them to 12V +* Lasers' sensors connected to MCU through optocouples diff --git a/Timelapse_keyboard_only_lasers/adc.c b/Timelapse_keyboard_only_lasers/adc.c new file mode 100644 index 0000000..f8de5f6 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/adc.c @@ -0,0 +1,62 @@ +/* + * adc.c - functions for Sharp 2Y0A02 distance meter & photosensor + * + * 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 "adc.h" +#include "main.h" +#include "usbkeybrd.h" + +uint16_t ADC_value; // Value of ADC +uint16_t ADC_trig_val; // -//- at trigger time + +void init_adc_sensor(){ + // we will use ADC1 channel 0 for IR sensor & ADC1 channel 1 for laser's photoresistor + // 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, GPIO6); + 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 = 1; + 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 + uint8_t adc_channel_array = ADC_POWER_CHANNEL; + adc_set_regular_sequence(ADC1, 1, &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 + 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; +} diff --git a/Timelapse_keyboard_only_lasers/adc.h b/Timelapse_keyboard_only_lasers/adc.h new file mode 100644 index 0000000..558aaca --- /dev/null +++ b/Timelapse_keyboard_only_lasers/adc.h @@ -0,0 +1,45 @@ +/* + * adc.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 uint16_t ADC_value; + +// pause for noice removal +#define ADC_NOICE_TIMEOUT (5) + +// channel6 - 12V +#define ADC_POWER_CHANNEL (6) +// 10.8V - power alarm (resistor divider: 10kOhm : (3.0kOhm || zener), U/100=2/5*ADC_value) +// (11.15Vin == 2.25Vout) +#define POWER_ALRM_LEVEL (2705) +// critical voltage: approx 8V +#define POWER_CRITICAL_LEVEL (2000) +// 11.5V - power OK +#define GOOD_POWER_LEVEL (2880) + +void init_adc_sensor(); + +#endif // __SHARP_H__ diff --git a/Timelapse_keyboard_only_lasers/hardware_ini.c b/Timelapse_keyboard_only_lasers/hardware_ini.c new file mode 100644 index 0000000..2458fa2 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/hardware_ini.c @@ -0,0 +1,129 @@ +/* + * 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" +#include + +/** + * GPIO initialisaion: clocking + pins setup + */ +void GPIO_init(){ + // enable clocking for all ports, APB2 & AFIO (we need AFIO to remap JTAG pins) + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN | + RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | + RCC_APB2ENR_IOPEEN | RCC_APB2ENR_AFIOEN); + // turn off SWJ/JTAG + AFIO_MAPR = AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF; + /* + * 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, GPIO0 | GPIO1 | GPIO4 | GPIO5 | GPIO7 | GPIO8); + // PA0/1 and PA7/8 - Lasers + //gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO0 | GPIO1); + //gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO0 | GPIO1); + // EXTI0 - Laser1, EXTI1 - Laser2, EXTI4 - PPS, EXTI5 - Button, EXTI7 - Laser3, EXTI8 - Laser4 + // trigger on rising edge + exti_set_trigger(EXTI0 | EXTI1 | EXTI4 | EXTI5 | EXTI7 | EXTI8, EXTI_TRIGGER_RISING); + AFIO_EXTICR1 = 0; // EXTI 0-3 from PORTA + nvic_enable_irq(NVIC_EXTI4_IRQ); // PPS + nvic_enable_irq(NVIC_EXTI0_IRQ); // Laser1 + nvic_enable_irq(NVIC_EXTI1_IRQ); // Laser2 + nvic_enable_irq(NVIC_EXTI9_5_IRQ); // Button, Lasers 3/4 + exti_enable_request(EXTI0 | EXTI1 | EXTI4 | EXTI5 | EXTI7 | EXTI8); + // LEDS: opendrain output (&turn all OFF) + gpio_set(LEDS_Y_PORT, LEDS_Y1_PIN | LEDS_Y2_PIN); + gpio_set_mode(LEDS_Y_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, + LEDS_Y1_PIN | LEDS_Y2_PIN); + gpio_set(LEDS_G_PORT, LEDS_G1_PIN | LEDS_G2_PIN); + gpio_set_mode(LEDS_G_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, + LEDS_G1_PIN | LEDS_G2_PIN); + gpio_set(LEDS_R_PORT, LEDS_R1_PIN | LEDS_R2_PIN); + gpio_set_mode(LEDS_R_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, + LEDS_R1_PIN | LEDS_R2_PIN); + // beeper pin: push-pull + gpio_set(BEEPER_PORT, BEEPER_PIN); + gpio_set_mode(BEEPER_PORT, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, BEEPER_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); +*/ +} + +/** + * PA5 interrupt - print time at button-switch trigger and Lasers3/4 + * EXTI5 - Button, EXTI7 - Laser3, EXTI8 - Laser4 + */ +void exti9_5_isr(){ + if(EXTI_PR & EXTI5){ + if(trigger_ms[0] == DIDNT_TRIGGERED){ // prevent bounce + trigger_ms[0] = Timer; + memcpy(&trigger_time[0], ¤t_time, sizeof(curtime)); + } + EXTI_PR = EXTI5; + } + if(EXTI_PR & EXTI7){ + if(trigger_ms[3] == DIDNT_TRIGGERED){ // prevent bounce + trigger_ms[3] = Timer; + memcpy(&trigger_time[3], ¤t_time, sizeof(curtime)); + } + EXTI_PR = EXTI7; + } + if(EXTI_PR & EXTI8){ + if(trigger_ms[4] == DIDNT_TRIGGERED){ // prevent bounce + trigger_ms[4] = Timer; + memcpy(&trigger_time[4], ¤t_time, sizeof(curtime)); + } + EXTI_PR = EXTI8; + } +} + +void exti0_isr(){ // Laser1 + if(EXTI_PR & EXTI0){ + if(trigger_ms[1] == DIDNT_TRIGGERED){ // prevent bounce + trigger_ms[1] = Timer; + memcpy(&trigger_time[1], ¤t_time, sizeof(curtime)); + } + EXTI_PR = EXTI0; + } +} + +void exti1_isr(){ // Laser2 +// if(EXTI_PR & EXTI1){ + if(trigger_ms[2] == DIDNT_TRIGGERED){ // prevent bounce + trigger_ms[2] = Timer; + memcpy(&trigger_time[2], ¤t_time, sizeof(curtime)); + } + EXTI_PR = EXTI1; + //} +} diff --git a/Timelapse_keyboard_only_lasers/hardware_ini.h b/Timelapse_keyboard_only_lasers/hardware_ini.h new file mode 100644 index 0000000..7ca578f --- /dev/null +++ b/Timelapse_keyboard_only_lasers/hardware_ini.h @@ -0,0 +1,75 @@ +/* + * 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__ + +/* + * Timers: + * SysTick - system time + */ + +void GPIO_init(); +void SysTick_init(); + +// yellow LEDs: PA11, PA12; Y1 - trigr, Y2 - PPS +#define LEDS_Y_PORT GPIOA +#define LEDS_Y1_PIN GPIO13 +#define LEDS_Y2_PIN GPIO15 +// green LEDs: PB7, PB8; G1 - GPS rdy +#define LEDS_G_PORT GPIOB +#define LEDS_G1_PIN GPIO7 +#define LEDS_G2_PIN GPIO8 +// red LEDs: PB6, PB5; R2 - power +#define LEDS_R_PORT GPIOB +#define LEDS_R1_PIN GPIO6 +#define LEDS_R2_PIN GPIO5 +// beeper - PB9 +#define BEEPER_PORT GPIOB +#define BEEPER_PIN GPIO9 + + +/* + * 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/Timelapse_keyboard_only_lasers/keycodes.c b/Timelapse_keyboard_only_lasers/keycodes.c new file mode 100644 index 0000000..7d9d2f5 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/keycodes.c @@ -0,0 +1,74 @@ +/* + * keycodes.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 "keycodes.h" +/* + * Keyboard buffer: + * buf[0]: MOD + * buf[1]: reserved + * buf[2]..buf[7] - keycodes 1..6 + */ +static uint8_t buf[8] = {0,0,0,0,0,0,0,0}; + +#define _(x) (x|0x80) +// array for keycodes according to ASCII table; MSB is MOD_SHIFT flag +static const uint8_t keycodes[] = { + // space !"#$%&' + KEY_SPACE, _(KEY_1), _(KEY_QUOTE), _(KEY_3), _(KEY_4), _(KEY_5), _(KEY_7), KEY_QUOTE, + // ()*+,-./ + _(KEY_9), _(KEY_0), _(KEY_8), _(KEY_EQUAL), KEY_COMMA, KEY_MINUS, KEY_PERIOD, KEY_SLASH, + // 0..9 + 39, 30, 31, 32, 33, 34, 35, 36, 37, 38, + // :;<=>?@ + _(KEY_SEMICOLON), KEY_SEMICOLON, _(KEY_COMMA), KEY_EQUAL, _(KEY_PERIOD), _(KEY_SLASH), _(KEY_2), + // A..Z: for a in $(seq 0 25); do printf "$((a+132)),"; done + 132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157, + // [\]^_` + KEY_LEFT_BRACE, KEY_BACKSLASH, KEY_RIGHT_BRACE, _(KEY_6), _(KEY_MINUS), KEY_TILDE, + // a..z: for a in $(seq 0 25); do printf "$((a+4)),"; done + 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29, + // {|}~ + _(KEY_LEFT_BRACE), _(KEY_BACKSLASH), _(KEY_RIGHT_BRACE), _(KEY_TILDE) +}; + +uint8_t *set_key_buf(uint8_t MOD, uint8_t KEY){ + buf[0] = MOD; + buf[2] = KEY; + return buf; +} + +/** + * return buffer for sending symbol "ltr" with addition modificator mod + */ +uint8_t *press_key_mod(char ltr, uint8_t mod){ + uint8_t MOD = 0; + uint8_t KEY = 0; + if(ltr > 31){ + KEY = keycodes[ltr - 32]; + if(KEY & 0x80){ + MOD = MOD_SHIFT; + KEY &= 0x7f; + } + }else if (ltr == '\n') KEY = KEY_ENTER; + buf[0] = MOD | mod; + buf[2] = KEY; + return buf; +} diff --git a/Timelapse_keyboard_only_lasers/keycodes.h b/Timelapse_keyboard_only_lasers/keycodes.h new file mode 100644 index 0000000..98a2fa1 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/keycodes.h @@ -0,0 +1,138 @@ +/* + * keycodes.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 __KEYKODES_H__ +#define __KEYKODES_H__ + +#include + +uint8_t *set_key_buf(uint8_t MOD, uint8_t KEY); +#define release_key() set_key_buf(0,0) +uint8_t *press_key_mod(char key, uint8_t mod); +#define press_key(k) press_key_mod(k, 0) + +#define MOD_CTRL 0x01 +#define MOD_SHIFT 0x02 +#define MOD_ALT 0x04 +#define MOD_GUI 0x08 + +#define LEFT(mod) (mod) +#define RIGHT(mod) ((mod << 4)) + +#define KEY_A 4 +#define KEY_B 5 +#define KEY_C 6 +#define KEY_D 7 +#define KEY_E 8 +#define KEY_F 9 +#define KEY_G 10 +#define KEY_H 11 +#define KEY_I 12 +#define KEY_J 13 +#define KEY_K 14 +#define KEY_L 15 +#define KEY_M 16 +#define KEY_N 17 +#define KEY_O 18 +#define KEY_P 19 +#define KEY_Q 20 +#define KEY_R 21 +#define KEY_S 22 +#define KEY_T 23 +#define KEY_U 24 +#define KEY_V 25 +#define KEY_W 26 +#define KEY_X 27 +#define KEY_Y 28 +#define KEY_Z 29 +#define KEY_1 30 +#define KEY_2 31 +#define KEY_3 32 +#define KEY_4 33 +#define KEY_5 34 +#define KEY_6 35 +#define KEY_7 36 +#define KEY_8 37 +#define KEY_9 38 +#define KEY_0 39 +#define KEY_ENTER 40 +#define KEY_ESC 41 +#define KEY_BACKSPACE 42 +#define KEY_TAB 43 +#define KEY_SPACE 44 +#define KEY_MINUS 45 +#define KEY_EQUAL 46 +#define KEY_LEFT_BRACE 47 +#define KEY_RIGHT_BRACE 48 +#define KEY_BACKSLASH 49 +#define KEY_NUMBER 50 +#define KEY_SEMICOLON 51 +#define KEY_QUOTE 52 +#define KEY_TILDE 53 +#define KEY_COMMA 54 +#define KEY_PERIOD 55 +#define KEY_SLASH 56 +#define KEY_CAPS_LOCK 57 +#define KEY_F1 58 +#define KEY_F2 59 +#define KEY_F3 60 +#define KEY_F4 61 +#define KEY_F5 62 +#define KEY_F6 63 +#define KEY_F7 64 +#define KEY_F8 65 +#define KEY_F9 66 +#define KEY_F10 67 +#define KEY_F11 68 +#define KEY_F12 69 +#define KEY_PRINTSCREEN 70 +#define KEY_SCROLL_LOCK 71 +#define KEY_PAUSE 72 +#define KEY_INSERT 73 +#define KEY_HOME 74 +#define KEY_PAGE_UP 75 +#define KEY_DELETE 76 +#define KEY_END 77 +#define KEY_PAGE_DOWN 78 +#define KEY_RIGHT 79 +#define KEY_LEFT 80 +#define KEY_DOWN 81 +#define KEY_UP 82 +#define KEY_NUM_LOCK 83 +#define KEYPAD_SLASH 84 +#define KEYPAD_ASTERIX 85 +#define KEYPAD_MINUS 86 +#define KEYPAD_PLUS 87 +#define KEYPAD_ENTER 88 +#define KEYPAD_1 89 +#define KEYPAD_2 90 +#define KEYPAD_3 91 +#define KEYPAD_4 92 +#define KEYPAD_5 93 +#define KEYPAD_6 94 +#define KEYPAD_7 95 +#define KEYPAD_8 96 +#define KEYPAD_9 97 +#define KEYPAD_0 98 +#define KEYPAD_PERIOD 99 + +#endif // __KEYKODES_H__ diff --git a/Timelapse_keyboard_only_lasers/ld/devices.data b/Timelapse_keyboard_only_lasers/ld/devices.data new file mode 100644 index 0000000..7f29538 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/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/Timelapse_keyboard_only_lasers/ld/stm32f103x4.ld b/Timelapse_keyboard_only_lasers/ld/stm32f103x4.ld new file mode 100644 index 0000000..efed65e --- /dev/null +++ b/Timelapse_keyboard_only_lasers/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/Timelapse_keyboard_only_lasers/ld/stm32f103x6.ld b/Timelapse_keyboard_only_lasers/ld/stm32f103x6.ld new file mode 100644 index 0000000..13f05f9 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/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/Timelapse_keyboard_only_lasers/ld/stm32f103x8.ld b/Timelapse_keyboard_only_lasers/ld/stm32f103x8.ld new file mode 100644 index 0000000..2c4640f --- /dev/null +++ b/Timelapse_keyboard_only_lasers/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/Timelapse_keyboard_only_lasers/ld/stm32f103xB.ld b/Timelapse_keyboard_only_lasers/ld/stm32f103xB.ld new file mode 100644 index 0000000..138444d --- /dev/null +++ b/Timelapse_keyboard_only_lasers/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/Timelapse_keyboard_only_lasers/ld/stm32f103xC.ld b/Timelapse_keyboard_only_lasers/ld/stm32f103xC.ld new file mode 100644 index 0000000..fda76bf --- /dev/null +++ b/Timelapse_keyboard_only_lasers/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/Timelapse_keyboard_only_lasers/ld/stm32f103xD.ld b/Timelapse_keyboard_only_lasers/ld/stm32f103xD.ld new file mode 100644 index 0000000..0f996c2 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/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/Timelapse_keyboard_only_lasers/ld/stm32f103xE.ld b/Timelapse_keyboard_only_lasers/ld/stm32f103xE.ld new file mode 100644 index 0000000..b0fcb69 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/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/Timelapse_keyboard_only_lasers/ld/stm32f103xF.ld b/Timelapse_keyboard_only_lasers/ld/stm32f103xF.ld new file mode 100644 index 0000000..62d47db --- /dev/null +++ b/Timelapse_keyboard_only_lasers/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/Timelapse_keyboard_only_lasers/ld/stm32f103xG.ld b/Timelapse_keyboard_only_lasers/ld/stm32f103xG.ld new file mode 100644 index 0000000..0c0c968 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/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/Timelapse_keyboard_only_lasers/main.c b/Timelapse_keyboard_only_lasers/main.c new file mode 100644 index 0000000..b656100 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/main.c @@ -0,0 +1,311 @@ +/* + * main.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 "main.h" +#include "usbkeybrd.h" +#include "hardware_ini.h" +#include "uart.h" +#include "GPS.h" +#include "adc.h" +#include // independent watchdog + +volatile uint32_t Timer = 0; // global timer (milliseconds) +volatile uint32_t msctr = 0; // global milliseconds for different purposes +volatile int32_t systick_val = 0; +volatile int32_t timer_val = 0; +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; + +#define TMNOTINI {25,61,61} +curtime current_time = TMNOTINI; + +// 0 - Button, 1..4 - Lasers1..4 +curtime trigger_time[5] = {TMNOTINI, TMNOTINI, TMNOTINI, TMNOTINI, TMNOTINI}; +uint32_t trigger_ms[5] = {DIDNT_TRIGGERED, DIDNT_TRIGGERED, DIDNT_TRIGGERED, DIDNT_TRIGGERED, 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(void){ + uint8_t *string; // string from UART2 & pointer to last full GPS answer + uint8_t lastGPSans[UART_BUF_DATA_SIZE] = {0}; + int i; + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + // init systick (1ms) + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); // Systyck: 72/8=9MHz + systick_set_reload(STK_RVR_DEFAULT_VAL); // 9000 pulses: 1kHz + systick_interrupt_enable(); + systick_counter_enable(); + + GPIO_init(); +/* + // if PC11 connected to usb 1.5kOhm pull-up through transistor + rcc_periph_clock_enable(RCC_GPIOC); + gpio_set(GPIOC, GPIO11); + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO11); +*/ + usb_disconnect(); // turn off USB while initializing all + usbkeybrd_setup(); + UART_init(USART2); // init GPS UART + + usb_connect(); // turn on USB + GPS_send_start_seq(); + init_adc_sensor(); + // time (in milliseconds from MCU start) for trigger, adc & power LED status; power LED blink interval + // blink time: (1000ms - powerLEDblink) - LED ON + // GPSstatus_tm - timer for blinking by GPS LED if there's no GPS after timer is good + // powerLEDblink - LED blinking time (depends on power level) + uint32_t usbkbrdtm = 0, trigrtm = 0, powerLEDtm = 0, GPSstatus_tm = 0, powerLEDblink = 1; + // istriggered == 1 after ANY trigger's event (set it to 1 at start to prevent false events) + // GPSLEDblink - GPS LED blinking + uint8_t istriggered = 1, GPSLEDblink = 0; + iwdg_set_period_ms(50); // set watchdog timeout to 50ms + iwdg_start(); + while(1){ + if(Timer == 500) // turn off PPS LED after 500ms + gpio_set(LEDS_Y_PORT, LEDS_Y2_PIN); + poll_usbkeybrd(); + if(usbkbrdtm != msctr){ // process USB not frequently than once per 1ms + process_usbkbrd(); + usbkbrdtm = msctr; + } + if((string = check_UART2())){ + memcpy(lastGPSans, string, UART_BUF_DATA_SIZE); + GPS_parse_answer(string); + } + if(GPIO_ODR(GPIOA) & GPIO0 || GPIO_ODR(GPIOA) & GPIO8 ){ // Laser 1/4 shines + gpio_clear(LEDS_Y_PORT, LEDS_Y1_PIN); + }else{ + gpio_set(LEDS_Y_PORT, LEDS_Y1_PIN); + } + if(GPIO_ODR(GPIOA) & GPIO1){ // Laser 2 shines + gpio_clear(LEDS_R_PORT, LEDS_R1_PIN); + }else{ + gpio_set(LEDS_R_PORT, LEDS_R1_PIN); + } + if(GPIO_ODR(GPIOA) & GPIO7){ // Laser 3 shines + gpio_clear(LEDS_G_PORT, LEDS_G1_PIN); + }else{ + gpio_set(LEDS_G_PORT, LEDS_G1_PIN); + } + if(istriggered){ // there was any trigger event + if(msctr - trigrtm > TRIGGER_DELAY || trigrtm > msctr){ // turn off LED & beeper + istriggered = 0; + gpio_set(BEEPER_PORT, BEEPER_PIN); + for(i = 0; i < 5; ++i){ + if(trigger_ms[i] != DIDNT_TRIGGERED){ // show all messages + P("Event"); + put_char_to_buf('0' + i); + P(" time: "); + print_time(&(trigger_time[i]), trigger_ms[i]); + trigger_ms[i] = DIDNT_TRIGGERED; + } + } + } + }else{ + for(i = 0; i < 5; ++i){ + if(trigger_ms[i] != DIDNT_TRIGGERED){ // Control Button pressed or Lasers shadows + trigrtm = msctr; + istriggered = 1; + /*if(*lastGPSans){ + P("GPS last message: "); + send_msg((char*)lastGPSans); + newline(); + }*/ + } + } + if(istriggered){ // turn on beeper + gpio_clear(BEEPER_PORT, BEEPER_PIN); + } + } + // check 12V power level (once per 1ms) + if(powerLEDtm != msctr){ + uint16_t _12V = ADC_value; + if(_12V < GOOD_POWER_LEVEL){ // insufficient power? - blink LED R2 + // calculate blink time only if there's [was] too low level + if(_12V < POWER_ALRM_LEVEL || powerLEDblink){ + powerLEDblink = GOOD_POWER_LEVEL - _12V; + // critical level: power LED is almost OFF + if(_12V < POWER_CRITICAL_LEVEL) powerLEDblink = 990; + } + }else{ // power restored - LED G2 shines + if(powerLEDblink){ + gpio_clear(LEDS_G_PORT, LEDS_G2_PIN); + powerLEDblink = 0; + } + powerLEDtm = msctr; + } + if(powerLEDblink){ + if(GPIO_ODR(LEDS_G_PORT) & LEDS_G2_PIN){ // LED is OFF + if(msctr - powerLEDtm > powerLEDblink || msctr < powerLEDtm){ // turn LED ON + powerLEDtm = msctr; + gpio_clear(LEDS_G_PORT, LEDS_G2_PIN); + } + }else{ + if(msctr - powerLEDtm > (1000 - powerLEDblink) || msctr < powerLEDtm){ // turn LED OFF + powerLEDtm = msctr; + gpio_set(LEDS_G_PORT, LEDS_G2_PIN); + } + } + } + } + // check GPS status to turn on/off GPS LED + if(current_time.H < 24){ // timer OK + if((GPS_status != GPS_VALID) || need_sync){ + GPSLEDblink = 1; + }else{ + GPSLEDblink = 0; + if((GPIO_ODR(LEDS_R_PORT) & LEDS_R2_PIN) == 0) + gpio_clear(LEDS_R_PORT, LEDS_R2_PIN); // turn ON R2 LED + } + if(GPSLEDblink){ + if(msctr - GPSstatus_tm > 500 || msctr < GPSstatus_tm){ + GPSstatus_tm = msctr; + if(GPIO_ODR(LEDS_R_PORT) & LEDS_R2_PIN){ // LED is OFF + gpio_clear(LEDS_R_PORT, LEDS_R2_PIN); + }else{ + gpio_set(LEDS_R_PORT, LEDS_R2_PIN); + } + } + } + }else{ // something bad with timer - turn OFF R2 LED + if(!(GPIO_ODR(LEDS_R_PORT) & LEDS_R2_PIN)){ + gpio_set(LEDS_R_PORT, LEDS_R2_PIN); + } + } + iwdg_reset(); // reset watchdog + } +} + + +/** + * 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(); + } +} +// 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){ + gpio_clear(LEDS_Y_PORT, LEDS_Y2_PIN); + // 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(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; + } +} + +/** + * 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) put_char_to_buf('0'); + print_int(H); put_char_to_buf(':'); + if(M < 10) put_char_to_buf('0'); + print_int(M); put_char_to_buf(':'); + if(S < 10) put_char_to_buf('0'); + print_int(S); put_char_to_buf('.'); + if(T < 100) put_char_to_buf('0'); + if(T < 10) put_char_to_buf('0'); + print_int(T); + P(", "); + S += H*3600 + M*60; + print_int(S); + put_char_to_buf('.'); + if(T < 100) put_char_to_buf('0'); + if(T < 10) put_char_to_buf('0'); + print_int(T); + if(GPS_status == GPS_NOT_VALID) P(" (not valid)"); + if(need_sync) P(" need synchronisation"); + newline(); +} diff --git a/Timelapse_keyboard_only_lasers/main.h b/Timelapse_keyboard_only_lasers/main.h new file mode 100644 index 0000000..1565652 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/main.h @@ -0,0 +1,75 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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) + +// debounce delay: .4s +#define TRIGGER_DELAY (400) + +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 curtime trigger_time[]; +extern uint32_t trigger_ms[]; + +extern volatile int need_sync; + +void set_time(uint8_t *buf); + +void print_time(curtime *T, uint32_t m); + +#endif // __MAIN_H__ + diff --git a/Timelapse_keyboard_only_lasers/timelapse.bin b/Timelapse_keyboard_only_lasers/timelapse.bin new file mode 100755 index 0000000000000000000000000000000000000000..0a8b7068cba612a4ebe9b3c844714bb8aa64d913 GIT binary patch literal 9896 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 literal 0 HcmV?d00001 diff --git a/Timelapse_keyboard_only_lasers/uart.c b/Timelapse_keyboard_only_lasers/uart.c new file mode 100644 index 0000000..ef4fe36 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/uart.c @@ -0,0 +1,247 @@ +/* + * uart.c - functions to work with UART + * + * 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 "uart.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); +} + + +/** + * 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 +} diff --git a/Timelapse_keyboard_only_lasers/uart.h b/Timelapse_keyboard_only_lasers/uart.h new file mode 100644 index 0000000..85715ca --- /dev/null +++ b/Timelapse_keyboard_only_lasers/uart.h @@ -0,0 +1,46 @@ +/* + * uart.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 __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__ diff --git a/Timelapse_keyboard_only_lasers/usbkeybrd.c b/Timelapse_keyboard_only_lasers/usbkeybrd.c new file mode 100644 index 0000000..b5b7a77 --- /dev/null +++ b/Timelapse_keyboard_only_lasers/usbkeybrd.c @@ -0,0 +1,276 @@ +/* + * usbkeybrd.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 "usbkeybrd.h" +#include "keycodes.h" + +#define BUFLEN (1024) +static char sendbuf[BUFLEN]; +static char *msg_start = sendbuf, *msg_end = sendbuf; +static const char *buf_end = sendbuf+BUFLEN; + +usbd_device *usbd_dev; + +const struct usb_device_descriptor dev = { + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = 64, +// 0x045E 0x005C - Microsoft Office Keyboard (106/109) + .idVendor = 0x045E, + .idProduct = 0x005C, + .bcdDevice = 0x0200, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1, +}; + +static const uint8_t hid_report_descriptor[] = { + 0x05, 0x01, /* Usage Page (Generic Desktop) */ + 0x09, 0x06, /* Usage (Keyboard) */ + 0xA1, 0x01, /* Collection (Application) */ +// 0x85, 0x02, /* Report ID */ + 0x05, 0x07, /* Usage (Key codes) */ + 0x19, 0xE0, /* Usage Minimum (224) */ + 0x29, 0xE7, /* Usage Maximum (231) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0x75, 0x01, /* Report Size (1) */ + 0x95, 0x08, /* Report Count (8) */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + 0x95, 0x01, /* Report Count (1) */ + 0x75, 0x08, /* Report Size (8) */ + 0x81, 0x01, /* Input (Constant) ;5 bit padding */ + 0x95, 0x05, /* Report Count (5) */ + 0x75, 0x01, /* Report Size (1) */ + 0x05, 0x08, /* Usage Page (Page# for LEDs) */ + 0x19, 0x01, /* Usage Minimum (01) */ + 0x29, 0x05, /* Usage Maximum (05) */ + 0x91, 0x02, /* Output (Data, Variable, Absolute) */ + 0x95, 0x01, /* Report Count (1) */ + 0x75, 0x03, /* Report Size (3) */ + 0x91, 0x01, /* Output (Constant) */ + 0x95, 0x06, /* Report Count (1) */ + 0x75, 0x08, /* Report Size (3) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x65, /* Logical Maximum (101) */ + 0x05, 0x07, /* Usage (Key codes) */ + 0x19, 0x00, /* Usage Minimum (00) */ + 0x29, 0x65, /* Usage Maximum (101) */ + 0x81, 0x00, /* Input (Data, Array) */ + 0x09, 0x05, /* Usage (Vendor Defined) */ + 0x15, 0x00, /* Logical Minimum (0)) */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255)) */ + 0x75, 0x08, /* Report Count (2)) */ + 0x95, 0x02, /* Report Size (8 bit)) */ + 0xB1, 0x02, /* Feature (Data, Variable, Absolute) */ + 0xC0 /* End Collection,End Collection */ +}; + +static const struct { + struct usb_hid_descriptor hid_descriptor; + struct { + uint8_t bReportDescriptorType; + uint16_t wDescriptorLength; + } __attribute__((packed)) hid_report; +} __attribute__((packed)) hid_function = { + .hid_descriptor = { + .bLength = sizeof(hid_function), + .bDescriptorType = USB_DT_HID, + .bcdHID = 0x0100, + .bCountryCode = 0, + .bNumDescriptors = 1, + }, + .hid_report = { + .bReportDescriptorType = USB_DT_REPORT, + .wDescriptorLength = sizeof(hid_report_descriptor), + }, +}; + +const struct usb_endpoint_descriptor hid_endpoint = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x81, + .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, + .wMaxPacketSize = 8, + .bInterval = 0x10, +}; + +const struct usb_interface_descriptor hid_iface = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_HID, + .bInterfaceSubClass = 1, // boot + .bInterfaceProtocol = 1, // keyboard + .iInterface = 0, + + .endpoint = &hid_endpoint, + + .extra = &hid_function, + .extralen = sizeof(hid_function), +}; + +const struct usb_interface ifaces[] = {{ + .num_altsetting = 1, + .altsetting = &hid_iface, +}}; + +const struct usb_config_descriptor config = { + .bLength = USB_DT_CONFIGURATION_SIZE, + .bDescriptorType = USB_DT_CONFIGURATION, + .wTotalLength = 0, + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0xC0, + .bMaxPower = 0x32, + + .interface = ifaces, +}; + +static const char *usb_strings[] = { + "Timelapse keyboard", + "EEV", + "v01", +}; + +/* Buffer to be used for control requests. */ +uint8_t usbd_control_buffer[128]; +static int got_config = 0; +static int hid_control_request(usbd_device *usbddev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len, + void (**complete)(usbd_device *usbddev, struct usb_setup_data *req)){ + (void)complete; + (void)usbddev; + + if ((req->bmRequestType != 0x81) || + (req->bRequest != USB_REQ_GET_DESCRIPTOR) || + (req->wValue != 0x2200)) + return 0; + + *buf = (uint8_t *)hid_report_descriptor; + *len = sizeof(hid_report_descriptor); + got_config = 1; + return 1; +} + +void hid_set_config(usbd_device *usbddev, uint16_t wValue){ + (void)wValue; + (void)usbddev; + usbd_ep_setup(usbd_dev, 0x81, USB_ENDPOINT_ATTR_INTERRUPT, 4, NULL); + usbd_register_control_callback( + usbddev, + USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, + hid_control_request); +} + +void usbkeybrd_setup(){ + usbd_dev = usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings, 3, usbd_control_buffer, sizeof(usbd_control_buffer)); + usbd_register_set_config_callback(usbd_dev, hid_set_config); +} + +void put_char_to_buf(char ch){ + *(msg_end++) = ch; + if(msg_end == buf_end) + msg_end = sendbuf; +} + +/** + * put data into keyboard buffer + * THERE's NO DATA CORRUPTION CONTROL HERE!!! + */ +void send_msg(char *msg){ + while(*msg){ + put_char_to_buf(*(msg++)); + } +} +/* +void newline(){ + put_char_to_buf('\n'); +}*/ + +/** + * send data from keyboard buffer + */ +void process_usbkbrd(){ + if(!got_config) return; // don't allow sending messages until first connection - to prevent hangs + static uint8_t pressed = 0; + if(pressed){ // the keyboard was "pressed" + if(8 == usbd_ep_write_packet(usbd_dev, 0x81, release_key(), 8)) + pressed = 0; + }else if(msg_start != msg_end){ // we need to send keypress event + if(8 == usbd_ep_write_packet(usbd_dev, 0x81, press_key(*msg_start), 8)){ + if(++msg_start == buf_end) + msg_start = sendbuf; + pressed = 1; + } + }else return; +} + +/** + * 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){ + inline void putc(char c){ + if(c < 10) + put_char_to_buf(c + '0'); + else + put_char_to_buf(c + 'a' - 10); + } + put_char_to_buf('0'); + put_char_to_buf('x'); + 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){ + char buf[10]; + int32_t L = 0; + if(N < 0){ + put_char_to_buf('-'); + N = -N; + } + if(N){ + while(N){ + buf[L++] = N % 10 + '0'; + N /= 10; + } + while(L--) put_char_to_buf(buf[L]); + }else put_char_to_buf('0'); +} + diff --git a/Timelapse_keyboard_only_lasers/usbkeybrd.h b/Timelapse_keyboard_only_lasers/usbkeybrd.h new file mode 100644 index 0000000..ab3de8f --- /dev/null +++ b/Timelapse_keyboard_only_lasers/usbkeybrd.h @@ -0,0 +1,44 @@ +/* + * usbkeybrd.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 __USBKEYBRD_H__ +#define __USBKEYBRD_H__ + +#include "main.h" + +extern usbd_device *usbd_dev; + +void process_usbkbrd(); +void send_msg(char *msg); +void put_char_to_buf(char ch); +#define P(x) send_msg(x) +void usbkeybrd_setup(); + +void print_hex(uint8_t *buff, uint8_t l); +void print_int(int32_t N); + +//void newline(); +#define newline() do{put_char_to_buf('\n');}while(0) + +#define poll_usbkeybrd() usbd_poll(usbd_dev) + +#endif // __USBKEYBRD_H__