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

Pin class should be used in generic implementations like SoftwarePwmChannel or SoftwareSpi #2047

Open
krwq opened this issue Feb 27, 2023 · 9 comments
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation Priority:2 Work that is important, but not critical for the release

Comments

@krwq
Copy link
Member

krwq commented Feb 27, 2023

We've recently added Pin class but classes like SoftwarePwmChannel or SoftwareSpi use pin directly. I think we should provide constructor overloads for at minimum those two classes.

Other candidates:

  • LCD Character screen
  • GPIO extenders
@krwq krwq added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Feb 27, 2023
@ghost ghost added the untriaged label Feb 27, 2023
@Ellerbach
Copy link
Member

What would be the advantage of doing this? And what would be the typical usage?
For me, the Software PWM and Software SPI have different usage than the Gpio Pin. So not really sure of the value for mixing the Gpio Pin with the software PWM and SPI.

@krwq
Copy link
Member Author

krwq commented Feb 27, 2023

to me anything which uses multiple GPIO pins as input is candidate for using GpioPin. What are your thoughts on what qualifies?

@pgrawehr
Copy link
Contributor

You mean we should at a ctor taking a list of Gpiopins instead of numbers? I agree, as this was one of the use cases why we added the GpioPin.

@Ellerbach
Copy link
Member

So how would you see the API? Any example of high level implementation? I fully get the extender, that's all ok and done for that, I'm bit more skeptical for PWM and SPI.

@krwq
Copy link
Member Author

krwq commented Feb 28, 2023

For SPI you could add another constructor like this (and similar for PWM):

public SoftwareSpi(GpioPin clk, GpioPin sdi, GpioPin sdo, GpioPin cs = null, SpiConnectionSettings? settings = null, bool shouldDispose = true);
// existing one:
public SoftwareSpi(int clk, int sdi, int sdo, int cs = -1, SpiConnectionSettings? settings = null, GpioController? gpioController = null, bool shouldDispose = true);

that would allow to easily use pins from different controllers. For SPI especially that makes sense for CS pin which you might want to use extender for.

PWM is more arguable since it only takes 1 pin.

@Ellerbach
Copy link
Member

Ho yes, definitely. We can add constructors for this and adjust the bindings. What we have to keep in mind is that the default behavior for GpioPin is to open it. Good news is that we can change the mode when needed.
We do already have bindings on nanoFramework which does accept either Controller and pin number either GpioPin. It does require to change a bit of conde inside to operate GpioPin directly rather then the controller. But it's quite straight forward.

@joperezr
Copy link
Member

joperezr commented Mar 1, 2023

Just throwing out a thought here, but what about creating a special subclass of GpioController which takes in GpioPin instances, and "acts" as a controller but in reallity it is really just forwarding the reads and writes to the GpioPins? The advantage of a model like this, is that you would no longer need to essentially add hundreds of new constructors to the types in this library, and instead just use the existinc controller that already takes in a custom GpioController. The usage I have in mind would be something like:

GpioPin clk_GpioPin, sdi_GpioPin, sdo_GpioPin;

var virtualGpioController = new VirtualGpioController();
virtualGpioController.AddVirtualPin(clk_GpioPin, pinNumber: 16);
virtualGpioController.AddVirtualPin(sdi_GpioPin, pinNumber: 17);
virtualGpioController.AddVirtualPin(sdo_GpioPin, pinNumber: 18);

var SoftwareSpi = new SoftwareSpi(16, 17, 18, virtualGpioController); // With this, we can now still use GpioPin objects we have and use existing constructors.

The VirtualGpioController would literally only be a collection of GpioPins and would just forward the calls made to it like:

public override void Write(int pinNumber, PinValue value) => _gpioPins[pinNumber].Write(value);

OpenPin override would likely just be a no-op, since we know that virtual pins passed in to this controller would already be open.

Thoughts?

@krwq
Copy link
Member Author

krwq commented Mar 2, 2023

While I agree this is a solution it likely feels overly complex from user perspective. We could also create a source gen which does reverse (so we always take pins but constructor which takes numbers could be generated).

Improving on suggested idea, I'd rather go with something like this so you don't have to know the virtual numbers:

var vc = new VirtualGpioController();
var SoftwareSpi = new SoftwareSpi(vc.GetVirtualPinNumber(clk_GpioPin), vc.GetVirtualPinNumber(sdi_GpioPin), vc.GetVirtualPinNumber(sdo_GpioPin), vc);

but still, I'd rather have us direct support for popular devices

@krwq krwq added the Priority:2 Work that is important, but not critical for the release label Mar 9, 2023
@ghost ghost removed the untriaged label Mar 9, 2023
@Ellerbach
Copy link
Member

[Triage] Having both approaches with a VirtualGpioController makes sense to cover different scenarios. If anyone have time for a proposal and draft PR, feel free to assign yourself!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation Priority:2 Work that is important, but not critical for the release
Projects
None yet
Development

No branches or pull requests

4 participants