mirror of
https://github.com/Ralim/IronOS.git
synced 2025-02-26 07:53:55 +00:00
Merge branch 'master' into MHP30
This commit is contained in:
@@ -59,7 +59,38 @@ I2C_CLASS::I2C_REG OLED_Setup_Array[] = {
|
||||
};
|
||||
// Setup based on the SSD1307 and modified for the SSD1306
|
||||
|
||||
const uint8_t REFRESH_COMMANDS[17] = {0x80, 0xAF, 0x80, 0x21, 0x80, 0x20, 0x80, 0x7F, 0x80, 0xC0, 0x80, 0x22, 0x80, 0x00, 0x80, 0x01, 0x40};
|
||||
const uint8_t REFRESH_COMMANDS[17] = {
|
||||
// Set display ON:
|
||||
0x80,
|
||||
0xAF, // cmd
|
||||
|
||||
// Set column address:
|
||||
// A[6:0] - Column start address = 0x20
|
||||
// B[6:0] - Column end address = 0x7F
|
||||
0x80,
|
||||
0x21, // cmd
|
||||
0x80,
|
||||
0x20, // A
|
||||
0x80,
|
||||
0x7F, // B
|
||||
|
||||
// Set COM output scan direction (normal mode, COM0 to COM[N-1])
|
||||
0x80,
|
||||
0xC0,
|
||||
|
||||
// Set page address:
|
||||
// A[2:0] - Page start address = 0
|
||||
// B[2:0] - Page end address = 1
|
||||
0x80,
|
||||
0x22, // cmd
|
||||
0x80,
|
||||
0x00, // A
|
||||
0x80,
|
||||
0x01, // B
|
||||
|
||||
// Start of data
|
||||
0x40,
|
||||
};
|
||||
|
||||
/*
|
||||
* Animation timing function that follows a bezier curve.
|
||||
@@ -180,6 +211,36 @@ void OLED::drawScrollIndicator(uint8_t y, uint8_t height) {
|
||||
fillArea(OLED_WIDTH - 1, 8, 1, 8, column.strips[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Masks (removes) the scrolling indicator, i.e. clears the rightmost column
|
||||
* on the screen. This operates directly on the OLED graphics RAM, as this
|
||||
* is intended to be used before calling `OLED::transitionScrollDown()`.
|
||||
*/
|
||||
void OLED::maskScrollIndicatorOnOLED() {
|
||||
// The right-most column depends on the screen rotation, so just take
|
||||
// it from the screen buffer which is updated by `OLED::setRotation`.
|
||||
uint8_t rightmostColumn = screenBuffer[7];
|
||||
uint8_t maskCommands[] = {
|
||||
// Set column address:
|
||||
// A[6:0] - Column start address = rightmost column
|
||||
// B[6:0] - Column end address = rightmost column
|
||||
0x80,
|
||||
0x21, // cmd
|
||||
0x80,
|
||||
rightmostColumn, // A
|
||||
0x80,
|
||||
rightmostColumn, // B
|
||||
|
||||
// Start of data
|
||||
0x40,
|
||||
|
||||
// Clears two 8px strips
|
||||
0x00,
|
||||
0x00,
|
||||
};
|
||||
FRToSI2C::Transmit(DEVICEADDR_OLED, maskCommands, sizeof(maskCommands));
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays a transition animation between two framebuffers.
|
||||
* @param forwardNavigation Direction of the navigation animation.
|
||||
@@ -235,6 +296,45 @@ void OLED::useSecondaryFramebuffer(bool useSecondary) {
|
||||
setFramebuffer(NULL);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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 function blocks until the transition has completed.**
|
||||
*/
|
||||
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 + 2) % 8;
|
||||
// Change page start address:
|
||||
screenBuffer[13] = nextPage;
|
||||
// Change page end address:
|
||||
screenBuffer[15] = nextPage + 1;
|
||||
|
||||
refresh();
|
||||
osDelay(TICKS_100MS / 5);
|
||||
|
||||
uint8_t const startLine = pageStart * 8 + 1;
|
||||
uint8_t const scrollTo = (pageStart + 2) * 8;
|
||||
|
||||
// Scroll the screen by changing display start line.
|
||||
for (uint8_t current = startLine; current <= scrollTo; current++) {
|
||||
// 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;
|
||||
|
||||
FRToSI2C::I2C_RegisterWrite(DEVICEADDR_OLED, 0x80, scrollCommandByte);
|
||||
osDelay(TICKS_100MS / 5);
|
||||
}
|
||||
}
|
||||
|
||||
void OLED::setRotation(bool leftHanded) {
|
||||
#ifdef OLED_FLIP
|
||||
|
||||
@@ -88,8 +88,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 drawScrollIndicator(uint8_t p, uint8_t h); // Draws a scrolling position indicator
|
||||
static void maskScrollIndicatorOnOLED();
|
||||
static void transitionSecondaryFramebuffer(bool forwardNavigation);
|
||||
static void useSecondaryFramebuffer(bool useSecondary);
|
||||
static void transitionScrollDown();
|
||||
|
||||
private:
|
||||
static void drawChar(uint16_t charCode, FontStyle fontStyle); // Draw a character to the current cursor location
|
||||
|
||||
@@ -1063,6 +1063,7 @@ void gui_Menu(const menuitem *menu) {
|
||||
uint8_t scrollContentSize = 0;
|
||||
bool scrollBlink = false;
|
||||
bool lastValue = false;
|
||||
bool scrollingDown = false;
|
||||
|
||||
ScrollMessage scrollMessage;
|
||||
|
||||
@@ -1088,6 +1089,10 @@ void gui_Menu(const menuitem *menu) {
|
||||
|
||||
while ((menu[currentScreen].draw != nullptr) && earlyExit == false) {
|
||||
OLED::setCursor(0, 0);
|
||||
if (scrollingDown) {
|
||||
animOpenState = true;
|
||||
}
|
||||
|
||||
// If the user has hesitated for >=3 seconds, show the long text
|
||||
// Otherwise "draw" the option
|
||||
if ((xTaskGetTickCount() - lastButtonTime < (TICKS_SECOND * 3)) || menu[currentScreen].description == 0) {
|
||||
@@ -1101,7 +1106,7 @@ void gui_Menu(const menuitem *menu) {
|
||||
uint8_t position = OLED_HEIGHT * currentScreen / scrollContentSize;
|
||||
if (lastValue)
|
||||
scrollBlink = !scrollBlink;
|
||||
if (!lastValue || !scrollBlink)
|
||||
if ((!lastValue || !scrollBlink) && !scrollingDown)
|
||||
OLED::drawScrollIndicator(position, indicatorHeight);
|
||||
} else {
|
||||
// Draw description
|
||||
@@ -1109,6 +1114,19 @@ void gui_Menu(const menuitem *menu) {
|
||||
lcdRefresh |= scrollMessage.drawUpdate(description, xTaskGetTickCount());
|
||||
}
|
||||
|
||||
if (lcdRefresh) {
|
||||
if (scrollingDown) {
|
||||
OLED::maskScrollIndicatorOnOLED();
|
||||
OLED::transitionScrollDown();
|
||||
scrollingDown = false;
|
||||
animOpenState = false;
|
||||
} else {
|
||||
OLED::refresh(); // update the LCD
|
||||
osDelay(40);
|
||||
}
|
||||
lcdRefresh = false;
|
||||
}
|
||||
|
||||
ButtonState buttons = getButtonState();
|
||||
|
||||
if (buttons != lastButtonState) {
|
||||
@@ -1135,7 +1153,8 @@ void gui_Menu(const menuitem *menu) {
|
||||
case BUTTON_B_SHORT:
|
||||
if (scrollMessage.isReset()) {
|
||||
currentScreen++;
|
||||
lastValue = false;
|
||||
scrollingDown = true;
|
||||
lastValue = false;
|
||||
} else
|
||||
scrollMessage.reset();
|
||||
break;
|
||||
@@ -1156,6 +1175,7 @@ void gui_Menu(const menuitem *menu) {
|
||||
case BUTTON_B_LONG:
|
||||
if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) {
|
||||
currentScreen++;
|
||||
scrollingDown = true;
|
||||
autoRepeatTimer = xTaskGetTickCount();
|
||||
scrollMessage.reset();
|
||||
|
||||
@@ -1171,11 +1191,6 @@ void gui_Menu(const menuitem *menu) {
|
||||
autoRepeatAcceleration = PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN;
|
||||
}
|
||||
|
||||
if (lcdRefresh) {
|
||||
OLED::refresh(); // update the LCD
|
||||
osDelay(40);
|
||||
lcdRefresh = false;
|
||||
}
|
||||
if ((xTaskGetTickCount() - lastButtonTime) > (TICKS_SECOND * 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
|
||||
@@ -1183,6 +1198,8 @@ void gui_Menu(const menuitem *menu) {
|
||||
scrollMessage.reset();
|
||||
}
|
||||
}
|
||||
|
||||
animOpenState = false;
|
||||
}
|
||||
|
||||
void enterSettingsMenu() {
|
||||
|
||||
Reference in New Issue
Block a user