spectre-core 0.0.13__py3-none-any.whl → 0.0.15__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.
@@ -46,4 +46,5 @@ class PName(Enum):
46
46
  OBJECT = "object"
47
47
  OBS_LAT = "obs_lat"
48
48
  OBS_LON = "obs_lon"
49
- OBS_ALT = "obs_alt"
49
+ OBS_ALT = "obs_alt"
50
+ NORMALISED_GAIN = "normalised_gain"
@@ -7,7 +7,7 @@ from textwrap import dedent
7
7
  from copy import deepcopy
8
8
 
9
9
  from ._pnames import PName
10
- from ._pconstraints import BasePConstraint, EnforceSign, PowerOfTwo
10
+ from ._pconstraints import BasePConstraint, EnforceSign, PowerOfTwo, Bound
11
11
  from ._parameters import Parameter
12
12
 
13
13
  # value type
@@ -300,6 +300,14 @@ _base_ptemplates: dict[PName, PTemplate] = {
300
300
  pconstraints=[
301
301
  EnforceSign.non_positive
302
302
  ]),
303
+ PName.NORMALISED_GAIN: PTemplate(PName.NORMALISED_GAIN,
304
+ float,
305
+ help = """
306
+ The normalised gain value, where 1.0 is mapped to the max gain of the receiver being used.
307
+ """,
308
+ pconstraints=[
309
+ Bound(0.0, 1.0)
310
+ ]),
303
311
  PName.EVENT_HANDLER_KEY: PTemplate(PName.EVENT_HANDLER_KEY,
304
312
  str,
305
313
  help = """
@@ -490,4 +498,4 @@ def get_base_ptemplate(
490
498
  # A deep copy is required as each receiver instance may mutate the original instance
491
499
  # according to its particular use case. Copying preserves the original instance,
492
500
  # enabling reuse.
493
- return deepcopy( _base_ptemplates[pname] )
501
+ return deepcopy( _base_ptemplates[pname] )
@@ -8,6 +8,7 @@ from .plugins._receiver_names import ReceiverName
8
8
  from .plugins._test import Test
9
9
  from .plugins._rsp1a import RSP1A
10
10
  from .plugins._rspduo import RSPduo
11
+ from .plugins._b200mini import B200mini
11
12
 
12
13
  from ._base import BaseReceiver
13
14
  from ._factory import get_receiver
@@ -15,6 +16,6 @@ from ._register import get_registered_receivers
15
16
  from ._spec_names import SpecName
16
17
 
17
18
  __all__ = [
18
- "Test", "RSP1A", "RSPduo", "BaseReceiver", "get_receiver",
19
+ "Test", "RSP1A", "RSPduo", "B200mini", "BaseReceiver", "get_receiver",
19
20
  "get_registered_receivers", "SpecName", "ReceiverName"
20
- ]
21
+ ]
@@ -3,7 +3,7 @@
3
3
  # SPDX-License-Identifier: GPL-3.0-or-later
4
4
 
5
5
  from abc import ABC, abstractmethod
6
- from typing import Callable, Optional, Literal, overload
6
+ from typing import Callable, Optional, Literal, overload, Any
7
7
 
8
8
  from spectre_core.exceptions import ModeNotFoundError
9
9
  from spectre_core.capture_configs import (
@@ -236,34 +236,11 @@ class BaseReceiver(ABC):
236
236
  """
237
237
  self.specs[name] = value
238
238
 
239
-
240
- # tell static type checkers the type of specification
241
- @overload
242
- def get_spec(self, spec_name: Literal[SpecName.API_RETUNING_LATENCY]) -> float: ...
243
- @overload
244
- def get_spec(self, spec_name: Literal[SpecName.FREQUENCY_LOWER_BOUND]) -> float: ...
245
- @overload
246
- def get_spec(self, spec_name: Literal[SpecName.FREQUENCY_UPPER_BOUND]) -> float: ...
247
- @overload
248
- def get_spec(self, spec_name: Literal[SpecName.SAMPLE_RATE_LOWER_BOUND]) -> int: ...
249
- @overload
250
- def get_spec(self, spec_name: Literal[SpecName.SAMPLE_RATE_UPPER_BOUND]) -> int: ...
251
- @overload
252
- def get_spec(self, spec_name: Literal[SpecName.BANDWIDTH_LOWER_BOUND]) -> float: ...
253
- @overload
254
- def get_spec(self, spec_name: Literal[SpecName.BANDWIDTH_UPPER_BOUND]) -> float: ...
255
- @overload
256
- def get_spec(self, spec_name: Literal[SpecName.RF_GAIN_UPPER_BOUND]) -> int: ...
257
- @overload
258
- def get_spec(self, spec_name: Literal[SpecName.IF_GAIN_UPPER_BOUND]) -> int: ...
259
- @overload
260
- def get_spec(self, spec_name: Literal[SpecName.BANDWIDTH_OPTIONS]) -> list[float]: ...
261
-
262
239
 
263
240
  def get_spec(
264
241
  self,
265
242
  spec_name: SpecName
266
- ) -> float|int|list[float|int]:
243
+ ) -> Any:
267
244
  """
268
245
  Retrieve a hardware specification.
269
246
 
@@ -328,4 +305,4 @@ class BaseReceiver(ABC):
328
305
  parameters = self.capture_template.apply_template(capture_config.parameters)
329
306
  self.pvalidator(parameters)
330
307
 
331
- return parameters
308
+ return parameters
@@ -11,6 +11,7 @@ from .plugins._receiver_names import ReceiverName
11
11
  from .plugins._rsp1a import RSP1A
12
12
  from .plugins._rspduo import RSPduo
13
13
  from .plugins._test import Test
14
+ from .plugins._b200mini import B200mini
14
15
 
15
16
 
16
17
  @overload
@@ -37,6 +38,14 @@ def get_receiver(
37
38
  ...
38
39
 
39
40
 
41
+ @overload
42
+ def get_receiver(
43
+ receiver_name: Literal[ReceiverName.B200MINI],
44
+ mode: Optional[str] = None
45
+ ) -> B200mini:
46
+ ...
47
+
48
+
40
49
  @overload
41
50
  def get_receiver(
42
51
  receiver_name: ReceiverName,
@@ -18,6 +18,8 @@ class SpecName(Enum):
18
18
  Negative values indicate attenuation.
19
19
  :ivar RF_GAIN_UPPER_BOUND: The upper bound for the radio frequency gain, in dB.
20
20
  Negative values indicate attenuation.
21
+ :ivar API_RETUNING_LATENCY: An empirical estimate of the delay between issuing a command
22
+ for a receiver to retune its center frequency and the actual physical update of the center frequency.
21
23
  """
