Ejemplo n.º 1
0
        /// <summary>
        ///     Construct an SPI device attached to a particular module
        /// </summary>
        /// <param name="spiModule">The module this device is attached to</param>
        /// <param name="chipSelect">The chip select pin used by this device</param>
        /// <param name="chipSelectMode">The ChipSelectMode to use with this device</param>
        /// <param name="speedMhz">The speed to operate this device at</param>
        /// <param name="mode">The SpiMode of this device</param>
        public SpiDevice(Spi spiModule, SpiChipSelectPin chipSelect,
                         ChipSelectMode chipSelectMode = ChipSelectMode.SpiActiveLow, double speedMhz = 6,
                         SpiMode mode = SpiMode.Mode00)
        {
            ChipSelectMode = chipSelectMode;
            ChipSelect     = chipSelect;
            _spi           = spiModule;
            Frequency      = speedMhz;
            Mode           = mode;

            _spi.Enabled = true;

            ChipSelect.MakeDigitalPushPullOutAsync();

            // Set the initial chip select state
            if (chipSelectMode == ChipSelectMode.PulseLowAtBeginning ||
                chipSelectMode == ChipSelectMode.PulseLowAtEnd || chipSelectMode == ChipSelectMode.SpiActiveLow)
            {
                ChipSelect.DigitalValue = true;
            }
            else
            {
                ChipSelect.DigitalValue = false;
            }
        }
        /// <summary>
        /// Construct an SPI device attached to a particular module
        /// </summary>
        /// <param name="SpiModule">The module this device is attached to</param>
        /// <param name="ChipSelect">The chip select pin used by this device</param>
        /// <param name="csMode">The ChipSelectMode to use with this device</param>
        /// <param name="SpeedMHz">The speed to operate this device at</param>
        /// <param name="mode">The SpiMode of this device</param>
        public SpiDevice(Spi SpiModule, Pin ChipSelect, ChipSelectMode csMode = ChipSelectMode.SpiActiveLow, double SpeedMHz = 1, SpiMode mode = SpiMode.Mode00)
        {
            this.ChipSelectMode = csMode;
            this.ChipSelect = ChipSelect;
            this.spi = SpiModule;
            this.Frequency = SpeedMHz;
            this.Mode = mode;

            this.ChipSelect.Mode = PinMode.PushPullOutput;

            spi.Enabled = true;
        }
 /// <summary>
 ///     Set up a ChainableShiftRegisterOutput connected to an SPI port.
 /// </summary>
 /// <param name="spiModule">the SPI module to use</param>
 /// <param name="latchPin">The latch pin to use</param>
 /// <param name="numBytes">The number of bytes to write to this device</param>
 /// <param name="mode">The SPI mode to use for all shift registers in this chain</param>
 /// <param name="csMode">The ChipSelectMode to use for all shift registers in this chain</param>
 /// <param name="speedMhz">The speed to use for all shift registers in this chain</param>
 public ChainableShiftRegisterOutput(Spi spiModule, SpiChipSelectPin latchPin, int numBytes = 1,
                                     double speedMhz = 6, SpiMode mode = SpiMode.Mode00, ChipSelectMode csMode = ChipSelectMode.PulseHighAtEnd)
 {
     spiDevice     = new SpiDevice(spiModule, latchPin, csMode, speedMhz, mode);
     this.numBytes = numBytes;
     CurrentValue  = new byte[numBytes];
     lastValues    = new byte[numBytes];
 }
