From 5c5bd9468e7e00019d11310c268894e0177b192c Mon Sep 17 00:00:00 2001 From: eddyem Date: Tue, 14 Feb 2017 22:16:58 +0300 Subject: [PATCH] Add Morze --- F0-nolib/Readme.md | 9 ++ F0-nolib/morze/Makefile | 137 +++++++++++++++++++++++ F0-nolib/morze/Readme.md | 8 ++ F0-nolib/morze/ld/stm32f030f.ld | 12 ++ F0-nolib/morze/main.c | 122 +++++++++++++++++++++ F0-nolib/morze/morse.c | 188 ++++++++++++++++++++++++++++++++ F0-nolib/morze/morse.h | 51 +++++++++ F0-nolib/morze/morze.bin | Bin 0 -> 2216 bytes F0-nolib/morze/usart.c | 161 +++++++++++++++++++++++++++ F0-nolib/morze/usart.h | 51 +++++++++ 10 files changed, 739 insertions(+) create mode 100644 F0-nolib/Readme.md create mode 100644 F0-nolib/morze/Makefile create mode 100644 F0-nolib/morze/Readme.md create mode 100644 F0-nolib/morze/ld/stm32f030f.ld create mode 100644 F0-nolib/morze/main.c create mode 100644 F0-nolib/morze/morse.c create mode 100644 F0-nolib/morze/morse.h create mode 100755 F0-nolib/morze/morze.bin create mode 100644 F0-nolib/morze/usart.c create mode 100644 F0-nolib/morze/usart.h diff --git a/F0-nolib/Readme.md b/F0-nolib/Readme.md new file mode 100644 index 0000000..7e575fd --- /dev/null +++ b/F0-nolib/Readme.md @@ -0,0 +1,9 @@ +Samples for STM32F042-nucleo and chinese STM32F030-based devboard +================================= + +This directory contains examples for F0 without any library + +- blink - simple LED blink +- uart - USART over DMA with hardware end-of-string detection +- uart_blink - code for STM32F030F4, echo data on USART1 and blink LEDS on PA4 and PA5 +- morze - for STM32F030, echo data from USART1 on TIM3CH1 (PA6) as Morze code diff --git a/F0-nolib/morze/Makefile b/F0-nolib/morze/Makefile new file mode 100644 index 0000000..f85ea34 --- /dev/null +++ b/F0-nolib/morze/Makefile @@ -0,0 +1,137 @@ +BINARY = morze +BOOTPORT ?= /dev/ttyUSB0 +BOOTSPEED ?= 115200 +# MCU FAMILY +FAMILY = F0 +# MCU code +MCU = F030x4 +DEFS = -DEBUG +# change this linking script depending on particular MCU model, +# for example, if you have STM32F103VBT6, you should write: +LDSCRIPT = ld/stm32f030f.ld + +INDEPENDENT_HEADERS= + +FP_FLAGS ?= -msoft-float +ASM_FLAGS = -mthumb -mcpu=cortex-m0 -march=armv6-m -mtune=cortex-m0 +ARCH_FLAGS = $(ASM_FLAGS) $(FP_FLAGS) + +############################################################################### +# Executables +PREFIX ?= /opt/bin/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 +OBJDIR = mk +LDSCRIPT ?= $(BINARY).ld +SRC := $(wildcard *.c) +OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o)) +STARTUP = $(OBJDIR)/startup.o +OBJS += $(STARTUP) +DEPS := $(OBJS:.o=.d) + +INC_DIR ?= ../inc + +INCLUDE := -I$(INC_DIR)/F0 -I$(INC_DIR)/cm +LIB_DIR := $(INC_DIR)/ld + +############################################################################### +# C flags +CFLAGS += -O2 -g -MD -D__thumb2__=1 +CFLAGS += -Wall -Werror -Wextra -Wshadow -Wimplicit-function-declaration +CFLAGS += -Wredundant-decls $(INCLUDE) +# -Wmissing-prototypes -Wstrict-prototypes +CFLAGS += -fno-common -ffunction-sections -fdata-sections + +############################################################################### +# Linker flags +LDFLAGS += --static -nostartfiles +#--specs=nano.specs +LDFLAGS += -L$(LIB_DIR) +LDFLAGS += -T$(LDSCRIPT) +LDFLAGS += -Wl,-Map=$(OBJDIR)/$(BINARY).map +LDFLAGS += -Wl,--gc-sections + +############################################################################### +# Used libraries +LDLIBS += -Wl,--start-group -lc -lgcc -Wl,--end-group +LDLIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) + +DEFS += -DSTM32$(FAMILY) -DSTM32$(MCU) + +#.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 list + +elf: $(ELF) +bin: $(BIN) +hex: $(HEX) +list: $(LIST) + +ifneq ($(MAKECMDGOALS),clean) +-include $(DEPS) +endif + +$(OBJDIR): + mkdir $(OBJDIR) + +$(STARTUP): $(INC_DIR)/startup/vector.c + $(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $< + +$(OBJDIR)/%.o: %.c + @echo " CC $<" + $(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $< + +#$(OBJDIR)/%.d: %.c $(OBJDIR) +# $(CC) -MM -MG $< | sed -e 's,^\([^:]*\)\.o[ ]*:,$(@D)/\1.o $(@D)/\1.d:,' >$@ + +$(BIN): $(ELF) + @echo " OBJCOPY $(BIN)" + $(OBJCOPY) -Obinary $(ELF) $(BIN) + +$(HEX): $(ELF) + @echo " OBJCOPY $(HEX)" + $(OBJCOPY) -Oihex $(ELF) $(HEX) + +$(LIST): $(ELF) + @echo " OBJDUMP $(LIST)" + $(OBJDUMP) -S $(ELF) > $(LIST) + +$(ELF): $(OBJDIR) $(OBJS) + @echo " LD $(ELF)" + $(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(ELF) + +clean: + @echo " CLEAN" + $(RM) $(OBJS) $(DEPS) $(ELF) $(HEX) $(LIST) $(OBJDIR)/*.map + @rmdir $(OBJDIR) 2>/dev/null || true + + +flash: $(BIN) + @echo " FLASH $(BIN)" + $(STFLASH) write $(BIN) 0x8000000 + +boot: $(BIN) + @echo " LOAD $(BIN) through bootloader" + $(STBOOT) -b$(BOOTSPEED) $(BOOTPORT) -w $(BIN) + +.PHONY: clean flash boot diff --git a/F0-nolib/morze/Readme.md b/F0-nolib/morze/Readme.md new file mode 100644 index 0000000..0c5d9d5 --- /dev/null +++ b/F0-nolib/morze/Readme.md @@ -0,0 +1,8 @@ +Code for STM32F030F4 chinese board + +Echo received by USART data as morze code (@ PA6, TIM3CH1) + +USART Rx by interrupts, Tx by DMA, Morze by timer3 with DMA @ each letter +- Toggle onboard green LED once per second. +- Echo received by USART1 data (not more than 64 bytes including '\n') on B115200 +- Morze text by dimmer diff --git a/F0-nolib/morze/ld/stm32f030f.ld b/F0-nolib/morze/ld/stm32f030f.ld new file mode 100644 index 0000000..f8b61f1 --- /dev/null +++ b/F0-nolib/morze/ld/stm32f030f.ld @@ -0,0 +1,12 @@ +/* Linker script for STM32F030f4, 16K flash, 4K RAM. */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 16K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 4K +} + +/* Include the common ld script. */ +INCLUDE stm32f0.ld + diff --git a/F0-nolib/morze/main.c b/F0-nolib/morze/main.c new file mode 100644 index 0000000..e63cb09 --- /dev/null +++ b/F0-nolib/morze/main.c @@ -0,0 +1,122 @@ +/* + * main.c + * + * Copyright 2017 Edward V. Emelianoff + * + * 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 "stm32f0.h" +#include "usart.h" +#include "morse.h" + +volatile uint32_t Tms = 0; + +/* Called when systick fires */ +void sys_tick_handler(void){ + ++Tms; +} + +static void gpio_setup(void){ + /* Enable clocks to the GPIO subsystems (A&B) */ + RCC->AHBENR |= RCC_AHBENR_GPIOAEN; + /* Set green leds (PA4 & PA6) as output; AF1 to enable timer on PA6 */ + GPIOA->MODER = GPIO_MODER_MODER4_O | GPIO_MODER_MODER6_AF; + GPIOA->AFR[0] |= 1<<24; // AF1 + GPIOA->OTYPER = 1 << 6; // PA6 - opendrain, PA4 - pushpull +} + +// Tim3_ch1 - PA6, 48MHz -> 1kHz +static void tim3_setup(){ + RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // enable clocking + RCC->AHBENR |= RCC_AHBENR_DMA1EN; + TIM3->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; // PWM mode 1: acive->inactive, preload enable + TIM3->PSC = 47999; // 1kHz + TIM3->ARR = WRD_GAP; + TIM3->CCR1 = 0; + TIM3->CCER = TIM_CCER_CC1P | TIM_CCER_CC1E; // turn it on, active low + TIM3->EGR |= TIM_EGR_UG; + // DMA ch3 - TIM3_UP + DMA1_Channel3->CPAR = (uint32_t)(&(TIM3->DMAR)); // TIM3_ch1 + DMA1_Channel3->CMAR = (uint32_t)(mbuff); + DMA1_Channel3->CNDTR = 0; + // memsiz 16bit, psiz 32bit, memincrement, from memory + DMA1_Channel3->CCR |= DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_1 + | DMA_CCR_MINC | DMA_CCR_DIR; + TIM3->DCR = (2 << 8) // three bytes + + (((uint32_t)&TIM3->ARR - (uint32_t)&TIM3->CR1) >> 2); + TIM3->DIER = TIM_DIER_UDE; // enable DMA requests + DMA1_Channel3->CCR |= DMA_CCR_TCIE; // enable TC interrupt +} + +char buftoping[256] = {0}, *nxtltr = buftoping; + +int main(void){ + uint32_t lastT = 0; // last time counter value + int L = 0; // length + char *txt; + sysreset(); + SysTick_Config(6000, 1); + gpio_setup(); + tim3_setup(); + USART1_config(); + int first = 1; // first letter in phrase + while (1){ + if(dmaflag){ + dmaflag = 0; + if(*nxtltr){ + DMA1_Channel3->CCR &= ~DMA_CCR_EN; + while(ALL_OK != usart1_send(nxtltr, 1)); + uint8_t x; + nxtltr = fillbuffer(nxtltr, &x); + if(x){ + DMA1_Channel3->CNDTR = 3 * x; + DMA1_Channel3->CCR |= DMA_CCR_EN; + //x += '0'; + //while(ALL_OK != usart1_send((char*)&x, 1)); + if(first){ // first letter in message + first = 0; + TIM3->CR1 |= TIM_CR1_CEN; + TIM3->EGR |= TIM_EGR_UG; // force update generation + } + } + }else{ + TIM3->CR1 &= ~TIM_CR1_CEN; // turn timer off + first = 1; + } + } + if(lastT > Tms || Tms - lastT > 499){ + pin_toggle(GPIOA, 1<<4); // blink by onboard LED once per second + lastT = Tms; + } + if(usart1rx()){ // usart1 received data, store in in buffer + L = usart1_getline(&txt); + if(L < 256 && !*nxtltr){ + memcpy(buftoping, txt, L); + buftoping[L] = 0; + nxtltr = buftoping; + dmaflag = 1; // + usart1_send("Send ", 5); + while(ALL_OK != usart1_send(txt, L)); + }else usart1_send("Please, wait\n", 13); + } + /* if(L){ // text waits for sending + if(ALL_OK == usart1_send(txt, L)){ + L = 0; + } + }*/ + } +} diff --git a/F0-nolib/morze/morse.c b/F0-nolib/morze/morse.c new file mode 100644 index 0000000..5b49764 --- /dev/null +++ b/F0-nolib/morze/morse.c @@ -0,0 +1,188 @@ +/* + * geany_encoding=koi8-r + * morse.c + * + * Copyright 2017 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 "stm32f0.h" +#include "morse.h" + +#define MAXPINGS (8) + +uint16_t mbuff[3*MAXPINGS]; +/* +32 (0x20) - 64 (0x40) - @ 96 (0x60) - ` 128 (0x80) - 160 (0xa0) - 192 (0xc0) - 224 (0xe0) - + 33 (0x21) - ! 65 (0x41) - A 97 (0x61) - a 129 (0x81) - 161 (0xa1) - 193 (0xc1) - 225 (0xe1) - + 34 (0x22) - " 66 (0x42) - B 98 (0x62) - b 130 (0x82) - 162 (0xa2) - 194 (0xc2) - 226 (0xe2) - + 35 (0x23) - # 67 (0x43) - C 99 (0x63) - c 131 (0x83) - 163 (0xa3) - 195 (0xc3) - 227 (0xe3) - + 36 (0x24) - $ 68 (0x44) - D 100 (0x64) - d 132 (0x84) - 164 (0xa4) - 196 (0xc4) - 228 (0xe4) - + 37 (0x25) - % 69 (0x45) - E 101 (0x65) - e 133 (0x85) - 165 (0xa5) - 197 (0xc5) - 229 (0xe5) - + 38 (0x26) - & 70 (0x46) - F 102 (0x66) - f 134 (0x86) - 166 (0xa6) - 198 (0xc6) - 230 (0xe6) - + 39 (0x27) - ' 71 (0x47) - G 103 (0x67) - g 135 (0x87) - 167 (0xa7) - 199 (0xc7) - 231 (0xe7) - + 40 (0x28) - ( 72 (0x48) - H 104 (0x68) - h 136 (0x88) - 168 (0xa8) - 200 (0xc8) - 232 (0xe8) - + 41 (0x29) - ) 73 (0x49) - I 105 (0x69) - i 137 (0x89) - 169 (0xa9) - 201 (0xc9) - 233 (0xe9) - + 42 (0x2a) - * 74 (0x4a) - J 106 (0x6a) - j 138 (0x8a) - 170 (0xaa) - 202 (0xca) - 234 (0xea) - + 43 (0x2b) - + 75 (0x4b) - K 107 (0x6b) - k 139 (0x8b) - 171 (0xab) - 203 (0xcb) - 235 (0xeb) - + 44 (0x2c) - , 76 (0x4c) - L 108 (0x6c) - l 140 (0x8c) - 172 (0xac) - 204 (0xcc) - 236 (0xec) - + 45 (0x2d) - - 77 (0x4d) - M 109 (0x6d) - m 141 (0x8d) - 173 (0xad) - 205 (0xcd) - 237 (0xed) - + 46 (0x2e) - . 78 (0x4e) - N 110 (0x6e) - n 142 (0x8e) - 174 (0xae) - 206 (0xce) - 238 (0xee) - + 47 (0x2f) - / 79 (0x4f) - O 111 (0x6f) - o 143 (0x8f) - 175 (0xaf) - 207 (0xcf) - 239 (0xef) - + 48 (0x30) - 0 80 (0x50) - P 112 (0x70) - p 144 (0x90) - 176 (0xb0) - 208 (0xd0) - 240 (0xf0) - + 49 (0x31) - 1 81 (0x51) - Q 113 (0x71) - q 145 (0x91) - 177 (0xb1) - 209 (0xd1) - 241 (0xf1) - + 50 (0x32) - 2 82 (0x52) - R 114 (0x72) - r 146 (0x92) - 178 (0xb2) - 210 (0xd2) - 242 (0xf2) - + 51 (0x33) - 3 83 (0x53) - S 115 (0x73) - s 147 (0x93) - 179 (0xb3) - 211 (0xd3) - 243 (0xf3) - + 52 (0x34) - 4 84 (0x54) - T 116 (0x74) - t 148 (0x94) - 180 (0xb4) - 212 (0xd4) - 244 (0xf4) - + 53 (0x35) - 5 85 (0x55) - U 117 (0x75) - u 149 (0x95) - 181 (0xb5) - 213 (0xd5) - 245 (0xf5) - + 54 (0x36) - 6 86 (0x56) - V 118 (0x76) - v 150 (0x96) - 182 (0xb6) - 214 (0xd6) - 246 (0xf6) - + 55 (0x37) - 7 87 (0x57) - W 119 (0x77) - w 151 (0x97) - 183 (0xb7) - 215 (0xd7) - 247 (0xf7) - + 56 (0x38) - 8 88 (0x58) - X 120 (0x78) - x 152 (0x98) - 184 (0xb8) - 216 (0xd8) - 248 (0xf8) - + 57 (0x39) - 9 89 (0x59) - Y 121 (0x79) - y 153 (0x99) - 185 (0xb9) - 217 (0xd9) - 249 (0xf9) - + 58 (0x3a) - : 90 (0x5a) - Z 122 (0x7a) - z 154 (0x9a) - 186 (0xba) - 218 (0xda) - 250 (0xfa) - + 59 (0x3b) - ; 91 (0x5b) - [ 123 (0x7b) - { 155 (0x9b) - 187 (0xbb) - 219 (0xdb) - 251 (0xfb) - + 60 (0x3c) - < 92 (0x5c) - \ 124 (0x7c) - | 156 (0x9c) - 188 (0xbc) - 220 (0xdc) - 252 (0xfc) - + 61 (0x3d) - = 93 (0x5d) - ] 125 (0x7d) - } 157 (0x9d) - 189 (0xbd) - 221 (0xdd) - 253 (0xfd) - + 62 (0x3e) - > 94 (0x5e) - ^ 126 (0x7e) - ~ 158 (0x9e) - 190 (0xbe) - 222 (0xde) - 254 (0xfe) - + 63 (0x3f) - ? 95 (0x5f) - _ 127 (0x7f) - 159 (0x9f) - 191 (0xbf) - 223 (0xdf) - 255 (0xff) - +*/ +// 1 - len in pings, 2 - pings (0 - dot, 1 - dash), reverse order +static const uint8_t ascii[] = { // sarting from space+1 + 6, 53, // ! -*-*-- + 6, 18, // " *-**-* + 5, 29, // # [no] -*--- + 7, 72, // $ ***-**- + 8, 86, // % [pc] *--*-*-* + 5, 2, // & *-*** + 6, 30, // ' *----* + 5, 13, // ( -*--* + 6, 45, // ) -*--*- + 7, 40, // * [str] ***-*-* + 5, 10, // + *-*-* + 6, 51, // , --**-- + 6, 33, // - -****- + 6, 42, // . *-*-*- + 5, 9, // / -**-* + 5, 31, // 0 ----- + 5, 30, // 1 *---- + 5, 28, // 2 **--- + 5, 24, // 3 ***-- + 5, 16, // 4 ****- + 5, 0, // 5 ***** + 5, 1, // 6 -**** + 5, 3, // 7 --*** + 5, 7, // 8 ---** + 5, 15, // 9 ----* + 6, 7, // : ---*** + 6, 21, // ; -*-*-* + 7, 2, // < [ls] *-***** + 5, 17, // = -***- + 6, 3, // > [gs] --**** + 6, 12, // ? **--** + 6, 22, // @ *--*-* + 2, 2, // a *- + 4, 1, // b -*** + 4, 5, // c -*-* + 3, 1, // d -** + 1, 0, // e * + 4, 4, // f **-* + 3, 3, // g --* + 4, 0, // h **** + 2, 0, // i ** + 4, 14, // j *--- + 3, 5, // k -*- + 4, 2, // l *-** + 2, 3, // m -- + 2, 1, // n -* + 3, 7, // o --- + 4, 6, // p *--* + 4, 11, // q --*- + 3, 2, // r *-* + 3, 0, // s *** + 1, 1, // t - + 3, 4, // u **- + 4, 8, // v ***- + 3, 6, // w *-- + 4, 9, // x -**- + 4, 13, // y -*-- + 4, 3, // z --** + 5, 13, // [ [(] + 6, 40, // \ [End of work] ***-*- // + 6, 45, // ] [)] + 7, 96, // ^ [hat] *****-- + 6, 44, // _ **--*- + 6, 30, // ` ['] + 2, 2, // a *- + 4, 1, // b -*** + 4, 5, // c -*-* + 3, 1, // d -** + 1, 0, // e * + 4, 4, // f **-* + 3, 3, // g --* + 4, 0, // h **** + 2, 0, // i ** + 4, 14, // j *--- + 3, 5, // k -*- + 4, 2, // l *-** + 2, 3, // m -- + 2, 1, // n -* + 3, 7, // o --- + 4, 6, // p *--* + 4, 11, // q --*- + 3, 2, // r *-* + 3, 0, // s *** + 1, 1, // t - + 3, 4, // u **- + 4, 8, // v ***- + 3, 6, // w *-- + 4, 9, // x -**- + 4, 13, // y -*-- + 4, 3, // z --** + 5, 13, // { [(] + 6, 30, // | ['] + 6, 45, // } [)] + 8, 37, // ~ [tld] -*-**-** +}; +/* + * I was too lazy +static const uint8_t koi8[] = { + +};*/ + +/** + * return next character in word + * @param str (i) - string to send + * @param len (o) - length of buffer/3 + */ +char *fillbuffer(char *str, uint8_t *len){ + const uint8_t *arr = NULL; + char ltr = *str++; + if(ltr > ' ' && ltr < 127){ arr = ascii; ltr -= '!'; }; + if(!arr){*len = 1; mbuff[0] = WRD_GAP+DASH_LEN; mbuff[2] = 0; return str;}; + ltr *= 2; + uint8_t i, N = arr[(uint8_t)ltr], code = arr[(uint8_t)ltr+1]; + uint16_t *ptr = mbuff; + for(i = 0; i < N; ++i){ + uint16_t L = DOT_LEN; + if(code & 1) L = DASH_LEN; + *ptr++ = L + SHRT_GAP; *ptr++ = 0; *ptr++ = L; + code >>= 1; + } + ptr[-3] += LTR_GAP; + *len = N; + return str; +} diff --git a/F0-nolib/morze/morse.h b/F0-nolib/morze/morse.h new file mode 100644 index 0000000..68eeed3 --- /dev/null +++ b/F0-nolib/morze/morse.h @@ -0,0 +1,51 @@ +/* + * geany_encoding=koi8-r + * morse.h + * + * Copyright 2017 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 __MORSE_H__ +#define __MORSE_H__ +#include + +/* +International Morse code is composed of five elements: + + short mark, dot or "dit" (): "dot duration" is one time unit long == 50ms + longer mark, dash or "dah" (): three time units long == 150ms + inter-element gap between the dots and dashes within a character: one dot duration or one unit long == 50ms + short gap (between letters): three time units long == 150ms + medium gap (between words): seven time units long == 350ms +*/ +// base timing (in ms) +#define DOT_LEN (75) +#define DASH_LEN (3*DOT_LEN) +#define SHRT_GAP (DOT_LEN) +// minus shr gap +#define LTR_GAP (2*DOT_LEN) +// minus ltr gap +#define WRD_GAP (4*DOT_LEN) + +extern uint16_t mbuff[]; +char *fillbuffer(char *ltr, uint8_t *len); + + +#endif // __MORSE_H__ diff --git a/F0-nolib/morze/morze.bin b/F0-nolib/morze/morze.bin new file mode 100755 index 0000000000000000000000000000000000000000..a4051d86c69417efa6131150c76ed9689d232fb7 GIT binary patch literal 2216 zcmbVMeQaA-6+icV`Nc^ZJFg9Xj^n(KEKTaP%s4?~8N>7IUTwc5%ST%hcM;cVqdjLE zi?jln1j6kYYSwj18&s_|>pFD;q;6;gA|cU8p_3+66k(^^lr$Y=0?9(O!fb47DD-h& z(Eb9o5|(~G_uYFw?)jZ_F8DzCjsW5_h;Ja^4nJ4tvtxJNOa5cy+T9Ir@ORg_n~(Ro z|MpRtf7^t4BlJU)ojPKw-K%q>5$_7o<#hF=Yz6b6oz7E}yD(!`78=s~V0G@jN3R4j zQ?MgcBq}He!+)A1o#U{{+Aco{qw>iXYpXv&iXUt}0HOSF{*}BC8x&tod{{C};mapG zJM!Vl_sVSV`R34(kIRc@Edwqo%4H9TOj@!@Orn#!7R~!`kEoUT-&uXK2uVG0DV(D35K(jQs-2IweD|P8>F_js+i|cK7#V4m9)l^G0U> z_tU=Ufl$k4nd+k>1NBd?v{WZR$kXOUGiHrk>t`I4*il;w@O zcH*{MrA77WHfudQc2eI5Z;d^)pC2=Fl3`>= z)1%gDI-0&pN9d9ov@e0**q4^+;R7}IJNI8iCN#V|R4&{kI?V2|_C9jTBznQz)3c|y z+lENA2)bf-Q+5g>yNe@c8W}%oNEFr-8>?CQ={mHnmzeV_A;oq+{o8Hk{OXiKA+iN^ zGjJvFV0ws3cC~9!fQYv^WDc5*8{b2@L9^Nz$^yoX*k=;_^53Sp%aG6U=>4Nw2Lo--4sVpTn((^I?mnY4PGOxF%3(P>SE$Ol`qp$L^EymBP(=0J$Ix?Xr z#rP351;iK`%j?H;tEAeP%@*~z8pi3mLVwWhbW8L~PR7oYCWs;%{xL<};5;Q!E5{mE zcC)o5b^P8_baQHj%C_q_uU}MVso%;&aM+*n#}~DFw~PDp+S}?91nD$nhTZPW;7&as z#0hhGaGbZCx(eogABl%Bzc!TD+`K-3HQaUDtjhdqt{^DyZcY1bXm2XD_O&LXcB^#^ zc8;_@(r8~W_wR%Vl!z|TCads5VeTs(foqS2b`2aOubbiC)w%JVkv-l>W3jRzTLJq} z!naHmXpvJ=pGc#<fPhD`lc?wqy#rF(A=DmuvcJF^U`Ga+$Q$Ss_|yH6xm+l^A&l z^eEv4?-*p2H45N@rKh-HMLZL)mxvh7Xq#Sz<`Wukd4 zoONAH7r<}JiK-$|JUyy?$WZA3_Vp0utN`^bU>xL!L*H&6xV0B?av>iT?l&~SM}t`KK&HWaLrEB_ZN^E}jT`}|5Zutvet zS!#e9V8QobR~6~nP9B!G+RgMa`)l;a_A9h(`#S$XeX*AlAC>C#GluVr&&kuW6lWvB zm2flYzYt01Yw)|_zxH#nbC@IB@*^YGq{S} + * + * 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 "usart.h" +#include // memcpy + +extern volatile uint32_t Tms; + +static int datalen[2] = {0,0}; // received data line length (including '\n') + +int linerdy = 0, // received data ready + dlen = 0, // length of data (including '\n') in current buffer + bufovr = 0, // input buffer overfull + txrdy = 1, // transmission done + dmaflag = 0 +; + +static int rbufno = 0; // current rbuf number +static char rbuf[2][UARTBUFSZ], tbuf[UARTBUFSZ]; // receive & transmit buffers +static char *recvdata = NULL; + +void USART1_config(){ + /* Enable the peripheral clock of GPIOA */ + RCC->AHBENR |= RCC_AHBENR_GPIOAEN; + /* GPIO configuration for USART1 signals */ + /* (1) Select AF mode (10) on PA9 and PA10 */ + /* (2) AF1 for USART1 signals */ + GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER9|GPIO_MODER_MODER10))\ + | (GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1); /* (1) */ + GPIOA->AFR[1] = (GPIOA->AFR[1] &~ (GPIO_AFRH_AFRH1 | GPIO_AFRH_AFRH2))\ + | (1 << (1 * 4)) | (1 << (2 * 4)); /* (2) */ + /* Enable the peripheral clock USART1 */ + RCC->APB2ENR |= RCC_APB2ENR_USART1EN; + /* Configure USART1 */ + /* (1) oversampling by 16, 115200 baud */ + /* (2) 8 data bit, 1 start bit, 1 stop bit, no parity */ + USART1->BRR = 480000 / 1152; /* (1) */ + USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; /* (2) */ + /* polling idle frame Transmission */ + while(!(USART1->ISR & USART_ISR_TC)){} + USART1->ICR |= USART_ICR_TCCF; /* clear TC flag */ + USART1->CR1 |= USART_CR1_RXNEIE; /* enable TC, TXE & RXNE interrupt */ + RCC->AHBENR |= RCC_AHBENR_DMA1EN; + DMA1_Channel2->CPAR = (uint32_t) &(USART1->TDR); // periph + DMA1_Channel2->CMAR = (uint32_t) tbuf; // mem + DMA1_Channel2->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq + USART1->CR3 = USART_CR3_DMAT; + NVIC_SetPriority(DMA1_Channel2_3_IRQn, 3); + NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); + /* Configure IT */ + /* (3) Set priority for USART1_IRQn */ + /* (4) Enable USART1_IRQn */ + NVIC_SetPriority(USART1_IRQn, 0); /* (3) */ + NVIC_EnableIRQ(USART1_IRQn); /* (4) */ +} + +void usart1_isr(){ + #ifdef CHECK_TMOUT + static uint32_t tmout = 0; + #endif + if(USART1->ISR & USART_ISR_RXNE){ // RX not emty - receive next char + #ifdef CHECK_TMOUT + if(tmout && Tms >= tmout){ // set overflow flag + bufovr = 1; + datalen[rbufno] = 0; + } + tmout = Tms + TIMEOUT_MS; + if(!tmout) tmout = 1; // prevent 0 + #endif + // read RDR clears flag + uint8_t rb = USART1->RDR; + if(datalen[rbufno] < UARTBUFSZ){ // put next char into buf + rbuf[rbufno][datalen[rbufno]++] = rb; + if(rb == '\n'){ // got newline - line ready + linerdy = 1; + dlen = datalen[rbufno]; + recvdata = rbuf[rbufno]; + // prepare other buffer + rbufno = !rbufno; + datalen[rbufno] = 0; + #ifdef CHECK_TMOUT + // clear timeout at line end + tmout = 0; + #endif + } + }else{ // buffer overrun + bufovr = 1; + datalen[rbufno] = 0; + #ifdef CHECK_TMOUT + tmout = 0; + #endif + } + } +} + +// both timer and usart DMA +void dma1_channel2_3_isr(){ + if(DMA1->ISR & DMA_ISR_TCIF2){ // Tx + DMA1->IFCR |= DMA_IFCR_CTCIF2; // clear TC flag + txrdy = 1; + } + if(DMA1->ISR & DMA_ISR_TCIF3){ // TIM3_UPd + DMA1_Channel3->CCR &= ~DMA_CCR_EN; + DMA1->IFCR |= DMA_IFCR_CTCIF3; // clear TC flag + dmaflag = 1; + } +} + +/** + * return length of received data (without trailing zero + */ +int usart1_getline(char **line){ + if(bufovr){ + bufovr = 0; + linerdy = 0; + return 0; + } + *line = recvdata; + linerdy = 0; + return dlen; +} + +TXstatus usart1_send(const char *str, int len){ + if(!txrdy) return LINE_BUSY; + if(len > UARTBUFSZ) return STR_TOO_LONG; + txrdy = 0; + DMA1_Channel2->CCR &= ~DMA_CCR_EN; + memcpy(tbuf, str, len); + DMA1_Channel2->CNDTR = len; + DMA1_Channel2->CCR |= DMA_CCR_EN; // start transmission + return ALL_OK; +} + +TXstatus usart1_send_blocking(const char *str, int len){ + if(!txrdy) return LINE_BUSY; + int i; + for(i = 0; i < len; ++i){ + USART1->TDR = *str++; + while(!(USART1->ISR & USART_ISR_TXE)); + } + txrdy = 1; + return ALL_OK; +} diff --git a/F0-nolib/morze/usart.h b/F0-nolib/morze/usart.h new file mode 100644 index 0000000..3f4fcd8 --- /dev/null +++ b/F0-nolib/morze/usart.h @@ -0,0 +1,51 @@ +/* + * usart.h + * + * Copyright 2017 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 __USART_H__ +#define __USART_H__ + +#include "stm32f0.h" + +// input and output buffers size +#define UARTBUFSZ (64) +// timeout between data bytes +#define TIMEOUT_MS (1500) +// check timeout +#define CHECK_TMOUT + +typedef enum{ + ALL_OK, + LINE_BUSY, + STR_TOO_LONG +} TXstatus; + +#define usart1rx() (linerdy) +#define usart1ovr() (bufovr) + +extern int linerdy, bufovr, txrdy, dmaflag; + +void USART1_config(); +int usart1_getline(char **line); +TXstatus usart1_send(const char *str, int len); +TXstatus usart1_send_blocking(const char *str, int len); + + +#endif // __USART_H__