├── .vscode ├── settings.json ├── c_cpp_properties.json ├── tasks.json └── launch.json ├── .gitmodules ├── inc ├── common-defines.h └── core │ └── system.h ├── .gitignore ├── readme.md ├── src ├── core │ └── system.c └── firmware.c ├── interpolate-points.py ├── linkerscript.ld ├── Makefile └── sketch.drawio /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "nvic.h": "c" 4 | } 5 | } -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libopencm3"] 2 | path = libopencm3 3 | url = https://github.com/libopencm3/libopencm3.git 4 | -------------------------------------------------------------------------------- /inc/common-defines.h: -------------------------------------------------------------------------------- 1 | #ifndef INC_COMMON_DEFINES_H 2 | #define INC_COMMON_DEFINES_H 3 | 4 | #include 5 | #include 6 | 7 | #endif // INC_COMMON_DEFINES_H 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.o 3 | *.d 4 | *.bin 5 | *.elf 6 | *.hex 7 | *.srec 8 | *.list 9 | *.map 10 | *.stylecheck 11 | generated.*.ld 12 | .gdb_history 13 | .DS_Store 14 | 15 | # Project files from idea/netbeans/eclipse 16 | nbproject/ 17 | .idea/ 18 | .project 19 | -------------------------------------------------------------------------------- /inc/core/system.h: -------------------------------------------------------------------------------- 1 | #ifndef INC_SYSTEM_H 2 | #define INC_SYSTEM_H 3 | 4 | #include "common-defines.h" 5 | 6 | #define CPU_FREQ (84000000) 7 | #define SYSTICK_FREQ (1000) 8 | 9 | void system_setup(void); 10 | uint64_t system_get_ticks(void); 11 | 12 | #endif // INC_SYSTEM_H 13 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Linux", 5 | "includePath": [ 6 | "${workspaceFolder}/**" 7 | ], 8 | "defines": [ 9 | "STM32F4", 10 | "__ARM_ARCH_7EM__" 11 | ], 12 | "compilerPath": "/usr/bin/arm-none-eabi-gcc", 13 | "cStandard": "c99", 14 | "cppStandard": "c++14", 15 | "intelliSenseMode": "gcc-arm" 16 | } 17 | ], 18 | "version": 4 19 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Rendering 3D Graphics On An Oscilloscope 2 | 3 | | Branch | Description | 4 | | ---------- | ---------------------------------------------------------------------------------------------- | 5 | | `main` | Code to generate a static image | 6 | | `renderer` | Code for the 3D renderer | 7 | | `pdm` | Code to use pulse density modulation to render images, as described in the patreon bonus video | 8 | -------------------------------------------------------------------------------- /src/core/system.c: -------------------------------------------------------------------------------- 1 | #include "core/system.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | static volatile uint64_t ticks = 0; 8 | 9 | void sys_tick_handler(void) { 10 | ticks++; 11 | } 12 | 13 | static void rcc_setup(void) { 14 | rcc_clock_setup_pll(&rcc_hsi_configs[RCC_CLOCK_3V3_84MHZ]); 15 | } 16 | 17 | static void systick_setup(void) { 18 | systick_set_frequency(SYSTICK_FREQ, CPU_FREQ); 19 | systick_counter_enable(); 20 | systick_interrupt_enable(); 21 | } 22 | 23 | uint64_t system_get_ticks(void) { 24 | return ticks; 25 | } 26 | 27 | void system_setup(void) { 28 | rcc_setup(); 29 | systick_setup(); 30 | } 31 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "shell", 8 | "label": "power_on", 9 | "command": "JLinkExe -CommandFile .vscode/jlink/power-on.jlink", 10 | "problemMatcher": [] 11 | }, 12 | { 13 | "type": "shell", 14 | "label": "power_off", 15 | "command": "JLinkExe -CommandFile .vscode/jlink/power-off.jlink", 16 | "problemMatcher": [] 17 | }, 18 | { 19 | "type": "shell", 20 | "label": "build_debug", 21 | "command": "make bin", 22 | "problemMatcher": "$gcc" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "JLink: Debug Application", 5 | "cwd": "${workspaceFolder}", 6 | "executable": "./firmware.elf", 7 | "serverpath": "/usr/bin/JLinkGDBServer", 8 | "servertype": "jlink", 9 | "request": "launch", 10 | "type": "cortex-debug", 11 | "device": "STM32F401RE", 12 | "runToEntryPoint": "main", 13 | "interface": "swd", 14 | "preLaunchTask": "build_debug" 15 | }, 16 | { 17 | "name": "JLink: Attach to active", 18 | "cwd": "${workspaceFolder}", 19 | "executable": "./firmware.elf", 20 | "serverpath": "/usr/bin/JLinkGDBServer", 21 | "servertype": "jlink", 22 | "request": "attach", 23 | "type": "cortex-debug", 24 | "device": "STM32F401RE", 25 | "runToEntryPoint": "main", 26 | "interface": "swd" 27 | }, 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /interpolate-points.py: -------------------------------------------------------------------------------- 1 | from numpy import fft 2 | import math 3 | import matplotlib.pyplot as plt 4 | 5 | def lerp(t, a, b): 6 | return a + (b - a) * t 7 | 8 | def normalize(a, d = 1): 9 | return list(map(lambda p: [p[0]/d, p[1]/d], a)) 10 | 11 | def scale(a, scale): 12 | return list(map(lambda p: [p[0]*scale, p[1]*scale], a)) 13 | 14 | def offset(a, offset): 15 | return list(map(lambda p: [p[0]+offset, p[1]+offset], a)) 16 | 17 | 18 | def interpolate(a, in_between_points = 100): 19 | out = [] 20 | for p1, p2 in zip(a, a[1:] + [a[0]]): 21 | for i in range(in_between_points): 22 | t = i/in_between_points 23 | x = lerp(t, p1[0], p2[0]) 24 | y = lerp(t, p1[1], p2[1]) 25 | out.append([x, y]) 26 | return out 27 | 28 | def print_signal_array(a, name, type_name="float"): 29 | out = f"#define {name.upper()}_LENGTH ({len(a)})\n" 30 | out += f"{type_name} {name}[{name.upper()}_LENGTH] = {{\n " 31 | 32 | for i, value in enumerate(a): 33 | if i > 0 and i % 16 == 0: 34 | out += "\n " 35 | out += f"{value}, " 36 | out += "\n};" 37 | print(out) 38 | 39 | def plot_fft(signal, sample_rate): 40 | fft_result = fft.fft(signal) 41 | Hx = abs(fft_result) 42 | freqX = fft.fftfreq(len(Hx), 1/sample_rate) 43 | 44 | plt.plot((freqX), Hx) #plot freqX vs Hx 45 | plt.show() 46 | 47 | def plot_signal(signal): 48 | plt.plot(range(len(signal)), signal) 49 | plt.show() 50 | 51 | 52 | 53 | interpolation_points = 15 54 | max_scale = 256-1 55 | 56 | points = [ 57 | [2, 7], 58 | [5, 7], 59 | [6, 6], 60 | [6, 3], 61 | [3, 3], 62 | [2, 4], 63 | [2, 7], 64 | [3, 6], 65 | [6, 6], 66 | [5, 7], 67 | [5, 4], 68 | [6, 3], 69 | [3, 3], 70 | [3, 6], 71 | [3, 3], 72 | [2, 4], 73 | [5, 4], 74 | [5, 7], 75 | ] 76 | 77 | points = interpolate(points, interpolation_points) 78 | 79 | norm_max = 0 80 | for (p,) in zip(points): 81 | norm_max = max(abs(p[0]), abs(p[1]), norm_max) 82 | 83 | normed = normalize(points, norm_max) 84 | scaled = scale(normed, max_scale) 85 | xs = list(map(lambda p: int(p[0] + 0.5), scaled)) 86 | ys = list(map(lambda p: int(p[1]+ 0.5), scaled)) 87 | 88 | # rate = len(xs) 89 | # plot_fft(xs, rate) 90 | # plot_signal(xs * 3) 91 | 92 | print(f"#define NUM_POINTS ({len(xs)})") 93 | print_signal_array(xs, "xs", "uint8_t") 94 | print_signal_array(ys, "ys", "uint8_t") 95 | print_signal_array(xs, "xs", "float") 96 | print_signal_array(ys, "ys", "float") -------------------------------------------------------------------------------- /linkerscript.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopencm3 project. 3 | * 4 | * Copyright (C) 2009 Uwe Hermann 5 | * Copyright (C) 2011 Stephen Caudle 6 | * 7 | * This library is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | */ 20 | 21 | /* Define memory regions. */ 22 | MEMORY 23 | { 24 | rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K 25 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K 26 | } 27 | 28 | /* Enforce emmition of the vector table. */ 29 | EXTERN (vector_table) 30 | 31 | /* Define the entry point of the output file. */ 32 | ENTRY(reset_handler) 33 | 34 | /* Define sections. */ 35 | SECTIONS 36 | { 37 | .text : { 38 | *(.vectors) /* Vector table */ 39 | *(.text*) /* Program code */ 40 | . = ALIGN(4); 41 | *(.rodata*) /* Read-only data */ 42 | . = ALIGN(4); 43 | } >rom 44 | 45 | /* C++ Static constructors/destructors, also used for __attribute__ 46 | * ((constructor)) and the likes */ 47 | .preinit_array : { 48 | . = ALIGN(4); 49 | __preinit_array_start = .; 50 | KEEP (*(.preinit_array)) 51 | __preinit_array_end = .; 52 | } >rom 53 | .init_array : { 54 | . = ALIGN(4); 55 | __init_array_start = .; 56 | KEEP (*(SORT(.init_array.*))) 57 | KEEP (*(.init_array)) 58 | __init_array_end = .; 59 | } >rom 60 | .fini_array : { 61 | . = ALIGN(4); 62 | __fini_array_start = .; 63 | KEEP (*(.fini_array)) 64 | KEEP (*(SORT(.fini_array.*))) 65 | __fini_array_end = .; 66 | } >rom 67 | 68 | /* 69 | * Another section used by C++ stuff, appears when using newlib with 70 | * 64bit (long long) printf support 71 | */ 72 | .ARM.extab : { 73 | *(.ARM.extab*) 74 | } >rom 75 | .ARM.exidx : { 76 | __exidx_start = .; 77 | *(.ARM.exidx*) 78 | __exidx_end = .; 79 | } >rom 80 | 81 | . = ALIGN(4); 82 | _etext = .; 83 | 84 | /* ram, but not cleared on reset, eg boot/app comms */ 85 | .noinit (NOLOAD) : { 86 | *(.noinit*) 87 | } >ram 88 | . = ALIGN(4); 89 | 90 | .data : { 91 | _data = .; 92 | *(.data*) /* Read-write initialized data */ 93 | *(.ramtext*) /* "text" functions to run in ram */ 94 | . = ALIGN(4); 95 | _edata = .; 96 | } >ram AT >rom 97 | _data_loadaddr = LOADADDR(.data); 98 | 99 | .bss : { 100 | *(.bss*) /* Read-write zero initialized data */ 101 | *(COMMON) 102 | . = ALIGN(4); 103 | _ebss = .; 104 | } >ram 105 | 106 | /* 107 | * The .eh_frame section appears to be used for C++ exception handling. 108 | * You may need to fix this if you're using C++. 109 | */ 110 | /DISCARD/ : { *(.eh_frame) } 111 | 112 | . = ALIGN(4); 113 | end = .; 114 | } 115 | 116 | PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram)); 117 | -------------------------------------------------------------------------------- /src/firmware.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "core/system.h" 7 | 8 | #define PWM_PORT (GPIOA) 9 | #define PWM_CH1_PIN (GPIO2) 10 | #define PWM_CH2_PIN (GPIO3) 11 | #define PWM_CH1_OC (TIM_OC3) 12 | #define PWM_CH2_OC (TIM_OC4) 13 | 14 | 15 | #define NUM_POINTS (126) 16 | #define XS_LENGTH (126) 17 | uint8_t xs[XS_LENGTH] = { 18 | 73, 88, 104, 120, 135, 151, 167, 182, 187, 193, 198, 203, 208, 213, 219, 219, 19 | 219, 219, 219, 219, 219, 219, 203, 187, 172, 156, 141, 125, 109, 104, 99, 94, 20 | 88, 83, 78, 73, 73, 73, 73, 73, 73, 73, 73, 78, 83, 88, 94, 99, 21 | 104, 109, 125, 141, 156, 172, 187, 203, 219, 213, 208, 203, 198, 193, 187, 182, 22 | 182, 182, 182, 182, 182, 182, 182, 187, 193, 198, 203, 208, 213, 219, 203, 187, 23 | 172, 156, 141, 125, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 24 | 109, 109, 109, 104, 99, 94, 88, 83, 78, 73, 88, 104, 120, 135, 151, 167, 25 | 182, 182, 182, 182, 182, 182, 182, 182, 167, 151, 135, 120, 104, 88, 26 | }; 27 | #define YS_LENGTH (126) 28 | uint8_t ys[YS_LENGTH] = { 29 | 255, 255, 255, 255, 255, 255, 255, 255, 250, 245, 239, 234, 229, 224, 219, 203, 30 | 187, 172, 156, 141, 125, 109, 109, 109, 109, 109, 109, 109, 109, 114, 120, 125, 31 | 130, 135, 141, 146, 161, 177, 193, 208, 224, 239, 255, 250, 245, 239, 234, 229, 32 | 224, 219, 219, 219, 219, 219, 219, 219, 219, 224, 229, 234, 239, 245, 250, 255, 33 | 239, 224, 208, 193, 177, 161, 146, 141, 135, 130, 125, 120, 114, 109, 109, 109, 34 | 109, 109, 109, 109, 109, 125, 141, 156, 172, 187, 203, 219, 203, 187, 172, 156, 35 | 141, 125, 109, 114, 120, 125, 130, 135, 141, 146, 146, 146, 146, 146, 146, 146, 36 | 146, 161, 177, 193, 208, 224, 239, 255, 255, 255, 255, 255, 255, 255, 37 | }; 38 | 39 | uint8_t point_index = 0; 40 | 41 | void tim3_isr(void) { 42 | timer_set_oc_value(TIM2, PWM_CH1_OC, xs[point_index]); 43 | timer_set_oc_value(TIM2, PWM_CH2_OC, ys[point_index]); 44 | 45 | point_index = (point_index + 1) % NUM_POINTS; 46 | 47 | timer_clear_flag(TIM3, TIM_SR_CC1IF); 48 | } 49 | 50 | static void timer_setup(void) { 51 | rcc_periph_clock_enable(RCC_TIM2); 52 | timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); 53 | timer_set_oc_mode(TIM2, PWM_CH1_OC, TIM_OCM_PWM1); 54 | timer_set_oc_mode(TIM2, PWM_CH2_OC, TIM_OCM_PWM1); 55 | 56 | // 25.6kHz ~= cf / (prescaler * period) 57 | timer_set_prescaler(TIM2, 13-1); 58 | timer_set_period(TIM2, 256-1); 59 | 60 | timer_enable_counter(TIM2); 61 | timer_enable_oc_output(TIM2, PWM_CH1_OC); 62 | timer_enable_oc_output(TIM2, PWM_CH2_OC); 63 | 64 | // Set the interrupt 65 | rcc_periph_clock_enable(RCC_TIM3); 66 | timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); 67 | timer_set_oc_mode(TIM3, PWM_CH1_OC, TIM_OCM_ACTIVE); 68 | 69 | // 750Hz 70 | timer_set_prescaler(TIM3, 1000-1); 71 | timer_set_period(TIM3, 112-1); 72 | 73 | timer_enable_counter(TIM3); 74 | timer_enable_irq(TIM3, TIM_DIER_CC1IE); 75 | nvic_enable_irq(NVIC_TIM3_IRQ); 76 | } 77 | 78 | static void gpio_setup(void) { 79 | rcc_periph_clock_enable(RCC_GPIOA); 80 | gpio_mode_setup(PWM_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, PWM_CH1_PIN | PWM_CH2_PIN); 81 | gpio_set_af(PWM_PORT, GPIO_AF1, PWM_CH1_PIN | PWM_CH2_PIN); 82 | } 83 | 84 | int main(void) { 85 | system_setup(); 86 | gpio_setup(); 87 | timer_setup(); 88 | 89 | while(1){} 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Be silent per default, but 'make V=1' will show all compiler calls. 3 | ifneq ($(V),1) 4 | Q := @ 5 | NULL := 2>/dev/null 6 | endif 7 | 8 | SRC_DIR = src 9 | INC_DIR = inc 10 | OPENCM3_DIR = libopencm3 11 | 12 | BINARY = firmware 13 | 14 | ############################################################################### 15 | # Basic Device Setup 16 | 17 | LIBNAME = opencm3_stm32f4 18 | DEFS += -DSTM32F4 19 | FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16 20 | ARCH_FLAGS = -mthumb -mcpu=cortex-m4 $(FP_FLAGS) 21 | 22 | ############################################################################### 23 | # Linkerscript 24 | 25 | LDSCRIPT = linkerscript.ld 26 | LDLIBS += -l$(LIBNAME) 27 | LDFLAGS += -L$(OPENCM3_DIR)/lib 28 | 29 | ############################################################################### 30 | # Includes 31 | 32 | DEFS += -I$(OPENCM3_DIR)/include 33 | DEFS += -I$(INC_DIR) 34 | 35 | ############################################################################### 36 | # Executables 37 | 38 | PREFIX ?= arm-none-eabi- 39 | 40 | CC := $(PREFIX)gcc 41 | CXX := $(PREFIX)g++ 42 | LD := $(PREFIX)gcc 43 | AR := $(PREFIX)ar 44 | AS := $(PREFIX)as 45 | OBJCOPY := $(PREFIX)objcopy 46 | OBJDUMP := $(PREFIX)objdump 47 | GDB := $(PREFIX)gdb 48 | STFLASH = $(shell which st-flash) 49 | OPT := -Os 50 | DEBUG := -ggdb3 51 | CSTD ?= -std=c99 52 | 53 | 54 | ############################################################################### 55 | # Source files 56 | 57 | OBJS += $(SRC_DIR)/$(BINARY).o 58 | OBJS += $(SRC_DIR)/core/system.o 59 | 60 | ############################################################################### 61 | # C flags 62 | 63 | TGT_CFLAGS += $(OPT) $(CSTD) $(DEBUG) 64 | TGT_CFLAGS += $(ARCH_FLAGS) 65 | TGT_CFLAGS += -Wextra -Wshadow -Wimplicit-function-declaration 66 | TGT_CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes 67 | TGT_CFLAGS += -fno-common -ffunction-sections -fdata-sections 68 | 69 | ############################################################################### 70 | # C++ flags 71 | 72 | TGT_CXXFLAGS += $(OPT) $(CXXSTD) $(DEBUG) 73 | TGT_CXXFLAGS += $(ARCH_FLAGS) 74 | TGT_CXXFLAGS += -Wextra -Wshadow -Wredundant-decls -Weffc++ 75 | TGT_CXXFLAGS += -fno-common -ffunction-sections -fdata-sections 76 | 77 | ############################################################################### 78 | # C & C++ preprocessor common flags 79 | 80 | TGT_CPPFLAGS += -MD 81 | TGT_CPPFLAGS += -Wall -Wundef 82 | TGT_CPPFLAGS += $(DEFS) 83 | 84 | ############################################################################### 85 | # Linker flags 86 | 87 | TGT_LDFLAGS += --static -nostartfiles 88 | TGT_LDFLAGS += -T$(LDSCRIPT) 89 | TGT_LDFLAGS += $(ARCH_FLAGS) $(DEBUG) 90 | TGT_LDFLAGS += -Wl,-Map=$(*).map -Wl,--cref 91 | TGT_LDFLAGS += -Wl,--gc-sections 92 | ifeq ($(V),99) 93 | TGT_LDFLAGS += -Wl,--print-gc-sections 94 | endif 95 | 96 | ############################################################################### 97 | # Used libraries 98 | 99 | LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group 100 | 101 | ############################################################################### 102 | ############################################################################### 103 | ############################################################################### 104 | 105 | .SUFFIXES: .elf .bin .hex .srec .list .map .images 106 | .SECONDEXPANSION: 107 | .SECONDARY: 108 | 109 | all: elf bin 110 | 111 | elf: $(BINARY).elf 112 | bin: $(BINARY).bin 113 | hex: $(BINARY).hex 114 | srec: $(BINARY).srec 115 | list: $(BINARY).list 116 | GENERATED_BINARIES=$(BINARY).elf $(BINARY).bin $(BINARY).hex $(BINARY).srec $(BINARY).list $(BINARY).map 117 | 118 | images: $(BINARY).images 119 | flash: $(BINARY).flash 120 | 121 | $(OPENCM3_DIR)/lib/lib$(LIBNAME).a: 122 | ifeq (,$(wildcard $@)) 123 | $(warning $(LIBNAME).a not found, attempting to rebuild in $(OPENCM3_DIR)) 124 | $(MAKE) -C $(OPENCM3_DIR) 125 | endif 126 | 127 | # Define a helper macro for debugging make errors online 128 | # you can type "make print-OPENCM3_DIR" and it will show you 129 | # how that ended up being resolved by all of the included 130 | # makefiles. 131 | print-%: 132 | @echo $*=$($*) 133 | 134 | %.images: %.bin %.hex %.srec %.list %.map 135 | @#printf "*** $* images generated ***\n" 136 | 137 | %.bin: %.elf 138 | @#printf " OBJCOPY $(*).bin\n" 139 | $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).bin 140 | 141 | %.hex: %.elf 142 | @#printf " OBJCOPY $(*).hex\n" 143 | $(Q)$(OBJCOPY) -Oihex $(*).elf $(*).hex 144 | 145 | %.srec: %.elf 146 | @#printf " OBJCOPY $(*).srec\n" 147 | $(Q)$(OBJCOPY) -Osrec $(*).elf $(*).srec 148 | 149 | %.list: %.elf 150 | @#printf " OBJDUMP $(*).list\n" 151 | $(Q)$(OBJDUMP) -S $(*).elf > $(*).list 152 | 153 | %.elf %.map: $(OBJS) $(LDSCRIPT) $(OPENCM3_DIR)/lib/lib$(LIBNAME).a Makefile 154 | @#printf " LD $(*).elf\n" 155 | $(Q)$(LD) $(TGT_LDFLAGS) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(*).elf 156 | 157 | %.o: %.c 158 | @#printf " CC $(*).c\n" 159 | $(Q)$(CC) $(TGT_CFLAGS) $(CFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $(*).o -c $(*).c 160 | 161 | %.o: %.S 162 | @#printf " CC $(*).S\n" 163 | $(Q)$(CC) $(TGT_CFLAGS) $(CFLAGS) -o $(*).o -c $(*).S 164 | 165 | %.o: %.cxx 166 | @#printf " CXX $(*).cxx\n" 167 | $(Q)$(CXX) $(TGT_CXXFLAGS) $(CXXFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $(*).o -c $(*).cxx 168 | 169 | %.o: %.cpp 170 | @#printf " CXX $(*).cpp\n" 171 | $(Q)$(CXX) $(TGT_CXXFLAGS) $(CXXFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $(*).o -c $(*).cpp 172 | 173 | clean: 174 | @#printf " CLEAN\n" 175 | $(Q)$(RM) $(GENERATED_BINARIES) generated.* $(OBJS) $(OBJS:%.o=%.d) 176 | 177 | 178 | .PHONY: images clean elf bin hex srec list 179 | 180 | -include $(OBJS:.o=.d) 181 | -------------------------------------------------------------------------------- /sketch.drawio: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | --------------------------------------------------------------------------------