FIX Display.print2 bug for value==10 (resulted in "0")
This commit is contained in:
parent
71b99cca5e
commit
a0b3ace3e6
@ -24,226 +24,226 @@ class Display {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
const uint8_t width;
|
const uint8_t width;
|
||||||
|
|
||||||
const uint8_t height;
|
const uint8_t height;
|
||||||
|
|
||||||
const size_t pixelCount;
|
const size_t pixelCount;
|
||||||
|
|
||||||
const size_t pixelByteCount;
|
const size_t pixelByteCount;
|
||||||
|
|
||||||
bool fpsShow = false;
|
bool fpsShow = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Adafruit_NeoPixel leds;
|
Adafruit_NeoPixel leds;
|
||||||
|
|
||||||
milliseconds_t fpsLastMillis = 0;
|
milliseconds_t fpsLastMillis = 0;
|
||||||
|
|
||||||
int fps = 0;
|
int fps = 0;
|
||||||
|
|
||||||
Color *buffer = nullptr;
|
Color *buffer = nullptr;
|
||||||
|
|
||||||
uint8_t brightness = 10;
|
uint8_t brightness = 10;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Display(uint8_t width, uint8_t height) :
|
Display(uint8_t width, uint8_t height) :
|
||||||
width(width), height(height),
|
width(width), height(height),
|
||||||
pixelCount(width * height),
|
pixelCount(width * height),
|
||||||
pixelByteCount(pixelCount * sizeof(Color)),
|
pixelByteCount(pixelCount * sizeof(Color)),
|
||||||
leds(pixelCount, GPIO_NUM_13) {
|
leds(pixelCount, GPIO_NUM_13) {
|
||||||
buffer = (Color *) malloc(pixelByteCount);
|
buffer = (Color *) malloc(pixelByteCount);
|
||||||
if (buffer == nullptr) {
|
if (buffer == nullptr) {
|
||||||
Serial.print("+-----------------------------------------------+\n");
|
Serial.print("+-----------------------------------------------+\n");
|
||||||
Serial.print("| OUT OF MEMORY: Cannot allocate double-buffer! |\n");
|
Serial.print("| OUT OF MEMORY: Cannot allocate double-buffer! |\n");
|
||||||
Serial.print("+-----------------------------------------------+\n");
|
Serial.print("+-----------------------------------------------+\n");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
~Display() {
|
~Display() {
|
||||||
if (buffer == nullptr) {
|
if (buffer == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
free(buffer);
|
|
||||||
buffer = nullptr;
|
|
||||||
}
|
}
|
||||||
|
free(buffer);
|
||||||
|
buffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
leds.begin();
|
leds.begin();
|
||||||
clear();
|
clear();
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
calculateFPS();
|
||||||
|
drawFpsBorder();
|
||||||
|
if (isDirty()) {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void loop() {
|
void setBrightness(uint8_t value) {
|
||||||
calculateFPS();
|
brightness = value;
|
||||||
drawFpsBorder();
|
}
|
||||||
if (isDirty()) {
|
|
||||||
flush();
|
uint8_t getBrightness() const {
|
||||||
}
|
return brightness;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
if (buffer == nullptr) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
memset(buffer, 0, pixelByteCount);
|
||||||
|
}
|
||||||
|
|
||||||
void setBrightness(uint8_t value) {
|
enum ALIGN {
|
||||||
brightness = value;
|
LEFT, RIGHT
|
||||||
}
|
};
|
||||||
|
|
||||||
uint8_t getBrightness() const {
|
uint8_t print2(int x, int y, double valueDbl, Color colorPositive, Color colorZero, Color colorNegative, ALIGN align = RIGHT) {
|
||||||
return brightness;
|
const Color color = valueDbl == 0 ? colorZero : (valueDbl < 0 ? colorNegative : colorPositive);
|
||||||
}
|
return print2(x, y, valueDbl, color, align);
|
||||||
|
}
|
||||||
void clear() {
|
|
||||||
if (buffer == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
memset(buffer, 0, pixelByteCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ALIGN {
|
|
||||||
LEFT, RIGHT
|
|
||||||
};
|
|
||||||
|
|
||||||
uint8_t print2(int x, int y, double valueDbl, Color colorPositive, Color colorZero, Color colorNegative, ALIGN align = RIGHT) {
|
|
||||||
const Color color = valueDbl == 0 ? colorZero : (valueDbl < 0 ? colorNegative : colorPositive);
|
|
||||||
return print2(x, y, valueDbl, color, align);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t print2(int x, int y, double valueDbl, Color color, ALIGN align = RIGHT) {
|
|
||||||
if (isnan(valueDbl)) {
|
|
||||||
x -= 3 * (DISPLAY_CHAR_WIDTH + 1) - 1;
|
|
||||||
x += print(x, y, SYMBOL_DASH, color, true) + 1;
|
|
||||||
x += print(x, y, SYMBOL_DASH, color, true) + 1;
|
|
||||||
x += print(x, y, SYMBOL_DASH, color, true) + 1;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int value = (int) round(abs(valueDbl));
|
|
||||||
const bool negative = valueDbl < 0;
|
|
||||||
|
|
||||||
const int digitCount = (int) max(1.0, ceil(log10(value))); // log10 is -inf for value==0, hence the max(1.0, ...)
|
|
||||||
if (align == RIGHT) {
|
|
||||||
x -= ((negative ? 1 : 0) + digitCount) * (DISPLAY_CHAR_WIDTH + 1) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int divider = (int) pow(10, digitCount - 1);
|
|
||||||
if (negative) {
|
|
||||||
x += print(x, y, SYMBOL_DASH, color, true) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool showIfZero = false;
|
|
||||||
// Serial.printf("x=%d, y=%d, value=%d, align=%s, digitCount=%d, divider=%d\n", x, y, value, align == LEFT ? "LEFT" : "RIGHT", digitCount, divider);
|
|
||||||
for (int digitPos = 0; digitPos < digitCount; ++digitPos) {
|
|
||||||
const int digitVal = value / divider % 10;
|
|
||||||
showIfZero |= digitVal != 0 || (digitPos == digitCount - 1);
|
|
||||||
x += print(x, y, digitVal, color, showIfZero) + 1;
|
|
||||||
// Serial.printf(" digitPos=%d, x=%d, y=%d, digitVal=%d, showIfZero=%s, divider=%d\n", digitPos, x, y, digitVal, showIfZero ? "true" : "false", divider);
|
|
||||||
divider /= 10;
|
|
||||||
}
|
|
||||||
// Serial.println();
|
|
||||||
|
|
||||||
|
uint8_t print2(int x, int y, double valueDbl, Color color, ALIGN align = RIGHT) {
|
||||||
|
if (isnan(valueDbl)) {
|
||||||
|
x -= 3 * (DISPLAY_CHAR_WIDTH + 1) - 1;
|
||||||
|
x += print(x, y, SYMBOL_DASH, color, true) + 1;
|
||||||
|
x += print(x, y, SYMBOL_DASH, color, true) + 1;
|
||||||
|
x += print(x, y, SYMBOL_DASH, color, true) + 1;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t print(uint8_t xPos, uint8_t yPos, uint8_t index, Color color, bool showIfZero) {
|
const int value = (int) round(abs(valueDbl));
|
||||||
if (index == 0 && !showIfZero) {
|
const bool negative = valueDbl < 0;
|
||||||
return DISPLAY_CHAR_WIDTH;
|
|
||||||
}
|
const int digitCount = (int) max(1.0, floor(log10(value)) + 1); // log10 is -inf for value==0, hence the max(1.0, ...)
|
||||||
if (index >= SYMBOL_COUNT) {
|
if (align == RIGHT) {
|
||||||
Serial.printf("Cannot print2 symbol #%u.\n", index);
|
x -= ((negative ? 1 : 0) + digitCount) * (DISPLAY_CHAR_WIDTH + 1) - 1;
|
||||||
index = SYMBOL_COUNT - 1;
|
}
|
||||||
}
|
|
||||||
bool *symbolBit = SYMBOLS[index];
|
int divider = (int) pow(10, digitCount - 1);
|
||||||
for (uint8_t y = 0; y < DISPLAY_CHAR_HEIGHT; ++y) {
|
if (negative) {
|
||||||
for (uint8_t x = 0; x < DISPLAY_CHAR_WIDTH; ++x) {
|
x += print(x, y, SYMBOL_DASH, color, true) + 1;
|
||||||
if (*(symbolBit++)) {
|
}
|
||||||
set(xPos + x, yPos + y, color);
|
|
||||||
} else {
|
bool showIfZero = false;
|
||||||
set(xPos + x, yPos + y, BLACK);
|
// Serial.printf("x=%d, y=%d, value=%d, align=%s, digitCount=%d, divider=%d\n", x, y, value, align == LEFT ? "LEFT" : "RIGHT", digitCount, divider);
|
||||||
}
|
for (int digitPos = 0; digitPos < digitCount; ++digitPos) {
|
||||||
}
|
const int digitVal = value / divider % 10;
|
||||||
}
|
showIfZero |= digitVal != 0 || (digitPos == digitCount - 1);
|
||||||
|
x += print(x, y, digitVal, color, showIfZero) + 1;
|
||||||
|
// Serial.printf(" digitPos=%d, x=%d, y=%d, digitVal=%d, showIfZero=%s, divider=%d\n", digitPos, x, y, digitVal, showIfZero ? "true" : "false", divider);
|
||||||
|
divider /= 10;
|
||||||
|
}
|
||||||
|
// Serial.println();
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t print(uint8_t xPos, uint8_t yPos, uint8_t index, Color color, bool showIfZero) {
|
||||||
|
if (index == 0 && !showIfZero) {
|
||||||
return DISPLAY_CHAR_WIDTH;
|
return DISPLAY_CHAR_WIDTH;
|
||||||
}
|
}
|
||||||
|
if (index >= SYMBOL_COUNT) {
|
||||||
void set(Vector pos, Color color) {
|
Serial.printf("Cannot print2 symbol #%u.\n", index);
|
||||||
set((uint8_t) round(pos.x), (uint8_t) round(pos.y), color);
|
index = SYMBOL_COUNT - 1;
|
||||||
}
|
}
|
||||||
|
bool *symbolBit = SYMBOLS[index];
|
||||||
void set(uint8_t x, uint8_t y, Color color) {
|
for (uint8_t y = 0; y < DISPLAY_CHAR_HEIGHT; ++y) {
|
||||||
if (x >= width || y >= height) {
|
for (uint8_t x = 0; x < DISPLAY_CHAR_WIDTH; ++x) {
|
||||||
return;
|
if (*(symbolBit++)) {
|
||||||
|
set(xPos + x, yPos + y, color);
|
||||||
|
} else {
|
||||||
|
set(xPos + x, yPos + y, BLACK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((y % 2) != 0) {
|
|
||||||
x = width - x - 1;
|
|
||||||
}
|
|
||||||
set(y * width + x, color);
|
|
||||||
}
|
}
|
||||||
|
return DISPLAY_CHAR_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
void set(uint16_t index, Color color) {
|
void set(Vector pos, Color color) {
|
||||||
if (buffer == nullptr) {
|
set((uint8_t) round(pos.x), (uint8_t) round(pos.y), color);
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
buffer[index] = {
|
void set(uint8_t x, uint8_t y, Color color) {
|
||||||
// yes, correct order is GRB !!!
|
if (x >= width || y >= height) {
|
||||||
(uint8_t) (color.g * brightness >> 8),
|
return;
|
||||||
(uint8_t) (color.r * brightness >> 8),
|
|
||||||
(uint8_t) (color.b * brightness >> 8)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
if ((y % 2) != 0) {
|
||||||
|
x = width - x - 1;
|
||||||
|
}
|
||||||
|
set(y * width + x, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(uint16_t index, Color color) {
|
||||||
|
if (buffer == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buffer[index] = {
|
||||||
|
// yes, correct order is GRB !!!
|
||||||
|
(uint8_t) (color.g * brightness >> 8),
|
||||||
|
(uint8_t) (color.r * brightness >> 8),
|
||||||
|
(uint8_t) (color.b * brightness >> 8)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void flush() {
|
void flush() {
|
||||||
if (buffer == nullptr) {
|
if (buffer == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memcpy(leds.getPixels(), buffer, pixelByteCount);
|
memcpy(leds.getPixels(), buffer, pixelByteCount);
|
||||||
leds.show();
|
leds.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDirty() const {
|
||||||
|
if (buffer == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return memcmp(leds.getPixels(), buffer, pixelByteCount) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void calculateFPS() {
|
||||||
|
fps = (int) round(1000.0 / (millis() - fpsLastMillis));
|
||||||
|
fpsLastMillis = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawFpsBorder() {
|
||||||
|
if (!fpsShow) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isDirty() const {
|
int frames = fps;
|
||||||
if (buffer == nullptr) {
|
|
||||||
return false;
|
Color color = RED;
|
||||||
}
|
if (frames > 3 * 76) {
|
||||||
return memcmp(leds.getPixels(), buffer, pixelByteCount) != 0;
|
frames -= 3 * 76;
|
||||||
|
color = WHITE;
|
||||||
|
} else if (frames > 2 * 76) {
|
||||||
|
frames -= 2 * 76;
|
||||||
|
color = BLUE;
|
||||||
|
} else if (frames > 76) {
|
||||||
|
frames -= 76;
|
||||||
|
color = GREEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void calculateFPS() {
|
for (int x = 0; x <= width - 1 && frames-- > 0; x++) {
|
||||||
fps = (int) round(1000.0 / (millis() - fpsLastMillis));
|
set(x, 0, color);
|
||||||
fpsLastMillis = millis();
|
|
||||||
}
|
}
|
||||||
|
for (int y = 0; y <= height - 1 && frames-- > 0; y++) {
|
||||||
void drawFpsBorder() {
|
set(width - 1, y, color);
|
||||||
if (!fpsShow) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int frames = fps;
|
|
||||||
|
|
||||||
Color color = RED;
|
|
||||||
if (frames > 3 * 76) {
|
|
||||||
frames -= 3 * 76;
|
|
||||||
color = WHITE;
|
|
||||||
} else if (frames > 2 * 76) {
|
|
||||||
frames -= 2 * 76;
|
|
||||||
color = BLUE;
|
|
||||||
} else if (frames > 76) {
|
|
||||||
frames -= 76;
|
|
||||||
color = GREEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int x = 0; x <= width - 1 && frames-- > 0; x++) {
|
|
||||||
set(x, 0, color);
|
|
||||||
}
|
|
||||||
for (int y = 0; y <= height - 1 && frames-- > 0; y++) {
|
|
||||||
set(width - 1, y, color);
|
|
||||||
}
|
|
||||||
for (int x = width - 1; x >= 0 && frames-- > 0; x--) {
|
|
||||||
set(x, height - 1, color);
|
|
||||||
}
|
|
||||||
for (int y = height - 1; y >= 0 && frames-- > 0; y--) {
|
|
||||||
set(0, y, color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
for (int x = width - 1; x >= 0 && frames-- > 0; x--) {
|
||||||
|
set(x, height - 1, color);
|
||||||
|
}
|
||||||
|
for (int y = height - 1; y >= 0 && frames-- > 0; y--) {
|
||||||
|
set(0, y, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user