RLE for greyscale lcd (gives more firmware space!) (#1142)
* use RLE encodes bitmaps on 212x64 pixel radios * fix model image display fix icon display * implement RLE bitmaps in companion for splash image on 212x64 radios reserve 3kB for RLE bitmaps in firmware * fix size check * use defines instead of magic numbers * fix display of splash screens on 212x64 radios * add warning message if compressed image is larger than the reserved space
This commit is contained in:
@@ -28,10 +28,14 @@
|
||||
|
||||
//*** Side Class ***
|
||||
|
||||
Side::Side(){
|
||||
Side::Side(QDialog* parent):
|
||||
parent(parent)
|
||||
{
|
||||
imageLabel = 0;
|
||||
fileNameEdit = 0;
|
||||
saveButton = 0;
|
||||
invertButton = 0;
|
||||
libraryButton = 0;
|
||||
loadFwButton=0;
|
||||
loadPictButton = 0;
|
||||
loadProfileButton = 0;
|
||||
@@ -62,7 +66,7 @@ bool Side::displayImage(QString fileName, Source pictSource)
|
||||
|
||||
// Determine which picture format to use
|
||||
if (pictSource == FW) {
|
||||
FirmwareInterface firmware(fileName);
|
||||
FirmwareInterface firmware(fileName, parent);
|
||||
if (!firmware.hasSplash())
|
||||
return false;
|
||||
else
|
||||
@@ -120,7 +124,7 @@ bool Side::saveImage()
|
||||
{
|
||||
if (*source == FW )
|
||||
{
|
||||
FirmwareInterface firmware(*saveToFileName);
|
||||
FirmwareInterface firmware(*saveToFileName, parent);
|
||||
if (!firmware.hasSplash()) {
|
||||
return false;
|
||||
}
|
||||
@@ -152,6 +156,8 @@ bool Side::saveImage()
|
||||
|
||||
CustomizeSplashDialog::CustomizeSplashDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
left(this),
|
||||
right(this),
|
||||
ui(new Ui::CustomizeSplashDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
@@ -40,7 +40,7 @@ enum LCDFormat {LCD9X, LCDTARANIS};
|
||||
class Side
|
||||
{
|
||||
public:
|
||||
Side();
|
||||
Side(QDialog* parent);
|
||||
void markSourceButton();
|
||||
void copyImage( Side );
|
||||
bool displayImage( QString fileName, Source source );
|
||||
@@ -59,6 +59,7 @@ public:
|
||||
QString *saveToFileName;
|
||||
|
||||
private:
|
||||
QDialog* parent;
|
||||
Source *source;
|
||||
LCDFormat *format;
|
||||
};
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "storage.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QMessageBox>
|
||||
#include <vector>
|
||||
|
||||
#define FW_MARK "FW"
|
||||
#define VERS_MARK "VERS"
|
||||
@@ -33,7 +35,131 @@
|
||||
#define EEPR_MARK "EEPR"
|
||||
#define FSIZE_MAX Boards::getFlashSize(Board::BOARD_UNKNOWN)
|
||||
|
||||
FirmwareInterface::FirmwareInterface(const QString & filename):
|
||||
class RleBitmap
|
||||
{
|
||||
public:
|
||||
RleBitmap(const uint8_t *src, size_t offset) :
|
||||
state(RLE_FIRST_BYTE), src(src), curPtr(src), byte(0), curCount(0), pos(0)
|
||||
{
|
||||
width = *curPtr++;
|
||||
rawRows = *curPtr++;
|
||||
rows = (rawRows +1)/2;
|
||||
skip(offset);
|
||||
}
|
||||
|
||||
void skip(size_t count)
|
||||
{
|
||||
while(count)
|
||||
{
|
||||
count--;
|
||||
getNext();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t getNext()
|
||||
{
|
||||
pos++;
|
||||
switch(state)
|
||||
{
|
||||
case RLE_FIRST_BYTE:
|
||||
byte = *curPtr++;
|
||||
if(byte == *curPtr)
|
||||
state = RLE_SECOND_BYTE;
|
||||
break;
|
||||
case RLE_SECOND_BYTE:
|
||||
byte = *curPtr++;
|
||||
curCount = (*curPtr++)+1;
|
||||
state = RLE_CONTINUE;
|
||||
// fall through
|
||||
case RLE_CONTINUE:
|
||||
curCount--;
|
||||
if(!curCount)
|
||||
state = RLE_FIRST_BYTE;
|
||||
break;
|
||||
}
|
||||
return byte;
|
||||
}
|
||||
|
||||
bool to(uint8_t* buf, size_t size)
|
||||
{
|
||||
while(pos<size)
|
||||
*buf++ = getNext();
|
||||
return pos == size;
|
||||
}
|
||||
uint8_t getWidth() const { return width; }
|
||||
uint8_t getRows() const { return rows; }
|
||||
uint8_t getRawRows() const { return rawRows; }
|
||||
void goToNextRow()
|
||||
{
|
||||
size_t offset = pos%width;
|
||||
if(offset)
|
||||
skip(width - pos%width);
|
||||
}
|
||||
|
||||
static size_t encode(uint8_t *buf, size_t bytes)
|
||||
{
|
||||
uint8_t* readPtr = buf;
|
||||
uint8_t* writePtr = buf;
|
||||
uint8_t state = 0;
|
||||
uint8_t count = 0;
|
||||
uint16_t prevByte = 0xFFFF;
|
||||
|
||||
while(bytes)
|
||||
{
|
||||
bytes--;
|
||||
uint8_t byte = *readPtr++;
|
||||
if(state == 0)
|
||||
{
|
||||
*writePtr++ = byte;;
|
||||
if(prevByte == byte)
|
||||
{
|
||||
state = 1;
|
||||
count = 0;
|
||||
} else {
|
||||
prevByte = byte;
|
||||
}
|
||||
} else {
|
||||
if(prevByte == byte)
|
||||
{
|
||||
count++;
|
||||
if(count == 255)
|
||||
{
|
||||
|
||||
*writePtr++ = count;
|
||||
prevByte = 0xFFFF;
|
||||
state = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
*writePtr++ = count;
|
||||
*writePtr++ = byte;
|
||||
prevByte = byte;
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(state != 0)
|
||||
*writePtr++ = count;
|
||||
return writePtr - buf;
|
||||
}
|
||||
|
||||
private:
|
||||
enum State {RLE_FIRST_BYTE, RLE_SECOND_BYTE, RLE_CONTINUE} state;
|
||||
const uint8_t* src;
|
||||
const uint8_t* curPtr;
|
||||
|
||||
uint8_t width;
|
||||
uint8_t rows;
|
||||
uint8_t rawRows;
|
||||
|
||||
uint8_t byte;
|
||||
uint16_t curCount;
|
||||
|
||||
size_t pos;
|
||||
};
|
||||
|
||||
FirmwareInterface::FirmwareInterface(const QString & filename, QDialog* parentDialog):
|
||||
parentDialog(parentDialog),
|
||||
flash(FSIZE_MAX, 0),
|
||||
flashSize(0),
|
||||
eepromVersion(0),
|
||||
@@ -220,7 +346,7 @@ void FirmwareInterface::seekSplash()
|
||||
return;
|
||||
}
|
||||
|
||||
if (seekSplash(QByteArray(OTX_SPS_TARANIS, OTX_SPS_SIZE), QByteArray(OTX_SPE, OTX_SPE_SIZE), 6784)) {
|
||||
if (seekSplash(QByteArray(OTX_SPS_TARANIS, OTX_SPS_SIZE), QByteArray(OTX_SPE, OTX_SPE_SIZE), RLE_SPLASH_MAX_SIZE)) {
|
||||
splashWidth = SPLASHX9D_WIDTH;
|
||||
splashHeight = SPLASHX9D_HEIGHT;
|
||||
splash_format = QImage::Format_Indexed8;
|
||||
@@ -243,7 +369,7 @@ bool FirmwareInterface::setSplash(const QImage & newsplash)
|
||||
return false;
|
||||
}
|
||||
|
||||
char b[SPLASH_SIZE_MAX] = {0};
|
||||
uint8_t b[SPLASH_SIZE_MAX] = {0};
|
||||
QColor color;
|
||||
QByteArray splash;
|
||||
if (splash_format == QImage::Format_Indexed8) {
|
||||
@@ -256,6 +382,15 @@ bool FirmwareInterface::setSplash(const QImage & newsplash)
|
||||
b[idx] |= z;
|
||||
}
|
||||
}
|
||||
if(splashWidth == SPLASHX9D_WIDTH && splashHeight == SPLASHX9D_HEIGHT)
|
||||
{
|
||||
splashSize = RleBitmap::encode(b, SPLASH_SIZE_MAX);
|
||||
if(splashSize > RLE_SPLASH_MAX_SIZE){
|
||||
if(parentDialog)
|
||||
QMessageBox::critical(parentDialog, CPN_STR_TTL_ERROR, parentDialog->tr("Compressed image size exceeds reserved space."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
QColor black = QColor(0,0,0);
|
||||
@@ -268,7 +403,7 @@ bool FirmwareInterface::setSplash(const QImage & newsplash)
|
||||
}
|
||||
}
|
||||
splash.clear();
|
||||
splash.append(b, splashSize);
|
||||
splash.append((char *)b, splashSize);
|
||||
flash.replace(splashOffset, splashSize, splash);
|
||||
return true;
|
||||
}
|
||||
@@ -288,6 +423,7 @@ QImage::Format FirmwareInterface::getSplashFormat()
|
||||
return splash_format;
|
||||
}
|
||||
|
||||
|
||||
QImage FirmwareInterface::getSplash()
|
||||
{
|
||||
if (splashOffset == 0 || splashSize == 0) {
|
||||
@@ -296,15 +432,35 @@ QImage FirmwareInterface::getSplash()
|
||||
|
||||
if (splash_format == QImage::Format_Indexed8) {
|
||||
QImage image(splashWidth, splashHeight, QImage::Format_RGB888);
|
||||
if (splashOffset > 0) {
|
||||
for (unsigned int y=0; y<splashHeight; y++) {
|
||||
unsigned int idx = (y/2)*splashWidth;
|
||||
for (unsigned int x=0; x<splashWidth; x++, idx++) {
|
||||
uint8_t byte = flash.at(splashOffset+idx);
|
||||
unsigned int z = (y & 1) ? (byte >> 4) : (byte & 0x0F);
|
||||
z = 255-(z*255)/15;
|
||||
QRgb rgb = qRgb(z, z, z);
|
||||
image.setPixel(x, y, rgb);
|
||||
if(splashWidth == SPLASHX9D_WIDTH && splashHeight == SPLASHX9D_HEIGHT)
|
||||
{
|
||||
std::vector<uint8_t> data;
|
||||
data.resize(splashWidth * splashHeight);
|
||||
RleBitmap img((uint8_t*)flash.data() + splashOffset - 2, 0);
|
||||
img.to(&data[0], data.size());
|
||||
if (splashOffset > 0) {
|
||||
for (unsigned int y=0; y<splashHeight; y++) {
|
||||
unsigned int idx = (y/2)*splashWidth;
|
||||
for (unsigned int x=0; x<splashWidth; x++, idx++) {
|
||||
uint8_t byte = data[idx];
|
||||
unsigned int z = (y & 1) ? (byte >> 4) : (byte & 0x0F);
|
||||
z = 255-(z*255)/15;
|
||||
QRgb rgb = qRgb(z, z, z);
|
||||
image.setPixel(x, y, rgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (splashOffset > 0) {
|
||||
for (unsigned int y=0; y<splashHeight; y++) {
|
||||
unsigned int idx = (y/2)*splashWidth;
|
||||
for (unsigned int x=0; x<splashWidth; x++, idx++) {
|
||||
uint8_t byte = flash.at(splashOffset+idx);
|
||||
unsigned int z = (y & 1) ? (byte >> 4) : (byte & 0x0F);
|
||||
z = 255-(z*255)/15;
|
||||
QRgb rgb = qRgb(z, z, z);
|
||||
image.setPixel(x, y, rgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,10 +36,13 @@
|
||||
#define ERSKY9X_SPE "SPE"
|
||||
#define ERSKY9X_OFFSET (7)
|
||||
|
||||
// 3kB - width and height bytes
|
||||
#define RLE_SPLASH_MAX_SIZE (3070)
|
||||
|
||||
class FirmwareInterface
|
||||
{
|
||||
public:
|
||||
FirmwareInterface(const QString & filename);
|
||||
FirmwareInterface(const QString & filename, QDialog* parentDialog = nullptr);
|
||||
inline QString getDate() { return date; }
|
||||
inline QString getTime() { return time; }
|
||||
int getSize() { return flashSize; }
|
||||
@@ -59,6 +62,7 @@ class FirmwareInterface
|
||||
bool isValid();
|
||||
|
||||
private:
|
||||
QDialog* parentDialog;
|
||||
QByteArray flash;
|
||||
uint flashSize;
|
||||
QString seekString(const QString & string);
|
||||
|
||||
@@ -6,5 +6,5 @@ set(STICKS_ARGS --rows 4)
|
||||
|
||||
add_bitmaps_target(taranis_xbm ${RADIO_SRC_DIR}/bitmaps/sticks.xbm 1bit "${STICKS_ARGS}") # 1bit format, 1byte size, split into 4 rows
|
||||
add_fonts_target(taranis_fonts ${RADIO_SRC_DIR}/fonts/${FONT_DIR}/*.png)
|
||||
add_bitmaps_target(taranis_bitmaps ${RADIO_SRC_DIR}/bitmaps/212x64/*.png 4bits "")
|
||||
add_bitmaps_target(taranis_bitmaps ${RADIO_SRC_DIR}/bitmaps/212x64/*.png 4bits "--rle")
|
||||
add_dependencies(taranis_bitmaps taranis_fonts taranis_xbm)
|
||||
|
||||
@@ -204,6 +204,10 @@ bool loadModelBitmap(char * name, uint8_t * bitmap)
|
||||
}
|
||||
|
||||
// In all error cases, we set the default logo
|
||||
memcpy(bitmap, logo_taranis, MODEL_BITMAP_SIZE);
|
||||
RleBitmap pic(logo_taranis, 0);
|
||||
*bitmap++ = pic.getWidth();
|
||||
*bitmap++ = pic.getRawRows();
|
||||
for(int i=0; i < MODEL_BITMAP_SIZE-2; i++)
|
||||
*bitmap++ = pic.getNext();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -976,4 +976,39 @@ void lcdDrawBitmap(coord_t x, coord_t y, const uint8_t * img, coord_t offset, co
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lcdDrawRleBitmap(coord_t x, coord_t y, const uint8_t * img, coord_t offset, coord_t width)
|
||||
{
|
||||
RleBitmap pic(img, offset);
|
||||
|
||||
uint8_t w = pic.getWidth();
|
||||
if (!width || width > w) {
|
||||
width = w;
|
||||
}
|
||||
if (x+width > LCD_W) {
|
||||
if (x >= LCD_W ) return;
|
||||
width = LCD_W-x;
|
||||
}
|
||||
uint8_t rows = pic.getRows();
|
||||
|
||||
for (uint8_t row=0; row<rows; row++) {
|
||||
uint8_t *p = &displayBuf[(row + (y/2)) * LCD_W + x];
|
||||
for (coord_t i=0; i<width; i++) {
|
||||
if (p >= DISPLAY_END) return;
|
||||
uint8_t b = pic.getNext();
|
||||
if (y & 1) {
|
||||
*p = (*p & 0x0f) + ((b & 0x0f) << 4);
|
||||
if ((p+LCD_W) < DISPLAY_END) {
|
||||
*(p+LCD_W) = (*(p+LCD_W) & 0xf0) + ((b & 0xf0) >> 4);
|
||||
}
|
||||
}
|
||||
else {
|
||||
*p = b;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
pic.goToNextRow();
|
||||
pic.skip(offset);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -168,7 +168,9 @@ void drawTelemetryTopBar();
|
||||
void lcdDraw1bitBitmap(coord_t x, coord_t y, const unsigned char * img, uint8_t idx, LcdFlags att=0);
|
||||
|
||||
void lcdDrawBitmap(coord_t x, coord_t y, const uint8_t * img, coord_t offset=0, coord_t width=0);
|
||||
#define LCD_ICON(x, y, icon) lcdDrawBitmap(x, y, icons, icon)
|
||||
void lcdDrawRleBitmap(coord_t x, coord_t y, const uint8_t * img, coord_t offset=0, coord_t width=0);
|
||||
#define LCD_ICON(x, y, icon) lcdDrawRleBitmap(x, y, icons, icon)
|
||||
|
||||
|
||||
void lcdClear();
|
||||
|
||||
@@ -193,4 +195,75 @@ inline pixel_t getPixel(unsigned int x, unsigned int y)
|
||||
|
||||
uint8_t getTextWidth(const char * s, uint8_t len=0, LcdFlags flags=0);
|
||||
|
||||
class RleBitmap
|
||||
{
|
||||
public:
|
||||
RleBitmap(const uint8_t *src, coord_t offset) :
|
||||
state(RLE_FIRST_BYTE), src(src), curPtr(src), byte(0), curCount(0), pos(0)
|
||||
{
|
||||
width = *curPtr++;
|
||||
rawRows = *curPtr++;
|
||||
rows = (rawRows +1)/2;
|
||||
skip(offset);
|
||||
}
|
||||
|
||||
void skip(coord_t count)
|
||||
{
|
||||
while(count)
|
||||
{
|
||||
count--;
|
||||
getNext();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t getNext()
|
||||
{
|
||||
pos++;
|
||||
switch(state)
|
||||
{
|
||||
case RLE_FIRST_BYTE:
|
||||
byte = *curPtr++;
|
||||
if(byte == *curPtr)
|
||||
state = RLE_SECOND_BYTE;
|
||||
break;
|
||||
case RLE_SECOND_BYTE:
|
||||
byte = *curPtr++;
|
||||
curCount = (*curPtr++)+1;
|
||||
state = RLE_CONTINUE;
|
||||
// fall through
|
||||
case RLE_CONTINUE:
|
||||
curCount--;
|
||||
if(!curCount)
|
||||
state = RLE_FIRST_BYTE;
|
||||
break;
|
||||
}
|
||||
return byte;
|
||||
}
|
||||
|
||||
uint8_t getWidth() const { return width; }
|
||||
uint8_t getRows() const { return rows; }
|
||||
uint8_t getRawRows() const { return rawRows; }
|
||||
void goToNextRow()
|
||||
{
|
||||
coord_t offset = pos%width;
|
||||
if(offset)
|
||||
skip(width - pos%width);
|
||||
}
|
||||
|
||||
private:
|
||||
enum State {RLE_FIRST_BYTE, RLE_SECOND_BYTE, RLE_CONTINUE} state;
|
||||
const uint8_t* src;
|
||||
const uint8_t* curPtr;
|
||||
|
||||
uint8_t width;
|
||||
uint8_t rows;
|
||||
uint8_t rawRows;
|
||||
|
||||
uint8_t byte;
|
||||
uint16_t curCount;
|
||||
|
||||
coord_t pos;
|
||||
};
|
||||
|
||||
|
||||
#endif // _LCD_H_
|
||||
|
||||
@@ -28,7 +28,7 @@ const unsigned char ASTERISK_BITMAP[] = {
|
||||
void drawAlertBox(const char * title, const char * text, const char * action)
|
||||
{
|
||||
lcdClear();
|
||||
lcdDrawBitmap(0, 0, ASTERISK_BITMAP);
|
||||
lcdDrawRleBitmap(0, 0, ASTERISK_BITMAP);
|
||||
|
||||
#define MESSAGE_LCD_OFFSET 60
|
||||
|
||||
|
||||
@@ -22,16 +22,21 @@
|
||||
#include "opentx.h"
|
||||
|
||||
#if defined(SPLASH)
|
||||
const unsigned char splashdata[] = {
|
||||
'S','P','S',0,
|
||||
#include "bitmaps/212x64/splash.lbm"
|
||||
'S','P','E',0 };
|
||||
const unsigned char * const splash_lbm = splashdata+4;
|
||||
#define MAXIMUM_SPLASH_IMAGE_SIZE 3072
|
||||
struct {
|
||||
const uint8_t __magic_prefix[4] = { 'S','P','S',0 };
|
||||
const uint8_t splashdata[MAXIMUM_SPLASH_IMAGE_SIZE] = {
|
||||
#include "bitmaps/212x64/splash.lbm"
|
||||
};
|
||||
const uint8_t __magic_suffix[4] = { 'S','P','E',0 };
|
||||
} splash_struct;
|
||||
static_assert(sizeof(splash_struct.splashdata) <= MAXIMUM_SPLASH_IMAGE_SIZE, "");
|
||||
const unsigned char * const splash_lbm = splash_struct.splashdata;
|
||||
|
||||
void drawSplash()
|
||||
{
|
||||
lcdClear();
|
||||
lcdDrawBitmap(0, 0, splash_lbm);
|
||||
lcdDrawRleBitmap(0, 0, splash_lbm);
|
||||
|
||||
#if MENUS_LOCK == 1
|
||||
if (readonly == false) {
|
||||
|
||||
@@ -52,9 +52,9 @@ void drawStartupAnimation(uint32_t duration, uint32_t totalDuration)
|
||||
lcdClear();
|
||||
|
||||
if (index == 0)
|
||||
lcdDrawBitmap((LCD_W - ANIMATIONS_BITMAP_WIDTH) / 2, (LCD_H - ANIMATIONS_BITMAP_HEIGHT) / 2, bmp_lock, 0, ANIMATIONS_BITMAP_WIDTH);
|
||||
lcdDrawRleBitmap((LCD_W - ANIMATIONS_BITMAP_WIDTH) / 2, (LCD_H - ANIMATIONS_BITMAP_HEIGHT) / 2, bmp_lock, 0, ANIMATIONS_BITMAP_WIDTH);
|
||||
else
|
||||
lcdDrawBitmap((LCD_W - ANIMATIONS_BITMAP_WIDTH) / 2, (LCD_H - ANIMATIONS_BITMAP_HEIGHT) / 2, bmp_startup, (index - 1) * ANIMATIONS_BITMAP_WIDTH, ANIMATIONS_BITMAP_WIDTH);
|
||||
lcdDrawRleBitmap((LCD_W - ANIMATIONS_BITMAP_WIDTH) / 2, (LCD_H - ANIMATIONS_BITMAP_HEIGHT) / 2, bmp_startup, (index - 1) * ANIMATIONS_BITMAP_WIDTH, ANIMATIONS_BITMAP_WIDTH);
|
||||
|
||||
lcdRefresh();
|
||||
}
|
||||
@@ -69,7 +69,7 @@ void drawShutdownAnimation(uint32_t duration, uint32_t totalDuration, const char
|
||||
lcdRefreshWait();
|
||||
lcdClear();
|
||||
|
||||
lcdDrawBitmap((LCD_W - ANIMATIONS_BITMAP_WIDTH) / 2, (LCD_H - ANIMATIONS_BITMAP_HEIGHT) / 2, bmp_shutdown, (3 - index) * ANIMATIONS_BITMAP_WIDTH, ANIMATIONS_BITMAP_WIDTH);
|
||||
lcdDrawRleBitmap((LCD_W - ANIMATIONS_BITMAP_WIDTH) / 2, (LCD_H - ANIMATIONS_BITMAP_HEIGHT) / 2, bmp_shutdown, (3 - index) * ANIMATIONS_BITMAP_WIDTH, ANIMATIONS_BITMAP_WIDTH);
|
||||
if (message) {
|
||||
lcdDrawText((LCD_W - getTextWidth(message)) / 2, LCD_H - 2*FH, message);
|
||||
}
|
||||
@@ -81,7 +81,7 @@ void drawSleepBitmap()
|
||||
{
|
||||
lcdRefreshWait();
|
||||
lcdClear();
|
||||
lcdDrawBitmap((LCD_W - ANIMATIONS_BITMAP_WIDTH) / 2, (LCD_H - ANIMATIONS_BITMAP_HEIGHT) / 2, bmp_sleep, 0);
|
||||
lcdDrawRleBitmap((LCD_W - ANIMATIONS_BITMAP_WIDTH) / 2, (LCD_H - ANIMATIONS_BITMAP_HEIGHT) / 2, bmp_sleep, 0);
|
||||
lcdRefresh();
|
||||
lcdRefreshWait();
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ void displayTopBarGauge(coord_t x, int count, bool blinking=false)
|
||||
}
|
||||
|
||||
#define LCD_NOTIF_ICON(x, icon) \
|
||||
lcdDrawBitmap(x, BAR_Y, icons, icon); \
|
||||
lcdDrawRleBitmap(x, BAR_Y, icons, icon); \
|
||||
lcdDrawSolidHorizontalLine(x, BAR_Y+8, 11)
|
||||
|
||||
void displayTopBar()
|
||||
|
||||
Reference in New Issue
Block a user