-
Notifications
You must be signed in to change notification settings - Fork 304
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
Pins re-factor for remote SPI support #459
Comments
All sounds pretty reasonable to me 👍
Rather than having all the unit-tests explicitly constructing MockPins, would it "make sense" to just have them constructing numbered pins, and then altering the Makefile so that 'make test' runs I guess if the allocating-of-pins to various interfaces (Pin/SPI/I2C) is being managed by Factory instances, maybe you could also have a method to tell the Factory to 'reserve' certain Pins? E.g. perhaps you have an addon board attached to some pins (managed by a different piece of software), and you want to tell GpioZero to never try allocating those pins. Not sure how that'd work with pigpiod and remote Pis though, so perhaps the 'reserved pins' should only be supported by strictly local pin implementations (rpigpio, rpio & nativepin) ? While you're messing about with Pins, is it worth thinking about #385 at the same time too, or is that an orthogonal problem?
Would this work? import os
os.environ['GPIOZERO_PIN_FACTORY'] = "mockpin"
from gpiozero import * |
That's more or less what I'm intending to do. Just to get the test suite going again (to make sure I haven't broken too much) I've just done a bulk replace of MockPin(n) with pin_factory.pin(n) for now, and after a few tweaks I got all the tests working again. Of course, I've just broken all the SPI tests now I'm shifting everything over to pin_factory.spi(**args). Ultimately I'll try to replace as much as I can with just straight pin references as that'll be much cleaner.
Good thought. I'm discovering having the factory instance makes the code much cleaner. No more messing around with
Actually I've got another private branch where I was working on fixing that. However, it's almost certainly broken with all these changes. I'm seriously considering merging it into here though, because my goal is to make this the last backwards incompatible change in pins (i.e. after this the goal is only to add to pins with stuff like I2C).
Yes, that will work - and I know because that's almost precisely what conftest.py now does :). However it's not "mockpin", but "mock". I dropped the pin suffix because firstly the factory isn't a pin instance anymore (so that'd be misleading), and secondly this means the factory label is now just the library name (like "rpio", "pigpio", "native", etc.) |
All looks good to me. Thanks Dave! |
No prob, given everyone sounds basically happy I'll press on. The SPI stuff's coming together right now (but the tests are all horribly broken). Might have something to push by tomorrow afternoon I think. |
Incidentally because this changes the names of the package entry points, when you want to test the PR that's eventually pushed you must run |
Does that mean this latest refactoring would still work when you add IO-expanders, etc. ? ;-) |
That's the plan.
Whether they form full blown factories that can be placed in pin_factory ... I'm not sure on that yet. The pin factory also contains the "pi_info" interface which really doesn't apply to expanders. Not wholly sure what to do about that yet so for now I've left it more or less as is (i.e. pi_info migrates to Factory, and that's about it). I might introduce a PiFactory sub-class (i.e. a factory specifically for pins on a Pi) which holds the pi_info interface. There's already a LocalFactory sub-class which more or less replaces LocalPin. However, I have planned for the concept that some factories may not be capable of constructing certain interfaces. I've added some custom exceptions for these cases and they appear in the base Factory class. Factories are even permitted to be incapable of constructing pins (imagine a chip which purely provides multiplexed I2C interfaces, but no GPIOs). |
Yup https://www.kickstarter.com/projects/land-boards/rpi-i2c-hub/description |
And presumably there's a separate Factory for each remote Pi that a pigpio instance might be talking to? |
Precisely. That's a bit different to how things are now (constructing pins individually if you want multiple hosts) but I think it's actually simpler: define the factories you need and then either construct pins from them directly or assign them as the current pin_factory while you construct devices. |
Okay, this is about to land. I've finally got all the tests working, the docs are building nicely and everything seems good. Now, it's a pretty gigantic patch so I'll lay out the story of what changes are in here working from the bottom up, so people can find their way around it. Obviously I won't merge this until some review's been done! A little warning up front: there's a contentious change in here that Ben and I discussed at PyConUK; more on that later! So, first let's quickly cover what doesn't change:
Now starting from the bottom let's work our way up:
Right ... contentious change time! One thing I didn't mention above is that pin reservation turned out to be quite tricky. In order to do pin reservation you need some means of uniquely identifying each pin in the system. "Easy!" says Dave and charges in by using the identify of each Pin object. Except that comes with a problem:
"Okay!" says Dave, "we need some other unique identifier for a pin that can exist independently of the Pin object itself". Cue long internal debate about what forms this could take (imagine much blackboard scribbling here):
So, slightly weirdly, pins have an
In future, this will likely become more complex as we add GPIO extenders. Pin representations don't change as far as users are concerned; Now the next issue reared its head... In several pin implementations, when we construct a pin, the only way to get it into a "known good" state is to set its function, and the function is often limited to input/output. Unfortunately, hardware SPI demands that its pins remain in "alternate function" mode in order to operate. Flip 'em to an input and things break. So, consider the scenario again:
Oh dear. So, whilst No, you know what: this is already way too long. Let's leave discussion of the stuff above for this ticket because I hope that despite some odd bits, it's all relatively uncontentious (albeit long). I'll open another ticket for the contentious change where we can chin-wag about it separately. |
Sorry! Dave's messing around with the pin implementations again. Hopefully the last time. The pin_factory is now really a factory object which can be asked to produce individual pins or pin-based interfaces like SPI (which can be supported properly via pigpio).
Sorry! Dave's messing around with the pin implementations again. Hopefully the last time. The pin_factory is now really a factory object which can be asked to produce individual pins or pin-based interfaces like SPI (which can be supported properly via pigpio).
Sorry! Dave's messing around with the pin implementations again. Hopefully the last time. The pin_factory is now really a factory object which can be asked to produce individual pins or pin-based interfaces like SPI (which can be supported properly via pigpio).
Sorry! Dave's messing around with the pin implementations again. Hopefully the last time. The pin_factory is now really a factory object which can be asked to produce individual pins or pin-based interfaces like SPI (which can be supported properly via pigpio).
Sorry! Dave's messing around with the pin implementations again. Hopefully the last time. The pin_factory is now really a factory object which can be asked to produce individual pins or pin-based interfaces like SPI (which can be supported properly via pigpio).
Fix #459 - properly support remote SPI with pigpio
This is turning out to be a pretty hefty PR, so I figured before I get too deep into it I should note down some of the goals of this to make sure everyone's happy with them. So, here's the goals:
Here's how I'm going about implementing this:
__new__
) and I don't fancy adding yet more class methods. The sensible thing to do here is to make an actual Factory instance with methods for returning a pin, an SPI interface, and probably in future an I2C interface (maybe 1-wire too eventually).Finally, this is what this means for end users:
Current state:
The basic coding work is done and works pretty well on a Pi. However, the vast majority of the test suite is quite broken because most references to MockPin (et al) need replacing with pin_factory (the test environment is configured by conftest prior to any attempt to import gpiozero to ensure it'll work on all platforms, sub-units will override pin_factory as required).
So, I anticipate this'll eventually be a mammoth patch, but the vast majority of it is going to be changes to the test suite (the actual coding work isn't that heavy - only really hits the pin implementations).
The text was updated successfully, but these errors were encountered: