Skip to content

Commit

Permalink
Possible fix for display glitches (CS timing for display could be wro…
Browse files Browse the repository at this point in the history
…ng two frames after app processing takes too long)
  • Loading branch information
patrickdowling committed Apr 8, 2020
1 parent cee19cc commit 3dbaab1
Showing 1 changed file with 25 additions and 7 deletions.
32 changes: 25 additions & 7 deletions software/o_c_REV/src/drivers/SH1106_128x64_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#ifdef DMA_PAGE_TRANSFER
#include <DMAChannel.h>
static DMAChannel page_dma;
static bool page_dma_active = false;
#endif
#ifndef SPI_SR_RXCTR
#define SPI_SR_RXCTR 0XF0
Expand Down Expand Up @@ -127,13 +128,29 @@ void SH1106_128x64_Driver::Init() {
/*static*/
void SH1106_128x64_Driver::Flush() {
#ifdef DMA_PAGE_TRANSFER
// Assume DMA transfer has completed, else we're doomed
digitalWriteFast(OLED_CS, OLED_CS_INACTIVE); // U8G_ESC_CS(0)
page_dma.clearComplete();
page_dma.disable();
// DmaSpi.h::post_finishCurrentTransfer_impl
SPI0_RSER = 0;
SPI0_SR = 0xFF0F0000;
// Famous last words: "Assume DMA transfer has completed, else we're doomed"
// Because it turns out there are conditions(*) where the timing is shifted
// such that it hasn't completed here, which causes weird display glitches
// from which there's no recovery.
//
// (*) If app processing in frame N takes too long, the next frame starts
// late; this leaves less time for frame N+1, and in N+2 the display CS line
// would be pulled high too soon. Why this effect is more pronounced with
// gcc >= 5.4.1 is a different mystery.

if (page_dma_active) {
while (!page_dma.complete()) { }
while (0 != (SPI0_SR & 0x0000f000)); // SPIx_SR TXCTR
while (!(SPI0_SR & SPI_SR_TCF));
page_dma_active = false;

digitalWriteFast(OLED_CS, OLED_CS_INACTIVE); // U8G_ESC_CS(0)
page_dma.clearComplete();
page_dma.disable();
// DmaSpi.h::post_finishCurrentTransfer_impl
SPI0_RSER = 0;
SPI0_SR = 0xFF0F0000;
}
#endif
}

Expand Down Expand Up @@ -174,6 +191,7 @@ void SH1106_128x64_Driver::SendPage(uint_fast8_t index, const uint8_t *data) {

page_dma.sourceBuffer(data, kPageSize);
page_dma.enable(); // go
page_dma_active = true;
#else
SPI_send(data, kPageSize);
digitalWriteFast(OLED_CS, OLED_CS_INACTIVE); // U8G_ESC_CS(0)
Expand Down

0 comments on commit 3dbaab1

Please sign in to comment.