-
Notifications
You must be signed in to change notification settings - Fork 4
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
Add support for 4.2 inch screen #17
base: master
Are you sure you want to change the base?
Conversation
Thanks! I don't have this screen to test it because it seems to go in and out of stock on AliExpress. Do you have a lick where I can order one? I'll review this and your other PR later today. |
22f067a
to
ff64494
Compare
I got mine here, still seems to be in stock atm. |
Partial update doesn't seem to quite work right, I will have to do some more digging as to why. |
024a16c
to
932d92e
Compare
I found in the c driver for this display that this display seems to need other commands and data for fast partial refresh. Here you can see the commands. When changing the /// Start a fast refresh of the display using the current in-screen buffers.
///
/// If the display hasn't done a [`Self::full_refresh`] yet, it will do that first.
pub async fn fast_refresh(&mut self) -> Result<()> {
if !self.initial_full_refresh_done {
// There a bug here which causes the new image to overwrite the existing image which then
// fades out over several updates.
self.full_refresh().await?;
}
if !self.using_partial_mode {
self.command_with_data(command::WRITE_LUT, &lut::LUT_PARTIAL_UPDATE)
.await?;
self.using_partial_mode = true;
}
self.command_with_data(command::DISPLAY_UPDATE_CONTROL, &[0x00])
.await?;
self.data(&[0x00]).await?;
self.command_with_data(command::UPDATE_DISPLAY_CTRL2, &[flag::UNDOCUMENTED])
.await?;
self.command(command::MASTER_ACTIVATE).await?;
self.wait_until_idle().await;
Ok(())
} This would prob break the other displays but i think it's possible to make display specific code. diff --git a/src/driver.rs b/src/driver.rs
index 37ab26c..de25bd1 100644
--- a/src/driver.rs
+++ b/src/driver.rs
@@ -377,7 +377,10 @@ where
.await?;
self.using_partial_mode = true;
}
- self.command_with_data(command::UPDATE_DISPLAY_CTRL2, &[flag::UNDOCUMENTED])
+ self.command_with_data(command::DISPLAY_UPDATE_CONTROL, &[0x00])
+ .await?;
+ self.data(&[0x00]).await?;
+ self.command_with_data(command::UPDATE_DISPLAY_CTRL2, &[0xfc])
.await?;
self.command(command::MASTER_ACTIVATE).await?;
self.wait_until_idle().await; Snapchat-886308807.mp4 |
@capt41nkirk This looks promising. Seems that you are using an esp32 c3 as well. I struggle with clearing the display. |
you can find my code in this repo: the example is in the espc6 folder, though it is actually rewritten for c3. Still i have some issues with the coordinates i think. |
My White is not updating properly. Looks like white in the buffer is treaded like transparent and just black dots are set. IMG_4363.1.movYour code on my setup starting from a black screen ... |
Hello, I have one of these 4.2" displays and I'd be interested in this PR to land. Is there any testing I can help with? |
@patcher-ms you could clone my code from above and use the ESP32-C3 example if you have that chip to test whether this works (including the full update at beginning and partial fast refresh afterwards). |
So full refresh didi not work for me. If I run it twice with different (long) text I get a mess. Anyhow I stepped through the code comparing it with GxEPD2 and I fixed it for me with the following patch (full_update) that's shares some common stuff with your partial fix. diff --git a/src/driver.rs b/src/driver.rs
--- a/src/driver.rs (revision 932d92e5d22f017ed3f64ee6ea9316eefd4f8f80)
+++ b/src/driver.rs (date 1738971139965)
@@ -216,6 +216,10 @@
self.initial_full_refresh_done = true;
self.using_partial_mode = false;
+
+ self.command_with_data(command::DISPLAY_UPDATE_CONTROL, &[0x40, 0x00])
+ .await?;
+
self.command_with_data(command::UPDATE_DISPLAY_CTRL2, &[flag::DISPLAY_MODE_1])
.await?;
self.command(command::MASTER_ACTIVATE).await?; |
@marsjo thanks for the update. Your change doesn't break my display, so it seems this is the more general solution. I updated my fork accordingly. Now we need to rewrite the code to make the functions screen specific for general usage of the driver for all screen sizes. |
I do not have the others Display currently - thinking of ordering them. I dislike the partial_buffer approach - but I have to find out more about the code. |
@marsjo I find it strange that your 4.2 screen did not work before your code change in full_refresh but mine did. Maybe there are also other controller chips/revisions. I attach a pic of the backside, maybe you can spot some differences. |
I do not have the sticker and the text on the cable - but the rest looks equal. I added the command 21 (see SSD1683 page 28) telling the chip to bypass Red RAM content as 0 (do not paint) while using BW normally. During Initalisation the options are set to Normal for Red and Inverse for B/W so I have no clue how this should work if we do not set it. By the way DISPLAY_UPDATE_CONTROL expects two data values instead of self.command_with_data(command::DISPLAY_UPDATE_CONTROL, &[0x00])
.await?;
self.data(&[0x00]).await?; we should write: self.command_with_data(command::DISPLAY_UPDATE_CONTROL, &[0x00, 0x00])
.await?; I think I should read how fast_update is done because I read that it uses the Red Buffer in some way. BTW: Is there a easy way to get the current millis is esp-rs? |
Next question: I read more inside the code and I wondering why do we write to the Red and B/W Buffer after the refresh? /// Update the screen with the provided partial frame buffer at the given position using a fast refresh.
///
/// `x`, and `width` must be multiples of 8.
pub async fn fast_partial_update_from_buffer(
&mut self,
buffer: &[u8],
x: u32,
y: u32,
width: u32,
height: u32,
) -> Result<()> {
self.write_partial_bw_buffer(buffer, x, y, width, height)
.await?;
self.fast_refresh().await?;
self.write_partial_red_buffer(buffer, x, y, width, height)
.await?;
self.write_partial_bw_buffer(buffer, x, y, width, height)
.await?;
Ok(())
} This might make sense for the red_buffer because we store the old image in it to enhance fast_update. But why would we write the same information into the b/w Buffer again? Removing those two lines I can reduce the update time of the example from 1912ms to 877ms. |
This adds support for the 4.2 inch screen. Currently stacked ontop #14, until merged, see diff here: thedevleon/weact-studio-epd@feat/sleep_and_wakeup...thedevleon:weact-studio-epd:feat/4.2_support
ToDo
Reference
https://github.com/ZinggJM/GxEPD2/blob/master/src/gdey/GxEPD2_420_GDEY042T81.cpp