Ejemplo n.º 4
0
        /// <summary>
        ///     Send/receive data
        /// </summary>
        /// <param name="dataToWrite">
        ///     a byte array of the data to send. The length of the transaction is determined by the length of this array.
        /// </param>
        /// <param name="chipSelect">The chip select pin, if any, to use during this transaction.</param>
        /// <param name="chipSelectMode">The chip select mode to use during this transaction (if a CS pin is selected)</param>
        /// <param name="speedMhz">The speed to perform this transaction at.</param>
        /// <param name="burstMode"The burst mode (if any) to use.</param>
        /// <param name="spiMode">The SPI mode to use during this transaction.</param>
        /// <returns>An awaitable byte array with the received data.</returns>
        public async Task <byte[]> SendReceiveAsync(byte[] dataToWrite, SpiChipSelectPin chipSelect = null,
                                                    ChipSelectMode chipSelectMode = ChipSelectMode.SpiActiveLow, double speedMhz = 6,
                                                    SpiBurstMode burstMode        = SpiBurstMode.NoBurst, SpiMode spiMode = SpiMode.Mode00)
        {
            var transactionLength = dataToWrite.Length;
            var returnedData      = new byte[transactionLength];

            if (Enabled != true)
            {
                Utility.Error("SPI module must be enabled before starting transaction", true);
            }

            if (chipSelect != null && chipSelect.SpiModule != this)
            {
                Utility.Error("Chip select pin must belong to this SPI module", true);
            }

            if (speedMhz > 0.8 && speedMhz < 6)
            {
                Debug.WriteLine(
                    "NOTICE: automatically rounding up SPI speed to 6 MHz, due to a possible silicon bug. This bug affects SPI speeds between 0.8 and 6 MHz, so if you need a speed lower than 6 MHz, please set to 0.8 MHz or lower.");

                speedMhz = 6;
            }

            using (await _device.ComsLock.LockAsync().ConfigureAwait(false))
            {
                var spi0Ckr = (int)Math.Round(24.0 / speedMhz - 1);
                if (spi0Ckr > 255.0)
                {
                    spi0Ckr = 255;
                    Debug.WriteLine(
                        "NOTICE: Requested SPI frequency of {0} MHz is below the minimum frequency, and will be clipped to 0.09375 MHz (93.75 kHz).",
                        speedMhz);
                }
                else if (spi0Ckr < 0)
                {
                    spi0Ckr = 0;
                    Debug.WriteLine(
                        "NOTICE: Requested SPI frequency of {0} MHz is above the maximum frequency, and will be clipped to 24 MHz.",
                        speedMhz);
                }

                var actualFrequency = 48.0 / (2.0 * (spi0Ckr + 1.0));

                if (Math.Abs(actualFrequency - speedMhz) > 1)
                {
                    Debug.WriteLine(
                        "NOTICE: SPI module actual frequency of {0} MHz is more than 1 MHz away from the requested frequency of {1} MHz",
                        actualFrequency, speedMhz);
                }

                if (dataToWrite.Length > 255)
                {
                    throw new Exception("Maximum packet length is 255 bytes");
                }

                var header = new byte[7];
                header[0] = (byte)DeviceCommands.SpiTransaction;
                header[1] = (byte)(chipSelect?.PinNumber ?? 255);
                header[2] = (byte)chipSelectMode;
                header[3] = (byte)spi0Ckr;
                header[4] = (byte)spiMode;
                header[5] = (byte)burstMode;
                header[6] = (byte)transactionLength;

                // just send the header
                if (burstMode == SpiBurstMode.BurstRx)
                {
                    await _device.SendPeripheralConfigPacketAsync(header).ConfigureAwait(false);
                }
                else
                {
                    var dataToSend = new byte[transactionLength + header.Length];
                    Array.Copy(header, dataToSend, header.Length);
                    Array.Copy(dataToWrite, 0, dataToSend, header.Length, transactionLength);

                    var bytesRemaining = dataToSend.Length;
                    var offset         = 0;
                    while (bytesRemaining > 0)
                    {
                        var transferLength = bytesRemaining > 64 ? 64 : bytesRemaining;
                        var tmp            = dataToSend.Skip(offset).Take(transferLength);
                        await _device.SendPeripheralConfigPacketAsync(tmp.ToArray()).ConfigureAwait(false);

                        offset         += transferLength;
                        bytesRemaining -= transferLength;
                    }
                }

                // no need to wait if we're not reading anything
                if (burstMode != SpiBurstMode.BurstTx)
                {
                    var bytesRemaining = transactionLength;
                    var srcIndex       = 0;
                    while (bytesRemaining > 0)
                    {
                        var numBytesToTransfer = bytesRemaining > 64 ? 64 : bytesRemaining;
                        var receivedData       = await _device.ReceiveCommsResponsePacketAsync((uint)numBytesToTransfer)
                                                 .ConfigureAwait(false);

                        Array.Copy(receivedData, 0, returnedData, srcIndex,
                                   receivedData.Length); // just in case we don't get what we're expecting
                        srcIndex       += numBytesToTransfer;
                        bytesRemaining -= numBytesToTransfer;
                    }
                }
            }

            return(returnedData);
        }
Ejemplo n.º 5
0
 /// <summary>
 ///     Construct a shift register attached to an SPI port
 /// </summary>
 /// <param name="spiModule">The SPI module this shift register is attached to</param>
 /// <param name="latchPin">The latch pin to use</param>
 /// <param name="numPins">The number of pins on the shift register</param>
 /// <param name="mode">THe SPI mode to use with this shift register (and subsequent ones on this chain)</param>
 /// <param name="csMode">The chip select mode to use with this shift register (and subsequent ones on this chain)</param>
 /// <param name="speedMhz">The speed to operate this shift register (and subsequent ones on this chain) with</param>
 public ShiftOut(Spi spiModule, SpiChipSelectPin latchPin, int numPins = 8, SpiMode mode = SpiMode.Mode00,
                 ChipSelectMode csMode = ChipSelectMode.PulseHighAtEnd, double speedMhz  = 1)
     : base(spiModule, latchPin, numPins / 8, speedMhz, mode, csMode)
 {
     setup(numPins);
 }