Exemplo n.º 1
0
        internal void Read(int deviceAddress, Span <byte> buffer)
        {
            if (deviceAddress < 0 || deviceAddress > ushort.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(deviceAddress));
            }

            if (buffer.Length > ushort.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(buffer), $"Buffer is too large. Maximum length is {ushort.MaxValue}.");
            }

            ushort bytesRead;
            var    ftStatus = FtFunction.FT4222_I2CMaster_Read(_ftHandle, (ushort)deviceAddress, in MemoryMarshal.GetReference(buffer), (ushort)buffer.Length, out bytesRead);

            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"{nameof(Read)} failed to read, error: {ftStatus}");
            }

            if (bytesRead != buffer.Length)
            {
                throw new IOException($"Number of bytes read ({bytesRead}) doesn't match length of the buffer ({buffer.Length}).");
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Create an SPI FT4222 class
        /// </summary>
        /// <param name="settings">SPI Connection Settings</param>
        public Ft4222Spi(SpiConnectionSettings settings)
        {
            _settings = settings;
            // Check device
            var devInfos = FtCommon.GetDevices();

            if (devInfos.Count == 0)
            {
                throw new IOException("No FTDI device available");
            }

            // Select the one from bus Id
            // FT4222 propose depending on the mode multiple interfaces. Only the A is available for SPI or where there is none as it's the only interface
            var devInfo = devInfos.Where(m => m.Description == "FT4222 A" || m.Description == "FT4222").ToArray();

            if ((devInfo.Length == 0) || (devInfo.Length < _settings.BusId))
            {
                throw new IOException($"Can't find a device to open SPI on index {_settings.BusId}");
            }

            DeviceInformation = devInfo[_settings.BusId];
            // Open device
            var ftStatus = FtFunction.FT_OpenEx(DeviceInformation.LocId, FtOpenType.OpenByLocation, out _ftHandle);

            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Failed to open device {DeviceInformation.Description} with error: {ftStatus}");
            }

            // Set the clock but we need some math
            var(ft4222Clock, tfSpiDiv) = CalculateBestClockRate();

            ftStatus = FtFunction.FT4222_SetClock(_ftHandle, ft4222Clock);
            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Failed set clock rate {ft4222Clock} on device: {DeviceInformation.Description}with error: {ftStatus}");
            }


            SpiClockPolarity pol = SpiClockPolarity.ClockIdleLow;

            if ((_settings.Mode == SpiMode.Mode2) || (_settings.Mode == SpiMode.Mode3))
            {
                pol = SpiClockPolarity.ClockIdelHigh;
            }

            SpiClockPhase pha = SpiClockPhase.ClockLeading;

            if ((_settings.Mode == SpiMode.Mode1) || (_settings.Mode == SpiMode.Mode3))
            {
                pha = SpiClockPhase.ClockTailing;
            }

            // Configure the SPI
            ftStatus = FtFunction.FT4222_SPIMaster_Init(_ftHandle, SpiOperatingMode.Single, tfSpiDiv, pol, pha, (byte)_settings.ChipSelectLine);
            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Failed setup SPI on device: {DeviceInformation.Description} with error: {ftStatus}");
            }
        }
Exemplo n.º 3
0
        private void InitializeGpio(Ft4222Device device)
        {
            DeviceInformation = device;
            // Open device
            var ftStatus = FtFunction.FT_OpenEx(DeviceInformation.LocId, FtOpenType.OpenByLocation, out _ftHandle);

            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Failed to open device {DeviceInformation.Description}, status: {ftStatus}");
            }

            ftStatus = FtFunction.FT4222_SetSuspendOut(_ftHandle, false);
            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Can't initialize GPIO for device {DeviceInformation.Description} changing Suspend out mode, status: {ftStatus}");
            }

            ftStatus = FtFunction.FT4222_SetWakeUpInterrupt(_ftHandle, false);
            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Can't initialize GPIO for device {DeviceInformation.Description} removing wake up interrupt, status: {ftStatus}");
            }

            for (int i = 0; i < PinCountConst; i++)
            {
                _gpioDirections[i] = GpioPinMode.Output;
            }

            ftStatus = FtFunction.FT4222_GPIO_Init(_ftHandle, _gpioDirections);

            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Can't initialize GPIO for device {DeviceInformation.Description}, status: {ftStatus}");
            }
        }
