PageRenderTime 75ms CodeModel.GetById 13ms app.highlight 52ms RepoModel.GetById 2ms app.codeStats 0ms

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