22
24
  FREQUENCY_LOWER_BOUND = "frequency_lower_bound"
23
25
  FREQUENCY_UPPER_BOUND = "frequency_upper_bound"
@@ -28,4 +30,4 @@ class SpecName(Enum):
28
30
  BANDWIDTH_OPTIONS = "bandwidth_options"
29
31
  IF_GAIN_UPPER_BOUND = "if_gain_upper_bound"
30
32
  RF_GAIN_UPPER_BOUND = "rf_gain_upper_bound"
31
- API_RETUNING_LATENCY = "api_retuning_latency"
33
+ API_RETUNING_LATENCY = "api_retuning_latency"
@@ -0,0 +1,72 @@
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 dataclasses import dataclass
6
+
7
+ from ._receiver_names import ReceiverName
8
+ from ._usrp import (
9
+ get_pvalidator_fixed_center_frequency,
10
+ get_capture_template_fixed_center_frequency
11
+ )
12
+ from .gr._usrp import CaptureMethod
13
+ from .._spec_names import SpecName
14
+ from .._base import BaseReceiver
15
+ from .._register import register_receiver
16
+
17
+ @dataclass(frozen=True)
18
+ class Mode:
19
+ """An operating mode for the `B200mini` receiver."""
20
+ FIXED_CENTER_FREQUENCY = "fixed_center_frequency"
21
+
22
+
23
+ @register_receiver(ReceiverName.B200MINI)
24
+ class B200mini(BaseReceiver):
25
+ """Receiver implementation for the USRP B200mini (https://www.ettus.com/all-products/usrp-b200mini/)"""
26
+ def _add_specs(
27
+ self
28
+ ) -> None:
29
+ self.add_spec( SpecName.SAMPLE_RATE_LOWER_BOUND, 200e3 )
30
+ self.add_spec( SpecName.SAMPLE_RATE_UPPER_BOUND, 56e6 )
31
+ self.add_spec( SpecName.FREQUENCY_LOWER_BOUND , 70e6 )
32
+ self.add_spec( SpecName.FREQUENCY_UPPER_BOUND , 6e9 )
33
+ self.add_spec( SpecName.BANDWIDTH_LOWER_BOUND , 200e3 )
34
+ self.add_spec( SpecName.BANDWIDTH_UPPER_BOUND , 56e6 )
35
+
36
+
37
+ def _add_capture_methods(
38
+ self
39
+ ) -> None:
40
+ self.add_capture_method(Mode.FIXED_CENTER_FREQUENCY,
41
+ CaptureMethod.fixed_center_frequency)
42
+
43
+
44
+ def _add_capture_templates(
45
+ self
46
+ ) -> None:
47
+ self.add_capture_template(Mode.FIXED_CENTER_FREQUENCY,
48
+ get_capture_template_fixed_center_frequency(self))
49
+
50
+
51
+ def _add_pvalidators(
52
+ self
53
+ ) -> None:
54
+ self.add_pvalidator(Mode.FIXED_CENTER_FREQUENCY,
55
+ get_pvalidator_fixed_center_frequency(self))
56
+
57
+
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+
@@ -10,7 +10,9 @@ class ReceiverName(Enum):
10
10
  :ivar RSP1A: SDRPlay RSP1A
11
11
  :ivar RSPDUO: SDRPlay RSPduo
12
12
  :ivar TEST: `spectre` test receiver.
13
+ :ivar B200MINI: USRP B200mini.
13
14
  """
14
- RSP1A = "rsp1a"
15
- RSPDUO = "rspduo"
16
- TEST = "test"
15
+ RSP1A = "rsp1a"
16
+ RSPDUO = "rspduo"
17
+ TEST = "test"
18
+ B200MINI = "b200mini"
@@ -6,8 +6,12 @@ from dataclasses import dataclass
6
6
 
7
7
  from ._receiver_names import ReceiverName
8
8
  from .gr._rsp1a import CaptureMethod
9
+ from ._sdrplay_receiver import (
10
+ get_pvalidator_fixed_center_frequency, get_pvalidator_swept_center_frequency,
11
+ get_capture_template_fixed_center_frequency, get_capture_template_swept_center_frequency
12
+ )
9
13
  from .._spec_names import SpecName
10
- from ._sdrplay_receiver import SDRPlayReceiver
14
+ from .._base import BaseReceiver
11
15
  from .._register import register_receiver
12
16
 
13
17
  @dataclass(frozen=True)
@@ -18,9 +22,11 @@ class Mode:
18
22
 
19
23
 
20
24
  @register_receiver(ReceiverName.RSP1A)
21
- class RSP1A(SDRPlayReceiver):
25
+ class RSP1A(BaseReceiver):
22
26
  """Receiver implementation for the SDRPlay RSP1A (https://www.sdrplay.com/rsp1a/)"""
23
- def _add_specs(self) -> None:
27
+ def _add_specs(
28
+ self
29
+ ) -> None:
24
30
  self.add_spec( SpecName.SAMPLE_RATE_LOWER_BOUND, 200e3 )
25
31
  self.add_spec( SpecName.SAMPLE_RATE_UPPER_BOUND, 10e6 )
26
32
  self.add_spec( SpecName.FREQUENCY_LOWER_BOUND , 1e3 )
@@ -45,15 +51,15 @@ class RSP1A(SDRPlayReceiver):
45
51
  self
46
52
  ) -> None:
47
53
  self.add_capture_template(Mode.FIXED_CENTER_FREQUENCY,
48
- self._get_capture_template_fixed_center_frequency())
54
+ get_capture_template_fixed_center_frequency(self))
49
55
  self.add_capture_template(Mode.SWEPT_CENTER_FREQUENCY,
50
- self._get_capture_template_swept_center_frequency())
56
+ get_capture_template_swept_center_frequency(self))
51
57
 
52
58
 
53
59
  def _add_pvalidators(
54
60
  self
55
61
  ) -> None:
56
62
  self.add_pvalidator(Mode.FIXED_CENTER_FREQUENCY,
57
- self._get_pvalidator_fixed_center_frequency())
63
+ get_pvalidator_fixed_center_frequency(self))
58
64
  self.add_pvalidator(Mode.SWEPT_CENTER_FREQUENCY,
59
- self._get_pvalidator_swept_center_frequency())
65
+ get_pvalidator_swept_center_frequency(self))
@@ -7,7 +7,11 @@ from dataclasses import dataclass
7
7
  from ._receiver_names import ReceiverName
8
8
  from .gr._rspduo import CaptureMethod
9
9
  from .._spec_names import SpecName
10
- from ._sdrplay_receiver import SDRPlayReceiver
10
+ from ._sdrplay_receiver import (
11
+ get_pvalidator_fixed_center_frequency, get_pvalidator_swept_center_frequency,
12
+ get_capture_template_fixed_center_frequency, get_capture_template_swept_center_frequency
13
+ )
14
+ from .._base import BaseReceiver
11
15
  from .._register import register_receiver
12
16
 
13
17
 
@@ -20,7 +24,7 @@ class Mode:
20
24
 
21
25
 
22
26
  @register_receiver(ReceiverName.RSPDUO)
23
- class RSPduo(SDRPlayReceiver):
27
+ class RSPduo(BaseReceiver):
24
28
  """Receiver implementation for the SDRPlay RSPduo (https://www.sdrplay.com/rspduo/)"""
25
29
  def _add_specs(self) -> None:
26
30
  self.add_spec( SpecName.SAMPLE_RATE_LOWER_BOUND, 200e3 )
@@ -49,19 +53,19 @@ class RSPduo(SDRPlayReceiver):
49
53
  self
50
54
  ) -> None:
51
55
  self.add_capture_template(Mode.TUNER_1_FIXED_CENTER_FREQUENCY,
52
- self._get_capture_template_fixed_center_frequency())
56
+ get_capture_template_fixed_center_frequency(self))
53
57
  self.add_capture_template(Mode.TUNER_2_FIXED_CENTER_FREQUENCY,
54
- self._get_capture_template_fixed_center_frequency())
58
+ get_capture_template_fixed_center_frequency(self))
55
59
  self.add_capture_template(Mode.TUNER_1_SWEPT_CENTER_FREQUENCY,
56
- self._get_capture_template_swept_center_frequency())
60
+ get_capture_template_swept_center_frequency(self))
57
61
 
58
62
 
59
63
  def _add_pvalidators(
60
64
  self
61
65
  ) -> None:
