Exemplo n.º 1
0
 /// <summary>
 ///     Start an SPI transaction
 /// </summary>
 /// <param name="dataToSend">The data to send</param>
 /// <param name="burst">The burst mode, if any, to use</param>
 /// <returns>Data received by the peripheral</returns>
 public Task <byte[]> SendReceiveAsync(byte[] dataToSend, SpiBurstMode burst = SpiBurstMode.NoBurst)
 {
     return(_spi.SendReceiveAsync(dataToSend, ChipSelect, ChipSelectMode, Frequency, burst, Mode));
 }
Exemplo n.º 2
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);
        }