/// <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)); }
/// <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); }