herosdevices.hardware.santec.slm200
===================================

.. py:module:: herosdevices.hardware.santec.slm200

.. autoapi-nested-parse::

   HERO driver and functions to control a Santec SLM.







Module Contents
---------------

.. py:data:: msg
   :value: ''


.. py:data:: FPGA_STATUS

.. py:data:: VIDEO_MODE

.. py:data:: CMD_CONTROL

.. py:data:: CMD_STATUSREQUEST

.. py:data:: CMD_STATUSRESPONSE

.. py:data:: CMD_IMAGEDATA

.. py:class:: SLM200(serial_number: str, config_dict: dict, default_config: str | None = None, keep_device_open: bool = True, channel: int = 0)

   Bases: :py:obj:`herosdevices.core.templates.DisplayDeviceTemplate`


   Driver for a Santec SLM200 spatial light modulator.

   The images can be transferred to the SLM200 via USB or DVI. This driver, however, only supports
   communication via USB. Since image upload via USB takes roughly 150ms, this driver is limited to
   around 6Hz of refresh rate. Precise and externally synchronized timing is only possible in USB mode.

   In USB mode (also called memory mode) images can be pushed via USB and stored in one of 128 memory
   slots. The image slot displayed on the SLM can be set randomly by the driver or an advance from one
   slot to the next can be triggered by a software trigger, and internal timer, or a logic signal
   (Trigger IN SMB jack).

   The SLM contains an FPGA that the computer communicates with by writing to an output FIFO/pipe
   and reading from an input FIFO/pipe. These two FIFOs are transparently accessed through the FTDI
   driver (D3xx) which provides methods to read and write these FIFOs/pipes.

   This driver is reverse engineered by looking at the data the vendor software sends via USB.
   This was achieved by looking at the API calls to the functions FT_WritePipe and FT_ReadPipe
   in the D3XX.dll which handles the communication with the FTDI USB3.0 chip (FT601).


   .. py:attribute:: MIN_SLOT
      :type:  int
      :value: 1



   .. py:attribute:: MAX_SLOT
      :type:  int
      :value: 128



   .. py:attribute:: IMAGE_SIZE
      :type:  tuple[int, int]
      :value: (1200, 1920)



   .. py:attribute:: default_config_dict
      :type:  dict


   .. py:attribute:: firmware_versions
      :value: ['2018021001', '2018021101', '2018020001', '2017080002', '2015010001']



   .. py:attribute:: trigger_functions


   .. py:attribute:: serial_number


   .. py:attribute:: channel
      :value: 0



   .. py:attribute:: firmware
      :type:  str | None
      :value: None



   .. py:attribute:: streaming_mode
      :type:  bool
      :value: False



   .. py:attribute:: request_sleep
      :type:  float
      :value: 0.015



   .. py:method:: write(buffer: bytes) -> None

      Stream buffered data to the SLM.



   .. py:method:: write_command(cmd_dict: dict, payload: bytes, seq_id: int = 0) -> None

      Send a command to the SLM.



   .. py:method:: read(length: int) -> bytes

      Read `length` bytes from the device.



   .. py:method:: read_command(length: int) -> dict

      Read a command response from the SLM.

      :param length: Length of the response to read in byte



   .. py:method:: request(cmd_dict: dict, payload: bytes, buffer: bytes | None = None, trials: int = 100, request_sleep: float | None = None) -> str

      Send a request to the SLM and wait for a response.

      :param cmd_dict: Dictionary containing command metadata
      :param payload: Payload to send, unused when buffer is used
      :param buffer: Pre-assembled buffer to send
      :param trials: Number of trials to attempt
      :param request_sleep: Sleep time between retries

      :returns: Status



   .. py:method:: firmware_serialnumber() -> str

      Get the serial number of the santec firmware running on the SLM.

      This not the same as the serial number used to identify the FTDI chip.

      :returns: Serial number.



   .. py:method:: video_mode(mode: int | str = 'USB') -> bool

      Set the video source the SLM draws the images from.

      :param mode: Video source. 0 = USB/Memory, 1 = DVI.

      :returns: Status of the operation.



   .. py:method:: contrast_level(value: int) -> bool

      Set the contrast/gamma level of the LCOS.

      :param value: Value between 0 and 1023.

      :returns: Status of the operation.



   .. py:method:: trigger_output(on: bool | None = None) -> bool

      Activate the trigger output of the SLM.

      This is especially useful in DVI mode orwhen software/automatic triggers are used.

      :param on: Determines whether the trigger output should be activated
                 If not set the current status is returned

      :returns: Status of the operation.



   .. py:method:: do_phase_calibration(wavelength: int, max_phase: int = 2) -> bool

      Calibrate the change of the lights phase as function of the bit value of each pixel.

      This can be used to adapt for different wavelength of the light and to change the
      maximum phase change for the maximum pixel value of 1023 (10bit).

      .. attention::
          This command takes some minutes to finish!

      :param wavelength: Wavelength of the indicent light in nm
      :param max_phase: Maximum phase change in units of pi

      :returns: Status of the operation.



   .. py:method:: trigger_software_fire() -> bool

      Fire a software trigger. Only works if the trigger mode was set to manual before.

      :returns: Status of the operation



   .. py:method:: trigger(mode: str | None = None) -> str

      Set or query the trigger mode.

      .. hint::
          The SLM can be triggered from four different sources:
              * none     : The image selected by :func:`display_slot` is displayed continuously                              and no trigger changes this.
              * manual   : The image in the next slot is displayed when the software trigger                              :func:`trigger_software_fire` is called.
              * auto     : The change to the next image is periodically triggered by an internal timer.
              * external : The change to the next image happens when a logic pulse on the trigger in                              SMB-connector is received.

      :param mode: Name of the trigger mode to set. If no argument is given,
                   the current trigger mode is returned

      :returns: The trigger mode



   .. py:attribute:: keep_device_open
      :value: True



   .. py:attribute:: default_config
      :type:  str


   .. py:method:: get_device() -> collections.abc.Iterator[None]

      Yield a device handle.

      .. code-block:: python

          # use the device in a with statement
          with self.get_device() as slm:
              slm.do_something()



   .. py:method:: open() -> Any

      Open the device handler and assign it to `self._device`.



   .. py:method:: teardown() -> None

      Release the device handler and potentially de-initialize the API.



   .. py:method:: reset() -> None

      Reset the device by closing and re-opening the handler.



   .. py:method:: get_status() -> dict

      Get a dict with the current device status.

      :returns: A dict with the device status



   .. py:property:: config_dict
      :type: dict


      Get a copy of the configuration dict.

      :returns: Copy of the configuration dict


   .. py:method:: update_configuration(new_config_dict: dict, merge: bool = True) -> None

      Update the configuration dict with new configuration.

      Each dict key corresponds a (new) configuration name.
      Each value is a dict with config property -> config value.

      :param new_config_dict: A dict of configurations where the keys are the configuration names
      :param merge: If ``True``, the new dict is recursively merged with the current set config dict. If ``False`` the
                    old configurations with the provided names (keys) are overwritten.



   .. py:method:: get_configuration() -> dict

      Get the currently active configuration.

      :returns: The currently active configuration.



   .. py:method:: configure(config: str = '') -> bool

      Configure the device with the known configuration `config`.

      To add a configuration to the device, use :meth:`update_configuration`.

      :param config: Key (name) of the configuration



   .. py:attribute:: set_configuration


   .. py:method:: push_image(slot: int, image: numpy.typing.NDArray[numpy.uint16], display_now: bool = True) -> bool

      Upload an image into a specified memory slot.

      :param slot: Slot number
      :param image: The image
      :param display_now: Flag whether to display the image immediately



   .. py:method:: display_slot(slot: int = 1) -> bool

      Set the memory slot to display on the SLM.

      :param slot: Slot number



.. py:data:: logger