Exemplo n.º 4
0
        protected override bool ReleaseHandle()
        {
            var ftStatus = FtFunction.FT4222_UnInitialize(this);

            ftStatus = FtFunction.FT_Close(this);
            return(ftStatus == FtStatus.Ok);
        }
Exemplo n.º 5
0
        /// <inheritdoc/>
        protected override void Write(int pinNumber, PinValue value)
        {
            var status = FtFunction.FT4222_GPIO_Write(_ftHandle, (GpioPort)pinNumber, value == PinValue.High ? GpioPinValue.High : GpioPinValue.Low);

            if (status != FtStatus.Ok)
            {
                throw new IOException($"{nameof(Write)}: failed to write GPIO, status: {status}");
            }
        }
Exemplo n.º 6
0
        /// <inheritdoc/>
        public override void Read(Span <byte> buffer)
        {
            ushort byteRead;
            var    ftStatus = FtFunction.FT4222_I2CMaster_Read(_ftHandle, (ushort)_settings.DeviceAddress, in MemoryMarshal.GetReference(buffer), (ushort)buffer.Length, out byteRead);

            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"{nameof(Read)} failed to read, error: {ftStatus}");
            }
        }
Exemplo n.º 7
0
        /// <inheritdoc/>
        protected override void SetPinMode(int pinNumber, PinMode mode)
        {
            _gpioDirections[pinNumber] = mode == PinMode.Output ? GpioPinMode.Output : GpioPinMode.Input;
            var status = FtFunction.FT4222_GPIO_Init(_ftHandle, _gpioDirections);

            if (status != FtStatus.Ok)
            {
                throw new IOException($"{nameof(SetPinMode)}: failed to set pin number {pinNumber} to {mode}, status: {status}");
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Get the versions of the chipset and dll
        /// </summary>
        /// <returns>Both the chipset and dll versions</returns>
        public static (Version?Chip, Version?Dll) GetVersions()
        {
            // First, let's find a device
            var devices = GetDevices();

            if (devices.Count == 0)
            {
                return(null, null);
            }

            // Check if the first not open device
            int idx = 0;

            for (idx = 0; idx < devices.Count; idx++)
            {
                if ((devices[idx].Flags & FtFlag.PortOpened) != FtFlag.PortOpened)
                {
                    break;
                }
            }

            if (idx == devices.Count)
            {
                throw new InvalidOperationException($"Can't find any open device to check the versions");
            }

            SafeFtHandle ftHandle = new SafeFtHandle();
            var          ftStatus = FtFunction.FT_OpenEx(devices[idx].LocId, FtOpenType.OpenByLocation, out ftHandle);

            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Can't open the device to check chipset version, status: {ftStatus}");
            }

            FtVersion ftVersion;

            ftStatus = FtFunction.FT4222_GetVersion(ftHandle, out ftVersion);
            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Can't find versions of chipset and FT4222, status: {ftStatus}");
            }

            ftStatus = FtFunction.FT_Close(ftHandle);
            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Can't close the device to check chipset version, status: {ftStatus}");
            }

            Version chip = new Version((int)(ftVersion.ChipVersion >> 24), (int)((ftVersion.ChipVersion >> 16) & 0xFF),
                                       (int)((ftVersion.ChipVersion >> 8) & 0xFF), (int)(ftVersion.ChipVersion & 0xFF));
            Version dll = new Version((int)(ftVersion.DllVersion >> 24), (int)((ftVersion.DllVersion >> 16) & 0xFF),
                                      (int)((ftVersion.DllVersion >> 8) & 0xFF), (int)(ftVersion.DllVersion & 0xFF));

            return(chip, dll);
        }
