Closed ghost closed 3 years ago
Looks good, unfortunately nothing stands out that might be wrong.
If the bug might be something related to subrectangle diffing, you could try to diagnose/workaround by trying what happens if you enable one of the config items
https://github.com/juj/fbcp-ili9341/blob/0b46b04f1d05a5f5088e750bfde28b2099b8da7d/config.h#L102
or
https://github.com/juj/fbcp-ili9341/blob/0b46b04f1d05a5f5088e750bfde28b2099b8da7d/config.h#L111
by removing the comments //
in front of those configs. (Only remove one of them at a time, they are mutually exclusive)
You are right about the diff.
With #define UPDATE_FRAMES_IN_SINGLE_RECTANGULAR_DIFF
I have the same trouble in one block.
With #define UPDATE_FRAMES_WITHOUT_DIFFING
, I have no shifting, just the cursor
I will make a simpler program, just a square changing color.
Could you give me some hint to debug it ?
One way to debug is to uncomment https://github.com/juj/fbcp-ili9341/blob/0b46b04f1d05a5f5088e750bfde28b2099b8da7d/spi.cpp#L18 to dump all the written bytes to the display. The SET_CURSOR_X/Y and pixel write commands are defined at https://github.com/juj/fbcp-ili9341/blob/0b46b04f1d05a5f5088e750bfde28b2099b8da7d/ssd1351.h#L16-L18
Perhaps the coordinate locations to update get sent wrong or similar in the bad updates.
Google search suggests setterm --cursor off might hide the cursor.
Thanks for hints.
So I make a simple test. A square at pos 0,0, size 50x50 and it change of color every second.
I let the initialisation and then I launch my program.
This is the output for 4 changes :
75 117
00 0
7F 127
75 117
7F 127
7F 127
75 117
00 0
7F 127
75 117
0E 14
7F 127
75 117
7F 127
7F 127
75 117
00 0
7F 127
75 117
7F 127
7F 127
75 117
00 0
7F 127
75 117
7F 127
7F 127
I am surprised to not see any 0x15 command.
I have make the test with and without #define DISPLAY_WRITE_PIXELS_CMD_DOES_NOT_RESET_WRITE_CURSOR
I make another test, I start it after a reboot so the screen display the console
After initialisation, I have this, we can see the console refresh the screen (0,2) to (0,127)
75 117
02 2
7F 127
15 21
00 0
7F 127
75 117
7F 127
7F 127
I launch my test, we can see the DISPLAY_SET_CURSOR_X is sent only one time, and the DISPLAY_SET_CURSOR_Y is sent for each change. Is there a way to force the DISPLAY_SET_CURSOR_X ?
75 117
00 0
7F 127
75 117
7F 127
7F 127
75 117
00 0
7F 127
15 21
00 0
3F 63
75 117
7F 127
7F 127
75 117
00 0
7F 127
75 117
7F 127
7F 127
75 117
00 0
7F 127
75 117
7F 127
7F 127
75 117
00 0
7F 127
75 117
7F 127
7F 127
75 117
00 0
7F 127
75 117
7F 127
7F 127
I am surprised to not see any 0x15 command.
Oh hmm, it looks like that debug #define needs DMA to be disabled, otherwise it will not print out the writes that go out via DMA (by default large writes go via DMA, and short writes via CPU, for fastest performance/best bus utilization). So re-run with DMA disabled to see the debug prints for pixel writes as well.
I launch my test, we can see the DISPLAY_SET_CURSOR_X is sent only one time, and the DISPLAY_SET_CURSOR_Y is sent for each change. Is there a way to force the DISPLAY_SET_CURSOR_X ?
The default driver behavior is to only update the cursors when needed, to avoid sending excessive bytes if the cursor coordinates do not change from one task to the next. fbcp-ili9341.cpp keeps track of the current write cursor position and write window that the display hardware should be at. It is possible that the bug is related to quirks/discrepancies between how the display hardware actually updates the cursor, and how fbcp-ili9341.cpp is tracking it. (That is what the different #defines DISPLAY_WRITE_PIXELS_CMD_DOES_NOT_RESET_WRITE_CURSOR
and MUST_SEND_FULL_CURSOR_WINDOW
are about - different displays behave subtly differently with respect to how the write cursor updates after commands)
To make fbcp-ili9341 drop tracking of the write cursors and windows altogether, but instead always before each task it would reset the window for the task (even if it thinks it would be redundant to do so), you can try something like the following:
diff --git a/fbcp-ili9341.cpp b/fbcp-ili9341.cpp
index a7d324f..8bb0b51 100644
--- a/fbcp-ili9341.cpp
+++ b/fbcp-ili9341.cpp
@@ -395,7 +395,10 @@ int main()
++i->size;
}
#endif
- // Update the write cursor if needed
+ // Before each pixel write, update the write cursor to the subrectangle of the specified pixel write task
+ QUEUE_SET_WRITE_WINDOW_TASK(DISPLAY_SET_CURSOR_X, displayXOffset + i->x, displayXOffset + i->endX - 1);
+ QUEUE_SET_WRITE_WINDOW_TASK(DISPLAY_SET_CURSOR_Y, displayYOffset + i->y, displayYOffset + gpuFrameHeight - 1);
+/*
#ifndef DISPLAY_WRITE_PIXELS_CMD_DOES_NOT_RESET_WRITE_CURSOR
if (spiY != i->y)
#endif
@@ -458,7 +461,7 @@ int main()
}
#endif
}
-
+*/
// Submit the span pixels
SPITask *task = AllocTask(i->size*SPI_BYTESPERPIXEL);
task->cmd = DISPLAY_WRITE_PIXELS;
(did not test this in practice, but should be something like that)
Closing out old issues.
Hello,
I need help for my project.
I try your framebuffer but I have some trouble.
I use a Raspberry Pi zero wh and a ssd1351 OLED 128x128
It work but sometimes the updated zone is shifted. And at the bottom something erase the line (cursor may be)
This is my config
cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DSSD1351=ON -DGPIO_TFT_DATA_CONTROL=24 -DGPIO_TFT_RESET_PIN=25 -DSPI_BUS_CLOCK_DIVISOR=12 -DSTATISTICS=OFF ..
This is the trace :
bcm_host_get_peripheral_address: 0x20000000, bcm_host_get_peripheral_size: 33554432, bcm_host_get_sdram_address: 0x40000000 BCM core speed: current: 400000000hz, max turbo: 400000000hz. SPI CDIV: 12, SPI max frequency: 33333333hz Allocated DMA channel 7 Allocated DMA channel 1 Enabling DMA channels Tx:7 and Rx:1 DMA hardware register file is at ptr: 0xb4b99000, using DMA TX channel: 7 and DMA RX channel: 1 DMA hardware TX channel register file is at ptr: 0xb4b99700, DMA RX channel register file is at ptr: 0xb4b99100 Resetting DMA channels for use DMA all set up Initializing display Resetting display at reset GPIO pin 25 InitSPI done Relevant source display area size with overscan cropped away: 128x128. Source GPU display is 128x128. Output SPI display is 128x128 with a drawable area of 128x128. Applying scaling factor horiz=1.00x & vert=1.00x, xOffset: 0, yOffset: 0, scaledWidth: 128, scaledHeight: 128 Creating dispmanX resource of size 128x128 (aspect ratio=1.000000). GPU grab rectangle is offset x=0,y=0, size w=128xh=128, aspect ratio=1.000000 All initialized, now running main loop...
This is my change in code :
`
define DISPLAY_NATIVE_WIDTH 128
define DISPLAY_NATIVE_HEIGHT 128
`
And the initialisation :
`
BEGIN_SPI_COMMUNICATION(); { SPI_TRANSFER(0xFD/Set Command Lock/, 0x12); SPI_TRANSFER(0xFD/Set Command Lock/, 0xB1); SPI_TRANSFER(0xAE/Sleep Mode On (Display OFF)/);
// Some voltage settings from the spec sheet to try out, although power on defaults seem to work fine as well: SPI_TRANSFER(0xB1/Set Phase Length/, 0x32/Phase1=0, Phase2=4/); //SSD1351_CMD_PRECHARGE SPI_TRANSFER(0xBE/Set VCOMH Voltage/, 0x05); //SSD1351_CMD_VCOMH SPI_TRANSFER(0xB4/Set Segment Low Voltage/, 0xA0, 0xB5, 0x55); //SSD1351_CMD_SETVSL SPI_TRANSFER(0xB6/Set Second Precharge Period/, 0x01/1 DCLK/); //SSD1351_CMD_PRECHARGE2
} `