diff options
Diffstat (limited to 'controller')
76 files changed, 0 insertions, 7299 deletions
diff --git a/controller/fw/Makefile b/controller/fw/Makefile deleted file mode 100644 index 3aae9fb..0000000 --- a/controller/fw/Makefile +++ /dev/null @@ -1,333 +0,0 @@ - -######################################################################################################################## -# Dependency directories -######################################################################################################################## - -CUBE_DIR ?= STM32CubeF4 -CMSIS_DIR ?= cmsis -MSPDEBUG_DIR ?= mspdebug -LIBSODIUM_DIR ?= libsodium -TINYAES_DIR ?= tinyaes -MUSL_DIR ?= musl -RSLIB_DIR ?= reed_solomon - -######################################################################################################################## -# Algorithm parameters -######################################################################################################################## - -FMEAS_ADC_SAMPLING_RATE ?= 1000 -FMEAS_ADC_MAX ?= 4096 -FMEAS_FFT_LEN ?= 256 -FMEAS_FFT_WINDOW ?= gaussian -FMEAS_FFT_WINDOW_SIGMA ?= 16.0 -# TODO: validate -FMEAS_SAMPLING_RATE ?= $(shell echo $(FMEAS_ADC_SAMPLING_RATE) / \($(FMEAS_FFT_LEN)/2\) | bc -l) - -DSSS_GOLD_CODE_NBITS ?= 5 -DSSS_DECIMATION ?= 10 -# TODO maybe auto adjust this based on detection rate? -DSSS_THRESHOLD_FACTOR ?= 5.0f -DSSS_WAVELET_WIDTH ?= 7.3 -DSSS_WAVELET_LUT_SIZE ?= 69 -DSSS_FILTER_FC ?= 3e-3 -DSSS_FILTER_ORDER ?= 12 - -# Transmission symbols: 20 for 20*6=120 bit key + 10 for reed-solomon ECC -TRANSMISSION_SYMBOLS ?= 30 -PRESIG_STORE_SIZE ?= 3 - -# will be generated if necessary -PRESIG_KEYFILE ?= presig_test_key.secret - -######################################################################################################################## -# Sources -######################################################################################################################## - -C_SOURCES := src/main.c -C_SOURCES += src/mspdebug_wrapper.c -C_SOURCES += src/spi_flash.c -C_SOURCES += src/freq_meas.c -C_SOURCES += src/dsss_demod.c -C_SOURCES += src/rslib.c -C_SOURCES += src/crypto.c -C_SOURCES += src/adc.c -C_SOURCES += src/protocol.c -C_SOURCES += src/serial.c -C_SOURCES += src/con_usart.c -C_SOURCES += src/dma_util.c -C_SOURCES += src/gpio_helpers.c -C_SOURCES += tinyprintf/tinyprintf.c - -C_SOURCES += $(MSPDEBUG_DIR)/drivers/jtaglib.c - -CMSIS_SOURCES += TransformFunctions/arm_rfft_fast_init_f32.c -CMSIS_SOURCES += TransformFunctions/arm_rfft_fast_f32.c -CMSIS_SOURCES += TransformFunctions/arm_cfft_init_f32.c -CMSIS_SOURCES += TransformFunctions/arm_cfft_f32.c -CMSIS_SOURCES += TransformFunctions/arm_cfft_radix8_f32.c -CMSIS_SOURCES += CommonTables/arm_const_structs.c -CMSIS_SOURCES += CommonTables/arm_common_tables.c -CMSIS_SOURCES += TransformFunctions/arm_bitreversal.c -CMSIS_SOURCES += TransformFunctions/arm_bitreversal2.c -CMSIS_SOURCES := $(addprefix $(CMSIS_DIR)/CMSIS/DSP/Source/,$(CMSIS_SOURCES)) - -MUSL_SOURCES += math/tanhf.c math/atanhf.c -MUSL_SOURCES += math/expm1f.c math/log1pf.c -MUSL_SOURCES += math/expf.c math/exp2f_data.c -MUSL_SOURCES += math/powf.c -MUSL_SOURCES += math/sqrtf.c -MUSL_SOURCES += math/fabsf.c -MUSL_SOURCES += stdlib/abs.c -MUSL_SOURCES += string/memset.c -MUSL_SOURCES += string/memcpy.c -MUSL_SOURCES += string/memcmp.c -MUSL_SOURCES += string/strlen.c -MUSL_SOURCES += math/__math_oflowf.c -MUSL_SOURCES += math/__math_uflowf.c -MUSL_SOURCES += math/__math_xflowf.c -MUSL_SOURCES += math/__math_invalidf.c -MUSL_SOURCES += math/powf_data.c -MUSL_SOURCES := $(addprefix $(MUSL_DIR)/src/,$(MUSL_SOURCES)) - -RSLIB_SOURCES += $(addprefix $(RSLIB_DIR)/src/,rs.c ecc.c berlekamp.c galois.c) - -C_SOURCES += $(CMSIS_SOURCES) $(MUSL_SOURCES) $(RSLIB_SOURCES) - -CXX_SOURCES += - -BUILDDIR ?= build -BINARY := safetyreset.elf -LDSCRIPT := stm32f407.ld - -######################################################################################################################## -# Build parameters -######################################################################################################################## - -PREFIX ?= arm-none-eabi- - -DEBUG ?= 1 - -CC := $(PREFIX)gcc -CXX := $(PREFIX)g++ -LD := $(PREFIX)gcc -AR := $(PREFIX)ar -AS := $(PREFIX)as -SIZE := $(PREFIX)size -NM := $(PREFIX)nm -OBJCOPY := $(PREFIX)objcopy -OBJDUMP := $(PREFIX)objdump -GDB := $(PREFIX)gdb - -HOST_CC ?= $(HOST_PREFIX)gcc -HOST_CXX ?= $(HOST_PREFIX)g++ -HOST_LD ?= $(HOST_PREFIX)gcc -HOST_AR ?= $(HOST_PREFIX)ar -HOST_AS ?= $(HOST_PREFIX)as -HOST_OBJCOPY ?= $(HOST_PREFIX)objcopy -HOST_OBJDUMP ?= $(HOST_PREFIX)objdump - -PYTHON3 ?= python3 -DOT ?= dot - -CMSIS_DIR_ABS := $(abspath $(CMSIS_DIR)) -MSPDEBUG_DIR_ABS := $(abspath $(MSPDEBUG_DIR)) -LIBSODIUM_DIR_ABS := $(abspath $(LIBSODIUM_DIR)) -TINYAES_DIR_ABS := $(abspath $(TINYAES_DIR)) -MUSL_DIR_ABS := $(abspath $(MUSL_DIR)) - -ARCH_FLAGS ?= -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -SYSTEM_FLAGS ?= -nostdlib -ffreestanding -nostartfiles - -COMMON_CFLAGS += -Imspdebug/util -Imspdebug/drivers -Ilevmarq -COMMON_CFLAGS += -I$(CMSIS_DIR_ABS)/CMSIS/DSP/Include -I$(CMSIS_DIR_ABS)/CMSIS/Core/Include -CFLAGS += -I$(abspath musl_include_shims) -CFLAGS += -Itinyprintf -COMMON_CFLAGS += -I$(BUILDDIR) -Isrc -Itinyaes -CFLAGS += -I$(CUBE_DIR)/Drivers/CMSIS/Device/ST/STM32F4xx/Include -COMMON_CFLAGS += -I$(LIBSODIUM_DIR_ABS)/src/libsodium/include -I$(BUILDDIR)/libsodium/src/libsodium/include -I$(LIBSODIUM_DIR_ABS)/src/libsodium/include/sodium -COMMON_CFLAGS += -I$(RSLIB_DIR)/src - -COMMON_CFLAGS += -O0 -std=gnu11 -g -DSTM32F407xx -DSTM32F4 -DDEBUG=$(DEBUG) -CFLAGS += $(ARCH_FLAGS) $(SYSTEM_FLAGS) -#SIM_CFLAGS += -mthumb -mcpu=cortex-m4 -mfloat-abi=soft -CFLAGS += -fno-common -ffunction-sections -fdata-sections -COMMON_CFLAGS += -DARM_DSP_CONFIG_TABLES -DARM_FFT_ALLOW_TABLES \ - -DARM_TABLE_TWIDDLECOEF_F32_128 -DARM_TABLE_BITREVIDX_FLT_128 \ - -DARM_TABLE_TWIDDLECOEF_F32_128 -DARM_TABLE_TWIDDLECOEF_RFFT_F32_256 -COMMON_CFLAGS += -DDSSS_GOLD_CODE_NBITS=$(DSSS_GOLD_CODE_NBITS) -COMMON_CFLAGS += -DFMEAS_FFT_LEN=$(FMEAS_FFT_LEN) -COMMON_CFLAGS += -DFMEAS_ADC_MAX=$(FMEAS_ADC_MAX) -COMMON_CFLAGS += -DFMEAS_ADC_SAMPLING_RATE=$(FMEAS_ADC_SAMPLING_RATE) -COMMON_CFLAGS += -DFMEAS_FFT_WINDOW_SIGMA=$(FMEAS_FFT_WINDOW_SIGMA) -COMMON_CFLAGS += -DDSSS_DECIMATION=$(DSSS_DECIMATION) -COMMON_CFLAGS += -DDSSS_THRESHOLD_FACTOR=$(DSSS_THRESHOLD_FACTOR) -COMMON_CFLAGS += -DDSSS_WAVELET_WIDTH=$(DSSS_WAVELET_WIDTH) -COMMON_CFLAGS += -DDSSS_WAVELET_LUT_SIZE=$(DSSS_WAVELET_LUT_SIZE) -COMMON_CFLAGS += -DTRANSMISSION_SYMBOLS=$(TRANSMISSION_SYMBOLS) -COMMON_CFLAGS += -DPRESIG_STORE_SIZE=$(PRESIG_STORE_SIZE) - -# for musl -CFLAGS += -Dhidden= - -SIM_CFLAGS += -lm -DSIMULATION -SIM_CFLAGS += -Wall -Wextra -Wpedantic -Wshadow -Wimplicit-function-declaration -Wundef -Wno-unused-parameter - -INT_CFLAGS += -Wall -Wextra -Wpedantic -Wshadow -Wimplicit-function-declaration -Wundef -Wno-unused-parameter -INT_CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes - -CXXFLAGS += -Os -g -CXXFLAGS += $(ARCH_FLAGS) $(SYSTEM_FLAGS) -CXXFLAGS += -fno-common -ffunction-sections -fdata-sections -CXXFLAGS += -Wall -Wextra -Wshadow -Wundef -Wredundant-decls -CXXFLAGS += -I. - -LDFLAGS += $(ARCH_FLAGS) $(SYSTEM_FLAGS) - -LIBS += -lgcc -LDFLAGS += -Wl,--gc-sections - -LINKMEM_FLAGS ?= --trim-stubs=startup_stm32f407xx.o --trace-sections .isr_vector --highlight-subdirs $(BUILDDIR) - -OBJS := $(addprefix $(BUILDDIR)/,$(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o)) - -ALL_OBJS := $(OBJS) -ALL_OBJS += $(BUILDDIR)/src/startup_stm32f407xx.o -ALL_OBJS += $(BUILDDIR)/src/system_stm32f4xx.o -ALL_OBJS += $(BUILDDIR)/libsodium/src/libsodium/.libs/libsodium.a -ALL_OBJS += $(BUILDDIR)/levmarq/levmarq.o -ALL_OBJS += $(BUILDDIR)/generated/gold_code_$(DSSS_GOLD_CODE_NBITS).o -ALL_OBJS += $(BUILDDIR)/generated/fmeas_fft_window.o -ALL_OBJS += $(BUILDDIR)/generated/dsss_cwt_wavelet.o -ALL_OBJS += $(BUILDDIR)/generated/crypto_presig_data.o - -######################################################################################################################## -# Rules -######################################################################################################################## - -all: binsize - -.PHONY: binsize -binsize: $(BUILDDIR)/$(BINARY) $(BUILDDIR)/$(BINARY:.elf=-symbol-sizes.pdf) - $(LD) -T$(LDSCRIPT) $(LDFLAGS) -Wl,--print-memory-usage -o /dev/null $(ALL_OBJS) $(LIBS) - @echo - @echo "▐▬▬▬▌ SyMbOL sIzE HiGhScORe LiSt ▐▬▬▬▌" - $(NM) --print-size --size-sort --radix=d $< | tail -n 20 - -# $(BUILDDIR)/generated/dsss_butter_filter.h -src/dsss_demod.c: $(BUILDDIR)/generated/dsss_gold_code.h - -$(BUILDDIR)/generated/dsss_gold_code.h: $(BUILDDIR)/generated/gold_code_$(DSSS_GOLD_CODE_NBITS).h - ln -srf $< $@ - -.PRECIOUS: $(BUILDDIR)/generated/gold_code_%.c $(BUILDDIR)/generated/gold_code_%.h -$(BUILDDIR)/generated/gold_code_%.c $(BUILDDIR)/generated/gold_code_%.h&: | $(BUILDDIR)/generated - $(PYTHON3) tools/gold_code_header_gen.py -v dsss_gold_code_table -c $* > $(BUILDDIR)/generated/gold_code_$*.c - $(PYTHON3) tools/gold_code_header_gen.py -v dsss_gold_code_table -h $* > $(BUILDDIR)/generated/gold_code_$*.h - -.PRECIOUS: $(BUILDDIR)/generated/fmeas_fft_window.c -$(BUILDDIR)/generated/fmeas_fft_window.c: | $(BUILDDIR)/generated - $(PYTHON3) tools/fft_window_header_gen.py -v fmeas_fft_window_table $(FMEAS_FFT_WINDOW) $(FMEAS_FFT_LEN) $(FMEAS_FFT_WINDOW_SIGMA) > $@ - -.PRECIOUS: $(BUILDDIR)/generated/dsss_cwt_wavelet.c -$(BUILDDIR)/generated/dsss_cwt_wavelet.c: | $(BUILDDIR)/generated - $(PYTHON3) tools/cwt_wavelet_header_gen.py -v dsss_cwt_wavelet_table $(DSSS_WAVELET_LUT_SIZE) $(DSSS_WAVELET_WIDTH) > $@ - -.PRECIOUS: $(BUILDDIR)/generated/dsss_butter_filter.h -$(BUILDDIR)/generated/dsss_butter_filter.h: | $(BUILDDIR)/generated - $(PYTHON3) tools/butter_filter_gen.py -m dsss_filter $(DSSS_FILTER_FC) $(FMEAS_SAMPLING_RATE) $(DSSS_FILTER_ORDER) > $@ - -.PRECIOUS: $(BUILDDIR)/generated/crypto_presig_data.c -$(BUILDDIR)/generated/crypto_presig_data.c: $(PRESIG_KEYFILE) tools/presig_gen.py | $(BUILDDIR)/generated - $(PYTHON3) tools/presig_gen.py $(PRESIG_KEYFILE) prekey > $@ - -.PRECIOUS: $(PRESIG_KEYFILE) -$(PRESIG_KEYFILE): - $(PYTHON3) tools/presig_gen.py $@ keygen - -$(BUILDDIR)/generated: ; mkdir -p $@ - -.PRECIOUS: $(BUILDDIR)/$(BINARY) -$(BUILDDIR)/$(BINARY) $(BUILDDIR)/$(BINARY:.elf=.map) &: $(ALL_OBJS) - $(LD) -T$(LDSCRIPT) $(LDFLAGS) -o $@ -Wl,-Map=$(BUILDDIR)/$(BINARY:.elf=.map) $^ $(LIBS) - -build/$(BINARY:.elf=-symbol-sizes.dot): $(ALL_OBJS) - $(PYTHON3) tools/linkmem.py $(LINKMEM_FLAGS) $(LD) -T$(LDSCRIPT) $(LDFLAGS) $^ $(LIBS) > $@ - -%.pdf: %.dot - $(DOT) -T pdf $< -o $@ - -%.dot: %.elf - r2 -a arm -qc 'aa;agRd' $< 2>/dev/null >$@ - -tools: $(BUILDDIR)/tools/freq_meas_test -$(BUILDDIR)/tools/freq_meas_test: tools/freq_meas_test.c src/freq_meas.c levmarq/levmarq.c $(BUILDDIR)/generated/fmeas_fft_window.c $(CMSIS_SOURCES) - mkdir -p $(@D) - $(HOST_CC) $(COMMON_CFLAGS) $(SIM_CFLAGS) -o $@ $^ - -tools: $(BUILDDIR)/tools/dsss_demod_test -$(BUILDDIR)/tools/dsss_demod_test: tools/dsss_demod_test.c src/dsss_demod.c $(BUILDDIR)/generated/dsss_cwt_wavelet.c $(BUILDDIR)/generated/gold_code_$(DSSS_GOLD_CODE_NBITS).c - mkdir -p $(@D) - $(HOST_CC) $(COMMON_CFLAGS) $(SIM_CFLAGS) -o $@ $^ - -tools: $(BUILDDIR)/tools/crypto_test -$(BUILDDIR)/tools/crypto_test: tools/crypto_test.c src/crypto.c tinyaes/aes.c $(BUILDDIR)/generated/crypto_presig_data.c - mkdir -p $(@D) - $(HOST_CC) $(COMMON_CFLAGS) $(SIM_CFLAGS) -lsodium -o $@ $^ - -tools: $(BUILDDIR)/tools/e2e_test -$(BUILDDIR)/tools/e2e_test: tools/e2e_test.c src/freq_meas.c levmarq/levmarq.c $(BUILDDIR)/generated/fmeas_fft_window.c $(CMSIS_SOURCES) src/dsss_demod.c $(BUILDDIR)/generated/dsss_cwt_wavelet.c $(BUILDDIR)/generated/gold_code_$(DSSS_GOLD_CODE_NBITS).c - mkdir -p $(@D) - $(HOST_CC) $(COMMON_CFLAGS) $(SIM_CFLAGS) -o $@ $^ - -$(BUILDDIR)/src/%.o: src/%.s - mkdir -p $(@D) - $(CC) $(COMMON_CFLAGS) $(CFLAGS) $(INT_CFLAGS) -o $@ -c $< - -$(BUILDDIR)/src/%.o: src/%.c - mkdir -p $(@D) - $(CC) $(COMMON_CFLAGS) $(CFLAGS) $(INT_CFLAGS) -o $@ -c $< - -$(BUILDDIR)/src/%.o: src/%.cpp - mkdir -p $(@D) - $(CXX) $(CXXFLAGS) -o $@ -c $< - -$(BUILDDIR)/generated/%.o: $(BUILDDIR)/generated/%.c - mkdir -p $(@D) - $(CC) $(COMMON_CFLAGS) $(CFLAGS) $(INT_CFLAGS) -o $@ -c $< - -$(BUILDDIR)/%.o: %.c - mkdir -p $(@D) - $(CC) $(COMMON_CFLAGS) $(CFLAGS) $(EXT_CFLAGS) -o $@ -c $< - -$(BUILDDIR)/src/crypto.o: $(BUILDDIR)/libsodium/src/libsodium/include/sodium/version.h - -$(BUILDDIR)/libsodium/src/libsodium/.libs/libsodium.a $(BUILDDIR)/libsodium/src/libsodium/include/sodium/version.h &: - mkdir -p $(BUILDDIR)/libsodium - cd $(BUILDDIR)/libsodium && CFLAGS="$(COMMON_CFLAGS) $(CFLAGS) -DDEV_MODE=1" $(LIBSODIUM_DIR_ABS)/configure --host=arm-none-eabi && $(MAKE) -j $(shell nproc) - -$(BUILDDIR)/tinyaes/aes.o: - mkdir -p $(@D) - make -C $(@D) -f $(TINYAES_DIR_ABS)/Makefile VPATH=$(TINYAES_DIR_ABS) CFLAGS="$(COMMON_CFLAGS) $(CFLAGS) -c" CC=$(CC) LD=$(LD) AR=$(AR) aes.o - -# $(BUILDDIR)/musl/lib/libc.a: -# mkdir -p $(BUILDDIR)/musl -# cd $(BUILDDIR)/musl && CFLAGS="$(SIM_CFLAGS) $(COMMON_CFLAGS)" CC=$(CC) LD=$(LD) AR=$(AR) $(MUSL_DIR_ABS)/configure && $(MAKE) TARGET=arm-linux-musleabihf GCC_CONFIG="-mcpu=cortex-m4 -mfloat-abi=soft" -j $(shell nproc) - -build/rslib.so: $(RSLIB_SOURCES) src/rslib.c - gcc -fPIC -shared -Wall -Wextra -Wpedantic -std=gnu11 -O0 -g -o $@ -Isrc -I$(RSLIB_DIR)/src $^ - -clean: - rm -rf $(BUILDDIR)/src - rm -rf $(BUILDDIR)/generated - rm -f $(BUILDDIR)/$(BINARY) - rm -f $(BUILDDIR)/$(BINARY:.elf=.map) - rm -f $(BUILDDIR)/$(BINARY:.elf=-symbol-sizes.dot) - rm -f $(BUILDDIR)/$(BINARY:.elf=-symbol-sizes.pdf) - rm -f $(BUILDDIR)/tools/freq_meas_test - -mrproper: clean - rm -rf build - -.PHONY: clean mrproper - --include $(OBJS:.o=.d) diff --git a/controller/fw/cmsis b/controller/fw/cmsis deleted file mode 160000 -Subproject 4a65d88011a1595b7c8b42fa0d70b7bdfc132ac diff --git a/controller/fw/crypto-algorithms b/controller/fw/crypto-algorithms deleted file mode 160000 -Subproject cfbde48414baacf51fc7c74f275190881f037d3 diff --git a/controller/fw/levmarq/LICENSE b/controller/fw/levmarq/LICENSE deleted file mode 100644 index 2a05e3e..0000000 --- a/controller/fw/levmarq/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -levmarq.c, levmarq.h, and examples are provided under the MIT license. - -Copyright (c) 2008-2016 Ron Babich - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/controller/fw/levmarq/levmarq.c b/controller/fw/levmarq/levmarq.c deleted file mode 100644 index 4a764db..0000000 --- a/controller/fw/levmarq/levmarq.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * levmarq.c - * - * This file contains an implementation of the Levenberg-Marquardt algorithm - * for solving least-squares problems, together with some supporting routines - * for Cholesky decomposition and inversion. No attempt has been made at - * optimization. In particular, memory use in the matrix routines could be - * cut in half with a little effort (and some loss of clarity). - * - * It is assumed that the compiler supports variable-length arrays as - * specified by the C99 standard. - * - * Ron Babich, May 2008 - * - */ - -#include <stdio.h> -#include <math.h> - -#include "levmarq.h" -#include "simulation.h" - - -#define TOL 1e-20f /* smallest value allowed in cholesky_decomp() */ - - -/* set parameters required by levmarq() to default values */ -void levmarq_init(LMstat *lmstat) -{ - lmstat->max_it = 100; - lmstat->init_lambda = 0.0001f; - lmstat->up_factor = 10.0f; - lmstat->down_factor = 10.0f; - lmstat->target_derr = 1e-12f; -} - -/* perform least-squares minimization using the Levenberg-Marquardt - algorithm. The arguments are as follows: - - npar number of parameters - par array of parameters to be varied - ny number of measurements to be fit - y array of measurements - dysq array of error in measurements, squared - (set dysq=NULL for unweighted least-squares) - func function to be fit - grad gradient of "func" with respect to the input parameters - fdata pointer to any additional data required by the function - lmstat pointer to the "status" structure, where minimization parameters - are set and the final status is returned. - - Before calling levmarq, several of the parameters in lmstat must be set. - For default values, call levmarq_init(lmstat). - */ -int levmarq(int npar, float *par, int ny, float *y, float *dysq, - float (*func)(float *, int, void *), - void (*grad)(float *, float *, int, void *), - void *fdata, LMstat *lmstat) -{ - int x,i,j,it,nit,ill; - float lambda,up,down,mult,weight,err,newerr,derr,target_derr; - float h[npar][npar],ch[npar][npar]; - float g[npar],d[npar],delta[npar],newpar[npar]; - - nit = lmstat->max_it; - lambda = lmstat->init_lambda; - up = lmstat->up_factor; - down = 1/lmstat->down_factor; - target_derr = lmstat->target_derr; - weight = 1; - derr = newerr = 0; /* to avoid compiler warnings */ - - /* calculate the initial error ("chi-squared") */ - err = error_func(par, ny, y, dysq, func, fdata); - - /* main iteration */ - for (it=0; it<nit; it++) { - //DEBUG_PRINT("iteration %d", it); - - /* calculate the approximation to the Hessian and the "derivative" d */ - for (i=0; i<npar; i++) { - d[i] = 0; - for (j=0; j<=i; j++) - h[i][j] = 0; - } - - for (x=0; x<ny; x++) { - if (dysq) weight = 1/dysq[x]; /* for weighted least-squares */ - grad(g, par, x, fdata); - for (i=0; i<npar; i++) { - d[i] += (y[x] - func(par, x, fdata))*g[i]*weight; - for (j=0; j<=i; j++) - h[i][j] += g[i]*g[j]*weight; - } - } - - /* make a step "delta." If the step is rejected, increase - lambda and try again */ - mult = 1 + lambda; - ill = 1; /* ill-conditioned? */ - while (ill && (it<nit)) { - for (i=0; i<npar; i++) - h[i][i] = h[i][i]*mult; - - ill = cholesky_decomp(npar, ch, h); - - if (!ill) { - solve_axb_cholesky(npar, ch, delta, d); - for (i=0; i<npar; i++) - newpar[i] = par[i] + delta[i]; - newerr = error_func(newpar, ny, y, dysq, func, fdata); - derr = newerr - err; - ill = (derr > 0); - } - if (ill) { - mult = (1 + lambda*up)/(1 + lambda); - lambda *= up; - it++; - } - } - for (i=0; i<npar; i++) - par[i] = newpar[i]; - err = newerr; - lambda *= down; - - if ((!ill)&&(-derr<target_derr)) break; - } - - lmstat->final_it = it; - lmstat->final_err = err; - lmstat->final_derr = derr; - - if (it == nit) { - DEBUG_PRINT("did not converge"); - return -1; - } - - return it; -} - - -/* calculate the error function (chi-squared) */ -float error_func(float *par, int ny, float *y, float *dysq, - float (*func)(float *, int, void *), void *fdata) -{ - int x; - float res,e=0; - - for (x=0; x<ny; x++) { - res = func(par, x, fdata) - y[x]; - if (dysq) /* weighted least-squares */ - e += res*res/dysq[x]; - else - e += res*res; - } - return e; -} - - -/* solve the equation Ax=b for a symmetric positive-definite matrix A, - using the Cholesky decomposition A=LL^T. The matrix L is passed in "l". - Elements above the diagonal are ignored. - */ -void solve_axb_cholesky(int n, float l[n][n], float x[n], float b[n]) -{ - int i,j; - float sum; - - /* solve L*y = b for y (where x[] is used to store y) */ - - for (i=0; i<n; i++) { - sum = 0; - for (j=0; j<i; j++) - sum += l[i][j] * x[j]; - x[i] = (b[i] - sum)/l[i][i]; - } - - /* solve L^T*x = y for x (where x[] is used to store both y and x) */ - - for (i=n-1; i>=0; i--) { - sum = 0; - for (j=i+1; j<n; j++) - sum += l[j][i] * x[j]; - x[i] = (x[i] - sum)/l[i][i]; - } -} - - -/* This function takes a symmetric, positive-definite matrix "a" and returns - its (lower-triangular) Cholesky factor in "l". Elements above the - diagonal are neither used nor modified. The same array may be passed - as both l and a, in which case the decomposition is performed in place. - */ -int cholesky_decomp(int n, float l[n][n], float a[n][n]) -{ - int i,j,k; - float sum; - - for (i=0; i<n; i++) { - for (j=0; j<i; j++) { - sum = 0; - for (k=0; k<j; k++) - sum += l[i][k] * l[j][k]; - l[i][j] = (a[i][j] - sum)/l[j][j]; - } - - sum = 0; - for (k=0; k<i; k++) - sum += l[i][k] * l[i][k]; - sum = a[i][i] - sum; - if (sum<TOL) return 1; /* not positive-definite */ - l[i][i] = sqrtf(sum); - } - return 0; -} diff --git a/controller/fw/levmarq/levmarq.h b/controller/fw/levmarq/levmarq.h deleted file mode 100644 index dff13ab..0000000 --- a/controller/fw/levmarq/levmarq.h +++ /dev/null @@ -1,30 +0,0 @@ - -#ifndef __LEVMARQ_H__ -#define __LEVMARQ_H__ - -typedef struct { - int max_it; - float init_lambda; - float up_factor; - float down_factor; - float target_derr; - int final_it; - float final_err; - float final_derr; -} LMstat; - -void levmarq_init(LMstat *lmstat); - -int levmarq(int npar, float *par, int ny, float *y, float *dysq, - float (*func)(float *, int, void *), - void (*grad)(float *, float *, int, void *), - void *fdata, LMstat *lmstat); - -float error_func(float *par, int ny, float *y, float *dysq, - float (*func)(float *, int, void *), void *fdata); - -void solve_axb_cholesky(int n, float l[n][n], float x[n], float b[n]); - -int cholesky_decomp(int n, float l[n][n], float a[n][n]); - -#endif /* __LEVMARQ_H__ */ diff --git a/controller/fw/libopencm3 b/controller/fw/libopencm3 deleted file mode 160000 -Subproject cb0661f81de5b1cae52ca99c7b5985b678176db diff --git a/controller/fw/libsodium b/controller/fw/libsodium deleted file mode 160000 -Subproject a0a8706c9dc9e43bc51d16334cd6c0f6ae084ce diff --git a/controller/fw/mspdebug b/controller/fw/mspdebug deleted file mode 160000 -Subproject b506542094de19a0a11e638a7e34e0bc4adf8d7 diff --git a/controller/fw/musl b/controller/fw/musl deleted file mode 160000 -Subproject 040c1d16b468c50c04fc94edff521f163770832 diff --git a/controller/fw/musl_include_shims/bits/alltypes.h b/controller/fw/musl_include_shims/bits/alltypes.h deleted file mode 100644 index 581ca85..0000000 --- a/controller/fw/musl_include_shims/bits/alltypes.h +++ /dev/null @@ -1,23 +0,0 @@ - -/* shim file for musl */ - -#ifndef __MUSL_SHIM_BITS_ALLTYPES_H__ -#define __MUSL_SHIM_BITS_ALLTYPES_H__ - -#define _REDIR_TIME64 1 -#define _Addr int -#define _Int64 long long -#define _Reg int - -#define __BYTE_ORDER 1234 - -#define __LONG_MAX 0x7fffffffL - -#ifndef __cplusplus -typedef unsigned wchar_t; -#endif - -typedef float float_t; -typedef double double_t; - -#endif /* __MUSL_SHIM_BITS_ALLTYPES_H__ */ diff --git a/controller/fw/musl_include_shims/endian.h b/controller/fw/musl_include_shims/endian.h deleted file mode 100644 index 172c432..0000000 --- a/controller/fw/musl_include_shims/endian.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef _ENDIAN_H -#define _ENDIAN_H - -#include <features.h> - -#define __NEED_uint16_t -#define __NEED_uint32_t -#define __NEED_uint64_t - -#include <bits/alltypes.h> - -#define __PDP_ENDIAN 3412 - -#define BIG_ENDIAN __BIG_ENDIAN -#define LITTLE_ENDIAN __LITTLE_ENDIAN -#define PDP_ENDIAN __PDP_ENDIAN -#define BYTE_ORDER __BYTE_ORDER - -static __inline uint16_t __bswap16(uint16_t __x) -{ - return __x<<8 | __x>>8; -} - -static __inline uint32_t __bswap32(uint32_t __x) -{ - return __x>>24 | __x>>8&0xff00 | __x<<8&0xff0000 | __x<<24; -} - -static __inline uint64_t __bswap64(uint64_t __x) -{ - return __bswap32(__x)+0ULL<<32 | __bswap32(__x>>32); -} - -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define htobe16(x) __bswap16(x) -#define be16toh(x) __bswap16(x) -#define htobe32(x) __bswap32(x) -#define be32toh(x) __bswap32(x) -#define htobe64(x) __bswap64(x) -#define be64toh(x) __bswap64(x) -#define htole16(x) (uint16_t)(x) -#define le16toh(x) (uint16_t)(x) -#define htole32(x) (uint32_t)(x) -#define le32toh(x) (uint32_t)(x) -#define htole64(x) (uint64_t)(x) -#define le64toh(x) (uint64_t)(x) -#else -#define htobe16(x) (uint16_t)(x) -#define be16toh(x) (uint16_t)(x) -#define htobe32(x) (uint32_t)(x) -#define be32toh(x) (uint32_t)(x) -#define htobe64(x) (uint64_t)(x) -#define be64toh(x) (uint64_t)(x) -#define htole16(x) __bswap16(x) -#define le16toh(x) __bswap16(x) -#define htole32(x) __bswap32(x) -#define le32toh(x) __bswap32(x) -#define htole64(x) __bswap64(x) -#define le64toh(x) __bswap64(x) -#endif - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define betoh16(x) __bswap16(x) -#define betoh32(x) __bswap32(x) -#define betoh64(x) __bswap64(x) -#define letoh16(x) (uint16_t)(x) -#define letoh32(x) (uint32_t)(x) -#define letoh64(x) (uint64_t)(x) -#else -#define betoh16(x) (uint16_t)(x) -#define betoh32(x) (uint32_t)(x) -#define betoh64(x) (uint64_t)(x) -#define letoh16(x) __bswap16(x) -#define letoh32(x) __bswap32(x) -#define letoh64(x) __bswap64(x) -#endif -#endif - -#endif diff --git a/controller/fw/musl_include_shims/features.h b/controller/fw/musl_include_shims/features.h deleted file mode 100644 index 85cfb72..0000000 --- a/controller/fw/musl_include_shims/features.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _FEATURES_H -#define _FEATURES_H - -#if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE) -#define _GNU_SOURCE 1 -#endif - -#if defined(_DEFAULT_SOURCE) && !defined(_BSD_SOURCE) -#define _BSD_SOURCE 1 -#endif - -#if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) \ - && !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) \ - && !defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__) -#define _BSD_SOURCE 1 -#define _XOPEN_SOURCE 700 -#endif - -#if __STDC_VERSION__ >= 199901L -#define __restrict restrict -#elif !defined(__GNUC__) -#define __restrict -#endif - -#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) -#define __inline inline -#elif !defined(__GNUC__) -#define __inline -#endif - -#if __STDC_VERSION__ >= 201112L -#elif defined(__GNUC__) -#define _Noreturn __attribute__((__noreturn__)) -#else -#define _Noreturn -#endif - -#define __REDIR(x,y) __typeof__(x) x __asm__(#y) - -#endif diff --git a/controller/fw/musl_include_shims/fp_arch.h b/controller/fw/musl_include_shims/fp_arch.h deleted file mode 100644 index f5bab6d..0000000 --- a/controller/fw/musl_include_shims/fp_arch.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __MUSL_SHIM_FP_ARCH_H__ -#define __MUSL_SHIM_FP_ARCH_H__ - -#define hidden - -#endif /* __MUSL_SHIM_FP_ARCH_H__ */ diff --git a/controller/fw/musl_include_shims/libm.h b/controller/fw/musl_include_shims/libm.h deleted file mode 100644 index d48135d..0000000 --- a/controller/fw/musl_include_shims/libm.h +++ /dev/null @@ -1,270 +0,0 @@ -#ifndef _LIBM_H -#define _LIBM_H - -#include <stdint.h> -#include <float.h> -#include <math.h> -#include <endian.h> -#include "fp_arch.h" - -#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 -#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN -union ldshape { - long double f; - struct { - uint64_t m; - uint16_t se; - } i; -}; -#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN -/* This is the m68k variant of 80-bit long double, and this definition only works - * on archs where the alignment requirement of uint64_t is <= 4. */ -union ldshape { - long double f; - struct { - uint16_t se; - uint16_t pad; - uint64_t m; - } i; -}; -#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN -union ldshape { - long double f; - struct { - uint64_t lo; - uint32_t mid; - uint16_t top; - uint16_t se; - } i; - struct { - uint64_t lo; - uint64_t hi; - } i2; -}; -#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN -union ldshape { - long double f; - struct { - uint16_t se; - uint16_t top; - uint32_t mid; - uint64_t lo; - } i; - struct { - uint64_t hi; - uint64_t lo; - } i2; -}; -#else -#error Unsupported long double representation -#endif - -/* Support non-nearest rounding mode. */ -#define WANT_ROUNDING 1 -/* Support signaling NaNs. */ -#define WANT_SNAN 0 - -#if WANT_SNAN -#error SNaN is unsupported -#else -#define issignalingf_inline(x) 0 -#define issignaling_inline(x) 0 -#endif - -#ifndef TOINT_INTRINSICS -#define TOINT_INTRINSICS 0 -#endif - -#if TOINT_INTRINSICS -/* Round x to nearest int in all rounding modes, ties have to be rounded - consistently with converttoint so the results match. If the result - would be outside of [-2^31, 2^31-1] then the semantics is unspecified. */ -static double_t roundtoint(double_t); - -/* Convert x to nearest int in all rounding modes, ties have to be rounded - consistently with roundtoint. If the result is not representible in an - int32_t then the semantics is unspecified. */ -static int32_t converttoint(double_t); -#endif - -/* Helps static branch prediction so hot path can be better optimized. */ -#ifdef __GNUC__ -#define predict_true(x) __builtin_expect(!!(x), 1) -#define predict_false(x) __builtin_expect(x, 0) -#else -#define predict_true(x) (x) -#define predict_false(x) (x) -#endif - -/* Evaluate an expression as the specified type. With standard excess - precision handling a type cast or assignment is enough (with - -ffloat-store an assignment is required, in old compilers argument - passing and return statement may not drop excess precision). */ - -static inline float eval_as_float(float x) -{ - float y = x; - return y; -} - -static inline double eval_as_double(double x) -{ - double y = x; - return y; -} - -/* fp_barrier returns its input, but limits code transformations - as if it had a side-effect (e.g. observable io) and returned - an arbitrary value. */ - -#ifndef fp_barrierf -#define fp_barrierf fp_barrierf -static inline float fp_barrierf(float x) -{ - volatile float y = x; - return y; -} -#endif - -#ifndef fp_barrier -#define fp_barrier fp_barrier -static inline double fp_barrier(double x) -{ - volatile double y = x; - return y; -} -#endif - -#ifndef fp_barrierl -#define fp_barrierl fp_barrierl -static inline long double fp_barrierl(long double x) -{ - volatile long double y = x; - return y; -} -#endif - -/* fp_force_eval ensures that the input value is computed when that's - otherwise unused. To prevent the constant folding of the input - expression, an additional fp_barrier may be needed or a compilation - mode that does so (e.g. -frounding-math in gcc). Then it can be - used to evaluate an expression for its fenv side-effects only. */ - -#ifndef fp_force_evalf -#define fp_force_evalf fp_force_evalf -static inline void fp_force_evalf(float x) -{ - volatile float y; - y = x; -} -#endif - -#ifndef fp_force_eval -#define fp_force_eval fp_force_eval -static inline void fp_force_eval(double x) -{ - volatile double y; - y = x; -} -#endif - -#ifndef fp_force_evall -#define fp_force_evall fp_force_evall -static inline void fp_force_evall(long double x) -{ - volatile long double y; - y = x; -} -#endif - -#define FORCE_EVAL(x) do { \ - if (sizeof(x) == sizeof(float)) { \ - fp_force_evalf(x); \ - } else if (sizeof(x) == sizeof(double)) { \ - fp_force_eval(x); \ - } else { \ - fp_force_evall(x); \ - } \ -} while(0) - -#define asuint(f) ((union{float _f; uint32_t _i;}){f})._i -#define asfloat(i) ((union{uint32_t _i; float _f;}){i})._f -#define asuint64(f) ((union{double _f; uint64_t _i;}){f})._i -#define asdouble(i) ((union{uint64_t _i; double _f;}){i})._f - -#define EXTRACT_WORDS(hi,lo,d) \ -do { \ - uint64_t __u = asuint64(d); \ - (hi) = __u >> 32; \ - (lo) = (uint32_t)__u; \ -} while (0) - -#define GET_HIGH_WORD(hi,d) \ -do { \ - (hi) = asuint64(d) >> 32; \ -} while (0) - -#define GET_LOW_WORD(lo,d) \ -do { \ - (lo) = (uint32_t)asuint64(d); \ -} while (0) - -#define INSERT_WORDS(d,hi,lo) \ -do { \ - (d) = asdouble(((uint64_t)(hi)<<32) | (uint32_t)(lo)); \ -} while (0) - -#define SET_HIGH_WORD(d,hi) \ - INSERT_WORDS(d, hi, (uint32_t)asuint64(d)) - -#define SET_LOW_WORD(d,lo) \ - INSERT_WORDS(d, asuint64(d)>>32, lo) - -#define GET_FLOAT_WORD(w,d) \ -do { \ - (w) = asuint(d); \ -} while (0) - -#define SET_FLOAT_WORD(d,w) \ -do { \ - (d) = asfloat(w); \ -} while (0) - -hidden int __rem_pio2_large(double*,double*,int,int,int); - -hidden int __rem_pio2(double,double*); -hidden double __sin(double,double,int); -hidden double __cos(double,double); -hidden double __tan(double,double,int); -hidden double __expo2(double); - -hidden int __rem_pio2f(float,double*); -hidden float __sindf(double); -hidden float __cosdf(double); -hidden float __tandf(double,int); -hidden float __expo2f(float); - -hidden int __rem_pio2l(long double, long double *); -hidden long double __sinl(long double, long double, int); -hidden long double __cosl(long double, long double); -hidden long double __tanl(long double, long double, int); - -hidden long double __polevll(long double, const long double *, int); -hidden long double __p1evll(long double, const long double *, int); - -hidden double __lgamma_r(double, int *); -hidden float __lgammaf_r(float, int *); - -/* error handling functions */ -hidden float __math_xflowf(uint32_t, float); -hidden float __math_uflowf(uint32_t); -hidden float __math_oflowf(uint32_t); -hidden float __math_divzerof(uint32_t); -hidden float __math_invalidf(float); -hidden double __math_xflow(uint32_t, double); -hidden double __math_uflow(uint32_t); -hidden double __math_oflow(uint32_t); -hidden double __math_divzero(uint32_t); -hidden double __math_invalid(double); - -#endif diff --git a/controller/fw/reed_solomon b/controller/fw/reed_solomon deleted file mode 160000 -Subproject 9349f519af7e9a34f2e66de0c8b1ef90b5de28f diff --git a/controller/fw/src/adc.c b/controller/fw/src/adc.c deleted file mode 100644 index 02d729a..0000000 --- a/controller/fw/src/adc.c +++ /dev/null @@ -1,100 +0,0 @@ - -#include <assert.h> -#include <string.h> -#include <stdint.h> - -#include "adc.h" -#include "sr_global.h" - -static unsigned int adc_overruns = 0; -uint16_t adc_fft_buf[2][FMEAS_FFT_LEN]; -volatile int adc_fft_buf_ready_idx = -1; - -static DMA_TypeDef *const adc_dma = DMA2; -static DMA_Stream_TypeDef *const adc_stream = DMA2_Stream0; -static const int dma_adc_channel = 0; -static const int adc_channel = 10; - -/* Configure ADC1 to sample channel 0. Trigger from TIM1 CC0 every 1ms. Transfer readings into alternating buffers - * throug DMA. Enable DMA interrupts. - * - * We have two full FFT buffers. We always transfer data from the ADC to the back half of the active one, while a - * DMA memcpy'es the latter half of the inactive one to the front half of the active one. This means at the end of the - * ADC's DMA transfer, in the now-inactive buffer that the ADC results were just written to we have last half-period's - * data sitting in front of this half-period's data like so: [old_adc_data, new_adc_data] - * - * This means we can immediately start running an FFT on ADC DMA transfer complete interrupt. - */ -void adc_init() { - RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN | RCC_AHB1ENR_GPIOCEN; - RCC->APB2ENR |= RCC_APB2ENR_ADC1EN | RCC_APB2ENR_TIM1EN; - - /* PC0 -> ADC1.ch10 */ - GPIOC->MODER &= ~GPIO_MODER_MODER0_Msk; - GPIOC->MODER |= (3<<GPIO_MODER_MODER0_Pos); - - adc_dma->LIFCR |= 0x3f; - adc_stream->CR = 0; /* disable */ - while (adc_stream->CR & DMA_SxCR_EN) - ; /* wait for stream to become available */ - adc_stream->NDTR = FMEAS_FFT_LEN/2; - adc_stream->PAR = (uint32_t) &(ADC1->DR); - adc_stream->M0AR = (uint32_t) (adc_fft_buf[0] + FMEAS_FFT_LEN/2); - adc_stream->M1AR = (uint32_t) (adc_fft_buf[1] + FMEAS_FFT_LEN/2); - adc_stream->CR = (dma_adc_channel<<DMA_SxCR_CHSEL_Pos) | DMA_SxCR_DBM | (1<<DMA_SxCR_MSIZE_Pos) - | (1<<DMA_SxCR_PSIZE_Pos) | DMA_SxCR_MINC | (2<<DMA_SxCR_PL_Pos) - | DMA_SxCR_TCIE | DMA_SxCR_TEIE | DMA_SxCR_DMEIE; - adc_stream->CR |= DMA_SxCR_EN; - - NVIC_EnableIRQ(DMA2_Stream0_IRQn); - NVIC_SetPriority(DMA2_Stream0_IRQn, 128); - - ADC1->CR1 = (0<<ADC_CR1_RES_Pos) | (0<<ADC_CR1_DISCNUM_Pos) | ADC_CR1_DISCEN | (0<<ADC_CR1_AWDCH_Pos); - ADC1->CR2 = (1<<ADC_CR2_EXTEN_Pos) | (0<<ADC_CR2_EXTSEL_Pos) | ADC_CR2_DMA | ADC_CR2_ADON | ADC_CR2_DDS; - ADC1->SQR3 = (adc_channel<<ADC_SQR3_SQ1_Pos); - ADC1->SQR1 = (0<<ADC_SQR1_L_Pos); - ADC1->SMPR2 = (7<<ADC_SMPR2_SMP0_Pos); - - TIM1->CR2 = (2<<TIM_CR2_MMS_Pos); /* Enable update event on TRGO to provide a 1ms reference to rest of system */ - TIM1->CCMR1 = (6<<TIM_CCMR1_OC1M_Pos) | (0<<TIM_CCMR1_CC1S_Pos); - TIM1->CCER = TIM_CCER_CC1E; - assert(apb2_timer_speed%1000000 == 0); - TIM1->PSC = 1000-1; - TIM1->ARR = (apb2_timer_speed/1000000)-1; /* 1ms period */ - TIM1->CCR1 = 1; - TIM1->BDTR = TIM_BDTR_MOE; - - TIM1->CR1 = TIM_CR1_CEN; - TIM1->EGR = TIM_EGR_UG; -} - -void DMA2_Stream0_IRQHandler(void) { - uint8_t isr = (DMA2->LISR >> DMA_LISR_FEIF0_Pos) & 0x3f; - GPIOA->BSRR = 1<<11; - - if (isr & DMA_LISR_TCIF0) { /* Transfer complete */ - /* Check we're done processing the old buffer */ - if (adc_fft_buf_ready_idx != -1) { /* FIXME DEBUG */ - GPIOA->BSRR = 1<<11<<16; - /* clear all flags */ - adc_dma->LIFCR = isr<<DMA_LISR_FEIF0_Pos; - adc_overruns++; - return; - panic(); - } - - /* Kickoff FFT */ - int ct = !!(adc_stream->CR & DMA_SxCR_CT); - adc_fft_buf_ready_idx = !ct; - } - - if (isr & DMA_LISR_DMEIF0) /* Direct mode error */ - panic(); - - if (isr & DMA_LISR_TEIF0) /* Transfer error */ - panic(); - - GPIOA->BSRR = 1<<11<<16; - /* clear all flags */ - adc_dma->LIFCR = isr<<DMA_LISR_FEIF0_Pos; -} diff --git a/controller/fw/src/adc.h b/controller/fw/src/adc.h deleted file mode 100644 index e5611cb..0000000 --- a/controller/fw/src/adc.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __ADC_H__ -#define __ADC_H__ - -void adc_init(void); - -extern uint16_t adc_fft_buf[2][FMEAS_FFT_LEN]; -/* set index of ready buffer in adc.c, reset to -1 in main.c after processing */ -extern volatile int adc_fft_buf_ready_idx; - -#endif /* __ADC_H__ */ diff --git a/controller/fw/src/con_usart.c b/controller/fw/src/con_usart.c deleted file mode 100644 index f80fa79..0000000 --- a/controller/fw/src/con_usart.c +++ /dev/null @@ -1,33 +0,0 @@ - -#include <stm32f4_isr.h> -#include "con_usart.h" - -volatile struct usart_desc con_usart = { - .le_usart = USART1, - .le_usart_irqn = USART1_IRQn, - .tx_dmas = DMA2_Stream7, - .tx_dma_sn = 7, - .tx_dma_ch = 4, - .tx_dma = DMA2, - .tx_dma_irqn = DMA2_Stream7_IRQn, -}; - -void con_usart_init() { - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_DMA2EN; - RCC->APB2ENR |= RCC_APB2ENR_USART1EN; - - /* GPIO config: A9 (TX), A10 (RX) */ - GPIOA->MODER &= ~GPIO_MODER_MODER9_Msk & ~GPIO_MODER_MODER10_Msk; - GPIOA->MODER |= (2<<GPIO_MODER_MODER9_Pos) | (2<<GPIO_MODER_MODER10_Pos); - GPIOA->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED9_Msk & ~GPIO_OSPEEDR_OSPEED10_Msk; - GPIOA->OSPEEDR |= (2<<GPIO_OSPEEDR_OSPEED9_Pos) | (2<<GPIO_OSPEEDR_OSPEED10_Pos); - GPIOA->AFR[1] &= ~GPIO_AFRH_AFSEL9_Msk & ~GPIO_AFRH_AFSEL10_Msk; - GPIOA->AFR[1] |= (7<<GPIO_AFRH_AFSEL9_Pos) | (7<<GPIO_AFRH_AFSEL10_Pos); - - usart_dma_init(&con_usart, CON_USART_BAUDRATE); -} - -void DMA2_Stream7_IRQHandler(void) { - usart_dma_stream_irq(&con_usart); -} - diff --git a/controller/fw/src/con_usart.h b/controller/fw/src/con_usart.h deleted file mode 100644 index db73f0d..0000000 --- a/controller/fw/src/con_usart.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __CON_USART_H__ -#define __CON_USART_H__ - -#include "serial.h" - -extern volatile struct usart_desc con_usart; - -#define con_printf(...) usart_printf(&con_usart, __VA_ARGS__) -#define con_printf_blocking(...) usart_printf_blocking(&con_usart, __VA_ARGS__) - -#ifndef CON_USART_BAUDRATE -#define CON_USART_BAUDRATE 500000 -#endif - -void con_usart_init(void); - -#endif /* __CON_USART_H__ */ diff --git a/controller/fw/src/crypto.c b/controller/fw/src/crypto.c deleted file mode 100644 index f4f79a4..0000000 --- a/controller/fw/src/crypto.c +++ /dev/null @@ -1,80 +0,0 @@ - -#include <assert.h> -#include <unistd.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> - -#include <sodium.h> - -#include "crypto.h" -#include "simulation.h" - - -void debug_hexdump(const char *name, const uint8_t *buf, size_t len); -int verify_trigger_dom(const uint8_t inkey[PRESIG_MSG_LEN], - const char *domain_string, const uint8_t refkey[PRESIG_MSG_LEN]); - - -void debug_hexdump(const char *name, const uint8_t *buf, size_t len) { - DEBUG_PRINTN("%20s: ", name); - for (size_t i=0; i<len;) { - for (size_t j=0; j<8 && i<len; i++, j++) - DEBUG_PRINTN("%02x ", buf[i]); - DEBUG_PRINTN(" "); - } - DEBUG_PRINTN("\n"); -} - -/* Returns trigger sig height for correct trigger */ -int verify_trigger_dom(const uint8_t inkey[PRESIG_MSG_LEN], - const char *domain_string, const uint8_t refkey[PRESIG_MSG_LEN]) { - uint8_t key[crypto_auth_hmacsha512_KEYBYTES]; - uint8_t key_out[crypto_auth_hmacsha512_BYTES]; - - static_assert(PRESIG_MSG_LEN <= crypto_auth_hmacsha512_KEYBYTES); - memcpy(key, inkey, PRESIG_MSG_LEN); - memset(key + PRESIG_MSG_LEN, 0, sizeof(key) - PRESIG_MSG_LEN); - DEBUG_PRINT("ds \"%s\"", domain_string); - debug_hexdump("ref", refkey, PRESIG_MSG_LEN); - - for (int i=0; i<presig_height; i++) { - DEBUG_PRINT("Verifying height rel %d abs %d", i, presig_height-i); - debug_hexdump("key", key, sizeof(key)); - (void)crypto_auth_hmacsha512(key_out, (uint8_t *)domain_string, strlen(domain_string), key); - debug_hexdump("out", key_out, sizeof(key_out)); - memcpy(key, key_out, PRESIG_MSG_LEN); - memset(key + PRESIG_MSG_LEN, 0, sizeof(key) - PRESIG_MSG_LEN); - - if (!memcmp(key, refkey, PRESIG_MSG_LEN)) - return presig_height-i; - } - - return 0; -} - -int verify_trigger(const uint8_t inkey[PRESIG_MSG_LEN], int *height_out, int *domain_out) { - int res; - for (int i=0; i<_TRIGGER_DOMAIN_COUNT; i++) { - DEBUG_PRINT("Verifying domain %d", i); - if ((res = verify_trigger_dom(inkey, presig_domain_strings[i], presig_keys[i]))) { - DEBUG_PRINT("Match!"); - if (height_out) - *height_out = res - 1; - if (domain_out) - *domain_out = i; - return 1; - } - } - return 0; -} - -int oob_message_received(uint8_t msg[static OOB_TRIGGER_LEN]) { - int height, domain; - if (verify_trigger(msg, &height, &domain)) { - oob_trigger_activated(domain, height); - return 1; - } - - return 0; -} diff --git a/controller/fw/src/crypto.h b/controller/fw/src/crypto.h deleted file mode 100644 index 18a9816..0000000 --- a/controller/fw/src/crypto.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __CRYPTO_H__ -#define __CRYPTO_H__ - -#include <stdint.h> - -/* Presig message length: 15 byte = 120 bit ^= 20 * 6-bit symbols of 5-bit bipolar DSSS */ -#define PRESIG_MSG_LEN 15 -#define OOB_TRIGGER_LEN PRESIG_MSG_LEN - -enum trigger_domain { - TRIGGER_DOMAIN_ALL, - TRIGGER_DOMAIN_VENDOR, - TRIGGER_DOMAIN_SERIES, - TRIGGER_DOMAIN_COUNTRY, - TRIGGER_DOMAIN_REGION, - _TRIGGER_DOMAIN_COUNT -}; - -extern const char *presig_domain_strings[_TRIGGER_DOMAIN_COUNT]; -extern uint8_t presig_keys[_TRIGGER_DOMAIN_COUNT][PRESIG_MSG_LEN]; -extern int presig_height; -extern uint8_t presig_bundle_id[16]; -extern uint64_t bundle_timestamp; - -extern void oob_trigger_activated(enum trigger_domain domain, int height); - -int oob_message_received(uint8_t msg[static OOB_TRIGGER_LEN]); -int verify_trigger(const uint8_t inkey[PRESIG_MSG_LEN], int *height_out, int *domain_out); - -#endif /* __CRYPTO_H__ */ diff --git a/controller/fw/src/dma_util.c b/controller/fw/src/dma_util.c deleted file mode 100644 index 48de215..0000000 --- a/controller/fw/src/dma_util.c +++ /dev/null @@ -1,46 +0,0 @@ - -#include <assert.h> - -#include "dma_util.h" - -uint8_t dma_get_isr_and_clear(DMA_TypeDef *dma, int ch) { - uint8_t isr_val; - switch(ch) { - case 0: - isr_val = dma->LISR & 0x3f; - dma->LIFCR = isr_val; - return isr_val; - case 1: - isr_val = dma->LISR>>6 & 0x3f; - dma->LIFCR = isr_val<<6; - return isr_val; - case 2: - isr_val = dma->LISR>>16 & 0x3f; - dma->LIFCR = isr_val<<16; - return isr_val; - case 3: - isr_val = dma->LISR>>6>>16 & 0x3f; - dma->LIFCR = isr_val<<6<<16; - return isr_val; - case 4: - isr_val = dma->HISR & 0x3f; - dma->HIFCR = isr_val; - return isr_val; - case 5: - isr_val = dma->HISR>>6 & 0x3f; - dma->HIFCR = isr_val<<6; - return isr_val; - case 6: - isr_val = dma->HISR>>16 & 0x3f; - dma->HIFCR = isr_val<<16; - return isr_val; - case 7: - isr_val = dma->HISR>>6>>16 & 0x3f; - dma->HIFCR = isr_val<<6<<16; - return isr_val; - default: - assert(0); - return 0; - } -} - diff --git a/controller/fw/src/dma_util.h b/controller/fw/src/dma_util.h deleted file mode 100644 index 5ea2676..0000000 --- a/controller/fw/src/dma_util.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __DMA_UTIL_H__ -#define __DMA_UTIL_H__ - -#include <stdint.h> - -#include "sr_global.h" - -uint8_t dma_get_isr_and_clear(DMA_TypeDef *dma, int ch); - -#endif /* __DMA_UTIL_H__ */ diff --git a/controller/fw/src/dsss_demod.c b/controller/fw/src/dsss_demod.c deleted file mode 100644 index ad44b29..0000000 --- a/controller/fw/src/dsss_demod.c +++ /dev/null @@ -1,369 +0,0 @@ - -#include <unistd.h> -#include <stdbool.h> -#include <math.h> -#include <stdlib.h> -#include <assert.h> - -#include <arm_math.h> - -#include "freq_meas.h" -#include "sr_global.h" -#include "dsss_demod.h" -#include "simulation.h" - -#include "generated/dsss_gold_code.h" -// #include "generated/dsss_butter_filter.h" - -/* Generated CWT wavelet LUT */ -extern const float * const dsss_cwt_wavelet_table; - -//struct iir_biquad cwt_filter_bq[DSSS_FILTER_CLEN] = {DSSS_FILTER_COEFF}; - -void debug_print_vector(const char *name, size_t len, const float *data, size_t stride, bool index, bool debug); -static float gold_correlate_step(const size_t ncode, const float a[DSSS_CORRELATION_LENGTH], size_t offx, bool debug); -static float cwt_convolve_step(const float v[DSSS_WAVELET_LUT_SIZE], size_t offx); -//static float run_iir(const float x, const int order, const struct iir_biquad q[order], struct iir_biquad_state st[order]); -//static float run_biquad(float x, const struct iir_biquad *const q, struct iir_biquad_state *const restrict st); -static void matcher_init(struct matcher_state states[static DSSS_MATCHER_CACHE_SIZE]); -static void matcher_tick(struct matcher_state states[static DSSS_MATCHER_CACHE_SIZE], - uint64_t ts, int peak_ch, float peak_ampl); -static void group_received(struct dsss_demod_state *st); -static symbol_t decode_peak(int peak_ch, float peak_ampl); - -#ifdef SIMULATION -void debug_print_vector(const char *name, size_t len, const float *data, size_t stride, bool index, bool debug) { - if (!debug) - return; - - if (index) { - DEBUG_PRINTN(" %16s [", ""); - for (size_t i=0; i<len; i++) - DEBUG_PRINTN("%8zu ", i); - DEBUG_PRINTN("]\n"); - } - - DEBUG_PRINTN(" %16s: [", name); - for (size_t i=0; i<len; i++) - DEBUG_PRINTN("%8.5f, ", data[i*stride]); - DEBUG_PRINTN("]\n"); -} -#else -void debug_print_vector(unused_a const char *name, unused_a size_t len, unused_a const float *data, - unused_a size_t stride, unused_a bool index, unused_a bool debug) {} -#endif - -void dsss_demod_init(struct dsss_demod_state *st) { - memset(st, 0, sizeof(*st)); - matcher_init(st->matcher_cache); -} - -void dsss_demod_step(struct dsss_demod_state *st, float new_value, uint64_t ts) { - //const float hole_patching_threshold = 0.01 * DSSS_CORRELATION_LENGTH; - bool log = false; - bool log_groups = false; - - st->signal[st->signal_wpos] = new_value; - st->signal_wpos = (st->signal_wpos + 1) % ARRAY_LENGTH(st->signal); - - /* use new, incremented wpos for gold_correlate_step as first element of old data in ring buffer */ - for (size_t i=0; i<DSSS_GOLD_CODE_COUNT; i++) - st->correlation[i][st->correlation_wpos] = gold_correlate_step(i, st->signal, st->signal_wpos, false); - - st->correlation_wpos = (st->correlation_wpos + 1) % ARRAY_LENGTH(st->correlation[0]); - - float cwt[DSSS_GOLD_CODE_COUNT]; - for (size_t i=0; i<DSSS_GOLD_CODE_COUNT; i++) - cwt[i] = cwt_convolve_step(st->correlation[i], st->correlation_wpos); - - float avg = 0.0f; - for (size_t i=0; i<DSSS_GOLD_CODE_COUNT; i++) - avg += fabsf(cwt[i]); - avg /= (float)DSSS_GOLD_CODE_COUNT; - if (log) DEBUG_PRINTN("%6zu: %f ", ts, avg); - /* FIXME fix this filter */ - //avg = run_iir(avg, ARRAY_LENGTH(cwt_filter_bq), cwt_filter_bq, st->cwt_filter.st); - - float max_val = st->group.max; - int max_ch = st->group.max_ch; - int max_ts = st->group.max_ts; - bool found = false; - for (size_t i=0; i<DSSS_GOLD_CODE_COUNT; i++) { - float val = cwt[i] / avg; - if (log) DEBUG_PRINTN("%f ", cwt[i]); - if (log) DEBUG_PRINTN("%f ", val); - - if (fabsf(val) > fabsf(max_val)) { - max_val = val; - max_ch = i; - max_ts = ts; - } - - if (fabsf(val) > DSSS_THRESHOLD_FACTOR) - found = true; - } - if (log) DEBUG_PRINTN("%f %d ", max_val, found); - if (log) DEBUG_PRINTN("\n"); - - matcher_tick(st->matcher_cache, ts, max_ch, max_val); - - if (found) { - /* Continue ongoing group */ - st->group.len++; - st->group.max = max_val; - st->group.max_ch = max_ch; - st->group.max_ts = max_ts; - return; - } - - if (st->group.len == 0) - /* We're between groups */ - return; - - if (log_groups) DEBUG_PRINTN("GROUP: %zu %d %f\n", st->group.max_ts, st->group.max_ch, st->group.max); - /* A group ended. Process result. */ - group_received(st); - - /* reset grouping state */ - st->group.len = 0; - st->group.max_ts = 0; - st->group.max_ch = 0; - st->group.max = 0.0f; -} - -/* Map a sequence match to a data symbol. This maps the sequence's index number to the 2nd to n+2nd bit of the result, - * and maps the polarity of detection to the LSb. 5-bit example: - * - * [0, S, S, S, S, S, S, P] ; S ^= symbol index (0 - 2^n+1 so we need just about n+1 bit), P ^= symbol polarity - * - * Symbol polarity is preserved from transmitter to receiver. The symbol index is n+1 bit instead of n bit since we have - * 2^n+1 symbols to express, one too many for an n-bit index. - */ -symbol_t decode_peak(int peak_ch, float peak_ampl) { - return (peak_ch<<1) | (peak_ampl > 0); -} - -void matcher_init(struct matcher_state states[static DSSS_MATCHER_CACHE_SIZE]) { - for (size_t i=0; i<DSSS_MATCHER_CACHE_SIZE; i++) - states[i].last_phase = -1; /* mark as inactive */ -} - -/* TODO make these constants configurable from Makefile */ -const int group_phase_tolerance = (int)(DSSS_CORRELATION_LENGTH * 0.10); - -void matcher_tick(struct matcher_state states[static DSSS_MATCHER_CACHE_SIZE], uint64_t ts, int peak_ch, float peak_ampl) { - /* TODO make these constants configurable from Makefile */ - const float skip_sampling_depreciation = 0.2f; /* 0.0 -> no depreciation, 1.0 -> complete disregard */ - const float score_depreciation = 0.1f; /* 0.0 -> no depreciation, 1.0 -> complete disregard */ - const int current_phase = ts % DSSS_CORRELATION_LENGTH; - const int max_skips = TRANSMISSION_SYMBOLS/4*3; - bool debug = false; - - bool header_printed = false; - for (size_t i=0; i<DSSS_MATCHER_CACHE_SIZE; i++) { - if (states[i].last_phase == -1) - continue; /* Inactive entry */ - - if (current_phase == states[i].last_phase) { - /* Skip sampling */ - float score = fabsf(peak_ampl) * (1.0f - skip_sampling_depreciation); - if (score > states[i].candidate_score) { - if (debug && !header_printed) { - header_printed = true; - DEBUG_PRINTN("windows %zu\n", ts); - } - if (debug) DEBUG_PRINTN(" skip %zd old=%f new=%f\n", i, states[i].candidate_score, score); - /* We win, update candidate */ - assert(i < DSSS_MATCHER_CACHE_SIZE); - states[i].candidate_score = score; - states[i].candidate_phase = current_phase; - states[i].candidate_data = decode_peak(peak_ch, peak_ampl); - states[i].candidate_skips = 1; - } - } - - /* Note of caution on group_phase_tolerance: Group detection has some latency since a group is only considered - * "detected" after signal levels have fallen back below the detection threshold. This means we only get to - * process a group a couple ticks after its peak. We have to make sure the window is still open at this point. - * This means we have to match against group_phase_tolerance should a little bit loosely. - */ - int phase_delta = current_phase - states[i].last_phase; - if (phase_delta < 0) - phase_delta += DSSS_CORRELATION_LENGTH; - if (phase_delta == group_phase_tolerance + DSSS_DECIMATION) { - if (debug && !header_printed) { - header_printed = true; - DEBUG_PRINTN("windows %zu\n", ts); - } - if (debug) DEBUG_PRINTN(" %zd ", i); - /* Process window results */ - assert(i < DSSS_MATCHER_CACHE_SIZE); - assert(0 <= states[i].data_pos && states[i].data_pos < TRANSMISSION_SYMBOLS); - states[i].data[ states[i].data_pos ] = states[i].candidate_data; - states[i].data_pos = states[i].data_pos + 1; - states[i].last_score = score_depreciation * states[i].last_score + - (1.0f - score_depreciation) * states[i].candidate_score; - if (debug) DEBUG_PRINTN("commit pos=%d val=%d score=%f ", states[i].data_pos, states[i].candidate_data, states[i].last_score); - states[i].candidate_score = 0.0f; - states[i].last_skips += states[i].candidate_skips; - - if (states[i].last_skips > max_skips) { - if (debug) DEBUG_PRINTN("expire "); - states[i].last_phase = -1; /* invalidate entry */ - - } else if (states[i].data_pos == TRANSMISSION_SYMBOLS) { - if (debug) DEBUG_PRINTN("match "); - /* Frame received completely */ - handle_dsss_received(states[i].data); - states[i].last_phase = -1; /* invalidate entry */ - } - if (debug) DEBUG_PRINTN("\n"); - } - } -} - -static float gaussian(float a, float b, float c, float x) { - float n = x-b; - return a*expf(-n*n / (2.0f* c*c)); -} - - -static float score_group(const struct group *g, int phase_delta) { - /* TODO make these constants configurable from Makefile */ - const float distance_func_phase_tolerance = 10.0f; - return fabsf(g->max) * gaussian(1.0f, 0.0f, distance_func_phase_tolerance, phase_delta); -} - -void group_received(struct dsss_demod_state *st) { - bool debug = false; - const int group_phase = st->group.max_ts % DSSS_CORRELATION_LENGTH; - /* This is the score of a decoding starting at this group (with no context) */ - float base_score = score_group(&st->group, 0); - - float min_score = INFINITY; - ssize_t min_idx = -1; - ssize_t empty_idx = -1; - for (size_t i=0; i<DSSS_MATCHER_CACHE_SIZE; i++) { - - /* Search for empty entries */ - if (st->matcher_cache[i].last_phase == -1) { - empty_idx = i; - continue; - } - - /* Search for entries with matching phase */ - /* This is the score of this group given the cached decoding at [i] */ - int phase_delta = st->matcher_cache[i].last_phase - group_phase; - if (abs(phase_delta) <= group_phase_tolerance) { - - float group_score = score_group(&st->group, phase_delta); - if (st->matcher_cache[i].candidate_score < group_score) { - assert(i < DSSS_MATCHER_CACHE_SIZE); - if (debug) DEBUG_PRINTN(" appending %zu %d score=%f pd=%d\n", i, decode_peak(st->group.max_ch, st->group.max), group_score, phase_delta); - /* Append to entry */ - st->matcher_cache[i].candidate_score = group_score; - st->matcher_cache[i].candidate_phase = group_phase; - st->matcher_cache[i].candidate_data = decode_peak(st->group.max_ch, st->group.max); - st->matcher_cache[i].candidate_skips = 0; - } - } - - /* Search for weakest entry */ - /* TODO figure out this fitness function */ - float score = st->matcher_cache[i].last_score * (1.5f + 0.1 * st->matcher_cache[i].data_pos); - if (debug) DEBUG_PRINTN(" score %zd %f %f %d", i, score, st->matcher_cache[i].last_score, st->matcher_cache[i].data_pos); - if (score < min_score) { - min_idx = i; - min_score = score; - } - } - - /* If we found empty entries, replace one by a new decoding starting at this group */ - if (empty_idx >= 0) { - if (debug) DEBUG_PRINTN(" empty %zd %d\n", empty_idx, decode_peak(st->group.max_ch, st->group.max)); - assert(0 <= empty_idx && empty_idx < DSSS_MATCHER_CACHE_SIZE); - st->matcher_cache[empty_idx].last_phase = group_phase; - st->matcher_cache[empty_idx].candidate_score = base_score; - st->matcher_cache[empty_idx].last_score = base_score; - st->matcher_cache[empty_idx].candidate_phase = group_phase; - st->matcher_cache[empty_idx].candidate_data = decode_peak(st->group.max_ch, st->group.max); - st->matcher_cache[empty_idx].data_pos = 0; - st->matcher_cache[empty_idx].candidate_skips = 0; - st->matcher_cache[empty_idx].last_skips = 0; - - /* If the weakest decoding in cache is weaker than a new decoding starting here, replace it */ - } else if (min_score < base_score && min_idx >= 0) { - if (debug) DEBUG_PRINTN(" min %zd %d\n", min_idx, decode_peak(st->group.max_ch, st->group.max)); - assert(0 <= min_idx && min_idx < DSSS_MATCHER_CACHE_SIZE); - st->matcher_cache[min_idx].last_phase = group_phase; - st->matcher_cache[min_idx].candidate_score = base_score; - st->matcher_cache[min_idx].last_score = base_score; - st->matcher_cache[min_idx].candidate_phase = group_phase; - st->matcher_cache[min_idx].candidate_data = decode_peak(st->group.max_ch, st->group.max); - st->matcher_cache[min_idx].data_pos = 0; - st->matcher_cache[min_idx].candidate_skips = 0; - st->matcher_cache[min_idx].last_skips = 0; - } -} - -#if 0 -float run_iir(const float x, const int order, const struct iir_biquad q[order], struct iir_biquad_state st[order]) { - float intermediate = x; - for (int i=0; i<(order+1)/2; i++) - intermediate = run_biquad(intermediate, &q[i], &st[i]); - return intermediate; -} - -float run_biquad(float x, const struct iir_biquad *const q, struct iir_biquad_state *const restrict st) { - /* direct form 2, see https://en.wikipedia.org/wiki/Digital_biquad_filter */ - float intermediate = x + st->reg[0] * -q->a[0] + st->reg[1] * -q->a[1]; - float out = intermediate * q->b[0] + st->reg[0] * q->b[1] + st->reg[1] * q->b[2]; - st->reg[1] = st->reg[0]; - st->reg[0] = intermediate; - return out; -} -#endif - -float cwt_convolve_step(const float v[DSSS_WAVELET_LUT_SIZE], size_t offx) { - float sum = 0.0f; - for (ssize_t j=0; j<DSSS_WAVELET_LUT_SIZE; j++) { - /* Our wavelet is symmetric so convolution and correlation are identical. Use correlation here for ease of - * implementation */ - sum += v[(offx + j) % DSSS_WAVELET_LUT_SIZE] * dsss_cwt_wavelet_table[j]; - //DEBUG_PRINT(" j=%d v=%f w=%f", j, v[(offx + j) % DSSS_WAVELET_LUT_SIZE], dsss_cwt_wavelet_table[j]); - } - return sum; -} - -/* Compute last element of correlation for input [a] and hard-coded gold sequences. - * - * This is intened to be used once for each new incoming sample in [a]. It expects [a] to be of length - * [dsss_correlation_length] and produces the one sample where both the reference sequence and the input fully overlap. - * This is equivalent to "valid" mode in numpy's terminology[0]. - * - * [0] https://docs.scipy.org/doc/numpy/reference/generated/numpy.correlate.html - */ -float gold_correlate_step(const size_t ncode, const float a[DSSS_CORRELATION_LENGTH], size_t offx, bool debug) { - - float acc_outer = 0.0f; - uint8_t table_byte = 0; - if (debug) DEBUG_PRINTN("Correlate n=%zd: ", ncode); - for (size_t i=0; i<DSSS_GOLD_CODE_LENGTH; i++) { - - if ((i&7) == 0) { - table_byte = dsss_gold_code_table[ncode][i>>3]; /* Fetch sequence table item */ - if (debug) DEBUG_PRINTN("|"); - } - int bv = table_byte & (0x80>>(i&7)); /* Extract bit */ - bv = !!bv*2 - 1; /* Map 0, 1 -> -1, 1 */ - if (debug) DEBUG_PRINTN("%s%d\033[0m", bv == 1 ? "\033[92m" : "\033[91m", (bv+1)/2); - - float acc_inner = 0.0f; - for (size_t j=0; j<DSSS_DECIMATION; j++) - acc_inner += a[(offx + i*DSSS_DECIMATION + j) % DSSS_CORRELATION_LENGTH]; /* Multiply item */ - //if (debug) DEBUG_PRINTN("%.2f ", acc_inner); - acc_outer += acc_inner * bv; - } - if (debug) DEBUG_PRINTN("\n"); - return acc_outer / DSSS_CORRELATION_LENGTH; -} diff --git a/controller/fw/src/dsss_demod.h b/controller/fw/src/dsss_demod.h deleted file mode 100644 index b865d83..0000000 --- a/controller/fw/src/dsss_demod.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef __DSSS_DEMOD_H__ -#define __DSSS_DEMOD_H__ - -#include <stdint.h> -#include <unistd.h> - -#define DSSS_GOLD_CODE_LENGTH ((1<<DSSS_GOLD_CODE_NBITS) - 1) -#define DSSS_GOLD_CODE_COUNT ((1<<DSSS_GOLD_CODE_NBITS) + 1) -#define DSSS_CORRELATION_LENGTH (DSSS_GOLD_CODE_LENGTH * DSSS_DECIMATION) - -/* FIXME: move to makefile */ -#define DSSS_MATCHER_CACHE_SIZE 8 - -#if DSSS_GOLD_CODE_NBITS < 8 -typedef uint8_t symbol_t; -#else -typedef uint16_t symbol_t; -#endif - -struct iir_biquad { - float a[2]; - float b[3]; -}; - -struct iir_biquad_state { - float reg[2]; -}; - -struct cwt_iir_filter_state { - struct iir_biquad_state st[3]; -}; - -struct group { - int len; /* length of group in samples */ - float max; /* signed value of largest peak in group on any channel */ - uint64_t max_ts; /* absolute position of above peak */ - int max_ch; /* channel (gold sequence index) of above peak */ -}; - -struct matcher_state { - int last_phase; /* 0 .. DSSS_CORRELATION_LENGTH */ - int candidate_phase; - - float last_score; - float candidate_score; - - int last_skips; - int candidate_skips; - - symbol_t data[TRANSMISSION_SYMBOLS]; - int data_pos; - symbol_t candidate_data; -}; - -struct dsss_demod_state { - float signal[DSSS_CORRELATION_LENGTH]; - size_t signal_wpos; - - float correlation[DSSS_GOLD_CODE_COUNT][DSSS_WAVELET_LUT_SIZE]; - size_t correlation_wpos; - - struct cwt_iir_filter_state cwt_filter; - - struct group group; - - struct matcher_state matcher_cache[DSSS_MATCHER_CACHE_SIZE]; -}; - - -extern void handle_dsss_received(symbol_t data[static TRANSMISSION_SYMBOLS]); - -void dsss_demod_init(struct dsss_demod_state *st); -void dsss_demod_step(struct dsss_demod_state *st, float new_value, uint64_t ts); - -#endif /* __DSSS_DEMOD_H__ */ diff --git a/controller/fw/src/freq_meas.c b/controller/fw/src/freq_meas.c deleted file mode 100644 index 035ffd4..0000000 --- a/controller/fw/src/freq_meas.c +++ /dev/null @@ -1,168 +0,0 @@ - -#ifndef SIMULATION -#include <stm32f407xx.h> -#endif - -#include <unistd.h> -#include <math.h> - -#include <arm_math.h> -#include <levmarq.h> - -#include "freq_meas.h" -#include "sr_global.h" -#include "simulation.h" - - -/* FTT window lookup table defined in generated/fmeas_fft_window.c */ -extern const float * const fmeas_fft_window_table; - -/* jury-rig some definitions for these functions since the ARM headers only export an over-generalized variable bin size - * variant. */ -extern arm_status arm_rfft_32_fast_init_f32(arm_rfft_fast_instance_f32 * S); -extern arm_status arm_rfft_64_fast_init_f32(arm_rfft_fast_instance_f32 * S); -extern arm_status arm_rfft_128_fast_init_f32(arm_rfft_fast_instance_f32 * S); -extern arm_status arm_rfft_256_fast_init_f32(arm_rfft_fast_instance_f32 * S); -extern arm_status arm_rfft_512_fast_init_f32(arm_rfft_fast_instance_f32 * S); -extern arm_status arm_rfft_1024_fast_init_f32(arm_rfft_fast_instance_f32 * S); -extern arm_status arm_rfft_2048_fast_init_f32(arm_rfft_fast_instance_f32 * S); -extern arm_status arm_rfft_4096_fast_init_f32(arm_rfft_fast_instance_f32 * S); - -#define CONCAT(A, B, C) A ## B ## C -#define arm_rfft_init_name(nbits) CONCAT(arm_rfft_, nbits, _fast_init_f32) - -void func_gauss_grad(float *out, float *params, int x, void *userdata); -float func_gauss(float *params, int x, void *userdata); - -int adc_buf_measure_freq(uint16_t adc_buf[FMEAS_FFT_LEN], float *out) { - int rc; - float in_buf[FMEAS_FFT_LEN]; - float out_buf[FMEAS_FFT_LEN]; - /* - DEBUG_PRINTN(" [emulated adc buf] "); - for (size_t i=0; i<FMEAS_FFT_LEN; i++) - DEBUG_PRINTN("%5d, ", adc_buf[i]); - DEBUG_PRINTN("\n"); - */ - //DEBUG_PRINT("Applying window function"); - for (size_t i=0; i<FMEAS_FFT_LEN; i++) - in_buf[i] = ((float)adc_buf[i] / (float)FMEAS_ADC_MAX - 0.5) * fmeas_fft_window_table[i]; - - //DEBUG_PRINT("Running FFT"); - arm_rfft_fast_instance_f32 fft_inst; - if ((rc = arm_rfft_init_name(FMEAS_FFT_LEN)(&fft_inst)) != ARM_MATH_SUCCESS) { - *out = NAN; - return rc; - } - - /* - DEBUG_PRINTN(" [input] "); - for (size_t i=0; i<FMEAS_FFT_LEN; i++) - DEBUG_PRINTN("%010f, ", in_buf[i]); - DEBUG_PRINTN("\n"); - */ -#ifndef SIMULATION - GPIOA->BSRR = 1<<12; -#endif - arm_rfft_fast_f32(&fft_inst, in_buf, out_buf, 0); -#ifndef SIMULATION - GPIOA->BSRR = 1<<12<<16; -#endif - -#define FMEAS_FFT_WINDOW_MIN_F_HZ 30.0f -#define FMEAS_FFT_WINDOW_MAX_F_HZ 70.0f - const float binsize_hz = (float)FMEAS_ADC_SAMPLING_RATE / FMEAS_FFT_LEN; - const size_t first_bin = (int)(FMEAS_FFT_WINDOW_MIN_F_HZ / binsize_hz); - const size_t last_bin = (int)(FMEAS_FFT_WINDOW_MAX_F_HZ / binsize_hz + 0.5f); - const size_t nbins = last_bin - first_bin + 1; - - /* - DEBUG_PRINT("binsize_hz=%f first_bin=%zd last_bin=%zd nbins=%zd", binsize_hz, first_bin, last_bin, nbins); - DEBUG_PRINTN(" [bins real] "); - for (size_t i=0; i<FMEAS_FFT_LEN/2; i+=2) - DEBUG_PRINTN("%010f, ", out_buf[i]); - DEBUG_PRINTN("\n [bins imag] "); - for (size_t i=1; i<FMEAS_FFT_LEN/2; i+=2) - DEBUG_PRINTN("%010f, ", out_buf[i]); - DEBUG_PRINT("\n"); - - DEBUG_PRINT("Repacking FFT results"); - */ - /* Copy real values of target data to front of output buffer */ - for (size_t i=0; i<nbins; i++) { - float real = out_buf[2 * (first_bin + i)]; - float imag = out_buf[2 * (first_bin + i) + 1]; - out_buf[i] = sqrtf(real*real + imag*imag); - } - - /* - DEBUG_PRINT("Running Levenberg-Marquardt"); - */ - LMstat lmstat; - levmarq_init(&lmstat); - - float a_max = 0.0f; - int i_max = 0; - for (size_t i=0; i<nbins; i++) { - if (out_buf[i] > a_max) { - a_max = out_buf[i]; - i_max = i; - } - } - - float par[3] = { - a_max, i_max, 1.0f - }; - /* - DEBUG_PRINT(" par_pre={%010f, %010f, %010f}", par[0], par[1], par[2]); - */ - -#ifndef SIMULATION - GPIOA->BSRR = 1<<12; -#endif - if (levmarq(3, par, nbins, out_buf, NULL, func_gauss, func_gauss_grad, NULL, &lmstat) < 0) { -#ifndef SIMULATION - GPIOA->BSRR = 1<<12<<16; -#endif - *out = NAN; - return -1; - } -#ifndef SIMULATION - GPIOA->BSRR = 1<<12<<16; -#endif - - /* - DEBUG_PRINT(" par_post={%010f, %010f, %010f}", par[0], par[1], par[2]); - - DEBUG_PRINT("done."); - */ - float res = (par[1] + first_bin) * binsize_hz; - if (par[1] < 2 || res < 5 || res > 150 || par[0] < 1) { - *out = NAN; - return -1; - } - - *out = res; - return 0; -} - -float func_gauss(float *params, int x, void *userdata) { - UNUSED(userdata); - float a = params[0], b = params[1], c = params[2]; - float n = x-b; - return a*expf(-n*n / (2.0f* c*c)); -} - -void func_gauss_grad(float *out, float *params, int x, void *userdata) { - UNUSED(userdata); - float a = params[0], b = params[1], c = params[2]; - float n = x-b; - float e = expf(-n*n / (2.0f * c*c)); - - /* d/da */ - out[0] = e; - /* d/db */ - out[1] = a*n/(c*c) * e; - /* d/dc */ - out[2] = a*n*n/(c*c*c) * e; -} diff --git a/controller/fw/src/freq_meas.h b/controller/fw/src/freq_meas.h deleted file mode 100644 index 1c083f8..0000000 --- a/controller/fw/src/freq_meas.h +++ /dev/null @@ -1,7 +0,0 @@ - -#ifndef __FREQ_MEAS_H__ -#define __FREQ_MEAS_H__ - -int adc_buf_measure_freq(uint16_t adc_buf[FMEAS_FFT_LEN], float *out); - -#endif /* __FREQ_MEAS_H__ */ diff --git a/controller/fw/src/gold_code.h b/controller/fw/src/gold_code.h deleted file mode 100644 index 739b477..0000000 --- a/controller/fw/src/gold_code.h +++ /dev/null @@ -1,4 +0,0 @@ - -/* header file for generated gold code tables */ - -extern const uint8_t * const gold_code_table; diff --git a/controller/fw/src/gpio_helpers.c b/controller/fw/src/gpio_helpers.c deleted file mode 100644 index 07b9a33..0000000 --- a/controller/fw/src/gpio_helpers.c +++ /dev/null @@ -1,46 +0,0 @@ - -#include "gpio_helpers.h" - -void gpio_pin_mode(GPIO_TypeDef *gpio, int pin, int mode) { - gpio->MODER &= ~(3 << (2*pin)); - gpio->MODER |= mode << (2*pin); -} - -void gpio_pin_setup(GPIO_TypeDef *gpio, int pin, int mode, int speed, int pullups, int afsel) { - int gpio_idx = ((uint32_t)gpio>>10) & 0xf; - RCC->AHB1ENR |= 1<<gpio_idx; - - gpio->MODER &= ~(3 << (2*pin)); - gpio->MODER |= mode << (2*pin); - gpio->OSPEEDR &= ~(3 << (2*pin)); - gpio->OSPEEDR |= speed << (2*pin); - gpio->PUPDR &= ~(3 << (2*pin)); - gpio->PUPDR |= pullups << (2*pin); - gpio->AFR[pin>>3] &= ~(0xf << (4*(pin&7))); - gpio->AFR[pin>>3] |= afsel << (4*(pin&7)); - gpio->BSRR = 1<<pin<<16; -} - -void gpio_pin_output(GPIO_TypeDef *gpio, int pin, int speed) { - gpio_pin_setup(gpio, pin, 1, speed, 0, 0); -} - -void gpio_pin_tristate(GPIO_TypeDef *gpio, int pin, int tristate) { - if (tristate) - gpio->MODER &= ~(3 << (2*pin)); - else - gpio->MODER |= 1 << (2*pin); -} - -void gpio_pin_input(GPIO_TypeDef *gpio, int pin, int pullups) { - gpio_pin_setup(gpio, pin, 0, 0, pullups, 0); -} - -void gpio_pin_af(GPIO_TypeDef *gpio, int pin, int speed, int pullups, int afsel) { - gpio_pin_setup(gpio, pin, 2, speed, pullups, afsel); -} - -void gpio_pin_analog(GPIO_TypeDef *gpio, int pin) { - gpio_pin_setup(gpio, pin, 3, 0, 0, 0); -} - diff --git a/controller/fw/src/gpio_helpers.h b/controller/fw/src/gpio_helpers.h deleted file mode 100644 index abe2e85..0000000 --- a/controller/fw/src/gpio_helpers.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __GPIO_HELPERS_H__ -#define __GPIO_HELPERS_H__ - -#include <stm32f407xx.h> - -void gpio_pin_mode(GPIO_TypeDef *gpio, int pin, int mode); -void gpio_pin_setup(GPIO_TypeDef *gpio, int pin, int mode, int speed, int pullups, int afsel); -void gpio_pin_output(GPIO_TypeDef *gpio, int pin, int speed); -void gpio_pin_input(GPIO_TypeDef *gpio, int pin, int pullups); -void gpio_pin_af(GPIO_TypeDef *gpio, int pin, int speed, int pullups, int afsel); -void gpio_pin_analog(GPIO_TypeDef *gpio, int pin); -void gpio_pin_tristate(GPIO_TypeDef *gpio, int pin, int tristate); - -#endif /* __GPIO_HELPERS_H__ */ diff --git a/controller/fw/src/main.c b/controller/fw/src/main.c deleted file mode 100644 index 748ccaa..0000000 --- a/controller/fw/src/main.c +++ /dev/null @@ -1,394 +0,0 @@ - -#include <stdbool.h> -#include <stdint.h> -#include <assert.h> -#include <string.h> -#include <math.h> - -#include <stm32f407xx.h> - -#include "sr_global.h" -#include "adc.h" -#include "spi_flash.h" -#include "freq_meas.h" -#include "dsss_demod.h" -#include "con_usart.h" -#include "mspdebug_wrapper.h" -#include "crypto.h" - -static struct spi_flash_if spif; - -unsigned int sysclk_speed = 0; -unsigned int apb1_speed = 0; -unsigned int apb2_speed = 0; -unsigned int auxclk_speed = 0; -unsigned int apb1_timer_speed = 0; -unsigned int apb2_timer_speed = 0; - -struct leds leds; - -ssize_t jt_spi_flash_read_block(void *usr, int addr, size_t len, uint8_t *out); -static void update_image_flash_counter(void); - -void __libc_init_array(void) { /* we don't need this. */ } -void __assert_func (unused_a const char *file, unused_a int line, unused_a const char *function, unused_a const char *expr) { - asm volatile ("bkpt"); - while(1) {} -} - -static void clock_setup(void) -{ - /* 8MHz HSE clock as PLL source. */ -#define HSE_SPEED 8000000 - /* Divide by 8 -> 1 MHz */ -#define PLL_M 8 - /* Multiply by 336 -> 336 MHz VCO frequency */ -#define PLL_N 336 - /* Divide by 4 -> 84 MHz (max freq for our chip) */ -#define PLL_P 2 - /* Aux clock for USB OTG, SDIO, RNG: divide VCO frequency (336 MHz) by 7 -> 48 MHz (required by USB OTG) */ -#define PLL_Q 7 - - if (((RCC->CFGR & RCC_CFGR_SWS_Msk) >> RCC_CFGR_SW_Pos) != 0) - asm volatile ("bkpt"); - if (RCC->CR & RCC_CR_HSEON) - asm volatile ("bkpt"); - - RCC->CR |= RCC_CR_HSEON; - while(!(RCC->CR & RCC_CR_HSERDY)) - ; - - RCC->APB1ENR |= RCC_APB1ENR_PWREN; - - /* set voltage scale to 1 for max frequency - * (0b0) scale 2 for fCLK <= 144 Mhz - * (0b1) scale 1 for 144 Mhz < fCLK <= 168 Mhz - */ - PWR->CR |= PWR_CR_VOS; - - /* set AHB prescaler to /1 (CFGR:bits 7:4) */ - RCC->CFGR |= (0 << RCC_CFGR_HPRE_Pos); - /* set ABP1 prescaler to 4 -> 42MHz */ - RCC->CFGR |= (5 << RCC_CFGR_PPRE1_Pos); - /* set ABP2 prescaler to 2 -> 84MHz */ - RCC->CFGR |= (4 << RCC_CFGR_PPRE2_Pos); - - if (RCC->CR & RCC_CR_PLLON) - asm volatile ("bkpt"); - /* Configure PLL */ - static_assert(PLL_P % 2 == 0); - static_assert(PLL_P >= 2 && PLL_P <= 8); - static_assert(PLL_N >= 50 && PLL_N <= 432); - static_assert(PLL_M >= 2 && PLL_M <= 63); - static_assert(PLL_Q >= 2 && PLL_Q <= 15); - uint32_t old = RCC->PLLCFGR & ~(RCC_PLLCFGR_PLLM_Msk - | RCC_PLLCFGR_PLLN_Msk - | RCC_PLLCFGR_PLLP_Msk - | RCC_PLLCFGR_PLLQ_Msk - | RCC_PLLCFGR_PLLSRC); - RCC->PLLCFGR = old | (PLL_M<<RCC_PLLCFGR_PLLM_Pos) - | (PLL_N << RCC_PLLCFGR_PLLN_Pos) - | ((PLL_P/2 - 1) << RCC_PLLCFGR_PLLP_Pos) - | (PLL_Q << RCC_PLLCFGR_PLLQ_Pos) - | RCC_PLLCFGR_PLLSRC; /* select HSE as PLL source */ - RCC->CR |= RCC_CR_PLLON; - - sysclk_speed = HSE_SPEED / PLL_M * PLL_N / PLL_P; - auxclk_speed = HSE_SPEED / PLL_M * PLL_N / PLL_Q; - apb1_speed = sysclk_speed / 4; - apb1_timer_speed = apb1_speed * 2; - apb2_speed = sysclk_speed / 2; - apb2_timer_speed = apb2_speed * 2; - - /* Wait for main PLL */ - while(!(RCC->CR & RCC_CR_PLLRDY)) - ; - - /* Configure Flash: enable prefetch, insn cache, data cache; set latency = 5 wait states - * See reference manual (RM0090), Section 3.5.1, Table 10 (p. 80) - */ - FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | (5<<FLASH_ACR_LATENCY_Pos); - - /* Select PLL as system clock source */ - RCC->CFGR &= ~RCC_CFGR_SW_Msk; - RCC->CFGR |= 2 << RCC_CFGR_SW_Pos; - - /* Wait for clock to switch over */ - while ((RCC->CFGR & RCC_CFGR_SWS_Msk)>>RCC_CFGR_SWS_Pos != 2) - ; -} - -static void led_setup(void) -{ - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN; - /* onboard leds */ - GPIOA->MODER |= (1<<GPIO_MODER_MODER6_Pos) | (1<<GPIO_MODER_MODER7_Pos); - GPIOB->MODER |= (1<<GPIO_MODER_MODER11_Pos) | (1<<GPIO_MODER_MODER12_Pos) | (1<<GPIO_MODER_MODER13_Pos)| (1<<GPIO_MODER_MODER14_Pos); - GPIOB->BSRR = 0xf << 11; -} - -static void spi_flash_if_set_cs(bool val) { - if (val) - GPIOB->BSRR = 1<<0; - else - GPIOB->BSRR = 1<<16; -} - -static void spi_flash_setup(void) -{ - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; - - GPIOB->MODER &= ~GPIO_MODER_MODER3_Msk & ~GPIO_MODER_MODER4_Msk & ~GPIO_MODER_MODER5_Msk & ~GPIO_MODER_MODER0_Msk; - GPIOB->MODER |= (2<<GPIO_MODER_MODER3_Pos) /* SCK */ - | (2<<GPIO_MODER_MODER4_Pos) /* MISO */ - | (2<<GPIO_MODER_MODER5_Pos) /* MOSI */ - | (1<<GPIO_MODER_MODER0_Pos); /* CS */ - - GPIOB->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED3_Msk & ~GPIO_OSPEEDR_OSPEED4_Msk - & ~GPIO_OSPEEDR_OSPEED5_Msk & ~GPIO_OSPEEDR_OSPEED0_Msk; - GPIOB->OSPEEDR |= (2<<GPIO_OSPEEDR_OSPEED3_Pos) /* SCK */ - | (2<<GPIO_OSPEEDR_OSPEED4_Pos) /* MISO */ - | (2<<GPIO_OSPEEDR_OSPEED5_Pos) /* MOSI */ - | (2<<GPIO_OSPEEDR_OSPEED0_Pos); /* CS */ - - GPIOB->AFR[0] &= ~GPIO_AFRL_AFSEL3_Msk & ~GPIO_AFRL_AFSEL4_Msk & ~GPIO_AFRL_AFSEL5_Msk; - GPIOB->AFR[0] |= (5<<GPIO_AFRL_AFSEL3_Pos) | (5<<GPIO_AFRL_AFSEL4_Pos) | (5<<GPIO_AFRL_AFSEL5_Pos); - - RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; - RCC->APB2RSTR |= RCC_APB2RSTR_SPI1RST; - RCC->APB2RSTR &= ~RCC_APB2RSTR_SPI1RST; - - spif_init(&spif, 256, SPI1, &spi_flash_if_set_cs); -} - -/* SPI flash test routine to be called from gdb */ -#ifdef SPI_FLASH_TEST -void spi_flash_test(void) { - spif_clear_mem(&spif); - - uint32_t buf[1024]; - for (size_t addr=0; addr<0x10000; addr += sizeof(buf)) { - for (size_t i=0; i<sizeof(buf); i+= sizeof(buf[0])) - buf[i/sizeof(buf[0])] = addr + i; - - spif_write(&spif, addr, sizeof(buf), (char *)buf); - } - - for (size_t i=0; i<sizeof(buf)/sizeof(buf[0]); i++) - buf[i] = 0; - spif_read(&spif, 0x1030, sizeof(buf), (char *)buf); - asm volatile ("bkpt"); -} -#endif - -static struct jtag_img_descriptor { - size_t devmem_img_start; - size_t spiflash_img_start; - size_t img_len; -} jtag_img = { - .devmem_img_start = 0x00c000, - .spiflash_img_start = 0x000000, - .img_len = 0x004000, -}; - -char fw_dump[0x4000] = { -#include "EasyMeter_Q3DA1002_V3.03_fw_dump_0xc000.h" -}; -const int fw_dump_offx = 0xc000; -const int row2_offx = 0xf438 - fw_dump_offx; - -ssize_t jt_spi_flash_read_block(void *usr, int addr, size_t len, uint8_t *out) { - /* - struct jtag_img_descriptor *desc = (struct jtag_img_descriptor *)usr; - return spif_read(&spif, desc->spiflash_img_start + addr, len, (char *)out); - */ - - for (size_t i=0; i<len; i++) - out[i] = fw_dump[addr - fw_dump_offx + i]; - - return len; -} - -void update_image_flash_counter() { - static int flash_counter = 0; - flash_counter ++; - fw_dump[row2_offx + 0] = flash_counter/10000 + '0'; - flash_counter %= 10000; - fw_dump[row2_offx + 1] = flash_counter/1000 + '0'; - flash_counter %= 1000; - fw_dump[row2_offx + 2] = flash_counter/100 + '0'; - flash_counter %= 100; - fw_dump[row2_offx + 3] = flash_counter/10 + '0'; - flash_counter %= 10; - fw_dump[row2_offx + 4] = flash_counter + '0'; -} - -/* Callback from crypto.c:oob_message_received */ -void oob_trigger_activated(enum trigger_domain domain, int serial) { - con_printf("oob_trigger_activated(%d, %d)\r\n", domain, serial); - con_printf("Attempting to flash meter...\r\n"); - update_image_flash_counter(); - - int flash_tries = 0; - while (flash_tries++ < 25) { - mspd_jtag_init(); - if (!mspd_jtag_flash_and_reset(jtag_img.devmem_img_start, jtag_img.img_len, jt_spi_flash_read_block, &jtag_img)) - break; - for (int j=0; j<168*1000*5; j++) - asm volatile ("nop"); - } - if (flash_tries == 25) - con_printf("Giving up.\r\n"); -} - -static unsigned int measurement_errors = 0; -static struct dsss_demod_state demod_state; -static uint32_t freq_sample_ts = 0; -static float debug_last_freq = 0; - -int main(void) -{ -#if DEBUG - /* PLL clock on MCO2 (pin C9) */ - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; - GPIOC->MODER &= ~GPIO_MODER_MODER9_Msk; - GPIOC->MODER |= (2<<GPIO_MODER_MODER9_Pos); - GPIOC->AFR[1] &= ~GPIO_AFRH_AFSEL9_Msk; - GPIOC->OSPEEDR |= (3<<GPIO_OSPEEDR_OSPEED9_Pos); - RCC->CFGR |= (6<<RCC_CFGR_MCO2PRE_Pos) | (3<<RCC_CFGR_MCO2_Pos); -#endif - - if (((SCB->CPACR>>20) & 0xf) != 0xf) { - asm volatile ("bkpt"); - } - - clock_setup(); - con_usart_init(); - con_printf("\033[0m\033[2J\033[HBooting...\r\n"); - - led_setup(); - spi_flash_setup(); - adc_init(); - -#if DEBUG - /* TIM1 CC1 (ADC trigger) on pin A8 */ - GPIOA->MODER &= ~GPIO_MODER_MODER8_Msk; - GPIOA->MODER |= (2<<GPIO_MODER_MODER8_Pos); - GPIOA->AFR[1] &= ~GPIO_AFRH_AFSEL8_Msk; - GPIOA->AFR[1] |= 1<<GPIO_AFRH_AFSEL8_Pos; - - GPIOA->MODER |= (1<<GPIO_MODER_MODER11_Pos) | (1<<GPIO_MODER_MODER12_Pos) | (1<<GPIO_MODER_MODER15_Pos); -#endif - - dsss_demod_init(&demod_state); - - con_printf("Booted.\r\n"); - - - /* FIXME DEBUG */ -#if 0 - uint8_t test_data[TRANSMISSION_SYMBOLS] = { - 0 - }; - con_printf("Test 0\r\n"); - handle_dsss_received(test_data); - - uint8_t test_data2[TRANSMISSION_SYMBOLS] = { - 0x24, 0x0f, 0x3b, 0x10, 0x27, 0x0e, 0x22, 0x30, 0x01, 0x2c, 0x1c, 0x0b, 0x35, 0x0a, 0x12, 0x27, 0x11, 0x20, - 0x0c, 0x10, 0xc0, 0x08, 0xa4, 0x72, 0xa9, 0x9b, 0x7b, 0x27, 0xee, 0xcd - }; - con_printf("Test 1\r\n"); - handle_dsss_received(test_data2); -#endif - /* END DEBUG */ - - while (23) { - if (adc_fft_buf_ready_idx != -1) { - for (int j=0; j<168*1000*2; j++) - asm volatile ("nop"); - GPIOA->BSRR = 1<<11; - memcpy(adc_fft_buf[!adc_fft_buf_ready_idx], adc_fft_buf[adc_fft_buf_ready_idx] + FMEAS_FFT_LEN/2, sizeof(adc_fft_buf[0][0]) * FMEAS_FFT_LEN/2); - GPIOA->BSRR = 1<<11<<16; - GPIOB->ODR ^= 1<<14; - - bool clip_low=false, clip_high=false; - const int clip_thresh = 100; - for (size_t j=FMEAS_FFT_LEN/2; j<FMEAS_FFT_LEN; j++) { - int val = adc_fft_buf[adc_fft_buf_ready_idx][j]; - if (val < clip_thresh) - clip_low = true; - if (val > FMEAS_ADC_MAX-clip_thresh) - clip_high = true; - } - GPIOB->ODR = (GPIOB->ODR & ~(3<<11)) | (!clip_low<<11) | (!clip_high<<12); - - for (int j=0; j<168*1000*2; j++) - asm volatile ("nop"); - - GPIOA->BSRR = 1<<11; - float out; - if (adc_buf_measure_freq(adc_fft_buf[adc_fft_buf_ready_idx], &out)) { - con_printf("%012d: measurement error\r\n", freq_sample_ts); - measurement_errors++; - GPIOB->BSRR = 1<<13; - debug_last_freq = NAN; - - } else { - debug_last_freq = out; - con_printf("%012d: %2d.%03d Hz\r\n", freq_sample_ts, (int)out, (int)(out * 1000) % 1000); - /* frequency ok led */ - if (48 < out && out < 52) - GPIOB->BSRR = 1<<13<<16; - else - GPIOB->BSRR = 1<<13; - - GPIOA->BSRR = 1<<12; - dsss_demod_step(&demod_state, out, freq_sample_ts); - GPIOA->BSRR = 1<<12<<16; - } - GPIOA->BSRR = 1<<11<<16; - - freq_sample_ts++; /* TODO: also increase in case of freq measurement error? */ - adc_fft_buf_ready_idx = -1; - } - } - - return 0; -} - -void NMI_Handler(void) { - asm volatile ("bkpt #1"); -} - -void HardFault_Handler(void) { - asm volatile ("bkpt #2"); -} - -void MemManage_Handler(void) { - asm volatile ("bkpt #3"); -} - -void BusFault_Handler(void) { - asm volatile ("bkpt #4"); -} - -void UsageFault_Handler(void) { - asm volatile ("bkpt #5"); -} - -void SVC_Handler(void) { - asm volatile ("bkpt #6"); -} - -void DebugMon_Handler(void) { - asm volatile ("bkpt #7"); -} - -void PendSV_Handler(void) { - asm volatile ("bkpt #8"); -} - -void SysTick_Handler(void) { - asm volatile ("bkpt #9"); -} - diff --git a/controller/fw/src/mspdebug_wrapper.c b/controller/fw/src/mspdebug_wrapper.c deleted file mode 100644 index c30864c..0000000 --- a/controller/fw/src/mspdebug_wrapper.c +++ /dev/null @@ -1,261 +0,0 @@ - -#include <unistd.h> -#include <errno.h> -#include <string.h> - -#include "output.h" -#include "jtaglib.h" - -#include "sr_global.h" -#include "gpio_helpers.h" -#include "mspdebug_wrapper.h" -#include "con_usart.h" - -#include <stm32f407xx.h> - -#define BLOCK_SIZE 512 /* bytes */ - - -static void sr_delay_inst(void); - -static struct jtdev sr_jtdev; -static struct jtdev sr_jtdev_default; - -enum sr_gpio_types { - SR_GPIO_TCK, - SR_GPIO_TMS, - SR_GPIO_TDI, - SR_GPIO_RST, - SR_GPIO_TST, - SR_GPIO_TDO, - SR_NUM_GPIOS -}; - -struct { - GPIO_TypeDef *gpio; - int pin; - int mode; -} gpios[SR_NUM_GPIOS] = { - [SR_GPIO_TCK] = {GPIOE, 10, 1}, - [SR_GPIO_TMS] = {GPIOE, 11, 1}, - [SR_GPIO_TDI] = {GPIOE, 12, 1}, - [SR_GPIO_RST] = {GPIOE, 9, 1}, - [SR_GPIO_TST] = {GPIOE, 14, 1}, - [SR_GPIO_TDO] = {GPIOE, 13, 0}, -}; - -void sr_delay_inst() { - for (int i=0; i<10; i++) - asm volatile("nop"); -} - -void mspd_jtag_init() { - for (int i=0; i<SR_NUM_GPIOS; i++) - gpio_pin_setup(gpios[i].gpio, gpios[i].pin, gpios[i].mode, 3, 0, 0); -} - -static void sr_gpio_write(int num, int out) { - if (out) - gpios[num].gpio->BSRR = 1<<gpios[num].pin; - else - gpios[num].gpio->BSRR = 1<<gpios[num].pin<<16; -} - -static void sr_jtdev_rst(struct jtdev *p, int out) { - UNUSED(p); - sr_gpio_write(SR_GPIO_RST, out); -} - -int mspd_jtag_flash_and_reset(size_t img_start, size_t img_len, ssize_t (*read_block)(void *usr, int addr, size_t len, uint8_t *out), void *usr) -{ - union { - uint8_t bytes[BLOCK_SIZE]; - uint16_t words[BLOCK_SIZE/2]; - } block; - - memcpy(&sr_jtdev, &sr_jtdev_default, sizeof(sr_jtdev)); - /* Initialize JTAG connection */ - unsigned int jtag_id = jtag_init(&sr_jtdev); - - if (sr_jtdev.failed) { - con_printf("Couldn't initialize device\r\n"); - return -EPIPE; - } - - con_printf("JTAG device ID: 0x%02x\r\n", jtag_id); - if (jtag_id != 0x89 && jtag_id != 0x91) - return -EINVAL; - -#if 0 - con_printf("Memory dump:\r\n"); - for (size_t i=0x1000; i<=0x10ff;) { - con_printf("%04x: ", i); - for (size_t j=0; j<16; i+=1, j+=1) { - con_printf("%02x ", jtag_read_mem(&sr_jtdev, 8, i)); - } - con_printf("\r\n"); - } - return 0; -#endif - - /* Clear flash */ - jtag_erase_flash(&sr_jtdev, JTAG_ERASE_MAIN, 0); - if (sr_jtdev.failed) - return -EPIPE; - - /* Write flash */ - for (size_t p = img_start; p < img_start + img_len; p += BLOCK_SIZE) { - con_printf("Writing block %04zx\r\n", p); - ssize_t nin = read_block(usr, p, BLOCK_SIZE, block.bytes); - - if (nin < 0) - return nin; - - if (nin & 1) { /* pad unaligned */ - block.bytes[nin] = 0; - nin ++; - } - - /* Convert to little-endian */ - for (ssize_t i=0; i<nin/2; i++) - block.words[i] = htole(block.words[i]); - - jtag_write_flash(&sr_jtdev, p, nin/2, block.words); - if (sr_jtdev.failed) - return -EPIPE; - } - - /* TODO: Verify flash here. */ - - /* Execute power on reset */ - jtag_execute_puc(&sr_jtdev); - if (sr_jtdev.failed) - return -EPIPE; - - jtag_release_device(&sr_jtdev, 0xfffe); - - return 0; -} - -/* mspdebug HAL shim */ - -int printc_err(const char *fmt, ...) { - va_list va; - va_start(va, fmt); - int rc = usart_printf_blocking_va(&con_usart, fmt, va); - if (rc) - return rc; - - size_t i; - for (i=0; fmt[i]; i++) - ; - if (i > 0 && fmt[i-1] == '\n') - usart_putc_nonblocking(&con_usart, '\r'); - return rc; -} - - -static void sr_jtdev_power_on(struct jtdev *p) { - UNUSED(p); - /* ignore */ -} - -static void sr_jtdev_connect(struct jtdev *p) { - UNUSED(p); - /* ignore */ -} - -static void sr_jtdev_tck(struct jtdev *p, int out) { - UNUSED(p); - sr_gpio_write(SR_GPIO_TCK, out); -} - -static void sr_jtdev_tms(struct jtdev *p, int out) { - UNUSED(p); - sr_gpio_write(SR_GPIO_TMS, out); -} - -static void sr_jtdev_tdi(struct jtdev *p, int out) { - UNUSED(p); - sr_gpio_write(SR_GPIO_TDI, out); -} - -static void sr_jtdev_tst(struct jtdev *p, int out) { - UNUSED(p); - sr_gpio_write(SR_GPIO_TST, out); -} - -static int sr_jtdev_tdo_get(struct jtdev *p) { - UNUSED(p); - return !!(gpios[SR_GPIO_TDO].gpio->IDR & (1<<gpios[SR_GPIO_TDO].pin)); -} - -static void sr_jtdev_tclk(struct jtdev *p, int out) { - UNUSED(p); - sr_gpio_write(SR_GPIO_TDI, out); -} - -static int sr_jtdev_tclk_get(struct jtdev *p) { - UNUSED(p); - return !!(gpios[SR_GPIO_TDI].gpio->ODR & (1<<gpios[SR_GPIO_TDI].pin)); -} - -static void sr_jtdev_tclk_strobe(struct jtdev *p, unsigned int count) { - UNUSED(p); - while (count--) { - gpios[SR_GPIO_TDI].gpio->BSRR = 1<<gpios[SR_GPIO_TDI].pin; - sr_delay_inst(); - gpios[SR_GPIO_TDI].gpio->BSRR = 1<<gpios[SR_GPIO_TDI].pin<<16; - } -} - -static void sr_jtdev_led_green(struct jtdev *p, int out) { - UNUSED(p); - UNUSED(out); - /* ignore */ -} - -static void sr_jtdev_led_red(struct jtdev *p, int out) { - UNUSED(p); - UNUSED(out); - /* ignore */ -} - - -static struct jtdev_func sr_jtdev_vtable = { - .jtdev_open = NULL, - .jtdev_close = NULL, - - .jtdev_power_off = NULL, - .jtdev_release = NULL, - - .jtdev_power_on = sr_jtdev_power_on, - .jtdev_connect = sr_jtdev_connect, - - .jtdev_tck = sr_jtdev_tck, - .jtdev_tms = sr_jtdev_tms, - .jtdev_tdi = sr_jtdev_tdi, - .jtdev_rst = sr_jtdev_rst, - .jtdev_tst = sr_jtdev_tst, - .jtdev_tdo_get = sr_jtdev_tdo_get, - - .jtdev_tclk = sr_jtdev_tclk, - .jtdev_tclk_get = sr_jtdev_tclk_get, - .jtdev_tclk_strobe = sr_jtdev_tclk_strobe, - - .jtdev_led_green = sr_jtdev_led_green, - .jtdev_led_red = sr_jtdev_led_red, - -}; - -static struct jtdev sr_jtdev = { - 0, - .f = &sr_jtdev_vtable -}; - -static struct jtdev sr_jtdev_default = { - 0, - .f = &sr_jtdev_vtable -}; - - diff --git a/controller/fw/src/mspdebug_wrapper.h b/controller/fw/src/mspdebug_wrapper.h deleted file mode 100644 index c3f5ac7..0000000 --- a/controller/fw/src/mspdebug_wrapper.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __MSPDEBUG_WRAPPER_H__ -#define __MSPDEBUG_WRAPPER_H__ - -void mspd_jtag_init(void); -int mspd_jtag_flash_and_reset(size_t img_start, size_t img_len, ssize_t (*read_block)(void *usr, int addr, size_t len, uint8_t *out), void *usr); - -#endif /* __MSPDEBUG_WRAPPER_H__ */ diff --git a/controller/fw/src/protocol.c b/controller/fw/src/protocol.c deleted file mode 100644 index 6b7d8b7..0000000 --- a/controller/fw/src/protocol.c +++ /dev/null @@ -1,44 +0,0 @@ - -#include <assert.h> - -#include "sr_global.h" -#include "dsss_demod.h" -#include "con_usart.h" -#include "rslib.h" -#include "crypto.h" - -void handle_dsss_received(uint8_t data[static TRANSMISSION_SYMBOLS]) { - /* Console status output */ - con_printf("DSSS data received: "); - for (int i=0; i<TRANSMISSION_SYMBOLS; i++) { - int x = (data[i]>>1) * (data[i]&1 ? 1 : -1); - con_printf("%3d ", x); - } - con_printf("\r\n"); - - /* Run reed-solomon error correction */ - const int sym_bits = DSSS_GOLD_CODE_NBITS + 1; /* +1 for amplitude sign bit */ - /* TODO identify erasures in DSSS demod layer */ - (void) rslib_decode(sym_bits, TRANSMISSION_SYMBOLS, (char *)data); - /* TODO error detection & handling */ - - /* Re-bit-pack data buffer to be bit-continuous: - * [ . . a b c d e f ] [ . . g h i j k l ] [ . . m n o p q r ] ... - * ==> [ a b c d e f g h ] [ i j k l m n o p ] [ q r ... ] ... - */ - static_assert((TRANSMISSION_SYMBOLS - NPAR) * (DSSS_GOLD_CODE_NBITS + 1) == OOB_TRIGGER_LEN * 8); - for (uint8_t i=0, j=0; i < TRANSMISSION_SYMBOLS - NPAR; i++, j += sym_bits) { - uint32_t sym = data[i]; /* [ ... | . . X X X X X X ] for 5-bit dsss */ - data[i] = 0; /* clear for output */ - - sym <<= 8-sym_bits; /* left-align: [ ... | X X X X X X . . ] */ - sym <<= 8; /* shift to second byte: [ ... | X X X X X X . . | . . . . . . . . ]*/ - sym >>= (j%8); /* shift to bit write offset: [ ... | . . . . X X X X | X X . . . . . . ] for offset 4 */ - data[j/8] |= sym >> 8; /* write upper byte */ - data[j/8 + 1] |= sym & 0xff; /* write lower byte */ - } - - /* hand off to crypto.c */ - oob_message_received(data); -} - diff --git a/controller/fw/src/rscode-config.h b/controller/fw/src/rscode-config.h deleted file mode 100644 index ea5183b..0000000 --- a/controller/fw/src/rscode-config.h +++ /dev/null @@ -1,8 +0,0 @@ -/* Config header for reed-solomon library */ - -#ifndef __RSCODE_CONFIG_H__ -#define __RSCODE_CONFIG_H__ - -#define NPAR 10 - -#endif /* __RSCODE_CONFIG_H__ */ diff --git a/controller/fw/src/rslib.c b/controller/fw/src/rslib.c deleted file mode 100644 index aa0db2c..0000000 --- a/controller/fw/src/rslib.c +++ /dev/null @@ -1,28 +0,0 @@ -#include <stdint.h> -#include <string.h> - -#include "rscode-config.h" -#include <ecc.h> - -#include "rslib.h" - -static struct rscode_driver driver; - -void rslib_encode(int nbits, size_t msglen, char msg[static msglen], char out[msglen + NPAR]) { - rscode_init(&driver, nbits); - rscode_encode(&driver, (unsigned char *)msg, msglen, (unsigned char *)out); -} - -int rslib_decode(int nbits, size_t msglen, char msg_inout[static msglen]) { - rscode_init(&driver, nbits); - return rscode_decode(&driver, (unsigned char *)msg_inout, msglen); -} - -int rslib_gexp(int z, int nbits) { - rscode_init(&driver, nbits); - return gexp(&driver, z); -} - -size_t rslib_npar() { - return NPAR; -} diff --git a/controller/fw/src/rslib.h b/controller/fw/src/rslib.h deleted file mode 100644 index bba8bb0..0000000 --- a/controller/fw/src/rslib.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __RSLIB_H__ -#define __RSLIB_H__ - -/* parity length configuration */ -#include "rscode-config.h" - -void rslib_encode(int nbits, size_t msglen, char msg[static msglen], char out[msglen + NPAR]); -int rslib_decode(int nbits, size_t msglen, char msg_inout[static msglen]); -int rslib_gexp(int z, int nbits); -size_t rslib_npar(void); - -#endif /* __RSLIB_H__ */ diff --git a/controller/fw/src/serial.c b/controller/fw/src/serial.c deleted file mode 100644 index 12df28a..0000000 --- a/controller/fw/src/serial.c +++ /dev/null @@ -1,186 +0,0 @@ -#include <string.h> -#include <stdarg.h> -#include <stdlib.h> - -#include "dma_util.h" -#include "sr_global.h" -#include "serial.h" - -#include <tinyprintf.h> - -static void usart_schedule_dma(volatile struct usart_desc *us); -static void usart_dma_reset(volatile struct usart_desc *us); -static void usart_putc_nonblocking_tpf(void *us, char c); -static void usart_wait_chunk_free(volatile struct usart_desc *us); -static void usart_putc_blocking_tpf(void *us, char c); - -void usart_dma_reset(volatile struct usart_desc *us) { - us->tx_buf.xfr_start = -1; - us->tx_buf.xfr_end = 0; - us->tx_buf.wr_pos = 0; - us->tx_buf.wr_idx = 0; - us->tx_buf.xfr_next = 0; - us->tx_buf.wraparound = false; - - for (size_t i=0; i<ARRAY_LENGTH(us->tx_buf.chunk_end); i++) - us->tx_buf.chunk_end[i] = -1; -} - -void usart_dma_init(volatile struct usart_desc *us, unsigned int baudrate) { - usart_dma_reset(us); - - /* Configure DMA 1 Channel 2 to handle uart transmission */ - us->tx_dmas->PAR = (uint32_t)&(us->le_usart->DR); - us->tx_dmas->CR = - (us->tx_dma_ch<<DMA_SxCR_CHSEL_Pos) - | (0<<DMA_SxCR_PL_Pos) - | (1<<DMA_SxCR_DIR_Pos) - | (0<<DMA_SxCR_MSIZE_Pos) /* 8 bit */ - | (0<<DMA_SxCR_PSIZE_Pos) /* 8 bit */ - | DMA_SxCR_MINC - | DMA_SxCR_TCIE; /* Enable transfer complete interrupt. */ - - /* triggered on transfer completion. We use this to process the ADC data */ - NVIC_EnableIRQ(us->tx_dma_irqn); - NVIC_SetPriority(us->tx_dma_irqn, 30); - - us->le_usart->CR1 = USART_CR1_TE; - /* Set divider for 115.2kBd @48MHz system clock. */ - us->le_usart->BRR = apb2_speed * 16 / baudrate / 16; /* 250kBd */ - us->le_usart->CR3 |= USART_CR3_DMAT; /* TX DMA enable */ - - /* And... go! */ - us->le_usart->CR1 |= USART_CR1_UE; -} - -void usart_schedule_dma(volatile struct usart_desc *us) { - volatile struct dma_tx_buf *buf = &us->tx_buf; - - ssize_t xfr_start, xfr_end, xfr_len; - if (buf->wraparound) { - buf->wraparound = false; - xfr_start = 0; - xfr_len = buf->xfr_end; - xfr_end = buf->xfr_end; - - } else { - if (buf->chunk_end[buf->xfr_next] == -1) - return; /* Nothing to trasnmit */ - - xfr_start = buf->xfr_end; - xfr_end = buf->chunk_end[buf->xfr_next]; - buf->chunk_end[buf->xfr_next] = -1; - buf->xfr_next = (buf->xfr_next + 1) % ARRAY_LENGTH(buf->chunk_end); - - if (xfr_end > xfr_start) { /* no wraparound */ - xfr_len = xfr_end - xfr_start; - - } else { /* wraparound */ - if (xfr_end != 0) - buf->wraparound = true; - xfr_len = sizeof(us->data) - xfr_start; - } - } - - buf->xfr_start = xfr_start; - buf->xfr_end = xfr_end; - - us->comm_led = 100; - - /* initiate transmission of new buffer */ - us->tx_dmas->M0AR = (uint32_t)(us->data + xfr_start); - us->tx_dmas->NDTR = xfr_len; - us->tx_dmas->CR |= DMA_SxCR_EN; -} - -void usart_dma_stream_irq(volatile struct usart_desc *us) { - uint8_t iflags = dma_get_isr_and_clear(us->tx_dma, us->tx_dma_sn); - - if (iflags & DMA_LISR_TCIF0) { /* Transfer complete */ - us->tx_dmas->CR &= ~DMA_SxCR_EN; - //if (us->tx_buf.wraparound) - usart_schedule_dma(us); - } - - if (iflags & DMA_LISR_FEIF0) - us->tx_errors++; -} - -int usart_putc_nonblocking(volatile struct usart_desc *us, char c) { - volatile struct dma_tx_buf *buf = &us->tx_buf; - - if (buf->wr_pos == buf->xfr_start) { - us->tx_byte_overruns++; - return -EBUSY; - } - - buf->data[buf->wr_pos] = c; - buf->wr_pos = (buf->wr_pos + 1) % sizeof(us->data); - return 0; -} - -int usart_putc_blocking(volatile struct usart_desc *us, char c) { - volatile struct dma_tx_buf *buf = &us->tx_buf; - - while (buf->wr_pos == buf->xfr_start) - ; - - buf->data[buf->wr_pos] = c; - buf->wr_pos = (buf->wr_pos + 1) % sizeof(us->data); - return 0; -} - -void usart_putc_nonblocking_tpf(void *us, char c) { - usart_putc_nonblocking((struct usart_desc *)us, c); -} - -void usart_putc_blocking_tpf(void *us, char c) { - usart_putc_blocking((struct usart_desc *)us, c); -} - -int usart_send_chunk_nonblocking(volatile struct usart_desc *us, const char *chunk, size_t chunk_len) { - for (size_t i=0; i<chunk_len; i++) - usart_putc_nonblocking(us, chunk[i]); - - return usart_flush(us); -} - -void usart_wait_chunk_free(volatile struct usart_desc *us) { - while (us->tx_buf.chunk_end[us->tx_buf.wr_idx] != -1) - ; -} - -int usart_flush(volatile struct usart_desc *us) { - /* Find a free slot for this chunk */ - if (us->tx_buf.chunk_end[us->tx_buf.wr_idx] != -1) { - us->tx_chunk_overruns++; - return -EBUSY; - } - - us->tx_buf.chunk_end[us->tx_buf.wr_idx] = us->tx_buf.wr_pos; - us->tx_buf.wr_idx = (us->tx_buf.wr_idx + 1) % ARRAY_LENGTH(us->tx_buf.chunk_end); - - if (!(us->tx_dmas->CR & DMA_SxCR_EN)) - usart_schedule_dma(us); - return 0; -} - -int usart_printf(volatile struct usart_desc *us, const char *fmt, ...) { - va_list va; - va_start(va, fmt); - tfp_format((void *)us, usart_putc_nonblocking_tpf, fmt, va); - return usart_flush(us); -} - -int usart_printf_blocking_va(volatile struct usart_desc *us, const char *fmt, va_list va) { - tfp_format((void *)us, usart_putc_blocking_tpf, fmt, va); - usart_wait_chunk_free(us); - return usart_flush(us); -} - -int usart_printf_blocking(volatile struct usart_desc *us, const char *fmt, ...) { - va_list va; - va_start(va, fmt); - return usart_printf_blocking_va(us, fmt, va); -} - diff --git a/controller/fw/src/serial.h b/controller/fw/src/serial.h deleted file mode 100644 index 73d2323..0000000 --- a/controller/fw/src/serial.h +++ /dev/null @@ -1,85 +0,0 @@ -/*
- * This file is part of the libusbhost library
- * hosted at http://github.com/libusbhost/libusbhost
- *
- * Copyright (C) 2015 Amir Hammad <amir.hammad@hotmail.com>
- *
- *
- * libusbhost is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef __SERIAL_H__
-#define __SERIAL_H__
-
-#include <stdint.h>
-#include <stddef.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <stdbool.h>
-
-#include "sr_global.h"
-
-struct dma_tx_buf {
- /* The following fields are accessed only from DMA ISR */
- ssize_t xfr_start; /* Start index of running DMA transfer */
- ssize_t xfr_end; /* End index of running DMA transfer plus one */
- bool wraparound;
- ssize_t xfr_next;
-
- /* The following fields are written only from non-interrupt code */
- ssize_t wr_pos; /* Next index to be written */
- ssize_t wr_idx;
- ssize_t chunk_end[8];
-
-/* Make GCC shut up about the zero-size array member. */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpedantic"
- /* Written outside ISR by usart_send_chunk_nonblocking, read via DMA */
- uint8_t data[0];
-#pragma GCC diagnostic pop
-};
-
-struct usart_desc {
- struct dma_tx_buf tx_buf;
- uint8_t data[512];
-
- uint32_t tx_chunk_overruns, tx_byte_overruns;
- uint32_t tx_errors;
-
- volatile uint8_t rx_buf[32];
-
- int comm_led;
-
- USART_TypeDef *le_usart;
- int le_usart_irqn;
- DMA_Stream_TypeDef *tx_dmas;
- int tx_dma_sn;
- int tx_dma_ch;
- DMA_TypeDef *tx_dma;
- int tx_dma_irqn;
-};
-
-void usart_dma_init(volatile struct usart_desc *us, unsigned int baudrate);
-int usart_send_chunk_nonblocking(volatile struct usart_desc *us, const char *chunk, size_t chunk_len);
-int usart_putc_nonblocking(volatile struct usart_desc *us, char c);
-int usart_putc_blocking(volatile struct usart_desc *us, char c);
-
-void usart_dma_stream_irq(volatile struct usart_desc *us);
-int usart_flush(volatile struct usart_desc *us);
-int usart_printf(volatile struct usart_desc *us, const char *fmt, ...);
-int usart_printf_blocking(volatile struct usart_desc *us, const char *fmt, ...);
-int usart_printf_blocking_va(volatile struct usart_desc *us, const char *fmt, va_list va);
-
-#endif // __SERIAL_H__
diff --git a/controller/fw/src/signal_processing.c b/controller/fw/src/signal_processing.c deleted file mode 100644 index e69de29..0000000 --- a/controller/fw/src/signal_processing.c +++ /dev/null diff --git a/controller/fw/src/simulation.h b/controller/fw/src/simulation.h deleted file mode 100644 index 2734e5b..0000000 --- a/controller/fw/src/simulation.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __SIMULATION_H__ -#define __SIMULATION_H__ - -#ifdef SIMULATION -#include <stdio.h> -#define DEBUG_PRINTN(...) printf(__VA_ARGS__) -#define DEBUG_PRINTNF(fmt, ...) DEBUG_PRINTN("%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__) -#define DEBUG_PRINT(fmt, ...) DEBUG_PRINTNF(fmt "\n", ##__VA_ARGS__) -#else -#define DEBUG_PRINT(...) ((void)0) -#define DEBUG_PRINTN(...) ((void)0) -#endif - -#endif /* __SIMULATION_H__ */ diff --git a/controller/fw/src/spi_flash.c b/controller/fw/src/spi_flash.c deleted file mode 100644 index 639c2b6..0000000 --- a/controller/fw/src/spi_flash.c +++ /dev/null @@ -1,200 +0,0 @@ -/* Library for SPI flash 25* devices. - * Copyright (c) 2014 Multi-Tech Systems - * Copyright (c) 2020 Jan Goette <ma@jaseg.de> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "spi_flash.h" - -enum { - WRITE_ENABLE = 0x06, - WRITE_DISABLE = 0x04, - READ_IDENTIFICATION = 0x9F, - READ_STATUS = 0x05, - WRITE_STATUS = 0x01, - READ_DATA = 0x03, - READ_DATA_FAST = 0x0B, - PAGE_PROGRAM = 0x02, - SECTOR_ERASE = 0xD8, - BULK_ERASE = 0xC7, - DEEP_POWER_DOWN = 0xB9, - DEEP_POWER_DOWN_RELEASE = 0xAB, -}; - -enum { - STATUS_SRWD = 0x80, // 0b 1000 0000 - STATUS_BP2 = 0x10, // 0b 0001 0000 - STATUS_BP1 = 0x08, // 0b 0000 1000 - STATUS_BP0 = 0x04, // 0b 0000 0100 - STATUS_WEL = 0x02, // 0b 0000 0010 - STATUS_WIP = 0x01, // 0b 0000 0001 -}; - - -static uint8_t spi_xfer(volatile SPI_TypeDef *spi, uint8_t b); -static uint8_t spi_read(struct spi_flash_if *spif); -static void spi_write(struct spi_flash_if *spif, uint8_t b); - -static void spif_write_page(struct spi_flash_if *spif, size_t addr, size_t len, const char* data); -static uint8_t spif_read_status(struct spi_flash_if *spif); -static void spif_enable_write(struct spi_flash_if *spif); -static void spif_wait_for_write(struct spi_flash_if *spif); - -#define low_byte(x) (x&0xff) -#define mid_byte(x) ((x>>8)&0xff) -#define high_byte(x) ((x>>16)&0xff) - -uint8_t spi_xfer(volatile SPI_TypeDef *spi, uint8_t b) { - while (!(spi->SR & SPI_SR_TXE)) - ; - (void) spi->DR; /* perform dummy read to clear RXNE flag */ - spi->DR = b; - while (!(spi->SR & SPI_SR_RXNE)) - ; - return spi->DR; -} - -uint8_t spi_read(struct spi_flash_if *spif) { - return spi_xfer(spif->spi, 0); -} - -void spi_write(struct spi_flash_if *spif, uint8_t b) { - (void)spi_xfer(spif->spi, b); -} - -void spif_init(struct spi_flash_if *spif, size_t page_size, SPI_TypeDef *spi, void (*cs)(bool val)) { - - spif->spi = spi; - spif->page_size = page_size; - spif->cs = cs; - spif->cs(1); - - spi->CR1 = (0<<SPI_CR1_BR_Pos) | SPI_CR1_CPOL | SPI_CR1_CPHA | SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_SPE | SPI_CR1_MSTR; - - spif->cs(0); - spi_write(spif, READ_IDENTIFICATION); - spif->id.mfg_id = spi_read(spif); - spif->id.type = spi_read(spif); - spif->id.size = 1<<spi_read(spif); - spif->cs(1); -} - -ssize_t spif_read(struct spi_flash_if *spif, size_t addr, size_t len, char* data) { - spif_enable_write(spif); - - spif->cs(0); - spi_write(spif, READ_DATA); - spi_write(spif, high_byte(addr)); - spi_write(spif, mid_byte(addr)); - spi_write(spif, low_byte(addr)); - - for (size_t i = 0; i < len; i++) - data[i] = spi_read(spif); - - spif->cs(1); - return len; -} - -void spif_write(struct spi_flash_if *spif, size_t addr, size_t len, const char* data) { - size_t written = 0, write_size = 0; - - while (written < len) { - write_size = spif->page_size - ((addr + written) % spif->page_size); - if (written + write_size > len) - write_size = len - written; - - spif_write_page(spif, addr + written, write_size, data + written); - written += write_size; - } -} - -static uint8_t spif_read_status(struct spi_flash_if *spif) { - spif->cs(0); - spi_write(spif, READ_STATUS); - uint8_t status = spi_read(spif); - spif->cs(1); - - return status; -} - -void spif_clear_sector(struct spi_flash_if *spif, size_t addr) { - spif_enable_write(spif); - - spif->cs(0); - spi_write(spif, SECTOR_ERASE); - spi_write(spif, high_byte(addr)); - spi_write(spif, mid_byte(addr)); - spi_write(spif, low_byte(addr)); - spif->cs(1); - - spif_wait_for_write(spif); -} - -void spif_clear_mem(struct spi_flash_if *spif) { - spif_enable_write(spif); - - spif->cs(0); - spi_write(spif, BULK_ERASE); - spif->cs(1); - - spif_wait_for_write(spif); -} - -static void spif_write_page(struct spi_flash_if *spif, size_t addr, size_t len, const char* data) { - spif_enable_write(spif); - - spif->cs(0); - spi_write(spif, PAGE_PROGRAM); - spi_write(spif, high_byte(addr)); - spi_write(spif, mid_byte(addr)); - spi_write(spif, low_byte(addr)); - - for (size_t i = 0; i < len; i++) { - spi_write(spif, data[i]); - } - - spif->cs(1); - spif_wait_for_write(spif); -} - -static void spif_enable_write(struct spi_flash_if *spif) { - spif->cs(0); - spi_write(spif, WRITE_ENABLE); - spif->cs(1); -} - -static void spif_wait_for_write(struct spi_flash_if *spif) { - while (spif_read_status(spif) & STATUS_WIP) - for (int i = 0; i < 800; i++) - ; -} - -void spif_deep_power_down(struct spi_flash_if *spif) { - spif->cs(0); - spi_write(spif, DEEP_POWER_DOWN); - spif->cs(1); -} - -void spif_wakeup(struct spi_flash_if *spif) { - spif->cs(0); - spi_write(spif, DEEP_POWER_DOWN_RELEASE); - spif->cs(1); -} - diff --git a/controller/fw/src/spi_flash.h b/controller/fw/src/spi_flash.h deleted file mode 100644 index 6443f11..0000000 --- a/controller/fw/src/spi_flash.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __SPI_FLASH_H__ -#define __SPI_FLASH_H__ - -#include <stdbool.h> -#include <unistd.h> - -#include <stm32f407xx.h> - -struct spi_mem_id { - size_t size; - uint8_t mfg_id; - uint8_t type; -}; - -struct spi_flash_if { - struct spi_mem_id id; - volatile SPI_TypeDef *spi; - size_t page_size; - void (*cs)(bool val); -}; - -void spif_init(struct spi_flash_if *spif, size_t page_size, SPI_TypeDef *spi, void (*cs)(bool val)); - -void spif_write(struct spi_flash_if *spif, size_t addr, size_t len, const char* data); -ssize_t spif_read(struct spi_flash_if *spif, size_t addr, size_t len, char* data); - -void spif_clear_mem(struct spi_flash_if *spif); -void spif_clear_sector(struct spi_flash_if *spif, size_t addr); - -void spif_deep_power_down(struct spi_flash_if *spif); -void spif_wakeup(struct spi_flash_if *spif); - -#endif /* __SPI_FLASH_H__ */ diff --git a/controller/fw/src/sr_global.h b/controller/fw/src/sr_global.h deleted file mode 100644 index 97db4e4..0000000 --- a/controller/fw/src/sr_global.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef __SR_GLOBAL_H__ -#define __SR_GLOBAL_H__ - -#include <stdint.h> -#include <sys/types.h> - -#ifndef SIMULATION -#include <stm32f407xx.h> -#include <stm32f4_isr.h> -#endif - -#define UNUSED(x) ((void) x) -#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0])) - -#define unused_a __attribute__((unused)) - -extern unsigned int sysclk_speed; -extern unsigned int apb1_speed; -extern unsigned int apb2_speed; -extern unsigned int auxclk_speed; -extern unsigned int apb1_timer_speed; -extern unsigned int apb2_timer_speed; - -extern struct leds { - unsigned int comm_tx; -} leds; -static inline uint16_t htole(uint16_t val) { return val; } - -void __libc_init_array(void); - -static inline void panic(void) { - asm volatile ("bkpt"); -} - -#endif /* __SR_GLOBAL_H__ */ diff --git a/controller/fw/src/startup_stm32f407xx.s b/controller/fw/src/startup_stm32f407xx.s deleted file mode 100644 index aeeeb22..0000000 --- a/controller/fw/src/startup_stm32f407xx.s +++ /dev/null @@ -1,521 +0,0 @@ -/** - ****************************************************************************** - * @file startup_stm32f407xx.s - * @author MCD Application Team - * @brief STM32F407xx Devices vector table for GCC based toolchains. - * This module performs: - * - Set the initial SP - * - Set the initial PC == Reset_Handler, - * - Set the vector table entries with the exceptions ISR address - * - Branches to main in the C library (which eventually - * calls main()). - * After Reset the Cortex-M4 processor is in Thread mode, - * priority is Privileged, and the Stack is set to Main. - ****************************************************************************** - * @attention - * - * <h2><center>© COPYRIGHT 2017 STMicroelectronics</center></h2> - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m4 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss -/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ - -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval : None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - ldr sp, =_estack /* set stack pointer */ - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system intitialization function.*/ - bl SystemInit -/* Call static constructors */ - bl __libc_init_array -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * @param None - * @retval None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M3. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDG_IRQHandler /* Window WatchDog */ - .word PVD_IRQHandler /* PVD through EXTI Line detection */ - .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ - .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ - .word FLASH_IRQHandler /* FLASH */ - .word RCC_IRQHandler /* RCC */ - .word EXTI0_IRQHandler /* EXTI Line0 */ - .word EXTI1_IRQHandler /* EXTI Line1 */ - .word EXTI2_IRQHandler /* EXTI Line2 */ - .word EXTI3_IRQHandler /* EXTI Line3 */ - .word EXTI4_IRQHandler /* EXTI Line4 */ - .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ - .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ - .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ - .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ - .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ - .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ - .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ - .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ - .word CAN1_TX_IRQHandler /* CAN1 TX */ - .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SCE_IRQHandler /* CAN1 SCE */ - .word EXTI9_5_IRQHandler /* External Line[9:5]s */ - .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ - .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ - .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ - .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ - .word TIM2_IRQHandler /* TIM2 */ - .word TIM3_IRQHandler /* TIM3 */ - .word TIM4_IRQHandler /* TIM4 */ - .word I2C1_EV_IRQHandler /* I2C1 Event */ - .word I2C1_ER_IRQHandler /* I2C1 Error */ - .word I2C2_EV_IRQHandler /* I2C2 Event */ - .word I2C2_ER_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXTI15_10_IRQHandler /* External Line[15:10]s */ - .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ - .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ - .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ - .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ - .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ - .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ - .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ - .word FSMC_IRQHandler /* FSMC */ - .word SDIO_IRQHandler /* SDIO */ - .word TIM5_IRQHandler /* TIM5 */ - .word SPI3_IRQHandler /* SPI3 */ - .word UART4_IRQHandler /* UART4 */ - .word UART5_IRQHandler /* UART5 */ - .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ - .word TIM7_IRQHandler /* TIM7 */ - .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ - .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ - .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ - .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ - .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ - .word ETH_IRQHandler /* Ethernet */ - .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ - .word CAN2_TX_IRQHandler /* CAN2 TX */ - .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ - .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ - .word CAN2_SCE_IRQHandler /* CAN2 SCE */ - .word OTG_FS_IRQHandler /* USB OTG FS */ - .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ - .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ - .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ - .word USART6_IRQHandler /* USART6 */ - .word I2C3_EV_IRQHandler /* I2C3 event */ - .word I2C3_ER_IRQHandler /* I2C3 error */ - .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ - .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ - .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ - .word OTG_HS_IRQHandler /* USB OTG HS */ - .word DCMI_IRQHandler /* DCMI */ - .word 0 /* CRYP crypto */ - .word HASH_RNG_IRQHandler /* Hash and Rng */ - .word FPU_IRQHandler /* FPU */ - - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler - - .weak PVD_IRQHandler - .thumb_set PVD_IRQHandler,Default_Handler - - .weak TAMP_STAMP_IRQHandler - .thumb_set TAMP_STAMP_IRQHandler,Default_Handler - - .weak RTC_WKUP_IRQHandler - .thumb_set RTC_WKUP_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak RCC_IRQHandler - .thumb_set RCC_IRQHandler,Default_Handler - - .weak EXTI0_IRQHandler - .thumb_set EXTI0_IRQHandler,Default_Handler - - .weak EXTI1_IRQHandler - .thumb_set EXTI1_IRQHandler,Default_Handler - - .weak EXTI2_IRQHandler - .thumb_set EXTI2_IRQHandler,Default_Handler - - .weak EXTI3_IRQHandler - .thumb_set EXTI3_IRQHandler,Default_Handler - - .weak EXTI4_IRQHandler - .thumb_set EXTI4_IRQHandler,Default_Handler - - .weak DMA1_Stream0_IRQHandler - .thumb_set DMA1_Stream0_IRQHandler,Default_Handler - - .weak DMA1_Stream1_IRQHandler - .thumb_set DMA1_Stream1_IRQHandler,Default_Handler - - .weak DMA1_Stream2_IRQHandler - .thumb_set DMA1_Stream2_IRQHandler,Default_Handler - - .weak DMA1_Stream3_IRQHandler - .thumb_set DMA1_Stream3_IRQHandler,Default_Handler - - .weak DMA1_Stream4_IRQHandler - .thumb_set DMA1_Stream4_IRQHandler,Default_Handler - - .weak DMA1_Stream5_IRQHandler - .thumb_set DMA1_Stream5_IRQHandler,Default_Handler - - .weak DMA1_Stream6_IRQHandler - .thumb_set DMA1_Stream6_IRQHandler,Default_Handler - - .weak ADC_IRQHandler - .thumb_set ADC_IRQHandler,Default_Handler - - .weak CAN1_TX_IRQHandler - .thumb_set CAN1_TX_IRQHandler,Default_Handler - - .weak CAN1_RX0_IRQHandler - .thumb_set CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SCE_IRQHandler - .thumb_set CAN1_SCE_IRQHandler,Default_Handler - - .weak EXTI9_5_IRQHandler - .thumb_set EXTI9_5_IRQHandler,Default_Handler - - .weak TIM1_BRK_TIM9_IRQHandler - .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler - - .weak TIM1_UP_TIM10_IRQHandler - .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler - - .weak TIM1_TRG_COM_TIM11_IRQHandler - .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler - - .weak TIM1_CC_IRQHandler - .thumb_set TIM1_CC_IRQHandler,Default_Handler - - .weak TIM2_IRQHandler - .thumb_set TIM2_IRQHandler,Default_Handler - - .weak TIM3_IRQHandler - .thumb_set TIM3_IRQHandler,Default_Handler - - .weak TIM4_IRQHandler - .thumb_set TIM4_IRQHandler,Default_Handler - - .weak I2C1_EV_IRQHandler - .thumb_set I2C1_EV_IRQHandler,Default_Handler - - .weak I2C1_ER_IRQHandler - .thumb_set I2C1_ER_IRQHandler,Default_Handler - - .weak I2C2_EV_IRQHandler - .thumb_set I2C2_EV_IRQHandler,Default_Handler - - .weak I2C2_ER_IRQHandler - .thumb_set I2C2_ER_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXTI15_10_IRQHandler - .thumb_set EXTI15_10_IRQHandler,Default_Handler - - .weak RTC_Alarm_IRQHandler - .thumb_set RTC_Alarm_IRQHandler,Default_Handler - - .weak OTG_FS_WKUP_IRQHandler - .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler - - .weak TIM8_BRK_TIM12_IRQHandler - .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler - - .weak TIM8_UP_TIM13_IRQHandler - .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler - - .weak TIM8_TRG_COM_TIM14_IRQHandler - .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler - - .weak TIM8_CC_IRQHandler - .thumb_set TIM8_CC_IRQHandler,Default_Handler - - .weak DMA1_Stream7_IRQHandler - .thumb_set DMA1_Stream7_IRQHandler,Default_Handler - - .weak FSMC_IRQHandler - .thumb_set FSMC_IRQHandler,Default_Handler - - .weak SDIO_IRQHandler - .thumb_set SDIO_IRQHandler,Default_Handler - - .weak TIM5_IRQHandler - .thumb_set TIM5_IRQHandler,Default_Handler - - .weak SPI3_IRQHandler - .thumb_set SPI3_IRQHandler,Default_Handler - - .weak UART4_IRQHandler - .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler - .thumb_set UART5_IRQHandler,Default_Handler - - .weak TIM6_DAC_IRQHandler - .thumb_set TIM6_DAC_IRQHandler,Default_Handler - - .weak TIM7_IRQHandler - .thumb_set TIM7_IRQHandler,Default_Handler - - .weak DMA2_Stream0_IRQHandler - .thumb_set DMA2_Stream0_IRQHandler,Default_Handler - - .weak DMA2_Stream1_IRQHandler - .thumb_set DMA2_Stream1_IRQHandler,Default_Handler - - .weak DMA2_Stream2_IRQHandler - .thumb_set DMA2_Stream2_IRQHandler,Default_Handler - - .weak DMA2_Stream3_IRQHandler - .thumb_set DMA2_Stream3_IRQHandler,Default_Handler - - .weak DMA2_Stream4_IRQHandler - .thumb_set DMA2_Stream4_IRQHandler,Default_Handler - - .weak ETH_IRQHandler - .thumb_set ETH_IRQHandler,Default_Handler - - .weak ETH_WKUP_IRQHandler - .thumb_set ETH_WKUP_IRQHandler,Default_Handler - - .weak CAN2_TX_IRQHandler - .thumb_set CAN2_TX_IRQHandler,Default_Handler - - .weak CAN2_RX0_IRQHandler - .thumb_set CAN2_RX0_IRQHandler,Default_Handler - - .weak CAN2_RX1_IRQHandler - .thumb_set CAN2_RX1_IRQHandler,Default_Handler - - .weak CAN2_SCE_IRQHandler - .thumb_set CAN2_SCE_IRQHandler,Default_Handler - - .weak OTG_FS_IRQHandler - .thumb_set OTG_FS_IRQHandler,Default_Handler - - .weak DMA2_Stream5_IRQHandler - .thumb_set DMA2_Stream5_IRQHandler,Default_Handler - - .weak DMA2_Stream6_IRQHandler - .thumb_set DMA2_Stream6_IRQHandler,Default_Handler - - .weak DMA2_Stream7_IRQHandler - .thumb_set DMA2_Stream7_IRQHandler,Default_Handler - - .weak USART6_IRQHandler - .thumb_set USART6_IRQHandler,Default_Handler - - .weak I2C3_EV_IRQHandler - .thumb_set I2C3_EV_IRQHandler,Default_Handler - - .weak I2C3_ER_IRQHandler - .thumb_set I2C3_ER_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_OUT_IRQHandler - .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_IN_IRQHandler - .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler - - .weak OTG_HS_WKUP_IRQHandler - .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler - - .weak OTG_HS_IRQHandler - .thumb_set OTG_HS_IRQHandler,Default_Handler - - .weak DCMI_IRQHandler - .thumb_set DCMI_IRQHandler,Default_Handler - - .weak HASH_RNG_IRQHandler - .thumb_set HASH_RNG_IRQHandler,Default_Handler - - .weak FPU_IRQHandler - .thumb_set FPU_IRQHandler,Default_Handler - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/controller/fw/src/stm32f4_isr.h b/controller/fw/src/stm32f4_isr.h deleted file mode 100644 index bc16421..0000000 --- a/controller/fw/src/stm32f4_isr.h +++ /dev/null @@ -1,98 +0,0 @@ - -#ifndef __STM32F4_ISR_H__ -#define __STM32F4_ISR_H__ - -void Reset_Handler(void); -void NMI_Handler(void); -void HardFault_Handler(void); -void MemManage_Handler(void); -void BusFault_Handler(void); -void UsageFault_Handler(void); -void SVC_Handler(void); -void DebugMon_Handler(void); -void PendSV_Handler(void); -void SysTick_Handler(void); - -void WWDG_IRQHandler(void); -void PVD_IRQHandler(void); -void TAMP_STAMP_IRQHandler(void); -void RTC_WKUP_IRQHandler(void); -void FLASH_IRQHandler(void); -void RCC_IRQHandler(void); -void EXTI0_IRQHandler(void); -void EXTI1_IRQHandler(void); -void EXTI2_IRQHandler(void); -void EXTI3_IRQHandler(void); -void EXTI4_IRQHandler(void); -void DMA1_Stream0_IRQHandler(void); -void DMA1_Stream1_IRQHandler(void); -void DMA1_Stream2_IRQHandler(void); -void DMA1_Stream3_IRQHandler(void); -void DMA1_Stream4_IRQHandler(void); -void DMA1_Stream5_IRQHandler(void); -void DMA1_Stream6_IRQHandler(void); -void ADC_IRQHandler(void); -void CAN1_TX_IRQHandler(void); -void CAN1_RX0_IRQHandler(void); -void CAN1_RX1_IRQHandler(void); -void CAN1_SCE_IRQHandler(void); -void EXTI9_5_IRQHandler(void); -void TIM1_BRK_TIM9_IRQHandler(void); -void TIM1_UP_TIM10_IRQHandler(void); -void TIM1_TRG_COM_TIM11_IRQHandler(void); -void TIM1_CC_IRQHandler(void); -void TIM2_IRQHandler(void); -void TIM3_IRQHandler(void); -void TIM4_IRQHandler(void); -void I2C1_EV_IRQHandler(void); -void I2C1_ER_IRQHandler(void); -void I2C2_EV_IRQHandler(void); -void I2C2_ER_IRQHandler(void); -void SPI1_IRQHandler(void); -void SPI2_IRQHandler(void); -void USART1_IRQHandler(void); -void USART2_IRQHandler(void); -void USART3_IRQHandler(void); -void EXTI15_10_IRQHandler(void); -void RTC_Alarm_IRQHandler(void); -void OTG_FS_WKUP_IRQHandler(void); -void TIM8_BRK_TIM12_IRQHandler(void); -void TIM8_UP_TIM13_IRQHandler(void); -void TIM8_TRG_COM_TIM14_IRQHandler(void); -void TIM8_CC_IRQHandler(void); -void DMA1_Stream7_IRQHandler(void); -void FSMC_IRQHandler(void); -void SDIO_IRQHandler(void); -void TIM5_IRQHandler(void); -void SPI3_IRQHandler(void); -void UART4_IRQHandler(void); -void UART5_IRQHandler(void); -void TIM6_DAC_IRQHandler(void); -void TIM7_IRQHandler(void); -void DMA2_Stream0_IRQHandler(void); -void DMA2_Stream1_IRQHandler(void); -void DMA2_Stream2_IRQHandler(void); -void DMA2_Stream3_IRQHandler(void); -void DMA2_Stream4_IRQHandler(void); -void ETH_IRQHandler(void); -void ETH_WKUP_IRQHandler(void); -void CAN2_TX_IRQHandler(void); -void CAN2_RX0_IRQHandler(void); -void CAN2_RX1_IRQHandler(void); -void CAN2_SCE_IRQHandler(void); -void OTG_FS_IRQHandler(void); -void DMA2_Stream5_IRQHandler(void); -void DMA2_Stream6_IRQHandler(void); -void DMA2_Stream7_IRQHandler(void); -void USART6_IRQHandler(void); -void I2C3_EV_IRQHandler(void); -void I2C3_ER_IRQHandler(void); -void OTG_HS_EP1_OUT_IRQHandler(void); -void OTG_HS_EP1_IN_IRQHandler(void); -void OTG_HS_WKUP_IRQHandler(void); -void OTG_HS_IRQHandler(void); -void DCMI_IRQHandler(void); -void HASH_RNG_IRQHandler(void); -void FPU_IRQHandler(void); - -#endif /* __STM32F4_ISR_H__ */ diff --git a/controller/fw/src/system_stm32f4xx.c b/controller/fw/src/system_stm32f4xx.c deleted file mode 100644 index 5d005ed..0000000 --- a/controller/fw/src/system_stm32f4xx.c +++ /dev/null @@ -1,742 +0,0 @@ -/** - ****************************************************************************** - * @file system_stm32f4xx.c - * @author MCD Application Team - * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File. - * - * This file provides two functions and one global variable to be called from - * user application: - * - SystemInit(): This function is called at startup just after reset and - * before branch to main program. This call is made inside - * the "startup_stm32f4xx.s" file. - * - * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used - * by the user application to setup the SysTick - * timer or configure other parameters. - * - * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must - * be called whenever the core clock is changed - * during program execution. - * - * - ****************************************************************************** - * @attention - * - * <h2><center>© COPYRIGHT 2017 STMicroelectronics</center></h2> - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/** @addtogroup CMSIS - * @{ - */ - -/** @addtogroup stm32f4xx_system - * @{ - */ - -/** @addtogroup STM32F4xx_System_Private_Includes - * @{ - */ - - -#include "stm32f4xx.h" - -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_TypesDefinitions - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_Defines - * @{ - */ - -/************************* Miscellaneous Configuration ************************/ -/*!< Uncomment the following line if you need to use external SRAM or SDRAM as data memory */ -#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\ - || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) -/* #define DATA_IN_ExtSRAM */ -#endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F469xx || STM32F479xx ||\ - STM32F412Zx || STM32F412Vx */ - -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) -/* #define DATA_IN_ExtSDRAM */ -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\ - STM32F479xx */ - -/*!< Uncomment the following line if you need to relocate your vector Table in - Internal SRAM. */ -/* #define VECT_TAB_SRAM */ -#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. - This value must be a multiple of 0x200. */ -/******************************************************************************/ - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_Macros - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_Variables - * @{ - */ - /* This variable is updated in three ways: - 1) by calling CMSIS function SystemCoreClockUpdate() - 2) by calling HAL API function HAL_RCC_GetHCLKFreq() - 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency - Note: If you use this function to configure the system clock; then there - is no need to call the 2 first functions listed above, since SystemCoreClock - variable is updated automatically. - */ -uint32_t SystemCoreClock = 16000000; -const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; -const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes - * @{ - */ - -#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) - static void SystemInit_ExtMemCtl(void); -#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_Functions - * @{ - */ - -/** - * @brief Setup the microcontroller system - * Initialize the FPU setting, vector table location and External memory - * configuration. - * @param None - * @retval None - */ -void SystemInit(void) -{ - SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ - __DSB(); - __ISB(); - -#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) - SystemInit_ExtMemCtl(); -#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ - - /* Configure the Vector Table location add offset address ------------------*/ -#ifdef VECT_TAB_SRAM - SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ -#else - SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ -#endif -} - -/** - * @brief Update SystemCoreClock variable according to Clock Register Values. - * The SystemCoreClock variable contains the core clock (HCLK), it can - * be used by the user application to setup the SysTick timer or configure - * other parameters. - * - * @note Each time the core clock (HCLK) changes, this function must be called - * to update SystemCoreClock variable value. Otherwise, any configuration - * based on this variable will be incorrect. - * - * @note - The system frequency computed by this function is not the real - * frequency in the chip. It is calculated based on the predefined - * constant and the selected clock source: - * - * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) - * - * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) - * - * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) - * or HSI_VALUE(*) multiplied/divided by the PLL factors. - * - * (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value - * 16 MHz) but the real value may vary depending on the variations - * in voltage and temperature. - * - * (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value - * depends on the application requirements), user has to ensure that HSE_VALUE - * is same as the real frequency of the crystal used. Otherwise, this function - * may have wrong result. - * - * - The result of this function could be not correct when using fractional - * value for HSE crystal. - * - * @param None - * @retval None - */ -void SystemCoreClockUpdate(void) -{ - uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; - - /* Get SYSCLK source -------------------------------------------------------*/ - tmp = RCC->CFGR & RCC_CFGR_SWS; - - switch (tmp) - { - case 0x00: /* HSI used as system clock source */ - SystemCoreClock = HSI_VALUE; - break; - case 0x04: /* HSE used as system clock source */ - SystemCoreClock = HSE_VALUE; - break; - case 0x08: /* PLL used as system clock source */ - - /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N - SYSCLK = PLL_VCO / PLL_P - */ - pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; - pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; - - if (pllsource != 0) - { - /* HSE used as PLL clock source */ - pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); - } - else - { - /* HSI used as PLL clock source */ - pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); - } - - pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; - SystemCoreClock = pllvco/pllp; - break; - default: - SystemCoreClock = HSI_VALUE; - break; - } - /* Compute HCLK frequency --------------------------------------------------*/ - /* Get HCLK prescaler */ - tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; - /* HCLK frequency */ - SystemCoreClock >>= tmp; -} - -#if defined (DATA_IN_ExtSRAM) && defined (DATA_IN_ExtSDRAM) -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F469xx) || defined(STM32F479xx) -/** - * @brief Setup the external memory controller. - * Called in startup_stm32f4xx.s before jump to main. - * This function configures the external memories (SRAM/SDRAM) - * This SRAM/SDRAM will be used as program data memory (including heap and stack). - * @param None - * @retval None - */ -void SystemInit_ExtMemCtl(void) -{ - __IO uint32_t tmp = 0x00; - - register uint32_t tmpreg = 0, timeout = 0xFFFF; - register __IO uint32_t index; - - /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */ - RCC->AHB1ENR |= 0x000001F8; - - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN); - - /* Connect PDx pins to FMC Alternate function */ - GPIOD->AFR[0] = 0x00CCC0CC; - GPIOD->AFR[1] = 0xCCCCCCCC; - /* Configure PDx pins in Alternate function mode */ - GPIOD->MODER = 0xAAAA0A8A; - /* Configure PDx pins speed to 100 MHz */ - GPIOD->OSPEEDR = 0xFFFF0FCF; - /* Configure PDx pins Output type to push-pull */ - GPIOD->OTYPER = 0x00000000; - /* No pull-up, pull-down for PDx pins */ - GPIOD->PUPDR = 0x00000000; - - /* Connect PEx pins to FMC Alternate function */ - GPIOE->AFR[0] = 0xC00CC0CC; - GPIOE->AFR[1] = 0xCCCCCCCC; - /* Configure PEx pins in Alternate function mode */ - GPIOE->MODER = 0xAAAA828A; - /* Configure PEx pins speed to 100 MHz */ - GPIOE->OSPEEDR = 0xFFFFC3CF; - /* Configure PEx pins Output type to push-pull */ - GPIOE->OTYPER = 0x00000000; - /* No pull-up, pull-down for PEx pins */ - GPIOE->PUPDR = 0x00000000; - - /* Connect PFx pins to FMC Alternate function */ - GPIOF->AFR[0] = 0xCCCCCCCC; - GPIOF->AFR[1] = 0xCCCCCCCC; - /* Configure PFx pins in Alternate function mode */ - GPIOF->MODER = 0xAA800AAA; - /* Configure PFx pins speed to 50 MHz */ - GPIOF->OSPEEDR = 0xAA800AAA; - /* Configure PFx pins Output type to push-pull */ - GPIOF->OTYPER = 0x00000000; - /* No pull-up, pull-down for PFx pins */ - GPIOF->PUPDR = 0x00000000; - - /* Connect PGx pins to FMC Alternate function */ - GPIOG->AFR[0] = 0xCCCCCCCC; - GPIOG->AFR[1] = 0xCCCCCCCC; - /* Configure PGx pins in Alternate function mode */ - GPIOG->MODER = 0xAAAAAAAA; - /* Configure PGx pins speed to 50 MHz */ - GPIOG->OSPEEDR = 0xAAAAAAAA; - /* Configure PGx pins Output type to push-pull */ - GPIOG->OTYPER = 0x00000000; - /* No pull-up, pull-down for PGx pins */ - GPIOG->PUPDR = 0x00000000; - - /* Connect PHx pins to FMC Alternate function */ - GPIOH->AFR[0] = 0x00C0CC00; - GPIOH->AFR[1] = 0xCCCCCCCC; - /* Configure PHx pins in Alternate function mode */ - GPIOH->MODER = 0xAAAA08A0; - /* Configure PHx pins speed to 50 MHz */ - GPIOH->OSPEEDR = 0xAAAA08A0; - /* Configure PHx pins Output type to push-pull */ - GPIOH->OTYPER = 0x00000000; - /* No pull-up, pull-down for PHx pins */ - GPIOH->PUPDR = 0x00000000; - - /* Connect PIx pins to FMC Alternate function */ - GPIOI->AFR[0] = 0xCCCCCCCC; - GPIOI->AFR[1] = 0x00000CC0; - /* Configure PIx pins in Alternate function mode */ - GPIOI->MODER = 0x0028AAAA; - /* Configure PIx pins speed to 50 MHz */ - GPIOI->OSPEEDR = 0x0028AAAA; - /* Configure PIx pins Output type to push-pull */ - GPIOI->OTYPER = 0x00000000; - /* No pull-up, pull-down for PIx pins */ - GPIOI->PUPDR = 0x00000000; - -/*-- FMC Configuration -------------------------------------------------------*/ - /* Enable the FMC interface clock */ - RCC->AHB3ENR |= 0x00000001; - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); - - FMC_Bank5_6->SDCR[0] = 0x000019E4; - FMC_Bank5_6->SDTR[0] = 0x01115351; - - /* SDRAM initialization sequence */ - /* Clock enable command */ - FMC_Bank5_6->SDCMR = 0x00000011; - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* Delay */ - for (index = 0; index<1000; index++); - - /* PALL command */ - FMC_Bank5_6->SDCMR = 0x00000012; - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* Auto refresh command */ - FMC_Bank5_6->SDCMR = 0x00000073; - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* MRD register program */ - FMC_Bank5_6->SDCMR = 0x00046014; - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* Set refresh count */ - tmpreg = FMC_Bank5_6->SDRTR; - FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1)); - - /* Disable write protection */ - tmpreg = FMC_Bank5_6->SDCR[0]; - FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF); - -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) - /* Configure and enable Bank1_SRAM2 */ - FMC_Bank1->BTCR[2] = 0x00001011; - FMC_Bank1->BTCR[3] = 0x00000201; - FMC_Bank1E->BWTR[2] = 0x0fffffff; -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ -#if defined(STM32F469xx) || defined(STM32F479xx) - /* Configure and enable Bank1_SRAM2 */ - FMC_Bank1->BTCR[2] = 0x00001091; - FMC_Bank1->BTCR[3] = 0x00110212; - FMC_Bank1E->BWTR[2] = 0x0fffffff; -#endif /* STM32F469xx || STM32F479xx */ - - (void)(tmp); -} -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ -#elif defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) -/** - * @brief Setup the external memory controller. - * Called in startup_stm32f4xx.s before jump to main. - * This function configures the external memories (SRAM/SDRAM) - * This SRAM/SDRAM will be used as program data memory (including heap and stack). - * @param None - * @retval None - */ -void SystemInit_ExtMemCtl(void) -{ - __IO uint32_t tmp = 0x00; -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) -#if defined (DATA_IN_ExtSDRAM) - register uint32_t tmpreg = 0, timeout = 0xFFFF; - register __IO uint32_t index; - -#if defined(STM32F446xx) - /* Enable GPIOA, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG interface - clock */ - RCC->AHB1ENR |= 0x0000007D; -#else - /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface - clock */ - RCC->AHB1ENR |= 0x000001F8; -#endif /* STM32F446xx */ - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN); - -#if defined(STM32F446xx) - /* Connect PAx pins to FMC Alternate function */ - GPIOA->AFR[0] |= 0xC0000000; - GPIOA->AFR[1] |= 0x00000000; - /* Configure PDx pins in Alternate function mode */ - GPIOA->MODER |= 0x00008000; - /* Configure PDx pins speed to 50 MHz */ - GPIOA->OSPEEDR |= 0x00008000; - /* Configure PDx pins Output type to push-pull */ - GPIOA->OTYPER |= 0x00000000; - /* No pull-up, pull-down for PDx pins */ - GPIOA->PUPDR |= 0x00000000; - - /* Connect PCx pins to FMC Alternate function */ - GPIOC->AFR[0] |= 0x00CC0000; - GPIOC->AFR[1] |= 0x00000000; - /* Configure PDx pins in Alternate function mode */ - GPIOC->MODER |= 0x00000A00; - /* Configure PDx pins speed to 50 MHz */ - GPIOC->OSPEEDR |= 0x00000A00; - /* Configure PDx pins Output type to push-pull */ - GPIOC->OTYPER |= 0x00000000; - /* No pull-up, pull-down for PDx pins */ - GPIOC->PUPDR |= 0x00000000; -#endif /* STM32F446xx */ - - /* Connect PDx pins to FMC Alternate function */ - GPIOD->AFR[0] = 0x000000CC; - GPIOD->AFR[1] = 0xCC000CCC; - /* Configure PDx pins in Alternate function mode */ - GPIOD->MODER = 0xA02A000A; - /* Configure PDx pins speed to 50 MHz */ - GPIOD->OSPEEDR = 0xA02A000A; - /* Configure PDx pins Output type to push-pull */ - GPIOD->OTYPER = 0x00000000; - /* No pull-up, pull-down for PDx pins */ - GPIOD->PUPDR = 0x00000000; - - /* Connect PEx pins to FMC Alternate function */ - GPIOE->AFR[0] = 0xC00000CC; - GPIOE->AFR[1] = 0xCCCCCCCC; - /* Configure PEx pins in Alternate function mode */ - GPIOE->MODER = 0xAAAA800A; - /* Configure PEx pins speed to 50 MHz */ - GPIOE->OSPEEDR = 0xAAAA800A; - /* Configure PEx pins Output type to push-pull */ - GPIOE->OTYPER = 0x00000000; - /* No pull-up, pull-down for PEx pins */ - GPIOE->PUPDR = 0x00000000; - - /* Connect PFx pins to FMC Alternate function */ - GPIOF->AFR[0] = 0xCCCCCCCC; - GPIOF->AFR[1] = 0xCCCCCCCC; - /* Configure PFx pins in Alternate function mode */ - GPIOF->MODER = 0xAA800AAA; - /* Configure PFx pins speed to 50 MHz */ - GPIOF->OSPEEDR = 0xAA800AAA; - /* Configure PFx pins Output type to push-pull */ - GPIOF->OTYPER = 0x00000000; - /* No pull-up, pull-down for PFx pins */ - GPIOF->PUPDR = 0x00000000; - - /* Connect PGx pins to FMC Alternate function */ - GPIOG->AFR[0] = 0xCCCCCCCC; - GPIOG->AFR[1] = 0xCCCCCCCC; - /* Configure PGx pins in Alternate function mode */ - GPIOG->MODER = 0xAAAAAAAA; - /* Configure PGx pins speed to 50 MHz */ - GPIOG->OSPEEDR = 0xAAAAAAAA; - /* Configure PGx pins Output type to push-pull */ - GPIOG->OTYPER = 0x00000000; - /* No pull-up, pull-down for PGx pins */ - GPIOG->PUPDR = 0x00000000; - -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F469xx) || defined(STM32F479xx) - /* Connect PHx pins to FMC Alternate function */ - GPIOH->AFR[0] = 0x00C0CC00; - GPIOH->AFR[1] = 0xCCCCCCCC; - /* Configure PHx pins in Alternate function mode */ - GPIOH->MODER = 0xAAAA08A0; - /* Configure PHx pins speed to 50 MHz */ - GPIOH->OSPEEDR = 0xAAAA08A0; - /* Configure PHx pins Output type to push-pull */ - GPIOH->OTYPER = 0x00000000; - /* No pull-up, pull-down for PHx pins */ - GPIOH->PUPDR = 0x00000000; - - /* Connect PIx pins to FMC Alternate function */ - GPIOI->AFR[0] = 0xCCCCCCCC; - GPIOI->AFR[1] = 0x00000CC0; - /* Configure PIx pins in Alternate function mode */ - GPIOI->MODER = 0x0028AAAA; - /* Configure PIx pins speed to 50 MHz */ - GPIOI->OSPEEDR = 0x0028AAAA; - /* Configure PIx pins Output type to push-pull */ - GPIOI->OTYPER = 0x00000000; - /* No pull-up, pull-down for PIx pins */ - GPIOI->PUPDR = 0x00000000; -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ - -/*-- FMC Configuration -------------------------------------------------------*/ - /* Enable the FMC interface clock */ - RCC->AHB3ENR |= 0x00000001; - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); - - /* Configure and enable SDRAM bank1 */ -#if defined(STM32F446xx) - FMC_Bank5_6->SDCR[0] = 0x00001954; -#else - FMC_Bank5_6->SDCR[0] = 0x000019E4; -#endif /* STM32F446xx */ - FMC_Bank5_6->SDTR[0] = 0x01115351; - - /* SDRAM initialization sequence */ - /* Clock enable command */ - FMC_Bank5_6->SDCMR = 0x00000011; - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* Delay */ - for (index = 0; index<1000; index++); - - /* PALL command */ - FMC_Bank5_6->SDCMR = 0x00000012; - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* Auto refresh command */ -#if defined(STM32F446xx) - FMC_Bank5_6->SDCMR = 0x000000F3; -#else - FMC_Bank5_6->SDCMR = 0x00000073; -#endif /* STM32F446xx */ - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* MRD register program */ -#if defined(STM32F446xx) - FMC_Bank5_6->SDCMR = 0x00044014; -#else - FMC_Bank5_6->SDCMR = 0x00046014; -#endif /* STM32F446xx */ - timeout = 0xFFFF; - while((tmpreg != 0) && (timeout-- > 0)) - { - tmpreg = FMC_Bank5_6->SDSR & 0x00000020; - } - - /* Set refresh count */ - tmpreg = FMC_Bank5_6->SDRTR; -#if defined(STM32F446xx) - FMC_Bank5_6->SDRTR = (tmpreg | (0x0000050C<<1)); -#else - FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1)); -#endif /* STM32F446xx */ - - /* Disable write protection */ - tmpreg = FMC_Bank5_6->SDCR[0]; - FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF); -#endif /* DATA_IN_ExtSDRAM */ -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */ - -#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\ - || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\ - || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) - -#if defined(DATA_IN_ExtSRAM) -/*-- GPIOs Configuration -----------------------------------------------------*/ - /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */ - RCC->AHB1ENR |= 0x00000078; - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN); - - /* Connect PDx pins to FMC Alternate function */ - GPIOD->AFR[0] = 0x00CCC0CC; - GPIOD->AFR[1] = 0xCCCCCCCC; - /* Configure PDx pins in Alternate function mode */ - GPIOD->MODER = 0xAAAA0A8A; - /* Configure PDx pins speed to 100 MHz */ - GPIOD->OSPEEDR = 0xFFFF0FCF; - /* Configure PDx pins Output type to push-pull */ - GPIOD->OTYPER = 0x00000000; - /* No pull-up, pull-down for PDx pins */ - GPIOD->PUPDR = 0x00000000; - - /* Connect PEx pins to FMC Alternate function */ - GPIOE->AFR[0] = 0xC00CC0CC; - GPIOE->AFR[1] = 0xCCCCCCCC; - /* Configure PEx pins in Alternate function mode */ - GPIOE->MODER = 0xAAAA828A; - /* Configure PEx pins speed to 100 MHz */ - GPIOE->OSPEEDR = 0xFFFFC3CF; - /* Configure PEx pins Output type to push-pull */ - GPIOE->OTYPER = 0x00000000; - /* No pull-up, pull-down for PEx pins */ - GPIOE->PUPDR = 0x00000000; - - /* Connect PFx pins to FMC Alternate function */ - GPIOF->AFR[0] = 0x00CCCCCC; - GPIOF->AFR[1] = 0xCCCC0000; - /* Configure PFx pins in Alternate function mode */ - GPIOF->MODER = 0xAA000AAA; - /* Configure PFx pins speed to 100 MHz */ - GPIOF->OSPEEDR = 0xFF000FFF; - /* Configure PFx pins Output type to push-pull */ - GPIOF->OTYPER = 0x00000000; - /* No pull-up, pull-down for PFx pins */ - GPIOF->PUPDR = 0x00000000; - - /* Connect PGx pins to FMC Alternate function */ - GPIOG->AFR[0] = 0x00CCCCCC; - GPIOG->AFR[1] = 0x000000C0; - /* Configure PGx pins in Alternate function mode */ - GPIOG->MODER = 0x00085AAA; - /* Configure PGx pins speed to 100 MHz */ - GPIOG->OSPEEDR = 0x000CAFFF; - /* Configure PGx pins Output type to push-pull */ - GPIOG->OTYPER = 0x00000000; - /* No pull-up, pull-down for PGx pins */ - GPIOG->PUPDR = 0x00000000; - -/*-- FMC/FSMC Configuration --------------------------------------------------*/ - /* Enable the FMC/FSMC interface clock */ - RCC->AHB3ENR |= 0x00000001; - -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); - /* Configure and enable Bank1_SRAM2 */ - FMC_Bank1->BTCR[2] = 0x00001011; - FMC_Bank1->BTCR[3] = 0x00000201; - FMC_Bank1E->BWTR[2] = 0x0fffffff; -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ -#if defined(STM32F469xx) || defined(STM32F479xx) - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); - /* Configure and enable Bank1_SRAM2 */ - FMC_Bank1->BTCR[2] = 0x00001091; - FMC_Bank1->BTCR[3] = 0x00110212; - FMC_Bank1E->BWTR[2] = 0x0fffffff; -#endif /* STM32F469xx || STM32F479xx */ -#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)\ - || defined(STM32F412Zx) || defined(STM32F412Vx) - /* Delay after an RCC peripheral clock enabling */ - tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN); - /* Configure and enable Bank1_SRAM2 */ - FSMC_Bank1->BTCR[2] = 0x00001011; - FSMC_Bank1->BTCR[3] = 0x00000201; - FSMC_Bank1E->BWTR[2] = 0x0FFFFFFF; -#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F412Zx || STM32F412Vx */ - -#endif /* DATA_IN_ExtSRAM */ -#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\ - STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */ - (void)(tmp); -} -#endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/controller/fw/src/test_decoder.py b/controller/fw/src/test_decoder.py deleted file mode 100644 index 8be5b02..0000000 --- a/controller/fw/src/test_decoder.py +++ /dev/null @@ -1,168 +0,0 @@ -"""Decoding module.""" -import numpy as np -import warnings -import test_pyldpc_utils as utils - -from numba import njit, int64, types, float64 - -np.set_printoptions(linewidth=180, threshold=1000, edgeitems=20) - -def decode(H, y, snr, maxiter=100): - """Decode a Gaussian noise corrupted n bits message using BP algorithm. - - Decoding is performed in parallel if multiple codewords are passed in y. - - Parameters - ---------- - H: array (n_equations, n_code). Decoding matrix H. - y: array (n_code, n_messages) or (n_code,). Received message(s) in the - codeword space. - maxiter: int. Maximum number of iterations of the BP algorithm. - - Returns - ------- - x: array (n_code,) or (n_code, n_messages) the solutions in the - codeword space. - - """ - m, n = H.shape - - bits_hist, bits_values, nodes_hist, nodes_values = utils.bitsandnodes(H) - - var = 10 ** (-snr / 10) - - if y.ndim == 1: - y = y[:, None] - # step 0: initialization - - Lc = 2 * y / var - _, n_messages = y.shape - - Lq = np.zeros(shape=(m, n, n_messages)) - - Lr = np.zeros(shape=(m, n, n_messages)) - - for n_iter in range(maxiter): - #print(f'============================ iteration {n_iter} ============================') - Lq, Lr, L_posteriori = _logbp_numba(bits_hist, bits_values, nodes_hist, - nodes_values, Lc, Lq, Lr, n_iter) - #print("Lq=", Lq.flatten()) - #print("Lr=", Lr.flatten()) - #print("L_posteriori=", L_posteriori.flatten()) - #print('L_posteriori=[') - #for row in L_posteriori.reshape([-1, 16]): - # for val in row: - # cc = '\033[91m' if val < 0 else ('\033[92m' if val > 0 else '\033[94m') - # print(f"{cc}{val: 012.6g}\033[38;5;240m", end=', ') - # print() - x = np.array(L_posteriori <= 0).astype(int) - - product = utils.incode(H, x) - - if product: - print(f'found, n_iter={n_iter}') - break - - if n_iter == maxiter - 1: - warnings.warn("""Decoding stopped before convergence. You may want - to increase maxiter""") - return x.squeeze() - - -output_type_log2 = types.Tuple((float64[:, :, :], float64[:, :, :], - float64[:, :])) - - -#@njit(output_type_log2(int64[:], int64[:], int64[:], int64[:], float64[:, :], -# float64[:, :, :], float64[:, :, :], int64), cache=True) -def _logbp_numba(bits_hist, bits_values, nodes_hist, nodes_values, Lc, Lq, Lr, - n_iter): - """Perform inner ext LogBP solver.""" - m, n, n_messages = Lr.shape - # step 1 : Horizontal - - bits_counter = 0 - nodes_counter = 0 - for i in range(m): - #print(f'=== i={i}') - ff = bits_hist[i] - ni = bits_values[bits_counter: bits_counter + ff] - bits_counter += ff - for j_iter, j in enumerate(ni): - nij = ni[:] - #print(f'\033[38;5;240mj={j:04d}', end=' ') - - X = np.ones(n_messages) - if n_iter == 0: - for kk in range(len(nij)): - if nij[kk] != j: - lcv = Lc[nij[kk],0] - lcc = '\033[91m' if lcv < 0 else ('\033[92m' if lcv > 0 else '\033[94m') - #print(f'nij={nij[kk]:04d} Lc={lcc}{lcv:> 8f}\033[38;5;240m', end=' ') - X *= np.tanh(0.5 * Lc[nij[kk]]) - else: - for kk in range(len(nij)): - if nij[kk] != j: - X *= np.tanh(0.5 * Lq[i, nij[kk]]) - #print(f'\n==== {i:03d} {j_iter:01d} {X[0]:> 8f}') - num = 1 + X - denom = 1 - X - for ll in range(n_messages): - if num[ll] == 0: - Lr[i, j, ll] = -1 - elif denom[ll] == 0: - Lr[i, j, ll] = 1 - else: - Lr[i, j, ll] = np.log(num[ll] / denom[ll]) - # step 2 : Vertical - - for j in range(n): - ff = nodes_hist[j] - mj = nodes_values[bits_counter: nodes_counter + ff] - nodes_counter += ff - for i in mj: - mji = mj[:] - Lq[i, j] = Lc[j] - - for kk in range(len(mji)): - if mji[kk] != i: - Lq[i, j] += Lr[mji[kk], j] - - # LLR a posteriori: - L_posteriori = np.zeros((n, n_messages)) - nodes_counter = 0 - for j in range(n): - ff = nodes_hist[j] - mj = nodes_values[bits_counter: nodes_counter + ff] - nodes_counter += ff - L_posteriori[j] = Lc[j] + Lr[mj, j].sum(axis=0) - - return Lq, Lr, L_posteriori - - -def get_message(tG, x): - """Compute the original `n_bits` message from a `n_code` codeword `x`. - - Parameters - ---------- - tG: array (n_code, n_bits) coding matrix tG. - x: array (n_code,) decoded codeword of length `n_code`. - - Returns - ------- - message: array (n_bits,). Original binary message. - - """ - n, k = tG.shape - - rtG, rx = utils.gausselimination(tG, x) - - message = np.zeros(k).astype(int) - - message[k - 1] = rx[k - 1] - for i in reversed(range(k - 1)): - message[i] = rx[i] - message[i] -= utils.binaryproduct(rtG[i, list(range(i+1, k))], - message[list(range(i+1, k))]) - - return abs(message) diff --git a/controller/fw/src/test_pyldpc_utils.py b/controller/fw/src/test_pyldpc_utils.py deleted file mode 100644 index 6b14532..0000000 --- a/controller/fw/src/test_pyldpc_utils.py +++ /dev/null @@ -1,182 +0,0 @@ -"""Conversion tools.""" -import math -import numbers -import numpy as np -import scipy -from scipy.stats import norm -pi = math.pi - - -def int2bitarray(n, k): - """Change an array's base from int (base 10) to binary (base 2).""" - binary_string = bin(n) - length = len(binary_string) - bitarray = np.zeros(k, 'int') - for i in range(length - 2): - bitarray[k - i - 1] = int(binary_string[length - i - 1]) - - return bitarray - - -def bitarray2int(bitarray): - """Change array's base from binary (base 2) to int (base 10).""" - bitstring = "".join([str(i) for i in bitarray]) - - return int(bitstring, 2) - - -def binaryproduct(X, Y): - """Compute a matrix-matrix / vector product in Z/2Z.""" - A = X.dot(Y) - try: - A = A.toarray() - except AttributeError: - pass - return A % 2 - - -def gaussjordan(X, change=0): - """Compute the binary row reduced echelon form of X. - - Parameters - ---------- - X: array (m, n) - change : boolean (default, False). If True returns the inverse transform - - Returns - ------- - if `change` == 'True': - A: array (m, n). row reduced form of X. - P: tranformations applied to the identity - else: - A: array (m, n). row reduced form of X. - - """ - A = np.copy(X) - m, n = A.shape - - if change: - P = np.identity(m).astype(int) - - pivot_old = -1 - for j in range(n): - filtre_down = A[pivot_old+1:m, j] - pivot = np.argmax(filtre_down)+pivot_old+1 - - if A[pivot, j]: - pivot_old += 1 - if pivot_old != pivot: - aux = np.copy(A[pivot, :]) - A[pivot, :] = A[pivot_old, :] - A[pivot_old, :] = aux - if change: - aux = np.copy(P[pivot, :]) - P[pivot, :] = P[pivot_old, :] - P[pivot_old, :] = aux - - for i in range(m): - if i != pivot_old and A[i, j]: - if change: - P[i, :] = abs(P[i, :]-P[pivot_old, :]) - A[i, :] = abs(A[i, :]-A[pivot_old, :]) - - if pivot_old == m-1: - break - - if change: - return A, P - return A - - -def binaryrank(X): - """Compute rank of a binary Matrix using Gauss-Jordan algorithm.""" - A = np.copy(X) - m, n = A.shape - - A = gaussjordan(A) - - return sum([a.any() for a in A]) - - -def f1(y, sigma): - """Compute normal density N(1,sigma).""" - f = norm.pdf(y, loc=1, scale=sigma) - return f - - -def fm1(y, sigma): - """Compute normal density N(-1,sigma).""" - - f = norm.pdf(y, loc=-1, scale=sigma) - return f - - -def bitsandnodes(H): - """Return bits and nodes of a parity-check matrix H.""" - if type(H) != scipy.sparse.csr_matrix: - bits_indices, bits = np.where(H) - nodes_indices, nodes = np.where(H.T) - else: - bits_indices, bits = scipy.sparse.find(H)[:2] - nodes_indices, nodes = scipy.sparse.find(H.T)[:2] - bits_histogram = np.bincount(bits_indices) - nodes_histogram = np.bincount(nodes_indices) - - return bits_histogram, bits, nodes_histogram, nodes - - -def incode(H, x): - """Compute Binary Product of H and x.""" - return (binaryproduct(H, x) == 0).all() - - -def gausselimination(A, b): - """Solve linear system in Z/2Z via Gauss Gauss elimination.""" - if type(A) == scipy.sparse.csr_matrix: - A = A.toarray().copy() - else: - A = A.copy() - b = b.copy() - n, k = A.shape - - for j in range(min(k, n)): - listedepivots = [i for i in range(j, n) if A[i, j]] - if len(listedepivots): - pivot = np.min(listedepivots) - else: - continue - if pivot != j: - aux = (A[j, :]).copy() - A[j, :] = A[pivot, :] - A[pivot, :] = aux - - aux = b[j].copy() - b[j] = b[pivot] - b[pivot] = aux - - for i in range(j+1, n): - if A[i, j]: - A[i, :] = abs(A[i, :]-A[j, :]) - b[i] = abs(b[i]-b[j]) - - return A, b - - -def check_random_state(seed): - """Turn seed into a np.random.RandomState instance - Parameters - ---------- - seed : None | int | instance of RandomState - If seed is None, return the RandomState singleton used by np.random. - If seed is an int, return a new RandomState instance seeded with seed. - If seed is already a RandomState instance, return it. - Otherwise raise ValueError. - """ - if seed is None or seed is np.random: - return np.random.mtrand._rand - if isinstance(seed, numbers.Integral): - return np.random.RandomState(seed) - if isinstance(seed, np.random.RandomState): - return seed - raise ValueError('%r cannot be used to seed a numpy.random.RandomState' - ' instance' % seed) diff --git a/controller/fw/src/tinyaes_adaptor.c b/controller/fw/src/tinyaes_adaptor.c deleted file mode 100644 index 2489e68..0000000 --- a/controller/fw/src/tinyaes_adaptor.c +++ /dev/null @@ -1,13 +0,0 @@ - -#include <stddef.h> -#include <string.h> - -void *memcpy(void *restrict dest, const void *restrict src, size_t n) { - unsigned char *d = dest; - const unsigned char *s = src; - - while (n--) - *d++ = *s++; - - return dest; -} diff --git a/controller/fw/stm32f407.ld b/controller/fw/stm32f407.ld deleted file mode 100644 index f998b4a..0000000 --- a/controller/fw/stm32f407.ld +++ /dev/null @@ -1,148 +0,0 @@ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K - RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K - CCMRAM (rwx) : ORIGIN = 0x10000000, LENGTH = 64K - BACKUP (rwx) : ORIGIN = 0x40024000, LENGTH = 4K -} - -/* Entry Point */ -ENTRY(Reset_Handler) - -/* Highest address of the user mode stack */ -_estack = 0x20020000; /* end of RAM */ -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0x200;; /* required amount of heap */ -_Min_Stack_Size = 0x400;; /* required amount of stack */ - -/* Define output sections */ -SECTIONS -{ - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - /* Constant data goes into FLASH */ - .rodata : - { - . = ALIGN(4); - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - . = ALIGN(4); - } >FLASH - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT(.fini_array.*))) - KEEP (*(.fini_array*)) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = LOADADDR(.data); - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM AT> FLASH - - _siccmram = LOADADDR(.ccmram); - - /* CCM-RAM section - * - * IMPORTANT NOTE! - * If initialized variables will be placed in this section, - * the startup code needs to be modified to copy the init-values. - */ - .ccmram : - { - . = ALIGN(4); - _sccmram = .; /* create a global symbol at ccmram start */ - *(.ccmram) - *(.ccmram*) - - . = ALIGN(4); - _eccmram = .; /* create a global symbol at ccmram end */ - } >CCMRAM AT> FLASH - - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss secion */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(4); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(4); - } >RAM - - .ARM.attributes 0 : { *(.ARM.attributes) } -} - - diff --git a/controller/fw/tinyaes b/controller/fw/tinyaes deleted file mode 160000 -Subproject 3fe133ffa32606b0d0d81e0ba1d8bacb392eb7e diff --git a/controller/fw/tinyprintf b/controller/fw/tinyprintf deleted file mode 160000 -Subproject 2ee30120ec15e321566b43f83c731d060bb437f diff --git a/controller/fw/tools/butter_filter_gen.py b/controller/fw/tools/butter_filter_gen.py deleted file mode 100644 index 0bb81bc..0000000 --- a/controller/fw/tools/butter_filter_gen.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python3 - -import math -import sys -import contextlib - -import scipy.signal as sig -import numpy as np - - -@contextlib.contextmanager -def wrap(left='{', right='}', file=None, end=''): - print(left, file=file, end=end) - yield - print(right, file=file, end=end) - -@contextlib.contextmanager -def print_include_guards(macro_name): - print(f'#ifndef {macro_name}') - print(f'#define {macro_name}') - print() - yield - print() - print(f'#endif /* {macro_name} */') - -macro_float = lambda f: f'{f}'.replace('.', 'F').replace('-', 'N').replace('+', 'P') - -ordinal = lambda n: "%d%s" % (n,"tsnrhtdd"[(n//10%10!=1)*(n%10<4)*n%10::4]) - -SI_TABLE = {-18: 'a', -15: 'f', -12: 'p', -9: 'n', -6: 'µ', -3: 'm', 0: '', 3: 'k', 6: 'M', 9: 'G', 12: 'T', 15: 'P', 18: 'E'} -def siprefix(x, space=' ', unit=''): - l = math.log10(x)//3*3 - if l in SI_TABLE: - return f'{x/10**l}{space}{SI_TABLE[l]}{unit}' - return f'{x}{space}{unit}' - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser() - parser.add_argument('-m', '--macro-name', default='butter_filter', help='Prefix for output macro names') - parser.add_argument('fc', type=float, help='Corner frequency [Hz]') - parser.add_argument('fs', type=float, help='Sampling rate [Hz]') - parser.add_argument('n', type=int, nargs='?', default=6, help='Filter order') - args = parser.parse_args() - - sos = sig.butter(args.n, args.fc, fs=args.fs, output='sos') - - print('/* THIS IS A GENERATED FILE. DO NOT EDIT! */') - print() - with print_include_guards(f'__BUTTER_FILTER_GENERATED_{args.n}_{macro_float(args.fc)}_{macro_float(args.fs)}__'): - - print(f'/* {ordinal(args.n)} order Butterworth IIR filter coefficients') - print(f' *') - print(f' * corner frequency f_c = {siprefix(args.fc)}Hz') - print(f' * sampling rate f_s = {siprefix(args.fs)}Hz') - print(f' */') - print() - print(f'#define {args.macro_name.upper()}_ORDER {args.n}') - print(f'#define {args.macro_name.upper()}_CLEN {(args.n+1)//2}') - - # scipy.signal.butter by default returns extremely small bs for the first biquad and large ones for subsequent - # sections. Balance magnitudes to reduce possible rounding errors. - first_biquad_bs = sos[0][:3] - approx_mag = round(math.log10(np.mean(first_biquad_bs))) - mags = [approx_mag // len(sos)] * len(sos) - mags[0] += approx_mag - sum(mags) - sos[0][:3] /= 10**approx_mag - sos = np.array([ sec * np.array([10**mag, 10**mag, 10**mag, 1, 1, 1]) for mag, sec in zip(mags, sos) ]) - - ones = np.ones([100000]) - _, steady_state = sig.sosfilt(sos, ones, zi=np.zeros([(args.n+1)//2, 2])) - - print(f'#define {args.macro_name.upper()}_COEFF ', end='') - for sec in sos: - bs, ases = sec[:3], sec[4:6] - - with wrap(): - print('.b=', end='') - with wrap(): - print(', '.join(f'{v}' for v in bs), end='') - print(', .a=', end='') - with wrap(): - print(', '.join(f'{v}' for v in ases), end='') - print(', ', end='') - print() - - print(f'#define {args.macro_name.upper()}_STEADY_STATE ', end='') - for sec in steady_state: - with wrap(): - print(', '.join(f'{v}' for v in sec), end='') - print(', ', end='') - print() - diff --git a/controller/fw/tools/crypto_test.c b/controller/fw/tools/crypto_test.c deleted file mode 100644 index 410fac2..0000000 --- a/controller/fw/tools/crypto_test.c +++ /dev/null @@ -1,46 +0,0 @@ - -#include <stdint.h> -#include <math.h> -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/fcntl.h> - -#include "crypto.h" - -void oob_trigger_activated(enum trigger_domain domain, int serial) { - printf("oob_trigger_activated(%d, %d)\n", domain, serial); - fflush(stdout); -} - -void print_usage() { - fprintf(stderr, "Usage: crypto_test [auth_key_hex]\n"); -} - -int main(int argc, char **argv) { - if (argc != 2) { - fprintf(stderr, "Error: Invalid arguments.\n"); - print_usage(); - return 1; - } - - uint8_t auth_key[16]; - - for (size_t i=0; argv[1][i+0] != '\0' && argv[1][i+1] != '\0' && i/2<sizeof(auth_key); i+= 2) { - char buf[3] = { argv[1][i+0], argv[1][i+1], 0}; - char *endptr; - auth_key[i/2] = strtoul(buf, &endptr, 16); - if (!endptr || *endptr != '\0') { - fprintf(stderr, "Invalid authkey\n"); - return 1; - } - } - - printf("rc=%d\n", oob_message_received(auth_key)); - - return 0; -} diff --git a/controller/fw/tools/crypto_test_runner.py b/controller/fw/tools/crypto_test_runner.py deleted file mode 100644 index 34c8b59..0000000 --- a/controller/fw/tools/crypto_test_runner.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python3 -import subprocess -from os import path -import binascii -import re - -import presig_gen - -def do_test(domain, value, height, root_key, binary, expect_fail=False): - auth = presig_gen.gen_at_height(domain, value, height, root_key) - auth = binascii.hexlify(auth).decode() - - output = subprocess.check_output([binary, auth]) - *lines, rc_line = output.decode().splitlines() - rc = int(re.match('^rc=(\d+)$', rc_line).group(1)) - assert expect_fail == (rc == 0) - -def run_tests(root_key, max_height, binary): - for domain, value in { - 'all': 'all', - 'vendor': presig_gen.TEST_VENDOR, - 'series': presig_gen.TEST_SERIES, - 'country': presig_gen.TEST_COUNTRY, - 'region': presig_gen.TEST_REGION, - }.items(): - for height in range(max_height): - do_test(domain, value, height, root_key, binary) - do_test(domain, 'fail', height, root_key, binary, expect_fail=True) - do_test('fail', 'fail', height, root_key, binary, expect_fail=True) - do_test('', '', height, root_key, binary, expect_fail=True) - do_test(domain, value, max_height, root_key, binary, expect_fail=True) - do_test(domain, value, max_height+1, root_key, binary, expect_fail=True) - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser() - parser.add_argument('keyfile', help='Root key file') - parser.add_argument('max_height', type=int, default=8, nargs='?', help='Height of generated prekeys') - default_binary = path.abspath(path.join(path.dirname(__file__), '../build/tools/crypto_test')) - parser.add_argument('binary', default=default_binary, nargs='?', help='crypto_test binary to use') - args = parser.parse_args() - - with open(args.keyfile, 'r') as f: - root_key = binascii.unhexlify(f.read().strip()) - - run_tests(root_key, args.max_height, args.binary) diff --git a/controller/fw/tools/cwt_wavelet_header_gen.py b/controller/fw/tools/cwt_wavelet_header_gen.py deleted file mode 100644 index 8be785b..0000000 --- a/controller/fw/tools/cwt_wavelet_header_gen.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python3 - -import textwrap - -import scipy.signal as sig -import numpy as np - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser() - parser.add_argument('n', type=int, help='Window size') - parser.add_argument('w', type=float, help='Wavelet width') - parser.add_argument('-v', '--variable', default='cwt_ricker_table', help='Name for alias variable pointing to generated wavelet LUT') - args = parser.parse_args() - - print(f'/* CWT Ricker wavelet LUT for {args.n} sample window of width {args.w}. */') - varname = f'cwt_ricker_{args.n}_window_{str(args.w).replace(".", "F")}' - print(f'const float {varname}[{args.n}] = {{') - - win = sig.ricker(args.n, args.w) - par = ' '.join(f'{f:>015.12e}f,' for f in win) - print(textwrap.fill(par, - initial_indent=' '*4, subsequent_indent=' '*4, - width=120, - replace_whitespace=False, drop_whitespace=False)) - print('};') - print() - print(f'const float * const {args.variable} __attribute__((weak)) = {varname};') - diff --git a/controller/fw/tools/dsss_demod_test.c b/controller/fw/tools/dsss_demod_test.c deleted file mode 100644 index f7df111..0000000 --- a/controller/fw/tools/dsss_demod_test.c +++ /dev/null @@ -1,109 +0,0 @@ - -#include <stdint.h> -#include <math.h> -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/fcntl.h> - -#include "dsss_demod.h" - -void handle_dsss_received(symbol_t data[static TRANSMISSION_SYMBOLS]) { - printf("data sequence received: [ "); - for (size_t i=0; i<TRANSMISSION_SYMBOLS; i++) { - //printf("%+3d", ((data[i]&1) ? 1 : -1) * (data[i]>>1)); - printf("%2d", data[i]); - if (i+1 < TRANSMISSION_SYMBOLS) - printf(", "); - } - printf(" ]\n"); -} - -void print_usage() { - fprintf(stderr, "Usage: dsss_demod_test [test_data.bin] [optional recording channel number]\n"); -} - -int main(int argc, char **argv) { - if (argc != 2 && argc != 3) { - fprintf(stderr, "Error: Invalid arguments.\n"); - print_usage(); - return 1; - } - - int fd = open(argv[1], O_RDONLY); - struct stat st; - if (fstat(fd, &st)) { - fprintf(stderr, "Error querying test data file size: %s\n", strerror(errno)); - return 2; - } - - if (st.st_size < 0 || st.st_size > 10000000) { - fprintf(stderr, "Error reading test data: too much test data (size=%zd)\n", st.st_size); - return 2; - } - - if (st.st_size % sizeof(float) != 0) { - fprintf(stderr, "Error reading test data: file size is not divisible by %zd (size=%zd)\n", sizeof(float), st.st_size); - return 2; - } - - char *buf = malloc(st.st_size); - if (!buf) { - fprintf(stderr, "Error allocating memory"); - return 2; - } - - int record_channel = -1; - if (argc == 3) { - char *endptr; - record_channel = strtoul(argv[2], &endptr, 10); - if (!endptr || *endptr != '\0') { - fprintf(stderr, "Invalid channel number \"%s\"\n", argv[2]); - return 1; - } - } - - if (record_channel != -1) - fprintf(stderr, "Reading %zd samples test data...", st.st_size/sizeof(float)); - ssize_t nread = 0; - while (nread < st.st_size) { - ssize_t rc = read(fd, buf + nread, st.st_size - nread); - - if (rc == -EINTR || rc == -EAGAIN) - continue; - - if (rc < 0) { - fprintf(stderr, "\nError reading test data: %s\n", strerror(errno)); - return 2; - } - - if (rc == 0) { - fprintf(stderr, "\nError reading test data: Unexpected end of file\n"); - return 2; - } - - nread += rc; - } - if (record_channel != -1) - fprintf(stderr, " done.\n"); - - const size_t n_samples = st.st_size / sizeof(float); - float *buf_f = (float *)buf; - - if (record_channel != -1) - fprintf(stderr, "Starting simulation.\n"); - - struct dsss_demod_state demod; - dsss_demod_init(&demod); - for (size_t i=0; i<n_samples; i++) { - //fprintf(stderr, "Iteration %zd/%zd\n", i, n_samples); - dsss_demod_step(&demod, buf_f[i], i); - } - - free(buf); - return 0; -} diff --git a/controller/fw/tools/dsss_demod_test_runner.py b/controller/fw/tools/dsss_demod_test_runner.py deleted file mode 100644 index d3c3cfc..0000000 --- a/controller/fw/tools/dsss_demod_test_runner.py +++ /dev/null @@ -1,241 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -from os import path -import subprocess -import json -from collections import namedtuple, defaultdict -from tqdm import tqdm -import uuid -import multiprocessing -import sqlite3 -import time -from urllib.parse import urlparse -import tempfile -import itertools - -import numpy as np -np.set_printoptions(linewidth=240) - -from dsss_demod_test_waveform_gen import load_noise_gen, modulate as dsss_modulate - - -def build_test_binary(nbits, thf, decimation, symbols, cachedir): - build_id = str(uuid.uuid4()) - builddir = path.join(cachedir, build_id) - os.mkdir(builddir) - - cwd = path.join(path.dirname(__file__), '..') - - env = os.environ.copy() - env['BUILDDIR'] = path.abspath(builddir) - env['DSSS_GOLD_CODE_NBITS'] = str(nbits) - env['DSSS_DECIMATION'] = str(decimation) - env['DSSS_THRESHOLD_FACTOR'] = str(thf) - env['DSSS_WAVELET_WIDTH'] = str(0.73 * decimation) - env['DSSS_WAVELET_LUT_SIZE'] = str(10 * decimation) - env['TRANSMISSION_SYMBOLS'] = str(symbols) - - with open(path.join(builddir, 'make_stdout.txt'), 'w') as stdout,\ - open(path.join(builddir, 'make_stderr.txt'), 'w') as stderr: - subprocess.run(['make', 'clean', os.path.abspath(path.join(builddir, 'tools/dsss_demod_test'))], - env=env, cwd=cwd, check=True, stdout=stdout, stderr=stderr) - - return build_id - -def sequence_matcher(test_data, decoded, max_shift=3): - match_result = [] - for shift in range(-max_shift, max_shift): - failures = -shift if shift < 0 else 0 # we're skipping the first $shift symbols - a = test_data if shift > 0 else test_data[-shift:] - b = decoded if shift < 0 else decoded[shift:] - for i, (ref, found) in enumerate(itertools.zip_longest(a, b)): - if ref is None: # end of signal - break - if ref != found: - failures += 1 - match_result.append(failures) - failures = min(match_result) - return failures/len(test_data) - -ResultParams = namedtuple('ResultParams', ['nbits', 'thf', 'decimation', 'symbols', 'seed', 'amplitude', 'background']) - -def run_test(seed, amplitude_spec, background, nbits, decimation, symbols, thfs, lookup_binary, cachedir): - noise_gen, noise_params = load_noise_gen(background) - - test_data = np.random.RandomState(seed=seed).randint(0, 2 * (2**nbits), symbols) - - signal = np.repeat(dsss_modulate(test_data, nbits) * 2.0 - 1, decimation) - # We're re-using the seed here. This is not a problem. - noise = noise_gen(seed, len(signal), *noise_params) - amplitudes = amplitude_spec[0] * 10 ** np.linspace(0, amplitude_spec[1], amplitude_spec[2]) - # DEBUG - my_pid = multiprocessing.current_process().pid - wql = len(amplitudes) * len(thfs) - print(f'[{my_pid}] starting, got workqueue of length {wql}') - i = 0 - # Map lsb to sign to match test program - # test_data = (test_data>>1) * (2*(test_data&1) - 1) - # END DEBUG - - output = [] - for amp in amplitudes: - with tempfile.NamedTemporaryFile(dir=cachedir) as f: - waveform = signal*amp + noise - f.write(waveform.astype('float32').tobytes()) - f.flush() - # DEBUG - fcopy = f'/tmp/test-{path.basename(f.name)}' - import shutil - shutil.copy(f.name, fcopy) - # END DEBUG - - for thf in thfs: - rpars = ResultParams(nbits, thf, decimation, symbols, seed, amp, background) - cmdline = [lookup_binary(nbits, thf, decimation, symbols), f.name] - # DEBUG - starttime = time.time() - # END DEBUG - try: - proc = subprocess.run(cmdline, stdout=subprocess.PIPE, encoding='utf-8', check=True, timeout=300) - - lines = proc.stdout.splitlines() - matched = [ l.partition('[')[2].partition(']')[0] - for l in lines if l.strip().startswith('data sequence received:') ] - matched = [ [ int(elem) for elem in l.split(',') ] for l in matched ] - - ser = min(sequence_matcher(test_data, match) for match in matched) if matched else None - output.append((rpars, ser)) - # DEBUG - #print(f'[{my_pid}] ran {i}/{wql}: time={time.time() - starttime}\n {ser=}\n {rpars}\n {" ".join(cmdline)}\n {fcopy}', flush=True) - i += 1 - # END DEBUG - - except subprocess.TimeoutExpired: - output.append((rpars, None)) - # DEBUG - print(f'[{my_pid}] ran {i}/{wql}: Timeout!\n {rpars}\n {" ".join(cmdline)}\n {fcopy}', flush=True) - i += 1 - # END DEBUG - print(f'[{my_pid}] finished.') - return output - -def parallel_generator(db, table, columns, builder, param_list, desc, context={}, params_mapper=lambda *args: args, - disable_cache=False): - with multiprocessing.Pool(multiprocessing.cpu_count()) as pool: - with db as conn: - jobs = [] - for params in param_list: - found_res = conn.execute( - f'SELECT result FROM {table} WHERE ({",".join(columns)}) = ({",".join("?"*len(columns))})', - params_mapper(*params)).fetchone() - - if found_res and not disable_cache: - yield params, json.loads(*found_res) - - else: - jobs.append((params, pool.apply_async(builder, params, context))) - - pool.close() - print('Using', len(param_list) - len(jobs), 'cached jobs', flush=True) - with tqdm(total=len(jobs), desc=desc) as tq: - for i, (params, res) in enumerate(jobs): - # DEBUG - print('Got result', i, params, res) - # END DEBUG - tq.update(1) - result = res.get() - with db as conn: - conn.execute(f'INSERT INTO {table} VALUES ({"?,"*len(params)}?,?)', - (*params_mapper(*params), json.dumps(result), timestamp())) - yield params, result - pool.join() - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser() - parser.add_argument('-d', '--dump', help='Write results to JSON file') - parser.add_argument('-c', '--cachedir', default='dsss_test_cache', help='Directory to store build output and data in') - parser.add_argument('-n', '--no-cache', action='store_true', help='Disable result cache') - parser.add_argument('-b', '--batches', type=int, default=1, help='Number of batches to split the computation into') - parser.add_argument('-i', '--index', type=int, default=0, help='Batch index to compute') - parser.add_argument('-p', '--prepare', action='store_true', help='Prepare mode: compile runners, then exit.') - args = parser.parse_args() - - DecoderParams = namedtuple('DecoderParams', ['nbits', 'thf', 'decimation', 'symbols']) -# dec_paramses = [ DecoderParams(nbits=nbits, thf=thf, decimation=decimation, symbols=20) -# for nbits in [5, 6] -# for thf in [4.5, 4.0, 5.0] -# for decimation in [10, 5, 22] ] - dec_paramses = [ DecoderParams(nbits=nbits, thf=thf, decimation=decimation, symbols=100) - for nbits in [5, 6] - for thf in [3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0] - for decimation in [1, 2, 3, 4, 5, 6, 9, 10, 11, 12, 16, 22, 30, 40, 50] ] -# dec_paramses = [ DecoderParams(nbits=nbits, thf=thf, decimation=decimation, symbols=100) -# for nbits in [5, 6, 7, 8] -# for thf in [1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0] -# for decimation in [1, 2, 3, 4, 5, 6, 9, 10, 11, 12, 16, 22, 30, 40, 50] ] - - build_cache_dir = path.join(args.cachedir, 'builds') - data_cache_dir = path.join(args.cachedir, 'data') - os.makedirs(build_cache_dir, exist_ok=True) - os.makedirs(data_cache_dir, exist_ok=True) - - build_db = sqlite3.connect(path.join(args.cachedir, 'build_db.sqlite3')) - build_db.execute('CREATE TABLE IF NOT EXISTS builds (nbits, thf, decimation, symbols, result, timestamp)') - timestamp = lambda: int(time.time()*1000) - - builds = dict(parallel_generator(build_db, table='builds', columns=['nbits', 'thf', 'decimation', 'symbols'], - builder=build_test_binary, param_list=dec_paramses, desc='Building decoders', - context=dict(cachedir=build_cache_dir))) - print('Done building decoders.') - if args.prepare: - sys.exit(0) - - GeneratorParams = namedtuple('GeneratorParams', ['seed', 'amplitude_spec', 'background']) - gen_params = [ GeneratorParams(rep, (5e-3, 1, 5), background) - #GeneratorParams(rep, (0.05e-3, 3.5, 50), background) - for rep in range(50) - for background in ['meas://fmeas_export_ocxo_2day.bin', 'synth://grid_freq_psd_spl_108pt.json'] ] -# gen_params = [ GeneratorParams(rep, (5e-3, 1, 5), background) -# for rep in range(1) -# for background in ['meas://fmeas_export_ocxo_2day.bin'] ] - - data_db = sqlite3.connect(path.join(args.cachedir, 'data_db.sqlite3')) - data_db.execute('CREATE TABLE IF NOT EXISTS waveforms' - '(seed, amplitude_spec, background, nbits, decimation, symbols, thresholds, result, timestamp)') - - 'SELECT FROM waveforms GROUP BY (amplitude_spec, background, nbits, decimation, symbols, thresholds, result)' - - dec_param_groups = defaultdict(lambda: []) - for nbits, thf, decimation, symbols in dec_paramses: - dec_param_groups[(nbits, decimation, symbols)].append(thf) - waveform_params = [ (*gp, *dp, thfs) for gp in gen_params for dp, thfs in dec_param_groups.items() ] - print(f'Generated {len(waveform_params)} parameter sets') - - # Separate out our batch - waveform_params = waveform_params[args.index::args.batches] - - def lookup_binary(*params): - return path.join(build_cache_dir, builds[tuple(params)], 'tools/dsss_demod_test') - - def params_mapper(seed, amplitude_spec, background, nbits, decimation, symbols, thresholds): - amplitude_spec = ','.join(str(x) for x in amplitude_spec) - thresholds = ','.join(str(x) for x in thresholds) - return seed, amplitude_spec, background, nbits, decimation, symbols, thresholds - - results = [] - for _params, chunk in parallel_generator(data_db, 'waveforms', - ['seed', 'amplitude_spec', 'background', 'nbits', 'decimation', 'symbols', 'thresholds'], - params_mapper=params_mapper, - builder=run_test, - param_list=waveform_params, desc='Simulating demodulation', - context=dict(cachedir=data_cache_dir, lookup_binary=lookup_binary), - disable_cache=args.no_cache): - results += chunk - - if args.dump: - with open(args.dump, 'w') as f: - json.dump(results, f) - diff --git a/controller/fw/tools/dsss_demod_test_waveform_gen.py b/controller/fw/tools/dsss_demod_test_waveform_gen.py deleted file mode 100644 index 414c553..0000000 --- a/controller/fw/tools/dsss_demod_test_waveform_gen.py +++ /dev/null @@ -1,86 +0,0 @@ - -from os import path -import json -import functools - -import numpy as np -import numbers -import math -from scipy import signal as sig -import scipy.fftpack - -sampling_rate = 10 # sp/s - -# From https://github.com/mubeta06/python/blob/master/signal_processing/sp/gold.py -preferred_pairs = {5:[[2],[1,2,3]], 6:[[5],[1,4,5]], 7:[[4],[4,5,6]], - 8:[[1,2,3,6,7],[1,2,7]], 9:[[5],[3,5,6]], - 10:[[2,5,9],[3,4,6,8,9]], 11:[[9],[3,6,9]]} - -def gen_gold(seq1, seq2): - gold = [seq1, seq2] - for shift in range(len(seq1)): - gold.append(seq1 ^ np.roll(seq2, -shift)) - return gold - -def gold(n): - n = int(n) - if not n in preferred_pairs: - raise KeyError('preferred pairs for %s bits unknown' % str(n)) - t0, t1 = preferred_pairs[n] - (seq0, _st0), (seq1, _st1) = sig.max_len_seq(n, taps=t0), sig.max_len_seq(n, taps=t1) - return gen_gold(seq0, seq1) - -def modulate(data, nbits=5): - # 0, 1 -> -1, 1 - mask = np.array(gold(nbits))*2 - 1 - - sel = mask[data>>1] - data_lsb_centered = ((data&1)*2 - 1) - - signal = (np.multiply(sel, np.tile(data_lsb_centered, (2**nbits-1, 1)).T).flatten() + 1) // 2 - return np.hstack([ np.zeros(len(mask)), signal, np.zeros(len(mask)) ]) - -def load_noise_meas_params(capture_file): - with open(capture_file, 'rb') as f: - meas_data = np.copy(np.frombuffer(f.read(), dtype='float32')) - meas_data -= np.mean(meas_data) - return (meas_data,) - -def mains_noise_measured(seed, n, meas_data): - last_valid = len(meas_data) - n - st = np.random.RandomState(seed) - start = st.randint(last_valid) - return meas_data[start:start+n] + 50.00 - -def load_noise_synth_params(specfile): - with open(specfile) as f: - d = json.load(f) - return {'spl_x': np.linspace(*d['x_spec']), - 'spl_N': d['x_spec'][2], - 'psd_spl': (d['t'], d['c'], d['k']) } - -def mains_noise_synthetic(seed, n, psd_spl, spl_N, spl_x): - st = np.random.RandomState(seed) - noise = st.normal(size=spl_N) * 2 - spec = scipy.fftpack.fft(noise) **2 - - spec *= np.exp(scipy.interpolate.splev(spl_x, psd_spl)) - - spec **= 1/2 - - renoise = scipy.fftpack.ifft(spec) - return renoise[10000:][:n] + 50.00 - -@functools.lru_cache() -def load_noise_gen(url): - schema, refpath = url.split('://') - if not path.isabs(refpath): - refpath = path.abspath(path.join(path.dirname(__file__), refpath)) - - if schema == 'meas': - return mains_noise_measured, load_noise_meas_params(refpath) - elif schema == 'synth': - return mains_noise_synthetic, load_noise_synth_params(refpath) - else: - raise ValueError('Invalid schema', schema) - diff --git a/controller/fw/tools/e2e_test.c b/controller/fw/tools/e2e_test.c deleted file mode 100644 index 935f70d..0000000 --- a/controller/fw/tools/e2e_test.c +++ /dev/null @@ -1,111 +0,0 @@ - -#include <stdint.h> -#include <math.h> -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/fcntl.h> - -#include "freq_meas.h" -#include "dsss_demod.h" - -typedef uint16_t adc_data_t; - -void handle_dsss_received(uint8_t data[static TRANSMISSION_SYMBOLS]) { - printf("data sequence received: [ "); - for (size_t i=0; i<TRANSMISSION_SYMBOLS; i++) { - printf("%+3d", ((data[i]&1) ? 1 : -1) * (data[i]>>1)); - if (i+1 < TRANSMISSION_SYMBOLS) - printf(", "); - } - printf(" ]\n"); -} - -void print_usage(void); -void print_usage() { - fprintf(stderr, "Usage: e2e_test [emulated_adc_data.bin]\n"); -} - -int main(int argc, char **argv) { - if (argc != 2) { - fprintf(stderr, "Error: Invalid arguments.\n"); - print_usage(); - return 1; - } - - int fd = open(argv[1], O_RDONLY); - struct stat st; - if (fstat(fd, &st)) { - fprintf(stderr, "Error querying test data file size: %s\n", strerror(errno)); - return 2; - } - - if (st.st_size < 0 || st.st_size > 100000000) { - fprintf(stderr, "Error reading test data: too much test data (size=%zd)\n", st.st_size); - return 2; - } - - if (st.st_size % sizeof(adc_data_t) != 0) { - fprintf(stderr, "Error reading test data: file size is not divisible by %zd (size=%zd)\n", sizeof(adc_data_t), st.st_size); - return 2; - } - - char *buf = malloc(st.st_size); - if (!buf) { - fprintf(stderr, "Error allocating memory"); - return 2; - } - - const size_t n_samples = st.st_size / sizeof(adc_data_t); - fprintf(stderr, "Reading %zd samples test data...", n_samples); - ssize_t nread = 0; - while (nread < st.st_size) { - ssize_t rc = read(fd, buf + nread, st.st_size - nread); - - if (rc == -EINTR || rc == -EAGAIN) - continue; - - if (rc < 0) { - fprintf(stderr, "\nError reading test data: %s\n", strerror(errno)); - return 2; - } - - if (rc == 0) { - fprintf(stderr, "\nError reading test data: Unexpected end of file\n"); - return 2; - } - - nread += rc; - } - fprintf(stderr, " done. Read %zd bytes.\n", nread); - - adc_data_t *buf_d = (adc_data_t *)buf; - - struct dsss_demod_state demod; - dsss_demod_init(&demod); - - fprintf(stderr, "Starting simulation.\n"); - size_t iterations = (n_samples-FMEAS_FFT_LEN)/(FMEAS_FFT_LEN/2); - for (size_t i=0; i<iterations; i++) { - - /* - fprintf(stderr, "Iteration %zd/%zd\n", i, iterations); - */ - float res = NAN; - int rc = adc_buf_measure_freq(buf_d + i*(FMEAS_FFT_LEN/2), &res); - if (rc) - printf("ERROR: Simulation error in iteration %zd at position %zd: %d\n", i, i*(FMEAS_FFT_LEN/2), rc); - - dsss_demod_step(&demod, res, i); - /* - printf("%09zd %12f\n", i, res); - */ - } - - free(buf); - return 0; -} diff --git a/controller/fw/tools/fft_window_header_gen.py b/controller/fw/tools/fft_window_header_gen.py deleted file mode 100644 index 7df2ee3..0000000 --- a/controller/fw/tools/fft_window_header_gen.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python3 - -import textwrap - -import scipy.signal as sig -import numpy as np - -WINDOW_TYPES = [ - 'boxcar', - 'triang', - 'blackman', - 'hamming', - 'hann', - 'bartlett', - 'flattop', - 'parzen', - 'bohman', - 'blackmanharris', - 'nuttall', - 'barthann', - 'kaiser', - 'gaussian', - 'general_gaussian', - 'slepian', - 'dpss', - 'chebwin', - 'exponential', - 'tukey', - ] - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser() - parser.add_argument('window', choices=WINDOW_TYPES, help='Type of window function to use') - parser.add_argument('n', type=int, help='Width of window in samples') - parser.add_argument('window_args', nargs='*', type=float, - help='''Window argument(s) if required. See https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.get_window.html#scipy.signal.get_window for details.''') - parser.add_argument('-v', '--variable', default='fft_window_table', help='Name for alias variable pointing to generated window') - args = parser.parse_args() - - print(f'/* FTT window table for {args.n} sample {args.window} window.') - if args.window_args: - print(f' * Window arguments were: ({" ,".join(str(arg) for arg in args.window_args)})') - print(f' */') - winargs = ''.join(f'_{arg:.4g}'.replace('.', 'F') for arg in args.window_args) - varname = f'fft_{args.n}_window_{args.window}{winargs}' - print(f'const float {varname}[{args.n}] = {{') - - win = sig.get_window(args.window if not args.window_args else (args.window, *args.window_args), - Nx=args.n, fftbins=True) - par = ' '.join(f'{f:>013.8g},' for f in win) - print(textwrap.fill(par, - initial_indent=' '*4, subsequent_indent=' '*4, - width=120, - replace_whitespace=False, drop_whitespace=False)) - print('};') - print() - print(f'const float * const {args.variable} __attribute__((weak)) = {varname};') - diff --git a/controller/fw/tools/fmeas_export_ocxo_2day.bin b/controller/fw/tools/fmeas_export_ocxo_2day.bin Binary files differdeleted file mode 100644 index c0cd8a8..0000000 --- a/controller/fw/tools/fmeas_export_ocxo_2day.bin +++ /dev/null diff --git a/controller/fw/tools/freq_meas_test.c b/controller/fw/tools/freq_meas_test.c deleted file mode 100644 index e2900ad..0000000 --- a/controller/fw/tools/freq_meas_test.c +++ /dev/null @@ -1,106 +0,0 @@ - -#include <stdint.h> -#include <math.h> -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/fcntl.h> - -#include "freq_meas.h" - -void print_usage(void); - -void print_usage() { - fprintf(stderr, "Usage: freq_meas_test [test_data.bin]\n"); -} - -int main(int argc, char **argv) { - if (argc != 2) { - fprintf(stderr, "Error: Invalid arguments.\n"); - print_usage(); - return 1; - } - - int fd = open(argv[1], O_RDONLY); - struct stat st; - if (fstat(fd, &st)) { - fprintf(stderr, "Error querying test data file size: %s\n", strerror(errno)); - return 2; - } - - if (st.st_size < 0 || st.st_size > 1000000) { - fprintf(stderr, "Error reading test data: too much test data (size=%zd)\n", st.st_size); - return 2; - } - - if (st.st_size % sizeof(float) != 0) { - fprintf(stderr, "Error reading test data: file size is not divisible by %zd (size=%zd)\n", sizeof(float), st.st_size); - return 2; - } - - char *buf = malloc(st.st_size); - if (!buf) { - fprintf(stderr, "Error allocating memory"); - return 2; - } - - fprintf(stderr, "Reading %zd samples test data...", st.st_size/sizeof(float)); - ssize_t nread = 0; - while (nread < st.st_size) { - ssize_t rc = read(fd, buf + nread, st.st_size - nread); - - if (rc == -EINTR || rc == -EAGAIN) - continue; - - if (rc < 0) { - fprintf(stderr, "\nError reading test data: %s\n", strerror(errno)); - return 2; - } - - if (rc == 0) { - fprintf(stderr, "\nError reading test data: Unexpected end of file\n"); - return 2; - } - - nread += rc; - } - fprintf(stderr, " done.\n"); - - const size_t n_samples = st.st_size / sizeof(float); - float *buf_f = (float *)buf; - - int16_t *sim_adc_buf = calloc(sizeof(int16_t), n_samples); - if (!sim_adc_buf) { - fprintf(stderr, "Error allocating memory\n"); - return 2; - } - - fprintf(stderr, "Converting and truncating test data..."); - for (size_t i=0; i<n_samples; i++) - /* Note on scaling: We can't simply scale by 0x8000 (1/2 full range) here. Our test data is nominally 1Vp-p but - * certain tests such as the interharmonics one can have some samples exceeding that range. */ - sim_adc_buf[i] = buf_f[i] * (0x4000-1); - fprintf(stderr, " done.\n"); - - fprintf(stderr, "Starting simulation.\n"); - - size_t iterations = (n_samples-FMEAS_FFT_LEN)/(FMEAS_FFT_LEN/2); - for (size_t i=0; i<iterations; i++) { - - fprintf(stderr, "Iteration %zd/%zd\n", i, iterations); - float res = NAN; - int rc = adc_buf_measure_freq(sim_adc_buf + i*(FMEAS_FFT_LEN/2), &res); - if (rc) - printf("ERROR: Simulation error in iteration %zd at position %zd: %d\n", i, i*(FMEAS_FFT_LEN/2), rc); - - printf("%09zd %12f\n", i, res); - } - - free(buf); - free(sim_adc_buf); - return 0; -} diff --git a/controller/fw/tools/freq_meas_test_runner.py b/controller/fw/tools/freq_meas_test_runner.py deleted file mode 100644 index 779922a..0000000 --- a/controller/fw/tools/freq_meas_test_runner.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python3 - -import os -from os import path -import subprocess -import json - -import numpy as np -np.set_printoptions(linewidth=240) - - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser() - parser.add_argument(metavar='test_data_directory', dest='dir', help='Directory with test data .bin files') - default_binary = path.abspath(path.join(path.dirname(__file__), '../build/tools/freq_meas_test')) - parser.add_argument(metavar='test_binary', dest='binary', nargs='?', default=default_binary) - parser.add_argument('-d', '--dump', help='Write raw measurements to JSON file') - args = parser.parse_args() - - bin_files = [ path.join(args.dir, d) for d in os.listdir(args.dir) if d.lower().endswith('.bin') ] - - savedata = {} - for p in bin_files: - output = subprocess.check_output([args.binary, p], stderr=subprocess.DEVNULL) - measurements = np.array([ float(value) for _offset, value in [ line.split() for line in output.splitlines() ] ]) - savedata[p] = list(measurements) - - # Cut off first and last sample for mean and RMS calculations as these show boundary effects. - measurements = measurements[1:-1] - mean = np.mean(measurements) - rms = np.sqrt(np.mean(np.square(measurements - mean))) - - print(f'{path.basename(p):<60}: mean={mean:<8.4f}Hz rms={rms*1000:.3f}mHz') - - if args.dump: - with open(args.dump, 'w') as f: - json.dump(savedata, f) - diff --git a/controller/fw/tools/gold_code_header_gen.py b/controller/fw/tools/gold_code_header_gen.py deleted file mode 100644 index fa98fce..0000000 --- a/controller/fw/tools/gold_code_header_gen.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import math -import textwrap -import contextlib - -import numpy as np -import scipy.signal as sig - -# From https://github.com/mubeta06/python/blob/master/signal_processing/sp/gold.py -preferred_pairs = {5:[[2],[1,2,3]], 6:[[5],[1,4,5]], 7:[[4],[4,5,6]], - 8:[[1,2,3,6,7],[1,2,7]], 9:[[5],[3,5,6]], - 10:[[2,5,9],[3,4,6,8,9]], 11:[[9],[3,6,9]]} - -def gen_gold(seq1, seq2): - gold = [seq1, seq2] - for shift in range(len(seq1)): - gold.append(seq1 ^ np.roll(seq2, -shift)) - return gold - -def gold(n): - n = int(n) - if not n in preferred_pairs: - raise KeyError('preferred pairs for %s bits unknown' % str(n)) - t0, t1 = preferred_pairs[n] - (seq0, _st0), (seq1, _st1) = sig.max_len_seq(n, taps=t0), sig.max_len_seq(n, taps=t1) - return gen_gold(seq0, seq1) - -@contextlib.contextmanager -def print_include_guards(macro_name): - print(f'#ifndef {macro_name}') - print(f'#define {macro_name}') - yield - print(f'#endif /* {macro_name} */') - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser(add_help=False) - parser.add_argument('n', type=int, choices=preferred_pairs, help='bit width of shift register. Generate 2**n + 1 sequences of length 2**n - 1.') - parser.add_argument('-v', '--variable', default='gold_code_table', help='Name for weak alias of generated table') - parser.add_argument('-h', '--header', action='store_true', help='Generate header file') - parser.add_argument('-c', '--source', action='store_true', help='Generate table source file') - args = parser.parse_args() - - if not args.header != args.source: - print('Exactly one of --header and --source must be given.', file=sys.stderr) - sys.exit(1) - - nbytes = math.ceil((2**args.n-1)/8) - - if args.source: - print('/* THIS IS A GENERATED FILE. DO NOT EDIT! */') - print('#include <unistd.h>') - print('#include <stdint.h>') - print() - print(f'/* {args.n} bit gold sequences: {2**args.n+1} sequences of length {2**args.n-1} bit.') - print(f' *') - print(f' * Each code is packed left-aligned into {nbytes} bytes in big-endian byte order.') - print(f' */') - print(f'const uint8_t {args.variable}[{2**args.n+1}][{nbytes}] = {{') - for i, code in enumerate(gold(args.n)): - par = '{' + ' '.join(f'0x{d:02x},' for d in np.packbits(code)) + f'}}, /* {i: 3d} "{"".join(str(x) for x in code)}" */' - print(textwrap.fill(par, initial_indent=' '*4, subsequent_indent=' '*4, width=120)) - print('};') - print() - else: - print('/* THIS IS A GENERATED FILE. DO NOT EDIT! */') - with print_include_guards(f'__GOLD_CODE_GENERATED_HEADER_{args.n}__'): - print(f'extern const uint8_t {args.variable}[{2**args.n+1}][{nbytes}];') diff --git a/controller/fw/tools/grid_freq_psd_spl_108pt.json b/controller/fw/tools/grid_freq_psd_spl_108pt.json deleted file mode 100644 index 5a0ff41..0000000 --- a/controller/fw/tools/grid_freq_psd_spl_108pt.json +++ /dev/null @@ -1 +0,0 @@ -{"x_spec": [3.2595692805152726e-05, 5.0, 613575], "t": [3.2595692805152726e-05, 3.2595692805152726e-05, 3.2595692805152726e-05, 3.2595692805152726e-05, 0.0001423024947075771, 0.00015800362803968106, 0.00017543716661470822, 0.00019479425764873777, 0.0002162871388378975, 0.00024015146540428407, 0.00026664889389955537, 0.00029606995109590574, 0.00032873721941990017, 0.0003650088738553592, 0.0004052826090950758, 0.00045000000000000004, 0.000499651343175437, 0.0005547810327489297, 0.0006159935292916862, 0.0006839599873288199, 0.0007594256141046668, 0.0008432178402871724, 0.0009362553921977272, 0.0010395583650374223, 0.0011542594075560205, 0.001281616140796111, 0.0014230249470757708, 0.001580036280396809, 0.0017543716661470824, 0.0019479425764873776, 0.002162871388378975, 0.0024015146540428403, 0.002666488938995554, 0.002960699510959057, 0.0032873721941990056, 0.0036500887385535925, 0.004052826090950754, 0.0045000000000000005, 0.00499651343175437, 0.005547810327489296, 0.006159935292916869, 0.0068395998732882, 0.007594256141046669, 0.008432178402871724, 0.009362553921977271, 0.010395583650374221, 0.011542594075560205, 0.012816161407961109, 0.014230249470757707, 0.01580036280396809, 0.017543716661470823, 0.01947942576487376, 0.02162871388378975, 0.024015146540428405, 0.026664889389955565, 0.02960699510959057, 0.03287372194199005, 0.036500887385535925, 0.04052826090950754, 0.045, 0.0499651343175437, 0.05547810327489296, 0.06159935292916863, 0.06839599873288206, 0.07594256141046668, 0.08432178402871732, 0.09362553921977272, 0.10395583650374222, 0.11542594075560206, 0.12816161407961107, 0.14230249470757705, 0.15800362803968088, 0.1754371666147082, 0.1947942576487376, 0.21628713883789774, 0.24015146540428406, 0.26664889389955565, 0.2960699510959057, 0.32873721941990053, 0.36500887385535924, 0.40528260909507535, 0.45, 0.499651343175437, 0.5547810327489296, 0.6159935292916868, 0.6839599873288206, 0.7594256141046669, 0.8432178402871732, 0.9362553921977271, 1.0395583650374223, 1.1542594075560206, 1.2816161407961109, 1.4230249470757708, 1.5800362803968104, 1.7543716661470823, 1.9479425764873777, 2.162871388378975, 2.4015146540428405, 2.6664889389955535, 2.960699510959057, 3.287372194199002, 3.6500887385535927, 4.052826090950758, 4.5, 5.0, 5.0, 5.0, 5.0], "c": [0.7720161468716866, -0.5547528253056444, 0.30706059086000753, 0.19422577014134906, -1.1954636661840032, 0.9215976941641111, -0.6668136393976918, -1.341269161156733, -0.16311330594842666, -1.7639636752234251, -1.238385544822954, -0.32649555618555554, -0.03086589610280171, -2.358195657381619, -0.5759152419849985, 0.1892225800004134, -1.8122889670546236, -0.8109120798216202, -0.5500991736738969, -4.680192969256771, -2.8007700704649876, 0.16866469558571784, -1.1040811840849307, -3.0243574268705546, -4.018139927365795, -4.100581028618109, -0.556354762846191, -7.414377514669229, 1.36396325920194, -6.002559557058508, -2.2113451390305365, -4.578944771104116, -4.372644849632638, -3.945339124673235, -4.778747958903158, -2.370174137632325, -5.7372466088109295, -4.707506574819875, -4.834404729330929, -5.005244244061701, -5.82644896783577, -4.717966026411524, -6.146374820241562, -4.972788381244952, -5.854957092953355, -5.702174935205885, -6.222035857079607, -6.2128389666872, -6.212821706753751, -6.253599689326325, -6.681685577659057, -6.372364384360678, -6.771223202540934, -6.856809137231159, -6.986412256164045, -7.190466178818742, -7.577896455149433, -7.515731696006047, -7.598155006351761, -7.824526916149126, -8.141496591776512, -8.36794927682997, -8.80307396767114, -8.828816533544659, -9.357524260470413, -9.658130054343863, -10.005768472049466, -10.499801262514108, -11.028689820560558, -11.413688641742898, -11.906162042727946, -12.232342460719975, -12.438432746733596, -13.088338100203112, -12.308710772618745, -11.685074853925329, -11.397838681243094, -12.265219694936695, -13.600359694898529, -14.031425961884718, -12.236885080485473, -13.527508426900974, -13.698402018452601, -13.397911198962568, -14.144410560196603, -13.905769594095293, -14.410874830544122, -14.531727635304264, -14.59275291853806, -14.35404826562502, -14.58670053318149, -14.432515268864977, -14.363428024828353, -14.429222027493264, -14.73947634127499, -14.717315405960353, -14.678539669792505, -14.825278423641382, -14.80936417940876, -14.943375264882789, -14.680885181815674, -14.54841244844906, -14.634365225950589, -14.609444790868906, 0.0, 0.0, 0.0, 0.0], "k": 3}
\ No newline at end of file diff --git a/controller/fw/tools/hum_generator.py b/controller/fw/tools/hum_generator.py deleted file mode 100755 index fbcabac..0000000 --- a/controller/fw/tools/hum_generator.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python -# coding: utf-8 - -import binascii -import struct - -import numpy as np -import pydub - -from dsss_demod_test_waveform_gen import load_noise_gen, modulate as dsss_modulate - -np.set_printoptions(linewidth=240) - -def generate_noisy_signal( - test_data=32, - test_nbits=5, - test_decimation=10, - test_signal_amplitude=20e-3, - noise_level=10e-3, - noise_spec='synth://grid_freq_psd_spl_108pt.json', - seed=0): - - #test_data = np.random.RandomState(seed=0).randint(0, 2 * (2**test_nbits), test_duration) - #test_data = np.array([0, 1, 2, 3] * 50) - if isinstance(test_data, int): - test_data = np.array(range(test_data)) - - - signal = np.repeat(dsss_modulate(test_data, test_nbits) * 2.0 - 1, test_decimation) - - noise_gen, noise_params = load_noise_gen(noise_spec) - noise = noise_gen(seed, len(signal), **noise_params) - return np.absolute(noise + signal*test_signal_amplitude) - -def write_raw_frequencies_bin(outfile, **kwargs): - with open(outfile, 'wb') as f: - for x in generate_noisy_signal(**kwargs): - f.write(struct.pack('f', x)) - -def synthesize_sine(freqs, freqs_sampling_rate=10.0, output_sampling_rate=44100): - duration = len(freqs) / freqs_sampling_rate # seconds - afreq_out = np.interp(np.linspace(0, duration, int(duration*output_sampling_rate)), np.linspace(0, duration, len(freqs)), freqs) - return np.sin(np.cumsum(2*np.pi * afreq_out / output_sampling_rate)) - -def write_flac(filename, signal, sampling_rate=44100): - signal -= np.min(signal) - signal /= np.max(signal) - signal -= 0.5 - signal *= 2**16 - 1 - le_bytes = signal.astype(np.int16).tobytes() - seg = pydub.AudioSegment(data=le_bytes, sample_width=2, frame_rate=sampling_rate, channels=1) - seg.export(filename, format='flac') - -def write_synthetic_hum_flac(filename, output_sampling_rate=44100, freqs_sampling_rate=10.0, **kwargs): - signal = generate_noisy_signal(**kwargs) - print(signal) - write_flac(filename, synthesize_sine(signal, freqs_sampling_rate, output_sampling_rate), - sampling_rate=output_sampling_rate) - -def emulate_adc_signal(adc_bits=12, adc_offset=0.4, adc_amplitude=0.25, freq_sampling_rate=10.0, output_sampling_rate=1000, **kwargs): - signal = synthesize_sine(generate_noisy_signal(), freq_sampling_rate, output_sampling_rate) - signal = signal*adc_amplitude + adc_offset - smin, smax = np.min(signal), np.max(signal) - if smin < 0.0 or smax > 1.0: - raise UserWarning('Amplitude or offset too large: Signal out of bounds with min/max [{smin}, {smax}] of ADC range') - signal *= 2**adc_bits -1 - return signal - -def save_adc_signal(fn, signal, dtype=np.uint16): - with open(fn, 'wb') as f: - f.write(signal.astype(dtype).tobytes()) - -def write_emulated_adc_signal_bin(filename, **kwargs): - save_adc_signal(filename, emulate_adc_signal(**kwargs)) - -def hum_cmd(args): - write_synthetic_hum_flac(args.out_flac, - output_sampling_rate=args.audio_sampling_rate, - freqs_sampling_rate=args.frequency_sampling_rate, - test_data = np.array(list(binascii.unhexlify(args.data))), - test_nbits = args.symbol_bits, - test_decimation = args.decimation, - test_signal_amplitude = args.signal_level/1e3, - noise_level = args.noise_level/1e3, - noise_spec=args.noise_spec, - seed = args.random_seed) - - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser() - cmd_parser = parser.add_subparsers(required=True) - hum_parser = cmd_parser.add_parser('hum', help='Generated artificial modulated mains hum') - # output parameters - hum_parser.add_argument('-a', '--audio-sampling-rate', type=int, default=44100) - - # modulation parameters - hum_parser.add_argument('-f', '--frequency-sampling-rate', type=float, default=10.0*100/128) - hum_parser.add_argument('-b', '--symbol-bits', type=int, default=5, help='bits per symbol (excluding sign bit)') - hum_parser.add_argument('-n', '--noise-level', type=float, default=1.0, help='Scale synthetic noise level') - hum_parser.add_argument('-s', '--signal-level', type=float, default=20.0, help='Synthetic noise level in mHz') - hum_parser.add_argument('-d', '--decimation', type=int, default=10, help='DSSS modulation decimation in frequency measurement cycles') - hum_parser.add_argument('-r', '--random-seed', type=int, default=0) - hum_parser.add_argument('--noise-spec', type=str, default='synth://grid_freq_psd_spl_108pt.json') - hum_parser.add_argument('out_flac', metavar='out.flac', help='FLAC output file') - hum_parser.add_argument('data', help='modulation data hex string') - hum_parser.set_defaults(func=hum_cmd) - - args = parser.parse_args() - args.func(args) - diff --git a/controller/fw/tools/ldparser.py b/controller/fw/tools/ldparser.py deleted file mode 100644 index c620fe2..0000000 --- a/controller/fw/tools/ldparser.py +++ /dev/null @@ -1,126 +0,0 @@ - -import sys - -import pyparsing as pp -from pyparsing import pyparsing_common as ppc - -LPAREN, RPAREN, LBRACE, RBRACE, LBROK, RBROK, COLON, SEMICOLON, EQUALS, COMMA = map(pp.Suppress, '(){}<>:;=,') - -parse_suffix_int = lambda lit: int(lit[:-1]) * (10**(3*(1 + 'kmgtpe'.find(lit[-1].lower())))) -si_suffix = pp.oneOf('k m g t p e', caseless=True) - -numeric_literal = pp.Regex('0x[0-9a-fA-F]+').setName('hex int').setParseAction(pp.tokenMap(int, 16)) \ - | (pp.Regex('[0-9]+[kKmMgGtTpPeE]')).setName('size int').setParseAction(pp.tokenMap(parse_suffix_int)) \ - | pp.Word(pp.nums).setName('int').setParseAction(pp.tokenMap(int)) -access_def = pp.Regex('[rR]?[wW]?[xX]?').setName('access literal').setParseAction(pp.tokenMap(str.lower)) - -origin_expr = pp.Suppress(pp.CaselessKeyword('ORIGIN')) + EQUALS + numeric_literal -length_expr = pp.Suppress(pp.CaselessKeyword('LENGTH')) + EQUALS + numeric_literal -mem_expr = pp.Group(ppc.identifier + LPAREN + access_def + RPAREN + COLON + origin_expr + COMMA + length_expr) -mem_contents = pp.ZeroOrMore(mem_expr) - -mem_toplevel = pp.CaselessKeyword("MEMORY") + pp.Group(LBRACE + pp.Optional(mem_contents, []) + RBRACE) - -glob = pp.Word(pp.alphanums + '._*') -match_expr = pp.Forward() -assignment = pp.Forward() -funccall = pp.Group(pp.Word(pp.alphas + '_') + LPAREN + (assignment | numeric_literal | match_expr | glob | ppc.identifier) + RPAREN + pp.Optional(SEMICOLON)) -value = numeric_literal | funccall | ppc.identifier | '.' -formula = (value + pp.oneOf('+ = * / %') + value) | value -# suppress stray semicolons -assignment << (SEMICOLON | pp.Group((ppc.identifier | '.') + EQUALS + (formula | value) + pp.Optional(SEMICOLON))) -match_expr << (glob + LPAREN + pp.OneOrMore(funccall | glob) + RPAREN) - -section_contents = pp.ZeroOrMore(assignment | funccall | match_expr); - -section_name = pp.Regex('\.[a-zA-Z0-9_.]+') -section_def = pp.Group(section_name + pp.Optional(numeric_literal) + COLON + LBRACE + pp.Group(section_contents) + - RBRACE + pp.Optional(RBROK + ppc.identifier + pp.Optional('AT' + RBROK + ppc.identifier))) -sec_contents = pp.ZeroOrMore(section_def | assignment) - -sections_toplevel = pp.Group(pp.CaselessKeyword("SECTIONS").suppress() + LBRACE + sec_contents + RBRACE) - -toplevel_elements = mem_toplevel | funccall | sections_toplevel | assignment -ldscript = pp.Group(pp.ZeroOrMore(toplevel_elements)) -ldscript.ignore(pp.cppStyleComment) - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser() - parser.add_argument('linker_script', type=argparse.FileType('r')) - args = parser.parse_args() - - #print(mem_expr.parseString('FLASH (rx) : ORIGIN = 0x0800000, LENGTH = 512K', parseAll=True)) - # print(ldscript.parseString(''' - # /* Entry Point */ - # ENTRY(Reset_Handler) - # - # /* Highest address of the user mode stack */ - # _estack = 0x20020000; /* end of RAM */ - # /* Generate a link error if heap and stack don't fit into RAM */ - # _Min_Heap_Size = 0x200;; /* required amount of heap */ - # _Min_Stack_Size = 0x400;; /* required amount of stack */ - # ''', parseAll=True)) - - print(ldscript.parseFile(args.linker_script, parseAll=True)) - #print(funccall.parseString('KEEP(*(.isr_vector))')) - #print(section_contents.parseString(''' - # . = ALIGN(4); - # KEEP(*(.isr_vector)) /* Startup code */ - # . = ALIGN(4); - # ''', parseAll=True)) - - #print(section_def.parseString(''' - # .text : - # { - # . = ALIGN(4); - # *(.text) /* .text sections (code) */ - # *(.text*) /* .text* sections (code) */ - # *(.glue_7) /* glue arm to thumb code */ - # *(.glue_7t) /* glue thumb to arm code */ - # *(.eh_frame) - # - # KEEP (*(.init)) - # KEEP (*(.fini)) - # - # . = ALIGN(4); - # _etext = .; /* define a global symbols at end of code */ - # } >FLASH - # ''', parseAll=True)) - - #print(section_def.parseString('.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH', parseAll=True)) - - #print(assignment.parseString('__preinit_array_start = .', parseAll=True)) - #print(assignment.parseString('a = 23', parseAll=True)) - #print(funccall.parseString('foo (a=23)', parseAll=True)) - #print(funccall.parseString('PROVIDE_HIDDEN (__preinit_array_start = .);', parseAll=True)) - #print(section_def.parseString(''' - # .preinit_array : - # { - # PROVIDE_HIDDEN (__preinit_array_start = .); - # KEEP (*(.preinit_array*)) - # PROVIDE_HIDDEN (__preinit_array_end = .); - # } >FLASH''', parseAll=True)) - #print(match_expr.parseString('*(SORT(.init_array.*))', parseAll=True)) - #print(funccall.parseString('KEEP (*(SORT(.init_array.*)))', parseAll=True)) - #print(section_def.parseString(''' - # .init_array : - # { - # PROVIDE_HIDDEN (__init_array_start = .); - # KEEP (*(SORT(.init_array.*))) - # KEEP (*(.init_array*)) - # PROVIDE_HIDDEN (__init_array_end = .); - # } >FLASH - # ''', parseAll=True)) - - #print(match_expr.parseString('*(.ARM.extab* .gnu.linkonce.armextab.*)', parseAll=True)) - #print(formula.parseString('. + _Min_Heap_Size', parseAll=True)) - #print(assignment.parseString('. = . + _Min_Heap_Size;', parseAll=True)) - #print(sections_toplevel.parseString(''' - # SECTIONS - # { - # .ARMattributes : { } - # } - # ''', parseAll=True)) - #sys.exit(0) - diff --git a/controller/fw/tools/linkmem.py b/controller/fw/tools/linkmem.py deleted file mode 100644 index 934a571..0000000 --- a/controller/fw/tools/linkmem.py +++ /dev/null @@ -1,276 +0,0 @@ - -import tempfile -import os -from os import path -import sys -import re -import subprocess -from contextlib import contextmanager -from collections import defaultdict -import colorsys - -import cxxfilt -from elftools.elf.elffile import ELFFile -from elftools.elf.enums import ENUM_ST_SHNDX -from elftools.elf.descriptions import describe_symbol_type, describe_sh_type -import libarchive -import matplotlib.cm - -@contextmanager -def chdir(newdir): - old_cwd = os.getcwd() - try: - os.chdir(newdir) - yield - finally: - os.chdir(old_cwd) - -def keep_last(it, first=None): - last = first - for elem in it: - yield last, elem - last = elem - -def delim(start, end, it, first_only=True): - found = False - for elem in it: - if end(elem): - if first_only: - return - found = False - elif start(elem): - found = True - elif found: - yield elem - -def delim_prefix(start, end, it): - yield from delim(lambda l: l.startswith(start), lambda l: end is not None and l.startswith(end), it) - -def trace_source_files(linker, cmdline, trace_sections=[], total_sections=['.text', '.data', '.rodata']): - with tempfile.TemporaryDirectory() as tempdir: - out_path = path.join(tempdir, 'output.elf') - output = subprocess.check_output([linker, '-o', out_path, f'-Wl,--print-map', *cmdline]) - lines = [ line.strip() for line in output.decode().splitlines() ] - # FIXME also find isr vector table references - - defs = {} - objs = defaultdict(lambda: 0) - aliases = {} - sec_name = None - last_loc = None - last_sym = None - line_cont = None - for last_line, line in keep_last(delim_prefix('Linker script and memory map', 'OUTPUT', lines), first=''): - if not line or line.startswith('LOAD '): - sec_name = None - continue - - # first part of continuation line - if m := re.match('^(\.[0-9a-zA-Z-_.]+)$', line): - line_cont = line - sec_name = None - continue - - if line_cont: - line = line_cont + ' ' + line - line_cont = None - - # -ffunction-sections/-fdata-sections section - if m := re.match('^(\.[0-9a-zA-Z-_.]+)\.([0-9a-zA-Z-_.]+)\s+(0x[0-9a-f]+)\s+(0x[0-9a-f]+)\s+(\S+)$', line): - sec, sym, loc, size, obj = m.groups() - *_, sym = sym.rpartition('.') - sym = cxxfilt.demangle(sym) - size = int(size, 16) - obj = path.abspath(obj) - - if sec not in total_sections: - size = 0 - - objs[obj] += size - defs[sym] = (sec, size, obj) - - sec_name, last_loc, last_sym = sec, loc, sym - continue - - # regular (no -ffunction-sections/-fdata-sections) section - if m := re.match('^(\.[0-9a-zA-Z-_]+)\s+(0x[0-9a-f]+)\s+(0x[0-9a-f]+)\s+(\S+)$', line): - sec, _loc, size, obj = m.groups() - size = int(size, 16) - obj = path.abspath(obj) - - if sec in total_sections: - objs[obj] += size - - sec_name = sec - last_loc, last_sym = None, None - continue - - # symbol def - if m := re.match('^(0x[0-9a-f]+)\s+(\S+)$', line): - loc, sym = m.groups() - sym = cxxfilt.demangle(sym) - loc = int(loc, 16) - if sym in defs: - continue - - if loc == last_loc: - assert last_sym is not None - aliases[sym] = last_sym - else: - assert sec_name - defs[sym] = (sec_name, None, obj) - last_loc, last_sym = loc, sym - - continue - - refs = defaultdict(lambda: set()) - for sym, (sec, size, obj) in defs.items(): - fn, _, member = re.match('^([^()]+)(\((.+)\))?$', obj).groups() - fn = path.abspath(fn) - - if member: - subprocess.check_call(['ar', 'x', '--output', tempdir, fn, member]) - fn = path.join(tempdir, member) - - with open(fn, 'rb') as f: - elf = ELFFile(f) - - symtab = elf.get_section_by_name('.symtab') - - symtab_demangled = { cxxfilt.demangle(nsym.name).replace(' ', ''): i - for i, nsym in enumerate(symtab.iter_symbols()) } - - s = set() - sec_map = { sec.name: i for i, sec in enumerate(elf.iter_sections()) } - matches = [ i for name, i in sec_map.items() if re.match(f'\.rel\..*\.{sym}', name) ] - if matches: - sec = elf.get_section(matches[0]) - for reloc in sec.iter_relocations(): - refsym = symtab.get_symbol(reloc['r_info_sym']) - name = refsym.name if refsym.name else elf.get_section(refsym['st_shndx']).name.split('.')[-1] - s.add(name) - refs[sym] = s - - for tsec in trace_sections: - matches = [ i for name, i in sec_map.items() if name == f'.rel{tsec}' ] - s = set() - if matches: - sec = elf.get_section(matches[0]) - for reloc in sec.iter_relocations(): - refsym = symtab.get_symbol(reloc['r_info_sym']) - s.add(refsym.name) - refs[tsec.replace('.', '_')] |= s - - return objs, aliases, defs, refs - -@contextmanager -def wrap(leader='', print=print, left='{', right='}'): - print(leader, left) - yield lambda *args, **kwargs: print(' ', *args, **kwargs) - print(right) - -def mangle(name): - return re.sub('[^a-zA-Z0-9_]', '_', name) - -hexcolor = lambda r, g, b, *_a: f'#{int(r*255):02x}{int(g*255):02x}{int(b*255):02x}' -def vhex(val): - r,g,b,_a = matplotlib.cm.viridis(1.0-val) - fc = hexcolor(r, g, b) - h,s,v = colorsys.rgb_to_hsv(r,g,b) - cc = '#000000' if v > 0.8 else '#ffffff' - return fc, cc - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser() - parser.add_argument('--trace-sections', type=str, action='append', default=[]) - parser.add_argument('--trim-stubs', type=str, action='append', default=[]) - parser.add_argument('--highlight-subdirs', type=str, default=None) - parser.add_argument('linker_binary') - parser.add_argument('linker_args', nargs=argparse.REMAINDER) - args = parser.parse_args() - - trace_sections = args.trace_sections - trace_sections_mangled = { sec.replace('.', '_') for sec in trace_sections } - objs, aliases, syms, refs = trace_source_files(args.linker_binary, args.linker_args, trace_sections) - - clusters = defaultdict(lambda: []) - for sym, (sec, size, obj) in syms.items(): - clusters[obj].append((sym, sec, size)) - - max_ssize = max(size or 0 for _sec, size, _obj in syms.values()) - max_osize = max(objs.values()) - - subdir_prefix = path.abspath(args.highlight_subdirs) + '/' if args.highlight_subdirs else '### NO HIGHLIGHT ###' - first_comp = lambda le_path: path.dirname(le_path).partition(os.sep)[0] - subdir_colors = sorted({ first_comp(obj[len(subdir_prefix):]) for obj in objs if obj.startswith(subdir_prefix) }) - subdir_colors = { path: hexcolor(*matplotlib.cm.Pastel1(i/len(subdir_colors))) for i, path in enumerate(subdir_colors) } - - subdir_sizes = defaultdict(lambda: 0) - for obj, size in objs.items(): - if not isinstance(size, int): - continue - if obj.startswith(subdir_prefix): - subdir_sizes[first_comp(obj[len(subdir_prefix):])] += size - else: - subdir_sizes['<others>'] += size - - print('Subdir sizes:', file=sys.stderr) - for subdir, size in sorted(subdir_sizes.items(), key=lambda x: x[1]): - print(f'{subdir:>20}: {size:>6,d} B', file=sys.stderr) - - def lookup_highlight(path): - if args.highlight_subdirs: - if obj.startswith(subdir_prefix): - highlight_head = first_comp(path[len(subdir_prefix):]) - return subdir_colors[highlight_head], highlight_head - else: - return '#e0e0e0', None - else: - return '#ddf7f4', None - - with wrap('digraph G', print) as lvl1print: - print('size="23.4,16.5!";') - print('graph [fontsize=40];') - print('node [fontsize=40];') - #print('ratio="fill";') - - print('rankdir=LR;') - print('ranksep=5;') - print('nodesep=0.2;') - print() - - for i, (obj, obj_syms) in enumerate(clusters.items()): - with wrap(f'subgraph cluster_{i}', lvl1print) as lvl2print: - print('style = "filled";') - highlight_color, highlight_head = lookup_highlight(obj) - print(f'bgcolor = "{highlight_color}";') - print('pencolor = none;') - fc, cc = vhex(objs[obj]/max_osize) - highlight_subdir_part = f'<font face="carlito" color="{cc}" point-size="40">{highlight_head} / </font>' if highlight_head else '' - lvl2print(f'label = <<table border="0"><tr><td border="0" cellpadding="5" bgcolor="{fc}">' - f'{highlight_subdir_part}' - f'<font face="carlito" color="{cc}"><b>{path.basename(obj)} ({objs[obj]}B)</b></font>' - f'</td></tr></table>>;') - lvl2print() - for sym, sec, size in obj_syms: - has_size = isinstance(size, int) and size > 0 - size_s = f' ({size}B)' if has_size else '' - fc, cc = vhex(size/max_ssize) if has_size else ('#ffffff', '#000000') - shape = 'box' if sec == '.text' else 'oval' - lvl2print(f'{mangle(sym)}[label = "{sym}{size_s}", style="rounded,filled", shape="{shape}", fillcolor="{fc}", fontname="carlito", fontcolor="{cc}" color=none];') - lvl1print() - - edges = set() - for start, ends in refs.items(): - for end in ends: - end = aliases.get(end, end) - if (start in syms or start in trace_sections_mangled) and end in syms: - edges.add((start, end)) - - for start, end in edges: - lvl1print(f'{mangle(start)} -> {mangle(end)} [style="bold", color="#333333"];') - - for sec in trace_sections: - lvl1print(f'{sec.replace(".", "_")} [label = "section {sec}", shape="box", style="filled,bold"];') - diff --git a/controller/fw/tools/linksize.py b/controller/fw/tools/linksize.py deleted file mode 100644 index c41a951..0000000 --- a/controller/fw/tools/linksize.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python3 - -def parse_linker_script(data): - pass - -def link(groups): - defined_symbols = {} - undefined_symbols = set() - for group, files in groups: - while True: - found_something = False - - for fn in files: - symbols = load_symbols(fn) - for symbol in symbols: - if symbol in defined_symbols: - - if not group or not found_something: - break - - -if __name__ == '__main__': - - import argparse - parser = argparse.ArgumentParser() - parser.add_argument('-T', '--script', type=str, help='Linker script to use') - parser.add_argument('-o', '--output', type=str, help='Output file to produce') - args, rest = parser.parse_known_intermixed_args() - print(rest) - - addprefix = lambda *xs: [ prefix + opt for opt in xs for prefix in ('', '-Wl,') ] - START_GROUP = addprefix('-(', '--start-group') - END_GROUP = addprefix('-)', '--end-group') - GROUP_OPTS = [*START_GROUP, *END_GROUP] - input_files = [ arg for arg in rest if not arg.startswith('-') or arg in GROUP_OPTS ] - - def input_file_iter(input_files): - group = False - files = [] - for arg in input_files: - if arg in START_GROUP: - assert not group - - if files: - yield False, files # nested -Wl,--start-group - group, files = True, [] - - elif arg in END_GROUP: - assert group # missing -Wl,--start-group - if files: - yield True, files - group, files = False, [] - - else: - files.append(arg) - - assert not group # missing -Wl,--end-group - if files: - yield False, files - - - diff --git a/controller/fw/tools/linktracer.py b/controller/fw/tools/linktracer.py deleted file mode 100644 index 0c53a60..0000000 --- a/controller/fw/tools/linktracer.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python3 - -import re -import subprocess -import tempfile -import pprint - -ARCHIVE_RE = r'([^(]*)(\([^)]*\))?' - -def trace_source_files(linker, cmdline): - with tempfile.NamedTemporaryFile() as mapfile: - output = subprocess.check_output([linker, f'-Wl,--Map={mapfile.name}', *cmdline]) - - # intentionally use generator here - idx = 0 - lines = [ line.rstrip() for line in mapfile.read().decode().splitlines() if line.strip() ] - - for idx, line in enumerate(lines[idx:], start=idx): - #print('Dropping', line) - if line == 'Linker script and memory map': - break - - idx += 1 - objects = [] - symbols = {} - sections = {} - current_object = None - last_offset = None - last_symbol = None - cont_sec = None - cont_ind = None - current_section = None - for idx, line in enumerate(lines[idx:], start=idx): - print(f'Processing >{line}') - if line.startswith('LOAD'): - _load, obj = line.split() - objects.append(obj) - continue - - if line.startswith('OUTPUT'): - break - - m = re.match(r'^( ?)([^ ]+)? +(0x[0-9a-z]+) +(0x[0-9a-z]+)?(.*)?$', line) - if m is None: - m = re.match(r'^( ?)([^ ]+)?$', line) - if m: - cont_ind, cont_sec = m.groups() - else: - cont_ind, cont_sec = None, None - last_offset, last_symbol = None, None - continue - indent, sec, offx, size, sym_or_src = m.groups() - if sec is None: - sec = cont_sec - ind = cont_ind - cont_sec = None - cont_ind = None - print(f'vals: indent={indent} sec={sec} offx={offx} size={size} sym_or_src={sym_or_src}') - if not re.match('^[a-zA-Z_0-9<>():*]+$', sym_or_src): - continue - - if indent == '': - print(f'Section: {sec} 0x{size:x}') - current_section = sec - sections[sec] = size - last_offset = None - last_symbol = None - continue - - if offx is not None: - offx = int(offx, 16) - if size is not None: - size = int(size, 16) - - if size is not None and sym_or_src is not None: - # archive/object line - archive, _member = re.match(ARCHIVE_RE, sym_or_src).groups() - current_object = archive - last_offset = offx - else: - if sym_or_src is not None: - assert size is None - if last_offset is not None: - last_size = offx - last_offset - symbols[last_symbol] = (last_size, current_section) - print(f'Symbol: {last_symbol} 0x{last_size:x} @{current_section}') - last_offset = offx - last_symbol = sym_or_src - - idx += 1 - - for idx, line in enumerate(lines[idx:], start=idx): - if line == 'Cross Reference Table': - break - - idx += 1 - - # map which symbol was pulled from which object in the end - used_defs = {} - for line in lines: - *left, right = line.split() - - archive, _member = re.match(ARCHIVE_RE, right).groups() - if left: - used_defs[''.join(left)] = archive - - #pprint.pprint(symbols) - - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser() - parser.add_argument('linker_binary') - parser.add_argument('linker_args', nargs=argparse.REMAINDER) - args = parser.parse_args() - - source_files = trace_source_files(args.linker_binary, args.linker_args) - diff --git a/controller/fw/tools/mapparse.py b/controller/fw/tools/mapparse.py deleted file mode 100644 index c1f460a..0000000 --- a/controller/fw/tools/mapparse.py +++ /dev/null @@ -1,129 +0,0 @@ - -import re -from collections import defaultdict, namedtuple - -Section = namedtuple('Section', ['name', 'offset', 'objects']) -ObjectEntry = namedtuple('ObjectEntry', ['filename', 'object', 'offset', 'size']) -FileEntry = namedtuple('FileEntry', ['section', 'object', 'offset', 'length']) - -class Memory: - def __init__(self, name, origin, length, attrs=''): - self.name, self.origin, self.length, self.attrs = name, origin, length, attrs - self.sections = {} - self.files = defaultdict(lambda: []) - self.totals = defaultdict(lambda: 0) - - def add_toplevel(self, name, offx, length): - self.sections[name] = Section(offx, length, []) - - def add_obj(self, name, offx, length, fn, obj): - base_section, sep, subsec = name[1:].partition('.') - base_section = '.'+base_section - if base_section in self.sections: - sec = secname, secoffx, secobjs = self.sections[base_section] - secobjs.append(ObjectEntry(fn, obj, offx, length)) - else: - sec = None - self.files[fn].append(FileEntry(sec, obj, offx, length)) - self.totals[fn] += length - -class MapFile: - def __init__(self, s): - self._lines = s.splitlines() - self.memcfg = {} - self.defaultmem = Memory('default', 0, 0xffffffffffffffff) - self._parse() - - def __getitem__(self, offx_or_name): - ''' Lookup a memory area by name or address ''' - if offx_or_name in self.memcfg: - return self.memcfg[offx_or_name] - - elif isinstance(offx_or_name, int): - for mem in self.memcfg.values(): - if mem.origin <= offx_or_name < mem.origin+mem.length: - return mem - else: - return self.defaultmem - - raise ValueError('Invalid argument type for indexing') - - def _skip(self, regex): - matcher = re.compile(regex) - for l in self: - if matcher.match(l): - break - - def __iter__(self): - while self._lines: - yield self._lines.pop(0) - - def _parse(self): - self._skip('^Memory Configuration') - - # Parse memory segmentation info - self._skip('^Name') - for l in self: - if not l: - break - name, origin, length, *attrs = l.split() - if not name.startswith('*'): - self.memcfg[name] = Memory(name, int(origin, 16), int(length, 16), attrs[0] if attrs else '') - - # Parse section information - toplevel_m = re.compile('^(\.[a-zA-Z0-9_.]+)\s+(0x[0-9a-fA-F]+)\s+(0x[0-9a-fA-F]+)') - secondlevel_m = re.compile('^ (\.[a-zA-Z0-9_.]+)\s+(0x[0-9a-fA-F]+)\s+(0x[0-9a-fA-F]+)\s+(.*)$') - secondlevel_linebreak_m = re.compile('^ (\.[a-zA-Z0-9_.]+)\n') - filelike = re.compile('^(/?[^()]*\.[a-zA-Z0-9-_]+)(\(.*\))?') - linebreak_section = None - for l in self: - # Toplevel section - match = toplevel_m.match(l) - if match: - name, offx, length = match.groups() - offx, length = int(offx, 16), int(length, 16) - self[offx].add_toplevel(name, offx, length) - - match = secondlevel_linebreak_m.match(l) - if match: - linebreak_section, = match.groups() - continue - - if linebreak_section: - l = ' {} {}'.format(linebreak_section, l) - linebreak_section = None - - # Second-level section - match = secondlevel_m.match(l) - if match: - name, offx, length, misc = match.groups() - match = filelike.match(misc) - if match: - fn, obj = match.groups() - obj = obj.strip('()') if obj else None - offx, length = int(offx, 16), int(length, 16) - self[offx].add_obj(name, offx, length, fn, obj) - - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser(description='Parser GCC map file') - parser.add_argument('mapfile', type=argparse.FileType('r'), help='The GCC .map file to parse') - parser.add_argument('-m', '--memory', type=str, help='The memory segments to print, comma-separated') - args = parser.parse_args() - mf = MapFile(args.mapfile.read()) - args.mapfile.close() - - mems = args.memory.split(',') if args.memory else mf.memcfg.keys() - - for name in mems: - mem = mf.memcfg[name] - print('Symbols by file for memory', name) - for tot, fn in reversed(sorted( (tot, fn) for fn, tot in mem.totals.items() )): - print(' {:>8} {}'.format(tot, fn)) - for length, offx, sec, obj in reversed(sorted(( (length, offx, sec, obj) for sec, obj, offx, length in - mem.files[fn] ), key=lambda e: e[0] )): - name = sec.name if sec else None - print(' {:>8} {:>#08x} {}'.format(length, offx, obj)) - #print('{:>16} 0x{:016x} 0x{:016x} ({:>24}) {}'.format(name, origin, length, length, attrs)) - diff --git a/controller/fw/tools/presig_gen.py b/controller/fw/tools/presig_gen.py deleted file mode 100644 index c5dafe7..0000000 --- a/controller/fw/tools/presig_gen.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -import textwrap -import uuid -import hmac -import binascii -import time -from datetime import datetime - -LINKING_KEY_SIZE = 15 -PRESIG_VERSION = '000.001' -DOMAINS = ['all', 'country', 'region', 'vendor', 'series'] - -def format_hex(data, indent=4, wrap=True): - indent = ' '*indent - par = ', '.join(f'0x{b:02x}' for b in data) - par = textwrap.fill(par, width=120, - initial_indent=indent, subsequent_indent=indent, - replace_whitespace=False, drop_whitespace=False) - if wrap: - return f'{{\n{par}\n}}' - return par - -def domain_string(domain, value): - return f'smart reset domain string v{PRESIG_VERSION}: domain:{domain}={value}' - -def keygen_cmd(args): - if os.path.exists(args.keyfile) and not args.force: - print("Error: keyfile already exists. We won't overwrite it. Instead please remove it manually.", - file=sys.stderr) - return 1 - - root_key = os.urandom(LINKING_KEY_SIZE) - - with open(args.keyfile, 'wb') as f: - f.write(binascii.hexlify(root_key)) - f.write(b'\n') - return 0 - -def gen_at_height(domain, value, height, key): - # nanananananana BLOCKCHAIN! - - ds = domain_string(domain, value).encode('utf-8') - - for height in range(height+1): - key = hmac.digest(key, ds, 'sha512')[:LINKING_KEY_SIZE] - - return key - -def auth_cmd(args): - with open(args.keyfile, 'r') as f: - root_key = binascii.unhexlify(f.read().strip()) - - vals = [ (domain, getattr(args, domain)) for domain in DOMAINS if getattr(args, domain) is not None ] - if not vals: - vals = [('all', 'all')] - for domain, value in vals: - auth = gen_at_height(domain, value, args.height, root_key) - print(f'{domain}="{value}" @{args.height}: {binascii.hexlify(auth).decode()}') - - -def prekey_cmd(args): - with open(args.keyfile, 'r') as f: - root_key = binascii.unhexlify(f.read().strip()) - - print('#include <stdint.h>') - print('#include <assert.h>') - print() - print('#include "crypto.h"') - print() - - bundle_id = uuid.uuid4().bytes - print(f'/* bundle id {binascii.hexlify(bundle_id).decode()} */') - print(f'uint8_t presig_bundle_id[16] = {format_hex(bundle_id)};') - print() - print(f'/* generated on {datetime.now()} */') - print(f'uint64_t bundle_timestamp = {int(time.time())};') - print() - print(f'int presig_height = {args.max_height};') - print() - - print('const char *presig_domain_strings[_TRIGGER_DOMAIN_COUNT] = {') - for domain in DOMAINS: - ds = domain_string(domain, getattr(args, domain)) - assert '"' not in ds - print(f' [TRIGGER_DOMAIN_{domain.upper()}] = "{ds}",') - print('};') - print() - - print('uint8_t presig_keys[_TRIGGER_DOMAIN_COUNT][PRESIG_MSG_LEN] = {') - for domain in DOMAINS: - key = gen_at_height(domain, getattr(args, domain), args.max_height, root_key) - print(f' [TRIGGER_DOMAIN_{domain.upper()}] = {{{format_hex(key, indent=0, wrap=False)}}},') - print('};') - - print() - print('static inline void __hack_asserts_only(void) {') - print(f' static_assert(_TRIGGER_DOMAIN_COUNT == {len(DOMAINS)});') - print(f' static_assert(PRESIG_MSG_LEN == {LINKING_KEY_SIZE});') - print('}') - print() - - - -TEST_VENDOR = 'Darthenschmidt Cyberei und Verschleierungstechnik GmbH' -TEST_SERIES = 'Frobnicator v0.23.7' -TEST_REGION = 'Neuland' -TEST_COUNTRY = 'Germany' - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser() - parser.add_argument('keyfile', help='Key file to use') - - subparsers = parser.add_subparsers(title='subcommands') - keygen_parser = subparsers.add_parser('keygen', help='Generate a new key') - keygen_parser.add_argument('-f', '--force', action='store_true', help='Force overwriting existing keyfile') - keygen_parser.set_defaults(func=keygen_cmd) - - auth_parser = subparsers.add_parser('auth', help='Generate one-time authentication string') - auth_parser.add_argument('height', type=int, help='Authentication string height, counting from 0 (root key)') - auth_parser.set_defaults(func=auth_cmd) - auth_parser.add_argument('-a', '--all', action='store_const', const='all', help='Vendor name for vendor domain') - auth_parser.add_argument('-v', '--vendor', type=str, nargs='?', const=TEST_VENDOR, help='Vendor name for vendor domain') - auth_parser.add_argument('-s', '--series', type=str, nargs='?', const=TEST_SERIES, help='Series identifier for series domain') - auth_parser.add_argument('-r', '--region', type=str, nargs='?', const=TEST_REGION, help='Region name for region domain') - auth_parser.add_argument('-c', '--country', type=str, nargs='?', const=TEST_COUNTRY, help='Country name for country domain') - - prekey_parser = subparsers.add_parser('prekey', help='Generate prekey data .C source code file') - prekey_parser.add_argument('-m', '--max-height', type=int, default=8, help='Height of generated prekey') - prekey_parser.add_argument('-v', '--vendor', type=str, default=TEST_VENDOR, help='Vendor name for vendor domain') - prekey_parser.add_argument('-s', '--series', type=str, default=TEST_SERIES, help='Series identifier for series domain') - prekey_parser.add_argument('-r', '--region', type=str, default=TEST_REGION, help='Region name for region domain') - prekey_parser.add_argument('-c', '--country', type=str, default=TEST_COUNTRY, help='Country name for country domain') - prekey_parser.set_defaults(func=prekey_cmd, all='all') - - args = parser.parse_args() - sys.exit(args.func(args)) - diff --git a/controller/fw/tools/reed_solomon.py b/controller/fw/tools/reed_solomon.py deleted file mode 100644 index c4ca6e4..0000000 --- a/controller/fw/tools/reed_solomon.py +++ /dev/null @@ -1,91 +0,0 @@ -import os, sys -import ctypes as C -import argparse -import binascii -import numpy as np -import timeit -import statistics - -lib = C.CDLL('rslib.so') - -lib.rslib_encode.argtypes = [C.c_int, C.c_size_t, C.POINTER(C.c_char), C.POINTER(C.c_char)] -lib.rslib_decode.argtypes = [C.c_int, C.c_size_t, C.POINTER(C.c_char)] -lib.rslib_gexp.argtypes = [C.c_int, C.c_int] -lib.rslib_gexp.restype = C.c_int -lib.rslib_decode.restype = C.c_int -lib.rslib_npar.restype = C.c_size_t - -def npar(): - return lib.rslib_npar() - -def encode(data: bytes, nbits=8): - out = C.create_string_buffer(len(data) + lib.rslib_npar()) - lib.rslib_encode(nbits, len(data), data, out) - return out.raw - -def decode(data: bytes, nbits=8): - inout = C.create_string_buffer(data) - lib.rslib_decode(nbits, len(data), inout) - return inout.raw[:-lib.rslib_npar() - 1] - -def cmdline_func_test(args, print=lambda *args, **kwargs: None, benchmark=False): - st = np.random.RandomState(seed=args.seed) - - lfsr = [lib.rslib_gexp(i, args.bits) for i in range(2**args.bits - 1)] - print('LFSR', len(set(lfsr)), lfsr) - assert all(0 < x < 2**args.bits for x in lfsr) - assert len(set(lfsr)) == 2**args.bits - 1 - - print('Seed', args.seed) - for i in range(args.repeat): - print(f'Run {i}') - test_data = bytes(st.randint(2**args.bits, size=args.message_length, dtype=np.uint8)) - print(' Raw:', binascii.hexlify(test_data).decode()) - encoded = encode(test_data, nbits=args.bits) - print(' Encoded:', binascii.hexlify(encoded).decode()) - - indices = st.permutation(len(encoded)) - encoded = list(encoded) - for pos in indices[:args.errors]: - encoded[pos] = st.randint(2**args.bits) - encoded = bytes(encoded) - print(' Modified:', ''.join(f'\033[91m{b:02x}\033[0m' if pos in indices[:args.errors] else f'{b:02x}' for pos, b in enumerate(encoded))) - - if benchmark: - rpt = 10000 - delta = timeit.timeit('decode(encoded, nbits=args.bits)', - globals={'args': args, 'decode': decode, 'encoded': encoded}, - number=rpt)/rpt - print(f'Decoding runtime: {delta*1e6:.3f}μs') - decoded = decode(encoded, nbits=args.bits) - print(' Decoded:', binascii.hexlify(decoded).decode()) - print(' Delta:', binascii.hexlify( - bytes(x^y for x, y in zip(test_data, decoded)) - ).decode().replace('0', '.')) - assert test_data == decoded - -def cmdline_func_encode(args, **kwargs): - data = np.frombuffer(binascii.unhexlify(args.hex_str), dtype=np.uint8) - # Map 8 bit input to 6 bit symbol string - data = np.packbits(np.pad(np.unpackbits(data).reshape((-1, 6)), ((0,0),(2, 0))).flatten()) - encoded = encode(data.tobytes(), nbits=args.bits) - print('symbol array:', ', '.join(f'0x{x:02x}' for x in encoded)) - print('hex string:', binascii.hexlify(encoded).decode()) - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - cmd_parser = parser.add_subparsers(required=True) - test_parser = cmd_parser.add_parser('test', help='Test reed-solomon implementation') - test_parser.add_argument('-m', '--message-length', type=int, default=6, help='Test message (plaintext) length in bytes') - test_parser.add_argument('-e', '--errors', type=int, default=2, help='Number of byte errors to insert into simulation') - test_parser.add_argument('-r', '--repeat', type=int, default=1000, help='Repeat experiment -r times') - test_parser.add_argument('-b', '--bits', type=int, default=8, help='Symbol bit size') - test_parser.add_argument('-s', '--seed', type=int, default=0, help='Random seed') - test_parser.set_defaults(func=cmdline_func_test) - enc_parser = cmd_parser.add_parser('encode', help='RS-Encode given hex string') - enc_parser.set_defaults(func=cmdline_func_encode) - enc_parser.add_argument('-b', '--bits', type=int, default=8, help='Symbol bit size') - enc_parser.add_argument('hex_str', type=str, help='Input data as hex string') - args = parser.parse_args() - args.func(args) - |