Finishing up freq meas
This commit is contained in:
parent
5effadcbaf
commit
ca01d52a86
14 changed files with 296 additions and 47 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -16,3 +16,6 @@
|
||||||
[submodule "controller/fw/musl"]
|
[submodule "controller/fw/musl"]
|
||||||
path = controller/fw/musl
|
path = controller/fw/musl
|
||||||
url = git://git.musl-libc.org/musl
|
url = git://git.musl-libc.org/musl
|
||||||
|
[submodule "controller/fw/levmarq"]
|
||||||
|
path = controller/fw/levmarq
|
||||||
|
url = https://gist.github.com/3539146.git
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,17 @@ LIBSODIUM_DIR ?= libsodium
|
||||||
TINYAES_DIR ?= tinyaes
|
TINYAES_DIR ?= tinyaes
|
||||||
MUSL_DIR ?= musl
|
MUSL_DIR ?= musl
|
||||||
|
|
||||||
C_SOURCES := src/main.c src/mspdebug_wrapper.c src/spi_flash.c
|
C_SOURCES := src/main.c src/mspdebug_wrapper.c src/spi_flash.c src/freq_meas.c
|
||||||
C_SOURCES += $(MSPDEBUG_DIR)/drivers/jtaglib.c
|
C_SOURCES += $(MSPDEBUG_DIR)/drivers/jtaglib.c
|
||||||
C_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/TransformFunctions/arm_rfft_f32.c
|
C_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/TransformFunctions/arm_rfft_f32.c
|
||||||
C_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/TransformFunctions/arm_bitreversal.c
|
C_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/TransformFunctions/arm_bitreversal.c
|
||||||
C_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/TransformFunctions/arm_cfft_radix4_f32.c
|
C_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/TransformFunctions/arm_cfft_radix4_f32.c
|
||||||
C_SOURCES += $(MUSL_DIR)/src/math/tanhf.c $(MUSL_DIR)/src/math/atanhf.c
|
C_SOURCES += $(MUSL_DIR)/src/math/tanhf.c $(MUSL_DIR)/src/math/atanhf.c
|
||||||
C_SOURCES += $(MUSL_DIR)/src/math/expm1f.c $(MUSL_DIR)/src/math/log1pf.c
|
C_SOURCES += $(MUSL_DIR)/src/math/expm1f.c $(MUSL_DIR)/src/math/log1pf.c
|
||||||
|
C_SOURCES += $(MUSL_DIR)/src/math/expf.c $(MUSL_DIR)/src/math/exp2f_data.c
|
||||||
|
C_SOURCES += $(MUSL_DIR)/src/math/__math_oflowf.c
|
||||||
|
C_SOURCES += $(MUSL_DIR)/src/math/__math_uflowf.c
|
||||||
|
C_SOURCES += $(MUSL_DIR)/src/math/__math_xflowf.c
|
||||||
|
|
||||||
CXX_SOURCES += src/ldpc_wrapper.cpp
|
CXX_SOURCES += src/ldpc_wrapper.cpp
|
||||||
|
|
||||||
|
|
@ -24,6 +28,14 @@ OPENCM3_LIB := opencm3_stm32f4
|
||||||
PREFIX ?= arm-none-eabi-
|
PREFIX ?= arm-none-eabi-
|
||||||
|
|
||||||
|
|
||||||
|
GOLD_CODE_NBITS ?= 5
|
||||||
|
FMEAS_ADC_SAMPLING_RATE ?= 1000
|
||||||
|
FMEAS_ADC_MAX ?= 4096
|
||||||
|
FMEAS_FFT_LEN ?= 256
|
||||||
|
FMEAS_FFT_WINDOW ?= gaussian
|
||||||
|
FMEAS_FFT_WINDOW_SIGMA ?= 8.0
|
||||||
|
|
||||||
|
|
||||||
CC := $(PREFIX)gcc
|
CC := $(PREFIX)gcc
|
||||||
CXX := $(PREFIX)g++
|
CXX := $(PREFIX)g++
|
||||||
LD := $(PREFIX)gcc
|
LD := $(PREFIX)gcc
|
||||||
|
|
@ -32,6 +44,7 @@ AS := $(PREFIX)as
|
||||||
OBJCOPY := $(PREFIX)objcopy
|
OBJCOPY := $(PREFIX)objcopy
|
||||||
OBJDUMP := $(PREFIX)objdump
|
OBJDUMP := $(PREFIX)objdump
|
||||||
GDB := $(PREFIX)gdb
|
GDB := $(PREFIX)gdb
|
||||||
|
PYTHON3 ?= python3
|
||||||
|
|
||||||
OPENCM3_DIR_ABS := $(abspath $(OPENCM3_DIR))
|
OPENCM3_DIR_ABS := $(abspath $(OPENCM3_DIR))
|
||||||
CMSIS_DIR_ABS := $(abspath $(CMSIS_DIR))
|
CMSIS_DIR_ABS := $(abspath $(CMSIS_DIR))
|
||||||
|
|
@ -41,14 +54,17 @@ TINYAES_DIR_ABS := $(abspath $(TINYAES_DIR))
|
||||||
MUSL_DIR_ABS := $(abspath $(MUSL_DIR))
|
MUSL_DIR_ABS := $(abspath $(MUSL_DIR))
|
||||||
|
|
||||||
CFLAGS += -I$(OPENCM3_DIR_ABS)/include -Imspdebug/util -Imspdebug/drivers
|
CFLAGS += -I$(OPENCM3_DIR_ABS)/include -Imspdebug/util -Imspdebug/drivers
|
||||||
CFLAGS += -I$(CMSIS_DIR_ABS)/CMSIS/DSP/Include -I$(CMSIS_DIR_ABS)/CMSIS/Core/Include
|
CFLAGS += -I$(CMSIS_DIR_ABS)/CMSIS/DSP/Include -I$(CMSIS_DIR_ABS)/CMSIS/Core/Include -Dhidden=
|
||||||
CFLAGS += -I$(abspath musl_include_shims)
|
CFLAGS += -I$(abspath musl_include_shims) -Ilevmarq -D
|
||||||
|
|
||||||
CFLAGS += -Os -std=gnu11 -g -DSTM32F4
|
CFLAGS += -Os -std=gnu11 -g -DSTM32F4
|
||||||
# Note: libopencm3 requires some standard libc definitions from stdint.h and stdbool.h, so we don't pass -nostdinc here.
|
# Note: libopencm3 requires some standard libc definitions from stdint.h and stdbool.h, so we don't pass -nostdinc here.
|
||||||
CFLAGS += -nostdlib -ffreestanding
|
CFLAGS += -nostdlib -ffreestanding
|
||||||
CFLAGS += -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
CFLAGS += -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||||
CFLAGS += -fno-common -ffunction-sections -fdata-sections
|
CFLAGS += -fno-common -ffunction-sections -fdata-sections
|
||||||
|
CFLAGS += -DGOLD_CODE_NBITS=$(GOLD_CODE_NBITS) -DFMEAS_FFT_LEN=$(FMEAS_FFT_LEN) -DFMEAS_ADC_MAX=$(FMEAS_ADC_MAX)
|
||||||
|
CFLAGS += -DFMEAS_ADC_SAMPLING_RATE=$(FMEAS_ADC_SAMPLING_RATE) -DFMEAS_FFT_WINDOW=$(FMEAS_FFT_WINDOW)
|
||||||
|
CFLAGS += -DFMEAS_FFT_WINDOW_SIGMA=$(FMEAS_FFT_WINDOW_SIGMA)
|
||||||
|
|
||||||
INT_CFLAGS += -Wall -Wextra -Wpedantic -Wshadow -Wimplicit-function-declaration -Wundef
|
INT_CFLAGS += -Wall -Wextra -Wpedantic -Wshadow -Wimplicit-function-declaration -Wundef
|
||||||
INT_CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes
|
INT_CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes
|
||||||
|
|
@ -71,7 +87,13 @@ all: $(BUILDDIR)/$(BINARY)
|
||||||
|
|
||||||
OBJS := $(addprefix $(BUILDDIR)/,$(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o))
|
OBJS := $(addprefix $(BUILDDIR)/,$(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o))
|
||||||
|
|
||||||
$(BUILDDIR)/$(BINARY): $(OBJS) $(OPENCM3_DIR)/lib/lib$(OPENCM3_LIB).a $(BUILDDIR)/libsodium/src/libsodium/.libs/libsodium.a $(BUILDDIR)/tinyaes/aes.o
|
$(BUILDDIR)/$(BINARY): $(OBJS) \
|
||||||
|
$(OPENCM3_DIR)/lib/lib$(OPENCM3_LIB).a \
|
||||||
|
$(BUILDDIR)/libsodium/src/libsodium/.libs/libsodium.a \
|
||||||
|
$(BUILDDIR)/tinyaes/aes.o \
|
||||||
|
$(BUILDDIR)/levmarq/levmarq.o \
|
||||||
|
$(BUILDDIR)/generated/gold_code_$(GOLD_CODE_NBITS).o \
|
||||||
|
$(BUILDDIR)/generated/fmeas_fft_window.o
|
||||||
$(LD) -T$(LDSCRIPT) $(LDFLAGS) -o $@ -Wl,-Map=$(BUILDDIR)/src/$*.map $^
|
$(LD) -T$(LDSCRIPT) $(LDFLAGS) -o $@ -Wl,-Map=$(BUILDDIR)/src/$*.map $^
|
||||||
|
|
||||||
$(BUILDDIR)/src/%.o: src/%.c
|
$(BUILDDIR)/src/%.o: src/%.c
|
||||||
|
|
@ -82,6 +104,10 @@ $(BUILDDIR)/src/%.o: src/%.cpp
|
||||||
mkdir -p $(@D)
|
mkdir -p $(@D)
|
||||||
$(CXX) $(CXXFLAGS) -o $@ -c $<
|
$(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
$(BUILDDIR)/generated/%.o: $(BUILDDIR)/generated/%.c
|
||||||
|
mkdir -p $(@D)
|
||||||
|
$(CC) $(CFLAGS) $(INT_CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
$(BUILDDIR)/%.o: %.c
|
$(BUILDDIR)/%.o: %.c
|
||||||
mkdir -p $(@D)
|
mkdir -p $(@D)
|
||||||
$(CC) $(CFLAGS) $(EXT_CFLAGS) -o $@ -c $<
|
$(CC) $(CFLAGS) $(EXT_CFLAGS) -o $@ -c $<
|
||||||
|
|
@ -97,11 +123,21 @@ $(BUILDDIR)/tinyaes/aes.o:
|
||||||
mkdir -p $(@D)
|
mkdir -p $(@D)
|
||||||
make -C $(@D) -f $(TINYAES_DIR_ABS)/Makefile VPATH=$(TINYAES_DIR_ABS) CFLAGS="$(CFLAGS) -c" CC=$(CC) LD=$(LD) AR=$(AR) aes.o
|
make -C $(@D) -f $(TINYAES_DIR_ABS)/Makefile VPATH=$(TINYAES_DIR_ABS) CFLAGS="$(CFLAGS) -c" CC=$(CC) LD=$(LD) AR=$(AR) aes.o
|
||||||
|
|
||||||
ldpc_decoder_test.so: ldpc_decoder.c
|
$(BUILDDIR)/generated/gold_code_%.c:
|
||||||
|
mkdir -p $(@D)
|
||||||
|
$(PYTHON3) tools/gold_code_header_gen.py $* > $@
|
||||||
|
|
||||||
|
$(BUILDDIR)/generated/fmeas_fft_window.c:
|
||||||
|
mkdir -p $(@D)
|
||||||
|
$(PYTHON3) tools/fft_window_header_gen.py -v fmeas_fft_window_table $(FMEAS_FFT_WINDOW) $(FMEAS_FFT_LEN) $(FMEAS_FFT_WINDOW_SIGMA) > $@
|
||||||
|
|
||||||
|
|
||||||
|
build/ldpc_decoder_test.so: src/ldpc_decoder.c
|
||||||
gcc -fPIC -shared -Wall -Wextra -Wpedantic -std=gnu11 -O0 -g -o $@ $^
|
gcc -fPIC -shared -Wall -Wextra -Wpedantic -std=gnu11 -O0 -g -o $@ $^
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-rm -r $(BUILDDIR)/src
|
-rm -r $(BUILDDIR)/src
|
||||||
|
-rm -r $(BUILDDIR)/generated
|
||||||
-rm $(BUILDDIR)/$(BINARY)
|
-rm $(BUILDDIR)/$(BINARY)
|
||||||
|
|
||||||
mrproper: clean
|
mrproper: clean
|
||||||
|
|
|
||||||
1
controller/fw/levmarq
Submodule
1
controller/fw/levmarq
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit d7734ce5a436b891d00dd3445dd0b57b1dfbe778
|
||||||
94
controller/fw/src/freq_meas.c
Normal file
94
controller/fw/src/freq_meas.c
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <arm_math.h>
|
||||||
|
#include <levmarq.h>
|
||||||
|
|
||||||
|
#include "freq_meas.h"
|
||||||
|
#include "sr_global.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)
|
||||||
|
|
||||||
|
float 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];
|
||||||
|
for (size_t i=0; i<FMEAS_FFT_LEN; i++)
|
||||||
|
in_buf[i] = (float)adc_buf[i] / (float)FMEAS_ADC_MAX * fmeas_fft_window_table[i];
|
||||||
|
|
||||||
|
arm_rfft_fast_instance_f32 fft_inst;
|
||||||
|
if ((rc = arm_rfft_init_name(FMEAS_FFT_LEN)(&fft_inst)) != ARM_MATH_SUCCESS)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
arm_rfft_fast_f32(&fft_inst, in_buf, out_buf, 0);
|
||||||
|
|
||||||
|
#define FMEAS_FFT_WINDOW_MIN_F 30.0f
|
||||||
|
#define FMEAS_FFT_WINDOW_MAX_F 70.0f
|
||||||
|
const float binsize = (float)FMEAS_ADC_SAMPLING_RATE / FMEAS_FFT_LEN;
|
||||||
|
const int first_bin = (int)(FMEAS_FFT_WINDOW_MIN_F / binsize);
|
||||||
|
const int last_bin = (int)(FMEAS_FFT_WINDOW_MAX_F / binsize + 0.5f);
|
||||||
|
const int nbins = last_bin - first_bin + 1;
|
||||||
|
|
||||||
|
/* Copy real values of target data to front of output buffer */
|
||||||
|
for (size_t i=0; i<nbins; i++)
|
||||||
|
out_buf[i] = out_buf[2 * (first_bin + i)];
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
if (levmarq(3, ¶ms, nbins, out_buf, NULL, func_gauss, func_gauss_grad, NULL, &lmstat))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*out = (params[1] + first_bin) * binsize;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float func_gauss(float *params, int x, void *userdata) {
|
||||||
|
UNUSED(userdata);
|
||||||
|
float a = params[0];
|
||||||
|
float mu = params[1];
|
||||||
|
float sigma = params[2];
|
||||||
|
return a*expf(-arm_power_f32((x-mu), 2.0f/(2.0f*(sigma*sigma))));
|
||||||
|
}
|
||||||
|
|
||||||
|
float func_gauss_grad(float *out, float *params, int x, void *userdata) {
|
||||||
|
UNUSED(userdata);
|
||||||
|
float a = params[0];
|
||||||
|
float mu = params[1];
|
||||||
|
float sigma = params[2];
|
||||||
|
return -(x-mu) / ( sigma*sigma*sigma * 2.5066282746310002f) * a*expf(-arm_power_f32((x-mu), 2.0f/(2.0f*(sigma*sigma))));
|
||||||
|
}
|
||||||
7
controller/fw/src/freq_meas.h
Normal file
7
controller/fw/src/freq_meas.h
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
#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__ */
|
||||||
4
controller/fw/src/gold_code.h
Normal file
4
controller/fw/src/gold_code.h
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
/* header file for generated gold code tables */
|
||||||
|
|
||||||
|
extern const uint8_t * const gold_code_table;
|
||||||
59
controller/fw/tools/fft_window_header_gen.py
Normal file
59
controller/fw/tools/fft_window_header_gen.py
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
#!/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};')
|
||||||
|
|
||||||
45
controller/fw/tools/gold_code_header_gen.py
Normal file
45
controller/fw/tools/gold_code_header_gen.py
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import argparse
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
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.')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
print('#include <unistd.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 {2**args.n // 8} bytes in big-endian byte order.')
|
||||||
|
print(f' */')
|
||||||
|
print(f'const uint8_t gold_code_{args.n}bit[] = {{')
|
||||||
|
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()
|
||||||
|
print(f'const uint8_t * const gold_code_table __attribute__((weak)) = gold_code_{args.n}bit;')
|
||||||
|
|
@ -33,13 +33,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 12,
|
"execution_count": 4,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "45cbf0c7c4314a3386adf52c261b1505",
|
"model_id": "171a6975a39e48bcac5e1247903b70f4",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -53,10 +53,10 @@
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"[<matplotlib.lines.Line2D at 0x7f8371954d00>]"
|
"[<matplotlib.lines.Line2D at 0x7f0144563d30>]"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 12,
|
"execution_count": 4,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
|
|
@ -88,13 +88,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 10,
|
"execution_count": 6,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "125cd5cc3ac44df5885f2c82cfa80c11",
|
"model_id": "2b835c8fb082428cabc1ad9112286728",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -111,7 +111,7 @@
|
||||||
"(1e-06, 0.5)"
|
"(1e-06, 0.5)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 10,
|
"execution_count": 6,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
|
|
@ -141,13 +141,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 11,
|
"execution_count": 7,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "65216e331e154ee980d16ae5de7fbfcd",
|
"model_id": "94ca3cb49e7d452dab8f7e2e8d632b84",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -164,7 +164,7 @@
|
||||||
"(5e-07, 0.02)"
|
"(5e-07, 0.02)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 11,
|
"execution_count": 7,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
|
|
@ -206,13 +206,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 9,
|
"execution_count": 8,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "d5721ab27d01416fb7fce8449b5d2289",
|
"model_id": "91a04300b9164bd7a9915d0028f3e563",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -242,13 +242,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 15,
|
"execution_count": 9,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "c419327f1f4f43c1903d3817d4651241",
|
"model_id": "2811a79d4ad8487f822750e4419ccfdb",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -278,13 +278,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 16,
|
"execution_count": 10,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "7c1941babb2e4d0c951d060fa9a4ba78",
|
"model_id": "c678197e011e4ab4982d3e1d2a2cee9a",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -316,13 +316,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 17,
|
"execution_count": 11,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "6034b96d5f08488a84d94b82cf319047",
|
"model_id": "52bcd29a41a54ed1bf9dc63e0c9e83d8",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -356,7 +356,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 18,
|
"execution_count": 12,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
|
@ -365,7 +365,7 @@
|
||||||
"15.923566878980893"
|
"15.923566878980893"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 18,
|
"execution_count": 12,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "e612fe37a7c34ceaa77e8bc587b8e065",
|
"model_id": "0b088957d9a24a74ab1b81d68099aa99",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -177,7 +177,7 @@
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "f8fa09f5053c4c52866ef240c789e741",
|
"model_id": "8a6f7e9ac8f04d1b84035c29623cfa99",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -240,7 +240,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 13,
|
"execution_count": 10,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
|
@ -249,7 +249,7 @@
|
||||||
"(200.0, 800.0)"
|
"(200.0, 800.0)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 13,
|
"execution_count": 10,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
|
|
@ -260,13 +260,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 10,
|
"execution_count": 11,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "e8e8458ea5914a939c7188785efd286c",
|
"model_id": "a3824e732a0647d4a12e8c5a567f5dc0",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -293,13 +293,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 11,
|
"execution_count": 12,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "875deca2c3d84e069dd0a5eaef4ea0aa",
|
"model_id": "342f89b5d55f435ab132deb5d051c926",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -370,13 +370,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 12,
|
"execution_count": 13,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "a36a994f6f484a6cba81b6e680c9eee1",
|
"model_id": "33431729d479469cb89bcf86e22508ad",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -426,13 +426,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 13,
|
"execution_count": 14,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "e4116959544f44f6a4b898419a5d51db",
|
"model_id": "e8a4ecab028f4fcf8d9821dd66a42027",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -510,7 +510,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 14,
|
"execution_count": 15,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
|
|
@ -529,13 +529,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 15,
|
"execution_count": 16,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "09069e2c9cb740d5b58846371aeea0f2",
|
"model_id": "bcf4b384d95949c38a4754cdb47ae512",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -560,7 +560,7 @@
|
||||||
"5.0"
|
"5.0"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 15,
|
"execution_count": 16,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
|
|
@ -597,13 +597,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 16,
|
"execution_count": 17,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "b812e4b240a642398f09bb3cff8f5cee",
|
"model_id": "cbc03380a4234b4d8160d25e867ff5a9",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -620,7 +620,7 @@
|
||||||
"(1.6666666666666667e-05, 0.5)"
|
"(1.6666666666666667e-05, 0.5)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 16,
|
"execution_count": 17,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
|
|
@ -656,13 +656,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 27,
|
"execution_count": 18,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "c835382368b6423ab5446835c5785afd",
|
"model_id": "8eb3621b74c04c4fb7dd3e919f0d1fed",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
|
@ -679,7 +679,7 @@
|
||||||
"(5e-07, 0.02)"
|
"(5e-07, 0.02)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 27,
|
"execution_count": 18,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue