Skip to content

Latest commit

 

History

History
127 lines (110 loc) · 5.81 KB

File metadata and controls

127 lines (110 loc) · 5.81 KB

Introduction

This page describes implementation details.

General information

Basic information

  • Starting point is using a Device object matching attached hardware: DeviceP24 or DeviceI24
    • If you have multiple devices, create multiple Device instances
    • With capabilities it is possible to query for available layer
  • To create a Device object, a Connection object is required, use SerialConnection to connect to a serial port
    • Connection must be opened and closed
  • Call device.initialize() to get a defined state of the device (it stops any active stimulation/measurement)
  • Device object has layers to access commands
    • Layer object has functions to send commands to the device and process acknowledges
    • To access layer, use helper functions get_layer_xxx
    • DeviceP24 has layer general, low level and mid level
    • DeviceI24 has layer general and dyscom
    • Do not mix usage of layers because device has a single internal state, e.g. calling low level init() and afterwards mid level update() will not work

Device communication

  • Each device has an instance of a PacketBuffer
    • Should be used to read packets from connection
    • Handles extraction of packets from byte stream
  • Most functions communicating with the device are async functions using name schema xxx, because they wait for a matching acknowledge and return values from acknowledge
    • If no matching acknowledge or no acknowledge arrives in time, an exception is raised
    • If a command has an error information and an error is set, an exception is raised
    • The async functions connection buffer handling is always identical:
      • Clear buffer
      • Send command
      • Process incoming data until the expected acknowledge arrives
      • More data remains in connection buffer
    • Do not call async functions in parallel (e.g. from different event loops), because each function expects specific commands from the device and clears incoming data buffer
  • Additionally functions with naming schema send_xxx are normal functions not waiting for acknowledge
    • The acknowledge needs to handled manually by using PacketBuffer object from device

Logging

  • Library creates a custom logger, see class Logger
  • By default some information is logged to console
  • Set log level to DEBUG to get more detailed information
    • logger().setLevel(logging.DEBUG)
  • For better performance, disable logger
    • logger().disabled = True

General layer (all devices)

  • Contains functions to get common information like device serial or firmware version

Mid level layer (P24)

  • Contains functions for mid level stimulation
  • This mode is good to let the device stimulate a predefined pattern until stop() is send
  • Usage
    • Call init() to set device in mid level mode
    • Call update() with stimulation pattern
    • Call get_current_data() every 1.5s to keep stimulation ongoing
    • Call stop() to end stimulation and leave mid level mode

Low level layer (P24)

  • Contains functions for low level stimulation
  • This mode is good to react to a external trigger to change stimulation pattern
  • Without send_channel_config() the device will not stimulate
  • Usage
    • Call init() to set device in low level mode
    • Update configuration with send_channel_config() when external trigger occurs
      • As soon as send_channel_config() arrives at device, it stimulates according stimulation pattern
      • It stops stimulation when stimulation pattern is over
    • Call stop() to leave low level mode

Dyscom layer (I24)

  • Contains functions for dyscom level
  • This mode is used by I24 to measure EMG or BI
  • Usage for live data
    • Call power_module() to power on measurement module
    • Call init() with parameter for measurement and DyscomInitFlag for live data
    • Call start() to start measurement
      • Device sends now DlSendLiveData packets with measurement data
    • Call stop() to end measurement
    • Call power_module() to power off measurement module
  • Usage for measurement data read from memory card
    • Call power_module() to power on measurement module and memory card
    • Call init() with parameter for measurement and DyscomInitFlag for storage mode
      • Result contains measurement id, that is the filename used later
    • Call start() to start measurement
      • Device sends nothing but stores measurement data on memory card
    • Call stop() to end measurement
    • Call power_module() to power off measurement module
    • Call get_meas_file_content() with filename from init() to get measurement data
    • Call power_module() to power off memory card
  • IMPORTANT: not all storage related functions are tested

Platform hints

Using USB under Linux with Hyper-V

  • On Windows
    • Install usbipd-win
    • usbipd list
    • usbipd bind --busid <BUSID>
  • On Linux
    • Install usbip
      • sudo apt install linux-tools-generic usbip
    • sudo usbip attach -r <host-ip> -b <BUSID>
    • In case of permission error
      • sudo chmod 666 /dev/ttyACMx

Using MacOS under VirtualBox

I24 protocol hints

DL_init

  • Init state seems always be UNUSED
  • Output data rate depends on init params filter property
  • Setting a filter overwrite other settings
    • ADS129x register channel 1-4 settings
    • ADS129x config register output data rate
    • Maybe more register values are changed

DL_get for type file system status and list of measurement info

  • Return never meaningful values, probably not implemented on I24 side

DL_get for type battery

  • Dl get types (table 23)
    • 0 -> Battery (was Unused)

DL_send_live_data

  • SignalType for each sample is always 0
  • Contains always 5 samples, regardless of selected signal types in DL_init
    • Fifth sample value seems always be zero