{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "dvrk-IO.schema.json",
    "title": "dVRK IO",
    "type": "object",
    "description": "Configuration file format for the dVRK IO.\n\n - This format is used by the dVRK system configuration file.\n - For details of implementation, see code under `sawIntuitiveResearchKit/core/components/code/IO_proxy_configuration.cdg`\n - [Schema file](dvrk-IO.schema.json)",
    "additionalProperties": false,
    "required": ["name", "port"],
    "properties": {

	"name": {
	    "type": "string",
	    "description": "Arbitrary name picked to name a single connection to dVRK controllers. Traditionally, dVRK systems used a single IO with a FireWire port. Default convention is to name the IO something like `IO`, `IO1`, `IO2`...\n\nThe name is used later on by the arms, inputs and any other component that needs to know which IO port should be used to communicate with a dVRK controller."
	},

	"port": {
            "type":"string",
            "description": "The port defines the type of connection between the PC and the dVRK controllers. For anyone using FireWire for all the connections, the setting should be `fw`. If your system uses FireWire between the dVRK controller and Ethernet to bridge between the controllers and the PC, use `udpfw`. Finally, if your system is recent (post 2024) and only uses FPGA V3, you can connect everything using only Ethernet cables and use `udp`.\nIf you have multiple FireWire or Ethernet adapters on your PC, you will need to add the FireWire port number or Ethernet IP address after the port's type (e.g. `fw:1`).\n\nHaving multiple IOs is very convenient to handle systems with multiple surgeon's consoles and avoid board Id conflicts. For example, one might want a system with 2 MTMLs and 2 MTMRs. The issue is that each arm assumes a default board Id based on the arm's type. Therefore, both MTMLs would use the same board Id(s) and create a conflict if used on the same IO port. It would be possible to update all your arms configuration files to change some board Ids but it's easier to use multiple ports.\n\nAccepted values are `fw`, `fw:X` (`X` is FireWire port), `udpfw`, `udp` or `udp:xx.xx.xx.xx` (`xx.xx.xx.xx` is the IP address of the dVRK controller.  Default controller address is 169.254.0.100.  Values are parsed by `BasePort::ParseOptions` in library Amp1394.",
            "pattern": "^fw$|^fw:[0-9]$|^udp$|^udp:[0-9]{2,3}.[0-9]{2,3}.[0-9]{2,3}.[0-9]{2,3}|^udpfw|^udpfw:[0-9]{2,3}.[0-9]{2,3}.[0-9]{2,3}.[0-9]{2,3}$",
            "examples": [
                {
					"name": "IO1",
                    "port": "fw"
                },
                {
					"name": "IO1",
                    "port": "udpfw"
                },
				{
					"name": "IO1",
                    "port": "udp"
                }
            ]
        },

        "protocol": {
            "type": "string",
            "description": "Protocol used for all communications. This applies wether the controllers are connected to the computer using FireWired or Ethernet (UDP with Link-Local `fw`, `udpfw` or `udp`).  This is an advanced setting and most users should avoid defining it.\n\n - `sequential-read-write`: the PC reads data from each board (2 FPGA/QLA per controller), performs its computations (conversions, safety checks, PID, ...) and then writes sequentially to each board (N reads, N writes). This is the only protocol supported on older firmware (3 and below).\n - `sequential-read-broadcast-write`: the PC reads sequentially but performs a single write for all the boards. The write message is an array of values sent to the boards, each board access the data it needs by index (N reads, 1 write). This is the default protocol for the dVRK controllers with firmware 4 and above.\n - `broadcast-query-read-write`: the PC sends a single query/synchronization to all boards, read values are aggregated in single packet over the bus and there's a single write (1 query, 1 read, 1 write). This is the fastest protocol available but some FireWire cards seem to have trouble synchronizing the read packets. You will have to test it on your hardware to see if it supports this protocol or not.  `broadcast-read-write` is the older name for this protocol and is provided for backward compatibility.",
            "enum": ["sequential-read-write", "srw",
                     "sequential-read-broadcast-write", "srbw",
                     "broadcast-query-read-write", "bqrw",
                     "broadcast-read-write", "brw"],
            "default": "sequential-read-broadcast-write"
        },

        "period": {
            "type": "number",
            "description": "Periodicity for the IO and PID loop.  Defined in seconds, i.e. interval between two iterations.  The default is defined in `mtsIntuitiveResearchKit.h` and is set so the loop frequency is 1500Hz, ~0.66ms so 0.00066s.  This is an advanced setting and most users should avoid defining it.",
            "exclusiveMinimum": 0.0,
            "examples": [
                {
                    "period": 0.001
                }
            ]
        },

        "watchdog_timeout": {
            "type": "number",
            "description": "Maximum lapse of time allowed between read/write accesses to the dVRK controllers.  It is used to detect abnormally slow IOs or disconnected cables.  The value is sent to the controllers and the controllers will turn off power if the communication loop time exceeds the watchdog timeout.\n\nDefined in seconds.  The default is defined in `mtsIntuitiveResearchKit.h` and is set to 30ms.  This is an advanced setting and most users should avoid defining it.  Setting it to zero disables the watchdog and should only be used by **experts**.  The maximum value is 300ms, i.e. 0.3s",
            "minimum": 0.0,
            "maximum": 0.3,
            "examples": [
                {
                    "watchdog-timeout": 0.05
                }
            ]
        },

        "configuration_files": {
            "type": "array",
            "description": "Extra configuration files to configure the IO component. The IO component can also be configured to support custom hardware using the controllers spare digital and analog IOs.\n\nThis setting shouldn't be used for the hardware supported by the dVRK software stack such as foot pedals, head sensor, focus controller... See examples in directory `share/io`.",
            "items": {
                "type": "string"
            },
            "examples": [
                {
                    "configuration_files": ["sawRobotIO1394_my_contact_sensor.json"]
                }
            ]
        },

	"close_all_relays": {
            "type": "boolean",
            "description": "Close all the e-stop safety relays on all the controllers found on the current port (FireWire or Ethernet).  This allows the user to skip the terminal based command: `qlacommand -c close-relays`.",
            "default": true
        }
    }
}
