summaryrefslogtreecommitdiff
path: root/controller/fw/tools
diff options
context:
space:
mode:
Diffstat (limited to 'controller/fw/tools')
-rw-r--r--controller/fw/tools/fft_window_header_gen.py59
-rw-r--r--controller/fw/tools/gold_code_header_gen.py45
2 files changed, 104 insertions, 0 deletions
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 <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;')