├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── README.md ├── bootloader ├── Makefile ├── linker │ └── stm32f301k8.ld ├── src │ ├── aes.c │ ├── aes.h │ ├── bootloader.c │ ├── bootloader.h │ ├── clocksource.c │ ├── clocksource.h │ ├── config.h │ ├── crc8.h │ ├── delay.c │ ├── delay.h │ ├── flash.h │ ├── led.c │ ├── led.h │ ├── macros.h │ ├── main.c │ ├── main.h │ ├── serial.c │ ├── serial.h │ ├── timeout.c │ └── timeout.h ├── stylecheck │ ├── README │ ├── cpplint.py │ ├── cpplint_test_header.h │ └── cpplint_unittest.py ├── test │ ├── Makefile │ ├── run_test.sh │ ├── test_aes.c │ ├── test_bootloader.c │ └── test_bootloader.h ├── tinyOSD_bootloader.config ├── tinyOSD_bootloader.creator ├── tinyOSD_bootloader.files ├── tinyOSD_bootloader.includes └── tools │ └── encrypt_hex.py ├── default.mcm ├── font_mcm_to_h.py ├── font_png_to_h.py ├── fonts ├── combat_font.png └── combat_font.xcf ├── generate_sin_table.py ├── linker ├── stm32f051.ld └── stm32f301k8.ld ├── logo_to_h.py ├── src ├── adc.c ├── adc.h ├── clocksource.c ├── clocksource.h ├── config.h ├── crc8.h ├── debug.c ├── debug.h ├── delay.c ├── delay.h ├── font.h ├── led.c ├── led.h ├── logo.h ├── macros.h ├── main.c ├── main.h ├── pilotlogo.h ├── rtc6705.c ├── rtc6705.h ├── serial.c ├── serial.h ├── timeout.c ├── timeout.h ├── video.c ├── video.h ├── video_io.c ├── video_io.h ├── video_render.c ├── video_render.h ├── video_spi_dma.c ├── video_spi_dma.h ├── video_timer.c └── video_timer.h ├── stylecheck ├── README ├── cpplint.py ├── cpplint_test_header.h └── cpplint_unittest.py ├── test └── send_osd_test.py ├── tinyOSD.config ├── tinyOSD.creator ├── tinyOSD.files └── tinyOSD.includes /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/ 3 | *.map 4 | 5 | # Object files 6 | *.o 7 | *.ko 8 | *.obj 9 | *.elf 10 | 11 | # Precompiled Headers 12 | *.gch 13 | *.pch 14 | 15 | # Libraries 16 | *.lib 17 | *.a 18 | *.la 19 | *.lo 20 | 21 | # Shared objects (inc. Windows DLLs) 22 | *.dll 23 | *.so 24 | *.so.* 25 | *.dylib 26 | 27 | # Executables 28 | *.exe 29 | *.out 30 | *.app 31 | *.i*86 32 | *.x86_64 33 | *.hex 34 | 35 | # Debug files 36 | *.dSYM/ 37 | *.su 38 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libopencm3"] 2 | path = libopencm3 3 | url = https://github.com/fishpepper/libopencm3.git 4 | [submodule "bootloader/libopencm3"] 5 | path = bootloader/libopencm3 6 | url = https://github.com/fishpepper/libopencm3.git 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ROOT := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) 2 | SOURCE_DIR = $(ROOT)/src 3 | INCLUDE_DIR = $(SOURCE_DIR) 4 | SOURCE_FILES_FOUND = $(wildcard $(SOURCE_DIR)/*.c) 5 | SOURCE_FILES = $(SOURCE_FILES_FOUND:./src/%=%) 6 | #SOURCE_FILES += eeprom_emulation/st_eeprom.c 7 | OBJECT_DIR := $(ROOT)/obj 8 | BIN_DIR = $(ROOT)/bin 9 | 10 | DEBUG ?= 11 | 12 | ifeq ($(DEBUG),GDB) 13 | CFLAGS := -Og -ggdb3 -DDEBUG 14 | else 15 | CFLAGS = -O2 -g 16 | endif 17 | 18 | ASFLAGS = -g 19 | 20 | # flash using blackmagicprobe 21 | BMP_PORT ?= /dev/ttyACM0 22 | 23 | 24 | # dfu util path 25 | DFU_UTIL ?= dfu-util 26 | 27 | # opencm3 lib config 28 | LIBNAME = opencm3_stm32f3 29 | DEFS += -DSTM32F3 30 | 31 | FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16 32 | ARCH_FLAGS = -mthumb -mcpu=cortex-m4 $(FP_FLAGS) 33 | 34 | LDSCRIPT = linker/stm32f301k8.ld 35 | TARGET = tinyOSD 36 | 37 | CFLAGS += -I./src 38 | LDFLAGS += -L./src 39 | 40 | # Be silent per default, but 'make V=1' will show all compiler calls. 41 | ifneq ($(V),1) 42 | Q := @ 43 | NULL := 2>/dev/null 44 | endif 45 | 46 | ############################################################################### 47 | # Executables 48 | 49 | PREFIX ?= arm-none-eabi 50 | 51 | CC := $(PREFIX)-gcc 52 | CXX := $(PREFIX)-g++ 53 | LD := $(PREFIX)-gcc 54 | AR := $(PREFIX)-ar 55 | AS := $(PREFIX)-as 56 | OBJCOPY := $(PREFIX)-objcopy 57 | OBJDUMP := $(PREFIX)-objdump 58 | GDB := $(PREFIX)-gdb 59 | STFLASH = $(shell which st-flash) 60 | ifneq ($(STSERIAL),) 61 | STFLASH += --serial $(STSERIAL) 62 | endif 63 | STYLECHECK := /checkpatch.pl 64 | STYLECHECKFLAGS := --no-tree -f --terse --mailback 65 | STYLECHECKFILES := $(shell find . -name '*.[ch]') 66 | OPT := -Os 67 | SIZE := $(PREFIX)-size 68 | CSTD ?= -std=gnu99 69 | 70 | 71 | ############################################################################### 72 | # objects 73 | OBJS += $(SOURCE_FILES:%.c=$(OBJECT_DIR)/%.o) 74 | # headers 75 | HEADER_FILES = $(SOURCE_FILES_FOUND:%.c=%.h) 76 | 77 | # where we search for the library 78 | LIBPATHS := ./libopencm3 ../../../../libopencm3 ../../../../../libopencm3 79 | OPENCM3_DIR := ./libopencm3 80 | 81 | ifeq ($(V),1) 82 | $(info Using $(OPENCM3_DIR) path to library) 83 | endif 84 | 85 | # Old style, assume LDSCRIPT exists 86 | DEFS += -I$(OPENCM3_DIR)/include 87 | LDFLAGS += -L$(OPENCM3_DIR)/lib 88 | LDLIBS += -l$(LIBNAME) 89 | 90 | SCRIPT_DIR = $(OPENCM3_DIR)/scripts 91 | 92 | ############################################################################### 93 | # C flags 94 | 95 | TGT_CFLAGS += $(OPT) $(CSTD) -g 96 | TGT_CFLAGS += $(ARCH_FLAGS) 97 | TGT_CFLAGS += -Wextra -Wshadow -Wimplicit-function-declaration 98 | TGT_CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes 99 | TGT_CFLAGS += -fno-common -ffunction-sections -fdata-sections 100 | TGT_CFLAGS += -MD -Wall -Wundef 101 | TGT_CFLAGS += -funroll-loops 102 | TGT_CFLAGS += $(DEFS) 103 | 104 | ############################################################################### 105 | # Linker flags 106 | 107 | TGT_LDFLAGS += --static -nostartfiles 108 | TGT_LDFLAGS += -T$(LDSCRIPT) 109 | TGT_LDFLAGS += $(ARCH_FLAGS) 110 | TGT_LDFLAGS += -Wl,-Map=$(*).map 111 | TGT_LDFLAGS += -Wl,--gc-sections 112 | ifeq ($(V),99) 113 | TGT_LDFLAGS += -Wl,--print-gc-sections 114 | endif 115 | 116 | ############################################################################### 117 | # Used libraries 118 | 119 | LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group 120 | 121 | ############################################################################### 122 | ############################################################################### 123 | ############################################################################### 124 | 125 | .SUFFIXES: .elf .bin .hex .srec .list .map .images 126 | .SECONDEXPANSION: 127 | .SECONDARY: 128 | 129 | all: elf 130 | 131 | elf: $(BIN_DIR)/$(TARGET).elf 132 | bin: $(BIN_DIR)/$(TARGET).bin 133 | hex: $(BIN_DIR)/$(TARGET).hex 134 | srec: $(BIN_DIR)/$(TARGET).srec 135 | list: $(BIN_DIR)/$(TARGET).list 136 | 137 | images: $(BIN_DIR)/$(TARGET).images 138 | flash: $(BIN_DIR)/$(TARGET).flash 139 | debug: $(BIN_DIR)/$(TARGET).debug 140 | 141 | # Either verify the user provided LDSCRIPT exists, or generate it. 142 | $(LDSCRIPT): 143 | ifeq (,$(wildcard $(LDSCRIPT))) 144 | $(error Unable to find specified linker script: $(LDSCRIPT)) 145 | endif 146 | 147 | # Define a helper macro for debugging make errors online 148 | # you can type "make print-OPENCM3_DIR" and it will show you 149 | # how that ended up being resolved by all of the included 150 | # makefiles. 151 | print-%: 152 | @echo $*=$($*) 153 | 154 | $(BIN_DIR)/%.images: $(BIN_DIR)/%.bin $(BIN_DIR)/%.hex $(BIN_DIR)/%.srec $(BIN_DIR)/%.lst $(BIN_DIR)/%.map 155 | @printf "*** $* images generated ***\n" 156 | 157 | $(BIN_DIR)/%.bin: $(BIN_DIR)/%.elf 158 | @printf " OBJCOPY $(*).bin\n" 159 | $(Q)$(OBJCOPY) -Obinary $(BIN_DIR)/$(*).elf $(BIN_DIR)/$(*).bin 160 | 161 | $(BIN_DIR)/%.hex: $(BIN_DIR)/%.elf 162 | @printf " OBJCOPY $(*).hex\n" 163 | $(Q)$(OBJCOPY) -Oihex $(BIN_DIR)/$(*).elf $(BIN_DIR)/$(*).hex 164 | 165 | $(BIN_DIR)/%.srec: $(BIN_DIR)/%.elf 166 | @printf " OBJCOPY $(*).srec\n" 167 | $(Q)$(OBJCOPY) -Osrec $(BIN_DIR)/$(*).elf $(BIN_DIR)/$(*).srec 168 | 169 | $(BIN_DIR)/%.lst: $(BIN_DIR)/%.elf 170 | @printf " OBJDUMP $(*).lst\n" 171 | $(Q)$(OBJDUMP) -S $(BIN_DIR)/$(*).elf > $(BIN_DIR)/$(*).lst 172 | 173 | $(BIN_DIR)/%.elf $(BIN_DIR)/%.map: $(OBJS) $(LDSCRIPT) bin_dir 174 | @printf " LD $(*).elf\n" 175 | $(Q)$(LD) $(TGT_LDFLAGS) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(BIN_DIR)/$(*).elf 176 | 177 | $(OBJECT_DIR)/%.o: $(SOURCE_DIR)/%.c libopencm3 obj_dir 178 | @printf " CC $(*).c\n" 179 | $(Q)$(CC) $(TGT_CFLAGS) $(CFLAGS) -o $(OBJECT_DIR)/$(*).o -c $(SOURCE_DIR)/$(*).c 180 | 181 | size: $(BIN_DIR)/$(TARGET).elf 182 | @printf "\n" 183 | $(Q)$(SIZE) $(BIN_DIR)/$(TARGET).elf 184 | 185 | clean: 186 | @#printf " CLEAN\n" 187 | $(Q)$(RM) $(OBJECT_DIR)/*.o $(OBJECT_DIR)/*.d $(BIN_DIR)/*.elf $(BIN_DIR)*.bin $(BIN_DIR)*.hex $(BIN_DIR)/*.srec $(BIN_DIR)/*.lst $(BIN_DIR)/*.map generated.* ${OBJS} ${OBJS:%.o:%.d} 188 | 189 | stylecheck: $(HEADER_FILES) $(SOURCE_FILES_FOUND) 190 | @./stylecheck/cpplint.py --filter=-build/include,-build/storage_class,-readability/casting,-runtime/arrays --extensions="h,c" --root=src --linelength=120 $(HEADER_FILES) $(SOURCE_FILES_FOUND) || true 191 | 192 | %.stlink-flash: %.bin 193 | @printf " FLASH $<\n" 194 | $(STFLASH) write $(*).bin 0x8000000 195 | 196 | 197 | bin_dir: 198 | @mkdir -p ${BIN_DIR} 199 | 200 | obj_dir: 201 | @mkdir -p ${OBJECT_DIR} 202 | @mkdir -p ${OBJECT_DIR}/eeprom_emulation 203 | 204 | ifeq ($(STLINK_PORT),) 205 | ifeq ($(BMP_PORT),) 206 | ifeq ($(OOCD_FILE),) 207 | %.flash: %.elf 208 | @printf " FLASH $<\n" 209 | (echo "halt; program $(realpath $(*).elf) verify reset" | nc -4 localhost 4444 2>/dev/null) || \ 210 | $(OOCD) -f interface/$(OOCD_INTERFACE).cfg \ 211 | -f target/$(OOCD_TARGET).cfg \ 212 | -c "program $(*).elf verify reset exit" \ 213 | $(NULL) 214 | else 215 | %.flash: %.elf 216 | @printf " FLASH $<\n" 217 | (echo "halt; program $(realpath $(*).elf) verify reset" | nc -4 localhost 4444 2>/dev/null) || \ 218 | $(OOCD) -f $(OOCD_FILE) \ 219 | -c "program $(*).elf verify reset exit" \ 220 | $(NULL) 221 | endif 222 | else 223 | %.flash: %.elf 224 | @printf " GDB $(*).elf (flash)\n" 225 | $(GDB) --batch \ 226 | -ex 'target extended-remote $(BMP_PORT)' \ 227 | -x scripts/black_magic_probe_flash.scr \ 228 | $(*).elf 229 | endif 230 | else 231 | %.flash: %.elf 232 | @printf " GDB $(*).elf (flash)\n" 233 | $(GDB) --batch \ 234 | -ex 'target extended-remote $(STLINK_PORT)' \ 235 | -x $(SCRIPT_DIR)/stlink_flash.scr \ 236 | $(*).elf 237 | endif 238 | 239 | %.debug: %.elf 240 | @printf " GDB $(*).elf (flash)\n" 241 | $(GDB) \ 242 | -ex 'target extended-remote $(BMP_PORT)' \ 243 | -x scripts/black_magic_probe_debug.scr \ 244 | $(*).elf 245 | 246 | 247 | st-erase : 248 | $(STFLASH) erase 249 | 250 | st-flasherase : st-erase st-flash 251 | 252 | st-flash : $(BIN_DIR)/$(TARGET).bin 253 | $(STFLASH) --reset write $(BIN_DIR)/$(TARGET).bin 0x8000000 254 | 255 | openocd-gdb : $(BIN_DIR)/$(TARGET).elf 256 | openocd -f interface/stlink-v2.cfg -f target/stm32f3x.cfg & $(GDB) $(BIN_DIR)/$(TARGET).elf -ex "target remote localhost:3333" -ex "load" 257 | 258 | 259 | dfu : $(BIN_DIR)/$(TARGET).bin 260 | $(DFU_UTIL) -a 0 -D $(BIN_DIR)/$(TARGET).bin -s 0x08000000:leave -R 261 | 262 | 263 | libopencm3 : libopencm3/lib/libopencm3_stm32f0.a submodules 264 | 265 | libopencm3/lib/libopencm3_stm32f0.a: 266 | $(MAKE) -C libopencm3 267 | 268 | #git submodules handling 269 | submodules: 270 | @git submodule update --init -- libopencm3 271 | 272 | 273 | .PHONY: images clean stylecheck styleclean elf bin hex srec list submodules bin_dir obj_dir stylecheck 274 | 275 | -include $(OBJS:.o=.d) 276 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tinyOSD 2 | 3 | My approach to a custom, fully graphic OSD for analog video without 4 | using special hardware. 5 | 6 | Some time ago I got annoyed by the available OSD solutions and I 7 | started to look for alternatives. Nowadays small micro controllers 8 | are fast enough and include fancy features like DMA so that the OSD 9 | generation can be handled in software. 10 | I selected a STM32F3 due to the availability in small packages and 11 | the necessary features I needed and got working. 12 | 13 | [![tinyOSD youtube video](https://img.youtube.com/vi/USWiuCVAzIQ/0.jpg)](https://www.youtube.com/watch?v=USWiuCVAzIQ) 14 | 15 | The result: 16 | * Fully opensource 17 | * Very high update rates 18 | * Full graphic overlays and animations 19 | * Custom, nice font (can be changed) 20 | * Currently showing 35 chars in 13 lines 21 | * "Multi-color": up to eight levels of gray on the screen 22 | * Configurable global brightness and "blackness" setting 23 | 24 | In addition I also release the hardware design of a reference 25 | implementation that also includes a RTC6705 vide transmitter chip: 26 | see https://github.com/fishpepper/tinyFINITY 27 | 28 | Please refer to my blogpost for more details: 29 | https://fishpepper.de/2019/03/11/tinyosd-tinyfinity-a-tiny-opensource-video-tx-with-full-graphic-osd 30 | 31 | 32 | -------------------------------------------------------------------------------- /bootloader/Makefile: -------------------------------------------------------------------------------- 1 | ROOT := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) 2 | SOURCE_DIR = $(ROOT)/src 3 | INCLUDE_DIR = $(SOURCE_DIR) 4 | SOURCE_FILES_FOUND = $(wildcard $(SOURCE_DIR)/*.c) 5 | SOURCE_FILES = $(SOURCE_FILES_FOUND:./src/%=%) 6 | #SOURCE_FILES += eeprom_emulation/st_eeprom.c 7 | OBJECT_DIR := $(ROOT)/obj 8 | BIN_DIR = $(ROOT)/bin 9 | CFLAGS = -O2 -g 10 | ASFLAGS = -g 11 | 12 | # flash using blackmagicprobe 13 | BMP_PORT ?= /dev/ttyACM0 14 | 15 | 16 | # dfu util path 17 | DFU_UTIL ?= dfu-util 18 | 19 | # opencm3 lib config 20 | LIBNAME = opencm3_stm32f3 21 | DEFS += -DSTM32F3 22 | 23 | FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16 24 | ARCH_FLAGS = -mthumb -mcpu=cortex-m4 $(FP_FLAGS) 25 | 26 | LDSCRIPT = linker/stm32f301k8.ld 27 | TARGET = bootloader 28 | 29 | CFLAGS += -I./src 30 | LDFLAGS += -L./src 31 | 32 | # Be silent per default, but 'make V=1' will show all compiler calls. 33 | ifneq ($(V),1) 34 | Q := @ 35 | NULL := 2>/dev/null 36 | endif 37 | 38 | ############################################################################### 39 | # Executables 40 | 41 | PREFIX ?= arm-none-eabi 42 | 43 | CC := $(PREFIX)-gcc 44 | CXX := $(PREFIX)-g++ 45 | LD := $(PREFIX)-gcc 46 | AR := $(PREFIX)-ar 47 | AS := $(PREFIX)-as 48 | OBJCOPY := $(PREFIX)-objcopy 49 | OBJDUMP := $(PREFIX)-objdump 50 | GDB := $(PREFIX)-gdb 51 | STFLASH = $(shell which st-flash) 52 | STYLECHECK := /checkpatch.pl 53 | STYLECHECKFLAGS := --no-tree -f --terse --mailback 54 | STYLECHECKFILES := $(shell find . -name '*.[ch]') 55 | OPT := -Os 56 | SIZE := $(PREFIX)-size 57 | CSTD ?= -std=gnu99 58 | 59 | 60 | ############################################################################### 61 | # objects 62 | OBJS += $(SOURCE_FILES:%.c=$(OBJECT_DIR)/%.o) 63 | # headers 64 | HEADER_FILES = $(SOURCE_FILES_FOUND:%.c=%.h) 65 | 66 | # where we search for the library 67 | LIBPATHS := ./libopencm3 ../../../../libopencm3 ../../../../../libopencm3 68 | OPENCM3_DIR := ./libopencm3 69 | 70 | ifeq ($(V),1) 71 | $(info Using $(OPENCM3_DIR) path to library) 72 | endif 73 | 74 | # Old style, assume LDSCRIPT exists 75 | DEFS += -I$(OPENCM3_DIR)/include 76 | LDFLAGS += -L$(OPENCM3_DIR)/lib 77 | LDLIBS += -l$(LIBNAME) 78 | 79 | SCRIPT_DIR = $(OPENCM3_DIR)/scripts 80 | 81 | ############################################################################### 82 | # C flags 83 | 84 | TGT_CFLAGS += $(OPT) $(CSTD) -g 85 | TGT_CFLAGS += $(ARCH_FLAGS) 86 | TGT_CFLAGS += -Wextra -Wshadow -Wimplicit-function-declaration 87 | TGT_CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes 88 | TGT_CFLAGS += -fno-common -ffunction-sections -fdata-sections 89 | TGT_CFLAGS += -MD -Wall -Wundef 90 | TGT_CFLAGS += -funroll-loops 91 | TGT_CFLAGS += $(DEFS) 92 | 93 | ############################################################################### 94 | # Linker flags 95 | 96 | TGT_LDFLAGS += --static -nostartfiles 97 | TGT_LDFLAGS += -T$(LDSCRIPT) 98 | TGT_LDFLAGS += $(ARCH_FLAGS) 99 | TGT_LDFLAGS += -Wl,-Map=$(*).map 100 | TGT_LDFLAGS += -Wl,--gc-sections 101 | ifeq ($(V),99) 102 | TGT_LDFLAGS += -Wl,--print-gc-sections 103 | endif 104 | 105 | ############################################################################### 106 | # Used libraries 107 | 108 | LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group 109 | 110 | ############################################################################### 111 | ############################################################################### 112 | ############################################################################### 113 | 114 | .SUFFIXES: .elf .bin .hex .srec .list .map .images 115 | .SECONDEXPANSION: 116 | .SECONDARY: 117 | 118 | all: elf 119 | 120 | elf: $(BIN_DIR)/$(TARGET).elf 121 | bin: $(BIN_DIR)/$(TARGET).bin 122 | hex: $(BIN_DIR)/$(TARGET).hex 123 | srec: $(BIN_DIR)/$(TARGET).srec 124 | lst: $(BIN_DIR)/$(TARGET).lst 125 | 126 | images: $(BIN_DIR)/$(TARGET).images 127 | flash: $(BIN_DIR)/$(TARGET).flash 128 | debug: $(BIN_DIR)/$(TARGET).debug 129 | 130 | # Either verify the user provided LDSCRIPT exists, or generate it. 131 | $(LDSCRIPT): 132 | ifeq (,$(wildcard $(LDSCRIPT))) 133 | $(error Unable to find specified linker script: $(LDSCRIPT)) 134 | endif 135 | 136 | # Define a helper macro for debugging make errors online 137 | # you can type "make print-OPENCM3_DIR" and it will show you 138 | # how that ended up being resolved by all of the included 139 | # makefiles. 140 | print-%: 141 | @echo $*=$($*) 142 | 143 | $(BIN_DIR)/%.images: $(BIN_DIR)/%.bin $(BIN_DIR)/%.hex $(BIN_DIR)/%.srec $(BIN_DIR)/%.lst $(BIN_DIR)/%.map 144 | @printf "*** $* images generated ***\n" 145 | 146 | $(BIN_DIR)/%.bin: $(BIN_DIR)/%.elf 147 | @printf " OBJCOPY $(*).bin\n" 148 | $(Q)$(OBJCOPY) -Obinary $(BIN_DIR)/$(*).elf $(BIN_DIR)/$(*).bin 149 | 150 | $(BIN_DIR)/%.hex: $(BIN_DIR)/%.elf 151 | @printf " OBJCOPY $(*).hex\n" 152 | $(Q)$(OBJCOPY) -Oihex $(BIN_DIR)/$(*).elf $(BIN_DIR)/$(*).hex 153 | 154 | $(BIN_DIR)/%.srec: $(BIN_DIR)/%.elf 155 | @printf " OBJCOPY $(*).srec\n" 156 | $(Q)$(OBJCOPY) -Osrec $(BIN_DIR)/$(*).elf $(BIN_DIR)/$(*).srec 157 | 158 | $(BIN_DIR)/%.lst: $(BIN_DIR)/%.elf 159 | @printf " OBJDUMP $(*).lst\n" 160 | $(Q)$(OBJDUMP) -S $(BIN_DIR)/$(*).elf > $(BIN_DIR)/$(*).lst 161 | 162 | $(BIN_DIR)/%.elf $(BIN_DIR)/%.map: $(OBJS) $(LDSCRIPT) bin_dir 163 | @printf " LD $(*).elf\n" 164 | $(Q)$(LD) $(TGT_LDFLAGS) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(BIN_DIR)/$(*).elf 165 | 166 | $(OBJECT_DIR)/%.o: $(SOURCE_DIR)/%.c libopencm3 obj_dir 167 | @printf " CC $(*).c\n" 168 | $(Q)$(CC) $(TGT_CFLAGS) $(CFLAGS) -o $(OBJECT_DIR)/$(*).o -c $(SOURCE_DIR)/$(*).c 169 | 170 | clean: 171 | @#printf " CLEAN\n" 172 | $(Q)$(RM) $(OBJECT_DIR)/*.o $(OBJECT_DIR)/*.d $(BIN_DIR)/*.elf $(BIN_DIR)*.bin $(BIN_DIR)*.hex $(BIN_DIR)/*.srec $(BIN_DIR)/*.lst $(BIN_DIR)/*.map generated.* ${OBJS} ${OBJS:%.o:%.d} 173 | 174 | stylecheck: $(HEADER_FILES) $(SOURCE_FILES_FOUND) 175 | @./stylecheck/cpplint.py --filter=-build/include,-build/storage_class,-readability/casting,-runtime/arrays --extensions="h,c" --root=bootloader/src --linelength=120 $(HEADER_FILES) $(SOURCE_FILES_FOUND) || true 176 | 177 | %.stlink-flash: %.bin 178 | @printf " FLASH $<\n" 179 | $(STFLASH) write $(*).bin 0x8000000 180 | 181 | 182 | bin_dir: 183 | @mkdir -p ${BIN_DIR} 184 | 185 | obj_dir: 186 | @mkdir -p ${OBJECT_DIR} 187 | @mkdir -p ${OBJECT_DIR}/eeprom_emulation 188 | 189 | size: $(BIN_DIR)/$(TARGET).elf 190 | @printf "\n" 191 | $(Q)$(SIZE) $(BIN_DIR)/$(TARGET).elf 192 | 193 | ifeq ($(STLINK_PORT),) 194 | ifeq ($(BMP_PORT),) 195 | ifeq ($(OOCD_FILE),) 196 | %.flash: %.elf 197 | @printf " FLASH $<\n" 198 | (echo "halt; program $(realpath $(*).elf) verify reset" | nc -4 localhost 4444 2>/dev/null) || \ 199 | $(OOCD) -f interface/$(OOCD_INTERFACE).cfg \ 200 | -f target/$(OOCD_TARGET).cfg \ 201 | -c "program $(*).elf verify reset exit" \ 202 | $(NULL) 203 | else 204 | %.flash: %.elf 205 | @printf " FLASH $<\n" 206 | (echo "halt; program $(realpath $(*).elf) verify reset" | nc -4 localhost 4444 2>/dev/null) || \ 207 | $(OOCD) -f $(OOCD_FILE) \ 208 | -c "program $(*).elf verify reset exit" \ 209 | $(NULL) 210 | endif 211 | else 212 | %.flash: %.elf 213 | @printf " GDB $(*).elf (flash)\n" 214 | $(GDB) --batch \ 215 | -ex 'target extended-remote $(BMP_PORT)' \ 216 | -x scripts/black_magic_probe_flash.scr \ 217 | $(*).elf 218 | endif 219 | else 220 | %.flash: %.elf 221 | @printf " GDB $(*).elf (flash)\n" 222 | $(GDB) --batch \ 223 | -ex 'target extended-remote $(STLINK_PORT)' \ 224 | -x $(SCRIPT_DIR)/stlink_flash.scr \ 225 | $(*).elf 226 | endif 227 | 228 | %.debug: %.elf 229 | @printf " GDB $(*).elf (flash)\n" 230 | $(GDB) \ 231 | -ex 'target extended-remote $(BMP_PORT)' \ 232 | -x scripts/black_magic_probe_debug.scr \ 233 | $(*).elf 234 | 235 | 236 | sterase : 237 | st-flash erase 238 | 239 | stflasherase : sterase stflash 240 | 241 | stflash : $(BIN_DIR)/$(TARGET).bin 242 | st-flash --reset write $(BIN_DIR)/$(TARGET).bin 0x8000000 243 | 244 | 245 | dfu : $(BIN_DIR)/$(TARGET).bin 246 | $(DFU_UTIL) -a 0 -D $(BIN_DIR)/$(TARGET).bin -s 0x08000000:leave -R 247 | 248 | 249 | libopencm3 : libopencm3/lib/libopencm3_stm32f0.a submodules 250 | 251 | libopencm3/lib/libopencm3_stm32f0.a: 252 | $(MAKE) -C libopencm3 253 | 254 | #git submodules handling 255 | submodules: 256 | @git submodule update --init -- libopencm3 257 | 258 | 259 | .PHONY: images clean stylecheck styleclean elf bin hex srec lst submodules bin_dir obj_dir stylecheck 260 | 261 | -include $(OBJS:.o=.d) 262 | -------------------------------------------------------------------------------- /bootloader/linker/stm32f301k8.ld: -------------------------------------------------------------------------------- 1 | /* linker script for STM32F301K8, 64K flash, 16K RAM) */ 2 | 3 | /* define memory regions */ 4 | MEMORY { 5 | rom (rx) : ORIGIN = 0x08000000, LENGTH = 5*2K 6 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K 7 | } 8 | 9 | /* Include the common ld script */ 10 | INCLUDE libopencm3_stm32f3.ld 11 | -------------------------------------------------------------------------------- /bootloader/src/aes.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef AES_H_ 21 | #define AES_H_ 22 | #include 23 | 24 | void aes_init(void); 25 | void aes_cbc_encrypt(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv); 26 | void aes_cbc_decrypt(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv); 27 | 28 | #endif // AES_H_ 29 | -------------------------------------------------------------------------------- /bootloader/src/bootloader.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef BOOTLOADER_H_ 21 | #define BOOTLOADER_H_ 22 | #include 23 | 24 | #define BOOTLOADER_COMMAND_INIT 0x7F 25 | #define BOOTLOADER_COMMAND_GET 0x00 26 | #define BOOTLOADER_COMMAND_GET_VERSION 0x01 27 | #define BOOTLOADER_COMMAND_GET_ID 0x02 28 | #define BOOTLOADER_COMMAND_READ_MEMORY 0x11 29 | #define BOOTLOADER_COMMAND_GO 0x21 30 | #define BOOTLOADER_COMMAND_WRITE_MEMORY 0x31 31 | #define BOOTLOADER_COMMAND_ERASE 0x43 32 | 33 | #define BOOTLOADER_RESPONSE_ACK 0x79 34 | #define BOOTLOADER_RESPONSE_NACK 0x1F 35 | 36 | void bootloader_init(void); 37 | void bootloader_main(void); 38 | void bootloader_jump_to_app(void); 39 | 40 | #endif // BOOTLOADER_H_ 41 | -------------------------------------------------------------------------------- /bootloader/src/clocksource.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #include "clocksource.h" 21 | #include "config.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #if CPU_CLOCK == 72000000 29 | static void clocksource_hse_in_8_out_72(void); 30 | #endif // CPU_CLOCK 31 | #if CPU_CLOCK == 48000000 32 | static void clocksource_hse_in_8_out_48(void); 33 | #endif // CPU_CLOCK 34 | 35 | uint32_t rcc_timer_frequency; 36 | 37 | void clocksource_init(void) { 38 | // set clock source 39 | #if CPU_CLOCK == 48000000 40 | clocksource_hse_in_8_out_48(); 41 | #elif CPU_CLOCK == 72000000 42 | clocksource_hse_in_8_out_72(); 43 | #else 44 | ERROR: unsupported clock freq requested 45 | #endif // CPU_CLOCK 46 | } 47 | 48 | #if CPU_CLOCK == 72000000 49 | static void clocksource_hse_in_8_out_72(void) { 50 | // see RM0366 p. 92 for clock tree 51 | 52 | // enable internal high-speed oscillator 53 | // we will run from hsi during setup 54 | rcc_osc_on(RCC_HSI); 55 | rcc_wait_for_osc_ready(RCC_HSI); 56 | 57 | // Select HSI as SYSCLK source. 58 | rcc_set_sysclk_source(RCC_CFGR_SW_HSI); 59 | 60 | // Enable external high-speed oscillator 8MHz 61 | rcc_osc_on(RCC_HSE); 62 | rcc_wait_for_osc_ready(RCC_HSE); 63 | 64 | // disable pll during setup (madatory!) 65 | rcc_osc_off(RCC_PLL); 66 | rcc_wait_for_osc_not_ready(RCC_PLL); 67 | 68 | // set up HSE 8MHz to PLL out 72 MHz 69 | // PL OUT = HSE/1 * 9 = 72 70 | rcc_set_prediv(RCC_CFGR2_PREDIV_NODIV); 71 | rcc_set_pll_source(RCC_CFGR_PLLSRC_HSE_PREDIV); 72 | rcc_set_pll_multiplier(RCC_CFGR_PLLMUL_PLL_IN_CLK_X9); 73 | 74 | // start pll 75 | rcc_osc_on(RCC_PLL); 76 | rcc_wait_for_osc_ready(RCC_PLL); 77 | 78 | // set up prescalers for AHB, ADC, ABP1, ABP2. 79 | // do this before setting sysclock source to PLL 80 | // otherwise we might run the peripherals at a frequency 81 | // that exceeds the limits 82 | rcc_set_hpre(RCC_CFGR_HPRE_DIV_NONE); // 72MHz (max: 72) 83 | rcc_set_ppre2(RCC_CFGR_PPRE2_DIV_2); // 36MHz (max: 72) 84 | rcc_set_ppre1(RCC_CFGR_PPRE1_DIV_2); // 36MHz (max: 36) 85 | 86 | // set flash waitstates 87 | flash_set_ws(FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_2WS); 88 | 89 | // finally select PLL as SYSCLK source 90 | rcc_set_sysclk_source(RCC_CFGR_SW_PLL); 91 | 92 | // set the peripheral clock frequencies used */ 93 | rcc_ahb_frequency = 72000000; 94 | rcc_apb1_frequency = 36000000; 95 | rcc_apb2_frequency = 36000000; 96 | } 97 | #endif // CPU_CLOCK 98 | 99 | #if CPU_CLOCK == 48000000 100 | static void clocksource_hse_in_8_out_48(void) { 101 | // see RM0366 p. 92 for clock tree 102 | 103 | // enable internal high-speed oscillator 104 | // we will run from hsi during setup 105 | rcc_osc_on(RCC_HSI); 106 | rcc_wait_for_osc_ready(RCC_HSI); 107 | 108 | // Select HSI as SYSCLK source. 109 | rcc_set_sysclk_source(RCC_CFGR_SW_HSI); 110 | 111 | // Enable external high-speed oscillator 8MHz 112 | rcc_osc_on(RCC_HSE); 113 | rcc_wait_for_osc_ready(RCC_HSE); 114 | 115 | // disable pll during setup (madatory!) 116 | rcc_osc_off(RCC_PLL); 117 | rcc_wait_for_osc_not_ready(RCC_PLL); 118 | 119 | // set up HSE 8MHz to PLL out 48 MHz 120 | // PL OUT = HSE/2 * 12 = 4 * 12 = 48 121 | rcc_set_prediv(RCC_CFGR2_PREDIV_DIV2); 122 | rcc_set_pll_source(RCC_CFGR_PLLSRC_HSE_PREDIV); 123 | rcc_set_pll_multiplier(RCC_CFGR_PLLMUL_PLL_IN_CLK_X12); 124 | 125 | // start pll 126 | rcc_osc_on(RCC_PLL); 127 | rcc_wait_for_osc_ready(RCC_PLL); 128 | 129 | // set up prescalers for AHB, ADC, ABP1, ABP2. 130 | // do this before setting sysclock source to PLL 131 | // otherwise we might run the peripherals at a frequency 132 | // that exceeds the limits 133 | rcc_set_hpre(RCC_CFGR_HPRE_DIV_NONE); // 48MHz (max: 72) 134 | rcc_set_ppre2(RCC_CFGR_PPRE2_DIV_2); // 24MHz (max: 72) 135 | rcc_set_ppre1(RCC_CFGR_PPRE1_DIV_2); // 24MHz (max: 36) 136 | 137 | // set flash waitstates 138 | flash_set_ws(FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_1WS); 139 | 140 | // finally select PLL as SYSCLK source 141 | rcc_set_sysclk_source(RCC_CFGR_SW_PLL); 142 | 143 | // set the peripheral clock frequencies used */ 144 | rcc_ahb_frequency = 48000000; 145 | rcc_apb1_frequency = 24000000; 146 | rcc_apb2_frequency = 24000000; 147 | } 148 | #endif // CPU_CLOCK 149 | 150 | -------------------------------------------------------------------------------- /bootloader/src/clocksource.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef CLOCKSOURCE_H_ 21 | #define CLOCKSOURCE_H_ 22 | 23 | #include 24 | extern uint32_t rcc_timer_frequency; 25 | 26 | void clocksource_init(void); 27 | 28 | #endif // CLOCKSOURCE_H_ 29 | -------------------------------------------------------------------------------- /bootloader/src/config.h: -------------------------------------------------------------------------------- 1 | // datasheets STM32F301 2 | // RM: http://www.st.com/resource/en/reference_manual/dm00094350.pdf 3 | // DS: http://www.keil.com/dd/docs/datashts/st/stm32f3xx/dm00093332.pdf 4 | 5 | #define BOOTLOADER_ALLOW_READ 1 6 | 7 | #define CPU_CLOCK 48000000 8 | 9 | // timeout waiting for bootloader data 10 | #define BOOTLOADER_TIMEOUT_MS 3000 11 | #define BOOTLOADER_MAX_BAD_COMMANDS 32 12 | 13 | #define DEVICE_FLASH_START 0x08000000 14 | #define DEVICE_FLASH_SIZE (64 * 1024) 15 | #define DEVICE_PAGE_SIZE ( 2 * 1024) 16 | 17 | #define BOOTLOADER_SIZE (5*DEVICE_PAGE_SIZE) 18 | #define BOOTLOADER_MAGIC_PAGE (DEVICE_FLASH_START + BOOTLOADER_SIZE) 19 | #define BOOTLOADER_APP_START (BOOTLOADER_MAGIC_PAGE + DEVICE_PAGE_SIZE) 20 | #define BOOTLOADER_APP_END (DEVICE_FLASH_START + DEVICE_FLASH_SIZE) 21 | 22 | #define BOOTLOADER_SIZE_PAGES (BOOTLOADER_SIZE / DEVICE_PAGE_SIZE) 23 | #define BOOTLOADER_FLASH_SIZE_PAGES (DEVICE_FLASH_SIZE / DEVICE_PAGE_SIZE) 24 | 25 | // magic page: 26 | // [CRC : 4 bytes] 27 | // [SIGNATURE : 16 bytes] 28 | // [UNIQUE ID : 12 bytes] 29 | // [empty ] 30 | #define FLASH_CRC_OFFSET ( 0) 31 | #define FLASH_SIGNATURE_OFFSET (FLASH_CRC_OFFSET + 4) 32 | #define FLASH_DEVICE_ID_OFFSET (FLASH_SIGNATURE_OFFSET + 16) 33 | 34 | // STM32f301 35 | #define BOOTLOADER_VERSION 0x40 36 | #define BOOTLOADER_DEVICE_ID 0x0439 37 | 38 | #define SERIAL_OVERRUN_DETECTION_DISABLED 0 39 | 40 | #ifndef LED_GPIO 41 | #define LED_GPIO GPIOA 42 | #define LED_PIN GPIO14 43 | #endif 44 | 45 | #ifndef SERIAL_GPIO 46 | #define SERIAL_GPIO GPIOA 47 | #define SERIAL_GPIO_AF GPIO_AF7 48 | #define SERIAL_UART USART2 49 | #define SERIAL_UART_RCC RCC_USART2 50 | #define SERIAL_TX_PIN GPIO2 51 | #define SERIAL_RX_PIN GPIO3 52 | #define SERIAL_UART_BAUDRATE 115200 53 | #endif 54 | 55 | // misc 56 | #define NVIC_PRIO_SYSTICK 0 57 | 58 | /* 59 | #define DEBUG_GPIO GPIOA 60 | #define DEBUG_GPIO_AF GPIO_AF7 61 | #define DEBUG_UART USART2 62 | #define DEBUG_UART_RCC RCC_USART2 63 | #define DEBUG_TX_PIN GPIO2 64 | #define DEBUG_UART_BAUDRATE 115200 65 | */ 66 | 67 | -------------------------------------------------------------------------------- /bootloader/src/crc8.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef CRC8_H_ 21 | #define CRC8_H_ 22 | 23 | #include 24 | 25 | // dvb s2 crc8 (poly 0xD5) lookup table 26 | static const uint8_t crc8_table[256] = { 27 | 0x0, 0xd5, 0x7f, 0xaa, 0xfe, 0x2b, 0x81, 0x54, 28 | 0x29, 0xfc, 0x56, 0x83, 0xd7, 0x2, 0xa8, 0x7d, 29 | 0x52, 0x87, 0x2d, 0xf8, 0xac, 0x79, 0xd3, 0x6, 30 | 0x7b, 0xae, 0x4, 0xd1, 0x85, 0x50, 0xfa, 0x2f, 31 | 0xa4, 0x71, 0xdb, 0xe, 0x5a, 0x8f, 0x25, 0xf0, 32 | 0x8d, 0x58, 0xf2, 0x27, 0x73, 0xa6, 0xc, 0xd9, 33 | 0xf6, 0x23, 0x89, 0x5c, 0x8, 0xdd, 0x77, 0xa2, 34 | 0xdf, 0xa, 0xa0, 0x75, 0x21, 0xf4, 0x5e, 0x8b, 35 | 0x9d, 0x48, 0xe2, 0x37, 0x63, 0xb6, 0x1c, 0xc9, 36 | 0xb4, 0x61, 0xcb, 0x1e, 0x4a, 0x9f, 0x35, 0xe0, 37 | 0xcf, 0x1a, 0xb0, 0x65, 0x31, 0xe4, 0x4e, 0x9b, 38 | 0xe6, 0x33, 0x99, 0x4c, 0x18, 0xcd, 0x67, 0xb2, 39 | 0x39, 0xec, 0x46, 0x93, 0xc7, 0x12, 0xb8, 0x6d, 40 | 0x10, 0xc5, 0x6f, 0xba, 0xee, 0x3b, 0x91, 0x44, 41 | 0x6b, 0xbe, 0x14, 0xc1, 0x95, 0x40, 0xea, 0x3f, 42 | 0x42, 0x97, 0x3d, 0xe8, 0xbc, 0x69, 0xc3, 0x16, 43 | 0xef, 0x3a, 0x90, 0x45, 0x11, 0xc4, 0x6e, 0xbb, 44 | 0xc6, 0x13, 0xb9, 0x6c, 0x38, 0xed, 0x47, 0x92, 45 | 0xbd, 0x68, 0xc2, 0x17, 0x43, 0x96, 0x3c, 0xe9, 46 | 0x94, 0x41, 0xeb, 0x3e, 0x6a, 0xbf, 0x15, 0xc0, 47 | 0x4b, 0x9e, 0x34, 0xe1, 0xb5, 0x60, 0xca, 0x1f, 48 | 0x62, 0xb7, 0x1d, 0xc8, 0x9c, 0x49, 0xe3, 0x36, 49 | 0x19, 0xcc, 0x66, 0xb3, 0xe7, 0x32, 0x98, 0x4d, 50 | 0x30, 0xe5, 0x4f, 0x9a, 0xce, 0x1b, 0xb1, 0x64, 51 | 0x72, 0xa7, 0xd, 0xd8, 0x8c, 0x59, 0xf3, 0x26, 52 | 0x5b, 0x8e, 0x24, 0xf1, 0xa5, 0x70, 0xda, 0xf, 53 | 0x20, 0xf5, 0x5f, 0x8a, 0xde, 0xb, 0xa1, 0x74, 54 | 0x9, 0xdc, 0x76, 0xa3, 0xf7, 0x22, 0x88, 0x5d, 55 | 0xd6, 0x3, 0xa9, 0x7c, 0x28, 0xfd, 0x57, 0x82, 56 | 0xff, 0x2a, 0x80, 0x55, 0x1, 0xd4, 0x7e, 0xab, 57 | 0x84, 0x51, 0xfb, 0x2e, 0x7a, 0xaf, 0x5, 0xd0, 58 | 0xad, 0x78, 0xd2, 0x7, 0x53, 0x86, 0x2c, 0xf9, 59 | }; 60 | 61 | 62 | 63 | /*#define CRC8_UPDATE(__crc, __a) { \ 64 | (__crc) ^= (__a); \ 65 | for (uint8_t _ii = 0; _ii < 8; ++_ii) { \ 66 | if ((__crc) & 0x80) { \ 67 | (__crc) = ((__crc) << 1) ^ 0xD5; \ 68 | } else { \ 69 | (__crc) = (__crc) << 1; \ 70 | } \ 71 | } \ 72 | }*/ 73 | 74 | #define CRC8_UPDATE(__crc, __val) ((__crc) = crc8_table[(__crc) ^ (__val)]) 75 | #define CRC8_INIT(__crc, __ival) { (__crc) = (__ival); } 76 | 77 | 78 | 79 | #endif // CRC8_H_ 80 | -------------------------------------------------------------------------------- /bootloader/src/delay.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/ or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | 21 | #include "delay.h" 22 | 23 | void delay_init(void) { 24 | // nothing to do 25 | } 26 | 27 | 28 | inline void delay_us(uint32_t us) { 29 | // based on https:// github.com/leaflabs/libmaple 30 | us *= 10; 31 | 32 | // fudge for function call overhead 33 | us--; 34 | us--; 35 | us--; 36 | us--; 37 | us--; 38 | us--; 39 | asm volatile(".syntax unified \n\t" 40 | " mov r0, %[us] \n\t" 41 | "1: subs r0, #1 \n\t" 42 | " bhi 1b \n\t" 43 | ".syntax divided \n\t" 44 | : 45 | : [us] "r" (us) 46 | : "r0"); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /bootloader/src/delay.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef DELAY_H_ 21 | #define DELAY_H_ 22 | 23 | #include 24 | #include "timeout.h" 25 | 26 | void delay_init(void); 27 | void delay_us(uint32_t us); 28 | #define delay_ms(ms) timeout_delay_ms(ms) 29 | 30 | 31 | #endif // DELAY_H_ 32 | -------------------------------------------------------------------------------- /bootloader/src/flash.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | This program is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | You should have received a copy of the GNU General Public License 12 | along with this program. If not, see . 13 | author: fishpepper gmail.com 14 | */ 15 | 16 | #ifndef FLASH_H_ 17 | #define FLASH_H_ 18 | #include 19 | 20 | void flash_init(void); 21 | void flash_read(uint16_t address, __xdata uint8_t *buf, uint16_t len); 22 | uint8_t flash_write_data(uint16_t address, __xdata uint8_t *buf, uint16_t len); 23 | uint8_t flash_erase_page(uint8_t page); 24 | static void flash_trigger_write(void); 25 | 26 | #if ((FLASH_SIZE) > 65535) 27 | #error "ERROR: maximum supported flash size is 64k!" 28 | #endif // ((DEVICE_FLASH_SIZE) > 65535) 29 | 30 | #define PAGECOUNT_BOOTLOADER ((BOOTLOADER_SIZE) / (FLASH_PAGESIZE)) 31 | #define PAGECOUNT_FLASH ((FLASH_SIZE) / (FLASH_PAGESIZE)) 32 | 33 | 34 | #endif // FLASH_H_ 35 | -------------------------------------------------------------------------------- /bootloader/src/led.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/ or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #include "led.h" 21 | #include "macros.h" 22 | #include "delay.h" 23 | #include 24 | 25 | void led_init(void) { 26 | // peripheral clocks enable 27 | rcc_periph_clock_enable(GPIO_RCC(LED_GPIO)); 28 | 29 | // set led pin as output 30 | gpio_mode_setup(LED_GPIO, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_PIN); 31 | gpio_set_output_options(LED_GPIO, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, LED_PIN); 32 | 33 | led_off(); 34 | } 35 | 36 | -------------------------------------------------------------------------------- /bootloader/src/led.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef LED_H_ 21 | #define LED_H_ 22 | 23 | #include 24 | #include "config.h" 25 | #include "macros.h" 26 | 27 | void led_init(void); 28 | 29 | #define led_on() { GPIO_TOGGLE(LED_GPIO, LED_PIN); } 30 | #define led_off() { GPIO_CLEAR(LED_GPIO, LED_PIN); } 31 | #define led_set(__val) {if (__val) {led_on(); } else {led_off(); }} 32 | #define led_toggle() { GPIO_TOGGLE(LED_GPIO, LED_PIN); } 33 | 34 | #endif // LED_H_ 35 | -------------------------------------------------------------------------------- /bootloader/src/macros.h: -------------------------------------------------------------------------------- 1 | #ifndef MACROS_H__ 2 | #define MACROS_H__ 3 | 4 | #include 5 | #include 6 | 7 | #define GLOBAL_INT_DISABLE() __asm volatile ("cpsid i") 8 | #define GLOBAL_INT_ENABLE() __asm volatile ("cpsie i") 9 | #define RELOCATE_VTABLE(__a) { SCB_VTOR = __a; } 10 | 11 | #define FLASH_U8_PTR(__a) (((uint8_t *)(__a))) 12 | #define FLASH_U16_PTR(__a) (((uint16_t *)(__a))) 13 | #define FLASH_U32_PTR(__a) (((uint32_t *)(__a))) 14 | 15 | #define GPIO_RCC(GPIO) (((0x14) << 5) + (17 + ((GPIO - PERIPH_BASE_AHB2)/0x0400))) 16 | 17 | #define DEFINE_TO_STR(x) #x 18 | #define DEFINE_TO_STR_VAL(x) DEFINE_TO_STR(x) 19 | 20 | #define min(a, b) (((a) < (b)) ? (a):(b)) 21 | #define max(a, b) (((a) > (b)) ? (a):(b)) 22 | 23 | #ifdef UNUSED 24 | #elif defined(__GNUC__) 25 | # define UNUSED(x) UNUSED_ ## x __attribute__((unused)) 26 | #elif defined(__LCLINT__) 27 | # define UNUSED(x) /*@unused@*/ x 28 | #else 29 | # define UNUSED(x) x 30 | #endif 31 | 32 | // relocate function to run from sram (no waitstates!) 33 | #define RUN_FROM_RAM __attribute__ ((long_call, section (".data"))) 34 | 35 | 36 | /*#define CRC_SET_INIT(__crc) { \ 37 | CRC_INIT = (__crc); \ 38 | CRC_CR = 0; \ 39 | CRC_CR |= CRC_CR_RESET; \ 40 | 41 | } 42 | #define CRC_UPDATE(__crc, __val) { CRC_DR = __val; __crc = CRC_DR;}*/ 43 | 44 | // *************************************************** 45 | // using those macros is a big speedup (no lib calls!) 46 | // *************************************************** 47 | #define DMA_SET_NUMBER_OF_DATA(_dma, _ch, _val) { DMA_CNDTR(_dma, _ch) = (_val); } 48 | #define DMA_SET_MEMORY_ADDRES_NOCHECK(_dma, _ch, _address) { DMA_CMAR(_dma, _ch) = (uint32_t) (_address); } 49 | 50 | //#define DMA_CLEAR_INTERRUPT_FLAGS(_dma, _ch, _flags) { DMA_IFCR(_dma) = ((_flags) << DMA_FLAG_OFFSET(_ch)); } 51 | #define DMA_CLEAR_INTERRUPT_FLAGS_MULTI(_dma, _flags) { DMA_IFCR(_dma) = (_flags); } 52 | #define DMA_DISABLE_CHANNEL(_dma, _ch) { DMA_CCR(_dma, _ch) &= ~DMA_CCR_EN; } 53 | #define DMA_ENABLE_CHANNEL(_dma, _ch) { DMA_CCR(_dma, _ch) |= DMA_CCR_EN; } 54 | 55 | #define TIMER_CLEAR_FLAG(_tim, _flags) { TIM_SR(_tim) = ~(_flags); } 56 | #define TIMER_DISABLE_IRQ(_tim, _irqs) { TIM_DIER(_tim) &= ~(_irqs); } 57 | #define TIMER_ENABLE_IRQ(_tim, _irqs) { TIM_DIER(_tim) |= (_irqs); } 58 | #define TIMER_GET_FLAG(_tim, _flag) (TIM_SR(_tim) & (_flag)) 59 | #define TIMER_SET_DMA_ON_COMPARE_EVENT(_tim) { TIM_CR2(_tim) &= ~TIM_CR2_CCDS; } 60 | #define TIMER_CLEAR_DMA_ON_COMPARE_EVENT(_tim) { TIM_CR2(_tim) |= TIM_CR2_CCDS; } 61 | 62 | #define GPIO_SET(__port, __gpios) { GPIO_BSRR(__port) = __gpios; } 63 | #define GPIO_CLEAR(__port, __gpios) { GPIO_BSRR(__port) = (__gpios)<<16; } 64 | #define GPIO_TOGGLE(__port, __gpios) { uint32_t p = GPIO_ODR(__port); \ 65 | GPIO_BSRR(__port) = ((p & (__gpios)) << 16) | (~p & (__gpios)); } 66 | 67 | 68 | 69 | // *************************************************** 70 | // manual loop unrolling 71 | // *************************************************** 72 | #define _UNROLL_LOOP_1(__cmd) {__cmd;} 73 | #define _UNROLL_LOOP_2(__cmd) {_UNROLL_LOOP_1(__cmd); _UNROLL_LOOP_1(__cmd); } 74 | #define _UNROLL_LOOP_4(__cmd) {_UNROLL_LOOP_2(__cmd); _UNROLL_LOOP_2(__cmd); } 75 | #define _UNROLL_LOOP_8(__cmd) {_UNROLL_LOOP_4(__cmd); _UNROLL_LOOP_4(__cmd); } 76 | #define _UNROLL_LOOP_16(__cmd) {_UNROLL_LOOP_8(__cmd); _UNROLL_LOOP_8(__cmd); } 77 | #define _UNROLL_LOOP_32(__cmd) {_UNROLL_LOOP_16(__cmd); _UNROLL_LOOP_16(__cmd); } 78 | #define _UNROLL_LOOP_64(__cmd) {_UNROLL_LOOP_32(__cmd); _UNROLL_LOOP_32(__cmd); } 79 | 80 | #define UNROLL_LOOP(__n, __cmd) \ 81 | { \ 82 | if(((__n)&1)!=0){_UNROLL_LOOP_1(__cmd);}\ 83 | if(((__n)&2)!=0){_UNROLL_LOOP_2(__cmd);}\ 84 | if(((__n)&4)!=0){_UNROLL_LOOP_4(__cmd);}\ 85 | if(((__n)&8)!=0){_UNROLL_LOOP_8(__cmd);}\ 86 | if(((__n)&16)!=0){_UNROLL_LOOP_16(__cmd);}\ 87 | if(((__n)&32)!=0){_UNROLL_LOOP_32(__cmd);}\ 88 | if(((__n)&64)!=0){_UNROLL_LOOP_64(__cmd);}\ 89 | } 90 | 91 | #endif // MACROS_H__ 92 | -------------------------------------------------------------------------------- /bootloader/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/ or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #include "main.h" 21 | #include "delay.h" 22 | #include "timeout.h" 23 | #include "led.h" 24 | #include "aes.h" 25 | #include "clocksource.h" 26 | #include "serial.h" 27 | #include "macros.h" 28 | #include "bootloader.h" 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | int main(void) { 36 | // init crystal osc & set clock options 37 | clocksource_init(); 38 | 39 | timeout_init(); 40 | 41 | delay_init(); 42 | 43 | led_init(); 44 | 45 | serial_init(); 46 | 47 | aes_init(); 48 | 49 | bootloader_init(); 50 | 51 | // this will never exit... 52 | bootloader_main(); 53 | 54 | while (1) { 55 | led_toggle(); 56 | timeout_delay_ms(100); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /bootloader/src/main.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef MAIN_H_ 21 | #define MAIN_H_ 22 | 23 | #endif // MAIN_H_ 24 | -------------------------------------------------------------------------------- /bootloader/src/serial.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/ or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #include "serial.h" 21 | #include "main.h" 22 | #include "config.h" 23 | #include "timeout.h" 24 | #include "led.h" 25 | #include "macros.h" 26 | #include "bootloader.h" 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | static void serial_init_gpio(void); 34 | static void serial_init_rcc(void); 35 | static void serial_init_uart(void); 36 | 37 | void serial_init(void) { 38 | serial_init_rcc(); 39 | serial_init_gpio(); 40 | serial_init_uart(); 41 | } 42 | 43 | void serial_init_rcc(void) { 44 | // crc module clock enable 45 | rcc_periph_clock_enable(RCC_CRC); 46 | 47 | // peripheral clocks enable 48 | rcc_periph_clock_enable(GPIO_RCC(SERIAL_GPIO)); 49 | rcc_periph_clock_enable(SERIAL_UART_RCC); 50 | } 51 | 52 | void serial_init_gpio(void) { 53 | // set rx and tx to AF 54 | gpio_mode_setup(SERIAL_GPIO, GPIO_MODE_AF, GPIO_PUPD_NONE, SERIAL_TX_PIN); 55 | gpio_mode_setup(SERIAL_GPIO, GPIO_MODE_AF, GPIO_PUPD_NONE, SERIAL_RX_PIN); 56 | 57 | // both are AF1 58 | gpio_set_af(SERIAL_GPIO, SERIAL_GPIO_AF, SERIAL_TX_PIN); 59 | gpio_set_af(SERIAL_GPIO, SERIAL_GPIO_AF, SERIAL_RX_PIN); 60 | 61 | // set uart tx pin as output 62 | gpio_set_output_options(SERIAL_GPIO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SERIAL_TX_PIN); 63 | } 64 | 65 | void serial_init_uart(void) { 66 | // setup USART parameters 67 | usart_set_baudrate(SERIAL_UART, SERIAL_UART_BAUDRATE); 68 | usart_set_databits(SERIAL_UART, 8); 69 | usart_set_parity(SERIAL_UART, USART_PARITY_NONE); 70 | usart_set_stopbits(SERIAL_UART, USART_CR2_STOPBITS_1); 71 | usart_set_mode(SERIAL_UART, USART_MODE_TX_RX); 72 | usart_set_flow_control(SERIAL_UART, USART_FLOWCONTROL_NONE); 73 | 74 | // disable overrun detection? 75 | #if SERIAL_OVERRUN_DETECTION_DISABLED 76 | USART_CR3(SERIAL_UART) |= USART_CR3_OVRDIS; 77 | #endif // SERIAL_OVERRUN_DETECTION_DISABLED 78 | 79 | // finally enable the USART 80 | usart_enable(SERIAL_UART); 81 | } 82 | 83 | uint8_t serial_getc(void) { 84 | // visual indicator 85 | led_toggle(); 86 | 87 | #if !SERIAL_OVERRUN_DETECTION_DISABLED 88 | // any bytes lost (overrun) 89 | if ((USART_ISR(SERIAL_UART) & USART_ISR_ORE) != 0) { 90 | // overrun detected 91 | USART_ICR(SERIAL_UART) |= USART_ICR_ORECF; 92 | } 93 | #endif // SERIAL_OVERRUN_DETECTION_DISABLED 94 | 95 | // wait for incoming data with timeout 96 | timeout_set(BOOTLOADER_TIMEOUT_MS); 97 | while ((USART_ISR(SERIAL_UART) & USART_ISR_RXNE) == 0) { 98 | // no new data, check for timeout 99 | if (timeout_timed_out()) { 100 | // timeout reached, try to jump to app 101 | // this will fail if the flash checksum is invalid 102 | bootloader_jump_to_app(); 103 | return 0; 104 | } 105 | } 106 | 107 | // ok, new data available, read and return it 108 | uint8_t rx = USART_RDR(SERIAL_UART); 109 | return rx; 110 | } 111 | 112 | void serial_putc(uint8_t c) { 113 | usart_send_blocking(SERIAL_UART, c); 114 | } 115 | -------------------------------------------------------------------------------- /bootloader/src/serial.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef SERIAL_H_ 21 | #define SERIAL_H_ 22 | 23 | #include 24 | 25 | void serial_init(void); 26 | 27 | uint8_t serial_getc(void); 28 | void serial_putc(uint8_t c); 29 | 30 | #endif // SERIAL_H_ 31 | -------------------------------------------------------------------------------- /bootloader/src/timeout.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/ or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #include "timeout.h" 21 | #include "delay.h" 22 | #include "led.h" 23 | #include 24 | #include 25 | #include 26 | 27 | static volatile __IO uint32_t timeout_100us; 28 | static volatile __IO uint32_t timeout2_100us; 29 | static volatile __IO uint32_t timeout_100us_delay; 30 | 31 | void timeout_init(void) { 32 | // configure 0.1ms sys tick: 33 | systick_set_clocksource(STK_CSR_CLKSOURCE_AHB); 34 | systick_set_reload(rcc_ahb_frequency / 10000); 35 | systick_interrupt_enable(); 36 | systick_counter_enable(); 37 | 38 | // clear counter so it starts right away 39 | STK_CVR = 0; 40 | 41 | // set prio 42 | nvic_set_priority(NVIC_SYSTICK_IRQ, NVIC_PRIO_SYSTICK); 43 | 44 | timeout_100us = 0; 45 | timeout2_100us = 0; 46 | timeout_100us_delay = 0; 47 | } 48 | 49 | void timeout_set_100us(__IO uint32_t hus) { 50 | timeout_100us = hus; 51 | } 52 | 53 | void timeout2_set_100us(__IO uint32_t hus) { 54 | timeout2_100us = hus; 55 | } 56 | 57 | uint8_t timeout_timed_out(void) { 58 | return(timeout_100us == 0); 59 | } 60 | 61 | uint8_t timeout2_timed_out(void) { 62 | return(timeout2_100us == 0); 63 | } 64 | 65 | void timeout2_delay_100us(uint16_t us) { 66 | timeout2_set_100us(us); 67 | while (!timeout2_timed_out()) {} 68 | } 69 | 70 | 71 | // seperate ms delay function 72 | void timeout_delay_ms(uint32_t timeout) { 73 | timeout_100us_delay = 10*timeout; 74 | 75 | while (timeout_100us_delay > 0) { 76 | } 77 | } 78 | 79 | void sys_tick_handler(void) { 80 | if (timeout_100us != 0) { 81 | timeout_100us--; 82 | } 83 | if (timeout2_100us != 0) { 84 | timeout2_100us--; 85 | } 86 | if (timeout_100us_delay != 0) { 87 | timeout_100us_delay--; 88 | } 89 | } 90 | 91 | uint32_t timeout_time_remaining(void) { 92 | return timeout_100us/ 10; 93 | } 94 | -------------------------------------------------------------------------------- /bootloader/src/timeout.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef TIMEOUT_H_ 21 | #define TIMEOUT_H_ 22 | 23 | #include 24 | #include 25 | 26 | void timeout_init(void); 27 | // void timeout_set(__IO uint32_t ms); 28 | #define timeout_set(x) timeout_set_100us(10*(x)); 29 | void timeout_set_100us(__IO uint32_t hus); 30 | void timeout2_set_100us(__IO uint32_t hus); 31 | void timeout2_delay_100us(uint16_t us); 32 | uint8_t timeout_timed_out(void); 33 | uint8_t timeout2_timed_out(void); 34 | void timeout_delay_ms(uint32_t timeout); 35 | uint32_t timeout_time_remaining(void); 36 | 37 | #endif // TIMEOUT_H_ 38 | -------------------------------------------------------------------------------- /bootloader/stylecheck/README: -------------------------------------------------------------------------------- 1 | This is automated checker to make sure a C++ file follows Google's C++ style 2 | guide (https://google.github.io/styleguide/cppguide.html). As it 3 | heavily relies on regular expressions, cpplint.py won't catch all violations of 4 | the style guide and will very occasionally report a false positive. There is a 5 | list of things we currently don't handle very well at the top of cpplint.py, 6 | and we welcome patches to improve it. 7 | 8 | The linting tool takes a list of files as input. For full usage instructions, 9 | please see the output of: 10 | 11 | ./cpplint.py --help 12 | 13 | Unit tests are provided in cpplint_unittest.py. This file can safely be ignored 14 | by end users who have downloaded this package and only want to run the lint 15 | tool. 16 | 17 | --- 18 | 19 | cpplint.py and its corresponding unit tests are Copyright (C) 2009 Google Inc. 20 | 21 | Redistribution and use in source and binary forms, with or without 22 | modification, are permitted provided that the following conditions are 23 | met: 24 | 25 | * Redistributions of source code must retain the above copyright 26 | notice, this list of conditions and the following disclaimer. 27 | * Redistributions in binary form must reproduce the above 28 | copyright notice, this list of conditions and the following disclaimer 29 | in the documentation and/or other materials provided with the 30 | distribution. 31 | * Neither the name of Google Inc. nor the names of its 32 | contributors may be used to endorse or promote products derived from 33 | this software without specific prior written permission. 34 | 35 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 36 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 37 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 38 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 39 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 41 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 42 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 43 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 44 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 45 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 46 | -------------------------------------------------------------------------------- /bootloader/stylecheck/cpplint_test_header.h: -------------------------------------------------------------------------------- 1 | // A test header for cpplint_unittest.py. 2 | -------------------------------------------------------------------------------- /bootloader/test/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -Wall -Os -Wl,-Map,test.map -D BUILD_TEST=1 -g 3 | OBJCOPY = objcopy 4 | 5 | .SILENT: 6 | .PHONY: clean 7 | 8 | all: test_aes test_bootloader 9 | 10 | test_aes : aes.o test_aes.o 11 | $(CC) $(CFLAGS) aes.o test_aes.o -o test_aes 12 | 13 | test_aes.o : test_aes.c 14 | # compiling test.c 15 | $(CC) $(CFLAGS) -c test_aes.c -o test_aes.o 16 | 17 | test_bootloader: aes.o bootloader.o test_bootloader.o 18 | $(CC) $(CFLAGS) aes.o bootloader.o test_bootloader.o -o test_bootloader 19 | 20 | test_bootloader.o : test_bootloader.c 21 | $(CC) $(CFLAGS) -c test_bootloader.c -o test_bootloader.o 22 | 23 | bootloader.o : ../src/bootloader.h ../src/bootloader.c 24 | $(CC) $(CFLAGS) --include test_bootloader.h -c ../src/bootloader.c -o bootloader.o 25 | 26 | aes.o : ../src/aes.h ../src/aes.c 27 | # compiling aes.c 28 | $(CC) $(CFLAGS) -c ../src/aes.c -o aes.o 29 | 30 | clean: 31 | rm -f *.OBJ *.LST *.o *.gch *.out *.hex *.map 32 | -------------------------------------------------------------------------------- /bootloader/test/run_test.sh: -------------------------------------------------------------------------------- 1 | ihex2bin -a 0x8000000 -i ../../bin/tinyOSD.aes.hex -o test.bin 2 | ./test_bootloader 3 | -------------------------------------------------------------------------------- /bootloader/test/test_aes.c: -------------------------------------------------------------------------------- 1 | #include "../src/aes.h" 2 | 3 | #include 4 | #include 5 | 6 | // prints string as hex 7 | static void phex(uint8_t* str, uint8_t len){ 8 | unsigned char i; 9 | for(i = 0; i < len; ++i) { 10 | printf("%.2x", str[i]); 11 | if (i%16 == 15) printf("\n"); 12 | } 13 | printf("\n"); 14 | } 15 | 16 | 17 | int main(void){ 18 | uint8_t in[] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 19 | 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 20 | 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, 21 | 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }; 22 | 23 | // our secret key (!) 24 | uint8_t secret_key[] = { 25 | 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 26 | 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, 27 | 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 28 | 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 29 | }; 30 | 31 | // initial IV 32 | uint8_t iv[] = { 33 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 34 | 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F 35 | }; 36 | 37 | uint8_t buffer[64]; 38 | 39 | aes_init(); 40 | 41 | printf("\nkey:\n"); 42 | phex(secret_key, 32); 43 | printf("\niv:\n"); 44 | phex(iv, 16); 45 | 46 | printf("\ninput : \n"); 47 | phex(in, 64); 48 | 49 | 50 | // first buffer gets key and IV, 51 | #if 1 52 | for(int i=0; i<4; i++){ 53 | aes_cbc_encrypt(buffer + i*16, in + i*16, 16, (i==0)?secret_key:0, (i==0)?iv:0); 54 | } 55 | #else 56 | aes_cbc_encrypt(buffer, in, 64, secret_key, iv); 57 | #endif 58 | // second run will use internal iv/key 59 | //aes_cbc_encrypt(buffer2, in, 64, 0, 0); 60 | 61 | printf("\noutput: \n"); 62 | phex(buffer, 64); 63 | 64 | uint8_t dec[64]; 65 | aes_cbc_decrypt(dec, buffer, 64, secret_key, iv); 66 | printf("\ninput (dec): \n"); 67 | phex(dec, 64); 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /bootloader/test/test_bootloader.c: -------------------------------------------------------------------------------- 1 | #define BUILD_TEST 1 2 | 3 | #include "test_bootloader.h" 4 | #include "../src/bootloader.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | // ./ihex2bin -a 0x8000000 -i ../priv/tinyOSD/bin/tinyOSD.aes.hex -o test.bin 11 | 12 | void flash_unlock(void){} 13 | void flash_lock(void){} 14 | void flash_program_half_word(uint32_t a, uint16_t val){ 15 | uint16_t *flash_ptr = flash_ptr_u16(a); 16 | 17 | //printf("FLASH[%X] = %04X\n", a, val); 18 | *flash_ptr = val; 19 | } 20 | void flash_erase_page(uint32_t a){} 21 | uint8_t serial_getc(){return 0;} 22 | void serial_putc(uint8_t x) {} 23 | uint32_t crc; 24 | void crc_reset(){ crc = 0xFFFFFFFFF;} 25 | 26 | #define CRC32POLY 0x04C11DB7 /* CRC-32 Polynom */ 27 | uint32_t crc_32( uint32_t crc, uint32_t data){ 28 | int i; 29 | 30 | uint32_t data2 = (data&0xFF)<<24 | ((data>>8)&0xFF)<<16 | ((data>>16)&0xFF)<<8 | ((data>>24)&0xFF)<<0; 31 | 32 | crc = crc ^ data2; 33 | 34 | for(i=0; i<32; i++) 35 | if (crc & 0x80000000) 36 | crc = (crc << 1) ^ 0x04C11DB7; // Polynomial used in STM32 37 | else 38 | crc = (crc << 1); 39 | 40 | return(crc); 41 | } 42 | 43 | uint32_t crc_calculate_block(uint32_t *p, uint32_t len) { 44 | 45 | /*uint8_t *u = (uint8_t *)p; 46 | for(int i=0; i= DEVICE_FLASH_SIZE){ 72 | printf("ERROR: access out of bounds (size = %X, accessed element = %X\n",DEVICE_FLASH_SIZE,a); 73 | exit(1); 74 | } 75 | 76 | return (uint8_t*)&FLASH[a]; 77 | } 78 | uint16_t *flash_ptr_u16(uint32_t a){ 79 | //printf("fetch flash ptr 16 for 0x%X\n", a); 80 | if ((a & 1) != 0){ 81 | printf("ERROR: alignment mismatch, requested u16 access to 0x%X\n",a); 82 | exit(1); 83 | } 84 | a = a - DEVICE_FLASH_START; 85 | if (a >= DEVICE_FLASH_SIZE){ 86 | printf("ERROR: access out of bounds (size = %X, accessed element = %X\n",DEVICE_FLASH_SIZE,a); 87 | exit(1); 88 | } 89 | 90 | return (uint16_t *)&FLASH[a]; 91 | } 92 | uint32_t *flash_ptr_u32(uint32_t a){ 93 | //printf("fetch flash ptr 32 for 0x%X\n", a); 94 | if ((a & 3) != 0){ 95 | printf("ERROR: alignment mismatch, requested u32 access to 0x%X\n",a); 96 | exit(1); 97 | } 98 | a = a - DEVICE_FLASH_START; 99 | if (a >= DEVICE_FLASH_SIZE){ 100 | printf("ERROR: access out of bounds (size = %X, accessed element = %X\n",DEVICE_FLASH_SIZE,a); 101 | exit(1); 102 | } 103 | 104 | return (uint32_t *)&FLASH[a]; 105 | } 106 | 107 | // prints string as hex 108 | static void phex(uint8_t* str, uint8_t len){ 109 | unsigned char i; 110 | for(i = 0; i < len; ++i) { 111 | printf("%.2x", str[i]); 112 | if (i%16 == 15) printf("\n"); 113 | } 114 | printf("\n"); 115 | } 116 | 117 | static void printflash(){ 118 | int i; 119 | for(i = 0; i < 20*32; ++i) { 120 | printf("%.2x", FLASH[i]); 121 | if (i%32 == 31) printf("\n"); 122 | } 123 | printf("...\n"); 124 | for(i = BOOTLOADER_SIZE-20*32; i < BOOTLOADER_SIZE; ++i) { 125 | printf("%.2x", FLASH[i]); 126 | if (i%32 == 31) printf("\n"); 127 | } 128 | printf("[MAGIC PAGE]\n"); 129 | for(i = BOOTLOADER_SIZE; i < BOOTLOADER_SIZE+20*32; ++i) { 130 | printf("%.2x", FLASH[i]); 131 | if (i%32 == 31) printf("\n"); 132 | } 133 | printf("...\n"); 134 | for(i = BOOTLOADER_SIZE + DEVICE_PAGE_SIZE - 20*32; i < BOOTLOADER_SIZE + DEVICE_PAGE_SIZE; ++i) { 135 | printf("%.2x", FLASH[i]); 136 | if (i%32 == 31) printf("\n"); 137 | } 138 | printf("[APP START]\n"); 139 | for(i = BOOTLOADER_SIZE + DEVICE_PAGE_SIZE; i < BOOTLOADER_SIZE + DEVICE_PAGE_SIZE + 20*32; ++i) { 140 | printf("%.2x", FLASH[i]); 141 | if (i%32 == 31) printf("\n"); 142 | } 143 | printf("...\n"); 144 | uint32_t end = BOOTLOADER_APP_END - DEVICE_FLASH_START; 145 | for(i = end-20*32; i < end; ++i) { 146 | printf("%.2x", FLASH[i]); 147 | if (i%32 == 31) printf("\n"); 148 | } 149 | 150 | printf("\n"); 151 | } 152 | 153 | 154 | 155 | int main(void){ 156 | // init flash content: 157 | FILE * file; 158 | file = fopen( "test.bin" , "r"); 159 | for(int i=0; i 3 | #include 4 | 5 | extern void flash_unlock(void); 6 | extern void flash_lock(void); 7 | extern void flash_program_half_word(uint32_t a, uint16_t buf); 8 | extern void flash_erase_page(uint32_t a); 9 | extern uint8_t serial_getc(); 10 | extern void serial_putc(uint8_t x); 11 | extern void crc_reset(); 12 | extern uint32_t crc_calculate_block(); 13 | extern void led_on(); 14 | 15 | #define DEBUG_PRINTF(format, ...) printf(format, ##__VA_ARGS__) 16 | 17 | #define GLOBAL_INT_DISABLE() {} 18 | #define GLOBAL_INT_ENABLE() {} 19 | #define RELOCATE_VTABLE(__a) {} 20 | 21 | #include "../src/config.h" 22 | 23 | extern uint8_t FLASH[]; 24 | 25 | extern uint8_t *flash_ptr_u8(uint32_t a); 26 | extern uint16_t *flash_ptr_u16(uint32_t a); 27 | extern uint32_t *flash_ptr_u32(uint32_t a); 28 | 29 | #define FLASH_U8_PTR(__a) flash_ptr_u8(__a) 30 | #define FLASH_U16_PTR(__a) flash_ptr_u16(__a) 31 | #define FLASH_U32_PTR(__a) flash_ptr_u32(__a) 32 | 33 | -------------------------------------------------------------------------------- /bootloader/tinyOSD_bootloader.config: -------------------------------------------------------------------------------- 1 | // Add predefined macros for your project here. For example: 2 | // #define THE_ANSWER 42 3 | -------------------------------------------------------------------------------- /bootloader/tinyOSD_bootloader.creator: -------------------------------------------------------------------------------- 1 | [General] 2 | -------------------------------------------------------------------------------- /bootloader/tinyOSD_bootloader.includes: -------------------------------------------------------------------------------- 1 | libopencm3/include/libopencm3/cm3 2 | libopencm3/include/libopencm3/dispatch 3 | libopencm3/include/libopencm3/efm32 4 | libopencm3/include/libopencm3/efm32/g 5 | libopencm3/include/libopencm3/efm32/gg 6 | libopencm3/include/libopencm3/efm32/lg 7 | libopencm3/include/libopencm3/efm32/tg 8 | libopencm3/include/libopencm3/ethernet 9 | libopencm3/include/libopencm3/lm3s 10 | libopencm3/include/libopencm3/lm4f 11 | libopencm3/include/libopencm3/lpc13xx 12 | libopencm3/include/libopencm3/lpc17xx 13 | libopencm3/include/libopencm3/lpc43xx 14 | libopencm3/include/libopencm3/lpc43xx/m0 15 | libopencm3/include/libopencm3/lpc43xx/m4 16 | libopencm3/include/libopencm3/sam 17 | libopencm3/include/libopencm3/sam/3a 18 | libopencm3/include/libopencm3/sam/3n 19 | libopencm3/include/libopencm3/sam/3s 20 | libopencm3/include/libopencm3/sam/3u 21 | libopencm3/include/libopencm3/sam/3x 22 | libopencm3/include/libopencm3/sam/common 23 | libopencm3/include/libopencm3/sam/d 24 | libopencm3/include/libopencm3/stm32 25 | libopencm3/include/libopencm3/stm32/common 26 | libopencm3/include/libopencm3/stm32/f0 27 | libopencm3/include/libopencm3/stm32/f1 28 | libopencm3/include/libopencm3/stm32/f2 29 | libopencm3/include/libopencm3/stm32/f3 30 | libopencm3/include/libopencm3/stm32/f4 31 | libopencm3/include/libopencm3/stm32/f7 32 | libopencm3/include/libopencm3/stm32/l0 33 | libopencm3/include/libopencm3/stm32/l1 34 | libopencm3/include/libopencm3/stm32/l4 35 | libopencm3/include/libopencm3/usb 36 | libopencm3/include/libopencm3/vf6xx 37 | libopencm3/include/libopencmsis 38 | libopencm3/include/libopencmsis/dispatch 39 | libopencm3/include/libopencmsis/efm32/g 40 | libopencm3/include/libopencmsis/efm32/gg 41 | libopencm3/include/libopencmsis/efm32/lg 42 | libopencm3/include/libopencmsis/efm32/tg 43 | libopencm3/include/libopencmsis/lm3s 44 | libopencm3/include/libopencmsis/lpc13xx 45 | libopencm3/include/libopencmsis/lpc17xx 46 | libopencm3/include/libopencmsis/lpc43xx/m0 47 | libopencm3/include/libopencmsis/lpc43xx/m4 48 | libopencm3/include/libopencmsis/sam/3a 49 | libopencm3/include/libopencmsis/sam/3n 50 | libopencm3/include/libopencmsis/sam/3s 51 | libopencm3/include/libopencmsis/sam/3u 52 | libopencm3/include/libopencmsis/sam/3x 53 | libopencm3/include/libopencmsis/sam/d 54 | libopencm3/include/libopencmsis/stm32/f0 55 | libopencm3/include/libopencmsis/stm32/f1 56 | libopencm3/include/libopencmsis/stm32/f2 57 | libopencm3/include/libopencmsis/stm32/f3 58 | libopencm3/include/libopencmsis/stm32/f4 59 | libopencm3/include/libopencmsis/stm32/f7 60 | libopencm3/include/libopencmsis/stm32/l0 61 | libopencm3/include/libopencmsis/stm32/l1 62 | libopencm3/include/libopencmsis/stm32/l4 63 | libopencm3/include/libopencmsis/vf6xx 64 | libopencm3/lib/stm32/common 65 | libopencm3/lib/usb 66 | libopencm3/tests/gadget-zero 67 | libopencm3/tests/shared 68 | src 69 | test -------------------------------------------------------------------------------- /bootloader/tools/encrypt_hex.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # This file is part of efm8load. efm8load is free software: you can 4 | # redistribute it and/or modify it under the terms of the GNU General Public 5 | # License as published by the Free Software Foundation, version 3. 6 | # 7 | # This program is distributed in the hope that it will be useful, but WITHOUT 8 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 9 | # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 10 | # details. 11 | # 12 | # You should have received a copy of the GNU General Public License along with 13 | # this program; if not, write to the Free Software Foundation, Inc., 51 14 | # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 15 | # 16 | # Copyright 2016 fishpepper.de 17 | # 18 | from __future__ import print_function 19 | import serial 20 | import argparse 21 | import sys 22 | import operator 23 | import crcmod 24 | from crcmod.predefined import * 25 | from intelhex import IntelHex 26 | from Crypto import Random 27 | from Crypto.Cipher import AES 28 | 29 | # example: 30 | # python encrypt_hex.py -s 64 -i 000102030405060708090A0B0C0D0E0F -k 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 ../../bin/tinyOSD.hex 31 | 32 | # if you are missing the intelhex package, you can install it by 33 | # pip install intelhex --user 34 | # the same goes for the crcmod 35 | # pip install crcmod --user 36 | 37 | class STM32Encrypt: 38 | """Encrypt a intel hex file using AES256""" 39 | 40 | def __init__(self, filename, flash_size, debug = False): 41 | self.debug = debug 42 | self.filename = filename 43 | self.flash_size = int(flash_size) * 1024 44 | self.page_size = 2048 45 | self.flash_start = 0x8000000 46 | # flash content: 47 | # [BOOTLOADER] 48 | # .. empty .. 49 | # [MAGIC+CRC PAGE] 50 | # [APP] 51 | # ... 52 | self.bl_size = 5 * self.page_size 53 | self.table = self.flash_start + self.bl_size 54 | self.app_start = self.table + self.page_size 55 | self.app_end = self.flash_start + self.flash_size 56 | # crc module 57 | self.crcmod = mkPredefinedCrcFun("crc-32-mpeg") #crc-32") #0x104c11db7, initCrc=0, xorOut=0xFFFFFFFF) 58 | # hex parser 59 | self.ih = IntelHex() 60 | # open file 61 | 62 | self.open_file() 63 | 64 | def open_file(self): 65 | print("> reading hex file '%s'" % (self.filename)) 66 | 67 | # read hex file 68 | self.ih.loadhex(self.filename) 69 | 70 | # verify that the reserved flash reigion is empty: 71 | address = self.flash_start; 72 | while(address < self.app_start): 73 | if (self.ih[address] != 0xFF): 74 | print("> ERROR: reserved region at flash end is not empty! FLASH[0x%X] = 0x%X (expected 0xFF)\n" % (address, self.ih[address])) 75 | sys.exit(1) 76 | address += 1 77 | self.data = "" 78 | address = self.app_start 79 | print("> input data : 0x%08X - 0x%08X" % (self.app_start, self.app_end)) 80 | while(address < self.app_end): 81 | c = chr(self.ih[address]) 82 | self.data = self.data + c 83 | address = address + 1 84 | 85 | print("> got data : " + 86 | " ".join("{:02x}".format(ord(c)) for c in self.data[0:16])+ 87 | " ... " + 88 | " ".join("{:02x}".format(ord(c)) for c in self.data[-32:])) 89 | 90 | # calc checksum over datablob WITHOUT magic page! 91 | crc_data = self.data 92 | print("> calc crc over %d bytes" % (len(crc_data))) 93 | print(" [" + " ".join("{:02x}".format(ord(c)) for c in crc_data[:16])) 94 | crc = self.crcmod(crc_data) 95 | crc_str = "" + chr((crc>>0)&0xFF) + chr((crc>>8)&0xFF) + chr((crc>>16)&0xFF) + chr((crc>> 24)&0xFF) 96 | 97 | # add magic page in front of data blob 98 | magic = crc_str # 4 byte crc 99 | magic = magic + "m" * 16 # 16 bytes magic (will be filled during enc) 100 | magic = magic + "\x00" * 12 # 12 bytes device id (will be filled later) 101 | # fill rest of page 102 | magic = magic + "\xFF" * (self.page_size - len(magic)) 103 | # prepend to data 104 | self.data = magic + self.data 105 | 106 | print("> added dummy magic page: " + 107 | " CRC32[" + " ".join("{:02x}".format(ord(c)) for c in self.data[0:4])+ "] [MAGIC]" + 108 | " ".join("{:02x}".format(ord(c)) for c in self.data[self.table:self.table+16])+ 109 | " ... " + 110 | " ".join("{:02x}".format(ord(c)) for c in self.data[-16:])+ 111 | " [%d bytes, CRC32 = 0x%08X]" % (len(self.data), crc)) 112 | 113 | 114 | def encrypt(self, key, iv, device): 115 | # parse into array: 116 | self.key = key.decode("hex") 117 | self.iv = iv.decode("hex") 118 | self.device = device.decode("hex") 119 | 120 | # show debug info 121 | print("> encoding...") 122 | print("> using key : " + " ".join("{:02x}".format(ord(c)) for c in self.key)) 123 | print("> using iv : " + " ".join("{:02x}".format(ord(c)) for c in self.iv)) 124 | print("> using deviceid: " + " ".join("{:02x}".format(ord(c)) for c in self.device)) 125 | 126 | # make sure that the key has the correct lenght: 127 | if len(self.key) != 32: 128 | print("> ERROR: key length mismatch, input key has to be 32 bytes as hex string!\n") 129 | sys.exit(1) 130 | if len(self.iv) != 16: 131 | print("> ERROR: iv length mismatch, input iv has to be 16 bytes as hex string!\n") 132 | sys.exit(1) 133 | if len(self.device) != 12: 134 | print("> ERROR: deviceid length mismatch, input deviceid has to be 12 bytes as hex string!\n") 135 | sys.exit(1) 136 | 137 | # update magic data + device id 138 | self.data = self.data[:4+16] + self.device + self.data[4+16+12:] 139 | 140 | print("> added magic page: " + 141 | " CRC32[" + " ".join("{:02x}".format(ord(c)) for c in self.data[0:4])+ "] " + 142 | " MAGIC[" + " ".join("{:02x}".format(ord(c)) for c in self.data[4:4+16])+ "] " + 143 | " DEVID[" + " ".join("{:02x}".format(ord(c)) for c in self.data[4+16:4+16+12])+ "] " + 144 | " ... " + 145 | " ".join("{:02x}".format(ord(c)) for c in self.data[-16:])+ 146 | " [%d bytes]" % (len(self.data))) 147 | 148 | 149 | # calculate AES256 CBC 150 | cipher = AES.new(self.key, AES.MODE_CBC, self.iv) 151 | encrypted = cipher.encrypt(self.data) 152 | 153 | print("> got encyrpted : " + 154 | " ".join("{:02x}".format(ord(c)) for c in encrypted[:16]) + 155 | " ... " + 156 | " ".join("{:02x}".format(ord(c)) for c in encrypted[-32:]) + 157 | " (%d bytes) " % (len(encrypted))) 158 | 159 | # store data in ihex formatter 160 | address = self.table 161 | i = 0 162 | while(address < self.app_end): 163 | self.ih[address] = ord(encrypted[i]) 164 | #print("ih[0x%X] = %X\n" % (address,self.ih[address])) 165 | address = address + 1 166 | i = i + 1 167 | 168 | output_fn = self.filename[:-3] + "aes.hex" 169 | print("> writing hex file '%s'" % (output_fn)) 170 | 171 | # write hex 172 | self.ih.write_hex_file(output_fn) 173 | 174 | 175 | if __name__ == "__main__": 176 | argp = argparse.ArgumentParser(description='encrypt_hex - a plain python encryption tool for intel hex files') 177 | 178 | argp.add_argument('-s', '--size', help='device flash size in KBytes, e.g. 64') 179 | argp.add_argument('-i', '--iv', help='initialization vector in hex format e.g. 0102....0F (16 bytes)') 180 | argp.add_argument('-k', '--key', help='encryption key in hex format e.g. AFFE1287817....BE (64 bytes)') 181 | argp.add_argument('-d', '--device', help='device id in hex format e.g. AFFE1287817....BE (12 bytes)') 182 | argp.add_argument('filename', help='input filename') 183 | args = argp.parse_args() 184 | 185 | print("###########################################") 186 | print("# encrypt_hex.py - (c) 2017 fishpepper.de #") 187 | print("###########################################") 188 | print("") 189 | 190 | ecrypt = STM32Encrypt(args.filename, args.size, debug=False) 191 | 192 | if (args.filename) and (args.key) and (args.iv) and (args.device): 193 | ecrypt.encrypt(args.key, args.iv, args.device) 194 | else: 195 | print() 196 | print("example: python encrypt_hex.py -s 64 -i 000102030405060708090A0B0C0D0E0F -k 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 -d 112233445566778899aabbcc ../../bin/tinyOSD.hex") 197 | print() 198 | argp.print_help() 199 | sys.exit(1) 200 | 201 | print 202 | sys.exit(0) 203 | -------------------------------------------------------------------------------- /font_mcm_to_h.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # read an ascii ppm generated by gimp 3 | # 4 | import sys 5 | import png 6 | 7 | if len(sys.argv) < 2: 8 | print "usage: " + sys.argv[0] + " file.mcm\n\n" 9 | sys.exit(1) 10 | 11 | fn = sys.argv[1] 12 | fh = open(fn, "r") 13 | 14 | #debug output image 15 | output_w = 192 16 | output_h = 287 17 | pngh = open('font.png', 'wb') 18 | pngw = png.Writer(output_w, output_h, greyscale=True) 19 | 20 | 21 | #skip MAX7456 coment 22 | version = fh.readline().strip() 23 | 24 | font_data = [] 25 | 26 | for n in range(256): 27 | for l in range(54): 28 | line = fh.readline().strip() 29 | byte = int(line, 2) 30 | font_data.append(byte) 31 | for l in range(10): 32 | # skip 10 dummy bytes 33 | fh.readline() 34 | 35 | # reformat to tinyOSD dataset 36 | font = [[], []] 37 | 38 | for data in font_data: 39 | for i in range(4): 40 | bitset = (data & 0xC0)>>6 41 | if (bitset == 0b00): 42 | # black 43 | font[0].append(0) 44 | font[1].append(1) 45 | elif (bitset == 0b10): 46 | # white 47 | font[0].append(1) 48 | font[1].append(0) 49 | else: 50 | # transparent 51 | font[0].append(0) 52 | font[1].append(0) 53 | data = data << 2 54 | 55 | # debug output png 56 | # font data is one char after the other (12px x 18px) 57 | pngdata = [] 58 | for y in range(output_h): 59 | row = [] 60 | for x in range(output_w): 61 | # fetch index. we have chars from left to right, top to bot 62 | char = (y/18)*16+(x/12) 63 | #print "char %d at %d x %d\n" %(char, x, y) 64 | idx = char*(12*18) + (x%12) + ((y%18)*12) 65 | if (font[0][idx] == 1): 66 | color = 0 67 | elif (font[1][idx] == 1): 68 | color = 255 69 | else: 70 | color = 128 71 | row.append(color) 72 | pngdata.append(row) 73 | 74 | #print(pngdata) 75 | 76 | pngw.write(pngh, pngdata) 77 | pngh.close() 78 | 79 | 80 | # dump to header 81 | fheader = open('src/font.h', 'w') 82 | 83 | fheader.write("#ifndef __FONT_H__\n") 84 | fheader.write("#define __FONT_H__\n") 85 | fheader.write("\n") 86 | 87 | fheader.write("// font data\n") 88 | fheader.write("static const uint8_t font_data[2][18][256*2] = {\n") 89 | 90 | # blow up font to 16 bits per pixel, add 2 px in front and back 91 | count = 0 92 | for col in range(2): 93 | fheader.write("\n { // color %d" % (col)) 94 | for row in range(18): 95 | fheader.write("\n { //row %d\n " % (row)) 96 | for char in range(256): 97 | index = char*(12*18) + row*12 98 | 99 | word = 0 100 | for i in range(12): 101 | bit = font[col][index + i] 102 | word = (word << 1) | bit 103 | word = word << 2 104 | fheader.write(hex((word >> 8) & 0xFF) + ", " + hex((word & 0xFF)) + ",") 105 | fheader.write("\n ") 106 | count = count + 1 107 | fheader.write(" },") 108 | fheader.write(" },") 109 | fheader.write("};\n") 110 | 111 | fheader.write("#endif // __FONT_H__\n") 112 | 113 | print ("wrote %d bytes font data" % ( count)) 114 | 115 | 116 | -------------------------------------------------------------------------------- /font_png_to_h.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # read an ascii ppm generated by gimp 3 | # 4 | import sys 5 | import png 6 | 7 | if len(sys.argv) < 2: 8 | print "usage: " + sys.argv[0] + " file.png\n\n" 9 | sys.exit(1) 10 | 11 | fn = sys.argv[1] 12 | fh = open(fn, "r") 13 | 14 | pngr = png.Reader(fh) 15 | (png_w, png_h, png_data, png_options) = pngr.read() 16 | 17 | print png_options 18 | 19 | raw_data = list(png_data) 20 | 21 | font = [[], []] 22 | 23 | for row in (raw_data): 24 | for x in range(0, len(row), 4): 25 | red = row[x] 26 | if (red == 0): 27 | # black 28 | font[1].append(1) 29 | font[0].append(0) 30 | elif (red == 255): 31 | # white 32 | font[1].append(0) 33 | font[0].append(1) 34 | else: 35 | # transparent 36 | font[1].append(0) 37 | font[0].append(0) 38 | 39 | print ("got %d bytes of fotn data\n" % (len(font[0]))) 40 | 41 | #debug output image 42 | max_char = 90 43 | output_w = max_char * 16 44 | output_h = png_h 45 | pngh = open('font.png', 'wb') 46 | pngw = png.Writer(output_w, output_h, greyscale=True) 47 | 48 | 49 | # debug output png 50 | # font data is one char after the other (12px x 18px) 51 | pngdata = [] 52 | for y in range(output_h): 53 | row = [] 54 | for x in range(max_char): 55 | for i in range(16): 56 | idx = png_w * y + x * 16 + i 57 | if (font[1][idx] == 1): 58 | color = 0 59 | elif (font[0][idx] == 1): 60 | color = 255 61 | else: 62 | color = 128 63 | row.append(color) 64 | pngdata.append(row) 65 | 66 | #print(pngdata) 67 | 68 | pngw.write(pngh, pngdata) 69 | 70 | pngh.close() 71 | 72 | 73 | # dump to header 74 | fheader = open('src/font.h', 'w') 75 | 76 | fheader.write("#ifndef __FONT_H__\n") 77 | fheader.write("#define __FONT_H__\n") 78 | fheader.write("\n") 79 | 80 | fheader.write("// font data\n") 81 | fheader.write("static const uint8_t font_data[2][18][256*2] = {\n") 82 | 83 | # blow up font to 16 bits per pixel, add 2 px in front and back 84 | count = 0 85 | for col in range(2): 86 | fheader.write("\n { // color %d" % (col)) 87 | for row in range(18): 88 | fheader.write("\n { //row %d\n " % (row)) 89 | for char in range(256): 90 | for b in range(2): 91 | byte = 0 92 | for i in range(8): 93 | index = 256*8*2 * row + char * 2 * 8 + b*8 + i 94 | bit = font[col][index] 95 | byte = (byte << 1) | bit 96 | fheader.write(hex(byte) + ", ") 97 | fheader.write("\n ") 98 | count = count + 1 99 | fheader.write(" },") 100 | fheader.write(" },") 101 | fheader.write("};\n") 102 | 103 | fheader.write("#endif // __FONT_H__\n") 104 | 105 | print ("wrote %d bytes font data" % ( count)) 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /fonts/combat_font.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishpepper/tinyOSD/0b783cd34302495adc637bcde434268e63862164/fonts/combat_font.png -------------------------------------------------------------------------------- /fonts/combat_font.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishpepper/tinyOSD/0b783cd34302495adc637bcde434268e63862164/fonts/combat_font.xcf -------------------------------------------------------------------------------- /generate_sin_table.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from __future__ import print_function 3 | import math 4 | 5 | print ("static const uint32_t video_cos_table[90] = {") 6 | for x in range(90): 7 | if (x % 8 == 0): 8 | print() 9 | print(hex(int(math.cos(x * 3.14 / 180.0) * 128)) + ",", end='') 10 | print("};") 11 | print() 12 | -------------------------------------------------------------------------------- /linker/stm32f051.ld: -------------------------------------------------------------------------------- 1 | /* linker script for STM32F051R8T6, 64K flash, 8K RAM) */ 2 | 3 | /* define memory regions */ 4 | MEMORY { 5 | rom (rx) : ORIGIN = 0x08000000, LENGTH = 64K 6 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K 7 | } 8 | 9 | /* Include the common ld script */ 10 | INCLUDE libopencm3_stm32f0.ld 11 | -------------------------------------------------------------------------------- /linker/stm32f301k8.ld: -------------------------------------------------------------------------------- 1 | /* linker script for STM32F301K8, 64K flash, 16K RAM) */ 2 | 3 | /* define memory regions */ 4 | MEMORY { 5 | /* flash is: BL ... [MAGIC PAGE] [APP] */ 6 | rom (rx) : ORIGIN = 0x08000000 + 5*2K + 1*2K, LENGTH = 64K-5*2K-1*2K 7 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K 8 | } 9 | 10 | /* Include the common ld script */ 11 | INCLUDE libopencm3_stm32f3.ld 12 | -------------------------------------------------------------------------------- /logo_to_h.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # read an ascii ppm generated by gimp 3 | # 4 | import sys 5 | 6 | if len(sys.argv) < 3: 7 | print "usage: " + sys.argv[0] + " file.ppm src/logo.h\n\n" 8 | sys.exit(1) 9 | 10 | fn = sys.argv[1] 11 | fh = open(fn, "r") 12 | outfn = sys.argv[2] 13 | out = open(outfn, "w") 14 | 15 | header = fh.readline() 16 | comment = fh.readline() 17 | dimension = fh.readline() 18 | maxcol = fh.readline() 19 | 20 | width = int(dimension.split()[0]) 21 | height = int(dimension.split()[1]) 22 | 23 | x = 0 24 | y = 0 25 | byte_out = 0 26 | byte_count = 0; 27 | # width has to be a multiple of 8: 28 | if not (width % 8 == 0): 29 | print("ERROR: image width has to be a multiple of 8!") 30 | sys.exit(1) 31 | 32 | 33 | imagedata = [[], []] # white and black bits 34 | i = 0 35 | 36 | for line in fh: 37 | #print(hex(int(line))) 38 | # skip blue and green: 39 | fh.next() 40 | fh.next() 41 | 42 | red_val = int(line) 43 | if (red_val == 0): 44 | # black overlay 45 | imagedata[0].append(0) 46 | imagedata[1].append(1) 47 | elif (red_val == 255): 48 | # white overlay 49 | imagedata[0].append(1) 50 | imagedata[1].append(0) 51 | elif (red_val > 60) and (red_val < 180): 52 | # transparent 53 | imagedata[0].append(0) 54 | imagedata[1].append(0) 55 | else: 56 | # "gray" overlay 57 | imagedata[0].append(1) 58 | imagedata[1].append(1) 59 | 60 | # next bit 61 | i = i + 1 62 | 63 | image_bytes = [[], []] # white and black bytes 64 | 65 | for col in range(2): 66 | byte = 0 67 | byte_count = 0 68 | for bit in imagedata[col]: 69 | byte = byte << 1 70 | if (bit != 0): 71 | byte = byte | 0x01 72 | 73 | if (byte_count == 8): 74 | # byte finished! 75 | image_bytes[col].append(byte) 76 | byte_count = 0 77 | byte = 0 78 | 79 | byte_count = byte_count + 1 80 | 81 | 82 | out.write("#ifndef LOGO_H__\n") 83 | out.write("#define LOGO_H__\n") 84 | out.write("#include \n") 85 | out.write("\n") 86 | out.write("#define LOGO_WIDTH " + str(width) + "\n") 87 | out.write("#define LOGO_HEIGHT " + str(height) + "\n") 88 | out.write("\n") 89 | 90 | 91 | # generate 16bit logo data: 92 | image_hwords = [[], []] 93 | 94 | for c in range(2): 95 | count = 1-c #white is 1 byte shifted 96 | hw = 0x00 97 | for x in image_bytes[c]: 98 | hw = (hw>>8) | (x<<8) 99 | if (count == 2): 100 | image_hwords[c].append(hw) 101 | hw = 0 102 | count = 0 103 | count = count + 1 104 | 105 | out.write("static const uint16_t logo_data16[2][LOGO_HEIGHT * (LOGO_WIDTH/8) / 2] = {\n") 106 | out.write(" {\n "); 107 | count = 0 108 | for x in image_hwords[0]: 109 | out.write(hex(x) + ", ") 110 | if ((count % 16) == 15): 111 | out.write("\n ") 112 | count = count + 1 113 | 114 | out.write("\n }, \n") 115 | out.write(" {\n "); 116 | count = 0 117 | for x in image_hwords[1]: 118 | out.write(hex(x) + ", ") 119 | if ((count % 16) == 15): 120 | out.write("\n ") 121 | count = count + 1 122 | 123 | out.write("\n }\n};") 124 | 125 | 126 | 127 | out.write("static const uint8_t logo_data8[2][LOGO_HEIGHT * (LOGO_WIDTH/8)] = {\n") 128 | out.write(" {\n "); 129 | count = 0 130 | for x in image_bytes[0]: 131 | out.write(hex(x) + ", ") 132 | if ((count % 16) == 15): 133 | out.write("\n ") 134 | count = count + 1 135 | 136 | out.write("\n }, \n") 137 | out.write(" {\n "); 138 | count = 0 139 | for x in image_bytes[1]: 140 | out.write(hex(x) + ", ") 141 | if ((count % 16) == 15): 142 | out.write("\n ") 143 | count = count + 1 144 | 145 | out.write("\n }\n};") 146 | 147 | 148 | 149 | out.write("\n#endif // LOGO_H__\n") 150 | fh.close() 151 | out.close() 152 | -------------------------------------------------------------------------------- /src/adc.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | This program is free software: you can redistribute it and/ or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | You should have received a copy of the GNU General Public License 12 | along with this program. If not, see . 13 | author: fishpepper gmail.com 14 | */ 15 | 16 | #include "adc.h" 17 | #include "debug.h" 18 | #include "led.h" 19 | #include "delay.h" 20 | #include "config.h" 21 | #include "macros.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | 29 | // internal functions 30 | static void adc_init_rcc(void); 31 | static void adc_init_gpio(void); 32 | static void adc_init_mode(void); 33 | 34 | void adc_init(void) { 35 | debug_function_call(); 36 | 37 | adc_init_rcc(); 38 | adc_init_gpio(); 39 | adc_init_mode(); 40 | } 41 | 42 | static void adc_init_rcc(void) { 43 | debug_function_call(); 44 | 45 | // enable adc clock 46 | rcc_periph_clock_enable(RCC_ADC12); 47 | 48 | // enable adc gpio clock 49 | rcc_periph_clock_enable(GPIO_RCC(VIDEO_ADC_GPIO)); 50 | 51 | // start with adc off 52 | adc_power_off(VIDEO_ADC); 53 | 54 | // ADC CLOCK = 48 / 4 = 12MHz 55 | adc_set_clk_prescale(VIDEO_ADC, ADC_CCR_CKMODE_DIV4); 56 | 57 | // run calibration 58 | adc_calibrate(VIDEO_ADC); 59 | } 60 | 61 | static void adc_init_gpio(void) { 62 | debug_function_call(); 63 | 64 | // set up analog inputs 65 | gpio_mode_setup(VIDEO_ADC_GPIO, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, VIDEO_ADC_PIN); 66 | 67 | /*gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9); 68 | gpio_set_af(GPIOA, GPIO_AF2, GPIO9);*/ 69 | } 70 | 71 | uint16_t adc_get_value(void) { 72 | uint16_t val = 10; 73 | if (ADC_ISR(VIDEO_ADC) & ADC_ISR_EOC){ 74 | val = ADC_DR(VIDEO_ADC); 75 | //debug_put_hex16(val); debug_put_newline(); 76 | return val; 77 | } 78 | //ADC_CR(VIDEO_ADC) |= ADC_CR_ADSTART; 79 | 80 | return val; 81 | } 82 | 83 | static void adc_init_mode(void) { 84 | debug_function_call(); 85 | 86 | // change settings while disabled 87 | adc_power_off(VIDEO_ADC); 88 | 89 | // set mode to continous 90 | //adc_set_continuous_conversion_mode(VIDEO_ADC); 91 | adc_disable_discontinuous_mode_regular(VIDEO_ADC); 92 | //FIXME? adc_set_operation_mode (VIDEO_ADC, ADC_MODE_SEQUENTIAL); 93 | adc_set_single_conversion_mode(VIDEO_ADC); 94 | 95 | // ext trigger: TIM1_TRGO 96 | adc_enable_external_trigger_regular(VIDEO_ADC, ADC_CFGR1_EXTSEL_VAL(0), ADC_CFGR1_EXTEN_RISING_EDGE); 97 | 98 | // right 12-bit data alignment in ADC reg 99 | adc_set_right_aligned(VIDEO_ADC); 100 | adc_set_resolution(VIDEO_ADC, ADC_CFGR1_RES_12_BIT); 101 | 102 | // adc_enable_temperature_sensor(); 103 | adc_disable_analog_watchdog_regular(VIDEO_ADC); 104 | 105 | // configure channel 106 | uint8_t channels[] = { VIDEO_ADC_CHANNEL }; 107 | 108 | // sample times for all channels 109 | adc_set_sample_time_on_all_channels(VIDEO_ADC, ADC_SMPR_SMP_61DOT5CYC); 110 | 111 | adc_set_regular_sequence(VIDEO_ADC, sizeof(channels), channels); 112 | 113 | // start up adc 114 | adc_power_on(VIDEO_ADC); 115 | 116 | // wait for ADC starting up 117 | int i; 118 | for (i = 0; i < 800000; i++) { 119 | asm("nop"); 120 | } 121 | 122 | // enable triggering per timer 123 | ADC_CR(VIDEO_ADC) |= ADC_CR_ADSTART; 124 | } 125 | -------------------------------------------------------------------------------- /src/adc.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef ADC_H_ 21 | #define ADC_H_ 22 | 23 | #include 24 | 25 | void adc_init(void); 26 | uint16_t adc_get_value(void); 27 | 28 | #endif // ADC_H_ 29 | -------------------------------------------------------------------------------- /src/clocksource.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #include "clocksource.h" 21 | #include "config.h" 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | 28 | #if CPU_CLOCK == 72000000 29 | static void clocksource_hse_in_8_out_72(void); 30 | #endif 31 | #if CPU_CLOCK == 48000000 32 | static void clocksource_hse_in_8_out_48(void); 33 | #endif 34 | 35 | uint32_t rcc_timer_frequency; 36 | 37 | void clocksource_init(void) { 38 | // set clock source 39 | #if CPU_CLOCK == 48000000 40 | clocksource_hse_in_8_out_48(); 41 | #elif CPU_CLOCK == 72000000 42 | clocksource_hse_in_8_out_72(); 43 | #else 44 | ERROR: unsupported clock freq requested 45 | #endif 46 | } 47 | 48 | #if CPU_CLOCK == 72000000 49 | static void clocksource_hse_in_8_out_72(void) { 50 | // see RM0366 p. 92 for clock tree 51 | 52 | // enable internal high-speed oscillator 53 | // we will run from hsi during setup 54 | rcc_osc_on(RCC_HSI); 55 | rcc_wait_for_osc_ready(RCC_HSI); 56 | 57 | // Select HSI as SYSCLK source. 58 | rcc_set_sysclk_source(RCC_CFGR_SW_HSI); 59 | 60 | // Enable external high-speed oscillator 8MHz 61 | rcc_osc_on(RCC_HSE); 62 | rcc_wait_for_osc_ready(RCC_HSE); 63 | 64 | // disable pll during setup (madatory!) 65 | rcc_osc_off(RCC_PLL); 66 | rcc_wait_for_osc_not_ready(RCC_PLL); 67 | 68 | // set up HSE 8MHz to PLL out 72 MHz 69 | // PL OUT = HSE/1 * 9 = 72 70 | rcc_set_prediv(RCC_CFGR2_PREDIV_NODIV); 71 | rcc_set_pll_source(RCC_CFGR_PLLSRC_HSE_PREDIV); 72 | rcc_set_pll_multiplier(RCC_CFGR_PLLMUL_PLL_IN_CLK_X9); 73 | 74 | // start pll 75 | rcc_osc_on(RCC_PLL); 76 | rcc_wait_for_osc_ready(RCC_PLL); 77 | 78 | // set up prescalers for AHB, ADC, ABP1, ABP2. 79 | // do this before setting sysclock source to PLL 80 | // otherwise we might run the peripherals at a frequency 81 | // that exceeds the limits 82 | rcc_set_hpre(RCC_CFGR_HPRE_DIV_NONE); // 72MHz (max: 72) 83 | rcc_set_ppre2(RCC_CFGR_PPRE2_DIV_2); // 36MHz (max: 72) 84 | rcc_set_ppre1(RCC_CFGR_PPRE1_DIV_2); // 36MHz (max: 36) 85 | 86 | // set flash waitstates 87 | flash_set_ws(FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_2WS); 88 | 89 | // finally select PLL as SYSCLK source 90 | rcc_set_sysclk_source(RCC_CFGR_SW_PLL); 91 | 92 | // set the peripheral clock frequencies used */ 93 | rcc_ahb_frequency = 72000000; 94 | rcc_apb1_frequency = 36000000; 95 | rcc_apb2_frequency = 36000000; 96 | } 97 | #endif 98 | 99 | #if CPU_CLOCK == 48000000 100 | static void clocksource_hse_in_8_out_48(void) { 101 | // see RM0366 p. 92 for clock tree 102 | 103 | // enable internal high-speed oscillator 104 | // we will run from hsi during setup 105 | rcc_osc_on(RCC_HSI); 106 | rcc_wait_for_osc_ready(RCC_HSI); 107 | 108 | // Select HSI as SYSCLK source. 109 | rcc_set_sysclk_source(RCC_CFGR_SW_HSI); 110 | 111 | // Enable external high-speed oscillator 8MHz 112 | rcc_osc_on(RCC_HSE); 113 | rcc_wait_for_osc_ready(RCC_HSE); 114 | 115 | // disable pll during setup (madatory!) 116 | rcc_osc_off(RCC_PLL); 117 | rcc_wait_for_osc_not_ready(RCC_PLL); 118 | 119 | // set up HSE 8MHz to PLL out 48 MHz 120 | // PL OUT = HSE/2 * 12 = 4 * 12 = 48 121 | rcc_set_prediv(RCC_CFGR2_PREDIV_DIV2); 122 | rcc_set_pll_source(RCC_CFGR_PLLSRC_HSE_PREDIV); 123 | rcc_set_pll_multiplier(RCC_CFGR_PLLMUL_PLL_IN_CLK_X12); 124 | 125 | // start pll 126 | rcc_osc_on(RCC_PLL); 127 | rcc_wait_for_osc_ready(RCC_PLL); 128 | 129 | // set up prescalers for AHB, ADC, ABP1, ABP2. 130 | // do this before setting sysclock source to PLL 131 | // otherwise we might run the peripherals at a frequency 132 | // that exceeds the limits 133 | rcc_set_hpre(RCC_CFGR_HPRE_DIV_NONE); // 48MHz (max: 72) 134 | rcc_set_ppre2(RCC_CFGR_PPRE2_DIV_2); // 24MHz (max: 72) 135 | rcc_set_ppre1(RCC_CFGR_PPRE1_DIV_2); // 24MHz (max: 36) 136 | 137 | // set flash waitstates 138 | flash_set_ws(FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_1WS); 139 | 140 | // finally select PLL as SYSCLK source 141 | rcc_set_sysclk_source(RCC_CFGR_SW_PLL); 142 | 143 | // set the peripheral clock frequencies used */ 144 | rcc_ahb_frequency = 48000000; 145 | rcc_apb1_frequency = 24000000; 146 | rcc_apb2_frequency = 24000000; 147 | } 148 | #endif 149 | -------------------------------------------------------------------------------- /src/clocksource.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef CLOCKSOURCE_H_ 21 | #define CLOCKSOURCE_H_ 22 | 23 | #include 24 | extern uint32_t rcc_timer_frequency; 25 | 26 | void clocksource_init(void); 27 | 28 | #endif // CLOCKSOURCE_H_ 29 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | // datasheets STM32F301 2 | // RM: http://www.st.com/resource/en/reference_manual/dm00094350.pdf 3 | // DS: http://www.keil.com/dd/docs/datashts/st/stm32f3xx/dm00093332.pdf 4 | 5 | #define DEBUG_PRINTS_ENABLED 1 6 | 7 | #define CAMOSD_RUNCAM 0 8 | #define CAMOSD_VM275 1 9 | #define EVALBOARD 2 10 | #define TINYFINITY 3 11 | 12 | 13 | //#define BOARD CAMOSD_VM275 14 | //#define BOARD CAMOSD_VM275 15 | #define BOARD TINYFINITY 16 | 17 | #if (BOARD == CAMOSD_VM275) 18 | // vm275 19 | #define CPU_VOLTAGE 1.8 20 | #define LED_GPIO GPIOA 21 | #define LED_PIN GPIO5 22 | #define VIDEO_BSYNC_VOLTAGE_MV 100 23 | #define VIDEO_DAC_VCC CPU_VOLTAGE 24 | #elif (BOARD == CAMOSD_RUNCAM) 25 | // camOSD runcam 26 | #define CPU_VOLTAGE 1.8 27 | #define LED_GPIO GPIOA 28 | #define LED_PIN GPIO5 29 | #define VIDEO_BSYNC_VOLTAGE_MV 210 30 | #define VIDEO_DAC_VCC CPU_VOLTAGE 31 | #elif (BOARD == TINYFINITY) 32 | // tinyFINITY 33 | #define CPU_VOLTAGE 3.3 34 | // led disabled 35 | #define LED_GPIO GPIOB 36 | #define LED_PIN GPIO0 37 | #define VIDEO_BSYNC_VOLTAGE_MV 100 38 | #define VIDEO_DAC_VCC CPU_VOLTAGE 39 | #else 40 | // eval board 41 | #define CPU_VOLTAGE 3.3 42 | #if 1 43 | //disabled 44 | #define LED_GPIO GPIOB 45 | #define LED_PIN GPIO0 46 | #else 47 | #define LED_GPIO GPIOE 48 | #define LED_PIN GPIO14 49 | #endif 50 | #define VIDEO_BSYNC_VOLTAGE_MV 100 51 | #define VIDEO_DAC_VCC CPU_VOLTAGE 52 | #endif 53 | 54 | #define CPU_CLOCK 48000000 55 | 56 | #define VIDEO_LEVEL_TERMINATION_R 75.0 57 | #define VIDEO_LEVEL_R2R_1R 169.0 58 | 59 | #define VIDEO_ADC ADC1 60 | #define VIDEO_ADC_CHANNEL 10 61 | #define VIDEO_ADC_GPIO GPIOA 62 | #define VIDEO_ADC_PIN GPIO6 63 | 64 | /*#define DEBUG_GPIO GPIOA 65 | #define DEBUG_GPIO_AF GPIO_AF1 66 | #define DEBUG_UART USART2 67 | #define DEBUG_UART_RCC RCC_USART2 68 | #define DEBUG_TX_PIN GPIO14 69 | #define DEBUG_UART_BAUDRATE 115200*/ 70 | 71 | #define DEBUG_GPIO GPIOA 72 | #define DEBUG_GPIO_AF GPIO_AF7 73 | #define DEBUG_UART USART2 74 | #define DEBUG_UART_RCC RCC_USART2 75 | #define DEBUG_TX_PIN GPIO2 76 | #define DEBUG_UART_BAUDRATE 115200 77 | 78 | #define SERIAL_GPIO GPIOA 79 | #define SERIAL_GPIO_AF GPIO_AF7 80 | #define SERIAL_UART USART2 81 | #define SERIAL_UART_RCC RCC_USART2 82 | #define SERIAL_UART_IRQ USART2_EXTI26_IRQHandler 83 | #define SERIAL_UART_IRQN NVIC_USART2_EXTI26_IRQ 84 | #define SERIAL_TX_PIN GPIO2 85 | #define SERIAL_RX_PIN GPIO3 86 | #define SERIAL_UART_BAUDRATE 115200 87 | 88 | 89 | 90 | #define RTC6705_GPIO GPIOA 91 | #define RTC6705_PIN_DATA GPIO5 92 | #define RTC6705_PIN_DATA_PIN_ID 5 93 | #define RTC6705_PIN_SCK GPIO1 94 | #define RTC6705_PIN_CS GPIO0 95 | 96 | 97 | #define SERIAL_OVERRUN_DETECTION_DISABLED 0 98 | 99 | #define NVIC_PRIO_COMPARATOR 0*64 100 | #define NVIC_PRIO_TIMER1 1*64 101 | #define NVIC_PRIO_SYSTICK 2*64 102 | #define NVIC_PRIO_DMA1 1*64 103 | #define NVIC_PRIO_PENDSV 2*64 104 | #define NVIC_PRIO_USART 3*64 105 | 106 | #define VIDEO_GPIO GPIOA 107 | #define VIDEO_INPUT_PIN GPIO7 108 | #define VIDEO_DAC_OUT_PIN GPIO4 109 | 110 | 111 | #if 0 112 | 113 | #define VIDEO_BLACK_GPIO GPIOB 114 | #define VIDEO_BLACK_MOSI_PIN GPIO5 115 | #define VIDEO_BLACK_MOSI_AF GPIO_AF6 116 | #define VIDEO_BLACK_DMA_CH DMA_CHANNEL3 117 | #define VIDEO_BLACK_DMA_IRQ NVIC_DMA1_CHANNEL3_IRQ 118 | #define VIDEO_BLACK_DMA_IRQ_HANDLER DMA1_CHANNEL3_IRQHandler 119 | #define VIDEO_BLACK_TIMER_DMA_CH DMA_CHANNEL2 120 | 121 | #define VIDEO_WHITE_GPIO GPIOA 122 | #define VIDEO_WHITE_MOSI_PIN GPIO11 123 | #define VIDEO_WHITE_MOSI_AF GPIO_AF5 124 | #define VIDEO_WHITE_DMA_CH DMA_CHANNEL5 125 | #define VIDEO_WHITE_DMA_IRQ NVIC_DMA1_CHANNEL5_IRQ 126 | #define VIDEO_WHITE_DMA_IRQ_HANDLER DMA1_CHANNEL5_IRQHandler 127 | #define VIDEO_WHITE_TIMER_DMA_CH DMA_CHANNEL4 128 | 129 | #define VIDEO_SPI_WHITE SPI2 130 | #define VIDEO_SPI_WHITE_RCC RCC_SPI2 131 | 132 | #define VIDEO_SPI_BLACK SPI3 133 | #define VIDEO_SPI_BLACK_RCC RCC_SPI3 134 | 135 | 136 | #define VIDEO_MUX_WHITE_GPIO GPIOA 137 | #define VIDEO_MUX_WHITE_DAC0 GPIO8 138 | #define VIDEO_MUX_WHITE_DAC1 GPIO9 139 | #define VIDEO_MUX_WHITE_DAC2 GPIO10 140 | #define VIDEO_MUX_WHITE_DAC3 GPIO12 141 | 142 | #define VIDEO_MUX_BLACK_GPIO GPIOB 143 | #define VIDEO_MUX_BLACK_DAC0 GPIO3 144 | #define VIDEO_MUX_BLACK_DAC1 GPIO4 145 | #define VIDEO_MUX_BLACK_DAC2 GPIO6 146 | #define VIDEO_MUX_BLACK_DAC3 GPIO7 147 | 148 | #else 149 | 150 | #define VIDEO_BLACK_GPIO GPIOA 151 | #define VIDEO_BLACK_MOSI_PIN GPIO11 152 | #define VIDEO_BLACK_MOSI_AF GPIO_AF5 153 | #define VIDEO_BLACK_DMA_CH DMA_CHANNEL5 154 | #define VIDEO_BLACK_DMA_IRQ NVIC_DMA1_CHANNEL5_IRQ 155 | #define VIDEO_BLACK_DMA_IRQ_HANDLER DMA1_CHANNEL5_IRQHandler 156 | #define VIDEO_BLACK_TIMER_DMA_CH DMA_CHANNEL4 157 | 158 | 159 | #define VIDEO_WHITE_GPIO GPIOB 160 | #define VIDEO_WHITE_MOSI_PIN GPIO5 161 | #define VIDEO_WHITE_MOSI_AF GPIO_AF6 162 | #define VIDEO_WHITE_DMA_CH DMA_CHANNEL3 163 | #define VIDEO_WHITE_DMA_IRQ NVIC_DMA1_CHANNEL3_IRQ 164 | #define VIDEO_WHITE_DMA_IRQ_HANDLER DMA1_CHANNEL3_IRQHandler 165 | #define VIDEO_WHITE_TIMER_DMA_CH DMA_CHANNEL2 166 | 167 | #define VIDEO_SPI_WHITE SPI3 168 | #define VIDEO_SPI_WHITE_RCC RCC_SPI3 169 | 170 | #define VIDEO_SPI_BLACK SPI2 171 | #define VIDEO_SPI_BLACK_RCC RCC_SPI2 172 | 173 | 174 | #define VIDEO_MUX_BLACK_GPIO GPIOA 175 | #define VIDEO_MUX_BLACK_DAC0 GPIO8 176 | #define VIDEO_MUX_BLACK_DAC1 GPIO9 177 | #define VIDEO_MUX_BLACK_DAC2 GPIO10 178 | #define VIDEO_MUX_BLACK_DAC3 GPIO12 179 | 180 | #define VIDEO_MUX_WHITE_GPIO GPIOB 181 | #define VIDEO_MUX_WHITE_DAC0 GPIO3 182 | #define VIDEO_MUX_WHITE_DAC1 GPIO4 183 | #define VIDEO_MUX_WHITE_DAC2 GPIO6 184 | #define VIDEO_MUX_WHITE_DAC3 GPIO7 185 | 186 | #endif 187 | 188 | #define VIDEO_COMP_EXTI_SOURCE GPIOA 189 | #define VIDEO_COMP_EXTI_SOURCE_LINE EXTI22 190 | #define VIDEO_COMP_EXTI_IRQN NVIC_COMP123_IRQ 191 | #define VIDEO_COMP COMP2 192 | 193 | 194 | #define VIDEO_DMA_WHITE DMA1 195 | #define VIDEO_DMA_BLACK DMA1 196 | #define VIDEO_DMA_CHANNEL_WHITE DMA_CHANNEL3 197 | 198 | 199 | 200 | //#define DEBUG_GPIO GPIOA 201 | //#define DEBUG_GPIO_AF GPIO_AF1 202 | //#define DEBUG_UART USART2 203 | //#define DEBUG_UART_RCC RCC_USART2 204 | //#define DEBUG_TX_PIN GPIO14 205 | //#define DEBUG_UART_BAUDRATE 115200 206 | // 207 | //#define SERIAL_GPIO GPIOA 208 | //#define SERIAL_GPIO_AF GPIO_AF1 209 | //#define SERIAL_UART USART 210 | //#define SERIAL_UART_RCC RCC_USART1 211 | //#define SERIAL_TX_PIN GPIO9 212 | //#define SERIAL_RX_PIN GPIO10 213 | //#define SERIAL_UART_BAUDRATE 115200 214 | 215 | 216 | 217 | -------------------------------------------------------------------------------- /src/crc8.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef CRC8_H_ 21 | #define CRC8_H_ 22 | 23 | #include 24 | 25 | // dvb s2 crc8 (poly 0xD5) lookup table 26 | static const uint8_t crc8_table[256] = { 27 | 0x0, 0xd5, 0x7f, 0xaa, 0xfe, 0x2b, 0x81, 0x54, 28 | 0x29, 0xfc, 0x56, 0x83, 0xd7, 0x2, 0xa8, 0x7d, 29 | 0x52, 0x87, 0x2d, 0xf8, 0xac, 0x79, 0xd3, 0x6, 30 | 0x7b, 0xae, 0x4, 0xd1, 0x85, 0x50, 0xfa, 0x2f, 31 | 0xa4, 0x71, 0xdb, 0xe, 0x5a, 0x8f, 0x25, 0xf0, 32 | 0x8d, 0x58, 0xf2, 0x27, 0x73, 0xa6, 0xc, 0xd9, 33 | 0xf6, 0x23, 0x89, 0x5c, 0x8, 0xdd, 0x77, 0xa2, 34 | 0xdf, 0xa, 0xa0, 0x75, 0x21, 0xf4, 0x5e, 0x8b, 35 | 0x9d, 0x48, 0xe2, 0x37, 0x63, 0xb6, 0x1c, 0xc9, 36 | 0xb4, 0x61, 0xcb, 0x1e, 0x4a, 0x9f, 0x35, 0xe0, 37 | 0xcf, 0x1a, 0xb0, 0x65, 0x31, 0xe4, 0x4e, 0x9b, 38 | 0xe6, 0x33, 0x99, 0x4c, 0x18, 0xcd, 0x67, 0xb2, 39 | 0x39, 0xec, 0x46, 0x93, 0xc7, 0x12, 0xb8, 0x6d, 40 | 0x10, 0xc5, 0x6f, 0xba, 0xee, 0x3b, 0x91, 0x44, 41 | 0x6b, 0xbe, 0x14, 0xc1, 0x95, 0x40, 0xea, 0x3f, 42 | 0x42, 0x97, 0x3d, 0xe8, 0xbc, 0x69, 0xc3, 0x16, 43 | 0xef, 0x3a, 0x90, 0x45, 0x11, 0xc4, 0x6e, 0xbb, 44 | 0xc6, 0x13, 0xb9, 0x6c, 0x38, 0xed, 0x47, 0x92, 45 | 0xbd, 0x68, 0xc2, 0x17, 0x43, 0x96, 0x3c, 0xe9, 46 | 0x94, 0x41, 0xeb, 0x3e, 0x6a, 0xbf, 0x15, 0xc0, 47 | 0x4b, 0x9e, 0x34, 0xe1, 0xb5, 0x60, 0xca, 0x1f, 48 | 0x62, 0xb7, 0x1d, 0xc8, 0x9c, 0x49, 0xe3, 0x36, 49 | 0x19, 0xcc, 0x66, 0xb3, 0xe7, 0x32, 0x98, 0x4d, 50 | 0x30, 0xe5, 0x4f, 0x9a, 0xce, 0x1b, 0xb1, 0x64, 51 | 0x72, 0xa7, 0xd, 0xd8, 0x8c, 0x59, 0xf3, 0x26, 52 | 0x5b, 0x8e, 0x24, 0xf1, 0xa5, 0x70, 0xda, 0xf, 53 | 0x20, 0xf5, 0x5f, 0x8a, 0xde, 0xb, 0xa1, 0x74, 54 | 0x9, 0xdc, 0x76, 0xa3, 0xf7, 0x22, 0x88, 0x5d, 55 | 0xd6, 0x3, 0xa9, 0x7c, 0x28, 0xfd, 0x57, 0x82, 56 | 0xff, 0x2a, 0x80, 0x55, 0x1, 0xd4, 0x7e, 0xab, 57 | 0x84, 0x51, 0xfb, 0x2e, 0x7a, 0xaf, 0x5, 0xd0, 58 | 0xad, 0x78, 0xd2, 0x7, 0x53, 0x86, 0x2c, 0xf9, 59 | }; 60 | 61 | 62 | 63 | /*#define CRC8_UPDATE(__crc, __a) { \ 64 | (__crc) ^= (__a); \ 65 | for (uint8_t _ii = 0; _ii < 8; ++_ii) { \ 66 | if ((__crc) & 0x80) { \ 67 | (__crc) = ((__crc) << 1) ^ 0xD5; \ 68 | } else { \ 69 | (__crc) = (__crc) << 1; \ 70 | } \ 71 | } \ 72 | }*/ 73 | 74 | #define CRC8_UPDATE(__crc, __val) ((__crc) = crc8_table[(__crc) ^ (__val)]) 75 | #define CRC8_INIT(__crc, __ival) { (__crc) = (__ival); } 76 | 77 | 78 | 79 | #endif // CRC8_H_ 80 | -------------------------------------------------------------------------------- /src/debug.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/ or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #include "debug.h" 21 | #include "delay.h" 22 | #include "main.h" 23 | #include "macros.h" 24 | #include 25 | #include "config.h" 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #if DEBUG_PRINTS_ENABLED 32 | static void debug_init_gpio(void); 33 | static void debug_init_rcc(void); 34 | static void debug_init_uart(void); 35 | 36 | void debug_init(void) { 37 | debug_init_rcc(); 38 | debug_init_gpio(); 39 | debug_init_uart(); 40 | 41 | debug_put_newline(); 42 | // ################### 43 | debug("### tinyOSD ###\n"); 44 | debug(" (c) by fishpepper \n\n"); 45 | debug("debug: init done\n"); 46 | } 47 | 48 | void debug_init_rcc(void) { 49 | // peripheral clocks enable 50 | rcc_periph_clock_enable(GPIO_RCC(DEBUG_GPIO)); 51 | rcc_periph_clock_enable(DEBUG_UART_RCC); 52 | } 53 | 54 | void debug_init_gpio(void) { 55 | // set uart tx pin as output 56 | gpio_mode_setup(DEBUG_GPIO, GPIO_MODE_AF, GPIO_PUPD_NONE, DEBUG_TX_PIN); 57 | gpio_set_output_options(DEBUG_GPIO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, DEBUG_TX_PIN); 58 | 59 | // setup USART TX pin as alternate function 60 | gpio_set_af(DEBUG_GPIO, DEBUG_GPIO_AF, DEBUG_TX_PIN); 61 | } 62 | 63 | void debug_init_uart(void) { 64 | // setup USART parameters 65 | usart_set_baudrate(DEBUG_UART, DEBUG_UART_BAUDRATE); 66 | usart_set_databits(DEBUG_UART, 8); 67 | usart_set_parity(DEBUG_UART, USART_PARITY_NONE); 68 | usart_set_stopbits(DEBUG_UART, USART_CR2_STOPBITS_1); 69 | usart_set_mode(DEBUG_UART, USART_MODE_TX); 70 | usart_set_flow_control(DEBUG_UART, USART_FLOWCONTROL_NONE); 71 | 72 | // finally enable the USART 73 | usart_enable(DEBUG_UART); 74 | } 75 | 76 | 77 | void debug_putc(uint8_t ch) { 78 | // add \r to newlines 79 | if (ch == '\n') debug_putc('\r'); 80 | usart_send_blocking(DEBUG_UART, ch); 81 | } 82 | 83 | void debug_flush(void) { 84 | } 85 | 86 | 87 | void debug(char *data) { 88 | uint8_t c = (uint8_t)*data++; 89 | while (c) { 90 | debug_putc(c); 91 | c = *data++; 92 | } 93 | } 94 | 95 | 96 | // put hexadecimal number to debug out. 97 | void debug_put_hex8(uint8_t val) { 98 | uint8_t lo = val&0x0F; 99 | uint8_t hi = val>>4; 100 | if (hi < 0x0A) { 101 | hi = '0' + hi; 102 | } else { 103 | hi = 'A' - 0x0A + hi; 104 | } 105 | 106 | if (lo < 0x0A) { 107 | lo = '0' + lo; 108 | } else { 109 | lo = 'A' - 0x0A + lo; 110 | } 111 | debug_putc(hi); 112 | debug_putc(lo); 113 | } 114 | 115 | // put 16bit hexadecimal number to debug out 116 | void debug_put_hex16(uint16_t val) { 117 | debug_put_hex8(val>>8); 118 | debug_put_hex8(val & 0xFF); 119 | } 120 | 121 | // put 32bit hexadecimal number to debug out 122 | void debug_put_hex32(uint32_t val) { 123 | debug_put_hex8(val>>24); 124 | debug_put_hex8(val>>16); 125 | debug_put_hex8(val>> 8); 126 | debug_put_hex8(val & 0xFF); 127 | } 128 | 129 | // output a signed 8-bit number to uart 130 | void debug_put_int8(int8_t c) { 131 | uint8_t tmp; 132 | uint8_t mul; 133 | uint8_t l; 134 | uint8_t uint_s; 135 | 136 | if (c < 0) { 137 | debug_putc('-'); 138 | uint_s = -c; 139 | } else { 140 | uint_s = c; 141 | } 142 | 143 | l = 0; 144 | for (mul = 100; mul > 0; mul = mul/ 10) { 145 | tmp = '0'; 146 | while (uint_s >= mul) { 147 | uint_s -= mul; 148 | tmp++; 149 | l = 1; 150 | } 151 | if ((l == 0) && (tmp == '0') && (mul != 1)) { 152 | // dont print spacer 153 | // debug_putc(' '); 154 | } else { 155 | debug_putc(tmp); 156 | } 157 | } 158 | } 159 | 160 | // output an unsigned 8-bit number to uart 161 | void debug_put_uint8(uint8_t c) { 162 | uint8_t tmp; 163 | uint8_t mul; 164 | uint8_t l; 165 | 166 | l = 0; 167 | for (mul = 100; mul >0 ; mul = mul/ 10) { 168 | tmp = '0'; 169 | while (c >= mul) { 170 | c -= mul; 171 | tmp++; 172 | l = 1; 173 | } 174 | if ((l == 0) && (tmp == '0') && (mul != 1)) { 175 | // dont print spacer 176 | // debug_putc(' '); 177 | } else { 178 | debug_putc(tmp); 179 | } 180 | } 181 | } 182 | 183 | // output an unsigned 16-bit number to uart 184 | void debug_put_uint16(uint16_t c) { 185 | uint8_t tmp; 186 | uint8_t l = 0; 187 | // loop unrolling is better(no int16 arithmetic) 188 | /*for (mul = 10000; mul>0; mul = mul/ 10) { 189 | uint16_t mul; 190 | 191 | l = 0; 192 | tmp = '0'; 193 | while (c>=mul) { 194 | c -= mul; 195 | tmp++; 196 | l = 1; 197 | } 198 | if ((l == 0) && (tmp == '0') && (mul!=1)) { 199 | // debug_putc(' '); 200 | } else { 201 | debug_putc(tmp); 202 | } 203 | }*/ 204 | tmp = 0; 205 | while (c >= 10000L) { 206 | c -= 10000L; 207 | tmp++; 208 | l = 1; 209 | } 210 | if (tmp != 0) debug_putc('0' + tmp); 211 | 212 | tmp = 0; 213 | while (c >= 1000L) { 214 | c -= 1000L; 215 | tmp++; 216 | l = 1; 217 | } 218 | if (l || (tmp != 0)) debug_putc('0' + tmp); 219 | 220 | tmp = 0; 221 | while (c >= 100) { 222 | c -= 100; 223 | tmp++; 224 | l = 1; 225 | } 226 | if (l || (tmp != 0)) debug_putc('0' + tmp); 227 | 228 | tmp = 0; 229 | while (c >= 10) { 230 | c -= 10; 231 | tmp++; 232 | l = 1; 233 | } 234 | if (l || (tmp != 0)) debug_putc('0' + tmp); 235 | 236 | debug_putc('0' + (uint8_t)c); 237 | } 238 | 239 | void debug_put_fixed2(uint16_t c) { 240 | uint8_t tmp; 241 | uint8_t l = 0; 242 | tmp = 0; 243 | while (c >= 10000L) { 244 | c -= 10000L; 245 | tmp++; 246 | l = 1; 247 | } 248 | if (tmp != 0) debug_putc('0' + tmp); 249 | 250 | tmp = 0; 251 | while (c >= 1000L) { 252 | c -= 1000L; 253 | tmp++; 254 | l = 1; 255 | } 256 | if (l || (tmp != 0)) debug_putc('0' + tmp); 257 | 258 | tmp = 0; 259 | while (c >= 100) { 260 | c -= 100; 261 | tmp++; 262 | l = 1; 263 | } 264 | if (l || (tmp != 0)) debug_putc('0' + tmp); 265 | 266 | debug_putc('.'); 267 | 268 | tmp = 0; 269 | while (c >= 10) { 270 | c -= 10; 271 | tmp++; 272 | l = 1; 273 | } 274 | if (l || (tmp != 0)) debug_putc('0' + tmp); 275 | 276 | debug_putc('0' + (uint8_t)c); 277 | } 278 | 279 | void debug_put_fixed1p3(uint16_t c) { 280 | uint8_t tmp; 281 | tmp = 0; 282 | while (c >= 1000L) { 283 | c -= 1000L; 284 | tmp++; 285 | } 286 | debug_putc('0' + tmp); 287 | 288 | debug_putc('.'); 289 | 290 | tmp = 0; 291 | while (c >= 100) { 292 | c -= 100; 293 | tmp++; 294 | } 295 | debug_putc('0' + tmp); 296 | 297 | tmp = 0; 298 | while (c >= 10) { 299 | c -= 10; 300 | tmp++; 301 | } 302 | debug_putc('0' + tmp); 303 | 304 | debug_putc('0' + (uint8_t)c); 305 | } 306 | 307 | void debug_put_newline(void) { 308 | debug_putc('\n'); 309 | } 310 | 311 | #endif 312 | -------------------------------------------------------------------------------- /src/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef DEBUG_H_ 21 | #define DEBUG_H_ 22 | 23 | #include 24 | #include "config.h" 25 | 26 | #if DEBUG_PRINTS_ENABLED 27 | void debug_init(void); 28 | void debug_putc(uint8_t ch); 29 | void debug_flush(void); 30 | void debug(char *data); 31 | void debug_put_hex8(uint8_t val); 32 | void debug_put_hex16(uint16_t val); 33 | void debug_put_hex32(uint32_t val); 34 | void debug_put_uint8(uint8_t c); 35 | void debug_put_int8(int8_t c); 36 | void debug_put_uint16(uint16_t c); 37 | void debug_put_newline(void); 38 | void debug_put_fixed2(uint16_t c); 39 | void debug_put_fixed1p3(uint16_t c); 40 | 41 | #else 42 | #define debug_init() {} 43 | #define debug_putc(x) {} 44 | #define debug_flush() {} 45 | #define debug(x) {} 46 | #define debug_put_hex8(x) {} 47 | #define debug_put_hex16(x) {} 48 | #define debug_put_hex32(x) {} 49 | #define debug_put_uint8(x) {} 50 | #define debug_put_int8(x) {} 51 | #define debug_put_uint16(x) {} 52 | #define debug_put_newline() {} 53 | #define debug_put_fixed2(x) {} 54 | #define debug_put_fixed1p3(x) {} 55 | #endif 56 | 57 | #define debug_function_call() { debug(__FILE__); debug(": "); debug((char*)__FUNCTION__); debug("()\n"); } 58 | #define debug_function_call_u16(val) { debug(__FILE__); debug(": "); debug((char*)__FUNCTION__); debug("("); debug_put_uint16(val); debug(")\n"); } 59 | #define debug_function_call_h32(val) { debug(__FILE__); debug(": "); debug((char*)__FUNCTION__); debug("(0x"); debug_put_hex32(val); debug(")\n"); } 60 | #define debug_function_call_fixed1p3(val) { debug(__FILE__); debug(": "); debug((char*)__FUNCTION__); debug("("); debug_put_fixed1p3(val); debug(")\n"); } 61 | 62 | 63 | #endif // DEBUG_H_ 64 | -------------------------------------------------------------------------------- /src/delay.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/ or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | 21 | #include "delay.h" 22 | 23 | void delay_init(void) { 24 | // nothing to do 25 | } 26 | 27 | 28 | inline void delay_us(uint32_t us) { 29 | // based on https:// github.com/leaflabs/libmaple 30 | us *= 10; 31 | 32 | // fudge for function call overhead 33 | us--; 34 | us--; 35 | us--; 36 | us--; 37 | us--; 38 | us--; 39 | asm volatile(".syntax unified \n\t" 40 | " mov r0, %[us] \n\t" 41 | "1: subs r0, #1 \n\t" 42 | " bhi 1b \n\t" 43 | ".syntax divided \n\t" 44 | : 45 | : [us] "r" (us) 46 | : "r0"); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/delay.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef DELAY_H_ 21 | #define DELAY_H_ 22 | 23 | #include 24 | #include "timeout.h" 25 | 26 | void delay_init(void); 27 | void delay_us(uint32_t us); 28 | #define delay_ms(ms) timeout_delay_ms(ms) 29 | 30 | 31 | #endif // DELAY_H_ 32 | -------------------------------------------------------------------------------- /src/led.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/ or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #include "led.h" 21 | #include "macros.h" 22 | #include "delay.h" 23 | #include 24 | 25 | void led_init(void) { 26 | // peripheral clocks enable 27 | rcc_periph_clock_enable(GPIO_RCC(LED_GPIO)); 28 | 29 | // set led pin as output 30 | gpio_mode_setup(LED_GPIO, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_PIN); 31 | gpio_set_output_options(LED_GPIO, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, LED_PIN); 32 | 33 | // some debug blinking 34 | for(uint8_t i=0; i<4; i++) { 35 | led_toggle(); 36 | for(uint8_t t=0; t<200; t++) { 37 | delay_us(1000); 38 | } 39 | } 40 | 41 | led_on(); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/led.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef LED_H_ 21 | #define LED_H_ 22 | 23 | #include 24 | #include "config.h" 25 | #include "macros.h" 26 | 27 | void led_init(void); 28 | 29 | #define led_on() { GPIO_TOGGLE(LED_GPIO, LED_PIN); } 30 | #define led_off() { GPIO_CLEAR(LED_GPIO, LED_PIN); } 31 | #define led_set(__val) { if (__val) { led_on(); }else{ led_off(); }} 32 | #define led_toggle() { GPIO_TOGGLE(LED_GPIO, LED_PIN); } 33 | 34 | #endif // LED_H_ 35 | -------------------------------------------------------------------------------- /src/macros.h: -------------------------------------------------------------------------------- 1 | #ifndef MACROS_H__ 2 | #define MACROS_H__ 3 | 4 | #include 5 | #include 6 | 7 | #define GPIO_RCC(GPIO) (((0x14) << 5) + (17 + ((GPIO - PERIPH_BASE_AHB2)/0x0400))) 8 | 9 | #define DEFINE_TO_STR(x) #x 10 | #define DEFINE_TO_STR_VAL(x) DEFINE_TO_STR(x) 11 | 12 | #define min(a,b) \ 13 | __extension__ ({ __typeof__ (a) _mina = (a); \ 14 | __typeof__ (b) _minb = (b); \ 15 | _mina < _minb ? _mina : _minb; }) 16 | #define max(a,b) \ 17 | __extension__ ({ __typeof__ (a) _maxa = (a); \ 18 | __typeof__ (b) _maxb = (b); \ 19 | _maxa > _maxb ? _maxa : _maxb; }) 20 | 21 | 22 | 23 | #ifdef UNUSED 24 | #elif defined(__GNUC__) 25 | # define UNUSED(x) UNUSED_ ## x __attribute__((unused)) 26 | #elif defined(__LCLINT__) 27 | # define UNUSED(x) /*@unused@*/ x 28 | #else 29 | # define UNUSED(x) x 30 | #endif 31 | 32 | // relocate function to run from sram (no waitstates!) 33 | #define RUN_FROM_RAM __attribute__ ((long_call, section (".data"))) 34 | 35 | 36 | /*#define CRC_SET_INIT(__crc) { \ 37 | CRC_INIT = (__crc); \ 38 | CRC_CR = 0; \ 39 | CRC_CR |= CRC_CR_RESET; \ 40 | 41 | } 42 | #define CRC_UPDATE(__crc, __val) { CRC_DR = __val; __crc = CRC_DR;}*/ 43 | 44 | // *************************************************** 45 | // using those macros is a big speedup (no lib calls!) 46 | // *************************************************** 47 | #define DMA_SET_NUMBER_OF_DATA(_dma, _ch, _val) { DMA_CNDTR(_dma, _ch) = (_val); } 48 | #define DMA_SET_MEMORY_ADDRES_NOCHECK(_dma, _ch, _address) { DMA_CMAR(_dma, _ch) = (uint32_t) (_address); } 49 | 50 | //#define DMA_CLEAR_INTERRUPT_FLAGS(_dma, _ch, _flags) { DMA_IFCR(_dma) = ((_flags) << DMA_FLAG_OFFSET(_ch)); } 51 | #define DMA_CLEAR_INTERRUPT_FLAGS_MULTI(_dma, _flags) { DMA_IFCR(_dma) = (_flags); } 52 | #define DMA_DISABLE_CHANNEL(_dma, _ch) { DMA_CCR(_dma, _ch) &= ~DMA_CCR_EN; } 53 | #define DMA_ENABLE_CHANNEL(_dma, _ch) { DMA_CCR(_dma, _ch) |= DMA_CCR_EN; } 54 | 55 | #define TIMER_CLEAR_FLAG(_tim, _flags) { TIM_SR(_tim) = ~(_flags); } 56 | #define TIMER_DISABLE_IRQ(_tim, _irqs) { TIM_DIER(_tim) &= ~(_irqs); } 57 | #define TIMER_ENABLE_IRQ(_tim, _irqs) { TIM_DIER(_tim) |= (_irqs); } 58 | #define TIMER_GET_FLAG(_tim, _flag) (TIM_SR(_tim) & (_flag)) 59 | #define TIMER_SET_DMA_ON_COMPARE_EVENT(_tim) { TIM_CR2(_tim) &= ~TIM_CR2_CCDS; } 60 | #define TIMER_CLEAR_DMA_ON_COMPARE_EVENT(_tim) { TIM_CR2(_tim) |= TIM_CR2_CCDS; } 61 | 62 | #define GPIO_SET(__port, __gpios) { GPIO_BSRR(__port) = __gpios; } 63 | #define GPIO_CLEAR(__port, __gpios) { GPIO_BSRR(__port) = (__gpios)<<16; } 64 | #define GPIO_TOGGLE(__port, __gpios) { uint32_t p = GPIO_ODR(__port); \ 65 | GPIO_BSRR(__port) = ((p & (__gpios)) << 16) | (~p & (__gpios)); } 66 | 67 | 68 | 69 | // *************************************************** 70 | // manual loop unrolling 71 | // *************************************************** 72 | #define _UNROLL_LOOP_1(__cmd) {__cmd;} 73 | #define _UNROLL_LOOP_2(__cmd) {_UNROLL_LOOP_1(__cmd); _UNROLL_LOOP_1(__cmd); } 74 | #define _UNROLL_LOOP_4(__cmd) {_UNROLL_LOOP_2(__cmd); _UNROLL_LOOP_2(__cmd); } 75 | #define _UNROLL_LOOP_8(__cmd) {_UNROLL_LOOP_4(__cmd); _UNROLL_LOOP_4(__cmd); } 76 | #define _UNROLL_LOOP_16(__cmd) {_UNROLL_LOOP_8(__cmd); _UNROLL_LOOP_8(__cmd); } 77 | #define _UNROLL_LOOP_32(__cmd) {_UNROLL_LOOP_16(__cmd); _UNROLL_LOOP_16(__cmd); } 78 | #define _UNROLL_LOOP_64(__cmd) {_UNROLL_LOOP_32(__cmd); _UNROLL_LOOP_32(__cmd); } 79 | 80 | #define UNROLL_LOOP(__n, __cmd) \ 81 | { \ 82 | if(((__n)&1)!=0){_UNROLL_LOOP_1(__cmd);}\ 83 | if(((__n)&2)!=0){_UNROLL_LOOP_2(__cmd);}\ 84 | if(((__n)&4)!=0){_UNROLL_LOOP_4(__cmd);}\ 85 | if(((__n)&8)!=0){_UNROLL_LOOP_8(__cmd);}\ 86 | if(((__n)&16)!=0){_UNROLL_LOOP_16(__cmd);}\ 87 | if(((__n)&32)!=0){_UNROLL_LOOP_32(__cmd);}\ 88 | if(((__n)&64)!=0){_UNROLL_LOOP_64(__cmd);}\ 89 | } 90 | 91 | #endif // MACROS_H__ 92 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/ or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #include "main.h" 21 | #include "delay.h" 22 | #include "timeout.h" 23 | #include "led.h" 24 | #include "clocksource.h" 25 | #include "debug.h" 26 | #include "video.h" 27 | #include "serial.h" 28 | #include "adc.h" 29 | #include "rtc6705.h" 30 | #include "macros.h" 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | 37 | // STM32F301 reference manual DM00094350.pdf 38 | // http://www.st.com/resource/en/reference_manual/dm00094350.pdf 39 | #include 40 | #include 41 | int main(void) { 42 | #if 0 43 | rcc_periph_clock_enable(GPIO_RCC(VIDEO_GPIO)); 44 | rcc_periph_clock_enable(RCC_DAC1); 45 | // set dac to output 46 | gpio_mode_setup(VIDEO_GPIO, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, VIDEO_DAC_OUT_PIN); 47 | //gpio_set_output_options(VIDEO_GPIO, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, VIDEO_DAC_OUT_PIN); 48 | 49 | 50 | // start with disabled dac 51 | dac_disable(CHANNEL_1); 52 | dac_disable_waveform_generation(CHANNEL_1); 53 | dac_buffer_disable(CHANNEL_1); 54 | 55 | // set default value and enable output 56 | 57 | dac_enable(CHANNEL_1); 58 | 59 | // software update trigher 60 | dac_set_trigger_source(DAC_CR_TSEL1_SW); 61 | //invert??https://www.mikrocontroller.net/topic/404156 62 | clocksource_init(); 63 | uint16_t i=0; 64 | while(1){ 65 | 66 | dac_load_data_buffer_single(i+=10, RIGHT12, CHANNEL_1); 67 | if (i>500) i = 0; 68 | dac_software_trigger(CHANNEL_1); 69 | for(uint8_t j=0; j<10; j++) delay_us(100); 70 | } 71 | 72 | while(1); 73 | #endif 74 | // init crystal osc & set clock options 75 | clocksource_init(); 76 | 77 | timeout_init(); 78 | delay_init(); 79 | 80 | led_init(); 81 | 82 | debug_init(); 83 | 84 | rtc6705_init(); 85 | 86 | adc_init(); 87 | 88 | video_init(); 89 | 90 | serial_init(); 91 | 92 | // this will never exit... 93 | video_main_loop(); 94 | 95 | while(1){ 96 | led_toggle(); 97 | timeout_delay_ms(100); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fishpepper/tinyOSD/0b783cd34302495adc637bcde434268e63862164/src/main.h -------------------------------------------------------------------------------- /src/pilotlogo.h: -------------------------------------------------------------------------------- 1 | #ifndef PILOTLOGO_H__ 2 | #define PILOTLOGO_H__ 3 | #include 4 | 5 | #define PILOTLOGO_HEIGHT 36 6 | #define PILOTLOGO_WIDTH 176 7 | 8 | static const uint16_t pilotlogo_data16[2][PILOTLOGO_HEIGHT * (PILOTLOGO_WIDTH/8) / 2] = { 9 | { 10 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 11 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f00, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 12 | 0x0, 0xff00, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff03, 0xff, 0xf01f, 0x0, 13 | 0x0, 0x0, 0x0, 0x0, 0x0, 0xe007, 0x0, 0xff07, 0x80ff, 0xf87f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 14 | 0xf83f, 0x0, 0xff0f, 0xc0ff, 0xfcff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfcff, 0x0, 0xc00f, 0xffc7, 0x7ff8, 15 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x100, 0x7ffc, 0x80, 0x1f, 0xff83, 0x7ff8, 0xfeff, 0xff0f, 0xffff, 0xf0ff, 0xff7f, 16 | 0x7fe, 0x7ffc, 0xf8, 0x1f, 0xff83, 0x7ff8, 0xffff, 0xff1f, 0xffff, 0xf8ff, 0xffff, 0x9fff, 0x7ffc, 0xff, 0xf1f, 0xffc7, 17 | 0x7ff8, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x7ffc, 0xc0ff, 0x1f3f, 0xffff, 0x7ff8, 0xffff, 0xffff, 0xffff, 0xffff, 18 | 0xffff, 0xffff, 0x7ffc, 0xe0ff, 0xf3f, 0xf0ff, 0x778, 0xffc, 0x1ffe, 0x3ff0, 0x7fe0, 0xfff0, 0xffc3, 0x7f8c, 0xe00f, 0x3f, 19 | 0xc0c3, 0x138, 0x7f0, 0x7f8, 0x1fc0, 0x3f80, 0x3ec0, 0xfe01, 0x7e00, 0xf003, 0x3f, 0x80c3, 0x38, 0x1f0, 0x7f0, 0x7c0, 20 | 0xf80, 0x3e80, 0xfc01, 0x7c00, 0xf001, 0x3f, 0x83c3, 0xf8, 0x1f0, 0x3f0, 0x7c0, 0xf80, 0x1e80, 0xfc01, 0x7800, 0xf001, 21 | 0x1f3f, 0x8fc3, 0x78f8, 0xf070, 0xe3e1, 0xc3c7, 0x8787, 0x1e0f, 0xf83f, 0x707c, 0xf8f0, 0x1f3f, 0x83c3, 0x78f8, 0xf070, 0xe3e3, 22 | 0xc3c7, 0x8787, 0x1e1f, 0xf83f, 0x707c, 0xf8f8, 0x1f3f, 0x80c3, 0x78f8, 0xf870, 0x3e0, 0xc3c7, 0xc787, 0x1e00, 0xf83f, 0x707c, 23 | 0xf800, 0x1f3f, 0xc0c3, 0x7878, 0xf870, 0x3e0, 0xc3c7, 0xc787, 0x1e00, 0xf83f, 0x707c, 0xf800, 0x1f3f, 0xf8c3, 0x7838, 0xf870, 24 | 0xffe3, 0xc3c7, 0xc787, 0xfe1f, 0xf83f, 0x707c, 0xf8ff, 0x1f3f, 0xfec3, 0x7838, 0xf070, 0xffe1, 0xc3c7, 0x8787, 0xfe0f, 0xf83f, 25 | 0x707c, 0xf8ff, 0x1f1f, 0xfec3, 0x7838, 0xe070, 0xffe0, 0x83c3, 0x787, 0xfe07, 0x1c3f, 0x783c, 0xf07f, 0x1f1f, 0x80c3, 0x7838, 26 | 0x170, 0x3f0, 0x7c0, 0xf80, 0x1e80, 0xc3e, 0x7800, 0xf001, 0x1f1f, 0x80c3, 0x7838, 0x370, 0x3f8, 0xfc0, 0x1f80, 0x1ec0, 27 | 0xe3e, 0x7e00, 0xe001, 0x1f0f, 0x80c3, 0x7878, 0x770, 0x7fc, 0x1fc0, 0x3f80, 0x3ee0, 0x1f3f, 0xff80, 0xe001, 0xff0f, 0xffff, 28 | 0xffff, 0xfff0, 0xffff, 0xffc7, 0xff87, 0xffff, 0xffff, 0xffff, 0xe0ff, 0xff07, 0xffff, 0xffff, 0xfff0, 0xffff, 0xffc7, 0xff87, 29 | 0xffff, 0xffff, 0xffff, 0xc0ff, 0xff01, 0xffff, 0xffff, 0xfff0, 0xffff, 0xffc7, 0xff87, 0xffff, 0xffff, 0xffff, 0x80ff, 0x0, 30 | 0xff1f, 0xffff, 0xfff0, 0xffff, 0xffc7, 0xff87, 0xffff, 0xffe3, 0xffff, 0xfe, 0x0, 0xff00, 0x7c0, 0xfeff, 0xff07, 0xffff, 31 | 0xf0ff, 0xc03f, 0x300, 0x81ff, 0xf8, 0x0, 0x0, 0x100, 0xf8ff, 0xf00, 0xffff, 0xc0ff, 0x0, 0x0, 0x0, 0x0, 32 | 0x0, 0x0, 0x0, 0xe07f, 0x100, 0x83ff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x800f, 0x0, 33 | 0x7e, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 34 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 35 | }, 36 | { 37 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 38 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 39 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 40 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 41 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x383f, 0x700, 0x80, 42 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x300, 0x80, 0x0, 0x7cff, 0x700, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 43 | 0x300, 0x80, 0x0, 0x7cff, 0x700, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300, 0x80, 0x0, 0x38f0, 0x700, 44 | 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x300, 0x80, 0x0, 0xe0, 0x700, 0x80, 0x0, 0x0, 0x0, 0x0, 45 | 0x0, 0x300, 0x80, 0x0, 0xf0, 0x870f, 0x3f8, 0x1f0, 0xfe0, 0x1fc0, 0xf80, 0x3c00, 0x7300, 0xf080, 0x0, 0x3cff, 46 | 0xc73f, 0xffe, 0x7f8, 0x3ff8, 0x7fe0, 0x3fc0, 0xfec1, 0xff01, 0xfc81, 0x0, 0x3cff, 0xc77f, 0xfff, 0xffe, 0x3ff8, 0x7ff8, 47 | 0x7ff0, 0xfec1, 0xff03, 0xfe83, 0x0, 0x3cff, 0x77c, 0xfff, 0xffe, 0x3ffc, 0x7ff8, 0x7ff0, 0xfee1, 0xff03, 0xfe87, 0x0, 48 | 0x3ce0, 0x770, 0x8f87, 0x1e0f, 0x381c, 0x783c, 0xf078, 0xc0e1, 0x8307, 0xf8f, 0x0, 0x3ce0, 0x77c, 0x8f87, 0x1c0f, 0x381c, 49 | 0x783c, 0xe078, 0xc0e1, 0x8307, 0x78f, 0x0, 0x3ce0, 0x77f, 0x8f87, 0x1f07, 0x38fc, 0x783c, 0xff38, 0xc0e1, 0x8307, 0xff8f, 50 | 0x0, 0x3ce0, 0x873f, 0x8f87, 0x1f07, 0x38fc, 0x783c, 0xff38, 0xc0e1, 0x8307, 0xff8f, 0x0, 0x3ce0, 0xc707, 0x8f87, 0x1c07, 51 | 0x3800, 0x783c, 0xe038, 0xc001, 0x8307, 0x8f, 0x0, 0x3ce0, 0xc701, 0x8f87, 0x1e0f, 0x3800, 0x783c, 0xf078, 0xc001, 0x8307, 52 | 0x8f, 0x0, 0x3ce0, 0xc701, 0x8f87, 0x1f1f, 0x3c00, 0x787c, 0xf8f8, 0xc001, 0xc3e3, 0x8087, 0x0, 0x3ce0, 0xc77f, 0x8f87, 53 | 0xffe, 0x3ffc, 0x7ff8, 0x7ff0, 0xc1e1, 0xfff3, 0xfe87, 0x0, 0x3ce0, 0xc77f, 0x8f87, 0x7fc, 0x3ffc, 0x7ff0, 0x3fe0, 0xc1e1, 54 | 0xfff1, 0xfe81, 0x0, 0x3ce0, 0x877f, 0x8f87, 0x3f8, 0x3ff8, 0x7fe0, 0x1fc0, 0xc0c1, 0x7fe0, 0xfe00, 0x0, 0x0, 0x0, 55 | 0xf00, 0x0, 0x3800, 0x7800, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf00, 0x0, 0x3800, 0x7800, 0x0, 56 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf00, 0x0, 0x3800, 0x7800, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 57 | 0x0, 0xf00, 0x0, 0x3800, 0x7800, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 58 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 59 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 60 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 61 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 62 | } 63 | }; 64 | #endif // PILOTLOGO_H__ 65 | -------------------------------------------------------------------------------- /src/rtc6705.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/ or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #include "rtc6705.h" 21 | #include "macros.h" 22 | #include "config.h" 23 | #include "debug.h" 24 | #include "delay.h" 25 | 26 | #include 27 | #include 28 | 29 | static void rtc6705_init_gpio(void); 30 | static void rtc6705_init_rcc(void); 31 | 32 | static uint32_t rtc6705_transfer(uint8_t address, uint8_t rw, uint32_t data); 33 | static uint32_t rtc6705_receive_bits(uint8_t n); 34 | static void rtc6705_send_bits(uint8_t n, uint32_t data); 35 | 36 | void rtc6705_init(void) { 37 | debug_function_call(); 38 | 39 | rtc6705_init_rcc(); 40 | rtc6705_init_gpio(); 41 | 42 | // shift out some dummy clocks: 43 | RTC6705_CS_HI(); 44 | for(uint8_t i=0; i<32; i++){ 45 | RTC6705_SCK_HI(); 46 | delay_us(1); 47 | RTC6705_SCK_LO(); 48 | delay_us(1); 49 | } 50 | 51 | #if DEBUG_PRINTS_ENABLED 52 | for (uint8_t i=0; i<=0xF; i++){ 53 | timeout_delay_ms(100); 54 | uint32_t res = rtc6705_transfer(i, RTC6705_COMMAND_READ, 0x0000); 55 | debug("rtc6705 reg 0x"); debug_put_hex8(i); 56 | debug(" = 0x"); 57 | debug_put_hex32(res); debug_put_newline(); 58 | } 59 | #endif 60 | 61 | // wait for the rtc6705 to be ready 62 | // TODO: find correct value?! 63 | timeout_delay_ms(100); 64 | 65 | // start on B4 5790 66 | // 2*(N*64+A)*20KHZ = 5790 67 | // N = 2261, A=46 68 | //rtc6705_transfer(0x00, RTC6705_COMMAND_WRITE, 0x190); // default, 8MHZ clock / 20khz spacing 69 | //rtc6705_transfer(0x01, RTC6705_COMMAND_WRITE, RTC6705_FREQUENCY_TO_REGVAL(5790)); //(2261<<7) + 46); 70 | // B4 71 | rtc6705_set_band_and_channel(1, 3); 72 | } 73 | 74 | // A B E F R 75 | static const uint32_t rtc6705_frequency_lookuptable[RTC6705_BAND_COUNT][RTC6705_CHANNEL_COUNT] = { 76 | // BAND A 77 | { 78 | RTC6705_FREQUENCY_TO_REGVAL(5865), //A1 79 | RTC6705_FREQUENCY_TO_REGVAL(5845), //A2 80 | RTC6705_FREQUENCY_TO_REGVAL(5825), //A3 81 | RTC6705_FREQUENCY_TO_REGVAL(5805), //A4 82 | RTC6705_FREQUENCY_TO_REGVAL(5785), //A5 83 | RTC6705_FREQUENCY_TO_REGVAL(5765), //A6 84 | RTC6705_FREQUENCY_TO_REGVAL(5745), //A7 85 | RTC6705_FREQUENCY_TO_REGVAL(5725), //A8 86 | }, 87 | // BAND B 88 | { 89 | RTC6705_FREQUENCY_TO_REGVAL(5733), // B1 90 | RTC6705_FREQUENCY_TO_REGVAL(5752), // B2 91 | RTC6705_FREQUENCY_TO_REGVAL(5771), // B3 92 | RTC6705_FREQUENCY_TO_REGVAL(5790), // B4 93 | RTC6705_FREQUENCY_TO_REGVAL(5809), // B5 94 | RTC6705_FREQUENCY_TO_REGVAL(5828), // B6 95 | RTC6705_FREQUENCY_TO_REGVAL(5847), // B7 96 | RTC6705_FREQUENCY_TO_REGVAL(5866), // B8 97 | }, 98 | // BAND E 99 | { 100 | RTC6705_FREQUENCY_TO_REGVAL(5705), // E1 101 | RTC6705_FREQUENCY_TO_REGVAL(5685), // E2 102 | RTC6705_FREQUENCY_TO_REGVAL(5665), // E3 103 | RTC6705_FREQUENCY_TO_REGVAL(5645), // E4 104 | RTC6705_FREQUENCY_TO_REGVAL(5885), // E5 105 | RTC6705_FREQUENCY_TO_REGVAL(5905), // E6 106 | RTC6705_FREQUENCY_TO_REGVAL(5925), // E7 107 | RTC6705_FREQUENCY_TO_REGVAL(5945), // E8 108 | }, 109 | // BAND F 110 | { 111 | RTC6705_FREQUENCY_TO_REGVAL(5740), // F1 112 | RTC6705_FREQUENCY_TO_REGVAL(5760), // F2 113 | RTC6705_FREQUENCY_TO_REGVAL(5780), // F3 114 | RTC6705_FREQUENCY_TO_REGVAL(5800), // F4 115 | RTC6705_FREQUENCY_TO_REGVAL(5820), // F5 116 | RTC6705_FREQUENCY_TO_REGVAL(5840), // F6 117 | RTC6705_FREQUENCY_TO_REGVAL(5860), // F7 118 | RTC6705_FREQUENCY_TO_REGVAL(5880), // F8 119 | }, 120 | // BAND R 121 | { 122 | RTC6705_FREQUENCY_TO_REGVAL(5658), // R1 123 | RTC6705_FREQUENCY_TO_REGVAL(5695), // R2 124 | RTC6705_FREQUENCY_TO_REGVAL(5732), // R3 125 | RTC6705_FREQUENCY_TO_REGVAL(5769), // R4 126 | RTC6705_FREQUENCY_TO_REGVAL(5806), // R5 127 | RTC6705_FREQUENCY_TO_REGVAL(5843), // R6 128 | RTC6705_FREQUENCY_TO_REGVAL(5880), // R7 129 | RTC6705_FREQUENCY_TO_REGVAL(5917), // R8 130 | } 131 | }; 132 | 133 | 134 | 135 | void rtc6705_set_band_and_channel(uint8_t band, uint8_t channel) { 136 | // band is 0, 1, 2, 3, 4 = A B E F R 137 | band = min(band, RTC6705_BAND_COUNT - 1); 138 | // channel is 0..7 -> limit 139 | channel = min(channel, RTC6705_CHANNEL_COUNT - 1); 140 | // fetch value from lookuptable 141 | uint32_t regval = rtc6705_frequency_lookuptable[band][channel]; 142 | 143 | // default, 8MHZ clock / 20khz spacing 144 | rtc6705_transfer(0x00, RTC6705_COMMAND_WRITE, 0x190); 145 | // send A and N 146 | rtc6705_transfer(0x01, RTC6705_COMMAND_WRITE, regval); 147 | } 148 | 149 | void rtc6705_set_frequency(uint16_t f) { 150 | // do not allow frequencies to low 151 | f = max(f, RTC6705_FREQUENCY_MIN); 152 | // do not allow frequencies to high 153 | f = min(f, RTC6705_FREQUENCY_MAX); 154 | 155 | // default, 8MHZ clock / 20khz spacing 156 | rtc6705_transfer(0x00, RTC6705_COMMAND_WRITE, 0x190); 157 | // send A and N 158 | rtc6705_transfer(0x01, RTC6705_COMMAND_WRITE, RTC6705_FREQUENCY_TO_REGVAL(f)); 159 | } 160 | 161 | static void rtc6705_init_rcc(void) { 162 | debug_function_call(); 163 | 164 | // peripheral clocks enable 165 | rcc_periph_clock_enable(GPIO_RCC(RTC6705_GPIO)); 166 | } 167 | 168 | static void rtc6705_init_gpio(void) { 169 | debug_function_call(); 170 | 171 | // set MOSI, SCK and CS pin as output 172 | uint32_t pins = RTC6705_PIN_CS | RTC6705_PIN_SCK | RTC6705_PIN_DATA; 173 | 174 | gpio_mode_setup(RTC6705_GPIO, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, pins); 175 | gpio_set_output_options(RTC6705_GPIO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, pins); 176 | 177 | // set up default idle levels 178 | RTC6705_CS_HI(); 179 | RTC6705_SCK_LO(); 180 | RTC6705_DATA_LO(); 181 | } 182 | 183 | 184 | static void rtc6705_send_bits(uint8_t n, uint32_t data) { 185 | // send n bits of data 186 | // data has to be right aligned 187 | while(n--) { 188 | //delay_us(1); 189 | asm("NOP"); 190 | RTC6705_SCK_LO(); 191 | 192 | // send bit 193 | if (data & 1) { 194 | RTC6705_DATA_HI(); 195 | } else { 196 | RTC6705_DATA_LO(); 197 | } 198 | data >>= 1; 199 | 200 | // toggle clock: 201 | //delay_us(1); 202 | asm("NOP"); 203 | RTC6705_SCK_HI(); 204 | } 205 | } 206 | 207 | static uint32_t rtc6705_receive_bits(uint8_t n) { 208 | uint32_t result = 0; 209 | // receive n bits of data 210 | for (uint8_t i=0; i>= 1; 290 | 291 | // toggle clock hi 292 | RTC6705_SCK_HI(); 293 | } 294 | 295 | RTC6705_SCK_LO(); 296 | 297 | // read or write? 298 | if (rw == 1) { 299 | // read: device will send us data, make sure SPI_DATA is input! 300 | RTC6705_DATA_HI(); 301 | } else { 302 | // write 303 | RTC6705_DATA_LO(); 304 | } 305 | 306 | // toggle clock 307 | RTC6705_SCK_HI(); 308 | 309 | if (rw) { 310 | // send 20 bits of data 311 | for(uint8_t i=0; i<20; i++) { 312 | // clock to low 313 | RTC6705_SCK_LO(); 314 | 315 | // set MOSI state 316 | if (data & 1) { 317 | RTC6705_MOSI_HI(); 318 | } else { 319 | RTC6705_MOSI_LO(); 320 | } 321 | // shift data 322 | data >>= 1; 323 | 324 | // toggle clock hi 325 | RTC6705_SCK_HI(); 326 | } 327 | // clock back to low level 328 | RTC6705_SCK_LO(); 329 | 330 | }else { 331 | // we will read data, gpio has to be input 332 | RTC6705_DATA_INPUT(); 333 | 334 | // read reply 335 | for(uint8_t i=0; i<20; i++) { 336 | // clock to low 337 | RTC6705_SCK_LO(); 338 | 339 | // read reply 340 | if (RTC6705_DATA_READ()) { 341 | result |= (1<<24); 342 | } 343 | result >>= 1; 344 | 345 | 346 | // toggle clock hi 347 | RTC6705_SCK_HI(); 348 | } 349 | 350 | // clock back to low level 351 | RTC6705_SCK_LO(); 352 | 353 | // revert data pin back to output 354 | RTC6705_DATA_OUTPUT(); 355 | } 356 | 357 | 358 | // make sure data is output again 359 | if (rw) { 360 | } 361 | 362 | // deselect device: 363 | RTC6705_CS_HI(); 364 | 365 | 366 | // restore idle state 367 | RTC6705_SCK_LO(); 368 | RTC6705_MOSI_LO(); 369 | } 370 | 371 | #endif 372 | -------------------------------------------------------------------------------- /src/rtc6705.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef RTC6705_H_ 21 | #define RTC6705_H_ 22 | 23 | #include 24 | 25 | void rtc6705_init(void); 26 | 27 | void rtc6705_set_frequency(uint16_t f); 28 | void rtc6705_set_band_and_channel(uint8_t band, uint8_t channel); 29 | 30 | #define RTC6705_CS_HI() { GPIO_SET(RTC6705_GPIO, RTC6705_PIN_CS); } 31 | #define RTC6705_CS_LO() { GPIO_CLEAR(RTC6705_GPIO, RTC6705_PIN_CS); } 32 | 33 | #define RTC6705_SCK_HI() { GPIO_SET(RTC6705_GPIO, RTC6705_PIN_SCK); } 34 | #define RTC6705_SCK_LO() { GPIO_CLEAR(RTC6705_GPIO, RTC6705_PIN_SCK); } 35 | 36 | #define RTC6705_DATA_HI() { GPIO_SET(RTC6705_GPIO, RTC6705_PIN_DATA); } 37 | #define RTC6705_DATA_LO() { GPIO_CLEAR(RTC6705_GPIO, RTC6705_PIN_DATA); } 38 | 39 | #define RTC6705_DATA_OUTPUT() { GPIO_MODER(RTC6705_GPIO) |= (1 << (2*RTC6705_PIN_DATA_PIN_ID)); } 40 | #define RTC6705_DATA_INPUT() { GPIO_MODER(RTC6705_GPIO) &= ~(3 << (2*RTC6705_PIN_DATA_PIN_ID)); } 41 | 42 | #define RTC6705_DATA_READ() (GPIO_IDR(RTC6705_GPIO) & RTC6705_PIN_DATA) 43 | 44 | #define RTC6705_COMMAND_READ 0 45 | #define RTC6705_COMMAND_WRITE 1 46 | 47 | #define RTC6705_FREQUENCY_MIN 5600 48 | #define RTC6705_FREQUENCY_MAX 5950 49 | 50 | #define RTC6705_FREQ_TO_A(__f) (((((uint64_t)(__f)*(uint64_t)1000000*(uint64_t)400)/(uint64_t)1000000) % 1024) / 16) 51 | #define RTC6705_FREQ_TO_N(__f) ((((uint64_t)(__f)*(uint64_t)1000000*(uint64_t)400)/(uint64_t)1000000) / 1024) 52 | #define RTC6705_FREQUENCY_TO_REGVAL(__f) ((RTC6705_FREQ_TO_N(__f)<<7) | RTC6705_FREQ_TO_A(__f)) 53 | 54 | #define RTC6705_BAND_COUNT 5 // A B E F R 55 | #define RTC6705_CHANNEL_COUNT 8 // 1 2 3 4 5 6 7 8 56 | 57 | 58 | #endif // RTC6705_H_ 59 | -------------------------------------------------------------------------------- /src/serial.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef SERIAL_H_ 21 | #define SERIAL_H_ 22 | 23 | #include 24 | 25 | void serial_init(void); 26 | void serial_process(void); 27 | 28 | #define SERIAL_TX_BUFFER_SIZE 128 29 | 30 | //#define PROTOCOL_FRAME_MAX_LEN 64 31 | extern const uint16_t *vtx_enabled_features; 32 | #define VTX_FEATURE_ENABLED(x) ((*vtx_enabled_features) & (x)) 33 | 34 | typedef enum { 35 | OSD_WRITE_MODE_VERTICAL = 0x0, 36 | OSD_WRITE_MODE_HORIZONTAL 37 | } openTCOCommandOSDWriteMode_e; 38 | 39 | #define OPENTCO_PROTOCOL_HEADER 0x80 40 | #define OPENTCO_CRC8_FROM_HEADER (0x89) 41 | 42 | #define OPENTCO_MAX_DATA_LENGTH 60 43 | #define OPENTCO_MAX_FRAME_LENGTH (OPENTCO_MAX_DATA_LENGTH + 4) 44 | 45 | // 0x01..0x07 = valid device ids 46 | #define OPENTCO_DEVICE_OSD 0x00 47 | #define OPENTCO_DEVICE_VTX 0x01 48 | #define OPENTCO_DEVICE_CAM 0x02 49 | // 50 | #define OPENTCO_DEVICE_MAX 0x07 51 | 52 | // 0x08..0x0F = valid device response ids 53 | #define OPENTCO_DEVICE_RESPONSE 0x08 54 | #define OPENTCO_DEVICE_OSD_RESPONSE (OPENTCO_DEVICE_RESPONSE | OPENTCO_DEVICE_OSD) 55 | #define OPENTCO_DEVICE_VTX_RESPONSE (OPENTCO_DEVICE_RESPONSE | OPENTCO_DEVICE_VTX) 56 | #define OPENTCO_DEVICE_CAM_RESPONSE (OPENTCO_DEVICE_RESPONSE | OPENTCO_DEVICE_CAM) 57 | 58 | // GENERIC 59 | #define OPENTCO_REGISTER_ACCESS_MODE_READ 0x80 60 | #define OPENTCO_REGISTER_ACCESS_MODE_WRITE 0x00 61 | #define OPENTCO_MAX_REGISTER 0x0F 62 | #define OPENTCO_GENERIC_COMMAND_REGISTER_ACCESS 0x00 63 | 64 | 65 | // OSD DEVICES 66 | #define OPENTCO_OSD_COMMAND_REGISTER_ACCESS OPENTCO_GENERIC_COMMAND_REGISTER_ACCESS 67 | #define OPENTCO_OSD_COMMAND_FILL_REGION 0x01 68 | #define OPENTCO_OSD_COMMAND_WRITE 0x02 69 | #define OPENTCO_OSD_COMMAND_WRITE_BUFFER_H 0x08 70 | #define OPENTCO_OSD_COMMAND_WRITE_BUFFER_V 0x09 71 | #define OPENTCO_OSD_COMMAND_SPECIAL 0x0F 72 | 73 | #define OPENTCO_OSD_REGISTER_STATUS 0x00 // R/W 74 | #define OPENTCO_OSD_REGISTER_SUPPORTED_FEATURES 0x01 // R 75 | #define OPENTCO_OSD_REGISTER_VIDEO_FORMAT 0x02 // R/W 76 | #define OPENTCO_OSD_REGISTER_BRIGHTNESS_BLACK 0x03 // R/W 77 | #define OPENTCO_OSD_REGISTER_BRIGHTNESS_WHITE 0x04 // R/W 78 | 79 | #define OPENTCO_OSD_COMMAND_SPECIAL_SUB_STICKSTATUS 0x00 80 | #define OPENTCO_OSD_COMMAND_SPECIAL_SUB_SPECTRUM 0x01 81 | 82 | typedef enum { 83 | OPENTCO_OSD_FEATURE_ENABLE = (1 << 0), 84 | OPENTCO_OSD_FEATURE_INVERT = (1 << 1), 85 | OPENTCO_OSD_FEATURE_BRIGHTNESS = (1 << 2), 86 | // 3..7 87 | OPENTCO_OSD_FEATURE_RENDER_LOGO = (1 << 8), 88 | OPENTCO_OSD_FEATURE_RENDER_PILOTLOGO = (1 << 9), 89 | OPENTCO_OSD_FEATURE_RENDER_STICKS = (1 << 10), 90 | OPENTCO_OSD_FEATURE_RENDER_SPECTRUM = (1 << 11), 91 | OPENTCO_OSD_FEATURE_RENDER_CROSSHAIR = (1 << 12) 92 | // 13..15 93 | } opentcoOSDFeatures_e; 94 | 95 | // VTX DEVICES 96 | #define OPENTCO_VTX_COMMAND_REGISTER_ACCESS OPENTCO_GENERIC_COMMAND_REGISTER_ACCESS 97 | #define OPENTCO_VTX_REGISTER_STATUS 0x00 // R/W: B0 = enable, B1 = pitmode 98 | 99 | typedef enum { 100 | OPENTCO_VTX_STATUS_ENABLE = (1 << 0), 101 | OPENTCO_VTX_STATUS_PITMODE = (1 << 1) 102 | } opentcoVTXStatus_e; 103 | 104 | // band, channel, and frequency can only be changed if tx is disabled! 105 | #define OPENTCO_VTX_REGISTER_BAND 0x01 // R/W Band, 0..n 106 | #define OPENTCO_VTX_REGISTER_CHANNEL 0x02 // R/W Channel, 0..7 107 | #define OPENTCO_VTX_REGISTER_FREQUENCY 0x03 // R/W: 5000 ... 6000 MHz 108 | #define OPENTCO_VTX_REGISTER_POWER 0x04 // R: [selected index|8] [name|string][':'|8]n*[value_i|string], W: selected index 109 | #define OPENTCO_VTX_POWER_COUNT 9 110 | 111 | 112 | #endif // SERIAL_H_ 113 | -------------------------------------------------------------------------------- /src/timeout.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/ or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #include "timeout.h" 21 | #include "delay.h" 22 | #include "led.h" 23 | #include 24 | #include 25 | #include 26 | 27 | static volatile __IO uint32_t timeout_100us; 28 | static volatile __IO uint32_t timeout2_100us; 29 | static volatile __IO uint32_t timeout_100us_delay; 30 | 31 | void timeout_init(void) { 32 | // configure 0.1ms sys tick: 33 | systick_set_clocksource(STK_CSR_CLKSOURCE_AHB); 34 | systick_set_reload(rcc_ahb_frequency / 10000); 35 | systick_interrupt_enable(); 36 | systick_counter_enable(); 37 | 38 | // clear counter so it starts right away 39 | STK_CVR = 0; 40 | 41 | // set prio 42 | nvic_set_priority(NVIC_SYSTICK_IRQ, NVIC_PRIO_SYSTICK); 43 | 44 | timeout_100us = 0; 45 | timeout2_100us = 0; 46 | timeout_100us_delay = 0; 47 | } 48 | 49 | void timeout_set_100us(__IO uint32_t hus) { 50 | timeout_100us = hus; 51 | } 52 | 53 | void timeout2_set_100us(__IO uint32_t hus) { 54 | timeout2_100us = hus; 55 | } 56 | 57 | uint8_t timeout_timed_out(void) { 58 | return(timeout_100us == 0); 59 | } 60 | 61 | uint8_t timeout2_timed_out(void) { 62 | return(timeout2_100us == 0); 63 | } 64 | 65 | void timeout2_delay_100us(uint16_t us) { 66 | timeout2_set_100us(us); 67 | while (!timeout2_timed_out()) {} 68 | } 69 | 70 | 71 | // seperate ms delay function 72 | void timeout_delay_ms(uint32_t timeout) { 73 | timeout_100us_delay = 10*timeout; 74 | 75 | while (timeout_100us_delay > 0) { 76 | } 77 | } 78 | 79 | void sys_tick_handler(void) { 80 | if (timeout_100us != 0) { 81 | timeout_100us--; 82 | } 83 | if (timeout2_100us != 0) { 84 | timeout2_100us--; 85 | } 86 | if (timeout_100us_delay != 0) { 87 | timeout_100us_delay--; 88 | } 89 | } 90 | 91 | uint32_t timeout_time_remaining(void) { 92 | return timeout_100us/ 10; 93 | } 94 | -------------------------------------------------------------------------------- /src/timeout.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef TIMEOUT_H_ 21 | #define TIMEOUT_H_ 22 | 23 | #include 24 | #include 25 | 26 | void timeout_init(void); 27 | // void timeout_set(__IO uint32_t ms); 28 | #define timeout_set(x) timeout_set_100us(10*(x)); 29 | void timeout_set_100us(__IO uint32_t hus); 30 | void timeout2_set_100us(__IO uint32_t hus); 31 | void timeout2_delay_100us(uint16_t us); 32 | uint8_t timeout_timed_out(void); 33 | uint8_t timeout2_timed_out(void); 34 | void timeout_delay_ms(uint32_t timeout); 35 | uint32_t timeout_time_remaining(void); 36 | 37 | #endif // TIMEOUT_H_ 38 | -------------------------------------------------------------------------------- /src/video.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef VIDEO_H_ 21 | #define VIDEO_H_ 22 | 23 | #define VIDEO_DEBUG_ODD_EVEN 0 24 | #define VIDEO_DEBUG_DMA 0 25 | #define VIDEO_DEBUG_DURATION_TEXTLINE 0 26 | #define VIDEO_DEBUG_DURATION_ANIMATION 0 27 | 28 | #define VIDEO_RENDER_DEBUG_DATA 0 29 | #define VIDEO_RENDER_ADCVAL 0 30 | #define VIDEO_RENDER_BARS 0 31 | 32 | #define VIDEO_BUFFER_WIDTH (2*38) //66 // max should be ~68 33 | #define VIDEO_CHAR_BUFFER_WIDTH 35 // THIS SHALL NEVER EXCEED VIDEO_BUFFER_WIDTH/2-3 ! 34 | #define VIDEO_CHAR_BUFFER_HEIGHT 13 35 | 36 | #include 37 | //#define VIDEO_START_LINE_ANIMATION (VIDEO_CENTER_ACTIVE_LINE - LOGO_HEIGHT/2) 38 | //#define VIDEO_END_LINE_ANIMATION (VIDEO_CENTER_ACTIVE_LINE + LOGO_HEIGHT/2) 39 | #define VIDEO_START_LINE_ANIMATION (68+1) 40 | #define VIDEO_END_LINE_ANIMATION (VIDEO_START_LINE_ANIMATION + LOGO_HEIGHT) 41 | #define VIDEO_CENTER_LINE_ANIMATION ((VIDEO_END_LINE_ANIMATION - VIDEO_START_LINE_ANIMATION)/2 + VIDEO_START_LINE_ANIMATION) 42 | 43 | #define VIDEO_START_PILOT_LOGO_Y (0*18) 44 | 45 | #define VIDEO_RENDER_STICK_SIZE 96 46 | #define VIDEO_RENDER_STICK_SIZE_X 96 47 | #define VIDEO_RENDER_STICK_SIZE_Y 128 48 | #define VIDEO_RENDER_STICK_POS_X (3*8) 49 | #define VIDEO_RENDER_STICK_POS_X2 (576 - VIDEO_RENDER_STICK_POS_X - VIDEO_RENDER_STICK_SIZE_X) 50 | #define VIDEO_START_LINE_STICKS (7*35) 51 | #define VIDEO_END_LINE_STICKS (VIDEO_START_LINE_STICKS + VIDEO_RENDER_STICK_SIZE) 52 | 53 | #define VIDEO_RENDER_SPECTRUM_BINS 16 54 | #define VIDEO_START_LINE_SPECTRUM (7*10) 55 | #define VIDEO_RENDER_SPECTRUM_SIZE_Y 128 56 | #define VIDEO_RENDER_SPECTRUM_SIZE_X (VIDEO_RENDER_SPECTRUM_BINS*2*8) 57 | #define VIDEO_RENDER_SPECTRUM_POS_X (576 - VIDEO_RENDER_SPECTRUM_SIZE_X - 32) 58 | 59 | void video_init(void); 60 | void video_main_loop(void); 61 | void video_put_uint8(uint8_t *buffer, uint8_t val); 62 | void video_put_uint16(uint8_t *buffer, uint16_t val); 63 | 64 | #define VIDEO_BLANK_LEVEL_DETECTION_MAX_MV 600 65 | 66 | #define VIDEO_BUFFER_FILL_REQUEST_IDLE 3 67 | 68 | #define WHITE 0 69 | #define BLACK 1 70 | 71 | 72 | #define VIDEO_MODE_PAL 0 73 | #define VIDEO_MODE_NTSC 1 74 | 75 | //NTSC 76 | #define VIDEO_FIRST_ACTIVE_LINE 40 77 | #define VIDEO_LAST_ACTIVE_LINE 516 78 | #define VIDEO_CENTER_ACTIVE_LINE ((VIDEO_LAST_ACTIVE_LINE - VIDEO_FIRST_ACTIVE_LINE) / 2) 79 | 80 | extern uint8_t video_char_buffer[VIDEO_CHAR_BUFFER_HEIGHT][VIDEO_CHAR_BUFFER_WIDTH]; 81 | extern uint16_t video_char_buffer_write_ptr; 82 | extern uint8_t video_mode; 83 | extern uint16_t video_min_level; 84 | extern uint8_t video_inverted; 85 | 86 | #define VIDEO_CLEAR_BUFFER(__col, __idx) { memset((void *)&video_line.buffer[__col][__idx][0], 0, (VIDEO_BUFFER_WIDTH/2)*2); } 87 | #define VIDEO_SET_BUFFER(__col, __idx) { memset((void *)&video_line.buffer[__col][__idx][0], 0xFFFF, (VIDEO_BUFFER_WIDTH/2)*2); } 88 | 89 | extern volatile uint8_t video_stick_data[4]; 90 | extern uint8_t video_armed_state; 91 | extern uint8_t video_spectrum_buffer[]; 92 | 93 | typedef struct { 94 | volatile uint16_t buffer[2][2][VIDEO_BUFFER_WIDTH/2]; 95 | 96 | // current line on screen 97 | volatile uint32_t active_line; 98 | 99 | // page currently beeing drawn 100 | volatile uint32_t currently_rendering; 101 | 102 | // pending fill requests? 103 | volatile uint32_t fill_request; 104 | } video_line_t; 105 | 106 | extern video_line_t video_line; 107 | extern volatile uint16_t video_stats_line_start; 108 | extern volatile uint16_t video_stats_line_usage_min; 109 | extern volatile uint16_t video_stats_line_usage_max; 110 | 111 | //extern volatile uint16_t video_buffer[2][2][VIDEO_BUFFER_WIDTH/2]; 112 | //extern volatile uint32_t video_buffer_fill_request; 113 | extern volatile uint32_t video_unprocessed_frame_count; 114 | extern volatile uint32_t video_uart_overrun; 115 | extern volatile uint32_t video_uart_checksum_err; 116 | //extern volatile uint32_t video_line; 117 | extern volatile uint32_t video_field; 118 | //extern volatile uint32_t video_buffer_page; 119 | 120 | #define TIMER_CLOCKS_PER_US (CPU_CLOCK / 1000000) 121 | #define _US_TO_CLOCKS(__us) ((uint32_t)((__us) * TIMER_CLOCKS_PER_US)) 122 | 123 | #define VIDEO_LINE_LEN 63.556 // us 124 | #define VIDEO_SYNC_SHORT 2.000 // us 125 | #define VIDEO_SYNC_HSYNC 4.700 // us 126 | #define VIDEO_FIELD_ODD 1 127 | #define VIDEO_FIELD_EVEN (1-VIDEO_FIELD_ODD) 128 | #define VIDEO_FIRST_FIELD VIDEO_FIELD_ODD // ODD (NTSC) 129 | #define VIDEO_SECOND_FIELD (1-(VIDEO_FIRST_FIELD)) 130 | 131 | // timing for high level (from shortest to longest period) 132 | // (1) [HI] BROAD SYNC: t ~ VIDEO_SYNC_HSYNC 133 | // (2) [HI] VSYNC+DATA: t ~ (VIDEO_LINE_LEN / 2) - VIDEO_SYNC_HSYNC 134 | // (3) [HI] SHORT SYNC: t ~ (VIDEO_LINE_LEN / 2) - VIDEO_SYNC_SHORT 135 | // (4) [HI] VIDEO DATA: t ~ VIDEO_LINE_LEN - VIDEO_SYNC_HSYNC 136 | // 137 | #define VIDEO_SYNC_HI_BROAD (VIDEO_SYNC_HSYNC) 138 | #define VIDEO_SYNC_HI_VSYNC ((VIDEO_LINE_LEN / 2.0) - VIDEO_SYNC_HSYNC) 139 | #define VIDEO_SYNC_HI_SHORT ((VIDEO_LINE_LEN / 2.0) - VIDEO_SYNC_SHORT) 140 | #define VIDEO_SYNC_HI_DATA (VIDEO_LINE_LEN) 141 | // 142 | // -> valid vsync = .... (1)---[xxx(2)xxx]---(3)------(4) 143 | // 144 | #define VIDEO_SYNC_VSYNC_MIN _US_TO_CLOCKS(VIDEO_SYNC_HI_VSYNC - (VIDEO_SYNC_HI_VSYNC - VIDEO_SYNC_HI_BROAD)/2.0) 145 | #define VIDEO_SYNC_VSYNC_MAX _US_TO_CLOCKS(VIDEO_SYNC_HI_VSYNC + (VIDEO_SYNC_HI_SHORT - VIDEO_SYNC_HI_VSYNC)/2.0) 146 | 147 | // timing for low level (from shortest to longest period) 148 | // (1) [LO] SHORT SYNC: t ~ 2.0us 149 | // (2) [LO] HSYNC : t ~ 4.7us 150 | // (3) [LO] BROAD : t ~ (VIDEO_LINE_LEN / 2) - VIDEO_SYNC_HSYNC 151 | // 152 | // 153 | // short sync = (1)xxx]---(2)------(3) 154 | // 155 | #define VIDEO_SYNC_SHORT_MIN _US_TO_CLOCKS(0) 156 | #define VIDEO_SYNC_SHORT_MAX _US_TO_CLOCKS(VIDEO_SYNC_SHORT + (VIDEO_SYNC_HSYNC - VIDEO_SYNC_SHORT)/2.0) 157 | // 158 | // hsync = (1)---[xxx(2)xxx]---(3) 159 | // 160 | #define VIDEO_SYNC_HSYNC_MIN _US_TO_CLOCKS(VIDEO_SYNC_HSYNC - (VIDEO_SYNC_HSYNC - VIDEO_SYNC_SHORT)/2.0) 161 | #define VIDEO_SYNC_HSYNC_MAX _US_TO_CLOCKS(VIDEO_SYNC_HSYNC + (VIDEO_SYNC_LO_BROAD - VIDEO_SYNC_HSYNC)/2.0) 162 | // 163 | // broad = (1)------(2)---[xxx(3)] 164 | // 165 | #define VIDEO_SYNC_LO_BROAD (VIDEO_LINE_LEN / 2.0) - VIDEO_SYNC_HSYNC 166 | 167 | 168 | 169 | #endif // VIDEO_H_ 170 | -------------------------------------------------------------------------------- /src/video_io.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/ or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #include "video_io.h" 21 | #include "video.h" 22 | #include "config.h" 23 | #include "macros.h" 24 | #include "delay.h" 25 | #include "serial.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include "debug.h" 31 | 32 | static void video_io_init_rcc(void); 33 | static void video_io_init_gpio(void); 34 | static void video_io_init_dac(void); 35 | static void video_io_set_dac_value_raw(uint16_t taregt); 36 | 37 | static void video_io_set_white_level_raw(uint8_t byte); 38 | static void video_io_set_black_level_raw(uint8_t byte); 39 | 40 | void video_io_init(void) { 41 | video_io_init_rcc(); 42 | video_io_init_gpio(); 43 | video_io_init_dac(); 44 | 45 | video_io_set_level_mv(WHITE, 1000); 46 | video_io_set_level_mv(BLACK, 0); 47 | } 48 | 49 | 50 | static void video_io_init_rcc(void) { 51 | debug_function_call(); 52 | 53 | // DAC clock 54 | rcc_periph_clock_enable(RCC_DAC1); 55 | 56 | // for EXTI / COMP (syscfg and comp share clock enable) 57 | rcc_periph_clock_enable(RCC_SYSCFG); 58 | 59 | // timer1 clock 60 | rcc_periph_clock_enable(RCC_TIM1); 61 | 62 | // timer2 clock 63 | //rcc_periph_clock_enable(RCC_TIM2); 64 | 65 | // peripheral clocks enable 66 | rcc_periph_clock_enable(GPIO_RCC(VIDEO_GPIO)); 67 | rcc_periph_clock_enable(GPIO_RCC(VIDEO_WHITE_GPIO)); 68 | rcc_periph_clock_enable(GPIO_RCC(VIDEO_BLACK_GPIO)); 69 | 70 | // spi 71 | rcc_periph_clock_enable(VIDEO_SPI_WHITE_RCC); 72 | rcc_periph_clock_enable(VIDEO_SPI_BLACK_RCC); 73 | 74 | // enable DMA Peripheral Clock 75 | rcc_periph_clock_enable(RCC_DMA1); 76 | } 77 | 78 | static void video_io_init_gpio(void) { 79 | debug_function_call(); 80 | 81 | // set video input pin as input 82 | gpio_mode_setup(VIDEO_GPIO, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, VIDEO_INPUT_PIN); 83 | 84 | // set dac to output 85 | gpio_mode_setup(VIDEO_GPIO, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, VIDEO_DAC_OUT_PIN); 86 | //gpio_set_output_options(VIDEO_GPIO, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, VIDEO_DAC_OUT_PIN); 87 | 88 | // set spi mosi to output 89 | gpio_mode_setup(VIDEO_WHITE_GPIO, GPIO_MODE_AF, GPIO_PUPD_NONE, VIDEO_WHITE_MOSI_PIN); 90 | gpio_set_af(VIDEO_WHITE_GPIO, VIDEO_WHITE_MOSI_AF, VIDEO_WHITE_MOSI_PIN); 91 | gpio_set_output_options(VIDEO_WHITE_GPIO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, VIDEO_WHITE_MOSI_PIN); 92 | GPIO_CLEAR(VIDEO_WHITE_GPIO, VIDEO_WHITE_MOSI_PIN); 93 | 94 | // set spi mosi to output 95 | gpio_mode_setup(VIDEO_BLACK_GPIO, GPIO_MODE_AF, GPIO_PUPD_NONE, VIDEO_BLACK_MOSI_PIN); 96 | gpio_set_af(VIDEO_BLACK_GPIO, VIDEO_BLACK_MOSI_AF, VIDEO_BLACK_MOSI_PIN); 97 | gpio_set_output_options(VIDEO_BLACK_GPIO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, VIDEO_BLACK_MOSI_PIN); 98 | GPIO_CLEAR(VIDEO_BLACK_GPIO, VIDEO_BLACK_MOSI_PIN); 99 | /* 100 | gpio_mode_setup(VIDEO_WHITE_GPIO, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, VIDEO_WHITE_MOSI_PIN); 101 | gpio_mode_setup(VIDEO_BLACK_GPIO, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, VIDEO_BLACK_MOSI_PIN); 102 | while(1){ 103 | GPIO_TOGGLE(VIDEO_WHITE_GPIO, VIDEO_WHITE_MOSI_PIN); 104 | GPIO_TOGGLE(VIDEO_BLACK_GPIO, VIDEO_BLACK_MOSI_PIN); 105 | } 106 | */ 107 | // set WHITE DAC to output: 108 | uint32_t pins = VIDEO_MUX_WHITE_DAC0 | VIDEO_MUX_WHITE_DAC1 | VIDEO_MUX_WHITE_DAC2 | VIDEO_MUX_WHITE_DAC3; 109 | gpio_mode_setup(VIDEO_MUX_WHITE_GPIO, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, pins); 110 | GPIO_CLEAR(VIDEO_MUX_WHITE_GPIO, pins); 111 | //GPIO_SET(VIDEO_MUX_WHITE_GPIO, VIDEO_MUX_WHITE_DAC2); 112 | //GPIO_SET(VIDEO_MUX_WHITE_GPIO, VIDEO_MUX_WHITE_DAC1); 113 | //GPIO_SET(VIDEO_MUX_WHITE_GPIO, VIDEO_MUX_WHITE_DAC0); 114 | 115 | // set BLACK DAC to output: 116 | pins = VIDEO_MUX_BLACK_DAC0 | VIDEO_MUX_BLACK_DAC1 | VIDEO_MUX_BLACK_DAC2 | VIDEO_MUX_BLACK_DAC3; 117 | gpio_mode_setup(VIDEO_MUX_BLACK_GPIO, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, pins); 118 | GPIO_CLEAR(VIDEO_MUX_BLACK_GPIO, pins); 119 | //GPIO_SET(VIDEO_MUX_BLACK_GPIO, VIDEO_MUX_BLACK_DAC1); 120 | } 121 | 122 | 123 | 124 | void video_io_set_level_mv(uint8_t port, uint16_t mv){ 125 | ///debug_function_call_u16(mv); 126 | 127 | ///debug("video_io: v_white = "); debug_put_uint16(v_white); debug_put_newline(); 128 | 129 | // limit to be inside allowed range of 0..700 (+200) mV 130 | mv = min(900, mv); 131 | 132 | //debug("video_io: v_set = "); debug_put_uint16(mv); debug_put_newline(); 133 | 134 | // add offset to pal levels: 135 | // 0 % = video signal min + black level 136 | // 100 % = video signal min + black level + 700mV 137 | // allow for a bit more, set black level to 250mV, max is 250+900 = 1150mV 138 | mv = mv + video_min_level + 250; 139 | 140 | // input: target voltage in mv 141 | // the output is terminated with 75 Ohm 142 | // minimum 1/Rtotal = 1/8R + 1/4R + 1/2R + 1/R 143 | // Rtotal = 8R / 15 144 | // Vmax = CPU_VOLTAGE * VIDEO_LEVEL_TERMINATION_R / (VIDEO_LEVEL_TERMINATION_R + Rtotal) 145 | float r_total = (8.0 * VIDEO_LEVEL_R2R_1R) / 15.0; 146 | float mv_max = (1000.0 * CPU_VOLTAGE) * VIDEO_LEVEL_TERMINATION_R / (VIDEO_LEVEL_TERMINATION_R + r_total); 147 | 148 | // every lsb will give 1/15th of v_max: 149 | float mv_lsb = mv_max / 15.0; 150 | 151 | float raw = mv / mv_lsb; 152 | 153 | if (raw > 15.0) { 154 | raw = 15; 155 | } 156 | 157 | if (VTX_FEATURE_ENABLED(OPENTCO_OSD_FEATURE_INVERT)) { 158 | // switch colors 159 | //raw = 15 - raw; 160 | port = (port == WHITE) ? BLACK : WHITE; 161 | } 162 | 163 | if (port == WHITE) { 164 | video_io_set_white_level_raw((uint8_t)raw); 165 | } else { 166 | video_io_set_black_level_raw((uint8_t)raw); 167 | } 168 | } 169 | 170 | static void video_io_set_white_level_raw(uint8_t byte){ 171 | // input: raw value, lower 4 bit will be set on R2R DAC 172 | uint32_t out = 0; 173 | 174 | // stm32 BSRR register is tricky: 175 | // writing to lower 16 bits set the I/O pin 176 | // writing to higher 16 bits clear the I/O pin 177 | if (byte & (1<<0)) { out |= VIDEO_MUX_WHITE_DAC0; } else { out |= (VIDEO_MUX_WHITE_DAC0)<<16; } 178 | if (byte & (1<<1)) { out |= VIDEO_MUX_WHITE_DAC1; } else { out |= (VIDEO_MUX_WHITE_DAC1)<<16; } 179 | if (byte & (1<<2)) { out |= VIDEO_MUX_WHITE_DAC2; } else { out |= (VIDEO_MUX_WHITE_DAC2)<<16; } 180 | if (byte & (1<<3)) { out |= VIDEO_MUX_WHITE_DAC3; } else { out |= (VIDEO_MUX_WHITE_DAC3)<<16; } 181 | 182 | // execute: 183 | GPIO_BSRR(VIDEO_MUX_WHITE_GPIO) = out; 184 | } 185 | 186 | static void video_io_set_black_level_raw(uint8_t byte){ 187 | // input: raw value, lower 4 bit will be set on R2R DAC 188 | uint32_t out = 0; 189 | 190 | // stm32 BSRR register is tricky: 191 | // writing to lower 16 bits set the I/O pin 192 | // writing to higher 16 bits clear the I/O pin 193 | if (byte & (1<<0)) { out |= VIDEO_MUX_BLACK_DAC0; } else { out |= (VIDEO_MUX_BLACK_DAC0)<<16; } 194 | if (byte & (1<<1)) { out |= VIDEO_MUX_BLACK_DAC1; } else { out |= (VIDEO_MUX_BLACK_DAC1)<<16; } 195 | if (byte & (1<<2)) { out |= VIDEO_MUX_BLACK_DAC2; } else { out |= (VIDEO_MUX_BLACK_DAC2)<<16; } 196 | if (byte & (1<<3)) { out |= VIDEO_MUX_BLACK_DAC3; } else { out |= (VIDEO_MUX_BLACK_DAC3)<<16; } 197 | 198 | // execute: 199 | GPIO_BSRR(VIDEO_MUX_BLACK_GPIO) = out; 200 | } 201 | 202 | static void video_io_init_dac(void) { 203 | debug_function_call(); 204 | 205 | // start with disabled dac 206 | dac_disable(CHANNEL_1); 207 | dac_disable_waveform_generation(CHANNEL_1); 208 | //dac_buffer_disable(CHANNEL_1); 209 | 210 | // set default value and enable output 211 | video_io_set_dac_value_mv(0); 212 | 213 | dac_enable(CHANNEL_1); 214 | 215 | // software update trigher 216 | dac_set_trigger_source(DAC_CR_TSEL1_SW); 217 | } 218 | 219 | 220 | // set dac to a given voltage level 221 | void video_io_set_dac_value_mv(uint16_t target) { 222 | //debug_function_call_fixed1p3(target); 223 | 224 | uint32_t tmp = target; 225 | tmp = (tmp * 0x0FFF) / (VIDEO_DAC_VCC * 1000); 226 | video_io_set_dac_value_raw(tmp); 227 | } 228 | 229 | static void video_io_set_dac_value_raw(uint16_t target) { 230 | //debug_function_call_h32(target); 231 | //dac_load_data_buffer_single(target, RIGHT12, CHANNEL_1); 232 | dac_load_data_buffer_single(target, RIGHT12, CHANNEL_1); 233 | dac_software_trigger(CHANNEL_1); 234 | } 235 | 236 | -------------------------------------------------------------------------------- /src/video_io.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef VIDEO_IO_H_ 21 | #define VIDEO_IO_H_ 22 | 23 | #include 24 | 25 | void video_io_init(void); 26 | void video_io_set_dac_value_mv(uint16_t target); 27 | void video_io_set_level_mv(uint8_t port, uint16_t mv); 28 | 29 | #endif // VIDEO_IO_H_ 30 | -------------------------------------------------------------------------------- /src/video_render.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef VIDEO_RENDER_H_ 21 | #define VIDEO_RENDER_H_ 22 | 23 | #include 24 | #include "logo.h" 25 | 26 | 27 | 28 | void video_render_init(void); 29 | void video_render_animation(uint8_t page_to_fill, uint16_t visible_line); 30 | void video_render_text(uint8_t page_to_fill, uint16_t visible_line); 31 | void video_render_sticks(uint8_t page_to_fill, uint16_t visible_line); 32 | void video_render_pilot_logo(uint8_t page_to_fill, uint16_t visible_line); 33 | 34 | void video_render_overlay_sticks(uint8_t page_to_fill, uint16_t visible_line); 35 | void video_render_overlay_spectrum(uint8_t page_to_fill, uint16_t visible_line); 36 | void video_render_grey_bars(uint8_t page_to_fill, uint16_t visible_line); 37 | 38 | 39 | #endif // VIDEO_RENDER_H_ 40 | -------------------------------------------------------------------------------- /src/video_spi_dma.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/ or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #include "video_spi_dma.h" 21 | #include "video_timer.h" 22 | #include "video.h" 23 | #include "config.h" 24 | #include "macros.h" 25 | #include "debug.h" 26 | #include "led.h" 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | 36 | 37 | static volatile uint32_t video_spi_dma_cr_trigger[2]; 38 | 39 | static void video_spi_dma_init_spi(uint32_t spi); 40 | static void video_spi_dma_init_dma(void); 41 | 42 | void video_spi_dma_init(void) { 43 | debug_function_call(); 44 | 45 | //set up both spi ports 46 | video_spi_dma_init_spi(VIDEO_SPI_WHITE); 47 | video_spi_dma_init_spi(VIDEO_SPI_BLACK); 48 | 49 | // set up dma 50 | video_spi_dma_init_dma(); 51 | 52 | // fire DMA for the first time to have valid levels on the MOSI pins 53 | //while(1){ 54 | debug("not sure if this works, testme\n"); 55 | SPI_CR2(VIDEO_SPI_WHITE) |= SPI_CR2_TXDMAEN; 56 | SPI_CR2(VIDEO_SPI_BLACK) |= SPI_CR2_TXDMAEN; 57 | //timeout_delay_ms(100); 58 | //} 59 | } 60 | 61 | 62 | static void video_spi_dma_init_spi(uint32_t spi) { 63 | debug_function_call(); 64 | 65 | // SPI NVIC 66 | // nvic_set_priority(NVIC_SPI2_IRQ, 3); 67 | // nvic_enable_irq(NVIC_SPI2_IRQ); 68 | 69 | // clean start 70 | spi_reset(spi); 71 | 72 | // set up spi 73 | // - master mode 74 | // - baud prescaler = apb_clk/2 = 48/2 = 24MHz! 75 | // - CPOL low 76 | // - CPHA 1 77 | // - 8 bit crc (?) 78 | // - MSB first 79 | spi_init_master(spi, 80 | SPI_CR1_BAUDRATE_FPCLK_DIV_2, 81 | SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE, 82 | SPI_CR1_CPHA_CLK_TRANSITION_1, 83 | SPI_CR1_CRCL_8BIT, 84 | SPI_CR1_MSBFIRST); 85 | 86 | // set NSS to software 87 | // NOTE: setting NSS high is important! even when controling it on our 88 | // own. otherwise spi will not send any data! 89 | spi_enable_software_slave_management(spi); 90 | spi_set_nss_high(spi); 91 | 92 | // set fifo to quarter full(=1 byte) 93 | spi_fifo_reception_threshold_8bit(spi); 94 | 95 | // Enable SPI periph 96 | spi_enable(spi); 97 | } 98 | 99 | 100 | 101 | static void video_spi_dma_init_dma(void) { 102 | debug_function_call(); 103 | 104 | // start disabled 105 | dma_disable_channel(VIDEO_DMA_WHITE, VIDEO_WHITE_TIMER_DMA_CH); 106 | dma_disable_channel(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH); 107 | 108 | dma_disable_channel(VIDEO_DMA_BLACK, VIDEO_BLACK_TIMER_DMA_CH); 109 | dma_disable_channel(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH); 110 | 111 | // TIM1_CH1 = DMA CH2 112 | // -> write SPI SPI_CR2(spi) |= SPI_CR2_TXDMAEN 113 | // this will initiate SPI transfer using DMA CH3 114 | 115 | // TIM1_CH4 = DMA CH4 116 | // write SPI txdma 117 | // this will initiate SPI tx on DMA CH5 118 | 119 | // BLACK = SPI3 TX = CH3 120 | nvic_set_priority(VIDEO_BLACK_DMA_IRQ, NVIC_PRIO_DMA1); 121 | nvic_enable_irq(VIDEO_BLACK_DMA_IRQ); 122 | 123 | // WHITE = SPI2 TX = CH5 124 | nvic_set_priority(VIDEO_WHITE_DMA_IRQ, NVIC_PRIO_DMA1); 125 | nvic_enable_irq(VIDEO_WHITE_DMA_IRQ); 126 | 127 | /***********************************************************/ 128 | 129 | 130 | 131 | // start with clean init 132 | dma_channel_reset(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH); 133 | 134 | // source and destination size 135 | dma_set_memory_size(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH, DMA_CCR_MSIZE_16BIT); 136 | dma_set_peripheral_size(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH, DMA_CCR_PSIZE_16BIT); 137 | 138 | // auto memory destination increment mode 139 | dma_enable_memory_increment_mode(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH); 140 | // source address increment disable 141 | dma_disable_peripheral_increment_mode(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH); 142 | 143 | // Location assigned to peripheral register will be target 144 | dma_set_read_from_memory(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH); 145 | 146 | // source and destination start addresses 147 | dma_set_peripheral_address(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH, (uint32_t)&(SPI_DR(VIDEO_SPI_WHITE))); 148 | dma_set_memory_address(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH, 149 | (uint32_t)&video_line.buffer[WHITE][video_line.currently_rendering][0]); 150 | 151 | // write full len 152 | dma_set_number_of_data(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH, VIDEO_BUFFER_WIDTH/2); 153 | 154 | // very high DMA_CHANNEL3 155 | dma_set_priority(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH, DMA_CCR_PL_VERY_HIGH); 156 | 157 | // enable tx complete int 158 | dma_enable_transfer_complete_interrupt(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH); 159 | 160 | // start with clean init 161 | dma_channel_reset(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH); 162 | 163 | // source and destination size 164 | dma_set_memory_size(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH, DMA_CCR_MSIZE_16BIT); 165 | dma_set_peripheral_size(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH, DMA_CCR_PSIZE_16BIT); 166 | 167 | // auto memory destination increment mode 168 | dma_enable_memory_increment_mode(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH); 169 | // source address increment disable 170 | dma_disable_peripheral_increment_mode(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH); 171 | 172 | // Location assigned to peripheral register will be target 173 | dma_set_read_from_memory(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH); 174 | 175 | // source and destination start addresses 176 | dma_set_peripheral_address(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH, (uint32_t)&(SPI_DR(VIDEO_SPI_BLACK))); 177 | dma_set_memory_address(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH, 178 | (uint32_t)&video_line.buffer[BLACK][video_line.currently_rendering][0]); 179 | 180 | // write full len 181 | dma_set_number_of_data(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH, VIDEO_BUFFER_WIDTH/2); 182 | 183 | // very high prio 184 | dma_set_priority(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH, DMA_CCR_PL_VERY_HIGH); 185 | 186 | // enable tx complete int 187 | dma_enable_transfer_complete_interrupt(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH); 188 | 189 | 190 | /***********************************************************/ 191 | 192 | // start with clean init 193 | dma_channel_reset(VIDEO_DMA_WHITE, VIDEO_WHITE_TIMER_DMA_CH); 194 | 195 | // source and destination size 196 | dma_set_memory_size(VIDEO_DMA_WHITE, VIDEO_WHITE_TIMER_DMA_CH, DMA_CCR_MSIZE_32BIT); 197 | dma_set_peripheral_size(VIDEO_DMA_WHITE, VIDEO_WHITE_TIMER_DMA_CH, DMA_CCR_PSIZE_32BIT); 198 | 199 | // memory destination increment disable 200 | dma_disable_memory_increment_mode(VIDEO_DMA_WHITE, VIDEO_WHITE_TIMER_DMA_CH); 201 | // source address increment disable 202 | dma_disable_peripheral_increment_mode(VIDEO_DMA_WHITE, VIDEO_WHITE_TIMER_DMA_CH); 203 | 204 | // Location assigned to peripheral register will be target 205 | dma_set_read_from_memory(VIDEO_DMA_WHITE, VIDEO_WHITE_TIMER_DMA_CH); 206 | 207 | // source and destination start addresses 208 | dma_set_peripheral_address(VIDEO_DMA_WHITE, VIDEO_WHITE_TIMER_DMA_CH, (uint32_t)&(SPI_CR2(VIDEO_SPI_WHITE))); 209 | 210 | //dma write will trigger SPI dma 211 | video_spi_dma_cr_trigger[0] = SPI_CR2(VIDEO_SPI_WHITE) | SPI_CR2_TXDMAEN; 212 | dma_set_memory_address(VIDEO_DMA_WHITE, VIDEO_WHITE_TIMER_DMA_CH, (uint32_t)&(video_spi_dma_cr_trigger[0])); 213 | 214 | // single word write 215 | dma_set_number_of_data(VIDEO_DMA_WHITE, VIDEO_WHITE_TIMER_DMA_CH, 1); 216 | // very high prio 217 | dma_set_priority(VIDEO_DMA_WHITE, VIDEO_WHITE_TIMER_DMA_CH, DMA_CCR_PL_VERY_HIGH); 218 | 219 | 220 | 221 | // start with clean init 222 | dma_channel_reset(VIDEO_DMA_BLACK, VIDEO_BLACK_TIMER_DMA_CH); 223 | 224 | // source and destination size 225 | dma_set_memory_size(VIDEO_DMA_BLACK, VIDEO_BLACK_TIMER_DMA_CH, DMA_CCR_MSIZE_32BIT); 226 | dma_set_peripheral_size(VIDEO_DMA_BLACK, VIDEO_BLACK_TIMER_DMA_CH, DMA_CCR_PSIZE_32BIT); 227 | 228 | // memory destination increment disable 229 | dma_disable_memory_increment_mode(VIDEO_DMA_BLACK, VIDEO_BLACK_TIMER_DMA_CH); 230 | // source address increment disable 231 | dma_disable_peripheral_increment_mode(VIDEO_DMA_BLACK, VIDEO_BLACK_TIMER_DMA_CH); 232 | 233 | // Location assigned to peripheral register will be target 234 | dma_set_read_from_memory(VIDEO_DMA_BLACK, VIDEO_BLACK_TIMER_DMA_CH); 235 | 236 | // source and destination start addresses 237 | dma_set_peripheral_address(VIDEO_DMA_BLACK, VIDEO_BLACK_TIMER_DMA_CH, (uint32_t)&(SPI_CR2(VIDEO_SPI_BLACK))); 238 | 239 | //dma write will trigger SPI dma 240 | video_spi_dma_cr_trigger[1] = SPI_CR2(VIDEO_SPI_BLACK) | SPI_CR2_TXDMAEN; 241 | dma_set_memory_address(VIDEO_DMA_BLACK, VIDEO_BLACK_TIMER_DMA_CH, (uint32_t)&(video_spi_dma_cr_trigger[1])); 242 | 243 | // single word write 244 | dma_set_number_of_data(VIDEO_DMA_BLACK, VIDEO_BLACK_TIMER_DMA_CH, 1); 245 | 246 | // very high prio 247 | dma_set_priority(VIDEO_DMA_BLACK, VIDEO_BLACK_TIMER_DMA_CH, DMA_CCR_PL_VERY_HIGH); 248 | } 249 | 250 | 251 | 252 | // BLACK DMA 253 | void VIDEO_BLACK_DMA_IRQ_HANDLER(void) { 254 | // clear flags 255 | DMA_CLEAR_INTERRUPT_FLAGS_MULTI(VIDEO_DMA_BLACK, 256 | (DMA_TCIF) << DMA_FLAG_OFFSET(VIDEO_BLACK_TIMER_DMA_CH) | 257 | (DMA_TCIF) << DMA_FLAG_OFFSET(VIDEO_BLACK_DMA_CH)); 258 | 259 | // disable dma during config 260 | DMA_DISABLE_CHANNEL(VIDEO_DMA_BLACK, VIDEO_BLACK_TIMER_DMA_CH); 261 | DMA_DISABLE_CHANNEL(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH); 262 | 263 | //clear pending dma transfer flag 264 | SPI_CR2(VIDEO_SPI_BLACK) &= ~SPI_CR2_TXDMAEN; 265 | 266 | 267 | // prepare to send tx trigger 268 | DMA_SET_NUMBER_OF_DATA(VIDEO_DMA_BLACK, VIDEO_BLACK_TIMER_DMA_CH, 1); 269 | 270 | // prepare to send dma spi data 271 | DMA_SET_MEMORY_ADDRES_NOCHECK(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH, 272 | (uint32_t)&video_line.buffer[BLACK][video_line.currently_rendering][0]); 273 | DMA_SET_NUMBER_OF_DATA(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH, VIDEO_BUFFER_WIDTH/2); 274 | 275 | // clear all dma if 276 | // NOT NECESSARY? move to define if enable is necc... 277 | // dma_clear_interrupt_flags(VIDEO_DMA_WHITE, VIDEO_DMA_CHANNEL_WHITE, DMA_TCIF); 278 | 279 | 280 | // disable timer match in order to clear pending timer triggers 281 | //TIMER_CLEAR_DMA_ON_COMPARE_EVENT(TIM1); 282 | TIMER_CLEAR_FLAG(TIM1, TIM_SR_CC1IF | TIM_SR_CC4IF); 283 | TIMER_DISABLE_IRQ(TIM1, TIM_DIER_CC1DE | TIM_DIER_CC4DE); 284 | } 285 | 286 | // WHITE DMA 287 | void VIDEO_WHITE_DMA_IRQ_HANDLER(void) { 288 | // clear flags 289 | DMA_CLEAR_INTERRUPT_FLAGS_MULTI(VIDEO_DMA_BLACK, 290 | (DMA_TCIF) << DMA_FLAG_OFFSET(VIDEO_WHITE_TIMER_DMA_CH) | 291 | (DMA_TCIF) << DMA_FLAG_OFFSET(VIDEO_WHITE_DMA_CH)); 292 | 293 | // disable dma during config 294 | DMA_DISABLE_CHANNEL(VIDEO_DMA_WHITE, VIDEO_WHITE_TIMER_DMA_CH); 295 | DMA_DISABLE_CHANNEL(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH); 296 | 297 | //clear pending dma transfer flag 298 | SPI_CR2(VIDEO_SPI_WHITE) &= ~SPI_CR2_TXDMAEN; 299 | 300 | // prepare to send tx trigger 301 | DMA_SET_NUMBER_OF_DATA(VIDEO_DMA_WHITE, VIDEO_WHITE_TIMER_DMA_CH, 1); 302 | 303 | // prepare to send dma spi data 304 | DMA_SET_MEMORY_ADDRES_NOCHECK(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH, 305 | (uint32_t)&video_line.buffer[WHITE][video_line.currently_rendering][0]); 306 | DMA_SET_NUMBER_OF_DATA(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH, VIDEO_BUFFER_WIDTH/2); 307 | 308 | // clear all dma if 309 | // NOT NECESSARY? move to define if enable is necc... 310 | // dma_clear_interrupt_flags(VIDEO_DMA_WHITE, VIDEO_DMA_CHANNEL_WHITE, DMA_TCIF); 311 | } 312 | -------------------------------------------------------------------------------- /src/video_spi_dma.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef VIDEO_SPI_DMA_H_ 21 | #define VIDEO_SPI_DMA_H_ 22 | 23 | #include 24 | 25 | void video_spi_dma_init(void); 26 | 27 | 28 | #endif // VIDEO_SPI_DMA_H_ 29 | -------------------------------------------------------------------------------- /src/video_timer.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/ or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #include "video_timer.h" 21 | #include "video_spi_dma.h" 22 | #include "video.h" 23 | #include "config.h" 24 | #include "macros.h" 25 | #include "debug.h" 26 | #include "led.h" 27 | #include "clocksource.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | 35 | #include 36 | #include 37 | 38 | static void video_timer_init_tim1(void); 39 | static void video_timer_init_comparator(void); 40 | 41 | static volatile uint16_t video_sync_last_compare_value; 42 | 43 | void video_timer_init(void) { 44 | video_timer_init_tim1(); 45 | video_timer_init_comparator(); 46 | } 47 | 48 | static void video_timer_init_tim1(void) { 49 | debug_function_call(); 50 | 51 | uint16_t prescaler; 52 | 53 | timer_disable_counter(TIM1); 54 | 55 | // reset TIMx peripheral 56 | timer_reset(TIM1); 57 | 58 | //timer_enable_irq(TIM1, TIM_DIER_CC2IE); 59 | 60 | // Set the timers global mode to: 61 | // - use no divider 62 | // - alignment edge 63 | // - count direction up 64 | timer_set_mode(TIM1, 65 | TIM_CR1_CKD_CK_INT, 66 | TIM_CR1_CMS_EDGE, 67 | TIM_CR1_DIR_UP); 68 | 69 | // enable master mode TRGO = CH3 OC (used as adc trigger) 70 | timer_set_master_mode(TIM1, TIM_CR2_MMS_COMPARE_OC3REF); 71 | 72 | //OC3REF is set on compare match 73 | timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_PWM2); 74 | 75 | // input compare trigger 76 | // on channel IC2 77 | timer_ic_set_input(TIM1, TIM_IC2, TIM_IC_IN_TI1); 78 | timer_ic_set_polarity(TIM1, TIM_IC2, TIM_IC_BOTH); 79 | timer_ic_set_prescaler(TIM1, TIM_IC2, TIM_IC_PSC_OFF); 80 | timer_ic_set_filter(TIM1, TIM_IC2, TIM_IC_OFF); 81 | timer_ic_enable(TIM1, TIM_IC2); 82 | 83 | // set CC2 as output to internals 84 | //timer_ic_set_input(TIM1, TIM_IC2, TIM_CCMR1_CC2S_OUT); 85 | 86 | 87 | // set up oc2 interrupt 88 | nvic_set_priority(NVIC_TIM1_CC_IRQ, NVIC_PRIO_TIMER1); 89 | nvic_enable_irq(NVIC_TIM1_CC_IRQ); 90 | 91 | timer_set_dma_on_compare_event(TIM1); 92 | timer_disable_oc_preload(TIM1, TIM_OC1); 93 | timer_disable_oc_preload(TIM1, TIM_OC3); 94 | timer_disable_oc_preload(TIM1, TIM_OC4); 95 | 96 | // line frequency 97 | // NTSC (color) 15734 Hz = 63.56 us per line 98 | // PAL 15625 Hz = 64.00 us per line (54 us line content) 99 | // -> set up timer to overflow every 100us (= 0.1ms) = 10kHz 100 | prescaler = 1; 101 | // debug("cvideo: tim1 presc "); 102 | // debug_put_uint16(prescaler); 103 | timer_set_prescaler(TIM1, prescaler - 1); 104 | // timer_set_repetition_counter(TIM1, 0); 105 | 106 | // timer_enable_preload(TIM1); 107 | timer_continuous_mode(TIM1); 108 | timer_set_period(TIM1, 0xFFFF); 109 | 110 | // enable DMA trigger to ch1 111 | //timer_enable_irq(TIM1, TIM_DIER_CC1DE | TIM_DIER_CC4DE); 112 | 113 | // DMA on compare event 114 | timer_set_dma_on_compare_event(TIM1); 115 | 116 | 117 | // start timer 1 118 | timer_enable_counter(TIM1); 119 | } 120 | 121 | static void video_timer_init_comparator(void) { 122 | debug_function_call(); 123 | 124 | // start disabled 125 | comp_disable(VIDEO_COMP); 126 | 127 | // set comparator inputs 128 | // inp = PA7 129 | // inm = DAC_OUT_1 (PA4) -> INM4 130 | comp_select_input_m(VIDEO_COMP, COMP2_CSR_INMSEL_DAC1_OUT1); 131 | 132 | // IC2 output 133 | comp_select_output(VIDEO_COMP, COMP2_CSR_OUTSEL_TIM1_IC1); 134 | 135 | // hysteresis 136 | comp_select_hyst(VIDEO_COMP, COMP_CSR_HYST_MED); 137 | 138 | // enable 139 | comp_enable(VIDEO_COMP); 140 | } 141 | 142 | void video_timer_init_interrupt(void) { 143 | debug_function_call(); 144 | 145 | // set up exti source 146 | exti_set_trigger(VIDEO_COMP_EXTI_SOURCE_LINE, EXTI_TRIGGER_BOTH); 147 | exti_enable_request(VIDEO_COMP_EXTI_SOURCE_LINE); 148 | 149 | // enable irq 150 | nvic_enable_irq(VIDEO_COMP_EXTI_IRQN); 151 | nvic_set_priority(VIDEO_COMP_EXTI_IRQN, NVIC_PRIO_COMPARATOR); 152 | } 153 | 154 | void COMP123_IRQHandler(void) { 155 | // well, this irq is only called on comp interrupts -> skip checking... 156 | // if (exti_get_flag_status(VIDEO_COMP_EXTI_SOURCE_LINE) != 0) { 157 | // clear flag 158 | // exti_reset_request(VIDEO_COMP_EXTI_SOURCE_LINE); 159 | EXTI_PR = VIDEO_COMP_EXTI_SOURCE_LINE; // clear flag 160 | 161 | // calc duration 162 | uint16_t current_compare_value = TIM_CCR2(TIM1); 163 | uint16_t pulse_len = current_compare_value - video_sync_last_compare_value; 164 | //video_dbg = pulse_len; 165 | 166 | // we trigger on both edges 167 | // check if this was rising or falling edge: 168 | if (!(COMP_CSR(VIDEO_COMP) & (COMP2_CSR_COMPOUT))) { 169 | // falling edge -> this was measuring the field length 170 | if ((pulse_len > VIDEO_SYNC_VSYNC_MIN) && (pulse_len < VIDEO_SYNC_VSYNC_MAX)) { 171 | // this was the last half line -> hsync! 172 | video_field = VIDEO_SECOND_FIELD; 173 | } 174 | } else { 175 | // rising edge -> this was measuring the a sync part 176 | if (pulse_len < VIDEO_SYNC_SHORT_MAX) { 177 | // all short sync pulses are shortsyncs 178 | // new (half)frame -> init line counter 179 | // video start at sync 20 on even and odd, as we count different 180 | // init to the right values here: 181 | if (video_field == VIDEO_FIELD_ODD) { 182 | // odd 183 | video_line.active_line = 15; 184 | } else { 185 | // even 186 | video_line.active_line = 14; 187 | } 188 | } else if (pulse_len < VIDEO_SYNC_HSYNC_MAX) { 189 | // store start ts of next line 190 | video_stats_line_start = current_compare_value; 191 | 192 | // this is longer than a short sync and not a broad sync 193 | current_compare_value += _US_TO_CLOCKS(6+1.5); 194 | 195 | //uint32_t ccval = current_compare_value +100; // _US_TO_CLOCKS(15); 196 | TIM_CCR1(TIM1) = current_compare_value; 197 | TIM_CCR4(TIM1) = current_compare_value + 2*16; // correct for offset by different dma access time 198 | 199 | // let the adc sample the middle of each line: 200 | TIM_CCR3(TIM1) = current_compare_value + _US_TO_CLOCKS(19); 201 | 202 | if (VIDEO_DEBUG_DMA) led_on(); 203 | 204 | // prepare next page rendering: 205 | video_line.currently_rendering = 1 - video_line.currently_rendering; 206 | video_line.fill_request = video_line.currently_rendering; 207 | 208 | TIMER_ENABLE_IRQ(TIM1, TIM_DIER_CC1DE | TIM_DIER_CC4DE); 209 | 210 | if (VIDEO_DEBUG_DMA) TIMER_ENABLE_IRQ(TIM1, TIM_DIER_CC4IE); 211 | 212 | //TIMER_ENABLE_IRQ(TIM1, TIM_DIER_CC3IE); 213 | 214 | // enable dma channel, this was set up during the dma end of tx int 215 | DMA_ENABLE_CHANNEL(VIDEO_DMA_WHITE, VIDEO_WHITE_TIMER_DMA_CH); 216 | DMA_ENABLE_CHANNEL(VIDEO_DMA_WHITE, VIDEO_WHITE_DMA_CH); 217 | DMA_ENABLE_CHANNEL(VIDEO_DMA_BLACK, VIDEO_BLACK_TIMER_DMA_CH); 218 | DMA_ENABLE_CHANNEL(VIDEO_DMA_BLACK, VIDEO_BLACK_DMA_CH); 219 | 220 | if (VIDEO_DEBUG_DMA) led_off(); 221 | 222 | // increment video field 223 | video_line.active_line += 2; 224 | 225 | // prepare for the next field 226 | video_field = VIDEO_FIRST_FIELD; 227 | } else { 228 | // this is a broad sync 229 | } 230 | } 231 | 232 | // store current value for period measurements 233 | video_sync_last_compare_value = current_compare_value; 234 | } 235 | 236 | // void TIM1_CC_IRQHandler(void) { 237 | void TIM1_CC_IRQHandler(void) { 238 | if (TIMER_GET_FLAG(TIM1, TIM_SR_CC4IF)) { 239 | TIMER_CLEAR_FLAG(TIM1, TIM_SR_CC4IF); 240 | if (VIDEO_DEBUG_DMA) led_toggle(); 241 | if (VIDEO_DEBUG_DMA) led_toggle(); 242 | } 243 | /*if (TIMER_GET_FLAG(TIM1, TIM_SR_CC3IF)) { 244 | TIMER_CLEAR_FLAG(TIM1, TIM_SR_CC3IF); 245 | led_toggle(); 246 | led_toggle(); 247 | }*/ 248 | } 249 | 250 | -------------------------------------------------------------------------------- /src/video_timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 fishpepper gmail.com 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | author: fishpepper gmail.com 18 | */ 19 | 20 | #ifndef VIDEO_TIMER_H_ 21 | #define VIDEO_TIMER_H_ 22 | 23 | #include 24 | 25 | void video_timer_init(void); 26 | void video_timer_init_interrupt(void); 27 | 28 | #endif // VIDEO_TIMER_H_ 29 | -------------------------------------------------------------------------------- /stylecheck/README: -------------------------------------------------------------------------------- 1 | This is automated checker to make sure a C++ file follows Google's C++ style 2 | guide (https://google.github.io/styleguide/cppguide.html). As it 3 | heavily relies on regular expressions, cpplint.py won't catch all violations of 4 | the style guide and will very occasionally report a false positive. There is a 5 | list of things we currently don't handle very well at the top of cpplint.py, 6 | and we welcome patches to improve it. 7 | 8 | The linting tool takes a list of files as input. For full usage instructions, 9 | please see the output of: 10 | 11 | ./cpplint.py --help 12 | 13 | Unit tests are provided in cpplint_unittest.py. This file can safely be ignored 14 | by end users who have downloaded this package and only want to run the lint 15 | tool. 16 | 17 | --- 18 | 19 | cpplint.py and its corresponding unit tests are Copyright (C) 2009 Google Inc. 20 | 21 | Redistribution and use in source and binary forms, with or without 22 | modification, are permitted provided that the following conditions are 23 | met: 24 | 25 | * Redistributions of source code must retain the above copyright 26 | notice, this list of conditions and the following disclaimer. 27 | * Redistributions in binary form must reproduce the above 28 | copyright notice, this list of conditions and the following disclaimer 29 | in the documentation and/or other materials provided with the 30 | distribution. 31 | * Neither the name of Google Inc. nor the names of its 32 | contributors may be used to endorse or promote products derived from 33 | this software without specific prior written permission. 34 | 35 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 36 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 37 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 38 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 39 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 41 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 42 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 43 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 44 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 45 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 46 | -------------------------------------------------------------------------------- /stylecheck/cpplint_test_header.h: -------------------------------------------------------------------------------- 1 | // A test header for cpplint_unittest.py. 2 | -------------------------------------------------------------------------------- /test/send_osd_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import serial 3 | import time 4 | import sys 5 | 6 | ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=0, parity=serial.PARITY_NONE, rtscts=0) 7 | 8 | def tinyosd_set_char_xy(x, y, c): 9 | pos = y*35 + x 10 | tinyosd_set_char(pos, c) 11 | 12 | def tinyosd_set_char(pos, c): 13 | tinyosd_send_buf(0x05, [(pos>>8)&0xFF]) #DMAH 14 | tinyosd_send_buf(0x06, [(pos )&0xFF]) #DMAL 15 | tinyosd_send_buf(0x07, [ord(c) &0xFF]) #DMAI 16 | 17 | 18 | def tinyosd_send_buf(address, buf): 19 | #[HEADER] LEN ADDR [CSUM] 20 | txbuf = [] 21 | 22 | length = len(buf) & 0xFF 23 | 24 | txbuf.append(0x80) #header 25 | txbuf.append(length) 26 | txbuf.append(address & 0xFF) 27 | for i in range(length): 28 | txbuf.append(buf[i]) 29 | 30 | #calc csum 31 | csum = 0 32 | for x in txbuf: 33 | csum ^= x 34 | 35 | txbuf.append(csum) 36 | 37 | #debug 38 | sys.stdout.write("TX: ") 39 | for x in txbuf: 40 | sys.stdout.write(" " + hex(x)) 41 | sys.stdout.write("\n") 42 | sys.stdout.flush() 43 | 44 | ser.write(txbuf) 45 | 46 | for (y) in range (13): 47 | for x in range(35): 48 | tinyosd_set_char_xy(x, y,'*') 49 | 50 | for (y) in range (13): 51 | for x in range(35): 52 | tinyosd_set_char_xy(x, y,' ') 53 | 54 | 55 | for (y) in range (13): 56 | for x in range(35): 57 | tinyosd_set_char_xy(x, y,'X') 58 | time.sleep(0.01) 59 | -------------------------------------------------------------------------------- /tinyOSD.config: -------------------------------------------------------------------------------- 1 | // Add predefined macros for your project here. For example: 2 | // #define THE_ANSWER 42 3 | -------------------------------------------------------------------------------- /tinyOSD.creator: -------------------------------------------------------------------------------- 1 | [General] 2 | -------------------------------------------------------------------------------- /tinyOSD.includes: -------------------------------------------------------------------------------- 1 | libopencm3/include/libopencm3/cm3 2 | libopencm3/include/libopencm3/dispatch 3 | libopencm3/include/libopencm3/efm32 4 | libopencm3/include/libopencm3/efm32/g 5 | libopencm3/include/libopencm3/efm32/gg 6 | libopencm3/include/libopencm3/efm32/lg 7 | libopencm3/include/libopencm3/efm32/tg 8 | libopencm3/include/libopencm3/ethernet 9 | libopencm3/include/libopencm3/lm3s 10 | libopencm3/include/libopencm3/lm4f 11 | libopencm3/include/libopencm3/lpc13xx 12 | libopencm3/include/libopencm3/lpc17xx 13 | libopencm3/include/libopencm3/lpc43xx 14 | libopencm3/include/libopencm3/lpc43xx/m0 15 | libopencm3/include/libopencm3/lpc43xx/m4 16 | libopencm3/include/libopencm3/sam 17 | libopencm3/include/libopencm3/sam/3a 18 | libopencm3/include/libopencm3/sam/3n 19 | libopencm3/include/libopencm3/sam/3s 20 | libopencm3/include/libopencm3/sam/3u 21 | libopencm3/include/libopencm3/sam/3x 22 | libopencm3/include/libopencm3/sam/common 23 | libopencm3/include/libopencm3/sam/d 24 | libopencm3/include/libopencm3/stm32 25 | libopencm3/include/libopencm3/stm32/common 26 | libopencm3/include/libopencm3/stm32/f0 27 | libopencm3/include/libopencm3/stm32/f1 28 | libopencm3/include/libopencm3/stm32/f2 29 | libopencm3/include/libopencm3/stm32/f3 30 | libopencm3/include/libopencm3/stm32/f4 31 | libopencm3/include/libopencm3/stm32/f7 32 | libopencm3/include/libopencm3/stm32/l0 33 | libopencm3/include/libopencm3/stm32/l1 34 | libopencm3/include/libopencm3/stm32/l4 35 | libopencm3/include/libopencm3/usb 36 | libopencm3/include/libopencm3/vf6xx 37 | libopencm3/include/libopencmsis 38 | libopencm3/include/libopencmsis/dispatch 39 | libopencm3/include/libopencmsis/efm32/g 40 | libopencm3/include/libopencmsis/efm32/gg 41 | libopencm3/include/libopencmsis/efm32/lg 42 | libopencm3/include/libopencmsis/efm32/tg 43 | libopencm3/include/libopencmsis/lm3s 44 | libopencm3/include/libopencmsis/lpc13xx 45 | libopencm3/include/libopencmsis/lpc17xx 46 | libopencm3/include/libopencmsis/lpc43xx/m0 47 | libopencm3/include/libopencmsis/lpc43xx/m4 48 | libopencm3/include/libopencmsis/sam/3a 49 | libopencm3/include/libopencmsis/sam/3n 50 | libopencm3/include/libopencmsis/sam/3s 51 | libopencm3/include/libopencmsis/sam/3u 52 | libopencm3/include/libopencmsis/sam/3x 53 | libopencm3/include/libopencmsis/sam/d 54 | libopencm3/include/libopencmsis/stm32/f0 55 | libopencm3/include/libopencmsis/stm32/f1 56 | libopencm3/include/libopencmsis/stm32/f2 57 | libopencm3/include/libopencmsis/stm32/f3 58 | libopencm3/include/libopencmsis/stm32/f4 59 | libopencm3/include/libopencmsis/stm32/f7 60 | libopencm3/include/libopencmsis/stm32/l0 61 | libopencm3/include/libopencmsis/stm32/l1 62 | libopencm3/include/libopencmsis/stm32/l4 63 | libopencm3/include/libopencmsis/vf6xx 64 | libopencm3/lib/stm32/common 65 | libopencm3/lib/usb 66 | libopencm3/tests/gadget-zero 67 | libopencm3/tests/shared 68 | src 69 | --------------------------------------------------------------------------------