Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modern code review #1263

Merged
merged 46 commits into from Nov 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
654dd9c
Code cleanup
richlander Nov 7, 2020
e737d2a
Update projects
richlander Nov 7, 2020
6391e20
Project updates
richlander Nov 7, 2020
d67de4e
Fix breaks
richlander Nov 7, 2020
0f4b3be
Update ExplorerHat project
richlander Nov 8, 2020
91bb426
Update Ft4222 project
richlander Nov 8, 2020
230e6f8
Update GoPiGo3
richlander Nov 8, 2020
4a78e44
Update GrovePi project
richlander Nov 8, 2020
4215804
Update a few more projects
richlander Nov 8, 2020
1b2f27d
More updates
richlander Nov 8, 2020
09751da
Update null checks
richlander Nov 8, 2020
2b17f8e
Fix ArgumentException usage
richlander Nov 9, 2020
104ebaa
Apply suggestions from code review
richlander Nov 9, 2020
f4bc1fe
Update src/devices/GoPiGo3/GoPiGo3.cs
richlander Nov 9, 2020
fa439a6
Update src/devices/Ina219/Ina219.cs
richlander Nov 9, 2020
17b91ad
Switch exception type
richlander Nov 9, 2020
f970412
Switch exception type
richlander Nov 9, 2020
2ce2a94
Update src/devices/Mcp3428/Mcp342x.cs
richlander Nov 9, 2020
f937b4f
Update src/devices/Mcp3xxx/Mcp3xxx.cs
richlander Nov 9, 2020
637af99
Update src/devices/Mcp9808/Mcp9808.cs
richlander Nov 9, 2020
fe3ee8d
Update src/devices/Mlx90614/Mlx90614.cs
richlander Nov 9, 2020
95c8eef
Update src/devices/Ssd13xx/Ssd13xx.cs
richlander Nov 9, 2020
9cce17c
Update src/devices/Tcs3472x/Tcs3472x.cs
richlander Nov 9, 2020
f57b77d
Update src/devices/Vl53L0X/Vl53L0X.cs
richlander Nov 9, 2020
9c85adf
Update src/devices/Ws28xx/Ws28xx.cs
richlander Nov 9, 2020
f09a6aa
Update src/devices/Hmc5883l/Hmc5883l.cs
richlander Nov 9, 2020
9d68e8c
Update src/devices/Mpr121/Mpr121.cs
richlander Nov 9, 2020
48fdd0e
Update src/devices/Mpu9250/Mpu6500.cs
richlander Nov 9, 2020
608ad92
Update src/devices/Nrf24l01/Nrf24l01.cs
richlander Nov 9, 2020
7d52dd4
Update src/devices/Pn5180/Pn5180.cs
richlander Nov 9, 2020
e9307ca
Update src/devices/Pn532/Pn532.cs
richlander Nov 9, 2020
14a3119
Update src/devices/Pn532/Pn532.cs
richlander Nov 9, 2020
f83e3e0
Update src/devices/RadioTransmitter/Devices/Kt0803/Kt0803.cs
richlander Nov 9, 2020
7621895
Update src/devices/RadioReceiver/Devices/Tea5767/Tea5767.cs
richlander Nov 9, 2020
54ddc83
Update src/devices/Rtc/Devices/Ds1307/Ds1307.cs
richlander Nov 9, 2020
4711f51
Update src/devices/Rtc/Devices/Ds3231/Ds3231.cs
richlander Nov 9, 2020
e6ea40f
Update src/devices/Rtc/Devices/Pcf8563/Pcf8563.cs
richlander Nov 9, 2020
b404013
Update src/devices/Seesaw/SeesawBase.cs
richlander Nov 9, 2020
28d1a52
Update src/devices/ShiftRegister/ShiftRegister.cs
richlander Nov 9, 2020
2714c15
Update src/devices/Shtc3/Shtc3.cs
richlander Nov 9, 2020
c537fa7
Update src/devices/Si7021/Si7021.cs
richlander Nov 9, 2020
3b8a52a
Update GoPiGo3.cs
richlander Nov 9, 2020
7969854
Update per feedback
richlander Nov 9, 2020
23bae6a
Add type in place of var
richlander Nov 9, 2020
6d6c639
Revert one switch expression to switch statement
richlander Nov 10, 2020
ee5140e
Add pragma for []?
richlander Nov 10, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
128 changes: 42 additions & 86 deletions src/devices/Ads1115/Ads1115.cs
Expand Up @@ -47,8 +47,8 @@ public class Ads1115 : IDisposable
/// <param name="measuringRange">Programmable Gain Amplifier</param>
/// <param name="dataRate">Data Rate</param>
/// <param name="deviceMode">Initial device mode</param>
public Ads1115(I2cDevice i2cDevice, InputMultiplexer inputMultiplexer = InputMultiplexer.AIN0, MeasuringRange measuringRange = MeasuringRange.FS4096, DataRate dataRate = DataRate.SPS128,
DeviceMode deviceMode = DeviceMode.Continuous)
public Ads1115(I2cDevice i2cDevice, InputMultiplexer inputMultiplexer = InputMultiplexer.AIN0, MeasuringRange measuringRange = MeasuringRange.FS4096,
DataRate dataRate = DataRate.SPS128, DeviceMode deviceMode = DeviceMode.Continuous)
{
_i2cDevice = i2cDevice ?? throw new ArgumentNullException(nameof(i2cDevice));
_inputMultiplexer = inputMultiplexer;
Expand All @@ -61,7 +61,6 @@ public class Ads1115 : IDisposable
_comparatorPolarity = ComparatorPolarity.Low;
_comparatorLatching = ComparatorLatching.NonLatching;
_comparatorQueue = ComparatorQueue.Disable;
_shouldDispose = false;

SetConfig();
DisableAlertReadyPin();
Expand All @@ -79,18 +78,18 @@ public class Ads1115 : IDisposable
/// <param name="dataRate">Data Rate</param>
/// <param name="deviceMode">Initial device mode</param>
public Ads1115(I2cDevice i2cDevice,
GpioController gpioController, int gpioInterruptPin, bool shouldDispose = true, InputMultiplexer inputMultiplexer = InputMultiplexer.AIN0, MeasuringRange measuringRange = MeasuringRange.FS4096, DataRate dataRate = DataRate.SPS128,
DeviceMode deviceMode = DeviceMode.Continuous)
GpioController? gpioController, int gpioInterruptPin, bool shouldDispose = true, InputMultiplexer inputMultiplexer = InputMultiplexer.AIN0, MeasuringRange measuringRange = MeasuringRange.FS4096,
DataRate dataRate = DataRate.SPS128, DeviceMode deviceMode = DeviceMode.Continuous)
: this(i2cDevice, inputMultiplexer, measuringRange, dataRate, deviceMode)
{
_gpioController = gpioController ?? throw new ArgumentNullException(nameof(gpioController));
if (gpioInterruptPin < 0 || gpioInterruptPin >= gpioController.PinCount)
_gpioController = gpioController ?? new GpioController();
if (gpioInterruptPin < 0 || gpioInterruptPin >= _gpioController.PinCount)
{
throw new ArgumentOutOfRangeException(nameof(gpioInterruptPin), $"The given GPIO Controller has no pin number {gpioInterruptPin}");
}

_gpioInterruptPin = gpioInterruptPin;
_shouldDispose = shouldDispose;
_shouldDispose = shouldDispose || gpioController is null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be cleaner to have an overload that didn't take a controller, and remove the shouldDispose from there? It seems weird this parameter is only used if a value is provided. Similar example is the HttpClient that takes a handler had the dispose boolean but the handler isn't nullable - only if you use the overload that doesn't take a handler is one instantiated and shouldDispose set to true:
https://github.com/dotnet/runtime/blob/master/src/libraries/System.Net.Http/src/System/Net/Http/HttpMessageInvoker.cs#L24-L28
https://github.com/dotnet/runtime/blob/master/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs#L130

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good feedback. That's something we could consider, but it gets complicated really quickly because of the interplay of GPIO and I2C or SPI. Some bindings have an overload for just GPIO and another for GPIO and I2C (or SPI) where GPIO is optional. It seems like optional parameters are a perfect match for this complexity. Also, this is really the only extra line that has to exist to allow it.

}

