1
0
forked from me/IronOS

Add navigation animations

This commit is contained in:
Patrick Horlebein
2020-04-03 22:40:03 +02:00
parent d45b1d7e27
commit 81abd5eeac
3 changed files with 105 additions and 4 deletions

View File

@@ -78,7 +78,7 @@ public:
// Draws a number at the current cursor location
// Clears the buffer
static void clearScreen() {
memset(&screenBuffer[FRAMEBUFFER_START], 0, OLED_WIDTH * 2);
memset(firstStripPtr, 0, OLED_WIDTH * 2);
}
// Draws the battery level symbol
static void drawBattery(uint8_t state) {
@@ -99,6 +99,10 @@ public:
static void drawFilledRect(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1,
bool clear);
static void drawHeatSymbol(uint8_t state);
static void presentSecondScreenBufferAnimatedBack();
static void presentSecondScreenBufferAnimated();
static void use_first_buffer();
static void use_second_buffer();
private:
static void drawChar(char c); // Draw a character to a specific location
static const uint8_t* currentFont;// Pointer to the current font used for rendering to the buffer
@@ -110,6 +114,7 @@ private:
static int16_t cursor_x, cursor_y;
static uint8_t displayOffset;
static uint8_t screenBuffer[16 + (OLED_WIDTH * 2) + 10]; // The data buffer
static uint8_t secondFrameBuffer[OLED_WIDTH * 2]; // The second frame buffer
};
#endif /* OLED_HPP_ */

View File

@@ -24,6 +24,7 @@ uint8_t OLED::fontWidth, OLED::fontHeight;
int16_t OLED::cursor_x, OLED::cursor_y;
uint8_t OLED::displayOffset;
uint8_t OLED::screenBuffer[16 + (OLED_WIDTH * 2) + 10]; // The data buffer
uint8_t OLED::secondFrameBuffer[OLED_WIDTH * 2]; // The second frame buffer
/*Setup params for the OLED screen*/
/*http://www.displayfuture.com/Display/datasheet/controller/SSD1307.pdf*/
@@ -85,6 +86,16 @@ void OLED::initialize() {
sizeof(OLED_Setup_Array));
}
void OLED::use_first_buffer() {
firstStripPtr = &screenBuffer[FRAMEBUFFER_START];
secondStripPtr = &screenBuffer[FRAMEBUFFER_START + OLED_WIDTH];
}
void OLED::use_second_buffer() {
firstStripPtr = &secondFrameBuffer[0];
secondStripPtr = &secondFrameBuffer[OLED_WIDTH];
}
/*
* Prints a char to the screen.
* UTF font handling is done using the two input chars.
@@ -106,6 +117,74 @@ void OLED::drawChar(char c) {
cursor_x += fontWidth;
}
void OLED::presentSecondScreenBufferAnimatedBack() {
OLED::use_first_buffer();
uint32_t totalDuration = 50;
uint32_t duration = 0;
uint32_t start = xTaskGetTickCount();
uint8_t offset = 0;
while (duration <= totalDuration)
{
duration = xTaskGetTickCount() - start;
uint8_t progress = (duration * OLED_WIDTH) / totalDuration;
for (uint8_t i = OLED_WIDTH - 1; i > progress; i--) {
firstStripPtr[i] = firstStripPtr[(i - progress) + offset];
secondStripPtr[i] = secondStripPtr[(i - progress) + offset];
}
offset = progress;
uint8_t *firstBackStripPtr = &secondFrameBuffer[0];
uint8_t *secondBackStripPtr = &secondFrameBuffer[OLED_WIDTH];
for (uint8_t i = 0; i < progress; i++) {
firstStripPtr[i] = firstBackStripPtr[(i - progress) + OLED_WIDTH];
secondStripPtr[i] = secondBackStripPtr[(i - progress) + OLED_WIDTH];
}
refresh();
osDelay(40);
}
}
void OLED::presentSecondScreenBufferAnimated() {
OLED::use_first_buffer();
uint32_t totalDuration = 50;
uint32_t duration = 0;
uint32_t start = xTaskGetTickCount();
uint8_t offset = 0;
while (duration < totalDuration)
{
duration = xTaskGetTickCount() - start;
uint8_t progress = (duration * OLED_WIDTH) / totalDuration;
for (uint8_t i = 0; i < OLED_WIDTH - progress; i++) {
firstStripPtr[i] = firstStripPtr[i + progress - offset];
secondStripPtr[i] = secondStripPtr[i + progress - offset];
}
offset = progress;
uint8_t *firstBackStripPtr = &secondFrameBuffer[0];
uint8_t *secondBackStripPtr = &secondFrameBuffer[OLED_WIDTH];
for (uint8_t i = OLED_WIDTH - progress; i < OLED_WIDTH; i++) {
firstStripPtr[i] = firstBackStripPtr[i - (OLED_WIDTH - progress)];
secondStripPtr[i] = secondBackStripPtr[i - (OLED_WIDTH - progress)];
}
refresh();
osDelay(40);
}
}
void OLED::setRotation(bool leftHanded) {
#ifdef MODEL_TS80
leftHanded = !leftHanded;

View File

@@ -823,6 +823,15 @@ void gui_Menu(const menuitem *menu) {
int16_t lastOffset = -1;
bool lcdRefresh = true;
ButtonState lastButtonState = BUTTON_NONE;
if (menu[currentScreen].draw.func != NULL) {
OLED::use_second_buffer();
OLED::setFont(0);
OLED::setCursor(0, 0);
OLED::clearScreen();
menu[currentScreen].draw.func();
OLED::presentSecondScreenBufferAnimated();
}
while ((menu[currentScreen].draw.func != NULL) && earlyExit == false) {
OLED::setFont(0);
@@ -871,10 +880,18 @@ void gui_Menu(const menuitem *menu) {
case BUTTON_F_SHORT:
// increment
if (descriptionStart == 0) {
if (menu[currentScreen].incrementHandler.func != NULL)
if (menu[currentScreen].incrementHandler.func != NULL) {
menu[currentScreen].incrementHandler.func();
else
// MARK: Might jump in submenu here
OLED::use_second_buffer();
OLED::setFont(0);
OLED::setCursor(0, 0);
OLED::clearScreen();
menu[currentScreen].draw.func();
OLED::presentSecondScreenBufferAnimatedBack();
} else {
earlyExit = true;
}
} else
descriptionStart = 0;
break;
@@ -920,7 +937,7 @@ void gui_Menu(const menuitem *menu) {
osDelay(40);
lcdRefresh = false;
}
if ((xTaskGetTickCount() - lastButtonTime) > (1000 * 30)) {
if ((xTaskGetTickCount() - lastButtonTime) > (100 * 30)) {
// If user has not pressed any buttons in 30 seconds, exit back a menu layer
// This will trickle the user back to the main screen eventually
earlyExit = true;