62
66
  self.add_pvalidator(Mode.TUNER_1_FIXED_CENTER_FREQUENCY,
63
- self._get_pvalidator_fixed_center_frequency())
67
+ get_pvalidator_fixed_center_frequency(self))
64
68
  self.add_pvalidator(Mode.TUNER_2_FIXED_CENTER_FREQUENCY,
65
- self._get_pvalidator_fixed_center_frequency())
69
+ get_pvalidator_fixed_center_frequency(self))
66
70
  self.add_pvalidator(Mode.TUNER_1_SWEPT_CENTER_FREQUENCY,
67
- self._get_pvalidator_swept_center_frequency())
71
+ get_pvalidator_swept_center_frequency(self))
@@ -12,179 +12,163 @@ from spectre_core.capture_configs import (
12
12
  from .._base import BaseReceiver
13
13
  from .._spec_names import SpecName
14
14
 
15
- class SDRPlayReceiver(BaseReceiver):
16
- """An abstract base class for SDRPlay receivers.
17
-
18
- Includes ready-to-go pvalidators and capture templates which are shared by all subclasses.
19
- Each subclasses must define the following hardware specifications:
20
-
21
- .. code-block:: python
22
- def _add_specs(self) -> None:
23
- self.add_spec( SpecName.SAMPLE_RATE_LOWER_BOUND, <TBD> )
24
- self.add_spec( SpecName.SAMPLE_RATE_UPPER_BOUND, <TBD> )
25
- self.add_spec( SpecName.FREQUENCY_LOWER_BOUND , <TBD> )
26
- self.add_spec( SpecName.FREQUENCY_UPPER_BOUND , <TBD> )
27
- self.add_spec( SpecName.IF_GAIN_UPPER_BOUND , <TBD> )
28
- self.add_spec( SpecName.RF_GAIN_UPPER_BOUND , <TBD> )
29
- self.add_spec( SpecName.API_RETUNING_LATENCY , <TBD> )
30
- self.add_spec( SpecName.BANDWIDTH_OPTIONS , <TBD> )
31
- """
32
- def _get_pvalidator_fixed_center_frequency(
33
- self
34
- ) -> Callable[[Parameters], None]:
35
- def pvalidator(parameters: Parameters):
36
- validate_fixed_center_frequency(parameters)
37
- return pvalidator
38
15
 
16
+ def get_pvalidator_fixed_center_frequency(
17
+ sdrplay_receiver: BaseReceiver
18
+ ) -> Callable[[Parameters], None]:
19
+ def pvalidator(parameters: Parameters) -> None:
20
+ validate_fixed_center_frequency(parameters)
21
+ return pvalidator
39
22
 
40
- def _get_pvalidator_swept_center_frequency(
41
- self
42
- ) -> Callable[[Parameters], None]:
43
- def pvalidator(parameters: Parameters):
44
- validate_swept_center_frequency(parameters,
45
- self.get_spec(SpecName.API_RETUNING_LATENCY))
46
- return pvalidator
47
23
 
24
+ def get_pvalidator_swept_center_frequency(
25
+ sdrplay_receiver: BaseReceiver
26
+ ) -> Callable[[Parameters], None]:
27
+ def pvalidator(parameters: Parameters) -> None:
28
+ validate_swept_center_frequency(parameters,
29
+ sdrplay_receiver.get_spec(SpecName.API_RETUNING_LATENCY))
30
+ return pvalidator
48
31
 
49
- def _get_capture_template_fixed_center_frequency(
50
- self
51
- ) -> CaptureTemplate:
52
-
53
- capture_template = get_base_capture_template( CaptureMode.FIXED_CENTER_FREQUENCY )
54
- capture_template.add_ptemplate( get_base_ptemplate(PName.BANDWIDTH) )
55
- capture_template.add_ptemplate( get_base_ptemplate(PName.IF_GAIN) )
56
- capture_template.add_ptemplate( get_base_ptemplate(PName.RF_GAIN) )
57
32
 
58
- capture_template.set_defaults(
59
- (PName.BATCH_SIZE, 3.0),
60
- (PName.CENTER_FREQUENCY, 95800000),
61
- (PName.SAMPLE_RATE, 600000),
62
- (PName.BANDWIDTH, 600000),
63
- (PName.WINDOW_HOP, 512),
64
- (PName.WINDOW_SIZE, 1024),
65
- (PName.WINDOW_TYPE, "blackman"),
66
- (PName.RF_GAIN, -30),
67
- (PName.IF_GAIN, -30)
68
- )
33
+ def get_capture_template_fixed_center_frequency(
34
+ sdrplay_receiver: BaseReceiver
35
+ ) -> CaptureTemplate:
36
+
37
+ capture_template = get_base_capture_template( CaptureMode.FIXED_CENTER_FREQUENCY )
38
+ capture_template.add_ptemplate( get_base_ptemplate(PName.BANDWIDTH) )
39
+ capture_template.add_ptemplate( get_base_ptemplate(PName.IF_GAIN) )
40
+ capture_template.add_ptemplate( get_base_ptemplate(PName.RF_GAIN) )
41
+
42
+ capture_template.set_defaults(
43
+ (PName.BATCH_SIZE, 3.0),
44
+ (PName.CENTER_FREQUENCY, 95800000),
45
+ (PName.SAMPLE_RATE, 600000),
46
+ (PName.BANDWIDTH, 600000),
47
+ (PName.WINDOW_HOP, 512),
48
+ (PName.WINDOW_SIZE, 1024),
49
+ (PName.WINDOW_TYPE, "blackman"),
50
+ (PName.RF_GAIN, -30),
51
+ (PName.IF_GAIN, -30)
52
+ )
69
53
 
70
- capture_template.add_pconstraint(
71
- PName.CENTER_FREQUENCY,
72
- [
73
- Bound(
74
- lower_bound=self.get_spec(SpecName.FREQUENCY_LOWER_BOUND),
75
- upper_bound=self.get_spec(SpecName.FREQUENCY_UPPER_BOUND)
76
- )
77
- ]
78
- )
79
- capture_template.add_pconstraint(
80
- PName.SAMPLE_RATE,
81
- [
82
- Bound(
83
- lower_bound=self.get_spec(SpecName.SAMPLE_RATE_LOWER_BOUND),
84
- upper_bound=self.get_spec(SpecName.SAMPLE_RATE_UPPER_BOUND)
85
- )
86
- ]
87
- )
88
- capture_template.add_pconstraint(
89
- PName.BANDWIDTH,
90
- [
91
- OneOf(
92
- self.get_spec( SpecName.BANDWIDTH_OPTIONS )
93
- )
94
- ]
95
- )
96
- capture_template.add_pconstraint(
97
- PName.IF_GAIN,
98
- [
99
- Bound(
100
- upper_bound=self.get_spec(SpecName.IF_GAIN_UPPER_BOUND)
101
- )
102
- ]
103
- )
104
- capture_template.add_pconstraint(
105
- PName.RF_GAIN,
106
- [
107
- Bound(
108
- upper_bound=self.get_spec(SpecName.RF_GAIN_UPPER_BOUND)
109
- )
110
- ]
111
- )
112
- return capture_template
54
+ capture_template.add_pconstraint(
55
+ PName.CENTER_FREQUENCY,
56
+ [
57
+ Bound(
58
+ lower_bound=sdrplay_receiver.get_spec(SpecName.FREQUENCY_LOWER_BOUND),
59
+ upper_bound=sdrplay_receiver.get_spec(SpecName.FREQUENCY_UPPER_BOUND)
60
+ )
61
+ ]
62
+ )
63
+ capture_template.add_pconstraint(
64
+ PName.SAMPLE_RATE,
65
+ [
66
+ Bound(
67
+ lower_bound=sdrplay_receiver.get_spec(SpecName.SAMPLE_RATE_LOWER_BOUND),
68
+ upper_bound=sdrplay_receiver.get_spec(SpecName.SAMPLE_RATE_UPPER_BOUND)
69
+ )
70
+ ]
71
+ )
72
+ capture_template.add_pconstraint(
73
+ PName.BANDWIDTH,
74
+ [
75
+ OneOf(
76
+ sdrplay_receiver.get_spec( SpecName.BANDWIDTH_OPTIONS )
77
+ )
78
+ ]
79
+ )
80
+ capture_template.add_pconstraint(
81
+ PName.IF_GAIN,
82
+ [
83
+ Bound(
84
+ upper_bound=sdrplay_receiver.get_spec(SpecName.IF_GAIN_UPPER_BOUND)
85
+ )
86
+ ]
87
+ )
88
+ capture_template.add_pconstraint(
89
+ PName.RF_GAIN,
90
+ [
91
+ Bound(
92
+ upper_bound=sdrplay_receiver.get_spec(SpecName.RF_GAIN_UPPER_BOUND)
93
+ )
94
+ ]
95
+ )
96
+ return capture_template
113
97
 
114
98
 
115
- def _get_capture_template_swept_center_frequency(
116
- self
117
- ) -> CaptureTemplate:
99
+ def get_capture_template_swept_center_frequency(
100
+ sdrplay_receiver: BaseReceiver
101
+ ) -> CaptureTemplate:
118
102
 
119
- capture_template = get_base_capture_template( CaptureMode.SWEPT_CENTER_FREQUENCY )
120
- capture_template.add_ptemplate( get_base_ptemplate(PName.BANDWIDTH) )
121
- capture_template.add_ptemplate( get_base_ptemplate(PName.IF_GAIN) )
122
- capture_template.add_ptemplate( get_base_ptemplate(PName.RF_GAIN) )
103
+ capture_template = get_base_capture_template( CaptureMode.SWEPT_CENTER_FREQUENCY )
104
+ capture_template.add_ptemplate( get_base_ptemplate(PName.BANDWIDTH) )
105
+ capture_template.add_ptemplate( get_base_ptemplate(PName.IF_GAIN) )
106
+ capture_template.add_ptemplate( get_base_ptemplate(PName.RF_GAIN) )
123
107
 
124
- capture_template.set_defaults(
125
- (PName.BATCH_SIZE, 4.0),
126
- (PName.MIN_FREQUENCY, 95000000),
127
- (PName.MAX_FREQUENCY, 100000000),
128
- (PName.SAMPLES_PER_STEP, 80000),
129
- (PName.FREQUENCY_STEP, 1536000),
130
- (PName.SAMPLE_RATE, 1536000),
131
- (PName.BANDWIDTH, 1536000),
132
- (PName.WINDOW_HOP, 512),
133
- (PName.WINDOW_SIZE, 1024),
134
- (PName.WINDOW_TYPE, "blackman"),
135
- (PName.RF_GAIN, -30),
136
- (PName.IF_GAIN, -30)
137
- )
108
+ capture_template.set_defaults(
109
+ (PName.BATCH_SIZE, 4.0),
110
+ (PName.MIN_FREQUENCY, 95000000),
111
+ (PName.MAX_FREQUENCY, 100000000),
112
+ (PName.SAMPLES_PER_STEP, 80000),
113
+ (PName.FREQUENCY_STEP, 1536000),
114
+ (PName.SAMPLE_RATE, 1536000),
115
+ (PName.BANDWIDTH, 1536000),
116
+ (PName.WINDOW_HOP, 512),
117
+ (PName.WINDOW_SIZE, 1024),
118
+ (PName.WINDOW_TYPE, "blackman"),
119
+ (PName.RF_GAIN, -30),
120
+ (PName.IF_GAIN, -30)
121
+ )
138
122
 
139
- capture_template.add_pconstraint(
140
- PName.MIN_FREQUENCY,
141
- [
142
- Bound(
143
- lower_bound=self.get_spec(SpecName.FREQUENCY_LOWER_BOUND),
144
- upper_bound=self.get_spec(SpecName.FREQUENCY_UPPER_BOUND)
145
- )
146
- ]
147
- )
148
- capture_template.add_pconstraint(
149
- PName.MAX_FREQUENCY,
150
- [
151
- Bound(
152
- lower_bound=self.get_spec(SpecName.FREQUENCY_LOWER_BOUND),
153
- upper_bound=self.get_spec(SpecName.FREQUENCY_UPPER_BOUND)
154
- )
155
- ]
156
- )
157
- capture_template.add_pconstraint(
158
- PName.SAMPLE_RATE,
159
- [
160
- Bound(
161
- lower_bound=self.get_spec(SpecName.SAMPLE_RATE_LOWER_BOUND),
162
- upper_bound=self.get_spec(SpecName.SAMPLE_RATE_UPPER_BOUND)
163
- )
164
- ]
165
- )
166
- capture_template.add_pconstraint(
167
- PName.BANDWIDTH,
168
- [
169
- OneOf(
170
- self.get_spec( SpecName.BANDWIDTH_OPTIONS )
171
- )
172
- ]
173
- )
174
- capture_template.add_pconstraint(
175
- PName.IF_GAIN,
176
- [
177
- Bound(
178
- upper_bound=self.get_spec(SpecName.IF_GAIN_UPPER_BOUND)
179
- )
180
- ]
181
- )
182
- capture_template.add_pconstraint(
183
- PName.RF_GAIN,
184
- [
185
- Bound(
186
- upper_bound=self.get_spec(SpecName.RF_GAIN_UPPER_BOUND)
187
- )
188
- ]
189
- )
190
- return capture_template
123
+ capture_template.add_pconstraint(
124
+ PName.MIN_FREQUENCY,
125
+ [
126
+ Bound(
127
+ lower_bound=sdrplay_receiver.get_spec(SpecName.FREQUENCY_LOWER_BOUND),
128
+ upper_bound=sdrplay_receiver.get_spec(SpecName.FREQUENCY_UPPER_BOUND)
129
+ )
130
+ ]
131
+ )
132
+ capture_template.add_pconstraint(
133
+ PName.MAX_FREQUENCY,
134
+ [
135
+ Bound(
136
+ lower_bound=sdrplay_receiver.get_spec(SpecName.FREQUENCY_LOWER_BOUND),
137
+ upper_bound=sdrplay_receiver.get_spec(SpecName.FREQUENCY_UPPER_BOUND)
138
+ )
139
+ ]
140
+ )
141
+ capture_template.add_pconstraint(
142
+ PName.SAMPLE_RATE,
143
+ [
144
+ Bound(
145
+ lower_bound=sdrplay_receiver.get_spec(SpecName.SAMPLE_RATE_LOWER_BOUND),
146
+ upper_bound=sdrplay_receiver.get_spec(SpecName.SAMPLE_RATE_UPPER_BOUND)
147
+ )
148
+ ]
149
+ )
150
+ capture_template.add_pconstraint(
151
+ PName.BANDWIDTH,
152
+ [
153
+ OneOf(
154
+ sdrplay_receiver.get_spec( SpecName.BANDWIDTH_OPTIONS )
155
+ )
156
+ ]
157
+ )
158
+ capture_template.add_pconstraint(
159
+ PName.IF_GAIN,
160
+ [
161
+ Bound(
162
+ upper_bound=sdrplay_receiver.get_spec(SpecName.IF_GAIN_UPPER_BOUND)
163
+ )
164
+ ]
165
+ )
166
+ capture_template.add_pconstraint(
167
+ PName.RF_GAIN,
168
+ [
169
+ Bound(
170
+ upper_bound=sdrplay_receiver.get_spec(SpecName.RF_GAIN_UPPER_BOUND)
171
+ )
172
+ ]
173
+ )
174
+ return capture_template
@@ -0,0 +1,70 @@
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 typing import Callable, overload
6
+
7
+ from spectre_core.capture_configs import (
8
+ CaptureTemplate, CaptureMode, Parameters, Bound, PName,
9
+ get_base_capture_template, get_base_ptemplate, OneOf,
10
+ validate_fixed_center_frequency, validate_swept_center_frequency
11
+ )
12
+ from .._base import BaseReceiver
13
+ from .._spec_names import SpecName
14
+
15
+
16
+ def get_pvalidator_fixed_center_frequency(
17
+ usrp_receiver: BaseReceiver
18
+ ) -> Callable[[Parameters], None]:
19
+ def pvalidator(parameters: Parameters) -> None:
20
+ validate_fixed_center_frequency(parameters)
21
+ return pvalidator
22
+
23
+
24
+ def get_capture_template_fixed_center_frequency(
25
+ usrp_receiver: BaseReceiver
26
+ ) -> CaptureTemplate:
27
+
28
+ capture_template = get_base_capture_template( CaptureMode.FIXED_CENTER_FREQUENCY )
29
+ capture_template.add_ptemplate( get_base_ptemplate(PName.BANDWIDTH) )
30
+ capture_template.add_ptemplate( get_base_ptemplate(PName.NORMALISED_GAIN) )
31
+
32
+ capture_template.set_defaults(
33
+ (PName.BATCH_SIZE, 3.0),
34
+ (PName.CENTER_FREQUENCY, 95800000),
35
+ (PName.SAMPLE_RATE, 1000000),
36
+ (PName.BANDWIDTH, 1000000),
37
+ (PName.WINDOW_HOP, 512),
38
+ (PName.WINDOW_SIZE, 1024),
39
+ (PName.WINDOW_TYPE, "blackman"),
40
+ (PName.NORMALISED_GAIN, 0.3),
41
+ )
42
+
43
+ capture_template.add_pconstraint(
44
+ PName.CENTER_FREQUENCY,
45
+ [
46
+ Bound(
47
+ lower_bound=usrp_receiver.get_spec(SpecName.FREQUENCY_LOWER_BOUND),
48
+ upper_bound=usrp_receiver.get_spec(SpecName.FREQUENCY_UPPER_BOUND)
49
+ )
50
+ ]
51
+ )
52
+ capture_template.add_pconstraint(
53
+ PName.SAMPLE_RATE,
54
+ [
55
+ Bound(
56
+ lower_bound=usrp_receiver.get_spec(SpecName.SAMPLE_RATE_LOWER_BOUND),
57
+ upper_bound=usrp_receiver.get_spec(SpecName.SAMPLE_RATE_UPPER_BOUND)
58
+ )
59
+ ]
60
+ )
61
+ capture_template.add_pconstraint(
62
+ PName.BANDWIDTH,
63
+ [
64
+ Bound(
65
+ lower_bound=usrp_receiver.get_spec( SpecName.BANDWIDTH_LOWER_BOUND ),
66
+ upper_bound=usrp_receiver.get_spec( SpecName.BANDWIDTH_UPPER_BOUND )
67
+ )
68
+ ]
69
+ )
70
+ return capture_template
@@ -1,17 +1,3 @@
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: Test receiver
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
1
  #
16
2
  # RSP1A receiver top blocks
17
3
  #
@@ -145,4 +131,4 @@ class _swept_center_frequency(spectre_top_block):
145
131
  @dataclass(frozen=True)
146
132
  class CaptureMethod:
147
133
  fixed_center_frequency = partial(capture, top_block_cls=_fixed_center_frequency)
148
- swept_center_frequency = partial(capture, top_block_cls=_swept_center_frequency, max_noutput_items=1024)
134
+ swept_center_frequency = partial(capture, top_block_cls=_swept_center_frequency, max_noutput_items=1024)
@@ -0,0 +1,62 @@
1
+ #
2
+ # USRP top blocks
3
+ #
4
+
5
+ from functools import partial
6
+ from dataclasses import dataclass
7
+ import time
8
+
9
+ from spectre_core.capture_configs import Parameters, PName
10
+ from spectre_core.config import get_batches_dir_path
11
+ from ._base import capture, spectre_top_block
12
+
13
+
14
+ class _fixed_center_frequency(spectre_top_block):
15
+ def flowgraph(
16
+ self,
17
+ tag: str,
18
+ parameters: Parameters
19
+ ) -> None:
20
+ # OOT moudle inline imports
21
+ from gnuradio import spectre
22
+ from gnuradio import uhd
23
+
24
+ # Variables
25
+ sample_rate = parameters.get_parameter_value(PName.SAMPLE_RATE)
26
+ normalised_gain = parameters.get_parameter_value(PName.NORMALISED_GAIN)
27
+ center_freq = parameters.get_parameter_value(PName.CENTER_FREQUENCY)
28
+ batch_size = parameters.get_parameter_value(PName.BATCH_SIZE)
29
+ bandwidth = parameters.get_parameter_value(PName.BANDWIDTH)
30
+
31
+ # Blocks
32
+ self.uhd_usrp_source_0 = uhd.usrp_source(
33
+ ",".join(("", '')),
34
+ uhd.stream_args(
35
+ cpu_format="fc32",
36
+ args='',
37
+ channels=list(range(0,1)),
38
+ ),
39
+ )
40
+ self.uhd_usrp_source_0.set_samp_rate(sample_rate)
41
+ self.uhd_usrp_source_0.set_time_now(uhd.time_spec(time.time()), uhd.ALL_MBOARDS)
42
+
43
+ self.uhd_usrp_source_0.set_center_freq(center_freq, 0)
44
+ self.uhd_usrp_source_0.set_antenna("RX2", 0)
45
+ self.uhd_usrp_source_0.set_bandwidth(bandwidth, 0)
46
+ self.uhd_usrp_source_0.set_rx_agc(False, 0)
47
+ self.uhd_usrp_source_0.set_normalized_gain(normalised_gain, 0)
48
+ self.spectre_batched_file_sink_0 = spectre.batched_file_sink(get_batches_dir_path(),
49
+ tag,
50
+ batch_size,
51
+ sample_rate, False,
52
+ 'freq',
53
+ 0)
54
+
55
+
56
+ # Connections
57
+ self.connect((self.uhd_usrp_source_0, 0), (self.spectre_batched_file_sink_0, 0))
58
+
59
+
60
+ @dataclass(frozen=True)
61
+ class CaptureMethod:
62
+ fixed_center_frequency = partial(capture, top_block_cls=_fixed_center_frequency)
@@ -186,5 +186,5 @@ def time_elapsed(
186
186
  datetimes: npt.NDArray[np.datetime64]
187
187
  ) -> npt.NDArray[np.float32]:
188
188
  """Convert an array of datetimes to seconds elapsed."""
189
- return (datetimes - datetimes[0]).astype('timedelta64[us]').astype(np.float32)
189
+ return (datetimes - datetimes[0]).astype('timedelta64[us]') / np.timedelta64(1, 's')
190
190
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: spectre-core
3
- Version: 0.0.13
3
+ Version: 0.0.15
4
4
  Summary: The core Python package used by the spectre program.
5
5
  Maintainer-email: Jimmy Fitzpatrick <jcfitzpatrick12@gmail.com>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -17,8 +17,8 @@ spectre_core/capture_configs/_capture_modes.py,sha256=uFBMwHYJCDqqQfYJvAUKzKXTmS
17
17
  spectre_core/capture_configs/_capture_templates.py,sha256=nSAxhOh1DeBzYY16evgOTkDuxRugGG5weJsICUouLPQ,10353
18
18
  spectre_core/capture_configs/_parameters.py,sha256=9KoNuwzDKtnyeju53fkImi1SeUjDn89cNwDL8zxX-YU,5563
19
19
  spectre_core/capture_configs/_pconstraints.py,sha256=bnl1m6M9iyo5KOsPKT_arwrrAZbxRKXVwTHQACzvs2g,5227
20
- spectre_core/capture_configs/_pnames.py,sha256=05mrrGfYHudaD2dYyukijbW-YtUnifZRn05xcBGv-fI,1852
21
- spectre_core/capture_configs/_ptemplates.py,sha256=p4lOi6W5B9gWv0d6ryNK9f_zxLHsj5PWW8Lmdco9ofg,24508
20
+ spectre_core/capture_configs/_pnames.py,sha256=xqBbaR6Hd6NdzGOZU7DDlKYol02HqW8RAjbnhrXIgAk,1898
21
+ spectre_core/capture_configs/_ptemplates.py,sha256=MVx_A2wy8b9zyiAHb2F5LLuYYarkTdv9r-dvMn2C_Fw,25068
22
22
  spectre_core/capture_configs/_pvalidators.py,sha256=0W-OMDY1lifRPonwgEAwoMYkA0PWbqlK5nE0zsYVcTw,9596
23
23
  spectre_core/config/__init__.py,sha256=CVddibAIWU4cNerXCxfeUn_cvnWWDBm4pWeUifqM6Ko,502
24
24
  spectre_core/config/_paths.py,sha256=Qn0KVe27P6Bo65MfHe4LpH_ryPvLgbTxKjc4MTw1BB8,4090
@@ -45,31 +45,34 @@ spectre_core/post_processing/_register.py,sha256=chK5bCQ-0bpMhplbKT3cdS5anLhIA5T
45
45
  spectre_core/post_processing/plugins/_event_handler_keys.py,sha256=LPA71kKsaLPyT2vpPJwm88-RWfX-AU0_T9H8-GdjINQ,614
46
46
  spectre_core/post_processing/plugins/_fixed_center_frequency.py,sha256=24LB3iDMa2KvgM7jyRnEr7Y45VK46bUT7Nj8bXGiGwc,5231
47
47
  spectre_core/post_processing/plugins/_swept_center_frequency.py,sha256=fzPAZ4zK1DRAHushUB-JS2IgKAuXyP4hdBLZJX6jBmo,20971
48
- spectre_core/receivers/__init__.py,sha256=A-BuCrnIRdRZe6HGXlLzKHGm8Zjfb8I9dzslBTeUHn4,660
49
- spectre_core/receivers/_base.py,sha256=E2aSYmveSMYxLrm5Uv235KlsehOyq82DvSolCIF6xug,10096
50
- spectre_core/receivers/_factory.py,sha256=5NdwZzBmUEHZQHltggDmuEoi-DRS6fHPSBzxvmq50zs,1843
48
+ spectre_core/receivers/__init__.py,sha256=uT3XNn12gSfK_M_GE__sK-TRWra92qkttnUJ-_6uViE,714
49
+ spectre_core/receivers/_base.py,sha256=6uilcdMRq0lw4s3IuyWVT_sUJ7fS9va1qUOHuqW9vg4,8993
50
+ spectre_core/receivers/_factory.py,sha256=xViruRYb9kFjndY_GmhK5vNQ0VxCE3rbKB3uzqtp_zE,2018
51
51
  spectre_core/receivers/_register.py,sha256=jWS3Q_ZOZcqUFunxJwR5VRZN4_eS3LzcP-5edQdmj4c,1366
52
- spectre_core/receivers/_spec_names.py,sha256=pLYM9rMoZkT3JmRvSNfWKFiIJmj07vrphDbw-fNhpO8,1611
52
+ spectre_core/receivers/_spec_names.py,sha256=SraBJw2VvO7gZYFEVO8byH_-bp8kpVQDQNhaXrzcLEE,1812
53
53
  spectre_core/receivers/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
- spectre_core/receivers/plugins/_receiver_names.py,sha256=GZi4xznxscLBJXbfkZLtQ-m0U3GH362HiI5-y_FQO1k,426
55
- spectre_core/receivers/plugins/_rsp1a.py,sha256=LAvjxcxIkZRPpc96wqkco7rQ-H3AvUowsp0WG8vgAkw,2438
56
- spectre_core/receivers/plugins/_rspduo.py,sha256=ypr4xiEMOq4EJKFECz01PZjUJ2UcsWJVZRou8Ln5Ogw,3049
57
- spectre_core/receivers/plugins/_sdrplay_receiver.py,sha256=QpQ2sRc9Tz2IZRL_LyBX3UPCQ270RQMHH2mP6Y_n1-o,6899
54
+ spectre_core/receivers/plugins/_b200mini.py,sha256=gpCnyUpNonFs-0sGSlub_oPTFpIIUqGhm39DB8s8RTY,1884
55
+ spectre_core/receivers/plugins/_receiver_names.py,sha256=b8cUln47Ya8rr8vnnHQEGa7j9Hf-hJsNbTNtGuZaWlA,498
56
+ spectre_core/receivers/plugins/_rsp1a.py,sha256=zgPemoRjd93CvI9bRg7PHzgAUHB9xXg5LCvkLHa3jbI,2641
57
+ spectre_core/receivers/plugins/_rspduo.py,sha256=Sim1TXcG_g1ohWKwvMk7XzrQC8NGydCMGZEf9hhvX-0,3230
58
+ spectre_core/receivers/plugins/_sdrplay_receiver.py,sha256=bdfjGvKSFW_jfQFIQQcIIf8UfbuMwW04SK6YMNMIINI,5737
58
59
  spectre_core/receivers/plugins/_test.py,sha256=t8oE4zQLYYWJV6SMIZAlNHs9mig263QJmP6XRLyF0RU,8277
60
+ spectre_core/receivers/plugins/_usrp.py,sha256=QAhtdhkknL5C7dvY6SECtsG35FuYpXK6zQqgG-ooklE,2416
59
61
  spectre_core/receivers/plugins/gr/__init__.py,sha256=oFSWmGoXQLK5X5xHvWzTdNr9amuaiiGjZirXZVogACU,154
60
62
  spectre_core/receivers/plugins/gr/_base.py,sha256=woFF6498aLIDf4EC7aD-TolY9LtZBqlLy-Vai_gfIvc,2571
61
- spectre_core/receivers/plugins/gr/_rsp1a.py,sha256=Nq0VNWjzfTd4Mruz4FSk6bfso6zh1cMw-C-qn5LpPv8,6614
63
+ spectre_core/receivers/plugins/gr/_rsp1a.py,sha256=JLMRCNouSblNizth7EmLrtWvbnpD-5zd7uhc6Pjcopw,6288
62
64
  spectre_core/receivers/plugins/gr/_rspduo.py,sha256=s5g5nOQHiVHCESaHdj2VmgXl_LaiMaqXhTJfUbC7Iew,9811
63
65
  spectre_core/receivers/plugins/gr/_test.py,sha256=YA3JKdJ_CT3J93pqHUjltKrQUoaDXzUloEJEXVHH718,5780
66
+ spectre_core/receivers/plugins/gr/_usrp.py,sha256=ZIg-WiiMWYKJbI4KkobeZrgncoRKYnvKlklYBXtmq4Q,2366
64
67
  spectre_core/spectrograms/__init__.py,sha256=AsiOmn9XrAAHUvK-fdhRddAxX4M1Wd6TCtdmxGkl3FA,763
65
68
  spectre_core/spectrograms/_analytical.py,sha256=Axnt9JOJnWXRRuVU5nHPz5QU09KoWqNZkR5NnTX6kMY,11356
66
- spectre_core/spectrograms/_array_operations.py,sha256=rhiHjnqFGT1bffJygMbeYWb1H9VGBK6-uAgFh8I9owc,7547
69
+ spectre_core/spectrograms/_array_operations.py,sha256=79vddwWqR5i6OkeD5L_84t8svslpmzW4b8uxbiCQl0I,7553
67
70
  spectre_core/spectrograms/_spectrogram.py,sha256=WhHEt_QpmzspDqYlzdZcJ8CAXxRfs8-JfP0T3NHpjLQ,28205
68
71
  spectre_core/spectrograms/_transform.py,sha256=WZ5jAe3bOpNldxHDSHPf8Q_1ifBdWqXB_mlF6DL1VuE,11734
69
72
  spectre_core/wgetting/__init__.py,sha256=UkS0Z0wuuqpoZ1EL35wJcDpjBiAaZgdZ7064yGESxNE,341
70
73
  spectre_core/wgetting/_callisto.py,sha256=m9II6ayswrY4h_ST3TodioZ4C865lN_uOF-BozvjZAg,6952
71
- spectre_core-0.0.13.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
72
- spectre_core-0.0.13.dist-info/METADATA,sha256=1PBd2ql6_9g9BGrwb1bWhnY4MSqRV1hdkXne6uE184o,42100
73
- spectre_core-0.0.13.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
74
- spectre_core-0.0.13.dist-info/top_level.txt,sha256=-UsyjpFohXgZpgcZ9QbVeXhsIyF3Am8RxNFNDV_Ta2Y,13
75
- spectre_core-0.0.13.dist-info/RECORD,,
74
+ spectre_core-0.0.15.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
75
+ spectre_core-0.0.15.dist-info/METADATA,sha256=9PWjpA43grOEKj7uhFP4xVseoSzAmkZrOZkZQYrJTt4,42100
76
+ spectre_core-0.0.15.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
77
+ spectre_core-0.0.15.dist-info/top_level.txt,sha256=-UsyjpFohXgZpgcZ9QbVeXhsIyF3Am8RxNFNDV_Ta2Y,13
78
+ spectre_core-0.0.15.dist-info/RECORD,,