diff --git a/OLEDDisplay.cpp b/OLEDDisplay.cpp index 2161d3e34ca0c957c181de60cc9a20da4d03f4d9..dc73f2061238fe69f9f997c96f84856cd46773d3 100644 --- a/OLEDDisplay.cpp +++ b/OLEDDisplay.cpp @@ -125,13 +125,13 @@ void OLEDDisplay::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1) { void OLEDDisplay::drawRect(int16_t x, int16_t y, int16_t width, int16_t height) { drawHorizontalLine(x, y, width); drawVerticalLine(x, y, height); - drawVerticalLine(x + width, y, height); - drawHorizontalLine(x, y + height, width); + drawVerticalLine(x + width - 1, y, height); + drawHorizontalLine(x, y + height - 1, width); } void OLEDDisplay::fillRect(int16_t xMove, int16_t yMove, int16_t width, int16_t height) { - for (int16_t i = yMove; i < yMove + height; i++) { - drawHorizontalLine(xMove, i, width); + for (int16_t x = xMove; x < xMove + width; x++) { + drawVerticalLine(x, yMove, height); } } @@ -161,6 +161,46 @@ void OLEDDisplay::drawCircle(int16_t x0, int16_t y0, int16_t radius) { setPixel(x0, y0 - radius); } +void OLEDDisplay::drawCircleQuads(int16_t x0, int16_t y0, int16_t radius, uint8_t quads) { + int16_t x = 0, y = radius; + int16_t dp = 1 - radius; + while (x < y) { + if (dp < 0) + dp = dp + 2 * (++x) + 3; + else + dp = dp + 2 * (++x) - 2 * (--y) + 5; + if (quads & 0x1) { + setPixel(x0 + x, y0 - y); + setPixel(x0 + y, y0 - x); + } + if (quads & 0x2) { + setPixel(x0 - y, y0 - x); + setPixel(x0 - x, y0 - y); + } + if (quads & 0x4) { + setPixel(x0 - y, y0 + x); + setPixel(x0 - x, y0 + y); + } + if (quads & 0x8) { + setPixel(x0 + x, y0 + y); + setPixel(x0 + y, y0 + x); + } + } + if (quads & 0x1 && quads & 0x8) { + setPixel(x0 + radius, y0); + } + if (quads & 0x4 && quads & 0x8) { + setPixel(x0, y0 + radius); + } + if (quads & 0x2 && quads & 0x4) { + setPixel(x0 - radius, y0); + } + if (quads & 0x1 && quads & 0x2) { + setPixel(x0, y0 - radius); + } +} + + void OLEDDisplay::fillCircle(int16_t x0, int16_t y0, int16_t radius) { int16_t x = 0, y = radius; int16_t dp = 1 - radius; @@ -215,7 +255,7 @@ void OLEDDisplay::drawHorizontalLine(int16_t x, int16_t y, int16_t length) { } void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) { - if (x < 0 || x > DISPLAY_WIDTH) return; + if (x < 0 || x >= DISPLAY_WIDTH) return; if (y < 0) { length += y; @@ -245,9 +285,9 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) { } switch (color) { - case WHITE: *bufferPtr |= drawBit; break; - case BLACK: *bufferPtr &= drawBit; break; - case INVERSE: *bufferPtr ^= drawBit; break; + case WHITE: *bufferPtr |= drawBit; break; + case BLACK: *bufferPtr &= ~drawBit; break; + case INVERSE: *bufferPtr ^= drawBit; break; } if (length < yOffset) return; @@ -280,28 +320,31 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) { if (length > 0) { drawBit = (1 << (length & 7)) - 1; switch (color) { - case WHITE: *bufferPtr |= drawBit; break; - case BLACK: *bufferPtr &= drawBit; break; - case INVERSE: *bufferPtr ^= drawBit; break; + case WHITE: *bufferPtr |= drawBit; break; + case BLACK: *bufferPtr &= ~drawBit; break; + case INVERSE: *bufferPtr ^= drawBit; break; } } } void OLEDDisplay::drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress) { uint16_t radius = height / 2; - uint16_t innerRadius = radius - 3; - setColor(WHITE); - drawCircle(x + radius, y + radius, radius); - drawRect(x+radius, y, width - 2*radius, height); - drawCircle(x + width - radius, y + radius, radius); - setColor(BLACK); - fillRect(x+radius, y+1, width - 2*radius + 1, height - 1); + uint16_t xRadius = x + radius; + uint16_t yRadius = y + radius; + uint16_t doubleRadius = 2 * radius; + uint16_t innerRadius = radius - 2; + setColor(WHITE); - uint16_t maxProgressWidth = (width - 2 * radius) * progress / 100; - for (uint16_t i = 0; i < maxProgressWidth; i++) { - fillCircle(x + radius + i, y + radius, innerRadius); - } + drawCircleQuads(xRadius, yRadius, radius, 0b00000110); + drawHorizontalLine(xRadius, y, width - doubleRadius + 1); + drawHorizontalLine(xRadius, y + height, width - doubleRadius + 1); + drawCircleQuads(x + width - radius, yRadius, radius, 0b00001001); + + uint16_t maxProgressWidth = (width - doubleRadius - 1) * progress / 100; + fillCircle(xRadius, yRadius, innerRadius); + fillRect(xRadius + 1, y + 2, maxProgressWidth, height - 3); + fillCircle(xRadius + maxProgressWidth, yRadius, innerRadius); } void OLEDDisplay::drawFastImage(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *image) { diff --git a/OLEDDisplay.h b/OLEDDisplay.h index 7c1dcf2c145f95257d21a51ad6b08417f0452022..5f35f6d52515e720c3f21c408488206715f8d50d 100644 --- a/OLEDDisplay.h +++ b/OLEDDisplay.h @@ -138,6 +138,9 @@ class OLEDDisplay : public Print { // Draw the border of a circle void drawCircle(int16_t x, int16_t y, int16_t radius); + // Draw all Quadrants specified in the quads bit mask + void drawCircleQuads(int16_t x0, int16_t y0, int16_t radius, uint8_t quads); + // Fill circle void fillCircle(int16_t x, int16_t y, int16_t radius);