PageRenderTime 65ms CodeModel.GetById 41ms RepoModel.GetById 0ms app.codeStats 0ms

/Main/GadgeteerCore/Gadgeteer42/Socket.cs

#
C# | 656 lines | 333 code | 48 blank | 275 comment | 45 complexity | 3eb558bb829e5f64f92802f98b658d31 MD5 | raw file
  1. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  4. namespace Gadgeteer
  5. {
  6. using Microsoft.SPOT;
  7. using Microsoft.SPOT.Hardware;
  8. using System;
  9. using System.Collections;
  10. using System.ComponentModel;
  11. using Gadgeteer.Modules;
  12. /// <summary>
  13. /// A class representing a socket, which may be on a mainboard or on an expansion module such as an SPI multiplexer.
  14. /// </summary>
  15. /// <remarks>
  16. /// This class is normally not directly used by application programs, who refer to sockets by their socket number.
  17. /// Modules should normally use this class and the GT.Interfaces classes to access functionality required to implement their APIs.
  18. /// Mainboards and multiplexer modules providing sockets should use this class's SocketInterfaces subclass to declare functionalities provided on their sockets.
  19. /// </remarks>
  20. public partial class Socket
  21. {
  22. /// <summary>
  23. /// The <see cref="SocketInterfaces.AnalogInput" /> provider for this socket.
  24. /// </summary>
  25. public SocketInterfaces.AnalogInputIndirector AnalogInputIndirector;
  26. /// <summary>
  27. /// The <see cref="SocketInterfaces.DigitalInput" /> provider for this socket.
  28. /// </summary>
  29. public SocketInterfaces.DigitalInputIndirector DigitalInputIndirector;
  30. /// <summary>
  31. /// The <see cref="SocketInterfaces.DigitalIO" /> provider for this socket.
  32. /// </summary>
  33. public SocketInterfaces.DigitalIOIndirector DigitalIOIndirector;
  34. /// <summary>
  35. /// The <see cref="SocketInterfaces.DigitalOutput" /> provider for this socket.
  36. /// </summary>
  37. public SocketInterfaces.DigitalOutputIndirector DigitalOutputIndirector;
  38. /// <summary>
  39. /// The <see cref="SocketInterfaces.I2CBus" /> provider for this socket.
  40. /// </summary>
  41. public SocketInterfaces.I2CBusIndirector I2CBusIndirector;
  42. /// <summary>
  43. /// The <see cref="SocketInterfaces.InterruptInput" /> provider for this socket.
  44. /// </summary>
  45. public SocketInterfaces.InterruptInputIndirector InterruptIndirector;
  46. /// <summary>
  47. /// The <see cref="SocketInterfaces.PwmOutput" /> provider for this socket.
  48. /// </summary>
  49. public SocketInterfaces.PwmOutputIndirector PwmOutputIndirector;
  50. /// <summary>
  51. /// The <see cref="SocketInterfaces.Serial" /> provider for this socket.
  52. /// </summary>
  53. public SocketInterfaces.SerialIndirector SerialIndirector;
  54. /// <summary>
  55. /// The <see cref="SocketInterfaces.Spi" /> provider for this socket.
  56. /// </summary>
  57. public SocketInterfaces.SpiIndirector SpiIndirector;
  58. /// <summary>
  59. /// The socket number corresponding to this socket. On mainboards, this is a positive number and is printed on the board itself.
  60. /// For module-provided sockets (i.e. sockets you plug other modules into) this is an automatically generated negative number.
  61. /// </summary>
  62. public int SocketNumber { get; private set; }
  63. /// <summary>
  64. /// The name of the socket. This is shown to users in any socket-related error messages generated by Gadgeteer Core.
  65. /// </summary>
  66. public string Name { get; private set; }
  67. /// <summary>
  68. /// Array of pins used by the socket. This is always of size 11, with index [1] to [10] being the relevant Cpu.Pin for the Socket.Pin.
  69. /// Index 0 is unused.
  70. /// </summary>
  71. public Cpu.Pin[] CpuPins { get; private set; }
  72. /// <summary>
  73. /// The supported types of this socket.
  74. /// </summary>
  75. public char[] SupportedTypes
  76. {
  77. get
  78. {
  79. return _SupportedTypes;
  80. }
  81. set
  82. {
  83. if (_registered) throw new SocketImmutableAfterRegistrationException();
  84. _SupportedTypes = value;
  85. }
  86. }
  87. private char[] _SupportedTypes = new char[] { };
  88. /// <summary>
  89. /// The SPI_module corresponding to this socket. This is Socket.SPIMissing if there is no SPI module on this socket.
  90. /// </summary>
  91. public SPI.SPI_module SPIModule
  92. {
  93. get
  94. {
  95. return _SPIModule;
  96. }
  97. set
  98. {
  99. if (_registered) throw new SocketImmutableAfterRegistrationException();
  100. _SPIModule = value;
  101. }
  102. }
  103. private SPI.SPI_module _SPIModule = Socket.SocketInterfaces.SPIMissing;
  104. /// <summary>
  105. /// Returns the serial port name (e.g. "COM1") associated with a particular socket.
  106. /// </summary>
  107. /// <returns>The serial port name</returns>
  108. public string SerialPortName
  109. {
  110. get
  111. {
  112. return _serialPortName;
  113. }
  114. set
  115. {
  116. if (_registered) throw new SocketImmutableAfterRegistrationException();
  117. _serialPortName = value;
  118. }
  119. }
  120. private string _serialPortName = null;
  121. /// <summary>
  122. /// Provides access to pulse width modulation (PWM) functionality on a socket pin 7.
  123. /// </summary>
  124. /// <returns>An instance of the Cpu.PWMChannel enumeration, which should be PWM_NONE if there is no PWM support.</returns>
  125. public Cpu.PWMChannel PWM7
  126. {
  127. get
  128. {
  129. return _PWM7;
  130. }
  131. set
  132. {
  133. if (_registered) throw new SocketImmutableAfterRegistrationException();
  134. _PWM7 = value;
  135. }
  136. }
  137. private Cpu.PWMChannel _PWM7 = Cpu.PWMChannel.PWM_NONE;
  138. /// <summary>
  139. /// Provides access to pulse width modulation (PWM) functionality on a socket pin 8.
  140. /// </summary>
  141. /// <returns>An instance of the Cpu.PWMChannel enumeration, which should be PWM_NONE if there is no PWM support on this socket pin.</returns>
  142. public Cpu.PWMChannel PWM8
  143. {
  144. get
  145. {
  146. return _PWM8;
  147. }
  148. set
  149. {
  150. if (_registered) throw new SocketImmutableAfterRegistrationException();
  151. _PWM8 = value;
  152. }
  153. }
  154. private Cpu.PWMChannel _PWM8 = Cpu.PWMChannel.PWM_NONE;
  155. /// <summary>
  156. /// Provides access to pulse width modulation (PWM) functionality on a socket pin 9.
  157. /// </summary>
  158. /// <returns>An instance of the Cpu.PWMChannel enumeration, which should be PWM_NONE if there is no PWM support on this socket pin.</returns>
  159. public Cpu.PWMChannel PWM9
  160. {
  161. get
  162. {
  163. return _PWM9;
  164. }
  165. set
  166. {
  167. if (_registered) throw new SocketImmutableAfterRegistrationException();
  168. _PWM9 = value;
  169. }
  170. }
  171. private Cpu.PWMChannel _PWM9 = Cpu.PWMChannel.PWM_NONE;
  172. internal double AnalogInputScale = double.MinValue;
  173. internal double AnalogInputOffset = double.MinValue;
  174. internal int AnalogInputPrecisionInBits = int.MinValue;
  175. /// <summary>
  176. /// Provides access to analog input functionality on a socket's pin 3.
  177. /// </summary>
  178. /// <returns>An instance of the Cpu.AnalogChannel enumeration, which should be ANALOG_NONE if there is no Analog input support on this socket pin.</returns>
  179. public Cpu.AnalogChannel AnalogInput3
  180. {
  181. get
  182. {
  183. return _AnalogInput3;
  184. }
  185. set
  186. {
  187. if (_registered) throw new SocketImmutableAfterRegistrationException();
  188. _AnalogInput3 = value;
  189. }
  190. }
  191. private Cpu.AnalogChannel _AnalogInput3 = Cpu.AnalogChannel.ANALOG_NONE;
  192. /// <summary>
  193. /// Provides access to analog input functionality on a socket's pin 4.
  194. /// </summary>
  195. /// <returns>An instance of the Cpu.AnalogChannel enumeration, which should be ANALOG_NONE if there is no Analog input support on this socket pin.</returns>
  196. public Cpu.AnalogChannel AnalogInput4
  197. {
  198. get
  199. {
  200. return _AnalogInput4;
  201. }
  202. set
  203. {
  204. if (_registered) throw new SocketImmutableAfterRegistrationException();
  205. _AnalogInput4 = value;
  206. }
  207. }
  208. private Cpu.AnalogChannel _AnalogInput4 = Cpu.AnalogChannel.ANALOG_NONE;
  209. /// <summary>
  210. /// Provides access to analog input functionality on a socket's pin 5.
  211. /// </summary>
  212. /// <returns>An instance of the Cpu.AnalogChannel enumeration, which should be ANALOG_NONE if there is no Analog input support on this socket pin.</returns>
  213. public Cpu.AnalogChannel AnalogInput5
  214. {
  215. get
  216. {
  217. return _AnalogInput5;
  218. }
  219. set
  220. {
  221. if (_registered) throw new SocketImmutableAfterRegistrationException();
  222. _AnalogInput5 = value;
  223. }
  224. }
  225. private Cpu.AnalogChannel _AnalogInput5 = Cpu.AnalogChannel.ANALOG_NONE;
  226. /// <summary>
  227. /// Provides access to analog output functionality on a socket.
  228. /// </summary>
  229. /// <remarks>
  230. /// Relies on native or hardware support for analog output provided by the mainboard manufacturer.
  231. /// </remarks>
  232. /// <returns>An instance of the SocketInterfaces.AnalogOutput class, which provides access to underlying analog output functionality.</returns>
  233. public SocketInterfaces.AnalogOutput AnalogOutput
  234. {
  235. get
  236. {
  237. return _AnalogOutput;
  238. }
  239. set
  240. {
  241. if (_registered) throw new SocketImmutableAfterRegistrationException();
  242. _AnalogOutput = value;
  243. }
  244. }
  245. private SocketInterfaces.AnalogOutput _AnalogOutput = null;
  246. /// <summary>
  247. /// NativeI2C functionality provided by the socket. Null if not available on this socket.
  248. /// </summary>
  249. public SocketInterfaces.NativeI2CWriteReadDelegate NativeI2CWriteRead
  250. {
  251. get
  252. {
  253. return _NativeI2CWriteRead;
  254. }
  255. set
  256. {
  257. if (_registered) throw new SocketImmutableAfterRegistrationException();
  258. _NativeI2CWriteRead = value;
  259. }
  260. }
  261. private SocketInterfaces.NativeI2CWriteReadDelegate _NativeI2CWriteRead = null;
  262. internal static ArrayList _sockets = new ArrayList();
  263. /// <summary>
  264. /// A special socket number indicating that a module socket is not used.
  265. /// </summary>
  266. public static int Unused { get { return int.MinValue; } }
  267. /// <summary>
  268. /// Get the <see cref="Socket"/> corresponding to a socket number.
  269. /// </summary>
  270. /// <param name="socketNumber">The socket number</param>
  271. /// <param name="throwExceptionIfSocketNumberInvalid">Whether to throw an <see cref="InvalidSocketException"/> if the socket does not exist.</param>
  272. /// <param name="module">The module using this socket.</param>
  273. /// <param name="socketLabel">The label on the socket, if there is more than one socket on the module (can be null).</param>
  274. /// <returns>The socket corresponding to the provided socket number.</returns>
  275. public static Socket GetSocket(int socketNumber, bool throwExceptionIfSocketNumberInvalid, Module module, string socketLabel)
  276. {
  277. if (socketLabel == "") socketLabel = null;
  278. if (socketNumber == Socket.Unused)
  279. {
  280. if (throwExceptionIfSocketNumberInvalid)
  281. {
  282. if (module == null)
  283. {
  284. throw new InvalidSocketException("Cannot get Socket for socket number Socket.NotConnected");
  285. }
  286. else
  287. {
  288. String errormessage = "Module " + module;
  289. if (socketLabel != null) errormessage += " socket " + socketLabel;
  290. errormessage += " must have a valid socket number specified (it does not support Socket.Unused)";
  291. throw new InvalidSocketException(errormessage);
  292. }
  293. }
  294. else
  295. {
  296. return null;
  297. }
  298. }
  299. lock (_sockets)
  300. {
  301. foreach (Socket socket in _sockets)
  302. {
  303. if (socket.SocketNumber == socketNumber) return socket;
  304. }
  305. }
  306. if (throwExceptionIfSocketNumberInvalid)
  307. {
  308. if (module == null)
  309. {
  310. throw new InvalidSocketException("Invalid socket number " + socketNumber + " specified.");
  311. }
  312. else
  313. {
  314. String errormessage = "Module " + module;
  315. if (socketLabel != null) errormessage += " socket " + socketLabel;
  316. errormessage += " cannot be used with invalid socket number " + socketNumber;
  317. throw new InvalidSocketException(errormessage);
  318. }
  319. }
  320. return null;
  321. }
  322. internal bool _registered = false;
  323. internal Socket(int socketNumber, string name)
  324. {
  325. this.Name = name;
  326. this.SocketNumber = socketNumber;
  327. this.CpuPins = new Cpu.Pin[11] { Socket.UnspecifiedPin, Socket.UnspecifiedPin, Socket.UnspecifiedPin, Socket.UnspecifiedPin, Socket.UnspecifiedPin, Socket.UnspecifiedPin, Socket.UnspecifiedPin, Socket.UnspecifiedPin, Socket.UnspecifiedPin, Socket.UnspecifiedPin, Socket.UnspecifiedPin };
  328. }
  329. /// <summary>
  330. /// Returns the Name of this socket.
  331. /// </summary>
  332. /// <returns></returns>
  333. public override string ToString()
  334. {
  335. return Name;
  336. }
  337. /// <summary>
  338. /// Determines whether the specified socket supports the given socket type
  339. /// </summary>
  340. /// <param name="type">The socket type</param>
  341. /// <returns></returns>
  342. public bool SupportsType(char type)
  343. {
  344. foreach (char supportedType in SupportedTypes)
  345. {
  346. if (type == supportedType) return true;
  347. }
  348. return false;
  349. }
  350. /// <summary>
  351. /// Checks that a given socket type is supported, and throws an <see cref="InvalidSocketException"/> if not. Optionally specifies the module which requires this type, resulting in a better error message.
  352. /// </summary>
  353. /// <param name="type">The socket type required.</param>
  354. /// <param name="module">The module requiring this socket type (can be null).</param>
  355. public void EnsureTypeIsSupported(char type, Module module)
  356. {
  357. if (!SupportsType(type))
  358. {
  359. throw new InvalidSocketException("Socket " + Name + " does not support type '" + type + "'" + (module != null ? " required by " + module + " module." : "."));
  360. }
  361. }
  362. /// <summary>
  363. /// Checks that one of a given set of socket types is supported, and throws an <see cref="InvalidSocketException"/> if not. Optionally specifies the module which requires this type, resulting in a better error message.
  364. /// </summary>
  365. /// <param name="types">The array of socket types required (any one of these is sufficient).</param>
  366. /// <param name="module">The module requiring this socket type (can be null).</param>
  367. public void EnsureTypeIsSupported(char[] types, Module module)
  368. {
  369. foreach (char type in types)
  370. {
  371. if (SupportsType(type)) return;
  372. }
  373. throw new InvalidSocketException("Socket " + Name + " does not support one of the types '" + new String(types) + "'" + (module != null ? " required by " + module + " module." : "."));
  374. }
  375. /// <summary>
  376. /// An enumeration of socket pins.
  377. /// </summary>
  378. public enum Pin
  379. {
  380. /// <summary>
  381. /// Socket pin 1
  382. /// </summary>
  383. One = 1,
  384. /// <summary>
  385. /// Socket pin 2
  386. /// </summary>
  387. Two = 2,
  388. /// <summary>
  389. /// Socket pin 3
  390. /// </summary>
  391. Three = 3,
  392. /// <summary>
  393. /// Socket pin 4
  394. /// </summary>
  395. Four = 4,
  396. /// <summary>
  397. /// Socket pin 5
  398. /// </summary>
  399. Five = 5,
  400. /// <summary>
  401. /// Socket pin 6
  402. /// </summary>
  403. Six = 6,
  404. /// <summary>
  405. /// Socket pin 7
  406. /// </summary>
  407. Seven = 7,
  408. /// <summary>
  409. /// Socket pin 8
  410. /// </summary>
  411. Eight = 8,
  412. /// <summary>
  413. /// Socket pin 9
  414. /// </summary>
  415. Nine = 9,
  416. /// <summary>
  417. /// Socket pin 10
  418. /// </summary>
  419. Ten = 10
  420. }
  421. /*
  422. private static ArrayList _reservedPins = new ArrayList();
  423. internal class PinReservation
  424. {
  425. public Socket ReservingSocket { get; private set; }
  426. public Socket.Pin ReservingPin { get; private set; }
  427. public Cpu.Pin CpuPin { get; private set; }
  428. public Module ReservingModule { get; private set; }
  429. public PinReservation(Socket socket, Socket.Pin pin, Cpu.Pin cpuPin, Module module)
  430. {
  431. ReservingSocket = socket;
  432. ReservingModule = module;
  433. ReservingPin = pin;
  434. CpuPin = cpuPin;
  435. }
  436. }
  437. */
  438. /// <summary>
  439. /// Tells GadgeteerCore that a pin is being used on this socket.
  440. /// This is called by Gadgteeer.Interface classes automatically. Gadgeteer.Modules which do not use a Gadgeteer.Interface helper class in using a pin should call this directly.
  441. /// Note that Gadgeteer allows mainboard pins to be reused across multiple sockets, so the reservation check also checks if the pin is used on a different socket where the pin is shared.
  442. /// </summary>
  443. /// <param name="pin">The socket pin being used</param>
  444. /// <param name="module">The module using the socket pin (can be null, but if it is not null a more useful error message will be generated).</param>
  445. /// <returns></returns>
  446. public Cpu.Pin ReservePin(Socket.Pin pin, Module module)
  447. {
  448. Cpu.Pin cpuPin = CpuPins[(int)pin];
  449. if (cpuPin == UnspecifiedPin)
  450. {
  451. throw new PinMissingException(this, pin);
  452. }
  453. if (cpuPin == UnnumberedPin)
  454. {
  455. // bypass checks, return no pin
  456. return Cpu.Pin.GPIO_NONE;
  457. }
  458. /*
  459. // Check to see if pin is already reserved
  460. foreach (PinReservation reservation in _reservedPins)
  461. {
  462. if (cpuPin == reservation.CpuPin)
  463. {
  464. throw new PinConflictException(this, pin, module, reservation);
  465. }
  466. }
  467. */
  468. // see if this is a display socket and reboot if we need to disable the LCD controller
  469. if (!(module is Module.DisplayModule) && (SupportsType('R') || SupportsType('G') || SupportsType('B')))
  470. {
  471. Module.DisplayModule.LCDControllerPinReuse();
  472. }
  473. //_reservedPins.Add(new PinReservation(this, pin, cpuPin, module));
  474. return cpuPin;
  475. }
  476. /// <summary>
  477. /// An exception raised when a socket pin which is unspecified by the socket provider is used.
  478. /// </summary>
  479. public class PinMissingException : ApplicationException
  480. {
  481. internal PinMissingException(Socket socket, Socket.Pin pin)
  482. : base("\nPin " + (int)pin + " on socket " + socket + " is not connected to a valid CPU pin.")
  483. { }
  484. }
  485. /*
  486. /// <summary>
  487. /// An exception raised when there is a pin conflict.
  488. /// </summary>
  489. public class PinConflictException : ApplicationException
  490. {
  491. internal PinConflictException(Socket socket, Socket.Pin pin, Module module, PinReservation priorReservation)
  492. : base("\nUnable to configure the " + (module != null ? module + " " : "") + "module using socket " + socket + " (pin " + (int)pin + "). " +
  493. "There is a conflict with the " + (priorReservation.ReservingModule != null ? priorReservation.ReservingModule + " " : "") + "module using socket " +
  494. priorReservation.ReservingSocket + " (pin " + priorReservation.ReservingPin + "). Please try using a different combination of sockets.")
  495. { }
  496. }
  497. */
  498. /// <summary>
  499. /// An exception raised when an invalid socket is specified, e.g. a socket incompatible with the functionality required.
  500. /// </summary>
  501. public class InvalidSocketException : ArgumentException
  502. {
  503. /// <summary>
  504. /// Generates a new invalid socket exception
  505. /// </summary>
  506. /// <param name="message">The exception cause</param>
  507. public InvalidSocketException(String message)
  508. : base(message)
  509. {
  510. }
  511. /// <summary>
  512. /// Throws an <see cref="InvalidSocketException" /> if a pin number is not in the specified range.
  513. /// </summary>
  514. /// <param name="pin">The pin number to test.</param>
  515. /// <param name="from">The lowest valid pin number.</param>
  516. /// <param name="to">The highest valid pin number.</param>
  517. /// <param name="iface">The requesting interface.</param>
  518. /// <param name="module">The requesting module.</param>
  519. /// <exception cref="InvalidSocketException">The <paramref name="pin" /> is out of the range specified by <paramref name="from" /> and <paramref name="to" />.</exception>
  520. /// <remarks>
  521. /// This method helps lowering the footprint and should be called when implementing a socket interface.
  522. /// </remarks>
  523. [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
  524. public static void ThrowIfOutOfRange(Socket.Pin pin, Socket.Pin from, Socket.Pin to, string iface, Module module)
  525. {
  526. if (pin >= from && pin <= to)
  527. return;
  528. string message = "Cannot use " + iface + " interface on pin " + pin + " - pin must be in range " + from + " to " + to + ".";
  529. if (module != null)
  530. message = "Module " + module + ": ";
  531. throw new InvalidSocketException(message);
  532. }
  533. /// <summary>
  534. /// Returns an <see cref="InvalidSocketException" /> with functionality error message.
  535. /// </summary>
  536. /// <param name="socket">The socket that has the error.</param>
  537. /// <param name="iface">The interface that is causing the error.</param>
  538. /// <returns>An <see cref="InvalidSocketException" /> with functionality error message.</returns>
  539. /// <remarks>
  540. /// This method helps lowering the footprint and should be called when implementing a socket interface.
  541. /// </remarks>
  542. [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
  543. public static InvalidSocketException FunctionalityException(Socket socket, string iface)
  544. {
  545. return new InvalidSocketException("Socket " + socket + " has an error with its " + iface + " functionality. Please try a different socket.");
  546. }
  547. /// <summary>
  548. /// Generates a new invalid socket exception
  549. /// </summary>
  550. /// <param name="message">The exception cause</param>
  551. /// <param name="e">The underlying exception</param>
  552. public InvalidSocketException(String message, Exception e)
  553. : base(message, e)
  554. {
  555. }
  556. }
  557. /// <summary>
  558. /// This exception is thrown when a socket which is already registered with GadgeteerCore is then modified.
  559. /// </summary>
  560. public class SocketImmutableAfterRegistrationException : InvalidOperationException
  561. {
  562. internal SocketImmutableAfterRegistrationException()
  563. : base("Socket data is immutable after socket is registered.")
  564. { }
  565. }
  566. /// <summary>
  567. /// A CPU pin which has no number, and for which reservation does not need to be tracked.
  568. /// </summary>
  569. public static readonly Cpu.Pin UnnumberedPin = (Cpu.Pin)int.MinValue;
  570. /// <summary>
  571. /// An unspecified CPU pin (e.g. for a socket which does not use this pin).
  572. /// </summary>
  573. public static readonly Cpu.Pin UnspecifiedPin = Cpu.Pin.GPIO_NONE;
  574. /// <summary>
  575. /// This static class contains interfaces used by mainboards to provide functionalities on sockets to Gadgeteer.
  576. /// End users do not need to use this class directly and should normally use GTM.Modules to access functionality.
  577. /// Module developers do not need to use this class directly and should normally use GT.Socket and GT.Interfaces to access the required functionality.
  578. /// </summary>
  579. public static partial class SocketInterfaces
  580. {
  581. /// <summary>
  582. /// Provides access to a socket's analog output functionality.
  583. /// </summary>
  584. public interface AnalogOutput
  585. {
  586. /// <summary>
  587. /// Specifies the minimum voltage that this analog output supports.
  588. /// </summary>
  589. double MinOutputVoltage { get; }
  590. /// <summary>
  591. /// Specifies the maximum voltage that this analog output supports.
  592. /// </summary>
  593. double MaxOutputVoltage { get; }
  594. /// <summary>
  595. /// Sets the voltage output by this analog output.
  596. /// </summary>
  597. /// <param name="value">The voltage to output</param>
  598. void SetVoltage(double value);
  599. /// <summary>
  600. /// A property to control whether the analog output functionality on this socket is active or not.
  601. /// </summary>
  602. bool Active { get; set; }
  603. }
  604. }
  605. }
  606. }