|
|
|
|
@@ -14,9 +14,8 @@
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
// rendering to the buffer
|
|
|
|
|
uint8_t *OLED::firstStripPtr; // Pointers to the strips to allow for buffer
|
|
|
|
|
// having extra content
|
|
|
|
|
uint8_t *OLED::secondStripPtr; // Pointers to the strips
|
|
|
|
|
uint8_t *OLED::stripPointers[4]; // Pointers to the strips to allow for buffer having extra content
|
|
|
|
|
|
|
|
|
|
bool OLED::inLeftHandedMode; // Whether the screen is in left or not (used for
|
|
|
|
|
// offsets in GRAM)
|
|
|
|
|
OLED::DisplayState OLED::displayState;
|
|
|
|
|
@@ -24,7 +23,7 @@ int16_t OLED::cursor_x, OLED::cursor_y;
|
|
|
|
|
bool OLED::initDone = false;
|
|
|
|
|
uint8_t OLED::displayOffset;
|
|
|
|
|
uint8_t OLED::screenBuffer[16 + (OLED_WIDTH * (OLED_HEIGHT / 8)) + 10]; // The data buffer
|
|
|
|
|
uint8_t OLED::secondFrameBuffer[OLED_WIDTH * 2];
|
|
|
|
|
uint8_t OLED::secondFrameBuffer[16 + (OLED_WIDTH * (OLED_HEIGHT / 8)) + 10];
|
|
|
|
|
uint32_t OLED::displayChecksum;
|
|
|
|
|
/*Setup params for the OLED screen*/
|
|
|
|
|
/*http://www.displayfuture.com/Display/datasheet/controller/SSD1307.pdf*/
|
|
|
|
|
@@ -33,7 +32,7 @@ uint32_t OLED::displayChecksum;
|
|
|
|
|
I2C_CLASS::I2C_REG OLED_Setup_Array[] = {
|
|
|
|
|
/**/
|
|
|
|
|
{0x80, 0xAE, 0}, /*Display off*/
|
|
|
|
|
{0x80, 0xD5, 0}, /*Set display clock divide ratio / osc freq*/
|
|
|
|
|
{0x80, 0xD3, 0}, /*Set display clock divide ratio / osc freq*/
|
|
|
|
|
{0x80, 0x52, 0}, /*Divide ratios*/
|
|
|
|
|
{0x80, 0xA8, 0}, /*Set Multiplex Ratio*/
|
|
|
|
|
{0x80, OLED_HEIGHT - 1, 0}, /*Multiplex ratio adjusts how far down the matrix it scans*/
|
|
|
|
|
@@ -41,11 +40,11 @@ I2C_CLASS::I2C_REG OLED_Setup_Array[] = {
|
|
|
|
|
{0x80, 0xD3, 0}, /*Set vertical Display offset*/
|
|
|
|
|
{0x80, 0x00, 0}, /*0 Offset*/
|
|
|
|
|
{0x80, 0x40, 0}, /*Set Display start line to 0*/
|
|
|
|
|
#ifdef OLED_SEGMENT_MAP_REVERSED
|
|
|
|
|
#ifdef OLED_SEGMENT_MAP_REVERSED
|
|
|
|
|
{0x80, 0xA1, 0}, /*Set Segment remap to normal*/
|
|
|
|
|
#else
|
|
|
|
|
#else
|
|
|
|
|
{0x80, 0xA0, 0}, /*Set Segment remap to normal*/
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
{0x80, 0x8D, 0}, /*Charge Pump*/
|
|
|
|
|
{0x80, 0x14, 0}, /*Charge Pump settings*/
|
|
|
|
|
{0x80, 0xDA, 0}, /*Set VCOM Pins hardware config*/
|
|
|
|
|
@@ -111,13 +110,21 @@ static uint8_t easeInOutTiming(uint8_t t) { return t * t * (300 - 2 * t) / 10000
|
|
|
|
|
* @param b The value associated with 100%
|
|
|
|
|
* @param t The percentage [0..<100]
|
|
|
|
|
*/
|
|
|
|
|
static uint8_t lerp(uint8_t a, uint8_t b, uint8_t t) { return a + t * (b - a) / 100; }
|
|
|
|
|
static uint16_t lerp(uint16_t a, uint16_t b, uint16_t t) { return a + t * (b - a) / 100; }
|
|
|
|
|
|
|
|
|
|
void OLED::initialize() {
|
|
|
|
|
cursor_x = cursor_y = 0;
|
|
|
|
|
inLeftHandedMode = false;
|
|
|
|
|
firstStripPtr = &screenBuffer[FRAMEBUFFER_START];
|
|
|
|
|
secondStripPtr = &screenBuffer[FRAMEBUFFER_START + OLED_WIDTH];
|
|
|
|
|
#ifdef OLED_128x32
|
|
|
|
|
stripPointers[0] = &screenBuffer[FRAMEBUFFER_START];
|
|
|
|
|
stripPointers[1] = &screenBuffer[FRAMEBUFFER_START + OLED_WIDTH];
|
|
|
|
|
stripPointers[2] = &screenBuffer[FRAMEBUFFER_START + 2 * OLED_WIDTH];
|
|
|
|
|
stripPointers[3] = &screenBuffer[FRAMEBUFFER_START + 3 * OLED_WIDTH];
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
stripPointers[0] = &screenBuffer[FRAMEBUFFER_START];
|
|
|
|
|
stripPointers[1] = &screenBuffer[FRAMEBUFFER_START + OLED_WIDTH];
|
|
|
|
|
#endif
|
|
|
|
|
displayOffset = 0;
|
|
|
|
|
memcpy(&screenBuffer[0], &REFRESH_COMMANDS[0], sizeof(REFRESH_COMMANDS));
|
|
|
|
|
|
|
|
|
|
@@ -133,14 +140,13 @@ void OLED::initialize() {
|
|
|
|
|
initDone = true;
|
|
|
|
|
}
|
|
|
|
|
void OLED::setFramebuffer(uint8_t *buffer) {
|
|
|
|
|
if (buffer == NULL) {
|
|
|
|
|
firstStripPtr = &screenBuffer[FRAMEBUFFER_START];
|
|
|
|
|
secondStripPtr = &screenBuffer[FRAMEBUFFER_START + OLED_WIDTH];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
stripPointers[0] = &buffer[FRAMEBUFFER_START];
|
|
|
|
|
stripPointers[1] = &buffer[FRAMEBUFFER_START + OLED_WIDTH];
|
|
|
|
|
|
|
|
|
|
firstStripPtr = &buffer[0];
|
|
|
|
|
secondStripPtr = &buffer[OLED_WIDTH];
|
|
|
|
|
#ifdef OLED_128x32
|
|
|
|
|
stripPointers[2] = &buffer[FRAMEBUFFER_START + (2 * OLED_WIDTH)];
|
|
|
|
|
stripPointers[3] = &buffer[FRAMEBUFFER_START + (3 * OLED_WIDTH)];
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@@ -233,7 +239,10 @@ void OLED::maskScrollIndicatorOnOLED() {
|
|
|
|
|
|
|
|
|
|
// Start of data
|
|
|
|
|
0x40,
|
|
|
|
|
|
|
|
|
|
#ifdef OLED_128x32
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
#endif
|
|
|
|
|
// Clears two 8px strips
|
|
|
|
|
0x00,
|
|
|
|
|
0x00,
|
|
|
|
|
@@ -249,8 +258,14 @@ void OLED::maskScrollIndicatorOnOLED() {
|
|
|
|
|
* Otherwise a rewinding navigation animation is shown to the second framebuffer contents.
|
|
|
|
|
*/
|
|
|
|
|
void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) {
|
|
|
|
|
uint8_t *firstBackStripPtr = &secondFrameBuffer[0];
|
|
|
|
|
uint8_t *secondBackStripPtr = &secondFrameBuffer[OLED_WIDTH];
|
|
|
|
|
uint8_t *stripBackPointers[4];
|
|
|
|
|
stripBackPointers[0] = &secondFrameBuffer[0];
|
|
|
|
|
stripBackPointers[1] = &secondFrameBuffer[OLED_WIDTH];
|
|
|
|
|
|
|
|
|
|
#ifdef OLED_128x32
|
|
|
|
|
stripBackPointers[2] = &secondFrameBuffer[OLED_WIDTH * 2];
|
|
|
|
|
stripBackPointers[3] = &secondFrameBuffer[OLED_WIDTH * 3];
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
TickType_t totalDuration = TICKS_100MS * 5; // 500ms
|
|
|
|
|
TickType_t duration = 0;
|
|
|
|
|
@@ -262,6 +277,7 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) {
|
|
|
|
|
uint8_t progress = ((duration * 100) / totalDuration); // Percentage of the period we are through for animation
|
|
|
|
|
progress = easeInOutTiming(progress);
|
|
|
|
|
progress = lerp(0, OLED_WIDTH, progress);
|
|
|
|
|
// Constrain
|
|
|
|
|
if (progress > OLED_WIDTH) {
|
|
|
|
|
progress = OLED_WIDTH;
|
|
|
|
|
}
|
|
|
|
|
@@ -278,11 +294,19 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) {
|
|
|
|
|
|
|
|
|
|
offset = progress;
|
|
|
|
|
|
|
|
|
|
memmove(&firstStripPtr[oldStart], &firstStripPtr[oldPrevious], OLED_WIDTH - progress);
|
|
|
|
|
memmove(&secondStripPtr[oldStart], &secondStripPtr[oldPrevious], OLED_WIDTH - progress);
|
|
|
|
|
memmove(&stripPointers[0][oldStart], &stripPointers[0][oldPrevious], OLED_WIDTH - progress);
|
|
|
|
|
memmove(&stripPointers[1][oldStart], &stripPointers[1][oldPrevious], OLED_WIDTH - progress);
|
|
|
|
|
#ifdef OLED_128x32
|
|
|
|
|
memmove(&stripPointers[2][oldStart], &stripPointers[2][oldPrevious], OLED_WIDTH - progress);
|
|
|
|
|
memmove(&stripPointers[3][oldStart], &stripPointers[3][oldPrevious], OLED_WIDTH - progress);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
memmove(&firstStripPtr[newStart], &firstBackStripPtr[newEnd], progress);
|
|
|
|
|
memmove(&secondStripPtr[newStart], &secondBackStripPtr[newEnd], progress);
|
|
|
|
|
memmove(&stripPointers[0][newStart], &stripBackPointers[0][newEnd], progress);
|
|
|
|
|
memmove(&stripPointers[1][newStart], &stripBackPointers[1][newEnd], progress);
|
|
|
|
|
#ifdef OLED_128x32
|
|
|
|
|
memmove(&stripPointers[2][newStart], &stripBackPointers[2][newEnd], progress);
|
|
|
|
|
memmove(&stripPointers[3][newStart], &stripBackPointers[3][newEnd], progress);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
refresh();
|
|
|
|
|
osDelay(TICKS_100MS / 7);
|
|
|
|
|
@@ -296,60 +320,62 @@ void OLED::useSecondaryFramebuffer(bool useSecondary) {
|
|
|
|
|
if (useSecondary) {
|
|
|
|
|
setFramebuffer(secondFrameBuffer);
|
|
|
|
|
} else {
|
|
|
|
|
setFramebuffer(NULL);
|
|
|
|
|
setFramebuffer(screenBuffer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Plays a transition animation of scrolling downward. Note this does *not*
|
|
|
|
|
* use the secondary framebuffer.
|
|
|
|
|
*
|
|
|
|
|
* This transition relies on the previous screen data already in the OLED
|
|
|
|
|
* RAM. The caller shall not call `OLED::refresh()` before calling this
|
|
|
|
|
* method, as doing so will overwrite the previous screen data. The caller
|
|
|
|
|
* does not need to call `OLED::refresh()` after this function returns.
|
|
|
|
|
* This assumes that the current display output buffer has the current on screen contents
|
|
|
|
|
* Then the secondary buffer has the "new" contents to be slid up onto the screen
|
|
|
|
|
* Sadly we cant use the hardware scroll as some devices with the 128x32 screens dont have the GRAM for holding both screens at once
|
|
|
|
|
*
|
|
|
|
|
* **This function blocks until the transition has completed or user presses button**
|
|
|
|
|
*/
|
|
|
|
|
void OLED::transitionScrollDown() {
|
|
|
|
|
// We want to draw the updated framebuffer to the next page downward.
|
|
|
|
|
uint8_t const pageStart = screenBuffer[13];
|
|
|
|
|
uint8_t const nextPage = (pageStart + (OLED_HEIGHT / 8)) % 8;
|
|
|
|
|
// Change page start address:
|
|
|
|
|
screenBuffer[13] = nextPage;
|
|
|
|
|
// Change page end address:
|
|
|
|
|
screenBuffer[15] = (nextPage + 1) % 8;
|
|
|
|
|
|
|
|
|
|
refresh(); // Now refresh to write out the contents to the new page
|
|
|
|
|
osDelay(TICKS_100MS / 5);
|
|
|
|
|
for (uint8_t heightPos = 0; heightPos < OLED_HEIGHT; heightPos++) {
|
|
|
|
|
// For each line, we shuffle all bits up a row
|
|
|
|
|
for (uint8_t xPos = 0; xPos < OLED_WIDTH; xPos++) {
|
|
|
|
|
const uint16_t firstStripPos = FRAMEBUFFER_START + xPos;
|
|
|
|
|
const uint16_t secondStripPos = firstStripPos + OLED_WIDTH;
|
|
|
|
|
#ifdef OLED_128x32
|
|
|
|
|
// For 32 pixel high OLED's we have four strips to tailchain
|
|
|
|
|
const uint16_t thirdStripPos = secondStripPos + OLED_WIDTH;
|
|
|
|
|
const uint16_t fourthStripPos = thirdStripPos + OLED_WIDTH;
|
|
|
|
|
// Move the MSB off the first strip, and pop MSB from second strip onto the first strip
|
|
|
|
|
screenBuffer[firstStripPos] = (screenBuffer[firstStripPos] >> 1) | ((screenBuffer[secondStripPos] & 0x01) << 7);
|
|
|
|
|
// Now shuffle off the second strip
|
|
|
|
|
screenBuffer[secondStripPos] = (screenBuffer[secondStripPos] >> 1) | ((screenBuffer[thirdStripPos] & 0x01) << 7);
|
|
|
|
|
// Now shuffle off the third strip
|
|
|
|
|
screenBuffer[thirdStripPos] = (screenBuffer[thirdStripPos] >> 1) | ((screenBuffer[fourthStripPos] & 0x01) << 7);
|
|
|
|
|
// Now forth strip gets the start of the new buffer
|
|
|
|
|
screenBuffer[fourthStripPos] = (screenBuffer[fourthStripPos] >> 1) | ((secondFrameBuffer[firstStripPos] & 0x01) << 7);
|
|
|
|
|
// Now cycle all the secondary buffers
|
|
|
|
|
|
|
|
|
|
uint8_t startLine = (pageStart * 8) + 1;
|
|
|
|
|
|
|
|
|
|
uint8_t scrollTo = (pageStart + (OLED_HEIGHT / 8)) * 8;
|
|
|
|
|
|
|
|
|
|
// Scroll the screen by changing display start line.
|
|
|
|
|
// This effectively scrolls off the bottom of the current page and into the next one
|
|
|
|
|
for (uint8_t current = startLine; current <= scrollTo; current++) {
|
|
|
|
|
if (getButtonState() != BUTTON_NONE) {
|
|
|
|
|
current = scrollTo;
|
|
|
|
|
secondFrameBuffer[firstStripPos] = (secondFrameBuffer[firstStripPos] >> 1) | ((secondFrameBuffer[secondStripPos] & 0x01) << 7);
|
|
|
|
|
secondFrameBuffer[secondStripPos] = (secondFrameBuffer[secondStripPos] >> 1) | ((secondFrameBuffer[thirdStripPos] & 0x01) << 7);
|
|
|
|
|
secondFrameBuffer[thirdStripPos] = (secondFrameBuffer[thirdStripPos] >> 1) | ((secondFrameBuffer[fourthStripPos] & 0x01) << 7);
|
|
|
|
|
// Finally on the bottom row; we shuffle it up ready
|
|
|
|
|
secondFrameBuffer[fourthStripPos] >>= 1;
|
|
|
|
|
#else
|
|
|
|
|
// Move the MSB off the first strip, and pop MSB from second strip onto the first strip
|
|
|
|
|
screenBuffer[firstStripPos] = (screenBuffer[firstStripPos] >> 1) | ((screenBuffer[secondStripPos] & 0x01) << 7);
|
|
|
|
|
// Now shuffle off the second strip MSB, and replace it with the MSB of the secondary buffer
|
|
|
|
|
screenBuffer[secondStripPos] = (screenBuffer[secondStripPos] >> 1) | ((secondFrameBuffer[firstStripPos] & 0x01) << 7);
|
|
|
|
|
// Finally, do the shuffle on the second frame buffer
|
|
|
|
|
secondFrameBuffer[firstStripPos] = (secondFrameBuffer[firstStripPos] >> 1) | ((secondFrameBuffer[secondStripPos] & 0x01) << 7);
|
|
|
|
|
// Finally on the bottom row; we shuffle it up ready
|
|
|
|
|
secondFrameBuffer[secondStripPos] >>= 1;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set display start line (0x40~0x7F):
|
|
|
|
|
// X[5:0] - display start line value
|
|
|
|
|
uint8_t scrollCommandByte = 0b01000000 | (current & 0b00111111);
|
|
|
|
|
|
|
|
|
|
// Also update setup command for "set display start line":
|
|
|
|
|
OLED_Setup_Array[8].val = scrollCommandByte;
|
|
|
|
|
|
|
|
|
|
I2C_CLASS::I2C_RegisterWrite(DEVICEADDR_OLED, 0x80, scrollCommandByte);
|
|
|
|
|
if (getButtonState() != BUTTON_NONE) {
|
|
|
|
|
// Exit early, but have to transition whole buffer
|
|
|
|
|
memcpy(screenBuffer + FRAMEBUFFER_START, secondFrameBuffer + FRAMEBUFFER_START, sizeof(screenBuffer) - FRAMEBUFFER_START);
|
|
|
|
|
refresh(); // Now refresh to write out the contents to the new page
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
refresh(); // Now refresh to write out the contents to the new page
|
|
|
|
|
osDelay(TICKS_100MS / 7);
|
|
|
|
|
}
|
|
|
|
|
// Now that scroll is done, revert to default page to avoid wrap issues
|
|
|
|
|
screenBuffer[13] = pageStart;
|
|
|
|
|
screenBuffer[15] = (pageStart + 1) % 8;
|
|
|
|
|
uint8_t scrollCommandByte = 0b01000000;
|
|
|
|
|
OLED_Setup_Array[8].val = scrollCommandByte;
|
|
|
|
|
refresh();
|
|
|
|
|
I2C_CLASS::I2C_RegisterWrite(DEVICEADDR_OLED, 0x80, scrollCommandByte);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OLED::setRotation(bool leftHanded) {
|
|
|
|
|
@@ -387,7 +413,7 @@ void OLED::setRotation(bool leftHanded) {
|
|
|
|
|
screenBuffer[7] = inLeftHandedMode ? OLED_GRAM_END_FLIP : OLED_GRAM_END; // End address of the ram segment we are writing to (96 wide)
|
|
|
|
|
screenBuffer[9] = inLeftHandedMode ? 0xC8 : 0xC0;
|
|
|
|
|
// Force a screen refresh
|
|
|
|
|
const int len = FRAMEBUFFER_START + (OLED_WIDTH * 2);
|
|
|
|
|
const int len = FRAMEBUFFER_START + (OLED_WIDTH * (OLED_HEIGHT / 8));
|
|
|
|
|
I2C_CLASS::Transmit(DEVICEADDR_OLED, screenBuffer, len);
|
|
|
|
|
osDelay(TICKS_10MS);
|
|
|
|
|
checkDisplayBufferChecksum();
|
|
|
|
|
@@ -540,15 +566,16 @@ void OLED::drawArea(int16_t x, int8_t y, uint8_t wide, uint8_t height, const uin
|
|
|
|
|
if (y == 0) {
|
|
|
|
|
// Splat first line of data
|
|
|
|
|
for (uint8_t xx = visibleStart; xx < visibleEnd; xx++) {
|
|
|
|
|
firstStripPtr[xx + x] = ptr[xx];
|
|
|
|
|
stripPointers[0][xx + x] = ptr[xx];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (y == 8 || height == 16) {
|
|
|
|
|
if (y == 8 || height >= 16) {
|
|
|
|
|
// Splat the second line
|
|
|
|
|
for (uint8_t xx = visibleStart; xx < visibleEnd; xx++) {
|
|
|
|
|
secondStripPtr[x + xx] = ptr[xx + (height == 16 ? wide : 0)];
|
|
|
|
|
stripPointers[1][x + xx] = ptr[xx + (height == 16 ? wide : 0)];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// TODO NEEDS HEIGHT HANDLERS for 24/32
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Draw an area, but y must be aligned on 0/8 offset
|
|
|
|
|
@@ -574,15 +601,15 @@ void OLED::drawAreaSwapped(int16_t x, int8_t y, uint8_t wide, uint8_t height, co
|
|
|
|
|
if (y == 0) {
|
|
|
|
|
// Splat first line of data
|
|
|
|
|
for (uint8_t xx = visibleStart; xx < visibleEnd; xx += 2) {
|
|
|
|
|
firstStripPtr[xx + x] = ptr[xx + 1];
|
|
|
|
|
firstStripPtr[xx + x + 1] = ptr[xx];
|
|
|
|
|
stripPointers[0][xx + x] = ptr[xx + 1];
|
|
|
|
|
stripPointers[0][xx + x + 1] = ptr[xx];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (y == 8 || height == 16) {
|
|
|
|
|
// Splat the second line
|
|
|
|
|
for (uint8_t xx = visibleStart; xx < visibleEnd; xx += 2) {
|
|
|
|
|
secondStripPtr[x + xx] = ptr[xx + 1 + (height == 16 ? wide : 0)];
|
|
|
|
|
secondStripPtr[x + xx + 1] = ptr[xx + (height == 16 ? wide : 0)];
|
|
|
|
|
stripPointers[1][x + xx] = ptr[xx + 1 + (height == 16 ? wide : 0)];
|
|
|
|
|
stripPointers[1][x + xx + 1] = ptr[xx + (height == 16 ? wide : 0)];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -608,13 +635,13 @@ void OLED::fillArea(int16_t x, int8_t y, uint8_t wide, uint8_t height, const uin
|
|
|
|
|
if (y == 0) {
|
|
|
|
|
// Splat first line of data
|
|
|
|
|
for (uint8_t xx = visibleStart; xx < visibleEnd; xx++) {
|
|
|
|
|
firstStripPtr[xx + x] = value;
|
|
|
|
|
stripPointers[0][xx + x] = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (y == 8 || height == 16) {
|
|
|
|
|
// Splat the second line
|
|
|
|
|
for (uint8_t xx = visibleStart; xx < visibleEnd; xx++) {
|
|
|
|
|
secondStripPtr[x + xx] = value;
|
|
|
|
|
stripPointers[1][x + xx] = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -630,9 +657,9 @@ void OLED::drawFilledRect(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, bool c
|
|
|
|
|
mask = mask << (y0 % 8);
|
|
|
|
|
for (uint8_t col = x0; col < x1; col++)
|
|
|
|
|
if (clear)
|
|
|
|
|
firstStripPtr[(y0 / 8) * 96 + col] &= ~mask;
|
|
|
|
|
stripPointers[0][(y0 / 8) * 96 + col] &= ~mask;
|
|
|
|
|
else
|
|
|
|
|
firstStripPtr[(y0 / 8) * 96 + col] |= mask;
|
|
|
|
|
stripPointers[0][(y0 / 8) * 96 + col] |= mask;
|
|
|
|
|
}
|
|
|
|
|
// Next loop down the line the total number of solids
|
|
|
|
|
if (y0 / 8 != y1 / 8)
|
|
|
|
|
@@ -640,18 +667,18 @@ void OLED::drawFilledRect(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, bool c
|
|
|
|
|
for (uint8_t r = (y0 / 8); r < (y1 / 8); r++) {
|
|
|
|
|
// This gives us the row index r
|
|
|
|
|
if (clear)
|
|
|
|
|
firstStripPtr[(r * 96) + col] = 0;
|
|
|
|
|
stripPointers[0][(r * 96) + col] = 0;
|
|
|
|
|
else
|
|
|
|
|
firstStripPtr[(r * 96) + col] = 0xFF;
|
|
|
|
|
stripPointers[0][(r * 96) + col] = 0xFF;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Finally draw the tail
|
|
|
|
|
mask = ~(mask << (y1 % 8));
|
|
|
|
|
for (uint8_t col = x0; col < x1; col++)
|
|
|
|
|
if (clear)
|
|
|
|
|
firstStripPtr[(y1 / 8) * 96 + col] &= ~mask;
|
|
|
|
|
stripPointers[0][(y1 / 8) * 96 + col] &= ~mask;
|
|
|
|
|
else
|
|
|
|
|
firstStripPtr[(y1 / 8) * 96 + col] |= mask;
|
|
|
|
|
stripPointers[0][(y1 / 8) * 96 + col] |= mask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OLED::drawHeatSymbol(uint8_t state) {
|
|
|
|
|
|