mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-25 17:42:48 +00:00
make eink screen look nicer
This commit is contained in:
parent
4db0c4a563
commit
649a120fe0
@ -54,8 +54,10 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl)
|
|||||||
// FIXME quick hack to limit drawing to a very slow rate
|
// FIXME quick hack to limit drawing to a very slow rate
|
||||||
uint32_t lastDrawMsec;
|
uint32_t lastDrawMsec;
|
||||||
|
|
||||||
// Write the buffer to the display memory
|
/**
|
||||||
void EInkDisplay::display(void)
|
* Force a display update if we haven't drawn within the specified msecLimit
|
||||||
|
*/
|
||||||
|
bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||||
{
|
{
|
||||||
// No need to grab this lock because we are on our own SPI bus
|
// No need to grab this lock because we are on our own SPI bus
|
||||||
// concurrency::LockGuard g(spiLock);
|
// concurrency::LockGuard g(spiLock);
|
||||||
@ -63,7 +65,7 @@ void EInkDisplay::display(void)
|
|||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
uint32_t sinceLast = now - lastDrawMsec;
|
uint32_t sinceLast = now - lastDrawMsec;
|
||||||
|
|
||||||
if (framePtr && (sinceLast > 60 * 1000 || lastDrawMsec == 0)) {
|
if (framePtr && (sinceLast > msecLimit || lastDrawMsec == 0)) {
|
||||||
lastDrawMsec = now;
|
lastDrawMsec = now;
|
||||||
|
|
||||||
// FIXME - only draw bits have changed (use backbuf similar to the other displays)
|
// FIXME - only draw bits have changed (use backbuf similar to the other displays)
|
||||||
@ -84,11 +86,26 @@ void EInkDisplay::display(void)
|
|||||||
updateDisplay(); // Send image to display and refresh
|
updateDisplay(); // Send image to display and refresh
|
||||||
DEBUG_MSG("done\n");
|
DEBUG_MSG("done\n");
|
||||||
|
|
||||||
// Put screen to sleep to save power
|
// Put screen to sleep to save power
|
||||||
ePaper.Sleep();
|
ePaper.Sleep();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// DEBUG_MSG("Skipping eink display\n");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write the buffer to the display memory
|
||||||
|
void EInkDisplay::display(void)
|
||||||
|
{
|
||||||
|
// We don't allow regular 'dumb' display() calls to draw on eink until we've shown
|
||||||
|
// at least one forceDisplay() keyframe. This prevents flashing when we should the critical
|
||||||
|
// bootscreen (that we want to look nice)
|
||||||
|
if (lastDrawMsec)
|
||||||
|
if (forceDisplay(slowUpdateMsec)) // Show the first screen a few seconds after boot, then slower
|
||||||
|
slowUpdateMsec = 5 * 60 * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
// Send a command to the display (low level function)
|
// Send a command to the display (low level function)
|
||||||
void EInkDisplay::sendCommand(uint8_t com)
|
void EInkDisplay::sendCommand(uint8_t com)
|
||||||
{
|
{
|
||||||
|
@ -14,15 +14,26 @@
|
|||||||
*/
|
*/
|
||||||
class EInkDisplay : public OLEDDisplay
|
class EInkDisplay : public OLEDDisplay
|
||||||
{
|
{
|
||||||
|
/// How often should we update the display, at first we do an update 5 secs after boot,
|
||||||
|
/// thereafter we do once per 5 minutes
|
||||||
|
uint32_t slowUpdateMsec = 5 * 1000;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* constructor
|
/* constructor
|
||||||
FIXME - the parameters are not used, just a temporary hack to keep working like the old displays
|
FIXME - the parameters are not used, just a temporary hack to keep working like the old displays
|
||||||
*/
|
*/
|
||||||
EInkDisplay(uint8_t address, int sda, int scl);
|
EInkDisplay(uint8_t address, int sda, int scl);
|
||||||
|
|
||||||
// Write the buffer to the display memory
|
// Write the buffer to the display memory (for eink we only do this occasionally)
|
||||||
virtual void display(void);
|
virtual void display(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force a display update if we haven't drawn within the specified msecLimit
|
||||||
|
*
|
||||||
|
* @return true if we did draw the screen
|
||||||
|
*/
|
||||||
|
bool forceDisplay(uint32_t msecLimit = 2000);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// the header size of the buffer used, e.g. for the SPI command header
|
// the header size of the buffer used, e.g. for the SPI command header
|
||||||
virtual int getBufferOffset(void) { return 0; }
|
virtual int getBufferOffset(void) { return 0; }
|
||||||
@ -33,3 +44,5 @@ class EInkDisplay : public OLEDDisplay
|
|||||||
// Connect to the display
|
// Connect to the display
|
||||||
virtual bool connect();
|
virtual bool connect();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,7 +72,10 @@ static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
|||||||
// draw an xbm image.
|
// draw an xbm image.
|
||||||
// Please note that everything that should be transitioned
|
// Please note that everything that should be transitioned
|
||||||
// needs to be drawn relative to x and y
|
// needs to be drawn relative to x and y
|
||||||
display->drawXbm(x + 32, y, icon_width, icon_height, (const uint8_t *)icon_bits);
|
|
||||||
|
// draw centered left to right and centered above the one line of app text
|
||||||
|
display->drawXbm(x + (SCREEN_WIDTH - icon_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_16 - icon_height) / 2, icon_width,
|
||||||
|
icon_height, (const uint8_t *)icon_bits);
|
||||||
|
|
||||||
display->setFont(ArialMT_Plain_16);
|
display->setFont(ArialMT_Plain_16);
|
||||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
@ -85,6 +88,7 @@ static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
|||||||
snprintf(buf, sizeof(buf), "%s",
|
snprintf(buf, sizeof(buf), "%s",
|
||||||
xstr(APP_VERSION)); // Note: we don't bother printing region or now, it makes the string too long
|
xstr(APP_VERSION)); // Note: we don't bother printing region or now, it makes the string too long
|
||||||
display->drawString(SCREEN_WIDTH - 20, 0, buf);
|
display->drawString(SCREEN_WIDTH - 20, 0, buf);
|
||||||
|
screen->forceDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
@ -570,7 +574,8 @@ void _screen_header()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl), ui(&dispdev) {
|
Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl), ui(&dispdev)
|
||||||
|
{
|
||||||
cmdQueue.setReader(this);
|
cmdQueue.setReader(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -608,7 +613,7 @@ void Screen::setup()
|
|||||||
|
|
||||||
displayWidth = dispdev.width();
|
displayWidth = dispdev.width();
|
||||||
displayHeight = dispdev.height();
|
displayHeight = dispdev.height();
|
||||||
|
|
||||||
ui.setTimePerTransition(300); // msecs
|
ui.setTimePerTransition(300); // msecs
|
||||||
ui.setIndicatorPosition(BOTTOM);
|
ui.setIndicatorPosition(BOTTOM);
|
||||||
// Defines where the first frame is located in the bar.
|
// Defines where the first frame is located in the bar.
|
||||||
@ -658,6 +663,14 @@ void Screen::setup()
|
|||||||
nodeStatusObserver.observe(&nodeStatus->onNewStatus);
|
nodeStatusObserver.observe(&nodeStatus->onNewStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Screen::forceDisplay()
|
||||||
|
{
|
||||||
|
// Nasty hack to force epaper updates for 'key' frames. FIXME, cleanup.
|
||||||
|
#ifdef HAS_EINK
|
||||||
|
dispdev.forceDisplay();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int32_t Screen::runOnce()
|
int32_t Screen::runOnce()
|
||||||
{
|
{
|
||||||
// If we don't have a screen, don't ever spend any CPU for us.
|
// If we don't have a screen, don't ever spend any CPU for us.
|
||||||
@ -722,6 +735,7 @@ int32_t Screen::runOnce()
|
|||||||
DEBUG_MSG("Setting idle framerate\n");
|
DEBUG_MSG("Setting idle framerate\n");
|
||||||
targetFramerate = IDLE_FRAMERATE;
|
targetFramerate = IDLE_FRAMERATE;
|
||||||
ui.setTargetFPS(targetFramerate);
|
ui.setTargetFPS(targetFramerate);
|
||||||
|
forceDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
// While showing the bootscreen or Bluetooth pair screen all of our
|
// While showing the bootscreen or Bluetooth pair screen all of our
|
||||||
|
@ -180,6 +180,9 @@ class Screen : public concurrency::OSThread
|
|||||||
|
|
||||||
int handleStatusUpdate(const meshtastic::Status *arg);
|
int handleStatusUpdate(const meshtastic::Status *arg);
|
||||||
|
|
||||||
|
/// Used to force (super slow) eink displays to draw critical frames
|
||||||
|
void forceDisplay();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Updates the UI.
|
/// Updates the UI.
|
||||||
//
|
//
|
||||||
|
Loading…
Reference in New Issue
Block a user