-
Notifications
You must be signed in to change notification settings - Fork 140
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
Initial support for Waveshare 2in13 v2 e-ink screen #51
Conversation
src/epd2in13_v2/mod.rs
Outdated
// 00 : normal | ||
// 01 : deep sleep mode 1 | ||
// 11 : deep sleep mode 2 | ||
self.cmd_with_data(spi, Command::DEEP_SLEEP_MODE, &[0x01])?; |
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 is the difference between these sleep modes?
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.
No clue yet, as I have not tried to understand this part yet :D
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've updated this part. There are 3 modes:
- 1 where access through MCU is alive including reading RAM and RAM content is kept.
- 1 where MCU/RAM access is not possible but RAM content is still kept
- 1 where no access is possible and RAM content is not kept.
I've added corresponding enum
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.
Do you know if this is also available on other epd from this newer generation?
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 think the controller are at least very close, but they have some subtle diff that makes them incompatible. At least where I've looked. It sure would be a good think to factor what can be factored... We would need to have the exact controller used for all displays and see how much they can share.
I know this one is close to 2in9 as command number are the same... But usually, sample code for init is different.
Everything else looks good from a first glance. |
Thanks for the comment. I'm still going from code to doc to try to understand how everything works. |
It's still missing some tests... I was willing to try to add something similar to https://github.com/eldruin/ds323x-rs/blob/master/tests/datetime.rs : using the Mock interface to check for expected SPI transfer for a given code sequence. If that's something you would be ok with, of course. Still new to rust, I'm trying to learn :) |
Is there a real SPI transfer with this new epd? The old ones were only able to write, but not able to read anything over SPI. |
I don't know yet. It looks like it's still only for writing even if it seems possible to read RAM/temp sensor (maybe waveshare removed this ?). But still, we could check that for a given code sequence, the MOSI part is correct. What do you think ? |
👍 Sounds good. |
b51c5fe
to
12bff67
Compare
Codecov Report
@@ Coverage Diff @@
## master #51 +/- ##
==========================================
- Coverage 30.77% 27.64% -3.13%
==========================================
Files 25 28 +3
Lines 1290 1653 +363
==========================================
+ Hits 397 457 +60
- Misses 893 1196 +303
Continue to review full report at Codecov.
|
27b8531
to
81171c4
Compare
I think the status is rather OK and may at least be enough for the review.
The RED RAM is used as a base for comparison (I guess) and should reflect what is currently on the screen. Having functions like To avoid people using this and wondering why the screen displays garbage, I've added an |
(side note: I've added a test similar to existing ones, but could not really test it. I've made all my tests using a tm4c123 board. I do have a raspi but don't have the setup to build/run/execute rust on it) |
Hmmmm, in fact, there's still an issue that I've not fixed yet. The visible (122) versus the controller size (128) of the screen. I need to take care of this before this gets merged. |
Thanks for all your work.
You can just reference a testproject of yours with the tm4c123 instead if you want. |
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.
Overall it looks really good I just had a lot of small questions since this seems to be a slightly different architecture.
background_color = White | ||
)) | ||
.draw(display); | ||
} |
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.
Are you showing anything new/special for this display? Else I would just keep the old examples and wouldn't add a new one for better visibility.
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.
Maybe an example how to use the different partial refresh mode of the display would be a great example and would best also added to the docs for the epd2in13
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 was trying to show what kind of animation you could do using the partial refresh. It's not simply quicker that the full refresh, it is quick enough for simple animation and does not flicker at all.
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.
That sounds great then 👍 Maybe add a small comment to the spinning animation. Would also be great to add a small gif/link to a video of this on the frontpage/readme if you have 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.
I've added few comments in the example. Let me know if that's enough.
I could also do the GIF sure, but I would like to first have the code ACKed :)
src/epd2in13_v2/mod.rs
Outdated
Ok(()) | ||
} | ||
|
||
/// Beware that this does not work well with the screen partial refresh feature. |
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.
is there any use in this function for this display since the screen partial refresh feature should be better? And did you add the function for the screen partial refresh feature somewhere?
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.
Maybe we could also use compile_error!("Your message") to make a compile time error here if it is always better to use the different method
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 there is, as the partial refresh should draw more power I think (the analog and clock are left enabled) and it's not perfect. Some artifacts may be visible after several partial refreshes. In some case, it can be great, for other no so great. In my simple app, I'll use a full refresh for some events (eg. clock changing) and use partial for showing animation for alarms.
self.cmd_with_data(spi, Command::WRITE_VCOM_REGISTER, &[vcom.0]) | ||
} | ||
|
||
fn set_gate_driving_voltage( |
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.
Some short description for these helper functions would be nice, since they are different from the normal/old control functions.
So the problem is that you need to do it twice because the display is showing multiple colors? I thought it was only a black/white display (version 2.13 (A) v2, but you have a B or C one? Or what is the red ram doing? (I also asked the same question in the review already, so just answer it whereever you see it first :-D ) Your pr looks really good, just add a few more testcases (mainly for all the bitfields), adding the display to the readme and a few other small things are missing (see the review). |
Ok, will do that ! |
Clearly, my doc is not enough :). The controller is using black and red names as it's meant for multicolor displays (1 RAM for Black/White, 1 RAM for Red). IIUC, this is also used for the partial refresh feature to store the «base» image (the one that should be displayed on the screen), hence the name in the code here. I don't know if it's a controller (but undocumented) feature, or simply a trick used by the display to implement its partial refresh. |
Hey @caemor , I was hacking again the driver for 2in13, and I have a small issue I don't know how to best handle it, maybe you already had some similar issue ? The display has 122 visible pixels, but everything being grouped by bytes, it means that some bytes only contain 2 bits of info, the other 6 are discarded/not visible. When the display is not rotated, it's «easy», the display could be declared as 250*122 and the buffer should be rounded up. But when the screen is rotated, the origin starts at 128, which is not visible. |
I've changed a bit how the rotation works and how buffer is allocated:
|
(screen handling moved to #52 to reduce this PR) |
7245707
to
a3ede7e
Compare
I think #52 looks good. What is your current progress here? |
fee7e72
to
4863836
Compare
I'm just starting to hack this again after a small pause. It's mostly ok as the last real problem was the screen size that will be handled by #52. I've used the bit_field crate as you requested, hope it's correct for you ? Then I have to sort out the example/test. You mentioned I could link my external project, but it's still in early phase as I'm still getting all the parts together (and the screen was the last one). There should hopefully be a new keyboard project using this crate, so that would make 2 users. Would that work ? I can still use the same example as the other and leave out the very specific parts (partial refresh). |
d1cbbe5
to
ed86b04
Compare
I've done a last refresh on this one. It's still based on #52. The «only» part that may be perfectible is the handling of |
While investigating the coverage regression, I've found some small issues... So I'll iterate this and #52 at least one more time :) |
Ok, I guess I need to add some test with «dumb» init values to have good coverage... But this will be very weak as there's no way I can really test the resulting state... I can have the code executed in a test and have codecov happy. It's true that the code is more or less dead. |
Don't worry too much about the code coverage. Its just too see if there was a big regression or big improvement somewhere :-D |
Error handling is currently a bit complicated, since e.g. the SPI::Error (write error) depends on the device the library is running on to be compatible to each. This situation will hopefully be improved by rust-embedded/embedded-hal#229 soon |
This initial support covers both the full (slow) update of the display and the partial (fast) update.
Do you think anything is missing? It looks good to me. |
I think everything is here. I've squashed all WIP commits :) |
Thanks for your great work! :-) Do you you already have a specific use case for this display? |
I'm working on an alarm clock for kids with colored light instead of buzzer (pink => stay in bed, green => ok to get up, …). It's still WIP, but starts to work. A colleague will use it in a DIY keyboard. You want to have pointers to the projects when they are mature enough? |
Sure that would be great |
This is an early version for 2.13 v2 e-Ink screen. It's an early version but is already working. I'll continue to test/polish it, but feel free to already give comments, I'm still new to this.