From aed68da09bde8013eaa80390ac82462e9e3ad8c4 Mon Sep 17 00:00:00 2001 From: crnbaker Date: Fri, 13 Oct 2023 15:24:34 +0100 Subject: [PATCH] #34 - implemented channel input impedance and coupling --- .../continuous_averaging_fifo_mode.py | 2 + .../continuous_multi_fifo_mode.py | 2 + src/example_scripts/finite_multi_fifo_mode.py | 2 + src/example_scripts/standard_single_mode.py | 2 + src/example_scripts/star_hub_example.py | 6 ++- .../digitiser/abstract_spectrum_digitiser.py | 15 +++++- .../devices/digitiser/digitiser_channel.py | 26 +++++++-- .../devices/digitiser/digitiser_interface.py | 11 +++- src/spectrumdevice/settings/__init__.py | 4 +- src/spectrumdevice/settings/channel.py | 53 ++++++++++++++++++- src/tests/configuration.py | 6 +-- src/tests/test_single_channel.py | 6 +++ 12 files changed, 120 insertions(+), 15 deletions(-) diff --git a/src/example_scripts/continuous_averaging_fifo_mode.py b/src/example_scripts/continuous_averaging_fifo_mode.py index 1734b0b..b1a937a 100644 --- a/src/example_scripts/continuous_averaging_fifo_mode.py +++ b/src/example_scripts/continuous_averaging_fifo_mode.py @@ -13,6 +13,7 @@ ExternalTriggerMode, TriggerSettings, AcquisitionSettings, + InputImpedance, ) @@ -56,6 +57,7 @@ def continuous_averaging_multi_fifo_example( enabled_channels=[0], vertical_ranges_in_mv=[200], vertical_offsets_in_percent=[0], + input_impedances=[InputImpedance.ONE_MEGA_OHM], timestamping_enabled=True, number_of_averages=num_averages, ) diff --git a/src/example_scripts/continuous_multi_fifo_mode.py b/src/example_scripts/continuous_multi_fifo_mode.py index f4094eb..5b1b7da 100644 --- a/src/example_scripts/continuous_multi_fifo_mode.py +++ b/src/example_scripts/continuous_multi_fifo_mode.py @@ -13,6 +13,7 @@ ExternalTriggerMode, TriggerSettings, AcquisitionSettings, + InputImpedance, ) @@ -56,6 +57,7 @@ def continuous_multi_fifo_example( enabled_channels=[0], vertical_ranges_in_mv=[200], vertical_offsets_in_percent=[0], + input_impedances=[InputImpedance.ONE_MEGA_OHM], timestamping_enabled=True, batch_size=batch_size, ) diff --git a/src/example_scripts/finite_multi_fifo_mode.py b/src/example_scripts/finite_multi_fifo_mode.py index ba25263..ee4461a 100644 --- a/src/example_scripts/finite_multi_fifo_mode.py +++ b/src/example_scripts/finite_multi_fifo_mode.py @@ -11,6 +11,7 @@ ExternalTriggerMode, TriggerSettings, AcquisitionSettings, + InputImpedance, ) @@ -54,6 +55,7 @@ def finite_multi_fifo_example( enabled_channels=[0], vertical_ranges_in_mv=[200], vertical_offsets_in_percent=[0], + input_impedances=[InputImpedance.ONE_MEGA_OHM], timestamping_enabled=True, batch_size=batch_size, ) diff --git a/src/example_scripts/standard_single_mode.py b/src/example_scripts/standard_single_mode.py index 4be116f..a97a25f 100644 --- a/src/example_scripts/standard_single_mode.py +++ b/src/example_scripts/standard_single_mode.py @@ -13,6 +13,7 @@ ExternalTriggerMode, TriggerSettings, AcquisitionSettings, + InputImpedance, ) @@ -54,6 +55,7 @@ def standard_single_mode_example( enabled_channels=[0], vertical_ranges_in_mv=[200], vertical_offsets_in_percent=[0], + input_impedances=[InputImpedance.ONE_MEGA_OHM], timestamping_enabled=True, ) diff --git a/src/example_scripts/star_hub_example.py b/src/example_scripts/star_hub_example.py index b044bb9..05f7075 100644 --- a/src/example_scripts/star_hub_example.py +++ b/src/example_scripts/star_hub_example.py @@ -8,6 +8,7 @@ ExternalTriggerMode, AcquisitionMode, AcquisitionSettings, + InputImpedance, ) @@ -67,8 +68,9 @@ def connect_to_star_hub_example( pre_trigger_length_in_samples=0, timeout_in_ms=1000, enabled_channels=[0, 8], # at least 1 channel from each child card must be enabled - vertical_ranges_in_mv=[200], - vertical_offsets_in_percent=[0], + vertical_ranges_in_mv=[200, 200], + vertical_offsets_in_percent=[0, 0], + input_impedances=[InputImpedance.ONE_MEGA_OHM, InputImpedance.ONE_MEGA_OHM], timestamping_enabled=True, batch_size=5, ) diff --git a/src/spectrumdevice/devices/digitiser/abstract_spectrum_digitiser.py b/src/spectrumdevice/devices/digitiser/abstract_spectrum_digitiser.py index 635fe21..193b27a 100644 --- a/src/spectrumdevice/devices/digitiser/abstract_spectrum_digitiser.py +++ b/src/spectrumdevice/devices/digitiser/abstract_spectrum_digitiser.py @@ -40,11 +40,22 @@ def configure_acquisition(self, settings: AcquisitionSettings) -> None: ) self.set_timeout_in_ms(settings.timeout_in_ms) self.set_enabled_channels(settings.enabled_channels) - for channel, v_range, v_offset in zip( - self.channels, settings.vertical_ranges_in_mv, settings.vertical_offsets_in_percent + + # Apply channel dependent settings + for channel, v_range, v_offset, impedance in zip( + self.channels, + settings.vertical_ranges_in_mv, + settings.vertical_offsets_in_percent, + settings.input_impedances, ): cast(SpectrumDigitiserChannel, channel).set_vertical_range_in_mv(v_range) cast(SpectrumDigitiserChannel, channel).set_vertical_offset_in_percent(v_offset) + cast(SpectrumDigitiserChannel, channel).set_input_impedance(impedance) + + # Only some hardware has software programmable input coupling, so coupling can be None + if settings.input_couplings is not None: + for channel, coupling in zip(self.channels, settings.input_couplings): + cast(SpectrumDigitiserChannel, channel).set_input_coupling(coupling) # Write the configuration to the card self.write_to_spectrum_device_register(SPC_M2CMD, M2CMD_CARD_WRITESETUP) diff --git a/src/spectrumdevice/devices/digitiser/digitiser_channel.py b/src/spectrumdevice/devices/digitiser/digitiser_channel.py index 4304efc..cf987f6 100644 --- a/src/spectrumdevice/devices/digitiser/digitiser_channel.py +++ b/src/spectrumdevice/devices/digitiser/digitiser_channel.py @@ -13,8 +13,14 @@ ) from spectrumdevice.exceptions import SpectrumCardIsNotADigitiser from spectrumdevice.settings.card_dependent_properties import CardType -from spectrumdevice.settings.channel import INPUT_IMPEDANCE_COMMANDS, InputImpedance, VERTICAL_OFFSET_COMMANDS, \ - VERTICAL_RANGE_COMMANDS +from spectrumdevice.settings.channel import ( + INPUT_IMPEDANCE_COMMANDS, + InputImpedance, + VERTICAL_OFFSET_COMMANDS, + VERTICAL_RANGE_COMMANDS, + InputCoupling, + INPUT_COUPLING_COMMANDS, +) class SpectrumDigitiserChannel(AbstractSpectrumChannel, SpectrumDigitiserChannelInterface): @@ -90,5 +96,17 @@ def input_impedance(self) -> InputImpedance: return InputImpedance(impedance_binary_value) def set_input_impedance(self, input_impedance: InputImpedance) -> None: - self._parent_device.write_to_spectrum_device_register(INPUT_IMPEDANCE_COMMANDS[self._number], - input_impedance.value) + self._parent_device.write_to_spectrum_device_register( + INPUT_IMPEDANCE_COMMANDS[self._number], input_impedance.value + ) + + @property + def input_coupling(self) -> InputCoupling: + """The current input impedance setting of the channel (50 Ohm or 1 MOhm)""" + coupling_binary_value = self._parent_device.read_spectrum_device_register(INPUT_COUPLING_COMMANDS[self._number]) + return InputCoupling(coupling_binary_value) + + def set_input_coupling(self, input_coupling: InputCoupling) -> None: + self._parent_device.write_to_spectrum_device_register( + INPUT_COUPLING_COMMANDS[self._number], input_coupling.value + ) diff --git a/src/spectrumdevice/devices/digitiser/digitiser_interface.py b/src/spectrumdevice/devices/digitiser/digitiser_interface.py index 71709f5..cde0cf4 100644 --- a/src/spectrumdevice/devices/digitiser/digitiser_interface.py +++ b/src/spectrumdevice/devices/digitiser/digitiser_interface.py @@ -14,7 +14,7 @@ from spectrumdevice.devices.abstract_device import SpectrumChannelInterface, SpectrumDeviceInterface from spectrumdevice.settings import AcquisitionMode, AcquisitionSettings from spectrumdevice import Measurement -from spectrumdevice.settings.channel import InputImpedance +from spectrumdevice.settings.channel import InputImpedance, InputCoupling class SpectrumDigitiserChannelInterface(SpectrumChannelInterface, ABC): @@ -52,6 +52,15 @@ def input_impedance(self) -> InputImpedance: def set_input_impedance(self, input_impedance: InputImpedance) -> None: raise NotImplementedError() + @property + @abstractmethod + def input_coupling(self) -> InputCoupling: + raise NotImplementedError() + + @abstractmethod + def set_input_coupling(self, input_coupling: InputCoupling) -> None: + raise NotImplementedError() + class SpectrumDigitiserInterface(SpectrumDeviceInterface, ABC): """Defines the public interface for control of all Spectrum digitiser devices, be they StarHub composite devices diff --git a/src/spectrumdevice/settings/__init__.py b/src/spectrumdevice/settings/__init__.py index ad36c3d..9e457db 100644 --- a/src/spectrumdevice/settings/__init__.py +++ b/src/spectrumdevice/settings/__init__.py @@ -11,7 +11,7 @@ from spectrumdevice.settings.card_dependent_properties import ModelNumber from spectrumdevice.settings.card_features import CardFeature, AdvancedCardFeature -from spectrumdevice.settings.channel import InputImpedance +from spectrumdevice.settings.channel import InputImpedance, InputCoupling from spectrumdevice.settings.device_modes import AcquisitionMode, ClockMode from spectrumdevice.settings.io_lines import IOLineMode, AvailableIOModes from spectrumdevice.settings.transfer_buffer import ( @@ -87,6 +87,8 @@ class AcquisitionSettings: SpectrumDigitiserCard.get_waveforms().""" number_of_averages: int = 1 """If an averaging AcquisitionMode is selected, this defines the number of averages.""" + input_couplings: Optional[List[InputCoupling]] = None + """The coupling (AC or DC) to apply to each channel. Only available on some hardware, so default is None.""" class SpectrumRegisterLength(Enum): diff --git a/src/spectrumdevice/settings/channel.py b/src/spectrumdevice/settings/channel.py index a804191..b68838e 100644 --- a/src/spectrumdevice/settings/channel.py +++ b/src/spectrumdevice/settings/channel.py @@ -13,7 +13,15 @@ SPCM_STOPLVL_HOLDLAST, SPCM_STOPLVL_LOW, SPCM_STOPLVL_ZERO, - SPC_50OHM0, SPC_50OHM1, SPC_50OHM10, SPC_50OHM11, SPC_50OHM12, SPC_50OHM13, SPC_50OHM14, SPC_50OHM15, SPC_50OHM2, + SPC_50OHM0, + SPC_50OHM1, + SPC_50OHM10, + SPC_50OHM11, + SPC_50OHM12, + SPC_50OHM13, + SPC_50OHM14, + SPC_50OHM15, + SPC_50OHM2, SPC_50OHM3, SPC_50OHM4, SPC_50OHM5, @@ -101,6 +109,22 @@ CHANNEL13, CHANNEL14, CHANNEL15, + SPC_ACDC0, + SPC_ACDC1, + SPC_ACDC2, + SPC_ACDC3, + SPC_ACDC4, + SPC_ACDC5, + SPC_ACDC6, + SPC_ACDC7, + SPC_ACDC8, + SPC_ACDC9, + SPC_ACDC10, + SPC_ACDC11, + SPC_ACDC12, + SPC_ACDC13, + SPC_ACDC14, + SPC_ACDC15, ) VERTICAL_RANGE_COMMANDS = ( @@ -251,4 +275,29 @@ class InputImpedance(Enum): SPC_50OHM13, SPC_50OHM14, SPC_50OHM15, -) \ No newline at end of file +) + + +class InputCoupling(Enum): + AC = 1 + DC = 0 + + +INPUT_COUPLING_COMMANDS = ( + SPC_ACDC0, + SPC_ACDC1, + SPC_ACDC2, + SPC_ACDC3, + SPC_ACDC4, + SPC_ACDC5, + SPC_ACDC6, + SPC_ACDC7, + SPC_ACDC8, + SPC_ACDC9, + SPC_ACDC10, + SPC_ACDC11, + SPC_ACDC12, + SPC_ACDC13, + SPC_ACDC14, + SPC_ACDC15, +) diff --git a/src/tests/configuration.py b/src/tests/configuration.py index 07e1623..a70fcad 100644 --- a/src/tests/configuration.py +++ b/src/tests/configuration.py @@ -12,8 +12,8 @@ class SpectrumTestMode(Enum): # Set to TestMode.MOCK_HARDWARE for software-only testing, even if Spectrum drivers are found on the system # Set to TestMode.REAL_HARDWARE to run tests on a real hardware device as configured below. -SINGLE_CARD_TEST_MODE = SpectrumTestMode.MOCK_HARDWARE -STAR_HUB_TEST_MODE = SpectrumTestMode.MOCK_HARDWARE +SINGLE_CARD_TEST_MODE = SpectrumTestMode.REAL_HARDWARE +STAR_HUB_TEST_MODE = SpectrumTestMode.REAL_HARDWARE # Set IP address of real spectrum device (for use if TestMode.REAL_HARDWARE is set above). Set to None to run tests on # a local (PCIe) card. @@ -36,7 +36,7 @@ class SpectrumTestMode(Enum): MOCK_DEVICE_TEST_FRAME_RATE_HZ = 10.0 # Trigger source to use for integration tests. Has no effect in SpectrumTestMode.MOCK_HARDWARE -INTEGRATION_TEST_TRIGGER_SOURCE = TriggerSource.SPC_TMASK_EXT0 +INTEGRATION_TEST_TRIGGER_SOURCE = TriggerSource.SPC_TMASK_SOFTWARE if SINGLE_CARD_TEST_MODE == SpectrumTestMode.REAL_HARDWARE and not SPECTRUM_DRIVERS_FOUND: diff --git a/src/tests/test_single_channel.py b/src/tests/test_single_channel.py index a4fb179..6a58498 100644 --- a/src/tests/test_single_channel.py +++ b/src/tests/test_single_channel.py @@ -1,6 +1,7 @@ from unittest import TestCase from spectrumdevice import SpectrumDigitiserChannel +from spectrumdevice.settings import InputImpedance from tests.device_factories import create_spectrum_card_for_testing @@ -21,3 +22,8 @@ def test_vertical_offset(self) -> None: offset = 1 self._channel.set_vertical_offset_in_percent(offset) self.assertEqual(offset, self._channel.vertical_offset_in_percent) + + def test_input_impedance(self) -> None: + impedance = InputImpedance.ONE_MEGA_OHM + self._channel.set_input_impedance(impedance) + self.assertEqual(impedance, self._channel.input_impedance)