Skip to content

Commit 96aab04

Browse files
authored
Add I2cTransferResult and I2cTransferStatus (#11)
1 parent b388ba4 commit 96aab04

File tree

5 files changed

+171
-47
lines changed

5 files changed

+171
-47
lines changed

System.Device.I2c/I2cDevice.cs

Lines changed: 93 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5-
using System;
5+
using System.Runtime.CompilerServices;
66

77
namespace System.Device.I2c
88
{
@@ -11,25 +11,40 @@ namespace System.Device.I2c
1111
/// </summary>
1212
public class I2cDevice : IDisposable
1313
{
14+
// this is used as the lock object
15+
// a lock is required because multiple threads can access the device
16+
[Diagnostics.DebuggerBrowsable(Diagnostics.DebuggerBrowsableState.Never)]
17+
private readonly object _syncLock;
1418

15-
private Windows.Devices.I2c.I2cDevice _device;
16-
// For the ReadByte and WriteByte operations
17-
private byte[] bufferSingleOperation = new byte[1];
19+
[Diagnostics.DebuggerBrowsable(Diagnostics.DebuggerBrowsableState.Never)]
20+
private readonly I2cConnectionSettings _connectionSettings;
21+
22+
[Diagnostics.DebuggerBrowsable(Diagnostics.DebuggerBrowsableState.Never)]
23+
private bool _disposed;
24+
25+
// speeds up the execution of ReadByte and WriteByte operations
26+
private readonly byte[] _buffer;
1827

1928
/// <summary>
2029
/// The connection settings of a device on an I2C bus. The connection settings are immutable after the device is created
2130
/// so the object returned will be a clone of the settings object.
2231
/// </summary>
23-
public I2cConnectionSettings ConnectionSettings { get; }
32+
public I2cConnectionSettings ConnectionSettings { get => _connectionSettings; }
2433

2534
/// <summary>
2635
/// Reads a byte from the I2C device.
2736
/// </summary>
2837
/// <returns>A byte read from the I2C device.</returns>
2938
public byte ReadByte()
3039
{
31-
_device.Read(bufferSingleOperation);
32-
return bufferSingleOperation[0];
40+
lock (_syncLock)
41+
{
42+
var buffer = new SpanByte(_buffer);
43+
44+
NativeTransmit(null, buffer);
45+
46+
return buffer[0];
47+
}
3348
}
3449

3550
/// <summary>
@@ -39,26 +54,27 @@ public byte ReadByte()
3954
/// The buffer to read the data from the I2C device.
4055
/// The length of the buffer determines how much data to read from the I2C device.
4156
/// </param>
42-
public void Read(SpanByte buffer)
57+
public I2cTransferResult Read(SpanByte buffer)
4358
{
44-
// This is allocating an intermediate buffer and then copy back the data to
45-
// the SpanByte. This is intend to be changed in a native implementation
46-
byte[] toRead = new byte[buffer.Length];
47-
_device.Read(toRead);
48-
for (int i = 0; i < toRead.Length; i++)
59+
lock (_syncLock)
4960
{
50-
buffer[i] = toRead[i];
61+
return NativeTransmit(null, buffer);
5162
}
5263
}
5364

5465
/// <summary>
5566
/// Writes a byte to the I2C device.
5667
/// </summary>
5768
/// <param name="value">The byte to be written to the I2C device.</param>
58-
public void WriteByte(byte value)
69+
public I2cTransferResult WriteByte(byte value)
5970
{
60-
bufferSingleOperation[0] = value;
61-
_device.Write(bufferSingleOperation);
71+
lock (_syncLock)
72+
{
73+
// copy value
74+
_buffer[0] = value;
75+
76+
return NativeTransmit(new SpanByte(_buffer), null);
77+
}
6278
}
6379

6480
/// <summary>
@@ -68,11 +84,12 @@ public void WriteByte(byte value)
6884
/// The buffer that contains the data to be written to the I2C device.
6985
/// The data should not include the I2C device address.
7086
/// </param>
71-
public void Write(SpanByte buffer)
87+
public I2cTransferResult Write(SpanByte buffer)
7288
{
73-
// This is allocating an intermediate buffer using the buffer of
74-
// the SpanByte. This is intend to be changed in a native implementation
75-
_device.Write(buffer.ToArray());
89+
lock (_syncLock)
90+
{
91+
return NativeTransmit(buffer, null);
92+
}
7693
}
7794

7895
/// <summary>
@@ -86,15 +103,11 @@ public void Write(SpanByte buffer)
86103
/// The buffer to read the data from the I2C device.
87104
/// The length of the buffer determines how much data to read from the I2C device.
88105
/// </param>
89-
public void WriteRead(SpanByte writeBuffer, SpanByte readBuffer)
106+
public I2cTransferResult WriteRead(SpanByte writeBuffer, SpanByte readBuffer)
90107
{
91-
// This is allocating an intermediate buffer and then copy back the data to
92-
// the SpanByte. This is intend to be changed in a native implementation
93-
byte[] toRead = new byte[readBuffer.Length];
94-
_device.WriteRead(writeBuffer.ToArray(), toRead);
95-
for (int i = 0; i < toRead.Length; i++)
108+
lock (_syncLock)
96109
{
97-
readBuffer[i] = toRead[i];
110+
return NativeTransmit(writeBuffer, readBuffer);
98111
}
99112
}
100113

@@ -114,26 +127,65 @@ public static I2cDevice Create(I2cConnectionSettings settings)
114127
/// <param name="settings">Connection settings</param>
115128
public I2cDevice(I2cConnectionSettings settings)
116129
{
117-
ConnectionSettings = settings;
118-
_device = Windows.Devices.I2c.I2cDevice.FromId($"I2C{settings.BusId}", new Windows.Devices.I2c.I2cConnectionSettings(settings.DeviceAddress)
130+
_connectionSettings = settings;
131+
132+
// create the buffer
133+
_buffer = new byte[1];
134+
135+
// create the lock object
136+
_syncLock = new object();
137+
138+
// call native init to allow HAL/PAL inits related with I2C hardware
139+
NativeInit();
140+
}
141+
142+
#region IDisposable Support
143+
144+
private void Dispose(bool disposing)
145+
{
146+
if (!_disposed)
119147
{
120-
BusSpeed = (Windows.Devices.I2c.I2cBusSpeed)settings.BusSpeed,
121-
SharingMode = (Windows.Devices.I2c.I2cSharingMode)settings.SharingMode
122-
});
148+
NativeDispose();
149+
150+
_disposed = true;
151+
}
123152
}
124153

125-
/// <inheritdoc cref="IDisposable.Dispose"/>
126-
public void Dispose()
154+
#pragma warning disable 1591
155+
~I2cDevice()
127156
{
128-
Dispose(true);
129-
GC.SuppressFinalize(this);
157+
Dispose(false);
130158
}
131159

132160
/// <summary>
133-
/// Disposes this instance
161+
/// <inheritdoc cref="IDisposable.Dispose"/>
134162
/// </summary>
135-
/// <param name="disposing"><see langword="true"/> if explicitly disposing, <see langword="false"/> if in finalizer</param>
136-
void Dispose(bool disposing)
137-
{ }
163+
public void Dispose()
164+
{
165+
lock (_syncLock)
166+
{
167+
if (!_disposed)
168+
{
169+
Dispose(true);
170+
171+
GC.SuppressFinalize(this);
172+
}
173+
}
174+
}
175+
176+
#endregion
177+
178+
#region external calls to native implementations
179+
180+
[MethodImpl(MethodImplOptions.InternalCall)]
181+
private extern void NativeInit();
182+
183+
[MethodImpl(MethodImplOptions.InternalCall)]
184+
private extern void NativeDispose();
185+
186+
[MethodImpl(MethodImplOptions.InternalCall)]
187+
private extern I2cTransferResult NativeTransmit(SpanByte writeBuffer, SpanByte readBuffer);
188+
189+
#endregion
138190
}
139191
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
namespace System.Device.I2c
6+
{
7+
/// <summary>
8+
/// Provides information about whether the data transfers that the <see cref="I2cDevice.Read"/>, <see cref="I2cDevice.Write"/>, or <see cref="I2cDevice.WriteRead"/> method performed succeeded, and the actual number
9+
/// of bytes the method transferred.
10+
/// </summary>
11+
public struct I2cTransferResult
12+
{
13+
[Diagnostics.DebuggerBrowsable(Diagnostics.DebuggerBrowsableState.Never)]
14+
private readonly uint _bytesTransferred;
15+
16+
[Diagnostics.DebuggerBrowsable(Diagnostics.DebuggerBrowsableState.Never)]
17+
private readonly I2cTransferStatus _status;
18+
19+
/// <summary>
20+
/// The actual number of bytes that the operation actually transferred. The following table describes what this value represents for each method.
21+
/// </summary>
22+
public uint BytesTransferred { get => _bytesTransferred; }
23+
24+
/// <summary>
25+
/// An enumeration value that indicates if the read or write operation transferred the full number of bytes that the method requested, or the reason
26+
/// that the full transfer did not succeed. For WriteReadPartial, the value indicates whether the data for both the write and the read operations was entirely transferred.
27+
/// </summary>
28+
public I2cTransferStatus Status { get => _status; }
29+
}
30+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
namespace System.Device.I2c
6+
{
7+
/// <summary>
8+
/// Describes whether the data transfers that the <see cref="I2cDevice.Read"/>, <see cref="I2cDevice.Write"/>, or <see cref="I2cDevice.WriteRead"/> methods performed succeeded, or provides the reason that the transfers did not succeed.
9+
/// </summary>
10+
public enum I2cTransferStatus
11+
{
12+
/// <summary>
13+
/// The transfer failed for an unknown reason.
14+
/// </summary>
15+
UnknownError,
16+
17+
/// <summary>
18+
/// The data was entirely transferred. For WriteRead, the data for both the write and the read operations was entirely transferred.
19+
/// For this status code, the value of the <see cref="I2cTransferResult.BytesTransferred"/> member that the method returns is the same as the size of the buffer
20+
/// you specified when you called the method, or is equal to the sum of the sizes of two buffers that you specified for WriteRead.
21+
/// </summary>
22+
FullTransfer,
23+
24+
/// <summary>
25+
/// The transfer failed due to the clock being stretched for too long. Ensure the clock line is not being held low.
26+
/// </summary>
27+
ClockStretchTimeout,
28+
29+
/// <summary>
30+
/// The I2C device negatively acknowledged the data transfer before all of the data was transferred.
31+
/// For this status code, the value of the <see cref="I2cTransferResult.BytesTransferred"/> member that the method returns is the number of bytes actually transferred.
32+
/// For <see cref="I2cDevice.WriteRead"/>, the value is the sum of the number of bytes that the operation wrote and the number of bytes that the operation read.
33+
/// </summary>
34+
PartialTransfer,
35+
36+
/// <summary>
37+
/// The bus address was not acknowledged. For this status code, the value of the <see cref="I2cTransferResult.BytesTransferred"/> member that the method returns of the method is 0.
38+
/// </summary>
39+
SlaveAddressNotAcknowledged,
40+
}
41+
}

System.Device.I2c/Properties/AssemblyInfo.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,17 @@
1010
// General Information about an assembly is controlled through the following
1111
// set of attributes. Change these attribute values to modify the information
1212
// associated with an assembly.
13-
[assembly: AssemblyTitle("CSharp.BlankApplication")]
13+
[assembly: AssemblyTitle("nanoFramework System.Device.I2c")]
1414
[assembly: AssemblyDescription("")]
15-
[assembly: AssemblyConfiguration("")]
16-
[assembly: AssemblyCompany("")]
17-
[assembly: AssemblyProduct("CSharp.BlankApplication")]
15+
[assembly: AssemblyCompany(".NET nanoFramework contributors")]
16+
[assembly: AssemblyProduct(".NET nanoFramework System.Device.I2c")]
1817
[assembly: AssemblyCopyright("Copyright (c) .NET Foundation and Contributors")]
1918
[assembly: AssemblyTrademark("")]
2019
[assembly: AssemblyCulture("")]
2120

2221
////////////////////////////////////////////////////////////////
2322
// update this whenever the native assembly signature changes //
24-
[assembly: AssemblyNativeVersion("100.2.0.2")]
23+
[assembly: AssemblyNativeVersion("100.0.0.1")]
2524
////////////////////////////////////////////////////////////////
2625

2726
// Setting ComVisible to false makes the types in this assembly not visible

System.Device.I2c/System.Device.I2c.nfproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
</RootNamespace>
1616
<AssemblyName>System.Device.I2c</AssemblyName>
1717
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
18-
<!--<NF_IsCoreLibrary>True</NF_IsCoreLibrary>-->
18+
<NF_IsCoreLibrary>True</NF_IsCoreLibrary>
1919
<DocumentationFile>bin\$(Configuration)\System.Device.I2c.xml</DocumentationFile>
2020
</PropertyGroup>
2121
<PropertyGroup>
@@ -47,6 +47,8 @@
4747
<Compile Include="I2cBusSpeed.cs" />
4848
<Compile Include="I2cConnectionSettings.cs" />
4949
<Compile Include="I2cDevice.cs" />
50+
<Compile Include="I2cTransferResult.cs" />
51+
<Compile Include="I2cTransferStatus.cs" />
5052
<Compile Include="Properties\AssemblyInfo.cs" />
5153
</ItemGroup>
5254
<ItemGroup>

0 commit comments

Comments
 (0)