spi.cs

来自「This is a Windows CE 6.0 Board Support P」· CS 代码 · 共 357 行

CS
357
字号
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Gumstix;
using OpenNETCF.IO;

namespace Gumstix
{
    public class SPI : StreamInterfaceDriver
    {

        #region SPI device IOCTL codes

        private const Int32 FILE_DEVICE_BUS_EXTENDER = 0x0000002a;
        private const Int32 FILE_ANY_ACCESS = 0x0;
        private const Int32 METHOD_BUFFERED = 0x0;

        private const Int32 CODE_IOCTL_RESET =		          3000;  // Reset
        private const Int32 CODE_IOCTL_EXCHANGE =  		      3001;  // Exchange data
        private const Int32 CODE_IOCTL_SET_MODE	=		      3002;  // Set mode
        private const Int32 CODE_IOCTL_GET_MODE	=		      3003;  // Get mode
        private const Int32 CODE_IOCTL_ENABLE_LOOPBACK =      3004;  // Enable loopback
        private const Int32 CODE_IOCTL_DISABLE_LOOPBACK	=     3005;  // Disable loopback 
        private const Int32 CODE_IOCTL_SET_BUS_SPEED_MASK =   3006;  // Set bus speed
        private const Int32 CODE_IOCTL_GET_BUS_SPEED_MASK =   3007;  // Get bus speed

        private const Int32 IOCTL_RESET =
            ((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
            | ((CODE_IOCTL_RESET) << 2) | (METHOD_BUFFERED);

        private const Int32 IOCTL_EXCHANGE =
            ((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
            | ((CODE_IOCTL_EXCHANGE) << 2) | (METHOD_BUFFERED);

        private const Int32 IOCTL_SET_MODE =
            ((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
            | ((CODE_IOCTL_SET_MODE) << 2) | (METHOD_BUFFERED);

        private const Int32 IOCTL_GET_MODE =
            ((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
            | ((CODE_IOCTL_GET_MODE) << 2) | (METHOD_BUFFERED);

        private const Int32 IOCTL_ENABLE_LOOPBACK =
            ((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
            | ((CODE_IOCTL_ENABLE_LOOPBACK) << 2) | (METHOD_BUFFERED);

        private const Int32 IOCTL_DISABLE_LOOPBACK =
            ((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
            | ((CODE_IOCTL_DISABLE_LOOPBACK) << 2) | (METHOD_BUFFERED);

        private const Int32 IOCTL_SET_BUS_SPEED_MASK =
            ((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
            | ((CODE_IOCTL_SET_BUS_SPEED_MASK) << 2) | (METHOD_BUFFERED);

        private const Int32 IOCTL_GET_BUS_SPEED_MASK =
            ((FILE_DEVICE_BUS_EXTENDER) << 16) | ((FILE_ANY_ACCESS) << 14)
            | ((CODE_IOCTL_GET_BUS_SPEED_MASK) << 2) | (METHOD_BUFFERED);


        #endregion

        #region Native interface structures

        [StructLayout(LayoutKind.Sequential)]
        private struct BusConfig
        {
            public bool pol;
            public bool pha;
            public UInt32 bitcount;
            public UInt32 rsvd1;
            public UInt32 rsvd2;

            public BusConfig(bool pol, bool pha, UInt32 bitcount)
            {
                this.pol = pol;
                this.pha = pha;
                this.bitcount = bitcount;
                this.rsvd1 = 0;
                this.rsvd2 = 0;
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct Packet
        {
            public IntPtr busConfig;
            public IntPtr txBuffer;
            public IntPtr rxBuffer;
            public UInt32 length;
            public IntPtr completeHandle;

            public Packet(IntPtr busConfig, IntPtr txData, IntPtr rxData, UInt32 dataLength, IntPtr handle)
            {
                this.busConfig = busConfig;
                this.txBuffer = txData;
                this.rxBuffer = rxData;
                this.length = dataLength;
                this.completeHandle = handle;
            }
        }
        #endregion

        #region ctor / dtor
        /// <summary>
        /// Provides access to the SPI #2 bus on the PXA270.
        /// </summary>
        public SPI() : base("SPI2:")
        {
            // open the driver
            Open(FileAccess.ReadWrite, FileShare.ReadWrite);
        }

        ~SPI()
        {
            // close the driver
            Close();
        }
        #endregion

        #region loop back test

        public bool Loopback
        {
            set
            {
                if (value)
                {
                    try
                    {
                        this.DeviceIoControl(IOCTL_ENABLE_LOOPBACK, null, null);
                    }
                    catch (Exception)
                    {
                        throw new Exception("Unable to complete SPI transaction:" + Marshal.GetLastWin32Error());
                    }
                }
                else
                {
                    try
                    {
                        this.DeviceIoControl(IOCTL_DISABLE_LOOPBACK, null, null);
                    }
                    catch (Exception)
                    {
                        throw new Exception("Unable to complete SPI transaction:" + Marshal.GetLastWin32Error());
                    }
                }
            }
        }

        #endregion

        #region transfer

        /// <summary>
        /// Transfer one byte of data over SPI bus
        /// </summary>
        /// <param name="data">data</param>
        /// <param name="pol">bus clock polarity</param>
        /// <param name="pha">bus clock phase</param>
        /// <returns>rx data</returns>
        public Byte Exchange(byte data, bool pol, bool pha)
        {
            byte rxdata = 0;

            BusConfig busConfig = new BusConfig(pol, pha, 8);

            int datasize = Marshal.SizeOf(data);
            IntPtr pTxbuffer = Marshal.AllocHGlobal(datasize);
            Marshal.StructureToPtr(data, pTxbuffer, false);
            IntPtr pRxbuffer = Marshal.AllocHGlobal(datasize);
            Marshal.StructureToPtr(rxdata, pRxbuffer, false);
            IntPtr pBusConfig = Marshal.AllocHGlobal(Marshal.SizeOf(busConfig));
            Marshal.StructureToPtr(busConfig, pBusConfig, false);

            Packet packet = new Packet(pBusConfig, pTxbuffer, pRxbuffer, 1, IntPtr.Zero);

            try
            {
                this.DeviceIoControl(IOCTL_EXCHANGE, SerializeToByteArray(packet), null);
                rxdata = Marshal.ReadByte(pRxbuffer);
            }
            catch (Exception)
            {
                throw new Exception("Unable to complete SPI transaction:" + Marshal.GetLastWin32Error());
            }
            finally
            {
                Marshal.FreeHGlobal(pTxbuffer);
                Marshal.FreeHGlobal(pRxbuffer);
                Marshal.FreeHGlobal(pBusConfig);
            }
            return rxdata;
        }

        /// <summary>
        /// Transfer one byte of data over SPI bus
        /// defaults pol and pha to false
        /// </summary>
        /// <param name="data">data</param>
        /// <returns>rx data</returns>
        public Byte Exchange(byte data)
        {
            return (Exchange(data, false, false));
        }

        /// <summary>
        /// Transfer two bytes (MSB first) of data over SPI bus
        /// </summary>
        /// <param name="data">data</param>
        /// <param name="pol">bus clock polarity</param>
        /// <param name="pha">bus clock phase</param>
        /// <returns>rx data</returns>
        public UInt16 Exchange(UInt16 data, bool pol, bool pha)
        {
            UInt16 rxdata = 0;

            BusConfig busConfig = new BusConfig(pol, pha, 16);

            int datasize = Marshal.SizeOf(data);
            IntPtr pTxbuffer = Marshal.AllocHGlobal(datasize);
            Marshal.StructureToPtr(data, pTxbuffer, false);
            IntPtr pRxbuffer = Marshal.AllocHGlobal(datasize);
            Marshal.StructureToPtr(rxdata, pRxbuffer, false);

            IntPtr pBusConfig = Marshal.AllocHGlobal(Marshal.SizeOf(busConfig));
            Marshal.StructureToPtr(busConfig, pBusConfig, false);

            Packet packet = new Packet(pBusConfig, pTxbuffer, pRxbuffer, 1, IntPtr.Zero);

            try
            {
                this.DeviceIoControl(IOCTL_EXCHANGE, SerializeToByteArray(packet), null);
                rxdata = (UInt16)Marshal.ReadInt16(pRxbuffer);
            }
            catch (Exception)
            {
                throw new Exception("Unable to complete SPI transaction:" + Marshal.GetLastWin32Error());
            }
            finally
            {
                Marshal.FreeHGlobal(pTxbuffer);
                Marshal.FreeHGlobal(pRxbuffer);
                Marshal.FreeHGlobal(pBusConfig);
            }
            return rxdata;
        }

        /// <summary>
        /// Transfer two bytes (MSB first) of data over SPI bus
        /// defaults pol and pha to false
        /// </summary>
        /// <param name="data">data</param>
        /// <returns>rx data</returns>
        public UInt16 Exchange(UInt16 data)
        {
            return (Exchange(data, false, false));
        }

        /// <summary>
        /// Transfer four bytes (MSB first) of data over SPI bus
        /// </summary>
        /// <param name="data">data</param>
        /// <param name="pol">bus clock polarity</param>
        /// <param name="pha">bus clock phase</param>
        /// <returns>rx data</returns>
        public UInt32 Exchange(UInt32 data, bool pol, bool pha)
        {
            UInt32 rxdata = 0;

            BusConfig busConfig = new BusConfig(pol, pha, 32);

            int datasize = Marshal.SizeOf(data);
            IntPtr pTxbuffer = Marshal.AllocHGlobal(datasize);
            Marshal.StructureToPtr(data, pTxbuffer, false);
            IntPtr pRxbuffer = Marshal.AllocHGlobal(datasize);
            Marshal.StructureToPtr(rxdata, pRxbuffer, false);

            IntPtr pBusConfig = Marshal.AllocHGlobal(Marshal.SizeOf(busConfig));
            Marshal.StructureToPtr(busConfig, pBusConfig, false);

            Packet packet = new Packet(pBusConfig, pTxbuffer, pRxbuffer, 1, IntPtr.Zero);

            try
            {
                this.DeviceIoControl(IOCTL_EXCHANGE, SerializeToByteArray(packet), null);
                rxdata = (UInt32)Marshal.ReadInt32(pRxbuffer);
            }
            catch (Exception)
            {
                throw new Exception("Unable to complete SPI transaction:" + Marshal.GetLastWin32Error());
            }
            finally
            {
                Marshal.FreeHGlobal(pTxbuffer);
                Marshal.FreeHGlobal(pRxbuffer);
                Marshal.FreeHGlobal(pBusConfig);
            }
            return rxdata;
        }

        /// <summary>
        /// Transfer four bytes (MSB first) of data over SPI bus
        /// defaults pol and pha to false
        /// </summary>
        /// <param name="data">data</param>
        /// <returns>rx data</returns>
        public UInt32 Exchange(UInt32 data)
        {
            return (Exchange(data, false, false));
        }


        #endregion

        #region P/Invoke helpers

        /// <summary>
        /// Byte array serializer
        /// </summary>
        /// <param name="anything"></param>
        /// <returns></returns>
        private static byte[] SerializeToByteArray(object anything)
        {
            int rawsize = Marshal.SizeOf(anything);
            IntPtr buffer = Marshal.AllocHGlobal(rawsize);
            Marshal.StructureToPtr(anything, buffer, false);
            byte[] rawdatas = new byte[rawsize];
            Marshal.Copy(buffer, rawdatas, 0, rawsize);
            Marshal.FreeHGlobal(buffer);
            return rawdatas;
        }

        /// <summary>
        /// De-serializer from byte array
        /// </summary>
        /// <param name="rawdatas"></param>
        /// <param name="anytype"></param>
        /// <returns></returns>
        private static object DeserializeFromByteArray(byte[] rawdatas, Type anytype)
        {
            int rawsize = Marshal.SizeOf(anytype);
            if (rawsize > rawdatas.Length)
                return null;
            IntPtr buffer = Marshal.AllocHGlobal(rawsize);
            Marshal.Copy(rawdatas, 0, buffer, rawsize);
            object retobj = Marshal.PtrToStructure(buffer, anytype);
            Marshal.FreeHGlobal(buffer);
            return retobj;
        }
        #endregion

    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?