-
Notifications
You must be signed in to change notification settings - Fork 28
Add more settings to SPI, and possibly add a Get-SPIDevice #54
base: master
Are you sure you want to change the base?
Conversation
var settings = new SpiConnectionSettings(this.BusId, this.ChipSelectLine) | ||
{ | ||
ClockFrequency = this.Frequency, | ||
DataBitLength = this.DataBitLength, | ||
Mode = this.Mode, | ||
DataFlow = this.DataFlow, | ||
ChipSelectLineActiveState = this.ChipSelectLineActiveState | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be concerned about overwriting defaults here if they aren't specified via the cmdlet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should be concerned because if those fields are not specified, they will have their defaults (0 for int, etc), which already happens with our current version. DataBitLength wasn't specified, hence it was always 0, etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should Not rely on types' default values.
For defaults we should use values common for SPI communication, so use/copy-paste the defaults from .NET code.
For example, in normal SPI communications default DataBitLength=8
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally agree. I was relying on the defaults because from what I saw they seemed to be the .NET defaults. Checking again, I was wrong. I was probably checking the wrong file .
Leaving the SpiSettings here for further reference
internal SpiDevice device = null; | ||
public int BusId { get; set; } | ||
|
||
public int ChipSelectLine { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these properties be public settable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've followed the same implementation as we have for I2C (here).
From my understanding, it will depend on what we want to do:
What should happen if the user changed their hardware from busId 0 to 1, or the ChipSelectLine? Should he create a new device? Or should we allow to change the busId and ChipSelectLine?
If we want to bind a device to a busId and ChipSelectLine, this should not be settable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
High level thinking is that these properties here are for information only
/ aka readlonly. If people want to use another set of settings, they need to construct another SPIDevice using Get-SPIDevice
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to clarify, this means that all properties should be readonly
, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you consider readonly struct for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to clarify, this means that all properties should be
readonly
, correct?
Correct.
Do you consider readonly struct for this?
This seems alright.
{ | ||
this.BusId = 0; | ||
this.ChipSelectLine = 0; | ||
this.Frequency = 500_000; // 500 KHz default speed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
defaults for other properties also have to be set here. They can be taken from .NET's SpiDevice
code.
public PinValue ChipSelectLineActiveState { get; set; } | ||
|
||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)] | ||
public SwitchParameter Raw { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like this is not used anywhere so can be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't understand from GH interface what property you are referring to. The Raw?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes; Raw
.
ChipSelectLineActiveState = this.ChipSelectLineActiveState | ||
}; | ||
|
||
SpiDevice spiDevice = SpiDevice.Create(settings); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should return our SPIDevice
wrapper that has public property of .NET's SpiDevice
. This way .NET's SpiDevice
object is accessible and can be used for scenarios like neopixels in this PR.
using System.Device.Gpio; | ||
using System.Device.Spi; | ||
|
||
public class SPIData : SPIDevice |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SPIData
should Not inherit from SPIDevice
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just have another SPIDevice
-type property
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not familiar with best practices for such cases. Why shouldn't it inherit from SPIDevice
? I've leveraged from inheritance because SPIData has all the properties that SPIDevice has, plus the Data and Response. Also, because an SPIData requires an SPIDevice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is very tempting to inherit SPIData
from SPIDevice
, but semantically the data object is not a subclass of a device object. Inheriting one from another usually brings problems down the road.
For same reason I2CDeviceRegisterData
does not inherit from I2CDevice
but rather has a property of this type that exposes device configuration data (as well as device object).
internal SpiDevice device = null; | ||
public int BusId { get; set; } | ||
|
||
public int ChipSelectLine { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
High level thinking is that these properties here are for information only
/ aka readlonly. If people want to use another set of settings, they need to construct another SPIDevice using Get-SPIDevice
.
|
||
public class SPIDevice | ||
{ | ||
internal SpiDevice device = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a problem if this class just holds 2 public properties:
public SpiDevice device;
public SpiConnectionSettings connectionSettings;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with this, but it would make sense to "expand" the connectionSettings when they are being displayed, like overriding the ToString
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can probably be done in a type format file for class SPIDevice
.
I also don't have a bug problem with overriding ToString
.
var settings = new SpiConnectionSettings(this.BusId, this.ChipSelectLine) | ||
{ | ||
ClockFrequency = this.Frequency, | ||
DataBitLength = this.DataBitLength, | ||
Mode = this.Mode, | ||
DataFlow = this.DataFlow, | ||
ChipSelectLineActiveState = this.ChipSelectLineActiveState | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should Not rely on types' default values.
For defaults we should use values common for SPI communication, so use/copy-paste the defaults from .NET code.
For example, in normal SPI communications default DataBitLength=8
.
settings.ClockFrequency = this.Frequency; | ||
|
||
using(var spiDevice = SpiDevice.Create(settings)) | ||
var settings = new SpiConnectionSettings(this.BusId, this.ChipSelectLine) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Constructing SpiConnectionSettings
and SPIDevice
can be moved from this cmdlet to Get-SPIDevice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This cmdlet can just take SPIDevice
object instead of all settings parameters.
Also, a general comment: using |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
general comments regarding feedback. Leaving it here to check later
public PinValue ChipSelectLineActiveState { get; set; } | ||
|
||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)] | ||
public SwitchParameter Raw { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't understand from GH interface what property you are referring to. The Raw?
using System.Device.Gpio; | ||
using System.Device.Spi; | ||
|
||
public class SPIData : SPIDevice |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not familiar with best practices for such cases. Why shouldn't it inherit from SPIDevice
? I've leveraged from inheritance because SPIData has all the properties that SPIDevice has, plus the Data and Response. Also, because an SPIData requires an SPIDevice
|
||
public class SPIDevice | ||
{ | ||
internal SpiDevice device = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with this, but it would make sense to "expand" the connectionSettings when they are being displayed, like overriding the ToString
This is an initial commit so that we can discuss if such changes can make sense.
This comes in sequence of issue #53. In my case, I have the neopixels which I can use to test the SPI, basing my implementation on dotnet IoT binding sample for the WS2812b.
Why a Get-SPIDevice - For this binding, they are passing the SPI device as a parameter (which was one of the reasons why I've decided to try an implementation of a Get-SPIDevice). It also seems, as I've pointed on the issue, that "this seems that the SPI device could be created once and used many times", which would make more sense than creating a device for each time we send some data.
Why more settings - Again, basing my implementation on their sample, there were some settings that seemed to be mandatory for it to work properly. Because it seems they are not mandatory, they can be created with default values.
Here's an example: