From ca01d52a8658ed01301f14a4d294097d4db533cf Mon Sep 17 00:00:00 2001 From: jaseg Date: Mon, 2 Mar 2020 19:42:36 +0100 Subject: Finishing up freq meas --- controller/fw/tools/fft_window_header_gen.py | 59 ++++++++++++++++++++++++++++ controller/fw/tools/gold_code_header_gen.py | 45 +++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 controller/fw/tools/fft_window_header_gen.py create mode 100644 controller/fw/tools/gold_code_header_gen.py (limited to 'controller/fw/tools') diff --git a/controller/fw/tools/fft_window_header_gen.py b/controller/fw/tools/fft_window_header_gen.py new file mode 100644 index 0000000..7df2ee3 --- /dev/null +++ b/controller/fw/tools/fft_window_header_gen.py @@ -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};') + diff --git a/controller/fw/tools/gold_code_header_gen.py b/controller/fw/tools/gold_code_header_gen.py new file mode 100644 index 0000000..e2bc210 --- /dev/null +++ b/controller/fw/tools/gold_code_header_gen.py @@ -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 ') + 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;') -- cgit