示例#1
0
 public byte[] Write(IDigitalOut DeviceSelect, byte[] Data, int DataLength)
 {
     DeviceSelect.SetOutput(false);
     byte[] DataReturn = RaspberryPi.SPIRW(BusNum, Data, DataLength);
     DeviceSelect.SetOutput(true);
     return(DataReturn);
 }
示例#2
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Enables the SPI slave device which uses a GPIO pin as a slave select.
        ///
        /// NOTE on how this works. When using a GPIO pin as a slave select line
        ///   we still need to open a SPIDev device because we need a device to
        ///   send the data to. The way SPIDev works each spidev device is
        ///   fundamentally associated with a particular slave select line and
        ///   this cannot be changed. The GPIO line will be used as a separate
        ///   slave select but the spidev device specific slave select will also
        ///   be asserted whenever the device is writtent to.
        ///
        ///   In order to use a GPIO as a slave select you must ignore and not
        ///   electrically attach anything to the slave select pin the SPIDEV
        ///   device uses as it will be asserted on each write.
        ///
        ///   In other words, the SPIDev device is needed to shift the data in
        ///   and out, however you must ignore its internal slave select line
        ///   entirely if you wish to use GPIO based slave selects. Otherwise
        ///   any device attached to it will be receive every write to the
        ///   SPIPort no matter which GPIO slave select is also asserted.
        ///
        /// </summary>
        /// <returns>ssHandle - the handle for the Slave Device or null for fail</returns>
        ///// <param name="spiSlaveDeviceIn">The GPIO of the pin we use as the slave select</param>
        /// <param name="output"> The <see cref="IDigitalOut"/> to prepare for SPI CS use. </param>
        /// <history>
        ///    16 Sep 17  Cai Biesinger - Modified for Scarlet: Switched from direct GPIO control to IDigitalOut.
        ///    21 Dec 14  Cynic - Originally written
        /// </history>
        public void EnableSPIGPIOSlaveDevice(IDigitalOut output)
        {
            // get first slave device. We need to check we have one
            SPISlaveDeviceHandle ssHandle = PortDevice;

            // sanity check
            if (ssHandle == null)
            {
                throw new Exception("At least one non GPIO Slave Device must be enabled first.");
            }

            // set this high by default, most modes have slave selects high and go low to activate
            output.SetOutput(true);

            //Console.WriteLine("SPIPort GPIO Slave Device Enabled: "+ gpioEnum.ToString());

            // record that we opened this slave device (so we can close it later)
            SlaveDevices.Add(output);
        }
示例#3
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Writes/Reads a buffer out/in to/from an SPI Slave Device.
        ///
        /// Note that the TO/FROM's and IN/OUT's in the above line are there because
        /// the SPI protocol always reads a byte for every byte sent. If you send a
        /// byte you get a byte. If you do not sent a byte you will never receive
        /// a byte since this code operates as an SPI Master. Thus if you only
        /// wish to receive you must send an equivalent number of bytes. The
        /// bytes you send are determined by the Slave. Sometimes this is just
        /// 0x00 and sometimes it represents an address to read - exactly what you,
        /// send is entirely slave device implementation dependent.
        ///
        /// If you only wish to transmit, not receive, just use NULL for your
        /// rxBuffer. The SPI port will still receive, of course, but you will
        /// not be bothered by it.
        ///
        /// NOTE: the Slave Select is set when you opened the port. The rule is
        /// one slave to one SPISlaveDeviceHandle.
        ///
        /// </summary>
        /// <param name="ssHandle">The SPI Slave Device handle to write to</param>
        /// <param name="txByteBuf">The buffer with bytes to write</param>
        /// <param name="rxByteBuf">The buffer with bytes to receive. Can be NULL</param>
        /// <param name="numBytes">The number of bytes to send/receive
        /// <history>
        ///    16 Sep 17  Cai Biesinger - Modified for Scarlet: switching from file descriptor GPIO to IDigitalOut.
        ///    21 Dec 14  Cynic - Originally written
        /// </history>
        public void SPITransfer(IDigitalOut output, byte[] txByteBuf, byte[] rxByteBuf, int numBytes)
        {
            int spiFileDescriptor = -1;
            int ioctlRetVal       = -1;

            // sanity check
            if (output == null)
            {
                throw new Exception("Null IDigitalOut object");
            }
            if (txByteBuf == null)
            {
                throw new Exception("Null tx buffer");
            }
            if (numBytes <= 0)
            {
                throw new Exception("numBytes <= 0");
            }

            // set up our file descriptor

            // use the descriptor of the first non-GPIO slave select
            // we find.

            // get first slave device. We need the file descriptor
            SPISlaveDeviceHandle firstHandle = PortDevice;

            // sanity check
            if (firstHandle == null)
            {
                throw new Exception("At least one non GPIO Slave Device must be enabled.");
            }
            // use this descriptor
            spiFileDescriptor = firstHandle.SpiDevFileDescriptor;

            // the data needs to be in unmanaged global memory
            // so the spidev driver can see it. This allocates
            // that memory. We MUST release this!
            IntPtr txBufPtr = Marshal.AllocHGlobal(numBytes + 1);
            IntPtr rxBufPtr = Marshal.AllocHGlobal(numBytes + 1);

            try
            {
                // copy the data from the tx buffer to our pointer
                Marshal.Copy(txByteBuf, 0, txBufPtr, numBytes);

                // create and fill in the contents of our transfer struct
                spi_ioc_transfer xfer = new spi_ioc_transfer();
                xfer.tx_buf        = txBufPtr;
                xfer.rx_buf        = rxBufPtr;
                xfer.len           = (UInt32)numBytes;
                xfer.speed_hz      = 0; //(UInt16)ssHandle.SpeedInHz;
                xfer.delay_usecs   = 0; // ssHandle.DelayUSecs;
                xfer.bits_per_word = 0; // ssHandle.BitsPerWord;
                xfer.cs_change     = 0; // ssHandle.CSChange;
                xfer.pad           = 0;

                // lower the slave select
                output.SetOutput(false);
                try
                {
                    // this is an external call to the libc.so.6 library
                    ioctlRetVal = ExternalIoCtl(spiFileDescriptor, SPI_IOC_MESSAGE_1, ref xfer);
                }
                finally
                {
                    // raise the slave select
                    // CaiB 2017-09-16: Chenged this to true, BBBCSIO never released SS.
                    output.SetOutput(true);
                }

                // did the call succeed?
                if (ioctlRetVal < 0)
                {
                    // it failed
                    throw new Exception("ExternalIoCtl on device " + output + " failed. retval=" + ioctlRetVal.ToString());
                }

                // did the caller supply a receive buffer
                if (rxByteBuf != null)
                {
                    // yes they did, copy the returned data in
                    Marshal.Copy(rxBufPtr, rxByteBuf, 0, numBytes);
                }
            }
            finally
            {
                // Free the unmanaged memory.
                Marshal.FreeHGlobal(txBufPtr);
                Marshal.FreeHGlobal(rxBufPtr);
            }
        }