Repository navigation
Add generalised spi driver for clockless LEDs - #112
Conversation
This addresses ahdinosaur#12 The implementation is currently pretty long winded for what it actually does (to my taste anyway). Most of this is due to hoops we're having to jump through to calculate buffer sizes at compile time (See ahdinosaur#107) Documentation is still to come
|
@ahdinosaur it would be great if you could let me know if this on the right track before I finish it off by adding documentation |
|
And I managed to completely fail to mention that I explained the motivation behind this in #12 (comment) |
ahdinosaur
left a comment
There was a problem hiding this comment.
Hi, thank you for this! 💜
Overall this looks great. I feel this definitely matches the vibes of the existing Blinksy code. I like your thinking in #12 (comment), thank you for sharing. I also feel like you "get" Blinksy, which gives me a good feeling.
I wouldn't worry about how many lines this adds. Yes there's some boilerplate, but I think that's okay.
I had a few nitpick comments, sorry, you can do with that as you want. 🤷♀️
| > { | ||
| spi: Spi, | ||
| freq_hz: Freq, | ||
| _led: PhantomData<Led>, |
There was a problem hiding this comment.
I don't usually _ the PhantomData (e.g. https://github.com/ahdinosaur/blinksy/blob/main/blinksy/src/control.rs#L245 ), but also it doesn't really matter.
| use crate::driver::ClocklessSpiAsync; | ||
| use crate::markers::{Async, Blocking}; | ||
|
|
||
| pub struct ClocklessSpiBuilder< |
There was a problem hiding this comment.
Good to see that you understood my builder pattern! 👍
It might be a lot of code, but it's mostly just boilerplate so I don't mind.
| Led, | ||
| SpiWord, | ||
| Freq, | ||
| Dm, |
There was a problem hiding this comment.
Is this what I called Exec? https://github.com/ahdinosaur/blinksy/blob/main/blinksy/src/control.rs#L249. Might be best to be consistent.
There was a problem hiding this comment.
Ohh, Dm comes from the esp-hal crate and how they handle this same situation. Yeah I'd be keen to be consistent with Blinksy, even if I do use Dm here: https://github.com/ahdinosaur/blinksy/blob/main/esp/blinksy-esp/src/rmt.rs#L129
| Led: ClocklessLed, | ||
| { | ||
| pub fn build(self) -> ClocklessSpi<BUFFER_SIZE, PULSE_SIZE, Led, Spi, SpiWord> { | ||
| assert!(BUFFER_SIZE > 0, "set buffer_size before calling build"); |
| use bitvec::{array::BitArray, order::Msb0, slice::BitSlice}; | ||
| use core::marker::PhantomData; | ||
|
|
||
| pub const fn freq_hz_to_duration_ns(freq_hz: u32) -> u32 { |
There was a problem hiding this comment.
Generally I like to order exports in a file like a house's intimacy gradient: most public at the top, most private at the bottom. These are all public, but I reckon the helpers should go at the bottom.
There was a problem hiding this comment.
Also 🤷♀️ , this file is more a collection of related things, so not a clear entrance. Feel free to ignore me.
There was a problem hiding this comment.
But also, do these functions need to be pub? Why not pub(crate)?
| duration_ns_to_freq_hz(max_clock_period_ns) | ||
| } | ||
|
|
||
| fn encode_spi_buffer< |
| .with_dma(p.DMA_CH0) | ||
| .with_buffers(dma_rx_buf, dma_tx_buf) | ||
| .into_async(); | ||
| let writer = ClocklessSpiBuilder::default() |
Also put more public stuff at the top of the file
|
Thanks @ahdinosaur for the feedback. All good suggestions. I've hopefully addressed them and added some documentation. Looks like I've broken CI. ugh. |
|
I keep getting caught out by this. Keep forgetting that code in docs gets run. Silly me. |
|
@ahdinosaur hopefully good for you to look over again now |
ahdinosaur
left a comment
There was a problem hiding this comment.
This looks great, thanks!
Minor docs feedback. 📝
| use bitvec::{array::BitArray, order::Msb0, slice::BitSlice}; | ||
| use core::marker::PhantomData; | ||
|
|
||
| /// Represents the timing (in number of SPI bits) to encode zero, one and reset LED signals |
There was a problem hiding this comment.
Definitely not my natural writing style but I'm happy to oblige ;-)
| /// | ||
| /// # Type Arguments | ||
| /// | ||
| /// - `Led` - The LED protocol implementation (must implement ClocklessLed) |
There was a problem hiding this comment.
Can this (and the next lines) link to the trait(s)?
| categories.workspace = true | ||
|
|
||
| [dependencies] | ||
| # radium 0.7 is a dependency of the latest released version of bitvec which breaks on esp32. So using an unreleased |
There was a problem hiding this comment.
We won't be able to publish a new crate version until this is resolved. Although I haven't been publishing new crate versions lately, but that's on me.
There was a problem hiding this comment.
This was a bit of show-stopper I think because it doesn't look like we could depend on a bitvec release for that fix getting done anytime soon. It's annoying.
Anyway, I've rejigged things to not depend on bitvec. It does tidy up the public interfaces just a tiny amount too even though what's under the hood is now more messy.
|
@ahdinosaur hopefully ready for another look over |
|
I keep thinking I'm done and then I find a bug I hadn't spotted before. See the last commit 96c13f1 |
|
Merged, thanks @mlandauer ! 🎉 |
|
Thank you @ahdinosaur! |
This addresses #12
The implementation is currently pretty long winded for what it actually does (to my taste anyway). Most of this is due to hoops we're having to jump through to calculate buffer sizes at compile time (See #107)
Documentation is still to come but I thought showing this to you earlier rather than later was probably a good idea!
I haven't changed anything to make it easier to build the examples (there are 2 now) in blinksy-esp. Happy to add that if it makes sense. The new example isn't actually building against blinksy-esp but rather is building against blinksy but is esp specific. If there's a better place to put that example...
I'm somewhat surprised at how large this PR has become. It certainly was not my intention. I don't like the way the blocking and async code is duplicated and I don't like that there are two buffer sizes that have to be calculated. The builder makes it slightly less messy.
The usage of the new api goes something like this: