PageRenderTime 57ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/Main/GadgeteerCore/Gadgeteer42/Socket.SocketInterfaces.cs

#
C# | 730 lines | 297 code | 53 blank | 380 comment | 76 complexity | 15726af78a7dc8854c35888ab41d3bea MD5 | raw file
  1. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  4. using Gadgeteer.Interfaces;
  5. using Gadgeteer.Modules;
  6. using Microsoft.SPOT;
  7. using Microsoft.SPOT.Hardware;
  8. using System;
  9. namespace Gadgeteer
  10. {
  11. partial class Socket
  12. {
  13. /// <summary>
  14. /// This static class contains interfaces used by mainboards to provide functionalities on sockets to Gadgeteer.
  15. /// End users do not need to use this class directly and should normally use GTM.Modules to access functionality.
  16. /// Module developers do not need to use this class directly and should normally use GT.Socket and GT.Interfaces to access the required functionality.
  17. /// </summary>
  18. public static partial class SocketInterfaces
  19. {
  20. /// <summary>
  21. /// Creates a new <see cref="Socket"/> object specifying the socket number.
  22. /// </summary>
  23. /// <remarks>
  24. /// This should be used by the mainboard's constructor to create socket instances,
  25. /// which should then configure the socket properties as appropriate, and then call <see cref="RegisterSocket"/>
  26. /// NB the socket name is fixed to be the same as the socket number.
  27. /// </remarks>
  28. /// <param name="socketNumber">The mainboard socket number</param>
  29. public static Socket CreateNumberedSocket(int socketNumber)
  30. {
  31. return new Socket(socketNumber, socketNumber.ToString());
  32. }
  33. /// <summary>
  34. /// Creates a new <see cref="Socket"/> object specifying the socket name.
  35. /// </summary>
  36. /// <remarks>
  37. /// This should be used by module constructors to create socket instances if they provide sockets to other modules.
  38. /// The module constructor should then configure the socket properties as appropriate, and then call <see cref="RegisterSocket"/>
  39. /// A socketNumber is auto-assigned.
  40. /// </remarks>
  41. /// <param name="name">The socket's name</param>
  42. public static Socket CreateUnnumberedSocket(String name)
  43. {
  44. int socketNumber;
  45. lock (Socket._sockets)
  46. {
  47. while (Socket.GetSocket(autoSocketNumber, false, null, null) != null) autoSocketNumber--;
  48. socketNumber = autoSocketNumber;
  49. autoSocketNumber--;
  50. }
  51. return new Socket(socketNumber, name);
  52. }
  53. private static int autoSocketNumber = -10;
  54. private static bool DoRegistrationChecks = true;
  55. private static void SocketRegistrationError(Socket socket, string message)
  56. {
  57. Debug.Print("Warning: socket " + socket + " is not compliant with Gadgeteer : " + message);
  58. }
  59. private static void TestPinsPresent(Socket socket, int[] pins, char type)
  60. {
  61. foreach (int pin in pins)
  62. {
  63. if (socket.CpuPins[pin] == Socket.UnspecifiedPin) SocketRegistrationError(socket, "Cpu pin " + pin + " must be specified for socket of type " + type);
  64. }
  65. }
  66. /// <summary>
  67. /// Registers a socket. Should be used by mainboards and socket-providing modules during initialization.
  68. /// </summary>
  69. /// <param name="socket">The socket to register</param>
  70. public static void RegisterSocket(Socket socket)
  71. {
  72. if (DoRegistrationChecks)
  73. {
  74. if (socket.CpuPins == null || socket.CpuPins.Length != 11) SocketRegistrationError(socket, "CpuPins array must be of length 11");
  75. if (socket.SupportedTypes == null || socket.SupportedTypes.Length == 0) SocketRegistrationError(socket, "SupportedTypes list is null/empty");
  76. foreach (char type in socket.SupportedTypes)
  77. {
  78. switch (type)
  79. {
  80. case 'A':
  81. TestPinsPresent(socket, new int[] { 3, 4, 5, 6 }, type);
  82. if (socket.AnalogInputIndirector == null)
  83. {
  84. if (socket.AnalogInput3 == Cpu.AnalogChannel.ANALOG_NONE || socket.AnalogInput4 == Cpu.AnalogChannel.ANALOG_NONE || socket.AnalogInput5 == Cpu.AnalogChannel.ANALOG_NONE) SocketRegistrationError(socket, "Socket of type A must support analog input functionality on pins 3, 4 and 5");
  85. if (socket.AnalogInputScale == double.MinValue || socket.AnalogInputOffset == double.MinValue || socket.AnalogInputPrecisionInBits == int.MinValue) SocketRegistrationError(socket, "Socket of type A must provide analog input scale/offset through calling SocketInterfaces.SetAnalogInputFactors");
  86. }
  87. break;
  88. case 'C':
  89. TestPinsPresent(socket, new int[] { 3, 4, 5, 6 }, type);
  90. break;
  91. case 'D':
  92. TestPinsPresent(socket, new int[] { 3, 6, 7 }, type);
  93. break;
  94. case 'E':
  95. TestPinsPresent(socket, new int[] { 6, 7, 8, 9 }, type);
  96. break;
  97. case 'F':
  98. TestPinsPresent(socket, new int[] { 3, 4, 5, 6, 7, 8, 9 }, type);
  99. break;
  100. case 'H':
  101. TestPinsPresent(socket, new int[] { 3 }, type);
  102. break;
  103. case 'I':
  104. TestPinsPresent(socket, new int[] { 3, 6, 8, 9 }, type);
  105. break;
  106. case 'K':
  107. TestPinsPresent(socket, new int[] { 3, 4, 5, 6, 7 }, type);
  108. if (socket.SerialIndirector == null)
  109. {
  110. if (socket.SerialPortName == null) SocketRegistrationError(socket, "Socket of type K must specify serial port name");
  111. }
  112. break;
  113. case 'O':
  114. TestPinsPresent(socket, new int[] { 3, 4, 5 }, type);
  115. if (socket.AnalogOutput == null) SocketRegistrationError(socket, "Socket of type O must support analog output functionality");
  116. break;
  117. case 'P':
  118. TestPinsPresent(socket, new int[] { 3, 6, 7, 8, 9 }, type);
  119. if (socket.PwmOutputIndirector == null)
  120. {
  121. if (socket.PWM7 == Cpu.PWMChannel.PWM_NONE || socket.PWM8 == Cpu.PWMChannel.PWM_NONE || socket.PWM9 == Cpu.PWMChannel.PWM_NONE) SocketRegistrationError(socket, "Socket of type P must support PWM functionality");
  122. }
  123. break;
  124. case 'S':
  125. TestPinsPresent(socket, new int[] { 3, 4, 5, 6, 7, 8, 9 }, type);
  126. if (socket.SpiIndirector == null)
  127. {
  128. if (socket.SPIModule == Socket.SocketInterfaces.SPIMissing) SocketRegistrationError(socket, "Socket of type S must specify SPI module number");
  129. }
  130. break;
  131. case 'T':
  132. TestPinsPresent(socket, new int[] { 4, 5, 6, 7 }, type);
  133. break;
  134. case 'U':
  135. TestPinsPresent(socket, new int[] { 3, 4, 5, 6 }, type);
  136. if (socket.SerialIndirector == null)
  137. {
  138. if (socket.SerialPortName == null) SocketRegistrationError(socket, "Socket of type U must specify serial port name");
  139. }
  140. break;
  141. case 'R':
  142. TestPinsPresent(socket, new int[] { 3, 4, 5, 6, 7, 8, 9 }, type);
  143. break;
  144. case 'G':
  145. TestPinsPresent(socket, new int[] { 3, 4, 5, 6, 7, 8, 9 }, type);
  146. break;
  147. case 'B':
  148. TestPinsPresent(socket, new int[] { 3, 4, 5, 6, 7, 8, 9 }, type);
  149. break;
  150. case 'X':
  151. TestPinsPresent(socket, new int[] { 3, 4, 5 }, type);
  152. break;
  153. case 'Y':
  154. TestPinsPresent(socket, new int[] { 3, 4, 5, 6, 7, 8, 9 }, type);
  155. break;
  156. case 'Z':
  157. // manufacturer specific socket - no tests
  158. break;
  159. case '*':
  160. // * is a special case - daisylink modules don't actually declare their new socket in code, instead reusing the mainboard socket number
  161. // so we don't need the below, but it doesnt hurt to leave it in
  162. TestPinsPresent(socket, new int[] { 3, 4, 5 }, type);
  163. break;
  164. default:
  165. SocketRegistrationError(socket, "Socket type '" + type + "' is not supported by Gadgeteer");
  166. break;
  167. }
  168. }
  169. }
  170. lock (Socket._sockets)
  171. {
  172. if (Socket.GetSocket(socket.SocketNumber, false, null, null) != null) throw new Socket.InvalidSocketException("Cannot register socket - socket number " + socket.SocketNumber + " already used");
  173. Socket._sockets.Add(socket);
  174. socket._registered = true;
  175. }
  176. }
  177. #region Interfaces
  178. /// <summary>
  179. /// Provides the analog input functionality.
  180. /// </summary>
  181. public abstract class AnalogInput : IDisposable
  182. {
  183. /// <summary>
  184. /// Gets or sets the active state of the analog input.
  185. /// </summary>
  186. public abstract bool IsActive { get; set; }
  187. /// <summary>
  188. /// Reads the current analog input value as a voltage between 0 and 3.3V.
  189. /// </summary>
  190. /// <returns>The current analog value in volts.</returns>
  191. public abstract double ReadVoltage();
  192. /// <summary>
  193. /// Reads the current analog input value as a proportion from 0.0 to 1.0 of the maximum value (3.3V).
  194. /// </summary>
  195. /// <returns>The analog input value from 0.0-1.0</returns>
  196. public virtual double ReadProportion()
  197. {
  198. return ReadVoltage() / 3.3;
  199. }
  200. /// <summary>
  201. /// Releases all resources used by the interface.
  202. /// </summary>
  203. public virtual void Dispose() { }
  204. }
  205. /// <summary>
  206. /// Provides the digital input functionality.
  207. /// </summary>
  208. public abstract class DigitalInput : IDisposable
  209. {
  210. /// <summary>
  211. /// Reads a Boolean value at the interface port input.
  212. /// </summary>
  213. /// <returns>A Boolean value that represents the current value of the port, either 0 or 1.</returns>
  214. public abstract bool Read();
  215. /// <summary>
  216. /// Releases all resources used by the interface.
  217. /// </summary>
  218. public virtual void Dispose() { }
  219. }
  220. /// <summary>
  221. /// Provides the digital input and output functionality.
  222. /// </summary>
  223. public abstract class DigitalIO : IDisposable
  224. {
  225. /// <summary>
  226. /// Gets or sets the mode for the digital input/output interface.
  227. /// </summary>
  228. /// <value>
  229. /// <list type="bullet">
  230. /// <item><see cref="IOMode.Input" /> if the interface is currently set for input operations.</item>
  231. /// <item><see cref="IOMode.Output" /> if the interface is currently set for ouput operations.</item>
  232. /// </list>
  233. /// </value>
  234. public abstract IOMode Mode { get; set; }
  235. /// <summary>
  236. /// Sets the interface to <see cref="IOMode.Output" /> and writes the specified value.
  237. /// </summary>
  238. /// <param name="state"></param>
  239. public abstract void Write(bool state);
  240. /// <summary>
  241. /// Sets the interface to <see cref="IOMode.Input" /> and reads a value.
  242. /// </summary>
  243. /// <returns>A Boolean value read from the interface.</returns>
  244. public abstract bool Read();
  245. /// <summary>
  246. /// Releases all resources used by the interface.
  247. /// </summary>
  248. public virtual void Dispose() { }
  249. }
  250. /// <summary>
  251. /// Provides the digital output functionality.
  252. /// </summary>
  253. public abstract class DigitalOutput : IDisposable
  254. {
  255. /// <summary>
  256. /// Writes a value to the interface port output.
  257. /// </summary>
  258. /// <param name="state">The value to be written to the port output.</param>
  259. public abstract void Write(bool state);
  260. /// <summary>
  261. /// Reads a Boolean value at the interface port input.
  262. /// </summary>
  263. /// <returns>The current value of the port (either 0 or 1).</returns>
  264. public abstract bool Read();
  265. /// <summary>
  266. /// Releases all resources used by the interface.
  267. /// </summary>
  268. public virtual void Dispose() { }
  269. }
  270. /// <summary>
  271. /// Provides the I2C functionality.
  272. /// </summary>
  273. public abstract class I2CBus : IDisposable
  274. {
  275. /// <summary>
  276. /// Gets or sets the address of the <see cref="I2CBus" /> device.
  277. /// </summary>
  278. public abstract ushort Address { get; set; }
  279. /// <summary>
  280. /// Performs a series of I2C transactions.
  281. /// </summary>
  282. /// <param name="transactions">The list of transactions to perform.</param>
  283. /// <param name="millisecondsTimeout">The amount of time, in milliseconds, that the system will wait before resuming execution of the transaction.</param>
  284. /// <returns>The number of bytes of data transferred in the transaction.</returns>
  285. public abstract int Execute(I2CDevice.I2CTransaction[] transactions, int millisecondsTimeout);
  286. /// <summary>
  287. /// Writes an array of bytes to the I2C device.
  288. /// </summary>
  289. /// <param name="writeBuffer">The array of bytes that will be sent to the I2C device.</param>
  290. /// <param name="millisecondsTimeout">The amount of time, in milliseconds, that the system will wait before resuming execution of the transaction.</param>
  291. /// <returns>The number of bytes of data transferred in the transaction.</returns>
  292. public int Write(byte[] writeBuffer, int millisecondsTimeout)
  293. {
  294. if (writeBuffer == null)
  295. return 0;
  296. var transactions = new I2CDevice.I2CTransaction[] { I2CDevice.CreateWriteTransaction(writeBuffer) };
  297. return Execute(transactions, millisecondsTimeout);
  298. }
  299. /// <summary>
  300. /// Reads an array of bytes from the device into a specified read buffer.
  301. /// </summary>
  302. /// <param name="readBuffer">The array of bytes that will contain the data read from the I2C device.</param>
  303. /// <param name="millisecondsTimeout">The amount of time, in milliseconds, that the system will wait before resuming execution of the transaction.</param>
  304. /// <returns>The number of bytes of data transferred in the transaction.</returns>
  305. public int Read(byte[] readBuffer, int millisecondsTimeout)
  306. {
  307. if (readBuffer == null)
  308. return 0;
  309. var transactions = new I2CDevice.I2CTransaction[] { I2CDevice.CreateReadTransaction(readBuffer) };
  310. return Execute(transactions, millisecondsTimeout);
  311. }
  312. /// <summary>
  313. /// Writes an array of bytes to the I2C device, and reads an array of bytes from the device into a specified read buffer.
  314. /// </summary>
  315. /// <param name="writeBuffer">The array of bytes that will be sent to the I2C device.</param>
  316. /// <param name="readBuffer">The array of bytes that will contain the data read from the I2C device.</param>
  317. /// <param name="millisecondsTimeout">The amount of time, in milliseconds, that the system will wait before resuming execution of the transaction.</param>
  318. /// <returns>The number of bytes of data transferred in the transaction.</returns>
  319. public int WriteRead(byte[] writeBuffer, byte[] readBuffer, int millisecondsTimeout)
  320. {
  321. if (writeBuffer == null)
  322. return Read(readBuffer, millisecondsTimeout);
  323. if (readBuffer == null)
  324. return Write(writeBuffer, millisecondsTimeout);
  325. var transactions = new I2CDevice.I2CTransaction[] { I2CDevice.CreateWriteTransaction(writeBuffer), I2CDevice.CreateReadTransaction(readBuffer) };
  326. return Execute(transactions, millisecondsTimeout);
  327. }
  328. /// <summary>
  329. /// Releases all resources used by the interface.
  330. /// </summary>
  331. public virtual void Dispose() { }
  332. }
  333. /// <summary>
  334. /// Provides the interrupt input functionality.
  335. /// </summary>
  336. public abstract class InterruptInput : IDisposable
  337. {
  338. /// <summary>
  339. /// Reads a Boolean value at the InterruptInput interface port input.
  340. /// </summary>
  341. /// <returns>A Boolean value that indicates the current value of the port as either 0 or 1).</returns>
  342. public abstract bool Read();
  343. /// <summary>
  344. /// Called when the first handler is subscribed to the <see cref="Interrupt" /> event.
  345. /// </summary>
  346. protected abstract void OnInterruptFirstSubscribed();
  347. /// <summary>
  348. /// Called when the last handler is unsubsrcibed from the <see cref="Interrupt" /> event.
  349. /// </summary>
  350. protected abstract void OnInterruptLastUnsubscribed();
  351. /// <summary>
  352. /// Raises the <see cref="Interrupt" /> event.
  353. /// </summary>
  354. /// <param name="value"><b>true</b> if the the value received from the interrupt is greater than zero; otherwise, <b>false</b>.</param>
  355. protected void RaiseInterrupt(bool value)
  356. {
  357. if (this.interrupt != null)
  358. {
  359. this.interrupt(this, value);
  360. }
  361. }
  362. private InterruptEventHandler interrupt;
  363. /// <summary>
  364. /// Raised when the <see cref="InterruptInput" /> interface detects an interrupt.
  365. /// </summary>
  366. public event InterruptEventHandler Interrupt
  367. {
  368. add
  369. {
  370. if (this.interrupt == null)
  371. {
  372. OnInterruptFirstSubscribed();
  373. }
  374. this.interrupt += value;
  375. }
  376. remove
  377. {
  378. this.interrupt -= value;
  379. if (this.interrupt == null)
  380. {
  381. this.OnInterruptLastUnsubscribed();
  382. }
  383. }
  384. }
  385. /// <summary>
  386. /// Releases all resources used by the interface.
  387. /// </summary>
  388. public virtual void Dispose() { }
  389. }
  390. /// <summary>
  391. /// Provides the PWM output functionality.
  392. /// </summary>
  393. public abstract class PwmOutput : IDisposable
  394. {
  395. /// <summary>
  396. /// Gets or sets a Boolean value that indicates whether the PWM interface is active, <b>true</b> if active otherwise <b>false</b>.
  397. /// </summary>
  398. public abstract bool IsActive { get; set; }
  399. /// <summary>
  400. /// Sets the frequency and duty cycle of the <see cref="PwmOutput" /> interface and starts the PWM signal.
  401. /// </summary>
  402. /// <param name="frequency">Required frequency in Hertz.</param>
  403. /// <param name="dutyCycle">Duty cycle from 0-1.</param>
  404. public abstract void Set(double frequency, double dutyCycle);
  405. /// <summary>
  406. /// Sets the period and high time of the <see cref="PWMOutput" /> interface and starts the PWM signal.
  407. /// </summary>
  408. /// <param name="period">Period of the signal in units specified <paramref name="factor" />.</param>
  409. /// <param name="highTime">High time of the signal in units specified by <paramref name="factor" />.</param>
  410. /// <param name="factor">The units of <paramref name="period" /> and <paramref name="highTime" />.</param>
  411. public abstract void Set(uint period, uint highTime, PwmScaleFactor factor);
  412. /// <summary>
  413. /// Releases all resources used by the interface.
  414. /// </summary>
  415. public virtual void Dispose() { }
  416. }
  417. /// <summary>
  418. /// Provides the SPI functionality.
  419. /// </summary>
  420. public abstract class Spi : IDisposable
  421. {
  422. /// <summary>
  423. /// Gets or sets the configuration of this <see cref="Spi" /> interface.
  424. /// </summary>
  425. public abstract SpiConfiguration Configuration { get; set; }
  426. /// <summary>
  427. /// Writes an array of bytes to the interface, and reads an array of bytes from the interface into a specified location in the read buffer.
  428. /// </summary>
  429. /// <param name="writeBuffer">The buffer whose contents will be written to the interface.</param>
  430. /// <param name="writeOffset">The offset in <paramref name="writeBuffer" /> to start write data from.</param>
  431. /// <param name="writeLength">The number of elements in <paramref name="writeBuffer" /> to write.</param>
  432. /// <param name="readBuffer">The buffer that will store the data that is read from the interface.</param>
  433. /// <param name="readOffset">The offset in <paramref name="readBuffer" /> to start read data from.</param>
  434. /// <param name="readLength">The number of elements in <paramref name="readBuffer" /> to fill.</param>
  435. /// <param name="startReadOffset">The offset in time, measured in transacted elements from <paramref name="writeBuffer" />, when to start reading back data into <paramref name="readBuffer" />.</param>
  436. public abstract void WriteRead(byte[] writeBuffer, int writeOffset, int writeLength, byte[] readBuffer, int readOffset, int readLength, int startReadOffset);
  437. /// <summary>
  438. /// Writes an array of unsigned values to the interface, and reads an array of unsigned values from the interface into a specified location in the read buffer.
  439. /// </summary>
  440. /// <param name="writeBuffer">The buffer whose contents will be written to the interface.</param>
  441. /// <param name="writeOffset">The offset in <paramref name="writeBuffer" /> to start write data from.</param>
  442. /// <param name="writeLength">The number of elements in <paramref name="writeBuffer" /> to write.</param>
  443. /// <param name="readBuffer">The buffer that will store the data that is read from the interface.</param>
  444. /// <param name="readOffset">The offset in <paramref name="readBuffer" /> to start read data from.</param>
  445. /// <param name="readLength">The number of elements in <paramref name="readBuffer" /> to fill.</param>
  446. /// <param name="startReadOffset">The offset in time, measured in transacted elements from <paramref name="writeBuffer" />, when to start reading back data into <paramref name="readBuffer" />.</param>
  447. public abstract void WriteRead(ushort[] writeBuffer, int writeOffset, int writeLength, ushort[] readBuffer, int readOffset, int readLength, int startReadOffset);
  448. /// <summary>
  449. /// Writes an array of bytes to the SPI interface, and reads an array of bytes from the interface into a
  450. /// specified location in the read buffer.
  451. /// </summary>
  452. /// <param name="writeBuffer">The buffer that will write to the interface.</param>
  453. /// <param name="readBuffer">The buffer that will store the data that is read from the interface.</param>
  454. /// <param name="readOffset">
  455. /// The offset in time, measured in transacted elements from <paramref name="writeBuffer"/>,
  456. /// to start reading data into.<paramref name="readBuffer"/>.
  457. /// </param>
  458. public void WriteRead(byte[] writeBuffer, byte[] readBuffer, int readOffset)
  459. {
  460. WriteRead(writeBuffer, 0, writeBuffer == null ? 0 : writeBuffer.Length, readBuffer, 0, readBuffer == null ? 0 : readBuffer.Length, readOffset);
  461. }
  462. /// <summary>
  463. /// Writes an array of bytes to the SPI interface, and reads an array of
  464. /// bytes from the interface into a specified location in the read buffer.
  465. /// </summary>
  466. /// <param name="writeBuffer">The buffer that will write to the interface.</param>
  467. /// <param name="readBuffer">The buffer that will store the data that is read from the interface.</param>
  468. /// <param name="readOffset">
  469. /// The offset in time, measured in transacted elements from <paramref name="writeBuffer"/>,
  470. /// to start reading data into <paramref name="readBuffer"/>.
  471. /// </param>
  472. public void WriteRead(ushort[] writeBuffer, ushort[] readBuffer, int readOffset)
  473. {
  474. WriteRead(writeBuffer, 0, writeBuffer == null ? 0 : writeBuffer.Length, readBuffer, 0, readBuffer == null ? 0 : readBuffer.Length, readOffset);
  475. }
  476. /// <summary>
  477. /// Writes an array of bytes to the interface, and reads an array of bytes from the interface.
  478. /// </summary>
  479. /// <param name="writeBuffer">The buffer that will write to the interface.</param>
  480. /// <param name="readBuffer">The buffer that will store the data that is read from the interface.</param>
  481. public void WriteRead(byte[] writeBuffer, byte[] readBuffer)
  482. {
  483. WriteRead(writeBuffer, 0, writeBuffer == null ? 0 : writeBuffer.Length, readBuffer, 0, readBuffer == null ? 0 : readBuffer.Length, 0);
  484. }
  485. /// <summary>
  486. /// Writes an array of unsigned values to the SPI interface, and reads an array of unsigned values from the interface.
  487. /// </summary>
  488. /// <param name="writeBuffer">The buffer that will write to the interface.</param>
  489. /// <param name="readBuffer">The buffer that will store the data that is read from the interface.</param>
  490. public void WriteRead(ushort[] writeBuffer, ushort[] readBuffer)
  491. {
  492. WriteRead(writeBuffer, 0, writeBuffer == null ? 0 : writeBuffer.Length, readBuffer, 0, readBuffer == null ? 0 : readBuffer.Length, 0);
  493. }
  494. /// <summary>
  495. /// Writes an array of bytes to the SPI interface. This is a synchronous call; it will not return until the bytes are written out.
  496. /// </summary>
  497. /// <param name="writeBuffer">The buffer that will write to the interface.</param>
  498. public void Write(params byte[] writeBuffer)
  499. {
  500. WriteRead(writeBuffer, 0, writeBuffer == null ? 0 : writeBuffer.Length, null, 0, 0, 0);
  501. }
  502. /// <summary>
  503. /// Writes an array of unsigned values to the SPI interface. This is a synchronous call; it will not return until the bytes are written out.
  504. /// </summary>
  505. /// <param name="writeBuffer">The buffer that will write to the interface.</param>
  506. public void Write(params ushort[] writeBuffer)
  507. {
  508. WriteRead(writeBuffer, 0, writeBuffer == null ? 0 : writeBuffer.Length, null, 0, 0, 0);
  509. }
  510. /// <summary>
  511. /// Releases all resources used by the interface.
  512. /// </summary>
  513. public virtual void Dispose() { }
  514. }
  515. #endregion
  516. #region Delegates
  517. /// <summary>
  518. /// Represents the method that provides indirected <see cref="AnalogInput" /> interface for a socket.
  519. /// </summary>
  520. /// <param name="socket">The socket.</param>
  521. /// <param name="pin">The analog input pin to use.</param>
  522. /// <param name="module">The module using the socket, which can be null if unspecified.</param>
  523. /// <returns>An <see cref="AnalogInput" /> interface.</returns>
  524. public delegate AnalogInput AnalogInputIndirector(Socket socket, Socket.Pin pin, Module module);
  525. /// <summary>
  526. /// Represents the method that provides indirected <see cref="AnalogOutput" /> interface for a socket.
  527. /// </summary>
  528. /// <param name="socket">The analog output capable socket.</param>
  529. /// <param name="pin">The pin to assign to the analog output.</param>
  530. /// <param name="module">The module using this analog output interface, which can be null if unspecified.</param>
  531. /// <returns>An <see cref="AnalogOutput" /> interface.</returns>
  532. public delegate AnalogOutput AnalogOutputIndirector(Socket socket, Socket.Pin pin, Module module);
  533. /// <summary>
  534. /// Represents the method that provides indirected <see cref="DigitalInput" /> interface for a socket.
  535. /// </summary>
  536. /// <param name="socket">The socket for the digital input interface.</param>
  537. /// <param name="pin">The pin used by the digital input interface.</param>
  538. /// <param name="glitchFilterMode">
  539. /// A value from the <see cref="GlitchFilterMode" /> enumeration that specifies
  540. /// whether to enable the glitch filter on this digital input interface.
  541. /// </param>
  542. /// <param name="resistorMode">
  543. /// A value from the <see cref="ResistorMode" /> enumeration that establishes a default state for the digital input interface. N.B. .NET Gadgeteer mainboards are only required to support ResistorMode.PullUp on interruptable GPIOs and are never required to support ResistorMode.PullDown; consider putting the resistor on the module itself.
  544. /// </param>
  545. /// <param name="module">The module using this interface, which can be null if unspecified.</param>
  546. /// <returns>An <see cref="DigitalInput" /> interface.</returns>
  547. public delegate DigitalInput DigitalInputIndirector(Socket socket, Socket.Pin pin, GlitchFilterMode glitchFilterMode, ResistorMode resistorMode, Module module);
  548. /// <summary>
  549. /// Represents the method that provides indirected <see cref="DigitalIO" /> interface for a socket.
  550. /// </summary>
  551. /// <param name="socket">The socket for the digital input/output interface.</param>
  552. /// <param name="pin">The pin used by the digital input/output interface.</param>
  553. /// <param name="initialState">
  554. /// The initial state to set on the digital input/output interface port.
  555. /// This value becomes effective as soon as the port is enabled as an output port.
  556. /// </param>
  557. /// <param name="glitchFilterMode">
  558. /// A value from the <see cref="GlitchFilterMode" /> enumeration that specifies
  559. /// whether to enable the glitch filter on this digital input/output interface.
  560. /// </param>
  561. /// <param name="resistorMode">
  562. /// A value from the <see cref="ResistorMode" /> enumeration that establishes a default state for the digital input/output interface. N.B. .NET Gadgeteer mainboards are only required to support ResistorMode.PullUp on interruptable GPIOs and are never required to support ResistorMode.PullDown; consider putting the resistor on the module itself.
  563. /// </param>
  564. /// <param name="module">The module using this interface, which can be null if unspecified.</param>
  565. /// <returns>An <see cref="DigitalIO" /> interface.</returns>
  566. public delegate DigitalIO DigitalIOIndirector(Socket socket, Socket.Pin pin, bool initialState, GlitchFilterMode glitchFilterMode, ResistorMode resistorMode, Module module);
  567. /// <summary>
  568. /// Represents the method that provides indirected <see cref="DigitalOutput" /> interface for a socket.
  569. /// </summary>
  570. /// <param name="socket">The socket for the digital output interface.</param>
  571. /// <param name="pin">The pin used by the digital output interface.</param>
  572. /// <param name="initialState">The initial state to place on the digital output interface port.</param>
  573. /// <param name="module">The module using this interface (which can be null if unspecified).</param>
  574. /// <returns>An <see cref="DigitalOutput" /> interface.</returns>
  575. public delegate DigitalOutput DigitalOutputIndirector(Socket socket, Socket.Pin pin, bool initialState, Module module);
  576. /// <summary>
  577. /// Represents the method that provides indirected <see cref="I2CBus" /> interface for a socket.
  578. /// </summary>
  579. /// <param name="address">The address for the I2C device.</param>
  580. /// <param name="clockRateKhz">The clock rate, in kHz, used when communicating with the I2C device.</param>
  581. /// <param name="socket">The socket for this I2C device interface.</param>
  582. /// <param name="module">The module using this I2C interface, which can be null if unspecified.</param>
  583. /// <returns>An <see cref="I2CBus" /> interface.</returns>
  584. public delegate I2CBus I2CBusIndirector(Socket socket, ushort address, int clockRateKhz, Module module);
  585. /// <summary>
  586. /// Represents the method that provides indirected <see cref="InterruptInput" /> interface for a socket.
  587. /// </summary>
  588. /// <param name="socket">The socket for the interrupt input interface.</param>
  589. /// <param name="pin">The pin used by the interrupt input interface.</param>
  590. /// <param name="glitchFilterMode">
  591. /// A value from the <see cref="GlitchFilterMode" /> enumeration that specifies
  592. /// whether to enable the glitch filter on this interrupt input interface.
  593. /// </param>
  594. /// <param name="resistorMode">
  595. /// A value from the <see cref="ResistorMode" /> enumeration that establishes a default state for the interrupt input interface. N.B. .NET Gadgeteer mainboards are only required to support ResistorMode.PullUp on interruptable GPIOs and are never required to support ResistorMode.PullDown; consider putting the resistor on the module itself.
  596. /// </param>
  597. /// <param name="interruptMode">
  598. /// A value from the <see cref="InterruptMode" /> enumeration that establishes the requisite conditions
  599. /// for the interface port to generate an interrupt.
  600. /// </param>
  601. /// <param name="module">The module using this interrupt input interface, which can be null if unspecified.</param>
  602. /// <returns>An <see cref="InterruptInput" /> interface.</returns>
  603. public delegate InterruptInput InterruptInputIndirector(Socket socket, Socket.Pin pin, GlitchFilterMode glitchFilterMode, ResistorMode resistorMode, InterruptMode interruptMode, Module module);
  604. /// <summary>
  605. /// Represents the method that provides indirected <see cref="PwmOutput" /> interface for a socket.
  606. /// </summary>
  607. /// <param name="socket">The socket that supports pulse width modulation (PWM) output.</param>
  608. /// <param name="pin">The pin on the socket that supports PWM.</param>
  609. /// <param name="invert">Whether to invert the output voltage.</param>
  610. /// <param name="module">The module using this PWM output interface, which can be null if unspecified.</param>
  611. /// <returns>An <see cref="PwmOutput" /> interface.</returns>
  612. public delegate PwmOutput PwmOutputIndirector(Socket socket, Socket.Pin pin, bool invert, Module module);
  613. /// <summary>
  614. /// Represents the method that provides indirected <see cref="Serial" /> interface for a socket.
  615. /// </summary>
  616. /// <param name="baudRate">The baud rate for the serial port.</param>
  617. /// <param name="parity">A value from the <see cref="SerialParity" /> enumeration that specifies
  618. /// the parity for the port.</param>
  619. /// <param name="stopBits">A value from the <see cref="SerialStopBits" /> enumeration that specifies
  620. /// the stop bits for the port.</param>
  621. /// <param name="dataBits">The number of data bits.</param>
  622. /// <param name="socket">The socket for this serial interface.</param>
  623. /// <param name="hardwareFlowControlRequirement">Specifies whether the module must use hardware flow control, will use hardware flow control if available, or does not use hardware flow control.</param>
  624. /// <param name="module">The module using this interface (which can be null if unspecified).</param>
  625. /// <returns>An <see cref="Serial" /> interface.</returns>
  626. public delegate Serial SerialIndirector(Socket socket, int baudRate, SerialParity parity, SerialStopBits stopBits, int dataBits, HardwareFlowControl hardwareFlowControlRequirement, Module module);
  627. /// <summary>
  628. /// Represents the method that provides indirected <see cref="Spi" /> interface for a socket.
  629. /// </summary>
  630. /// <param name="socket">The socket for this SPI interface.</param>
  631. /// <param name="spiConfiguration">The SPI configuration.</param>
  632. /// <param name="sharingMode">The sharing mode.</param>
  633. /// <param name="chipSelectSocket">The chip select socket to use.</param>
  634. /// <param name="chipSelectSocketPin">The chip select pin to use on the chip select socket.</param>
  635. /// <param name="busySocket">The busy socket to use.</param>
  636. /// <param name="busySocketPin">The busy pin to use on the busy socket.</param>
  637. /// <param name="module">The module using this interface (which can be null if unspecified).</param>
  638. /// <returns>An <see cref="Spi" /> interface.</returns>
  639. public delegate Spi SpiIndirector(Socket socket, SpiConfiguration spiConfiguration, SpiSharing sharingMode, Socket chipSelectSocket, Socket.Pin chipSelectSocketPin, Socket busySocket, Socket.Pin busySocketPin, Module module);
  640. #endregion
  641. /// <summary>
  642. /// Set the scale and offset used by <see cref="Microsoft.SPOT.Hardware.AnalogInput.Read"/> to transform the raw value into a voltage between 0 and 3.3V, and the precision in bits.
  643. /// </summary>
  644. /// <param name="scale">The multiplicative scale factor.</param>
  645. /// <param name="offset">The additive offset.</param>
  646. /// <param name="precisionInBits">The number of bits precision by this analog input socket.</param>
  647. /// <param name="socket">The socket being configured.</param>
  648. public static void SetAnalogInputFactors(Socket socket, double scale, double offset, int precisionInBits)
  649. {
  650. socket.AnalogInputScale = scale;
  651. socket.AnalogInputOffset = offset;
  652. socket.AnalogInputPrecisionInBits = precisionInBits;
  653. }
  654. /// <summary>
  655. /// A value indicating that a socket has no associated SPI bus
  656. /// </summary>
  657. public static readonly SPI.SPI_module SPIMissing = (SPI.SPI_module)(-1);
  658. /// <summary>
  659. /// Delegate for mainboards to provide custom native/hardware I2C support.
  660. /// </summary>
  661. /// <param name="socket">The socket.</param>
  662. /// <param name="sda">The socket pin for the SDA signal.</param>
  663. /// <param name="scl">The socket pin for the SCL signal.</param>
  664. /// <param name="address">The address to which to send the result.</param>
  665. /// <param name="write">The data buffer to write.</param>
  666. /// <param name="writeOffset">The offset in the buffer where writing begins (this can be null if no data is to be written).</param>
  667. /// <param name="writeLen">The number of bytes of data to write.</param>
  668. /// <param name="read">The data buffer that data is put into after a read operation (this can be null if no data is to be read).</param>
  669. /// <param name="readOffset">The offset to start writing data after a read operation.</param>
  670. /// <param name="readLen">The amount of data to read.</param>
  671. /// <param name="numWritten">The number of bytes actually written and acknowledged.</param>
  672. /// <param name="numRead">The number of bytes actually read.</param>
  673. /// <returns>Returns true if the whole transaction succeeds, otherwise false.</returns>
  674. public delegate bool NativeI2CWriteReadDelegate(Socket socket, Socket.Pin sda, Socket.Pin scl, byte address, byte[] write, int writeOffset, int writeLen, byte[] read, int readOffset, int readLen, out int numWritten, out int numRead);
  675. }
  676. }
  677. }