-
Notifications
You must be signed in to change notification settings - Fork 13
Add support for 4.2 inch b/w screen #17
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
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. |
932d92e to
51b27da
Compare
|
Thanks everyone for their input, I have tried to implement all the suggestions in this thread as display-specific code (unfortunately a bit of a hacky way, let me know if there's a better way), and can confirm that fast refresh now works in my screen. I do however get a border around the screen that slowly fades to back until it is cleared by the next partial refresh, so that's odd. I guess there's still more tinkering needed... |
… for 2.9 b/w screen
|
Tested also with the 2.9" B/W screen, still seems to work fine with the display-specific fixes. I tried to see if any of the additions would also work for the 2.9" screen, but they all break the screen in some way or another, so they are truely specific to the 4.2" screen. |
|
Added a bit more code specific to the 4.2 inch variant, based on the source code from here: https://github.com/WeActStudio/WeActStudio.EpaperModule/blob/master/Example/EpaperModuleTest_GD32F303/Epaper/epaper.c |
2c8f953 to
52a1204
Compare
|
Any news on this topic? Im planing to buy a 4.2 screen. Can I help in some way when I get it? |
|
Hey @avsaase! |


This adds support for the 4.2 inch b/w screen.
ToDo
References