-
Notifications
You must be signed in to change notification settings - Fork 48
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
More ergonomic opamp API, add lock and pga functionality #113
Conversation
Turns out I didn't need the unwrap after all (ff07d75) |
src/opamp.rs
Outdated
.vm_sel() | ||
.output() | ||
.opaintoen() | ||
.variant(OPAINTOEN_A::OutputPin) |
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.
Not sure if it would be worth it, but what if we had a trait with an associated const OPAINTOEN_A
that was implemented for external and InternalOutput types? Then would it be possible to unify this and fn follower below?
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.
Take a look at the other change I made on 13d4631 and let me know what you think. I'll play with the trait idea.
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.
Taking that one step further, what if all follower, pga, etc defaulted to internal only? Then the user could enable the output builder style. That would probably compose well with optional inverting inputs etc.
let opamp2 = opamp2.pga(gpioa.pa7) // <-- Noninverting
.inverting_input(..)
.output(..);
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 thought about that but I think complexity will increase a lot (e.g. we would need to store various configurations of outputs attached to the struct). I don't think that makes sense given the limited surface area of the API. I think that is probably the 'correct' way to do it though.
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.
what if we had a trait with an associated const OPAINTOEN_A that was implemented for external and InternalOutput types
I spent some time trying to get this working- I can't find a way to do it that preserves the compile-time checking of InternalOutput
for the ADC.
I tried using an associated type in the trait implementation (e.g. type output = InternalOutput;
, type output = PA<>
), but that doesn't work because the Rust compiler assumes the trait could be implemented in the future, resulting in a duplicate function definition error (long story short).
I'm just a user, but from what I have seen so far this looks great. I really like not having 6 different modules with their own types. I also like not having to use the Awesome :) |
For those interested, here's a branch where I'm working on adding the remaining Pga modes: It's a bit heavy handed right now (separate structs for each Pga variant), so I'm going to see if I can consolidate a bit (and test it!) before I put a PR up |
Ok I cleaned up the Pga implementation (a lot!), so I pulled it into this PR. I haven't tested all of this code on hardware yet (hoping to do that this weekend), but I'm feeling pretty good about the Pga implementation. |
src/opamp.rs
Outdated
/// Type of the associated vinm0 input. | ||
type vinm0; | ||
/// Type of the associated vinm1 input. | ||
type vinm1; |
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.
CI seems unhappy with these names.
What about something like this? :)
/// Type of the associated vinm0 input. | |
type vinm0; | |
/// Type of the associated vinm1 input. | |
type vinm1; | |
/// Type of the associated vinm0 input. | |
type Vinm0; | |
/// Type of the associated vinm1 input. | |
type Vinm1; |
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.
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.
Thanks a lot :)
Here's an attempt to improve the ergonomics of the opamp API. This PR also adds the remaining PGA modes.
Key changes:
Option<>
from the output interface, and instead implemented traits on the output pin directly, or a new typeInternalOutput
that represents the case where the opamp is directly connected to the ADC.Locked<_>
struct. Opamps can be moved from any of the implemented modes (Pga
,OpenLoop
,Follower
) into theLocked
state, at which point the lock bit is set and you cannot modify or disable the opamp (but you can pass it into the ADC, if appropriately configured)adc_op_pga
andadc_op_follower
were intended to work around limitations of the opamp (certain opamps can only operate in certain modes), but I can't see anything about that in the datasheet or reference manual. Maybe this is an artifact from copy-paste from another chip?Things I think are good:
Things I don't love
There's an unwrap in somedisable()
and alldisable_output()
functions. This is safe because those functions are only implemented on opamps that contain an output pin, but it relies on the module being implemented correctly.Let me know what you think! @usbalbin I know you worked on this code recently, so you may have opinions!