Skip to content

Commit dbe5f78

Browse files
committed
resets I2C pins back to original state, not blindly to input
1 parent 1b491be commit dbe5f78

File tree

1 file changed

+32
-7
lines changed

1 file changed

+32
-7
lines changed

Raspberry.IO.InterIntegratedCircuit/I2cDriver.cs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ public class I2cDriver : IDisposable
2121

2222
private readonly ProcessorPin sdaPin;
2323
private readonly ProcessorPin sclPin;
24+
private readonly bool wasSdaPinSet;
25+
private readonly bool wasSclPinSet;
2426

2527
private readonly IntPtr gpioAddress;
2628
private readonly IntPtr bscAddress;
@@ -72,8 +74,9 @@ public I2cDriver(ProcessorPin sdaPin, ProcessorPin sclPin)
7274
throw new InvalidOperationException("Unable to access device memory");
7375

7476
// Set the I2C pins to the Alt 0 function to enable I2C access on them
75-
SetPinMode((uint) (int) sdaPin, Interop.BCM2835_GPIO_FSEL_ALT0); // SDA
76-
SetPinMode((uint) (int) sclPin, Interop.BCM2835_GPIO_FSEL_ALT0); // SCL
77+
// remembers if the values were actually changed to clear them or not upon dispose
78+
wasSdaPinSet = SetPinMode((uint)(int)sdaPin, Interop.BCM2835_GPIO_FSEL_ALT0); // SDA
79+
wasSclPinSet = SetPinMode((uint) (int) sclPin, Interop.BCM2835_GPIO_FSEL_ALT0); // SCL
7780

7881
// Read the clock divider register
7982
var dividerAddress = bscAddress + (int) Interop.BCM2835_BSC_DIV;
@@ -89,9 +92,15 @@ public I2cDriver(ProcessorPin sdaPin, ProcessorPin sclPin)
8992
/// </summary>
9093
public void Dispose()
9194
{
92-
// Set all the I2C/BSC1 pins back to input
93-
SetPinMode((uint) (int) sdaPin, Interop.BCM2835_GPIO_FSEL_INPT); // SDA
94-
SetPinMode((uint) (int) sclPin, Interop.BCM2835_GPIO_FSEL_INPT); // SCL
95+
// Set all the I2C/BSC1 pins back to original values if changed
96+
if (wasSdaPinSet)
97+
{
98+
SetPinMode((uint)(int)sdaPin, Interop.BCM2835_GPIO_FSEL_INPT); // SDA
99+
}
100+
if (wasSclPinSet)
101+
{
102+
SetPinMode((uint)(int)sclPin, Interop.BCM2835_GPIO_FSEL_INPT); // SCL
103+
}
95104

96105
Interop.munmap(gpioAddress, Interop.BCM2835_BLOCK_SIZE);
97106
Interop.munmap(bscAddress, Interop.BCM2835_BLOCK_SIZE);
@@ -369,15 +378,31 @@ private static uint GetBscBase(ProcessorPin sdaPin, ProcessorPin sclPin)
369378
}
370379
}
371380

372-
private void SetPinMode(uint pin, uint mode)
381+
/// <summary>
382+
///
383+
/// </summary>
384+
/// <param name="pin"></param>
385+
/// <param name="mode"></param>
386+
/// <returns>True when value was changed, false otherwise.</returns>
387+
private bool SetPinMode(uint pin, uint mode)
373388
{
374389
// Function selects are 10 pins per 32 bit word, 3 bits per pin
375390
var paddr = gpioAddress + (int) (Interop.BCM2835_GPFSEL0 + 4*(pin/10));
376391
var shift = (pin%10)*3;
377392
var mask = Interop.BCM2835_GPIO_FSEL_MASK << (int) shift;
378393
var value = mode << (int) shift;
379394

380-
WriteUInt32Mask(paddr, value, mask);
395+
var existing = ReadUInt32(paddr) & mask;
396+
if (existing != value)
397+
{
398+
//Console.WriteLine($"existing is {x} masked:{x & mask} vs mask:{mask} value:{value}");
399+
WriteUInt32Mask(paddr, value, mask);
400+
return true;
401+
}
402+
else
403+
{
404+
return false;
405+
}
381406
}
382407

383408
private static void WriteUInt32Mask(IntPtr address, uint value, uint mask)

0 commit comments

Comments
 (0)