-
Notifications
You must be signed in to change notification settings - Fork 190
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
Last pixel per line does not change on display #326
Comments
Hi, good catch on that last pixel, looks like a bug indeed! I'm in the process of adding test cases for any new changes, which we can hopefully run in the Wokwi emulator. So your example cases are a good starting point for that :) |
I think I found another issue: the whole framebuffer is shifted by one row with respect to the actual pixels of the display. My guess is that the two render tasks and the framebuffer are somehow not aligned (its hard for me to understand the complex approach with the line queue, render tasks and so on). With a modified version of "epd_clear_area_cycles" (i.e., not using the framebuffer but the LCD driver only) I can make ALL pixels of the display black, even those in the first row. Testcase:
|
Great work. I would like to see that issues are so well documented and explained like this. That’s the way to do it. |
I'm also on holidays now. Maybe I have some time around mid of September to find the root cause of the issue.
|
I'm still working on this project but focusing on other aspects. I will go back to this issue in the next few weeks |
After some detailed analysis, I found a possible solution for the bug "whole framebuffer is shifted by one row": The vbp is set in function epd_lcd_start_frame in output_lcd/lcd_drive.c. The third parameter of lcd_ll_set_vertical_timing is the vbp. So line 656 of https://github.com/vroland/epdiy/blob/main/src/output_lcd/lcd_driver.c should be: With the original setting vbp=1 and a modified epd_clear not clearing ALL rows but only the actual rows of the display, epd_clear will have the same problem not changing the first row of the display. Here is a PDF-file with much more details of my analysis: If interested, I can also upload the data captured with the mixed-signal oscilloscope. |
Could you please check this and let me know how to modify it so that it can work properly on epdiy? |
Hi,
I think there is a bug in function 'epd_hl_update_area' in file 'highlevel.c' for updating the back framebuffer.
Basically, the last pixel/byte per line is NOT copied from front to back framebuffer.
Consequently, the last pixel per line does NOT change on the display/screen.
This effect (last pixel per line does NOT change) started me to investigate the mechanism with front and back frame buffers and updating the back frame buffer.
Relevant lines highlevel.c:
155: diff_area.x = 0;
156: diff_area.y = 0;
157: diff_area.width = epd_width();
158: diff_area.height = epd_height();
159:
160: int buf_width = epd_width();
161:
162: for (int l = diff_area.y; l < diff_area.y + diff_area.height; l++) {
163: if (state->dirty_lines[l] > 0) {
164: uint8_t* lfb = state->front_fb + buf_width / 2 * l;
165: uint8_t* lbb = state->back_fb + buf_width / 2 * l;
166:
167: int x = diff_area.x;
168: int x_last = diff_area.x + diff_area.width - 1;
169:
170: if (x % 2) {
171: (lbb + x / 2) = ((lfb + x / 2) & 0xF0) | ((lbb + x / 2) & 0x0F);
172: x += 1;
173: }
174:
175: if (x_last % 2) {
176: (lbb + x_last / 2) = ((lfb + x_last / 2) & 0x0F) | ((lbb + x_last / 2) & 0xF0);
177: x_last -= 1;
178: }
179:
180: memcpy(lbb + (x / 2), lfb + (x / 2), (x_last - x) / 2);
181: }
182: }
######### Proposals #########
My proposals are:
By the way, instead of using the modulo-operator (%) for detecting even/odd, I would use the binary-and (&).
I.e., instead of 'if (x % 2)' I would use 'if( x & 2 )'.
The modulo-operator usually needs a multiplication, a division and a subtraction, i.e., three assembly instructions.
The binary-and will be one assembly instruction.
However, I suspect that the compiler also knows about this optimization and will replace 'x % 2' by 'x & 2'.
Another question:
Lines 136ff (and also 155ff) are resetting 'diff_area' to the whole area of the framebuffer for drawing the front framebuffer and updating the back framebuffer.
Why not using 'diff_area' here as returned by 'epd_difference_image_cropped' in line 121?
######### Investigation #########
I investigated the update of the back framebuffer as follows, using just one line with 8 pixels.
x: coordinate.
front, back: color values of pixels in front and back frame buffer.
addr: address of frame buffer byte.
frame buffer: lower 4 bits: even pixel (x=0,2,4), upper 4 bits: odd pixels (x=1,3,5).
Case A: All 8 pixels differ in front and back frame buffer:
x 0 1 2 3 4 5 6 7
front 0 0 | 0 0 | 0 0 | 0 0
back 15 15 | 15 15 | 15 15 | 15 15
addr 0 | 1 | 2 | 3
x_first = 0 (even)
x_last = 7 (odd)
N_byte = (x_last-x_first+1)/2 = (7-0+1)/2 = 4
addr_start = x_first/2 = 0
--> copy 4 bytes from front to back starting at address 0
Case B: Upper 7 pixels differ in front and back frame buffer:
x 0 1 2 3 4 5 6 7
front 15 0 | 0 0 | 0 0 | 0 0
back 15 15 | 15 15 | 15 15 | 15 15
addr 0 | 1 | 2 | 3
x_first = 1
--> copy upper 4 bits from front to back at addr x_first/2=0, and x_first ++ (x_first = 2)
x_last = 7
N_byte = (x_last-x_first+1)/2 = (7-2+1)/2 = 3
addr_start = x_first/2 = 1
--> copy 3 bytes from front to back starting at address 1
Case C: Lower 7 pixels differ in front and back frame buffer:
x 0 1 2 3 4 5 6 7
front 0 0 | 0 0 | 0 0 | 0 15
back 15 15 | 15 15 | 15 15 | 15 15
addr 0 | 1 | 2 | 3
x_first = 0
x_last = 6
--> copy lower 4 bits from front to back at addr x_last/2=3, and x_last --, x_last = 5
N_byte = (x_last-x_first+1)/2 = (5-0+1)/2 = 3
addr_start = x_first/2 = 0
--> copy 3 bytes from front to back starting at address 0
The text was updated successfully, but these errors were encountered: