spectre-core 0.0.9__py3-none-any.whl → 0.0.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- spectre_core/__init__.py +0 -3
- spectre_core/_file_io/__init__.py +15 -0
- spectre_core/_file_io/file_handlers.py +128 -0
- spectre_core/capture_configs/__init__.py +29 -0
- spectre_core/capture_configs/_capture_config.py +85 -0
- spectre_core/capture_configs/_capture_templates.py +222 -0
- spectre_core/capture_configs/_parameters.py +110 -0
- spectre_core/capture_configs/_pconstraints.py +82 -0
- spectre_core/capture_configs/_ptemplates.py +450 -0
- spectre_core/capture_configs/_pvalidators.py +171 -0
- spectre_core/chunks/__init__.py +17 -201
- spectre_core/chunks/{base.py → _base.py} +15 -60
- spectre_core/chunks/_chunks.py +200 -0
- spectre_core/chunks/{factory.py → _factory.py} +6 -7
- spectre_core/chunks/library/{callisto/chunk.py → _callisto.py} +4 -7
- spectre_core/chunks/library/{fixed/chunk.py → _fixed_center_frequency.py} +7 -64
- spectre_core/chunks/library/_swept_center_frequency.py +103 -0
- spectre_core/config/__init__.py +20 -0
- spectre_core/config/_paths.py +77 -0
- spectre_core/config/_time_formats.py +15 -0
- spectre_core/exceptions.py +4 -5
- spectre_core/logging/__init__.py +11 -0
- spectre_core/logging/_configure.py +35 -0
- spectre_core/logging/_decorators.py +19 -0
- spectre_core/{logging.py → logging/_log_handlers.py} +13 -58
- spectre_core/plotting/__init__.py +7 -1
- spectre_core/plotting/{base.py → _base.py} +40 -20
- spectre_core/plotting/_format.py +18 -0
- spectre_core/plotting/{panel_stack.py → _panel_stack.py} +48 -48
- spectre_core/plotting/_panels.py +234 -0
- spectre_core/post_processing/__init__.py +10 -2
- spectre_core/post_processing/_base.py +119 -0
- spectre_core/post_processing/{factory.py → _factory.py} +7 -6
- spectre_core/post_processing/{post_processor.py → _post_processor.py} +3 -3
- spectre_core/post_processing/library/_fixed_center_frequency.py +115 -0
- spectre_core/post_processing/library/_swept_center_frequency.py +382 -0
- spectre_core/receivers/__init__.py +13 -2
- spectre_core/receivers/_base.py +180 -0
- spectre_core/receivers/{factory.py → _factory.py} +2 -2
- spectre_core/receivers/_spec_names.py +20 -0
- spectre_core/receivers/gr/__init__.py +3 -0
- spectre_core/receivers/gr/_base.py +33 -0
- spectre_core/receivers/gr/_rsp1a.py +158 -0
- spectre_core/receivers/gr/_rspduo.py +227 -0
- spectre_core/receivers/gr/_test.py +123 -0
- spectre_core/receivers/library/_rsp1a.py +61 -0
- spectre_core/receivers/library/_rspduo.py +69 -0
- spectre_core/receivers/library/_sdrplay_receiver.py +185 -0
- spectre_core/receivers/library/_test.py +221 -0
- spectre_core/spectrograms/__init__.py +18 -0
- spectre_core/spectrograms/{analytical.py → _analytical.py} +29 -27
- spectre_core/spectrograms/{array_operations.py → _array_operations.py} +47 -1
- spectre_core/spectrograms/{spectrogram.py → _spectrogram.py} +62 -35
- spectre_core/spectrograms/{transform.py → _transform.py} +76 -89
- spectre_core/{post_processing/library → wgetting}/__init__.py +4 -5
- spectre_core/wgetting/_callisto.py +155 -0
- {spectre_core-0.0.9.dist-info → spectre_core-0.0.11.dist-info}/METADATA +1 -1
- spectre_core-0.0.11.dist-info/RECORD +64 -0
- spectre_core/cfg.py +0 -116
- spectre_core/chunks/library/__init__.py +0 -8
- spectre_core/chunks/library/callisto/__init__.py +0 -0
- spectre_core/chunks/library/fixed/__init__.py +0 -0
- spectre_core/chunks/library/sweep/__init__.py +0 -0
- spectre_core/chunks/library/sweep/chunk.py +0 -400
- spectre_core/dynamic_imports.py +0 -22
- spectre_core/file_handlers/base.py +0 -68
- spectre_core/file_handlers/configs.py +0 -271
- spectre_core/file_handlers/json.py +0 -40
- spectre_core/file_handlers/text.py +0 -21
- spectre_core/plotting/factory.py +0 -26
- spectre_core/plotting/format.py +0 -19
- spectre_core/plotting/library/__init__.py +0 -7
- spectre_core/plotting/library/frequency_cuts/panel.py +0 -74
- spectre_core/plotting/library/integral_over_frequency/panel.py +0 -34
- spectre_core/plotting/library/spectrogram/panel.py +0 -92
- spectre_core/plotting/library/time_cuts/panel.py +0 -77
- spectre_core/plotting/panel_register.py +0 -13
- spectre_core/post_processing/base.py +0 -132
- spectre_core/post_processing/library/fixed/__init__.py +0 -0
- spectre_core/post_processing/library/fixed/event_handler.py +0 -40
- spectre_core/post_processing/library/sweep/event_handler.py +0 -54
- spectre_core/receivers/base.py +0 -422
- spectre_core/receivers/library/__init__.py +0 -7
- spectre_core/receivers/library/rsp1a/__init__.py +0 -0
- spectre_core/receivers/library/rsp1a/gr/__init__.py +0 -0
- spectre_core/receivers/library/rsp1a/gr/fixed.py +0 -104
- spectre_core/receivers/library/rsp1a/gr/sweep.py +0 -129
- spectre_core/receivers/library/rsp1a/receiver.py +0 -68
- spectre_core/receivers/library/rspduo/__init__.py +0 -0
- spectre_core/receivers/library/rspduo/gr/__init__.py +0 -0
- spectre_core/receivers/library/rspduo/gr/tuner_1_fixed.py +0 -114
- spectre_core/receivers/library/rspduo/gr/tuner_1_sweep.py +0 -131
- spectre_core/receivers/library/rspduo/gr/tuner_2_fixed.py +0 -120
- spectre_core/receivers/library/rspduo/gr/tuner_2_sweep.py +0 -119
- spectre_core/receivers/library/rspduo/receiver.py +0 -97
- spectre_core/receivers/library/test/__init__.py +0 -0
- spectre_core/receivers/library/test/gr/__init__.py +0 -0
- spectre_core/receivers/library/test/gr/cosine_signal_1.py +0 -83
- spectre_core/receivers/library/test/gr/tagged_staircase.py +0 -93
- spectre_core/receivers/library/test/receiver.py +0 -203
- spectre_core/receivers/validators.py +0 -231
- spectre_core/web_fetch/callisto.py +0 -101
- spectre_core-0.0.9.dist-info/RECORD +0 -74
- /spectre_core/chunks/{chunk_register.py → _register.py} +0 -0
- /spectre_core/post_processing/{event_handler_register.py → _register.py} +0 -0
- /spectre_core/receivers/{receiver_register.py → _register.py} +0 -0
- {spectre_core-0.0.9.dist-info → spectre_core-0.0.11.dist-info}/LICENSE +0 -0
- {spectre_core-0.0.9.dist-info → spectre_core-0.0.11.dist-info}/WHEEL +0 -0
- {spectre_core-0.0.9.dist-info → spectre_core-0.0.11.dist-info}/top_level.txt +0 -0
@@ -1,119 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
# -*- coding: utf-8 -*-
|
3
|
-
|
4
|
-
#
|
5
|
-
# SPDX-License-Identifier: GPL-3.0
|
6
|
-
#
|
7
|
-
# GNU Radio Python Flow Graph
|
8
|
-
# Title: Not titled yet
|
9
|
-
# GNU Radio version: 3.10.1.1
|
10
|
-
|
11
|
-
from gnuradio import gr
|
12
|
-
from gnuradio.filter import firdes
|
13
|
-
from gnuradio.fft import window
|
14
|
-
import sys
|
15
|
-
import signal
|
16
|
-
from argparse import ArgumentParser
|
17
|
-
from gnuradio.eng_arg import eng_float, intx
|
18
|
-
from gnuradio import eng_notation
|
19
|
-
from gnuradio import sdrplay3
|
20
|
-
from gnuradio import spectre
|
21
|
-
|
22
|
-
from spectre_core.cfg import CHUNKS_DIR_PATH
|
23
|
-
from spectre_core.file_handlers.configs import CaptureConfig
|
24
|
-
|
25
|
-
|
26
|
-
class tuner_2_sweep(gr.top_block):
|
27
|
-
def __init__(self,
|
28
|
-
capture_config: CaptureConfig):
|
29
|
-
gr.top_block.__init__(self, "tuner_2_sweep", catch_exceptions=True)
|
30
|
-
|
31
|
-
##################################################
|
32
|
-
# Unpack capture config
|
33
|
-
##################################################
|
34
|
-
samp_rate = capture_config['samp_rate']
|
35
|
-
bandwidth = capture_config['bandwidth']
|
36
|
-
min_freq = capture_config['min_freq']
|
37
|
-
max_freq = capture_config['max_freq']
|
38
|
-
freq_step = capture_config['freq_step']
|
39
|
-
samples_per_step = capture_config['samples_per_step']
|
40
|
-
IF_gain = capture_config['IF_gain']
|
41
|
-
RF_gain = capture_config['RF_gain']
|
42
|
-
chunk_size = capture_config['chunk_size']
|
43
|
-
start_freq = min_freq + samp_rate/2
|
44
|
-
tag = capture_config['tag']
|
45
|
-
|
46
|
-
##################################################
|
47
|
-
# Blocks
|
48
|
-
##################################################
|
49
|
-
self.spectre_sweep_driver_0 = spectre.sweep_driver(min_freq,
|
50
|
-
max_freq,
|
51
|
-
freq_step,
|
52
|
-
samp_rate,
|
53
|
-
samples_per_step,
|
54
|
-
'freq')
|
55
|
-
self.spectre_batched_file_sink_0 = spectre.batched_file_sink(CHUNKS_DIR_PATH,
|
56
|
-
tag,
|
57
|
-
chunk_size,
|
58
|
-
samp_rate,
|
59
|
-
True,
|
60
|
-
'freq',
|
61
|
-
start_freq)
|
62
|
-
self.sdrplay3_rspduo_0 = sdrplay3.rspduo(
|
63
|
-
'',
|
64
|
-
rspduo_mode="Single Tuner",
|
65
|
-
antenna="Tuner 2 50 ohm",
|
66
|
-
stream_args=sdrplay3.stream_args(
|
67
|
-
output_type='fc32',
|
68
|
-
channels_size=1
|
69
|
-
),
|
70
|
-
)
|
71
|
-
self.sdrplay3_rspduo_0.set_sample_rate(samp_rate, True)
|
72
|
-
self.sdrplay3_rspduo_0.set_center_freq(start_freq, True)
|
73
|
-
self.sdrplay3_rspduo_0.set_bandwidth(bandwidth)
|
74
|
-
self.sdrplay3_rspduo_0.set_antenna("Tuner 2 50 ohm")
|
75
|
-
self.sdrplay3_rspduo_0.set_gain_mode(False)
|
76
|
-
self.sdrplay3_rspduo_0.set_gain(IF_gain, 'IF', True)
|
77
|
-
self.sdrplay3_rspduo_0.set_gain(RF_gain, 'RF', True)
|
78
|
-
self.sdrplay3_rspduo_0.set_freq_corr(0)
|
79
|
-
self.sdrplay3_rspduo_0.set_dc_offset_mode(False)
|
80
|
-
self.sdrplay3_rspduo_0.set_iq_balance_mode(False)
|
81
|
-
self.sdrplay3_rspduo_0.set_agc_setpoint(-30)
|
82
|
-
self.sdrplay3_rspduo_0.set_rf_notch_filter(False)
|
83
|
-
self.sdrplay3_rspduo_0.set_dab_notch_filter(True)
|
84
|
-
self.sdrplay3_rspduo_0.set_am_notch_filter(False)
|
85
|
-
self.sdrplay3_rspduo_0.set_biasT(False)
|
86
|
-
self.sdrplay3_rspduo_0.set_stream_tags(True)
|
87
|
-
self.sdrplay3_rspduo_0.set_debug_mode(False)
|
88
|
-
self.sdrplay3_rspduo_0.set_sample_sequence_gaps_check(False)
|
89
|
-
self.sdrplay3_rspduo_0.set_show_gain_changes(False)
|
90
|
-
|
91
|
-
|
92
|
-
##################################################
|
93
|
-
# Connections
|
94
|
-
##################################################
|
95
|
-
self.msg_connect((self.spectre_sweep_driver_0, 'freq'), (self.sdrplay3_rspduo_0, 'freq'))
|
96
|
-
self.connect((self.sdrplay3_rspduo_0, 0), (self.spectre_batched_file_sink_0, 0))
|
97
|
-
self.connect((self.sdrplay3_rspduo_0, 0), (self.spectre_sweep_driver_0, 0))
|
98
|
-
|
99
|
-
|
100
|
-
def main(capture_config: CaptureConfig,
|
101
|
-
top_block_cls=tuner_2_sweep,
|
102
|
-
options=None):
|
103
|
-
tb = top_block_cls(capture_config)
|
104
|
-
|
105
|
-
def sig_handler(sig=None, frame=None):
|
106
|
-
tb.stop()
|
107
|
-
tb.wait()
|
108
|
-
|
109
|
-
sys.exit(0)
|
110
|
-
|
111
|
-
signal.signal(signal.SIGINT, sig_handler)
|
112
|
-
signal.signal(signal.SIGTERM, sig_handler)
|
113
|
-
|
114
|
-
tb.start(1024)
|
115
|
-
|
116
|
-
tb.wait()
|
117
|
-
|
118
|
-
if __name__ == '__main__':
|
119
|
-
main()
|
@@ -1,97 +0,0 @@
|
|
1
|
-
# SPDX-FileCopyrightText: © 2024 Jimmy Fitzpatrick <jcfitzpatrick12@gmail.com>
|
2
|
-
# This file is part of SPECTRE
|
3
|
-
# SPDX-License-Identifier: GPL-3.0-or-later
|
4
|
-
|
5
|
-
from spectre_core.receivers.base import SDRPlayReceiver
|
6
|
-
from spectre_core.receivers.receiver_register import register_receiver
|
7
|
-
from spectre_core.receivers.library.rspduo.gr import (
|
8
|
-
tuner_1_fixed,
|
9
|
-
tuner_1_sweep,
|
10
|
-
tuner_2_fixed,
|
11
|
-
tuner_2_sweep
|
12
|
-
)
|
13
|
-
from spectre_core.file_handlers.configs import CaptureConfig
|
14
|
-
|
15
|
-
|
16
|
-
@register_receiver("rspduo")
|
17
|
-
class Receiver(SDRPlayReceiver):
|
18
|
-
def __init__(self, *args, **kwargs):
|
19
|
-
super().__init__(*args, **kwargs)
|
20
|
-
|
21
|
-
|
22
|
-
def _set_capture_methods(self) -> None:
|
23
|
-
self._capture_methods = {
|
24
|
-
"tuner-1-fixed": self.__tuner_1_fixed,
|
25
|
-
"tuner-1-sweep": self.__tuner_1_sweep,
|
26
|
-
"tuner-2-fixed": self.__tuner_2_fixed,
|
27
|
-
"tuner-2-sweep": self.__tuner_2_sweep
|
28
|
-
}
|
29
|
-
|
30
|
-
|
31
|
-
def _set_validators(self) -> None:
|
32
|
-
self._validators = {
|
33
|
-
"tuner-1-fixed": self.__tuner_1_fixed_validator,
|
34
|
-
"tuner-1-sweep": self.__tuner_1_sweep_validator,
|
35
|
-
"tuner-2-fixed": self.__tuner_2_fixed_validator,
|
36
|
-
"tuner-2-sweep": self.__tuner_2_sweep_validator,
|
37
|
-
}
|
38
|
-
return
|
39
|
-
|
40
|
-
|
41
|
-
def _set_type_templates(self) -> None:
|
42
|
-
self._type_templates = {
|
43
|
-
"tuner-1-fixed": self._get_default_type_template("fixed"),
|
44
|
-
"tuner-1-sweep": self._get_default_type_template("sweep"),
|
45
|
-
"tuner-2-fixed": self._get_default_type_template("fixed"),
|
46
|
-
"tuner-2-sweep": self._get_default_type_template("sweep"),
|
47
|
-
}
|
48
|
-
|
49
|
-
def _set_specifications(self) -> None:
|
50
|
-
self._specifications = {
|
51
|
-
"center_freq_lower_bound": 1e3, # [Hz]
|
52
|
-
"center_freq_upper_bound": 2e9, # [Hz]
|
53
|
-
"samp_rate_lower_bound": 200e3, # [Hz]
|
54
|
-
"samp_rate_upper_bound": 10e6, # [Hz]
|
55
|
-
"bandwidth_lower_bound": 200e3, # [Hz]
|
56
|
-
"bandwidth_upper_bound": 8e6, # [Hz]
|
57
|
-
"IF_gain_upper_bound": -20, # [dB]
|
58
|
-
"RF_gain_upper_bound": 0, # [dB]
|
59
|
-
"api_latency": 50 * 1e-3 # [s]
|
60
|
-
}
|
61
|
-
|
62
|
-
|
63
|
-
def __tuner_1_fixed(self, capture_config: CaptureConfig) -> None:
|
64
|
-
tuner_1_fixed.main(capture_config)
|
65
|
-
|
66
|
-
|
67
|
-
def __tuner_1_sweep(self, capture_config: CaptureConfig) -> None:
|
68
|
-
tuner_1_sweep.main(capture_config)
|
69
|
-
|
70
|
-
|
71
|
-
def __tuner_2_fixed(self, capture_config: CaptureConfig) -> None:
|
72
|
-
tuner_2_fixed.main(capture_config)
|
73
|
-
|
74
|
-
|
75
|
-
def __tuner_2_sweep(self, capture_config: CaptureConfig) -> None:
|
76
|
-
tuner_2_sweep.main(capture_config)
|
77
|
-
|
78
|
-
|
79
|
-
def __tuner_1_fixed_validator(self, capture_config: CaptureConfig) -> None:
|
80
|
-
self._default_fixed_validator(capture_config)
|
81
|
-
self._sdrplay_validator(capture_config)
|
82
|
-
|
83
|
-
|
84
|
-
def __tuner_1_sweep_validator(self, capture_config: CaptureConfig) -> None:
|
85
|
-
self._default_sweep_validator(capture_config)
|
86
|
-
self._sdrplay_validator(capture_config)
|
87
|
-
|
88
|
-
|
89
|
-
def __tuner_2_fixed_validator(self, capture_config: CaptureConfig) -> None:
|
90
|
-
self._default_fixed_validator(capture_config)
|
91
|
-
self._sdrplay_validator(capture_config)
|
92
|
-
|
93
|
-
|
94
|
-
def __tuner_2_sweep_validator(self, capture_config: CaptureConfig) -> None:
|
95
|
-
self._default_sweep_validator(capture_config)
|
96
|
-
self._sdrplay_validator(capture_config)
|
97
|
-
|
File without changes
|
File without changes
|
@@ -1,83 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
# -*- coding: utf-8 -*-
|
3
|
-
|
4
|
-
#
|
5
|
-
# SPDX-License-Identifier: GPL-3.0
|
6
|
-
#
|
7
|
-
# GNU Radio Python Flow Graph
|
8
|
-
# Title: Not titled yet
|
9
|
-
# GNU Radio version: 3.10.1.1
|
10
|
-
|
11
|
-
# SPDX-FileCopyrightText: © 2024 Jimmy Fitzpatrick <jcfitzpatrick12@gmail.com>
|
12
|
-
# This file is part of SPECTRE
|
13
|
-
# SPDX-License-Identifier: GPL-3.0-or-later
|
14
|
-
|
15
|
-
import sys
|
16
|
-
import signal
|
17
|
-
from typing import Any
|
18
|
-
|
19
|
-
from gnuradio import analog
|
20
|
-
from gnuradio import blocks
|
21
|
-
from gnuradio import gr
|
22
|
-
from gnuradio.filter import firdes
|
23
|
-
from gnuradio.fft import window
|
24
|
-
from gnuradio.eng_arg import eng_float, intx
|
25
|
-
from gnuradio import eng_notation
|
26
|
-
from gnuradio import spectre
|
27
|
-
|
28
|
-
from spectre_core.cfg import CHUNKS_DIR_PATH
|
29
|
-
from spectre_core.file_handlers.configs import CaptureConfig
|
30
|
-
|
31
|
-
class cosine_signal_1(gr.top_block):
|
32
|
-
|
33
|
-
def __init__(self,
|
34
|
-
capture_config: CaptureConfig):
|
35
|
-
gr.top_block.__init__(self, "cosine-signal-1", catch_exceptions=True)
|
36
|
-
|
37
|
-
##################################################
|
38
|
-
# Unpack capture config
|
39
|
-
##################################################
|
40
|
-
samp_rate = capture_config['samp_rate']
|
41
|
-
tag = capture_config['tag']
|
42
|
-
chunk_size = capture_config['chunk_size']
|
43
|
-
frequency = capture_config['frequency']
|
44
|
-
amplitude = capture_config['amplitude']
|
45
|
-
|
46
|
-
##################################################
|
47
|
-
# Blocks
|
48
|
-
##################################################
|
49
|
-
self.spectre_batched_file_sink_0 = spectre.batched_file_sink(CHUNKS_DIR_PATH, tag, chunk_size, samp_rate)
|
50
|
-
self.blocks_throttle_0_1 = blocks.throttle(gr.sizeof_float*1, samp_rate,True)
|
51
|
-
self.blocks_throttle_0 = blocks.throttle(gr.sizeof_float*1, samp_rate,True)
|
52
|
-
self.blocks_null_source_1 = blocks.null_source(gr.sizeof_float*1)
|
53
|
-
self.blocks_float_to_complex_1 = blocks.float_to_complex(1)
|
54
|
-
self.analog_sig_source_x_0 = analog.sig_source_f(samp_rate, analog.GR_COS_WAVE, frequency, amplitude, 0, 0)
|
55
|
-
|
56
|
-
|
57
|
-
##################################################
|
58
|
-
# Connections
|
59
|
-
##################################################
|
60
|
-
self.connect((self.analog_sig_source_x_0, 0), (self.blocks_throttle_0, 0))
|
61
|
-
self.connect((self.blocks_float_to_complex_1, 0), (self.spectre_batched_file_sink_0, 0))
|
62
|
-
self.connect((self.blocks_null_source_1, 0), (self.blocks_throttle_0_1, 0))
|
63
|
-
self.connect((self.blocks_throttle_0, 0), (self.blocks_float_to_complex_1, 0))
|
64
|
-
self.connect((self.blocks_throttle_0_1, 0), (self.blocks_float_to_complex_1, 1))
|
65
|
-
|
66
|
-
|
67
|
-
def main(capture_config: CaptureConfig,
|
68
|
-
top_block_cls=cosine_signal_1,
|
69
|
-
options=None):
|
70
|
-
tb = top_block_cls(capture_config)
|
71
|
-
|
72
|
-
def sig_handler(sig=None, frame=None):
|
73
|
-
tb.stop()
|
74
|
-
tb.wait()
|
75
|
-
|
76
|
-
sys.exit(0)
|
77
|
-
|
78
|
-
signal.signal(signal.SIGINT, sig_handler)
|
79
|
-
signal.signal(signal.SIGTERM, sig_handler)
|
80
|
-
|
81
|
-
tb.start()
|
82
|
-
|
83
|
-
tb.wait()
|
@@ -1,93 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
# -*- coding: utf-8 -*-
|
3
|
-
|
4
|
-
#
|
5
|
-
# SPDX-License-Identifier: GPL-3.0
|
6
|
-
#
|
7
|
-
# GNU Radio Python Flow Graph
|
8
|
-
# Title: Not titled yet
|
9
|
-
# GNU Radio version: 3.10.1.1
|
10
|
-
|
11
|
-
# SPDX-FileCopyrightText: © 2024 Jimmy Fitzpatrick <jcfitzpatrick12@gmail.com>
|
12
|
-
# This file is part of SPECTRE
|
13
|
-
# SPDX-License-Identifier: GPL-3.0-or-later
|
14
|
-
|
15
|
-
import sys
|
16
|
-
import signal
|
17
|
-
from argparse import ArgumentParser
|
18
|
-
from typing import Any
|
19
|
-
|
20
|
-
from gnuradio import blocks
|
21
|
-
from gnuradio import gr
|
22
|
-
from gnuradio.filter import firdes
|
23
|
-
from gnuradio.fft import window
|
24
|
-
from gnuradio.eng_arg import eng_float, intx
|
25
|
-
from gnuradio import eng_notation
|
26
|
-
from gnuradio import spectre
|
27
|
-
|
28
|
-
from spectre_core.cfg import CHUNKS_DIR_PATH
|
29
|
-
from spectre_core.file_handlers.configs import CaptureConfig
|
30
|
-
|
31
|
-
class tagged_staircase(gr.top_block):
|
32
|
-
|
33
|
-
def __init__(self,
|
34
|
-
capture_config: CaptureConfig):
|
35
|
-
gr.top_block.__init__(self, "tagged-staircase", catch_exceptions=True)
|
36
|
-
|
37
|
-
##################################################
|
38
|
-
# Unpack capture config
|
39
|
-
##################################################
|
40
|
-
tag = capture_config['tag']
|
41
|
-
step_increment = capture_config['step_increment']
|
42
|
-
samp_rate = capture_config['samp_rate']
|
43
|
-
min_samples_per_step = capture_config['min_samples_per_step']
|
44
|
-
max_samples_per_step = capture_config['max_samples_per_step']
|
45
|
-
freq_step = capture_config['freq_step']
|
46
|
-
chunk_size = capture_config['chunk_size']
|
47
|
-
is_sweeping = True
|
48
|
-
|
49
|
-
##################################################
|
50
|
-
# Blocks
|
51
|
-
##################################################
|
52
|
-
self.spectre_tagged_staircase_0 = spectre.tagged_staircase(min_samples_per_step,
|
53
|
-
max_samples_per_step,
|
54
|
-
freq_step,
|
55
|
-
step_increment,
|
56
|
-
samp_rate)
|
57
|
-
self.spectre_batched_file_sink_0 = spectre.batched_file_sink(CHUNKS_DIR_PATH,
|
58
|
-
tag,
|
59
|
-
chunk_size,
|
60
|
-
samp_rate,
|
61
|
-
is_sweeping,
|
62
|
-
'rx_freq',
|
63
|
-
0
|
64
|
-
)
|
65
|
-
self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate, True)
|
66
|
-
|
67
|
-
|
68
|
-
##################################################
|
69
|
-
# Connections
|
70
|
-
##################################################
|
71
|
-
self.connect((self.blocks_throttle_0, 0), (self.spectre_batched_file_sink_0, 0))
|
72
|
-
self.connect((self.spectre_tagged_staircase_0, 0), (self.blocks_throttle_0, 0))
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
def main(capture_config: CaptureConfig,
|
78
|
-
top_block_cls=tagged_staircase,
|
79
|
-
options=None):
|
80
|
-
tb = top_block_cls(capture_config)
|
81
|
-
|
82
|
-
def sig_handler(sig=None, frame=None):
|
83
|
-
tb.stop()
|
84
|
-
tb.wait()
|
85
|
-
|
86
|
-
sys.exit(0)
|
87
|
-
|
88
|
-
signal.signal(signal.SIGINT, sig_handler)
|
89
|
-
signal.signal(signal.SIGTERM, sig_handler)
|
90
|
-
|
91
|
-
tb.start()
|
92
|
-
|
93
|
-
tb.wait()
|
@@ -1,203 +0,0 @@
|
|
1
|
-
# SPDX-FileCopyrightText: © 2024 Jimmy Fitzpatrick <jcfitzpatrick12@gmail.com>
|
2
|
-
# This file is part of SPECTRE
|
3
|
-
# SPDX-License-Identifier: GPL-3.0-or-later
|
4
|
-
|
5
|
-
from spectre_core.receivers import validators
|
6
|
-
from spectre_core.receivers.base import SPECTREReceiver
|
7
|
-
from spectre_core.receivers.receiver_register import register_receiver
|
8
|
-
from spectre_core.receivers.library.test.gr import cosine_signal_1
|
9
|
-
from spectre_core.receivers.library.test.gr import tagged_staircase
|
10
|
-
from spectre_core.file_handlers.configs import CaptureConfig
|
11
|
-
|
12
|
-
|
13
|
-
@register_receiver("test")
|
14
|
-
class Receiver(SPECTREReceiver):
|
15
|
-
def __init__(self, *args, **kwargs):
|
16
|
-
super().__init__(*args, **kwargs)
|
17
|
-
|
18
|
-
|
19
|
-
def _set_capture_methods(self) -> None:
|
20
|
-
self._capture_methods = {
|
21
|
-
"cosine-signal-1": self.__cosine_signal_1,
|
22
|
-
"tagged-staircase": self.__tagged_staircase
|
23
|
-
}
|
24
|
-
|
25
|
-
|
26
|
-
def _set_validators(self) -> None:
|
27
|
-
self._validators = {
|
28
|
-
"cosine-signal-1": self.__cosine_signal_1_validator,
|
29
|
-
"tagged-staircase": self.__tagged_staircase_validator
|
30
|
-
}
|
31
|
-
|
32
|
-
|
33
|
-
def _set_type_templates(self) -> None:
|
34
|
-
self._type_templates = {
|
35
|
-
"cosine-signal-1": {
|
36
|
-
"samp_rate": int, # [Hz]
|
37
|
-
"frequency": float, # [Hz]
|
38
|
-
"amplitude": float, # unitless
|
39
|
-
"chunk_size": int, # [s]
|
40
|
-
"joining_time": int, # [s]
|
41
|
-
"time_resolution": float, # [s]
|
42
|
-
"frequency_resolution": float, # [Hz]
|
43
|
-
"window_type": str, # the window type for the STFFT
|
44
|
-
"window_kwargs": dict, # keyword arguments for scipy get window function. Must be in order as in scipy documentation.
|
45
|
-
"window_size": int, # number of samples for the window
|
46
|
-
"hop": int, # STFFT hop shifts window by so many samples
|
47
|
-
"chunk_key": str, # maps to the corresponding chunk class
|
48
|
-
"event_handler_key": str, # maps to the event handler used in post processing
|
49
|
-
"watch_extension": str # event handlers watch for files with this extension
|
50
|
-
},
|
51
|
-
"tagged-staircase": {
|
52
|
-
"samp_rate": int, # [Hz]
|
53
|
-
"min_samples_per_step": int, # [samples]
|
54
|
-
"max_samples_per_step": int, # [samples]
|
55
|
-
"freq_step": float, # [Hz]
|
56
|
-
"step_increment": int, # [samples]
|
57
|
-
"chunk_size": int, # [s]
|
58
|
-
"joining_time": int, # [s]
|
59
|
-
"time_resolution": float, # [s]
|
60
|
-
"frequency_resolution": float, # [Hz]
|
61
|
-
"window_type": str, # the window type for the STFFT
|
62
|
-
"window_kwargs": dict, # keyword arguments for scipy get window function. Must be in order as in scipy documentation.
|
63
|
-
"window_size": int, # number of samples for the window
|
64
|
-
"hop": int, # keyword arguments for scipy STFFT class
|
65
|
-
"chunk_key": str, # maps to the corresponding chunk class
|
66
|
-
"event_handler_key": str, # maps to the event handler used in post processing
|
67
|
-
"watch_extension": str # event handlers watch for files with this extension
|
68
|
-
}
|
69
|
-
}
|
70
|
-
|
71
|
-
def _set_specifications(self) -> None:
|
72
|
-
self._specifications = {
|
73
|
-
"samp_rate_lower_bound": 64000
|
74
|
-
}
|
75
|
-
|
76
|
-
|
77
|
-
def __cosine_signal_1(self, capture_config: CaptureConfig) -> None:
|
78
|
-
cosine_signal_1.main(capture_config)
|
79
|
-
|
80
|
-
|
81
|
-
def __tagged_staircase(self, capture_config: CaptureConfig) -> None:
|
82
|
-
tagged_staircase.main(capture_config)
|
83
|
-
|
84
|
-
|
85
|
-
def __cosine_signal_1_validator(self, capture_config: CaptureConfig) -> None:
|
86
|
-
# unpack the capture config
|
87
|
-
samp_rate = capture_config["samp_rate"]
|
88
|
-
frequency = capture_config["frequency"]
|
89
|
-
amplitude = capture_config["amplitude"]
|
90
|
-
chunk_size = capture_config["chunk_size"]
|
91
|
-
window_type = capture_config["window_type"]
|
92
|
-
window_size = capture_config["window_size"]
|
93
|
-
hop = capture_config["hop"]
|
94
|
-
chunk_key = capture_config["chunk_key"]
|
95
|
-
event_handler_key = capture_config["event_handler_key"]
|
96
|
-
time_resolution = capture_config["time_resolution"]
|
97
|
-
frequency_resolution = capture_config["frequency_resolution"]
|
98
|
-
watch_extension = capture_config["watch_extension"]
|
99
|
-
|
100
|
-
validators.samp_rate_strictly_positive(samp_rate)
|
101
|
-
validators.chunk_size_strictly_positive(chunk_size)
|
102
|
-
validators.time_resolution(time_resolution, chunk_size)
|
103
|
-
validators.window(window_type,
|
104
|
-
{},
|
105
|
-
window_size,
|
106
|
-
chunk_size,
|
107
|
-
samp_rate)
|
108
|
-
validators.hop(hop)
|
109
|
-
validators.chunk_key(chunk_key,
|
110
|
-
"fixed")
|
111
|
-
validators.event_handler_key(event_handler_key,
|
112
|
-
"fixed")
|
113
|
-
validators.watch_extension(watch_extension,
|
114
|
-
"bin")
|
115
|
-
|
116
|
-
if samp_rate < self.specifications.get("samp_rate_lower_bound"):
|
117
|
-
raise ValueError((f"Sample rate must be greater than or equal to "
|
118
|
-
f"{self.specifications.get('samp_rate_lower_bound')}"))
|
119
|
-
|
120
|
-
if time_resolution != 0:
|
121
|
-
raise ValueError(f"Time resolution must be zero. "
|
122
|
-
f"Got {time_resolution} [s]")
|
123
|
-
|
124
|
-
if frequency_resolution != 0:
|
125
|
-
raise ValueError((f"Frequency resolution must be zero. "
|
126
|
-
f"Got {frequency_resolution}"))
|
127
|
-
|
128
|
-
# check that the sample rate is an integer multiple of the underlying signal frequency
|
129
|
-
if samp_rate % frequency != 0:
|
130
|
-
raise ValueError("The sampling rate must be some integer multiple of frequency")
|
131
|
-
|
132
|
-
a = samp_rate/frequency
|
133
|
-
if a < 2:
|
134
|
-
raise ValueError((f"The ratio of sampling rate over frequency must be a natural number greater than two. "
|
135
|
-
f"Got {a}"))
|
136
|
-
|
137
|
-
# ensuring the window type is rectangular
|
138
|
-
if window_type != "boxcar":
|
139
|
-
raise ValueError((f"The window type must be 'boxcar'. "
|
140
|
-
f"Got {window_type}"))
|
141
|
-
|
142
|
-
# analytical requirement
|
143
|
-
# if p is the number of sampled cycles, we can find that p = window_size / a
|
144
|
-
# the number of sampled cycles must be a positive natural number.
|
145
|
-
p = window_size / a
|
146
|
-
if window_size % a != 0:
|
147
|
-
raise ValueError((f"The number of sampled cycles must be a positive natural number. "
|
148
|
-
f"Computed that p={p}"))
|
149
|
-
|
150
|
-
|
151
|
-
if amplitude <= 0:
|
152
|
-
raise ValueError((f"The amplitude must be strictly positive. "
|
153
|
-
f"Got {amplitude}"))
|
154
|
-
|
155
|
-
|
156
|
-
def __tagged_staircase_validator(self, capture_config: CaptureConfig) -> None:
|
157
|
-
samp_rate = capture_config["samp_rate"]
|
158
|
-
min_samples_per_step = capture_config["min_samples_per_step"]
|
159
|
-
max_samples_per_step = capture_config["max_samples_per_step"]
|
160
|
-
freq_step = capture_config["freq_step"]
|
161
|
-
step_increment = capture_config["step_increment"]
|
162
|
-
chunk_size = capture_config["chunk_size"]
|
163
|
-
window_type = capture_config["window_type"]
|
164
|
-
window_kwargs = capture_config["window_kwargs"]
|
165
|
-
window_size = capture_config["window_size"]
|
166
|
-
hop = capture_config["hop"]
|
167
|
-
chunk_key = capture_config["chunk_key"]
|
168
|
-
event_handler_key = capture_config["event_handler_key"]
|
169
|
-
time_resolution = capture_config["time_resolution"]
|
170
|
-
watch_extension = capture_config["watch_extension"]
|
171
|
-
|
172
|
-
validators.samp_rate_strictly_positive(samp_rate)
|
173
|
-
validators.chunk_size_strictly_positive(chunk_size)
|
174
|
-
validators.time_resolution(time_resolution, chunk_size)
|
175
|
-
validators.window(window_type,
|
176
|
-
window_kwargs,
|
177
|
-
window_size,
|
178
|
-
chunk_size,
|
179
|
-
samp_rate)
|
180
|
-
validators.hop(hop)
|
181
|
-
validators.chunk_key(chunk_key, "sweep")
|
182
|
-
validators.event_handler_key(event_handler_key, "sweep")
|
183
|
-
validators.watch_extension(watch_extension,
|
184
|
-
"bin")
|
185
|
-
|
186
|
-
if freq_step != samp_rate:
|
187
|
-
raise ValueError(f"The frequency step must be equal to the sampling rate")
|
188
|
-
|
189
|
-
if min_samples_per_step <= 0:
|
190
|
-
raise ValueError((f"Minimum samples per step must be strictly positive. "
|
191
|
-
f"Got {min_samples_per_step}"))
|
192
|
-
|
193
|
-
if max_samples_per_step <= 0:
|
194
|
-
raise ValueError((f"Maximum samples per step must be strictly positive. "
|
195
|
-
f"Got {max_samples_per_step}"))
|
196
|
-
|
197
|
-
if step_increment <= 0:
|
198
|
-
raise ValueError((f"Step increment must be strictly positive. "
|
199
|
-
f"Got {step_increment}"))
|
200
|
-
|
201
|
-
if min_samples_per_step > max_samples_per_step:
|
202
|
-
raise ValueError((f"Minimum samples per step cannot be greater than the maximum samples per step. "
|
203
|
-
f"Got {min_samples_per_step}, which is greater than {max_samples_per_step}"))
|