/// <summary>
Expand Down Expand Up @@ -164,11 +163,7 @@ public DeviceMode DeviceMode
/// Comparator mode.
/// Only relevant if the comparator trigger event is set up and is changed by <see cref="EnableComparator(short, short, ComparatorMode, ComparatorQueue)"/>.
/// </summary>
public ComparatorMode ComparatorMode
{
get;
private set;
}
public ComparatorMode ComparatorMode { get; private set; }

/// <summary>
/// Comparator polarity. Indicates whether the rising or the falling edge of the ALRT/RDY Pin is relevant.
Expand Down Expand Up @@ -208,13 +203,7 @@ public ComparatorLatching ComparatorLatching
/// Minimum number of samples exceeding the lower/upper threshold before the ALRT pin is asserted.
/// This can only be set with <see cref="EnableComparator(short, short, ComparatorMode, ComparatorQueue)"/>.
/// </summary>
public ComparatorQueue ComparatorQueue
{
get
{
return _comparatorQueue;
}
}
public ComparatorQueue ComparatorQueue => _comparatorQueue;

/// <summary>
/// This event fires when a new value is available (in conversion ready mode) or the comparator threshold is exceeded.
Expand Down Expand Up @@ -285,7 +274,7 @@ private void DisableAlertReadyPin()
(byte)Register.ADC_CONFIG_REG_HI_THRESH, 0x7F, 0xFF
};
_i2cDevice.Write(writeBuff);
if (_gpioController != null)
if (_gpioController is object)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at the risk of starting a war, I think is not null is more clear than is object. They generate the same code (is not null vs is object).

Adding @jaredpar to make sure dissenting opinions way in.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sorta figured it isn't using not null due to language version requirements for the repo.
But in general re is object vs is not null, this feels like something that is going to keep coming up as people are opinionated on this; there's no technical advantage either way, it's purely preference driven.
So tl;dr, 🍿 (Hi Jared :)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing that people are going to have to get used to seeing it both ways. People that are super in the weeds of C# like the language team might decide that is object is extremely clear to them and choose it in general. Other people working on their company LOB codebases might decide on is not null because it seems easier for Joe/Jane Developer to understand what's going on. Each team/codebase will choose what they feel is clear and understandable to them (and readers of the code), though what that means will vary in context.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no reason to new set the lang version explicitly imho:

<PropertyGroup>
   <LangVersion>8.0</LangVersion>
</PropertyGroup>

{
_gpioController.UnregisterCallbackForPinValueChangedEvent(_gpioInterruptPin, ConversionReadyCallback);
_gpioController.ClosePin(_gpioInterruptPin);
Expand Down Expand Up @@ -319,7 +308,7 @@ private void WriteComparatorRegisters(short loThreshold, short hiThreshold)
/// for interrupt handling.</exception>
public void EnableConversionReady()
{
if (_gpioController == null)
if (_gpioController is null)
{
throw new InvalidOperationException("Must have provided a GPIO Controller for interrupt handling.");
}
Expand Down Expand Up @@ -349,7 +338,7 @@ public void EnableConversionReady()

private void ConversionReadyCallback(object sender, PinValueChangedEventArgs pinValueChangedEventArgs)
{
if (AlertReadyAsserted != null)
if (AlertReadyAsserted is object)
{
AlertReadyAsserted();
}
Expand All @@ -368,10 +357,7 @@ private void ConversionReadyCallback(object sender, PinValueChangedEventArgs pin
/// <param name="queueLength">Minimum number of samples that must exceed the threshold to trigger the event</param>
/// <exception cref="InvalidOperationException">The GPIO Controller for the interrupt handler has not been set up</exception>
public void EnableComparator(ElectricPotential lowerValue, ElectricPotential upperValue, ComparatorMode mode,
ComparatorQueue queueLength)
{
EnableComparator(VoltageToRaw(lowerValue), VoltageToRaw(upperValue), mode, queueLength);
}
ComparatorQueue queueLength) => EnableComparator(VoltageToRaw(lowerValue), VoltageToRaw(upperValue), mode, queueLength);

/// <summary>
/// Enable comparator callback mode.
Expand All @@ -388,7 +374,7 @@ private void ConversionReadyCallback(object sender, PinValueChangedEventArgs pin
public void EnableComparator(short lowerValue, short upperValue, ComparatorMode mode,
ComparatorQueue queueLength)
{
if (_gpioController == null)
if (_gpioController is null)
{
throw new InvalidOperationException("GPIO Controller must have been provided in constructor for this operation to work");
}
Expand Down Expand Up @@ -444,7 +430,7 @@ private ushort ReadConfigRegister()
/// This method must only be called in powerdown mode, otherwise it would timeout, since the busy bit never changes.
/// Due to that, we always write the configuration first in power down mode and then enable the continuous bit.
/// </summary>
/// <exception cref="TimeoutException">A timeout occured waiting for the ADC to finish the conversion</exception>
/// <exception cref="TimeoutException">A timeout occurred waiting for the ADC to finish the conversion</exception>
private void WaitWhileBusy()
{
// In powerdown-mode, wait until the busy bit goes high
Expand Down Expand Up @@ -502,10 +488,7 @@ private short ReadRawInternal()
/// For performance reasons, it is advised to use this method if quick readings with different input channels are required,
/// instead of setting all the properties first and then calling <see cref="ReadRaw()"/>.
/// </remarks>
public short ReadRaw(InputMultiplexer inputMultiplexer)
{
return ReadRaw(inputMultiplexer, MeasuringRange, DataRate);
}
public short ReadRaw(InputMultiplexer inputMultiplexer) => ReadRaw(inputMultiplexer, MeasuringRange, DataRate);

/// <summary>
/// Reads the next raw value, first switching to the given input and ranges.
Expand Down Expand Up @@ -590,30 +573,16 @@ public short VoltageToRaw(ElectricPotential voltage)
/// <returns>An electric potential (voltage).</returns>
public ElectricPotential MaxVoltageFromMeasuringRange(MeasuringRange measuringRange)
{
double voltage;
switch (measuringRange)
{
case MeasuringRange.FS6144:
voltage = 6.144;
break;
case MeasuringRange.FS4096:
voltage = 4.096;
break;
case MeasuringRange.FS2048:
voltage = 2.048;
break;
case MeasuringRange.FS1024:
voltage = 1.024;
break;
case MeasuringRange.FS0512:
voltage = 0.512;
break;
case MeasuringRange.FS0256:
voltage = 0.256;
break;
default:
throw new ArgumentOutOfRangeException(nameof(measuringRange), "Unknown measuring range used");
}
double voltage = measuringRange switch
{
MeasuringRange.FS6144 => 6.144,
MeasuringRange.FS4096 => 4.096,
MeasuringRange.FS2048 => 2.048,
MeasuringRange.FS1024 => 1.024,
MeasuringRange.FS0512 => 0.512,
MeasuringRange.FS0256 => 0.256,
_ => throw new ArgumentOutOfRangeException(nameof(measuringRange), "Unknown measuring range used")
};

return ElectricPotential.FromVolts(voltage);
}
Expand All @@ -623,50 +592,37 @@ public ElectricPotential MaxVoltageFromMeasuringRange(MeasuringRange measuringRa
/// </summary>
/// <param name="dataRate">One of the <see cref="DataRate"/> enumeration members.</param>
/// <returns>A frequency, in Hertz</returns>
public double FrequencyFromDataRate(DataRate dataRate)
public double FrequencyFromDataRate(DataRate dataRate) => dataRate switch
{
switch (dataRate)
{
case DataRate.SPS008:
return 8.0;
case DataRate.SPS016:
return 16.0;
case DataRate.SPS032:
return 32.0;
case DataRate.SPS064:
return 64.0;
case DataRate.SPS128:
return 128.0;
case DataRate.SPS250:
return 250.0;
case DataRate.SPS475:
return 475.0;
case DataRate.SPS860:
return 860.0;
default:
throw new ArgumentOutOfRangeException(nameof(dataRate), "Unknown data rate used");
}
}
DataRate.SPS008 => 8.0,
DataRate.SPS016 => 16.0,
DataRate.SPS032 => 32.0,
DataRate.SPS064 => 64.0,
DataRate.SPS128 => 128.0,
DataRate.SPS250 => 250.0,
DataRate.SPS475 => 475.0,
DataRate.SPS860 => 860.0,
_ => throw new ArgumentOutOfRangeException(nameof(dataRate), "Unknown data rate used")
};

/// <summary>
/// Cleanup.
/// Failing to dispose this class, especially when callbacks are active, may lead to undefined behavior.
/// </summary>
public void Dispose()
{
if (_i2cDevice != null)
if (_i2cDevice is object)
{
DisableAlertReadyPin();
_i2cDevice?.Dispose();
_i2cDevice.Dispose();
_i2cDevice = null!;
}

if (_shouldDispose && _gpioController != null)
if (_shouldDispose)
{
_gpioController.Dispose();
_gpioController?.Dispose();
_gpioController = null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving the nulling of _gpioController here means that if we called the constructor like
new Ads1115(i2cDevice, gpioController, 1, false, ...) then we would still keep the reference to the pass-in gpioController unlike the old code. Is this an intended change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. It would be better the old way. I was conflating the call to dispose and the assignment to null as related operations. They are not. Thanks for catching this.

Filed an issue on that: #1272

}

_gpioController = null;
}
}
}
29 changes: 9 additions & 20 deletions src/devices/Adxl345/Adxl345.cs
Expand Up @@ -45,27 +45,16 @@ public class Adxl345 : IDisposable
/// <param name="gravityRange">Gravity Measurement Range</param>
public Adxl345(SpiDevice sensor, GravityRange gravityRange)
{
if (gravityRange == GravityRange.Range02)
_sensor = sensor ?? throw new ArgumentNullException(nameof(sensor));
_range = gravityRange switch
{
_range = 4;
}
else if (gravityRange == GravityRange.Range04)
{
_range = 8;
}
else if (gravityRange == GravityRange.Range08)
{
_range = 16;
}
else if (gravityRange == GravityRange.Range16)
{
_range = 32;
}

GravityRange.Range02 => 4,
GravityRange.Range04 => 8,
GravityRange.Range08 => 16,
GravityRange.Range16 => 32,
_ => 0
};
_gravityRangeByte = (byte)gravityRange;

_sensor = sensor;

Initialize();
}

Expand Down Expand Up @@ -119,7 +108,7 @@ private Vector3 ReadAcceleration()
/// </summary>
public void Dispose()
{
if (_sensor != null)
if (_sensor is object)
{
_sensor.Dispose();
_sensor = null!;
Expand Down
7 changes: 3 additions & 4 deletions src/devices/Adxl345/samples/Program.cs
Expand Up @@ -9,14 +9,13 @@

SpiConnectionSettings settings = new (0, 0)
{
ClockFrequency = Iot.Device.Adxl345.Adxl345.SpiClockFrequency,
Mode = Iot.Device.Adxl345.Adxl345.SpiMode
ClockFrequency = Adxl345.SpiClockFrequency,
Mode = Adxl345.SpiMode
};

using SpiDevice device = SpiDevice.Create(settings);

// set gravity measurement range ±4G
using Iot.Device.Adxl345.Adxl345 sensor = new Iot.Device.Adxl345.Adxl345(device, GravityRange.Range04);
using Adxl345 sensor = new Adxl345(device, GravityRange.Range04);
while (true)
{
// read data
Expand Down
32 changes: 16 additions & 16 deletions src/devices/Ags01db/Ags01db.cs
Expand Up @@ -18,17 +18,17 @@ public class Ags01db : IDisposable
private const byte CRC_INIT = 0xFF;
private I2cDevice _i2cDevice;

private int _lastMeasurment = 0;
private int _lastMeasurement = 0;

/// <summary>
/// ASG01DB VOC (Volatile Organic Compounds) Gas Concentration (ppm)
/// </summary>
public double Concentration { get => GetConcentration(); }
public double Concentration => GetConcentration();

/// <summary>
/// ASG01DB Version
/// </summary>
public byte Version { get => GetVersion(); }
public byte Version => GetVersion();

/// <summary>
/// ASG01DB Default I2C Address
Expand All @@ -41,16 +41,7 @@ public class Ags01db : IDisposable
/// <param name="i2cDevice">The I2C device used for communication.</param>
public Ags01db(I2cDevice i2cDevice)
{
_i2cDevice = i2cDevice;
}

/// <summary>
/// Cleanup
/// </summary>
public void Dispose()
{
_i2cDevice?.Dispose();
_i2cDevice = null!;
_i2cDevice = i2cDevice ?? throw new ArgumentNullException(nameof(i2cDevice));
}

/// <summary>
Expand All @@ -60,9 +51,9 @@ public void Dispose()
private double GetConcentration()
{
// The time of two measurements should be more than 2s.
while (Environment.TickCount - _lastMeasurment < 2000)
while (Environment.TickCount - _lastMeasurement < 2000)
{
Thread.Sleep(TimeSpan.FromMilliseconds(Environment.TickCount - _lastMeasurment));
Thread.Sleep(Environment.TickCount - _lastMeasurement);
}

// Details in the Datasheet P5
Expand All @@ -77,7 +68,7 @@ private double GetConcentration()
_i2cDevice.Write(writeBuff);
_i2cDevice.Read(readBuff);

_lastMeasurment = Environment.TickCount;
_lastMeasurement = Environment.TickCount;

// CRC check error
if (!CheckCrc8(readBuff.Slice(0, 2), 2, readBuff[2]))
Expand Down Expand Up @@ -154,5 +145,14 @@ private bool CheckCrc8(ReadOnlySpan<byte> data, int length, byte crc8)
return false;
}
}

/// <summary>
/// Cleanup
/// </summary>
public void Dispose()
{
_i2cDevice?.Dispose();
_i2cDevice = null!;
}
}
}