-
Notifications
You must be signed in to change notification settings - Fork 234
added dac #247
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
added dac #247
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @eldruin (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
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.
Thank you for this proposal!
As a reminder, implementations proving this are necessary before merge. See here.
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.
Sorry I forgot to mention the try_
prefix.
An additional concern is whether set_voltage
can be implemented/makes sense for every DAC.
@eldruin Thanks for pointing me in this direction. I was working on an example implementation for a multichannel DAC but got stuck on how to implement a .split method that would return one DAC instance for each channel. But that mostly has to do with my limited knowledge of no-std programminging in Rust. I could try to continue that too. There are a couple of things I'm not sure about. The set_voltage is not something all DACs can implement. Many DACs use an external reference to scale their output so the scaling factor for value to voltage is not known beforehand. And I'm not sure its that useful, in most applications the DAC output will be scaled to some other value using a voltage divider or opamp right after the input anyway so the user of this trait will have to add her own scaling anyway and I'm not sure if using floats for this is always a good idea. The set_enabled and disabled methods could be useful. But most DACs I've seen have more extensive power-down modes. And as this trait would represent a single channel for a multi channel DAC. How would this work if the DAC does not allow enabling/disabling single channels? My choice would be to keep this to the DAC driver specific implementation and only have a try_set_output. Also I would make the Value a generic parameter of the trait. I think that would be more consistent with how its done in similar embedded hal traits like here https://github.com/rust-embedded/embedded-hal/blob/master/src/blocking/serial.rs for example. |
hmm, it's probably worth considering in the context of the |
@mendelt Thank you for your input! |
In my mind this trait could also be used for multi channel dacs without change. The dac driver could implement a .split() method that returns a tuple of |
Ah, that makes sense, and I can't imagine a situation where you'd want to use the same dac with multiple word lenghts. |
Thank you! I was looking at using a RefCell too but was unsure if that would be the right solution. I think that means you cannot move dac-channels to an interrupt handler for example right? Or should that not be something a driver is concerned with? |
@mendelt: Maybe a proxy for DAC's in |
I am not sure how that would fit. I would need to play around with it. |
Implemented this for a multichannel DAC (8 channel AD5668) with a split method based on a RefCell like @eldruin suggested. https://github.com/mendelt/ad5668/tree/dac-hal |
Maybe we remove the enable part. On the two DACs I have experience with it's applicable (STM32's onboard DAC, and MCP4921), but if it's not universal, then probably not appropriate. What I'm also struggling with is arguments passing to it; eg |
Maybe I'm missing what you mean here. But isn't that part of the setup for a specific DAC? Dependencies like clocks or pins or i2c/spi busses etc can be passed to a specific DAC implementation in a constructor method specific to that DAC? There is no need to make that part of the DAC trait. |
I guess there's not much that can be extracted into a generic trait |
I switched the f303 impl to using infallible traits built into the struct, and added a pub trait SingleChannelDac {
/// Error type returned by DAC methods
type Error;
type Word;
/// Output a constant signal, given a bit word.
fn try_set_value(&mut self, value: Self::Word) -> Result<(), Self::Error>;
} |
Yeah, but I don't think that's a bad thing. It is a simple abstraction but useful. |
Done |
Looks like only half of the move of |
Works! I'll see if I can test this with real devices later this week. But there are no code changes so I'm pretty confident that works. And I don think thats really the point of these example implementations anyway. |
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.
Nice! I updated the stm32f3 impl above to reflect this new API too. Ie moved the other stuff into infallible, non-EH methods.
Could this be made to support multiple channels as well similarly to |
Not sure if I understand this correctly. The The only thing from the |
I was talking about making a pub trait Channel<DAC> {
type ID: Copy;
fn channel(&self) -> Self::ID;
}
pub trait Dac<DAC, Word, CHAN: Channel<ADC>> {
type Error;
fn try_set_value(&mut self, value: Word, channel: &mut CHAN) -> Result<(), Self::Error>;
}
pub trait SingleChannelDac {
type Error;
type Word;
fn try_set_value(&mut self, value: Self::Word) -> Result<(), Self::Error>;
} I am still thinking whether the |
Ah sorry, got it. You actually convinced me that an associated type would be a better fit here (and maybe in most places) I looked around and I don't see that many drivers, even for peripheral types that do support multiple word-lengths, implement it. I think most |
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 do you think @David-OConnor?
I haven't used a multi-channel DAC before, so can't say what makes the most sense. |
I like the extra flexibility, but I have some trouble imagining a use for this. There might be dacs that have a reduced precision low-power mode? Or support low precision fast operation? But I haven't encountered them. @eldruin just out of curiosity, for the multichannel example. What is the use of the Channel trait? Cant you just use a type parameter or associated type to determine how to select channels? I think the primary use case is to allow for the use of tuples to select channels in banks right? |
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.
Ok, this is almost good to go.
Just two missing things:
- Add an entry about this trait to the changelog
- Add this trait to the prelude
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.
Sorry I forgot about the squashing. Could you squash all these commits into one?
It would be rather confusing to look at all 12 commits about this trait in the history.
There is also a conflict in the changelog.
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.
Ok, almost there!
- There is still a conflict in the Changelog. Please rebase this branch to the master branch and resolve it.
- Also, could you name the commit something like "Added single-channel DAC trait"?
Thank you!
Done |
1 similar comment
Done |
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.
Thank you!
I suggested a last fix to the documentation. Could you accept it and squash everything into one commit again?
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.
Hmm, there is still a conflict in the changelog file.
Do you know how to fix it? IIRC I tried both ways - when it had the What should the Added section of the changelog look like? |
Ok that worked. Thanks! |
Oh, great! I must have made some mistake before. |
Thoughts? |
Is there an MCU HAL implementation of this trait somewhere? The PR I linked above was closed. |
"try_" |
I would wrap the I would not use it on any real projects in this state though, without |
After a discussion on Matrix and further consideration, I don't think DAC is appropriate for EH. |
Basic features only. Could get more complicated with triggers, multi-channel features etc, but for now, would prefer to keep it simple and general, to avoid becoming too provincial.