Exemplo n.º 9
0
        /// <inheritdoc/>
        protected override PinValue Read(int pinNumber)
        {
            GpioPinValue pinVal;
            var          status = FtFunction.FT4222_GPIO_Read(_ftHandle, (GpioPort)pinNumber, out pinVal);

            if (status != FtStatus.Ok)
            {
                throw new IOException($"{nameof(Read)}: failed to write GPIO, status: {status}");
            }
            return(pinVal == GpioPinValue.High ? PinValue.High : PinValue.Low);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Create a FT4222 GPIO driver
        /// </summary>
        /// <param name="deviceNumber">Number of the device in the device list, default 0</param>
        public Ft4222Gpio(int deviceNumber = 0)
        {
            // Check device
            var devInfos = FtCommon.GetDevices();

            if (devInfos.Count == 0)
            {
                throw new IOException("No FTDI device available");
            }

            // Select the deviceNumber, only the last one in Mode 0 and Mode 1 can be open.
            // The last one is either B if in Mode 0 or D in mode 1.
            string strMode = devInfos[0].Type == FtDevice.Ft4222HMode1or2With4Interfaces ? "FT4222 D" : "FT4222 B";

            var devInfo = devInfos.Where(m => m.Description == strMode).ToArray();

            if ((devInfo.Length == 0) || (devInfo.Length < deviceNumber))
            {
                throw new IOException($"Can't find a device to open GPIO on index {deviceNumber}");
            }

            DeviceInformation = devInfo[deviceNumber];
            // Open device
            var ftStatus = FtFunction.FT_OpenEx(DeviceInformation.LocId, FtOpenType.OpenByLocation, out _ftHandle);

            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Failed to open device {DeviceInformation.Description}, status: {ftStatus}");
            }

            ftStatus = FtFunction.FT4222_SetSuspendOut(_ftHandle, false);
            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Can't initialize GPIO for device {DeviceInformation.Description} changing Suspend out mode, status: {ftStatus}");
            }

            ftStatus = FtFunction.FT4222_SetWakeUpInterrupt(_ftHandle, false);
            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Can't initialize GPIO for device {DeviceInformation.Description} removing wake up interrupt, status: {ftStatus}");
            }

            for (int i = 0; i < PinCountConst; i++)
            {
                _gpioDirections[i] = GpioPinMode.Output;
            }

            ftStatus = FtFunction.FT4222_GPIO_Init(_ftHandle, _gpioDirections);

            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Can't initialize GPIO for device {DeviceInformation.Description}, status: {ftStatus}");
            }
        }
Exemplo n.º 11
0
 /// <inheritdoc/>
 protected override void RemoveCallbackForPinValueChangedEvent(int pinNumber, PinChangeEventHandler callback)
 {
     _pinFallingHandlers[pinNumber] -= callback;
     _pinRisingHandlers[pinNumber]  -= callback;
     if (_pinFallingHandlers == null)
     {
         _gpioTriggers[pinNumber] &= ~GpioTrigger.Falling;
     }
     if (_pinRisingHandlers == null)
     {
         _gpioTriggers[pinNumber] &= ~GpioTrigger.Rising;
     }
     FtFunction.FT4222_GPIO_SetInputTrigger(_ftHandle, (GpioPort)pinNumber, _gpioTriggers[pinNumber]);
 }
Exemplo n.º 12
0
        /// <summary>
        /// Get the version of the chip and dll
        /// </summary>
        /// <returns>version</returns>
        public (Version chip, Version dll) GetVersions()
        {
            var ftStatus = FtFunction.FT4222_GetVersion(_ftHandle, out var ftVersion);

            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Can't find versions of chipset and FT4222, status: {ftStatus}");
            }

            var chip = new Version((int)(ftVersion.ChipVersion >> 24), (int)((ftVersion.ChipVersion >> 16) & 0xFF),
                                   (int)((ftVersion.ChipVersion >> 8) & 0xFF), (int)(ftVersion.ChipVersion & 0xFF));
            var dll = new Version((int)(ftVersion.DllVersion >> 24), (int)((ftVersion.DllVersion >> 16) & 0xFF),
                                  (int)((ftVersion.DllVersion >> 8) & 0xFF), (int)(ftVersion.DllVersion & 0xFF));

            return(chip, dll);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Create a FT4222 I2C Device
        /// </summary>
        /// <param name="settings">I2C Connection Settings</param>
        /// <param name="frequencyKbps">The speed of I2C transmission.</param>
        public Ft4222I2cEx(I2cConnectionSettings settings, uint frequencyKbps = I2cMasterFrequencyKbps)
        {
            _settings     = settings ?? throw new ArgumentNullException(nameof(settings));
            FrequencyKbps = frequencyKbps;

            // Check device
            var devInfos = FtCommon.GetDevices();

            if (devInfos.Count == 0)
            {
                throw new IOException("No FTDI device available");
            }

            // Select the one from bus Id
            // FT4222 propose depending on the mode multiple interfaces. Only the A is available for I2C or where there is none as it's the only interface
            var devInfo = devInfos.Where(m => m.Description == "FT4222 A" || m.Description == "FT4222").ToArray();

            if ((devInfo.Length == 0) || (devInfo.Length < _settings.BusId))
            {
                throw new IOException($"Can't find a device to open I2C on index {_settings.BusId}");
            }

            DeviceInformation = devInfo[_settings.BusId];
            // Open device
            var ftStatus = FtFunction.FT_OpenEx(DeviceInformation.LocId, FtOpenType.OpenByLocation, out _ftHandle);

            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Failed to open device {DeviceInformation.Description}, status: {ftStatus}");
            }

            // Set the clock
            FtClockRate ft4222Clock = FtClockRate.Clock24MHz;

            ftStatus = FtFunction.FT4222_SetClock(_ftHandle, ft4222Clock);
            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Failed set clock rate {ft4222Clock} on device: {DeviceInformation.Description}, status: {ftStatus}");
            }

            // Set the device as I2C Master
            ftStatus = FtFunction.FT4222_I2CMaster_Init(_ftHandle, frequencyKbps);
            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Failed to initialize I2C Master mode on device: {DeviceInformation.Description}, status: {ftStatus}");
            }
        }
Exemplo n.º 14
0
        /// <summary>
        /// Returns the list of FT4222 connected
        /// </summary>
        /// <returns>A list of devices connected</returns>
        public static List <DeviceInformation> GetDevices()
        {
            List <DeviceInformation> devInfos = new List <DeviceInformation>();
            FtStatus ftStatus = 0;

            // Check device
            uint numOfDevices;

            ftStatus = FtFunction.FT_CreateDeviceInfoList(out numOfDevices);

            Debug.WriteLine($"Number of devices: {numOfDevices}");
            if (numOfDevices == 0)
            {
                throw new IOException($"No device found");
            }

            Span <byte> sernum = stackalloc byte[16];
            Span <byte> desc   = stackalloc byte[64];

            for (uint i = 0; i < numOfDevices; i++)
            {
                uint     flags = 0;
                FtDevice ftDevice;
                uint     id;
                uint     locId;
                IntPtr   handle;
                ftStatus = FtFunction.FT_GetDeviceInfoDetail(i, out flags, out ftDevice, out id, out locId,
                                                             in MemoryMarshal.GetReference(sernum), in MemoryMarshal.GetReference(desc), out handle);
                if (ftStatus != FtStatus.Ok)
                {
                    throw new IOException($"Can't read device information on device index {i}, error {ftStatus}");
                }

                var devInfo = new DeviceInformation(
                    (FtFlag)flags,
                    ftDevice,
                    id,
                    locId,
                    Encoding.ASCII.GetString(sernum.ToArray(), 0, FindFirstZero(sernum)),
                    Encoding.ASCII.GetString(desc.ToArray(), 0, FindFirstZero(desc)));
                devInfos.Add(devInfo);
            }

            return(devInfos);
        }
Exemplo n.º 15
0
        /// <inheritdoc/>
        protected override void AddCallbackForPinValueChangedEvent(int pinNumber, PinEventTypes eventTypes, PinChangeEventHandler callback)
        {
            if (eventTypes == PinEventTypes.None)
            {
                throw new ArgumentException($"{PinEventTypes.None} is an invalid value.", nameof(eventTypes));
            }

            if (eventTypes.HasFlag(PinEventTypes.Falling))
            {
                _gpioTriggers[pinNumber]       |= GpioTrigger.Falling;
                _pinFallingHandlers[pinNumber] += callback;
            }
            if (eventTypes.HasFlag(PinEventTypes.Rising))
            {
                _gpioTriggers[pinNumber]      |= GpioTrigger.Rising;
                _pinRisingHandlers[pinNumber] += callback;
            }
            FtFunction.FT4222_GPIO_SetInputTrigger(_ftHandle, (GpioPort)pinNumber, _gpioTriggers[pinNumber]);
        }
Exemplo n.º 16
0
        internal void Write(int deviceAddress, ReadOnlySpan <byte> buffer)
        {
            if (deviceAddress < 0 || deviceAddress > ushort.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(deviceAddress));
            }

            if (buffer.Length > ushort.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(buffer), $"Buffer is too large. Maximum length is {ushort.MaxValue}.");
            }

            ushort bytesSent;
            var    ftStatus = FtFunction.FT4222_I2CMaster_Write(_ftHandle, (ushort)deviceAddress, in MemoryMarshal.GetReference(buffer), (ushort)buffer.Length, out bytesSent);

            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"{nameof(Write)} failed to write, error: {ftStatus}");
            }
        }
Exemplo n.º 17
0
        /// <summary>
        /// Create a FT4222 I2C Device
        /// </summary>
        /// <param name="deviceInformation">Device information. Use FtCommon.GetDevices to get it.</param>
        public Ft4222I2cBus(FtDevice deviceInformation)
        {
            switch (deviceInformation.Type)
            {
            case FtDeviceType.Ft4222HMode0or2With2Interfaces:
            case FtDeviceType.Ft4222HMode1or2With4Interfaces:
            case FtDeviceType.Ft4222HMode3With1Interface:
                break;

            default: throw new ArgumentException($"Unknown device type: {deviceInformation.Type}");
            }

            DeviceInformation = deviceInformation;
            // Open device
            var ftStatus = FtFunction.FT_OpenEx(DeviceInformation.LocId, FtOpenType.OpenByLocation, out _ftHandle);

            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Failed to open device {DeviceInformation.Description}, status: {ftStatus}");
            }

            // Set the clock
            FtClockRate ft4222Clock = FtClockRate.Clock24MHz;

            ftStatus = FtFunction.FT4222_SetClock(_ftHandle, ft4222Clock);
            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Failed set clock rate {ft4222Clock} on device: {DeviceInformation.Description}, status: {ftStatus}");
            }

            // Set the device as I2C Master
            ftStatus = FtFunction.FT4222_I2CMaster_Init(_ftHandle, I2cMasterFrequencyKbps);
            if (ftStatus != FtStatus.Ok)
            {
                throw new IOException($"Failed to initialize I2C Master mode on device: {DeviceInformation.Description}, status: {ftStatus}");
            }
        }
Exemplo n.º 18
0
        /// <inheritdoc/>
        protected override WaitForEventResult WaitForEvent(int pinNumber, PinEventTypes eventTypes, CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                ushort queueSize;
                var    ftStatus = FtFunction.FT4222_GPIO_GetTriggerStatus(_ftHandle, (GpioPort)pinNumber, out queueSize);
                if (ftStatus != FtStatus.Ok)
                {
                    throw new IOException($"Can't get trigger status, error {ftStatus}");
                }

                if (queueSize > 0)
                {
                    Span <GpioTrigger> gpioTriggers = stackalloc GpioTrigger[queueSize];
                    ushort             readTrigger;
                    ftStatus = FtFunction.FT4222_GPIO_ReadTriggerQueue(_ftHandle, (GpioPort)pinNumber, in MemoryMarshal.GetReference(gpioTriggers), queueSize, out readTrigger);
                    if (ftStatus != FtStatus.Ok)
                    {
                        throw new IOException($"Can't read trigger status, error {ftStatus}");
                    }

                    switch (eventTypes)
                    {
                    case PinEventTypes.Rising:
                        if (_gpioTriggers[pinNumber].HasFlag(GpioTrigger.Rising))
                        {
                            if (gpioTriggers.ToArray().Where(m => m == GpioTrigger.Rising).Count() > 0)
                            {
                                return(new WaitForEventResult()
                                {
                                    EventTypes = PinEventTypes.Rising,
                                    TimedOut = false
                                });
                            }
                        }

                        break;

                    case PinEventTypes.Falling:
                        if (_gpioTriggers[pinNumber].HasFlag(GpioTrigger.Falling))
                        {
                            if (gpioTriggers.ToArray().Where(m => m == GpioTrigger.Falling).Count() > 0)
                            {
                                return(new WaitForEventResult()
                                {
                                    EventTypes = PinEventTypes.Falling,
                                    TimedOut = false
                                });
                            }
                        }

                        break;

                    case PinEventTypes.None:
                    default:
                        break;
                    }
                }
            }

            return(new WaitForEventResult()
            {
                EventTypes = PinEventTypes.None,
                TimedOut = true
            });
        }