using System; using System.Runtime.InteropServices; using NvAPIWrapper.Native.Attributes; using NvAPIWrapper.Native.General.Structures; using NvAPIWrapper.Native.Helpers; using NvAPIWrapper.Native.Helpers.Structures; using NvAPIWrapper.Native.Interfaces; using NvAPIWrapper.Native.Interfaces.GPU; namespace NvAPIWrapper.Native.GPU.Structures { /// [StructLayout(LayoutKind.Sequential, Pack = 8)] [StructureVersion(3)] public struct I2CInfoV3 : IInitializable, IDisposable, II2CInfo { // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable private readonly StructureVersion _Version; private readonly OutputId _OutputMask; private readonly byte _UseDDCPort; private readonly byte _I2CDeviceAddress; private ValueTypeArray _I2CRegisterAddress; private readonly uint _I2CRegisterAddressLength; private ValueTypeArray _Data; private readonly uint _DataLength; // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable private readonly uint _I2CSpeed; private readonly I2CSpeed _I2CSpeedInKHz; private readonly byte _PortId; private readonly uint _IsPortIdPresent; /// // ReSharper disable once ConvertToAutoProperty public OutputId OutputMask { get => _OutputMask; } /// public bool UseDDCPort { get => _UseDDCPort > 0; } /// // ReSharper disable once ConvertToAutoProperty public I2CSpeed Speed { get => _I2CSpeedInKHz; } /// public bool IsReadOperation { get => (_I2CDeviceAddress & 1) == 1; } /// public byte DeviceAddress { get => (byte) (_I2CDeviceAddress >> 1); } /// public byte? PortId { get { if (_IsPortIdPresent > 0) { return _PortId; } return null; } } /// public byte[] Data { get { if (_Data.IsNull || _DataLength == 0) { return new byte[0]; } return _Data.ToArray((int) _DataLength); } } /// public byte[] RegisterAddress { get { if (_I2CRegisterAddress.IsNull || _I2CRegisterAddressLength == 0) { return new byte[0]; } return _I2CRegisterAddress.ToArray((int) _I2CRegisterAddressLength); } } /// /// Creates an instance of for write operations. /// /// The target display output mask /// The port id on which device is connected /// A boolean value indicating that the DDC port should be used instead of the communication port /// The device I2C slave address /// The target I2C register address /// The payload data /// The target speed of the transaction in kHz public I2CInfoV3( OutputId outputMask, byte? portId, bool useDDCPort, byte deviceAddress, byte[] registerAddress, byte[] data, I2CSpeed speed = I2CSpeed.Default ) : this(outputMask, portId, useDDCPort, deviceAddress, false, registerAddress, data, speed) { } /// /// Creates an instance of for read operations. /// /// The target display output mask /// The port id on which device is connected /// A boolean value indicating that the DDC port should be used instead of the communication port /// The device I2C slave address /// The target I2C register address /// The length of the buffer to allocate for the read operation. /// The target speed of the transaction in kHz public I2CInfoV3( OutputId outputMask, byte? portId, bool useDDCPort, byte deviceAddress, byte[] registerAddress, uint readDataLength, I2CSpeed speed = I2CSpeed.Default ) : this(outputMask, portId, useDDCPort, deviceAddress, true, registerAddress, new byte[readDataLength], speed) { } private I2CInfoV3( OutputId outputMask, byte? portId, bool useDDCPort, byte deviceAddress, bool isRead, byte[] registerAddress, byte[] data, I2CSpeed speed = I2CSpeed.Default ) { this = typeof(I2CInfoV3).Instantiate(); _UseDDCPort = useDDCPort ? (byte) 1 : (byte) 0; _OutputMask = outputMask; _I2CDeviceAddress = (byte) (deviceAddress << 1); _I2CSpeed = 0xFFFF; // Deprecated _I2CSpeedInKHz = speed; if (isRead) { _I2CDeviceAddress |= 1; } if (portId != null) { _PortId = portId.Value; _IsPortIdPresent = 1; } else { _IsPortIdPresent = 0; } if (registerAddress?.Length > 0) { _I2CRegisterAddress = ValueTypeArray.FromArray(registerAddress); _I2CRegisterAddressLength = (uint) registerAddress.Length; } else { _I2CRegisterAddress = ValueTypeArray.Null; _I2CRegisterAddressLength = 0; } if (data?.Length > 0) { _Data = ValueTypeArray.FromArray(data); _DataLength = (uint) data.Length; } else { _Data = ValueTypeArray.Null; _DataLength = 0; } } /// /// Calculates and fills the last byte of data to the checksum value required by the DDCCI protocol /// /// The target device address. /// The target register address. /// The data to be sent and store the checksum. public static void FillDDCCIChecksum(byte deviceAddress, byte[] registerAddress, byte[] data) { I2CInfoV2.FillDDCCIChecksum(deviceAddress, registerAddress, data); } /// public void Dispose() { if (!_I2CRegisterAddress.IsNull) { _I2CRegisterAddress.Dispose(); } if (!_Data.IsNull) { _Data.Dispose(); } } } }