-
Notifications
You must be signed in to change notification settings - Fork 72
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
Restructure crate to simplify usage/contributing #150
Conversation
1430289
to
be2c756
Compare
src/i2c_builder.rs
Outdated
} | ||
} | ||
|
||
impl I2CDIBuilder { |
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.
To be fair, if you're transitioning away from the main builders, maybe this could get some love as well. This struct is just 2 constructors - one with a default address and one with a specific one.
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.
Good shout. I've changed it to a struct with static methods. There's an argument to make them free functions in a module, but it should be better now either way.
where | ||
SIZE: DisplaySize, | ||
{ | ||
buffer: GenericArray<u8, SIZE::BufferSize>, |
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.
Time for const generics, maybe?
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.
Yes definitely! I decided I want to do them in another PR to keep this one a little shorter.
I'm not very familiar with this crate and this is only based on the initial comment: Did you consider multiple constructors instead of having to pass a mode object to let raw = Ssd1306::new( // or new_raw
interface,
DisplaySize128x64,
DisplayRotation::Rotate0,
);
let terminal = Ssd1306::new_terminal(
interface,
DisplaySize128x64,
DisplayRotation::Rotate0,
);
let graphics = Ssd1306::new_graphics(
interface,
DisplaySize128x64,
DisplayRotation::Rotate0,
); This wouldn't be scalable to lots of modes, but for three modes it might be easier to use. And you could still have a |
I did consider that, but decided to go with a single constructor and a mode argument. I'm not sure if there are any benefits between these two approaches, but if there's a drawback to mine I've missed please let me know. Otherwise, I think I'm going to leave it as is. |
No, it probably is just personal preference. But if I try to dig deep this would be the only objective advantage I can come up with (so feel free to just ignore it): The constructors are easier to discover by using code completion, while the values that can be used for the You did write that you modeled the code based on the types states in the HAL crates. How about removing the mode from If you want to keep the current solution I would suggest to change the order of the |
3573adb
to
7e03ca8
Compare
7e03ca8
to
dfb1e88
Compare
I've just pushed a commit which updates the initialisation to the following: let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
.into_buffered_graphics_mode(); (plus |
I like it. Is there a way to get rid of the separate |
I did think about that. I left it as a separate method to give some flexibility to the user if they wanted to init the display in another place (e.g. an RTIC interrupt on device wakeup) but that might be too contrived and it's a better idea to initialise the display inside |
Maybe mode and display initialization should be separated from each other. Like this: If directly initializing the display in |
Methods like |
Sweet! |
That's a good idea. I'll write that up and see what it looks like.
That was a deliberate choice I described in the PR description:
Personally I think this is ok, although there may be some methods that could be moved to |
OK, sorry I had missed to comment in the PR description. IMO using Is there a way to force a full flush to restore the image to the buffer content after |
Here are some random comments/questions about the
As I said these are just some things I noticed and are I wanted to leave them as a comment to give some outside perspective on the API. There might be good reasons for the current implementation I simply don't know about. |
cfce91b
to
cc790ee
Compare
cc790ee
to
37de04c
Compare
One more thing I noticed: |
And the column part of |
But perhaps it would be better to use |
The basic mode could also use a |
I was taking a look at moving the init around and realised it results in two let mut display = Ssd1306::new(interface, DisplaySize72x40, DisplayRotation::Rotate0)
.unwrap()
.into_buffered_graphics_mode()
.unwrap(); Which is quite cumbersome IMO, so maybe it's a better idea to add
Thanks for looking this over. Most of this is old stuff and inconsistencies that should be fixed indeed. Responding in order:
Hm, maybe there was a historic reason for this but I don't recall. @therealprof can you remember? Either way, I've pushed a commit to allow them to be used in any mode which I can revert if it's incorrect. |
OK, but should it be limited to SPI? |
Or: |
Regarding |
I've made a couple of different attempts at the init API now and either they don't work or I'm not happy with them. This crate has seen a lot of downloads, and I haven't come across people having issues forgetting to call This crate doesn't have the highest quality docs for sure, but this PR was originally focussed on the structure of the code more than anything else. |
OK.
Sorry for all the off topic comments. |
Not a problem! You brought up some good points which I've added in, so thank you for those :) |
Hi! Thank you for helping out with SSD1306 development! Please:
master
if you're not already up to dateCHANGELOG.md
entry in the Unreleased section under the appropriate heading (Added, Fixed, Changed, etc)rustfmt
on the project withcargo fmt --all
- CI will not pass without this stepPR description
This PR heavily refactors the crate structure. It does away with the builder, now requiring the passing in of all 4 config params. It also changes how modes work; instead of wrapping
Properties
in various other structs, it now has variousimpl
blocks on theSsd1301
struct with different modes in the type params. IMO this makes the code a lot cleaner whilst still allowing switching between modes easily.The code structure is a lot more approachable now. The "entry point"
Ssd1306
struct is a good jumping off point for contributors. Previously, there was a bunch ofProperties
and*Mode
stuff to dig through, without a clear structure.I'm interested to hear peoples' thoughts on the changes here.
One thing we miss in terms of type safety is a particular mode still allows raw
draw()
calls on the display. This allows e.g. drawing stuff with embedded-graphics inGraphicsMode
, but also allows blatting whatever you've drawn by writing garbage to the display withdisplay.draw(&[0xab; 1024])
whilst in the same mode. This was a deliberate choice to give users the freedom to do "in-band" stuff in whatever mode they're in, but with an escape hatch to do naughtier things if required.The
noise_i2c
example demonstrates a "raw" mode:GraphicsMode
andTerminalMode
look similar: