WIP: Split Render for multiple screen resolutions (#1888)

* Create README.md

* Move to new folder

* Migrating

* Migrate Remainder

* format fix (all but one) (#1889)

* Update USBPDDebug_FS2711.cpp

* Delete PrintVoltage.cpp

* Copy in 128x32 template

* Mask drawing for 96x16

* Import #1819

* Update Font.h

* Homescreen

* Update draw_homescreen_detailed.cpp

* Fix oled normal draw for variable height

* Update OLED.cpp

* Draw settings icons

* Update draw_homescreen_simplified.cpp

* Update draw_power_source_icon.cpp

* Fixup oled drawing for fill area

* Update the region fill for mixed heights

* Fix newline height

* FIXUP! Draw icons in settings menu at correct size

* Fix scrollbar

* Update settingsGUI.cpp

* S60(P) Disable auto display rotation

* On tall oled, scroll in 2 line increments

* Bugfix transition L<->R

@discip I take it back, there was a bug :)

* Draw every other one on transitions

* .

* cleanup

* Bootup logo: Draw in centre

* Update OLED.hpp

---------

Co-authored-by: discip <53649486+discip@users.noreply.github.com>
This commit is contained in:
Ben V. Brown
2024-07-12 08:27:05 +10:00
committed by GitHub
parent 18e936ae6d
commit 48649908a7
76 changed files with 2052 additions and 1588 deletions

View File

@@ -57,6 +57,7 @@
*
*/
#define ORIENTATION_MODE 0 // 0: Right 1:Left 2:Automatic - Default right
#define MAX_ORIENTATION_MODE 1 // Unlikely to ever change
#define REVERSE_BUTTON_TEMP_CHANGE 0 // 0:Default 1:Reverse - Reverse the plus and minus button assigment for temperature change
/**
@@ -151,7 +152,7 @@
#define ACCEL_MSA
#define PROFILE_SUPPORT
#define OLED_96x16 1
#define POW_PD 1
#define POW_PD_EXT 0
#define USB_PD_EPR_WATTAGE 0 /*No EPR*/

View File

@@ -57,6 +57,7 @@
*
*/
#define ORIENTATION_MODE 2 // 0: Right 1:Left 2:Automatic - Default Automatic
#define MAX_ORIENTATION_MODE 2 // Up to auto
#define REVERSE_BUTTON_TEMP_CHANGE 0 // 0:Default 1:Reverse - Reverse the plus and minus button assigment for temperature change
/**
@@ -276,6 +277,7 @@
#else
#define FLASH_LOGOADDR (0x08000000 + (62 * 1024))
#define SETTINGS_START_PAGE (0x08000000 + (63 * 1024))
#define OLED_96x16 1
#endif /* TS101 */
#endif /* CONFIGURATION_H_ */

View File

@@ -57,6 +57,7 @@
*
*/
#define ORIENTATION_MODE 2 // 0: Right 1:Left 2:Automatic - Default Automatic
#define MAX_ORIENTATION_MODE 2 // Up to auto
#define REVERSE_BUTTON_TEMP_CHANGE 0 // 0:Default 1:Reverse - Reverse the plus and minus button assigment for temperature change
/**
@@ -145,14 +146,15 @@
#define MIN_BOOST_TEMP_C 250 // The min settable temp for boost mode °C
#define MIN_BOOST_TEMP_F 480 // The min settable temp for boost mode °F
#define OLED_96x16 1
#define POW_PD 1
#define USB_PD_EPR_WATTAGE 0 /*No EPR (Yet?) */
#define POW_PD_EXT 0
#define POW_QC 1
#define POW_DC 1
#define POW_QC_20V 1
#define ENABLE_QC2 1
#define MAG_SLEEP_SUPPORT 1
#define POW_PD_EXT 0
#define POW_QC 1
#define POW_DC 1
#define POW_QC_20V 1
#define ENABLE_QC2 1
#define MAG_SLEEP_SUPPORT 1
#define TEMP_TMP36
#define ACCEL_BMA
#define ACCEL_SC7

View File

@@ -57,6 +57,7 @@
*
*/
#define ORIENTATION_MODE 2 // 0: Right 1:Left 2:Automatic - Default Automatic
#define MAX_ORIENTATION_MODE 2 // Up to auto
#define REVERSE_BUTTON_TEMP_CHANGE 0 // 0:Default 1:Reverse - Reverse the plus and minus button assigment for temperature change
/**
@@ -155,6 +156,7 @@
#define ENABLE_QC2 1
#define MAG_SLEEP_SUPPORT 1
#define DEVICE_HAS_VALIDATION_SUPPORT
#define OLED_96x16 1
#define TEMP_NTC
#define ACCEL_BMA
#define CUSTOM_MAX_TEMP_C 1 // Uses custom max temp lookup

View File

@@ -65,7 +65,8 @@
* OLED Orientation
*
*/
#define ORIENTATION_MODE 0 // 0: Right 1:Left 2:Automatic - Default Automatic
#define ORIENTATION_MODE 0 // 0: Right 1:Left (2:Automatic N/A)
#define MAX_ORIENTATION_MODE 1 // Disable auto mode
#define REVERSE_BUTTON_TEMP_CHANGE 0 // 0:Default 1:Reverse - Reverse the plus and minus button assigment for temperature change
/**

View File

@@ -15,6 +15,7 @@ void delay() {
}
void BootLogo::handleShowingLogo(const uint8_t *ptrLogoArea) {
OLED::clearScreen();
// Read the first few bytes and figure out what format we are looking at
if (OLD_LOGO_HEADER_VALUE == *(reinterpret_cast<const uint32_t *>(ptrLogoArea))) {
showOldFormat(ptrLogoArea);
@@ -23,11 +24,17 @@ void BootLogo::handleShowingLogo(const uint8_t *ptrLogoArea) {
}
OLED::clearScreen();
OLED::refresh();
}
void BootLogo::showOldFormat(const uint8_t *ptrLogoArea) {
#ifdef OLED_128x32
// Draw in middle
OLED::drawAreaSwapped(16, 8, 96, 16, (uint8_t *)(ptrLogoArea + 4));
#else
OLED::drawAreaSwapped(0, 0, 96, 16, (uint8_t *)(ptrLogoArea + 4));
#endif
OLED::refresh();
// Delay here with static logo until a button is pressed or its been the amount of seconds set by the user
delay();
@@ -85,8 +92,12 @@ int BootLogo::showNewFrame(const uint8_t *ptrLogoArea) {
return 1;
break;
case 0xFF:
// Full frame update
// Full frame update
#ifdef OLED_128x32
OLED::drawArea(16, 8, 96, 16, ptrLogoArea + 1);
#else
OLED::drawArea(0, 0, 96, 16, ptrLogoArea + 1);
#endif
length = 96;
break;
default:
@@ -95,7 +106,11 @@ int BootLogo::showNewFrame(const uint8_t *ptrLogoArea) {
for (int p = 0; p < length; p++) {
uint8_t index = ptrLogoArea[1 + (p * 2)];
uint8_t value = ptrLogoArea[2 + (p * 2)];
#ifdef OLED_128x32
OLED::drawArea(16 + (index % 96), index >= 96 ? 16 : 8, 1, 8, &value);
#else
OLED::drawArea(index % 96, index >= 96 ? 8 : 0, 1, 8, &value);
#endif
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -174,12 +174,6 @@ void OLED::drawChar(const uint16_t charCode, const FontStyle fontStyle, const ui
case FontStyle::SMALL:
case FontStyle::LARGE:
default:
if (charCode == '\x01' && cursor_y == 0) { // 0x01 is used as new line char
setCursor(soft_x_limit, 8);
return;
} else if (charCode <= 0x01) {
return;
}
currentFont = nullptr;
index = 0;
switch (fontStyle) {
@@ -193,6 +187,12 @@ void OLED::drawChar(const uint16_t charCode, const FontStyle fontStyle, const ui
fontWidth = 12;
break;
}
if (charCode == '\x01' && cursor_y == 0) { // 0x01 is used as new line char
setCursor(soft_x_limit, fontHeight);
return;
} else if (charCode <= 0x01) {
return;
}
currentFont = fontStyle == FontStyle::SMALL ? FontSectionInfo.font06_start_ptr : FontSectionInfo.font12_start_ptr;
index = charCode - 2;
@@ -209,17 +209,22 @@ void OLED::drawChar(const uint16_t charCode, const FontStyle fontStyle, const ui
*/
void OLED::drawScrollIndicator(uint8_t y, uint8_t height) {
union u_type {
uint16_t whole;
uint8_t strips[2];
uint32_t whole;
uint8_t strips[4];
} column;
column.whole = (1 << height) - 1;
column.whole <<= y;
column.whole = (1 << height) - 1; // preload a set of set bits of height
column.whole <<= y; // Shift down by the y value
// Draw a one pixel wide bar to the left with a single pixel as
// the scroll indicator.
fillArea(OLED_WIDTH - 1, 0, 1, 8, column.strips[0]);
fillArea(OLED_WIDTH - 1, 8, 1, 8, column.strips[1]);
#if OLED_HEIGHT == 32
fillArea(OLED_WIDTH - 1, 16, 1, 8, column.strips[2]);
fillArea(OLED_WIDTH - 1, 24, 1, 8, column.strips[3]);
#endif
}
/**
@@ -269,16 +274,18 @@ void OLED::transitionSecondaryFramebuffer(const bool forwardNavigation, const Ti
stripBackPointers[1] = &secondFrameBuffer[FRAMEBUFFER_START + OLED_WIDTH];
#ifdef OLED_128x32
stripBackPointers[2] = &secondFrameBuffer[OLED_WIDTH * 2];
stripBackPointers[3] = &secondFrameBuffer[OLED_WIDTH * 3];
stripBackPointers[2] = &secondFrameBuffer[FRAMEBUFFER_START + (OLED_WIDTH * 2)];
stripBackPointers[3] = &secondFrameBuffer[FRAMEBUFFER_START + (OLED_WIDTH * 3)];
#endif /* OLED_128x32 */
TickType_t totalDuration = TICKS_100MS * 5; // 500ms
TickType_t duration = 0;
TickType_t start = xTaskGetTickCount();
uint8_t offset = 0;
uint32_t loopCounter = 0;
TickType_t startDraw = xTaskGetTickCount();
while (duration <= totalDuration) {
loopCounter++;
duration = xTaskGetTickCount() - start;
uint16_t progress = ((duration * 100) / totalDuration); // Percentage of the period we are through for animation
progress = easeInOutTiming(progress);
@@ -316,7 +323,14 @@ void OLED::transitionSecondaryFramebuffer(const bool forwardNavigation, const Ti
memmove(&stripPointers[3][newStart], &stripBackPointers[3][newEnd], progress);
#endif /* OLED_128x32 */
#ifdef OLED_128x32
if (loopCounter % 2 == 0) {
refresh();
}
#else
refresh(); // Now refresh to write out the contents to the new page
#endif /* OLED_128x32 */
vTaskDelayUntil(&startDraw, TICKS_100MS / 7);
buttonsReleased |= getButtonState() == BUTTON_NONE;
if (getButtonState() != BUTTON_NONE && buttonsReleased) {
@@ -325,7 +339,7 @@ void OLED::transitionSecondaryFramebuffer(const bool forwardNavigation, const Ti
return;
}
}
refresh(); //
refresh(); // redraw at the end if required
}
void OLED::useSecondaryFramebuffer(bool useSecondary) {
@@ -389,7 +403,14 @@ void OLED::transitionScrollDown(const TickType_t viewEnterTime) {
refresh(); // Now refresh to write out the contents to the new page
return;
}
#ifdef OLED_128x32
// To keep things faster, only redraw every second line
if (heightPos % 2 == 0) {
refresh(); // Now refresh to write out the contents to the new page
}
#else
refresh(); // Now refresh to write out the contents to the new page
#endif
vTaskDelayUntil(&startDraw, TICKS_100MS / 7);
}
}
@@ -443,7 +464,15 @@ void OLED::transitionScrollUp(const TickType_t viewEnterTime) {
refresh(); // Now refresh to write out the contents to the new page
return;
}
#ifdef OLED_128x32
// To keep things faster, only redraw every second line
if (heightPos % 2 == 0) {
refresh(); // Now refresh to write out the contents to the new page
}
#else
refresh(); // Now refresh to write out the contents to the new page
#endif
vTaskDelayUntil(&startDraw, TICKS_100MS / 7);
}
}
@@ -639,76 +668,65 @@ void OLED::drawSymbol(uint8_t symbolID) {
}
// Draw an area, but y must be aligned on 0/8 offset
void OLED::drawArea(int16_t x, int8_t y, uint8_t wide, uint8_t height, const uint8_t *ptr) {
// Splat this from x->x+wide in two strides
if (x <= -wide) {
void OLED::drawArea(int16_t x, int8_t y, uint8_t width, uint8_t height, const uint8_t *ptr) {
// Splat this from x->x+width in two strides
if (x <= -width) {
return; // cutoffleft
}
if (x > 96) {
if (x > OLED_WIDTH) {
return; // cutoff right
}
uint8_t visibleStart = 0;
uint8_t visibleEnd = wide;
uint8_t visibleEnd = width;
// trimming to draw partials
if (x < 0) {
visibleStart -= x; // subtract negative value == add absolute value
}
if (x + wide > 96) {
visibleEnd = 96 - x;
if (x + width > OLED_WIDTH) {
visibleEnd = OLED_WIDTH - x;
}
if (y == 0) {
// Splat first line of data
uint8_t rowsDrawn = 0;
while (height > 0) {
for (uint8_t xx = visibleStart; xx < visibleEnd; xx++) {
stripPointers[0][xx + x] = ptr[xx];
stripPointers[(y / 8) + rowsDrawn][x + xx] = ptr[xx + (rowsDrawn * width)];
}
height -= 8;
rowsDrawn++;
}
if (y == 8 || height >= 16) {
// Splat the second line
for (uint8_t xx = visibleStart; xx < visibleEnd; xx++) {
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
// For data which has octets swapped in a 16-bit word.
void OLED::drawAreaSwapped(int16_t x, int8_t y, uint8_t wide, uint8_t height, const uint8_t *ptr) {
// Splat this from x->x+wide in two strides
if (x <= -wide) {
void OLED::drawAreaSwapped(int16_t x, int8_t y, uint8_t width, uint8_t height, const uint8_t *ptr) {
// Splat this from x->x+width in two strides
if (x <= -width) {
return; // cutoffleft
}
if (x > 96) {
if (x > OLED_WIDTH) {
return; // cutoff right
}
uint8_t visibleStart = 0;
uint8_t visibleEnd = wide;
uint8_t visibleEnd = width;
// trimming to draw partials
if (x < 0) {
visibleStart -= x; // subtract negative value == add absolute value
}
if (x + wide > 96) {
visibleEnd = 96 - x;
if (x + width > OLED_WIDTH) {
visibleEnd = OLED_WIDTH - x;
}
if (y == 0) {
// Splat first line of data
uint8_t rowsDrawn = 0;
while (height > 0) {
for (uint8_t xx = visibleStart; xx < visibleEnd; xx += 2) {
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) {
stripPointers[1][x + xx] = ptr[xx + 1 + (height == 16 ? wide : 0)];
stripPointers[1][x + xx + 1] = ptr[xx + (height == 16 ? wide : 0)];
stripPointers[(y / 8) + rowsDrawn][x + xx] = ptr[xx + 1 + (rowsDrawn * width)];
stripPointers[(y / 8) + rowsDrawn][x + xx + 1] = ptr[xx + (rowsDrawn * width)];
}
height -= 8;
rowsDrawn++;
}
}
@@ -717,7 +735,7 @@ void OLED::fillArea(int16_t x, int8_t y, uint8_t wide, uint8_t height, const uin
if (x <= -wide) {
return; // cutoffleft
}
if (x > 96) {
if (x > OLED_WIDTH) {
return; // cutoff right
}
@@ -728,63 +746,43 @@ void OLED::fillArea(int16_t x, int8_t y, uint8_t wide, uint8_t height, const uin
if (x < 0) {
visibleStart -= x; // subtract negative value == add absolute value
}
if (x + wide > 96) {
visibleEnd = 96 - x;
if (x + wide > OLED_WIDTH) {
visibleEnd = OLED_WIDTH - x;
}
if (y == 0) {
// Splat first line of data
uint8_t rowsDrawn = 0;
while (height > 0) {
for (uint8_t xx = visibleStart; xx < visibleEnd; xx++) {
stripPointers[0][xx + x] = value;
}
}
if (y == 8 || height == 16) {
// Splat the second line
for (uint8_t xx = visibleStart; xx < visibleEnd; xx++) {
stripPointers[1][x + xx] = value;
stripPointers[(y / 8) + rowsDrawn][x + xx] = value;
}
height -= 8;
rowsDrawn++;
}
}
void OLED::drawFilledRect(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, bool clear) {
//!! LSB is at the top of the screen !!
// Draw this in 3 sections
// This is basically a N wide version of vertical line
uint8_t remainingHeight = y1 - y0;
for (uint8_t currentRow = y0 / 8; (currentRow < (OLED_HEIGHT / 8)) && remainingHeight; currentRow++) {
uint8_t maskTop = (0xFF) << (y0 % 8); // Shift off the mask
y0 = 0; // Blank out any start offset for future iterations
// If we are terminating the bottom of the rectangle in this row, we mask the bottom side of things too
if (remainingHeight <= 8) {
uint8_t maskBottom = ~((0xFF) << y1 % 8); // Create mask for
maskTop = maskTop & maskBottom; // AND the two masks together for final write mask
}
// Step 1 : Draw in the top few pixels that are not /8 aligned
// LSB is at the top of the screen
uint8_t mask = 0xFF;
if (y0) {
mask = mask << (y0 % 8);
for (uint8_t col = x0; col < x1; col++) {
for (uint8_t xpos = x0; xpos < x1; xpos++) {
if (clear) {
stripPointers[0][(y0 / 8) * 96 + col] &= ~mask;
stripPointers[currentRow][xpos] &= ~maskTop;
} else {
stripPointers[0][(y0 / 8) * 96 + col] |= mask;
stripPointers[currentRow][xpos] |= maskTop;
}
}
}
// Next loop down the line the total number of solids
if (y0 / 8 != y1 / 8) {
for (uint8_t col = x0; col < x1; col++) {
for (uint8_t r = (y0 / 8); r < (y1 / 8); r++) {
// This gives us the row index r
if (clear) {
stripPointers[0][(r * 96) + col] = 0;
} else {
stripPointers[0][(r * 96) + col] = 0xFF;
}
}
}
}
// Finally draw the tail
mask = ~(mask << (y1 % 8));
for (uint8_t col = x0; col < x1; col++) {
if (clear) {
stripPointers[0][(y1 / 8) * 96 + col] &= ~mask;
} else {
stripPointers[0][(y1 / 8) * 96 + col] |= mask;
}
remainingHeight -= 8; // Reduce remaining height but the row stripe height
}
}

View File

@@ -136,7 +136,7 @@ public:
static void drawBattery(uint8_t state) { drawSymbol(3 + (state > 10 ? 10 : state)); }
// Draws a checkbox
static void drawCheckbox(bool state) { drawSymbol((state) ? 16 : 17); }
inline static void drawUnavailableIcon() { drawArea(OLED_WIDTH - 16 - 2, 0, 16, 16, UnavailableIcon); }
inline static void drawUnavailableIcon() { drawArea(OLED_WIDTH - OLED_HEIGHT - 2, 0, OLED_HEIGHT, OLED_HEIGHT, UnavailableIcon); }
static void debugNumber(int32_t val, FontStyle fontStyle);
static void drawHex(uint32_t x, FontStyle fontStyle, uint8_t digits);
static void drawSymbol(uint8_t symbolID); // Used for drawing symbols of a predictable width

View File

@@ -36,7 +36,6 @@ typedef struct {
} menuitem;
void enterSettingsMenu();
bool warnUser(const char *warning, const ButtonState buttons);
extern const menuitem rootSettingsMenu[];
extern const menuitem *subSettingsMenus[];

View File

@@ -57,7 +57,7 @@ static const SettingConstants settingsConstants[(int)SettingsOptions::SettingsOp
{ 0, 4, 1, CUT_OUT_SETTING}, // MinDCVoltageCells
{ 24, 38, 1, RECOM_VOL_CELL}, // MinVoltageCells
{ 90, QC_VOLTAGE_MAX, 2, 90}, // QCIdealVoltage
{ 0, 2, 1, ORIENTATION_MODE}, // OrientationMode
{ 0, MAX_ORIENTATION_MODE, 1, ORIENTATION_MODE}, // OrientationMode
{ 0, 9, 1, SENSITIVITY}, // Sensitivity
{ 0, 1, 1, ANIMATION_LOOP}, // AnimationLoop
{ 0, settingOffSpeed_t::MAX_VALUE - 1, 1, ANIMATION_SPEED}, // AnimationSpeed

View File

@@ -7,12 +7,14 @@
#include "settingsGUI.hpp"
#include "Buttons.hpp"
#include "Font.h"
#include "ScrollMessage.hpp"
#include "TipThermoModel.h"
#include "Translation.h"
#include "cmsis_os.h"
#include "configuration.h"
#include "main.hpp"
#include "ui_drawing.hpp"
#ifdef POW_DC
static void displayInputVRange(void);
@@ -114,7 +116,7 @@ static bool showHallEffect(void);
// Menu functions
#if defined(POW_DC) || defined(POW_QC)
#if defined(POW_DC) || defined(POW_QC) || defined(POW_PD)
static void displayPowerMenu(void);
#endif /* POW_DC or POW_QC */
@@ -206,7 +208,7 @@ const menuitem rootSettingsMenu[] {
* // Language
* Exit
*/
#if defined(POW_DC) || defined(POW_QC)
#if defined(POW_DC) || defined(POW_QC) || defined(POW_PD)
/* Power */
{0, nullptr, displayPowerMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
#endif
@@ -858,10 +860,10 @@ static void displayLogoTime(void) {
OLED::drawUnavailableIcon();
break;
case logoMode_t::ONETIME:
OLED::drawArea(OLED_WIDTH - 16 - 2, 0, 16, 16, RepeatOnce);
OLED::drawArea(OLED_WIDTH - OLED_HEIGHT - 2, 0, OLED_HEIGHT, OLED_HEIGHT, RepeatOnce);
break;
case logoMode_t::INFINITY:
OLED::drawArea(OLED_WIDTH - 16 - 2, 0, 16, 16, RepeatInf);
OLED::drawArea(OLED_WIDTH - OLED_HEIGHT - 2, 0, OLED_HEIGHT, OLED_HEIGHT, RepeatInf);
break;
default:
OLED::printNumber(getSettingValue(SettingsOptions::LOGOTime), 1, FontStyle::LARGE);
@@ -1013,10 +1015,11 @@ static void displayMenu(size_t index) {
// Draw symbol
// 16 pixel wide image
// less 2 pixel wide scrolling indicator
OLED::drawArea(OLED_WIDTH - 16 - 2, 0, 16, 16, (&SettingsMenuIcons[index][(16 * 2) * currentFrame]));
OLED::drawArea(OLED_WIDTH - SETTINGS_ICON_WIDTH - 2, 0, SETTINGS_ICON_WIDTH, SETTINGS_ICON_HEIGHT, (&SettingsMenuIcons[index][(SETTINGS_ICON_WIDTH * (SETTINGS_ICON_HEIGHT / 8)) * currentFrame]));
}
#if defined(POW_DC) || defined(POW_QC)
#if defined(POW_DC) || defined(POW_QC) || defined(POW_PD)
static void displayPowerMenu(void) { displayMenu(0); }
#endif /* POW_DC or POW_QC */

View File

@@ -26,6 +26,7 @@ extern "C" {
#include "settingsGUI.hpp"
#include "stdlib.h"
#include "string.h"
#include "ui_drawing.hpp"
#ifdef POW_PD
#include "USBPD.h"
#include "pd.h"
@@ -216,7 +217,7 @@ void startGUITask(void const *argument) {
OLED::setInverseDisplay(getSettingValue(SettingsOptions::OLEDInversion));
bool buttonLockout = false;
renderHomeScreenAssets();
ui_pre_render_assets();
getTipRawTemp(1); // reset filter
memset(&context, 0, sizeof(context));

View File

@@ -1,189 +0,0 @@
#include "Buttons.hpp"
#include "OperatingModes.h"
uint8_t buttonAF[sizeof(buttonA)];
uint8_t buttonBF[sizeof(buttonB)];
uint8_t disconnectedTipF[sizeof(disconnectedTip)];
bool showExitMenuTransition = false;
void renderHomeScreenAssets(void) {
// Generate the flipped screen into ram for later use
// flipped is generated by flipping each row
for (int row = 0; row < 2; row++) {
for (int x = 0; x < 42; x++) {
buttonAF[(row * 42) + x] = buttonA[(row * 42) + (41 - x)];
buttonBF[(row * 42) + x] = buttonB[(row * 42) + (41 - x)];
disconnectedTipF[(row * 42) + x] = disconnectedTip[(row * 42) + (41 - x)];
}
}
}
OperatingMode handleHomeButtons(const ButtonState buttons, guiContext *cxt) {
if (buttons != BUTTON_NONE && cxt->scratch_state.state1 == 0) {
return OperatingMode::HomeScreen; // Ignore button press
} else {
cxt->scratch_state.state1 = 1;
}
switch (buttons) {
case BUTTON_NONE:
// Do nothing
break;
case BUTTON_BOTH:
break;
case BUTTON_B_LONG:
cxt->transitionMode = TransitionAnimation::Up;
return OperatingMode::DebugMenuReadout;
break;
case BUTTON_F_LONG:
#ifdef PROFILE_SUPPORT
if (!isTipDisconnected()) {
cxt->transitionMode = TransitionAnimation::Left;
return OperatingMode::SolderingProfile;
} else {
return OperatingMode::HomeScreen;
}
#else
cxt->transitionMode = TransitionAnimation::Left;
return OperatingMode::TemperatureAdjust;
#endif
break;
case BUTTON_F_SHORT:
if (!isTipDisconnected()) {
cxt->transitionMode = TransitionAnimation::Left;
return OperatingMode::Soldering;
}
break;
case BUTTON_B_SHORT:
cxt->transitionMode = TransitionAnimation::Right;
return OperatingMode::SettingsMenu;
break;
default:
break;
}
return OperatingMode::HomeScreen;
}
void drawDetailedHomeScreen(uint32_t tipTemp) {
if (isTipDisconnected()) {
if (OLED::getRotation()) {
// in right handed mode we want to draw over the first part
OLED::drawArea(54, 0, 42, 16, disconnectedTipF);
} else {
OLED::drawArea(0, 0, 42, 16, disconnectedTip);
}
if (OLED::getRotation()) {
OLED::setCursor(-1, 0);
} else {
OLED::setCursor(42, 0);
}
uint32_t Vlt = getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0);
OLED::printNumber(Vlt / 10, 2, FontStyle::LARGE);
OLED::print(LargeSymbolDot, FontStyle::LARGE);
OLED::printNumber(Vlt % 10, 1, FontStyle::LARGE);
if (OLED::getRotation()) {
OLED::setCursor(48, 8);
} else {
OLED::setCursor(91, 8);
}
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
} else {
if (!(getSettingValue(SettingsOptions::CoolingTempBlink) && (tipTemp > 55) && (xTaskGetTickCount() % 1000 < 300))) {
// Blink temp if setting enable and temp < 55°
// 1000 tick/sec
// OFF 300ms ON 700ms
gui_drawTipTemp(true, FontStyle::LARGE); // draw in the temp
}
if (OLED::getRotation()) {
OLED::setCursor(6, 0);
} else {
OLED::setCursor(73, 0); // top right
}
// draw set temp
OLED::printNumber(getSettingValue(SettingsOptions::SolderingTemp), 3, FontStyle::SMALL);
OLED::printSymbolDeg(FontStyle::SMALL);
if (OLED::getRotation()) {
OLED::setCursor(0, 8);
} else {
OLED::setCursor(67, 8); // bottom right
}
printVoltage(); // draw voltage then symbol (v)
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
}
}
void drawSimplifiedHomeScreen(uint32_t tipTemp) {
bool tempOnDisplay = false;
bool tipDisconnectedDisplay = false;
if (OLED::getRotation()) {
OLED::drawArea(54, 0, 42, 16, buttonAF);
OLED::drawArea(12, 0, 42, 16, buttonBF);
OLED::setCursor(0, 0);
gui_drawBatteryIcon();
} else {
OLED::drawArea(0, 0, 42, 16, buttonA); // Needs to be flipped so button ends up
OLED::drawArea(42, 0, 42, 16, buttonB); // on right side of screen
OLED::setCursor(84, 0);
gui_drawBatteryIcon();
}
tipDisconnectedDisplay = false;
if (tipTemp > 55) {
tempOnDisplay = true;
} else if (tipTemp < 45) {
tempOnDisplay = false;
}
if (isTipDisconnected()) {
tempOnDisplay = false;
tipDisconnectedDisplay = true;
}
if (tempOnDisplay || tipDisconnectedDisplay) {
// draw temp over the start soldering button
// Location changes on screen rotation
if (OLED::getRotation()) {
// in right handed mode we want to draw over the first part
OLED::fillArea(55, 0, 41, 16, 0); // clear the area for the temp
OLED::setCursor(56, 0);
} else {
OLED::fillArea(0, 0, 41, 16, 0); // clear the area
OLED::setCursor(0, 0);
}
// If we have a tip connected draw the temp, if not we leave it blank
if (!tipDisconnectedDisplay) {
// draw in the temp
if (!(getSettingValue(SettingsOptions::CoolingTempBlink) && (xTaskGetTickCount() % 1000 < 300))) {
gui_drawTipTemp(false, FontStyle::LARGE); // draw in the temp
}
} else {
// Draw in missing tip symbol
if (OLED::getRotation()) {
// in right handed mode we want to draw over the first part
OLED::drawArea(54, 0, 42, 16, disconnectedTipF);
} else {
OLED::drawArea(0, 0, 42, 16, disconnectedTip);
}
}
}
}
OperatingMode drawHomeScreen(const ButtonState buttons, guiContext *cxt) {
currentTempTargetDegC = 0; // ensure tip is off
getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0);
uint32_t tipTemp = TipThermoModel::getTipInC();
// Setup LCD Cursor location
if (OLED::getRotation()) {
OLED::setCursor(50, 0);
} else {
OLED::setCursor(-1, 0);
}
if (getSettingValue(SettingsOptions::DetailedIDLE)) {
drawDetailedHomeScreen(tipTemp);
} else {
drawSimplifiedHomeScreen(tipTemp);
}
return handleHomeButtons(buttons, cxt);
}

View File

@@ -1,81 +0,0 @@
#include "FS2711.hpp"
#include "OperatingModes.h"
#include "stdbool.h"
#if POW_PD_EXT == 2
#ifdef HAS_POWER_DEBUG_MENU
OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) {
// Print out the USB-PD state
// Basically this is like the Debug menu, but instead we want to print out the PD status
uint8_t screen = 0;
ButtonState b;
for (;;) {
OLED::clearScreen(); // Ensure the buffer starts clean
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
OLED::print(SmallSymbolPDDebug, FontStyle::SMALL); // Print Title
OLED::setCursor(0, 8); // second line
if (screen > 7) {
screen = 0;
}
if (screen == 0) {
// Print the PD Debug state
OLED::print(SmallSymbolState, FontStyle::SMALL);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
fs2711_state_t state = FS2711::debug_get_state();
OLED::printNumber(state.pdo_num, 1, FontStyle::SMALL);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
// OLED::drawHex(state.req_pdo_num, FontStyle::SMALL, 4);
OLED::printNumber(state.req_pdo_num > 7 ? 0 : state.req_pdo_num + 1, 1, FontStyle::SMALL, true);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
uint8_t protocol = FS2711::selected_protocol();
OLED::printNumber(protocol, 2, FontStyle::SMALL);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
} else {
// Print out the Proposed power options one by one
uint16_t max_voltage = FS2711::debug_pdo_max_voltage(screen - 1);
if (max_voltage == 0) {
screen += 1;
} else {
uint16_t min_voltage = FS2711::debug_pdo_min_voltage(screen - 1);
uint16_t current = FS2711::debug_pdo_source_current(screen - 1);
uint16_t pdo_type = FS2711::debug_pdo_type(screen - 1);
OLED::printNumber(screen, 1, FontStyle::SMALL, true);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
if (pdo_type == 1) {
OLED::printNumber(min_voltage / 1000, 2, FontStyle::SMALL, true);
OLED::print(SmallSymbolMinus, FontStyle::SMALL);
OLED::printNumber(max_voltage / 1000, 2, FontStyle::SMALL, false);
} else {
OLED::printNumber(max_voltage / 1000, 2, FontStyle::SMALL, true);
}
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
OLED::printNumber(current / 1000, 2, FontStyle::SMALL, true);
OLED::print(SmallSymbolDot, FontStyle::SMALL);
OLED::printNumber(current % 1000, 1, FontStyle::SMALL, false);
OLED::print(SmallSymbolAmps, FontStyle::SMALL);
// OLED::printNumber(currentx100 % 100, 2, FontStyle::SMALL, true);
}
}
OLED::refresh();
b = getButtonState();
if (b == BUTTON_B_SHORT) {
return OperatingMode::InitialisationDone;
} else if (b == BUTTON_F_SHORT) {
screen++;
}
GUIDelay();
}
return OperatingMode::UsbPDDebug;
}
#endif
#endif

View File

@@ -1,57 +0,0 @@
#include "HUB238.hpp"
#include "OperatingModes.h"
#if POW_PD_EXT == 1
#ifdef HAS_POWER_DEBUG_MENU
OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) {
// Print out the USB-PD state
// Basically this is like the Debug menu, but instead we want to print out the PD status
uint8_t screen = 0;
ButtonState b;
for (;;) {
OLED::clearScreen(); // Ensure the buffer starts clean
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
OLED::print(SmallSymbolPDDebug, FontStyle::SMALL); // Print Title
OLED::setCursor(0, 8); // second line
if (screen > 6) {
screen = 0;
}
if (screen == 0) {
// Print the PD Debug state
OLED::print(SmallSymbolState, FontStyle::SMALL);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
uint16_t temp = hub238_debug_state();
OLED::drawHex(temp, FontStyle::SMALL, 4);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
// Print current selected specs
temp = hub238_source_voltage();
OLED::printNumber(temp, 2, FontStyle::SMALL, true);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
} else {
// Print out the Proposed power options one by one
const uint8_t voltages[] = {5, 9, 12, 15, 18, 20};
uint16_t voltage = voltages[screen - 1];
uint16_t currentx100 = hub238_getVoltagePDOCurrent(voltage);
OLED::printNumber(voltage, 2, FontStyle::SMALL, true);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
OLED::printNumber(currentx100 / 100, 1, FontStyle::SMALL, true);
OLED::print(SmallSymbolDot, FontStyle::SMALL);
OLED::printNumber(currentx100 % 100, 2, FontStyle::SMALL, true);
}
OLED::refresh();
b = getButtonState();
if (b == BUTTON_B_SHORT) {
return OperatingMode::InitialisationDone;
} else if (b == BUTTON_F_SHORT) {
screen++;
}
GUIDelay();
}
return OperatingMode::UsbPDDebug;
}
#endif
#endif

View File

@@ -1,19 +0,0 @@
#ifndef OPERATING_MODE_UTILITIES_H_
#define OPERATING_MODE_UTILITIES_H_
#include "Buttons.hpp"
#include "OLED.hpp"
#include <stdbool.h>
void GUIDelay(); //
bool checkForUnderVoltage(void); //
uint32_t getSleepTimeout(void); //
bool shouldBeSleeping(); //
bool shouldShutdown(void); //
void gui_drawTipTemp(bool symbol, const FontStyle font); //
void printVoltage(void); //
bool warnUser(const char *warning, const ButtonState buttons); //
void gui_drawBatteryIcon(void); //
bool checkForUnderVoltage(void); //
uint16_t min(uint16_t a, uint16_t b); //
void printCountdownUntilSleep(int sleepThres); //
#endif

View File

@@ -0,0 +1,5 @@
# UI
The User interface for IronOS is split into two halves in these folders.
The `logic` folder contains the `.cpp` files that implement the logic of each mode, this should handle button events and any logic.
The `drawing` folder contains the `.cpp` files that implement just the screen drawing for each mode. These are further subdivided by the screen _types_.

View File

@@ -0,0 +1,12 @@
#include "ui_drawing.hpp"
#ifdef OLED_128x32
void ui_draw_cjc_sampling(const uint8_t num_dots) {
OLED::setCursor(0, 0);
OLED::print(translatedString(Tr->CJCCalibrating), FontStyle::SMALL);
OLED::setCursor(0, 8);
OLED::print(SmallSymbolDot, FontStyle::SMALL);
for (uint8_t x = 0; x < num_dots; x++) {
OLED::print(SmallSymbolDot, FontStyle::SMALL);
}
}
#endif

View File

@@ -1,14 +1,19 @@
#include "OperatingModes.h"
#include "TipThermoModel.h"
#include "main.hpp"
#include "ui_drawing.hpp"
#ifdef OLED_128x32
extern osThreadId GUITaskHandle;
extern osThreadId MOVTaskHandle;
extern osThreadId PIDTaskHandle;
OperatingMode showDebugMenu(const ButtonState buttons, guiContext *cxt) {
void ui_draw_debug_menu(const uint8_t item_number) {
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
OLED::print(SmallSymbolVersionNumber, FontStyle::SMALL); // Print version number
OLED::setCursor(0, 8); // second line
OLED::print(DebugMenu[cxt->scratch_state.state1], FontStyle::SMALL);
switch (cxt->scratch_state.state1) {
OLED::print(DebugMenu[item_number], FontStyle::SMALL);
switch (item_number) {
case 0: // Build Date
break;
case 1: // Device ID
@@ -18,7 +23,7 @@ OperatingMode showDebugMenu(const ButtonState buttons, guiContext *cxt) {
// If device has validation code; then we want to take over both lines of the screen
OLED::clearScreen(); // Ensure the buffer starts clean
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
OLED::print(DebugMenu[cxt->scratch_state.state1], FontStyle::SMALL);
OLED::print(DebugMenu[item_number], FontStyle::SMALL);
OLED::drawHex(getDeviceValidation(), FontStyle::SMALL, 8);
OLED::setCursor(0, 8); // second line
#endif
@@ -86,17 +91,5 @@ OperatingMode showDebugMenu(const ButtonState buttons, guiContext *cxt) {
default:
break;
}
if (buttons == BUTTON_B_SHORT) {
cxt->transitionMode = TransitionAnimation::Down;
return OperatingMode::HomeScreen;
} else if (buttons == BUTTON_F_SHORT) {
cxt->scratch_state.state1++;
#ifdef HALL_SENSOR
cxt->scratch_state.state1 = cxt->scratch_state.state1 % 17;
#else
cxt->scratch_state.state1 = cxt->scratch_state.state1 % 16;
#endif
}
return OperatingMode::DebugMenuReadout; // Stay in debug menu
}
#endif

View File

@@ -0,0 +1,57 @@
#include "ui_drawing.hpp"
#ifdef OLED_128x32
extern uint8_t buttonAF[sizeof(buttonA)];
extern uint8_t buttonBF[sizeof(buttonB)];
extern uint8_t disconnectedTipF[sizeof(disconnectedTip)];
void ui_draw_homescreen_detailed(TemperatureType_t tipTemp) {
if (isTipDisconnected()) {
if (OLED::getRotation()) {
// in right handed mode we want to draw over the first part
OLED::drawArea(54, 0, 56, 32, disconnectedTipF);
} else {
OLED::drawArea(0, 0, 56, 32, disconnectedTip);
}
if (OLED::getRotation()) {
OLED::setCursor(-1, 0);
} else {
OLED::setCursor(56, 0);
}
uint32_t Vlt = getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0);
OLED::printNumber(Vlt / 10, 2, FontStyle::LARGE);
OLED::print(LargeSymbolDot, FontStyle::LARGE);
OLED::printNumber(Vlt % 10, 1, FontStyle::LARGE);
if (OLED::getRotation()) {
OLED::setCursor(48, 8);
} else {
OLED::setCursor(91, 8);
}
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
} else {
if (!(getSettingValue(SettingsOptions::CoolingTempBlink) && (tipTemp > 55) && (xTaskGetTickCount() % 1000 < 300))) {
// Blink temp if setting enable and temp < 55°
// 1000 tick/sec
// OFF 300ms ON 700ms
ui_draw_tip_temperature(true, FontStyle::LARGE); // draw in the temp
}
if (OLED::getRotation()) {
OLED::setCursor(6, 0);
} else {
OLED::setCursor(73, 0); // top right
}
// draw set temp
OLED::printNumber(getSettingValue(SettingsOptions::SolderingTemp), 3, FontStyle::SMALL);
OLED::printSymbolDeg(FontStyle::SMALL);
if (OLED::getRotation()) {
OLED::setCursor(0, 8);
} else {
OLED::setCursor(67, 8); // bottom right
}
printVoltage(); // draw voltage then symbol (v)
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
}
}
#endif

View File

@@ -0,0 +1,62 @@
#include "ui_drawing.hpp"
#ifdef OLED_128x32
extern uint8_t buttonAF[sizeof(buttonA)];
extern uint8_t buttonBF[sizeof(buttonB)];
extern uint8_t disconnectedTipF[sizeof(disconnectedTip)];
void ui_draw_homescreen_simplified(TemperatureType_t tipTemp) {
bool tempOnDisplay = false;
bool tipDisconnectedDisplay = false;
if (OLED::getRotation()) {
OLED::drawArea(68, 0, 56, 32, buttonAF);
OLED::drawArea(12, 0, 56, 32, buttonBF);
OLED::setCursor(0, 0);
ui_draw_power_source_icon();
} else {
OLED::drawArea(0, 0, 56, 32, buttonA); // Needs to be flipped so button ends up
OLED::drawArea(58, 0, 56, 32, buttonB); // on right side of screen
OLED::setCursor(116, 0);
ui_draw_power_source_icon();
}
tipDisconnectedDisplay = false;
if (tipTemp > 55) {
tempOnDisplay = true;
} else if (tipTemp < 45) {
tempOnDisplay = false;
}
if (isTipDisconnected()) {
tempOnDisplay = false;
tipDisconnectedDisplay = true;
}
if (tempOnDisplay || tipDisconnectedDisplay) {
// draw temp over the start soldering button
// Location changes on screen rotation
if (OLED::getRotation()) {
// in right handed mode we want to draw over the first part
OLED::fillArea(68, 0, 56, 32, 0); // clear the area for the temp
OLED::setCursor(56, 0);
} else {
OLED::fillArea(0, 0, 56, 32, 0); // clear the area
OLED::setCursor(0, 0);
}
// If we have a tip connected draw the temp, if not we leave it blank
if (!tipDisconnectedDisplay) {
// draw in the temp
if (!(getSettingValue(SettingsOptions::CoolingTempBlink) && (xTaskGetTickCount() % 1000 < 300))) {
ui_draw_tip_temperature(false, FontStyle::LARGE); // draw in the temp
}
} else {
// Draw in missing tip symbol
if (OLED::getRotation()) {
// in right handed mode we want to draw over the first part
OLED::drawArea(54, 0, 56, 32, disconnectedTipF);
} else {
OLED::drawArea(0, 0, 56, 32, disconnectedTip);
}
}
}
}
#endif

View File

@@ -0,0 +1,43 @@
#include "ui_drawing.hpp"
#ifdef OLED_128x32
void ui_draw_power_source_icon(void) {
#if defined(POW_PD) || defined(POW_QC) || defined(POW_PD_EXT)
if (!getIsPoweredByDCIN()) {
// On non-DC inputs we replace this symbol with the voltage we are operating on
// If <9V then show single digit, if not show dual small ones vertically stacked
uint16_t V = getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0);
if (V % 10 >= 5) {
V = (V / 10) + 1; // round up
} else {
V = V / 10;
}
int16_t xPos = OLED::getCursorX();
OLED::printNumber(V / 10, 1, FontStyle::LARGE);
OLED::setCursor(xPos, 16);
OLED::printNumber(V % 10, 1, FontStyle::LARGE);
return;
}
#endif
#ifdef POW_DC
if (getSettingValue(SettingsOptions::MinDCVoltageCells)) {
// User is on a lithium battery
// we need to calculate which of the 10 levels they are on
uint8_t cellCount = getSettingValue(SettingsOptions::MinDCVoltageCells) + 2;
uint32_t cellV = getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0) / cellCount;
// Should give us approx cell voltage X10
// Range is 42 -> Minimum voltage setting (systemSettings.minVoltageCells) = 9 steps therefore we will use battery 0-9
if (cellV < getSettingValue(SettingsOptions::MinVoltageCells)) {
cellV = getSettingValue(SettingsOptions::MinVoltageCells);
}
cellV -= getSettingValue(SettingsOptions::MinVoltageCells); // Should leave us a number of 0-9
if (cellV > 9) {
cellV = 9;
}
OLED::drawBattery(cellV + 1);
} else {
OLED::drawSymbol(15); // Draw the DC Logo
}
#endif
}
#endif

View File

@@ -0,0 +1,59 @@
#include "ui_drawing.hpp"
#ifdef OLED_128x32
void ui_draw_soldering_profile_advanced(TemperatureType_t tipTemp, TemperatureType_t profileCurrentTargetTemp, uint32_t phaseElapsedSeconds, uint32_t phase, const uint32_t phaseTimeGoal) {
// print temperature
if (OLED::getRotation()) {
OLED::setCursor(48, 0);
} else {
OLED::setCursor(0, 0);
}
OLED::printNumber(tipTemp, 3, FontStyle::SMALL);
OLED::print(SmallSymbolSlash, FontStyle::SMALL);
OLED::printNumber(profileCurrentTargetTemp, 3, FontStyle::SMALL);
if (getSettingValue(SettingsOptions::TemperatureInF)) {
OLED::print(SmallSymbolDegF, FontStyle::SMALL);
} else {
OLED::print(SmallSymbolDegC, FontStyle::SMALL);
}
// print phase
if (phase > 0 && phase <= getSettingValue(SettingsOptions::ProfilePhases)) {
if (OLED::getRotation()) {
OLED::setCursor(36, 0);
} else {
OLED::setCursor(55, 0);
}
OLED::printNumber(phase, 1, FontStyle::SMALL);
}
// print time progress / preheat / cooldown
if (OLED::getRotation()) {
OLED::setCursor(42, 8);
} else {
OLED::setCursor(0, 8);
}
if (phase == 0) {
OLED::print(translatedString(Tr->ProfilePreheatString), FontStyle::SMALL);
} else if (phase > getSettingValue(SettingsOptions::ProfilePhases)) {
OLED::print(translatedString(Tr->ProfileCooldownString), FontStyle::SMALL);
} else {
OLED::printNumber(phaseElapsedSeconds / 60, 1, FontStyle::SMALL);
OLED::print(SmallSymbolColon, FontStyle::SMALL);
OLED::printNumber(phaseElapsedSeconds % 60, 2, FontStyle::SMALL, false);
OLED::print(SmallSymbolSlash, FontStyle::SMALL);
// blink if we can't keep up with the time goal
if (phaseElapsedSeconds < phaseTimeGoal + 2 || (xTaskGetTickCount() / TICKS_SECOND) % 2 == 0) {
OLED::printNumber(phaseTimeGoal / 60, 1, FontStyle::SMALL);
OLED::print(SmallSymbolColon, FontStyle::SMALL);
OLED::printNumber(phaseTimeGoal % 60, 2, FontStyle::SMALL, false);
}
}
}
#endif

View File

@@ -0,0 +1,45 @@
#include "power.hpp"
#include "ui_drawing.hpp"
#ifdef OLED_128x32
void ui_draw_soldering_basic_status(bool boostModeOn) {
OLED::setCursor(0, 0);
// We switch the layout direction depending on the orientation of the oled
if (OLED::getRotation()) {
// battery
ui_draw_power_source_icon();
// Space out gap between battery <-> temp
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
// Draw current tip temp
ui_draw_tip_temperature(true, FontStyle::LARGE);
// We draw boost arrow if boosting,
// or else gap temp <-> heat indicator
if (boostModeOn) {
OLED::drawSymbol(2);
} else {
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
}
// Draw heating/cooling symbols
OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average()));
} else {
// Draw heating/cooling symbols
OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average()));
// We draw boost arrow if boosting,
// or else gap temp <-> heat indicator
if (boostModeOn) {
OLED::drawSymbol(2);
} else {
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
}
// Draw current tip temp
ui_draw_tip_temperature(true, FontStyle::LARGE);
// Space out gap between battery <-> temp
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
ui_draw_power_source_icon();
}
}
#endif

View File

@@ -0,0 +1,69 @@
#include "power.hpp"
#include "ui_drawing.hpp"
#include <OperatingModes.h>
#ifdef OLED_128x32
void ui_draw_soldering_power_status(bool boost_mode_on) {
if (OLED::getRotation()) {
OLED::setCursor(50, 0);
} else {
OLED::setCursor(-1, 0);
}
ui_draw_tip_temperature(true, FontStyle::LARGE);
if (boost_mode_on) { // Boost mode is on
if (OLED::getRotation()) {
OLED::setCursor(34, 0);
} else {
OLED::setCursor(50, 0);
}
OLED::print(LargeSymbolPlus, FontStyle::LARGE);
} else {
#ifndef NO_SLEEP_MODE
if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) {
if (OLED::getRotation()) {
OLED::setCursor(32, 0);
} else {
OLED::setCursor(47, 0);
}
printCountdownUntilSleep(getSleepTimeout());
}
#endif
if (OLED::getRotation()) {
OLED::setCursor(32, 8);
} else {
OLED::setCursor(47, 8);
}
OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL, 2);
}
if (OLED::getRotation()) {
OLED::setCursor(0, 0);
} else {
OLED::setCursor(67, 0);
}
// Print wattage
{
uint32_t x10Watt = x10WattHistory.average();
if (x10Watt > 999) {
// If we exceed 99.9W we drop the decimal place to keep it all fitting
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
OLED::printNumber(x10WattHistory.average() / 10, 3, FontStyle::SMALL);
} else {
OLED::printNumber(x10WattHistory.average() / 10, 2, FontStyle::SMALL);
OLED::print(SmallSymbolDot, FontStyle::SMALL);
OLED::printNumber(x10WattHistory.average() % 10, 1, FontStyle::SMALL);
}
OLED::print(SmallSymbolWatts, FontStyle::SMALL);
}
if (OLED::getRotation()) {
OLED::setCursor(0, 8);
} else {
OLED::setCursor(67, 8);
}
printVoltage();
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
}
#endif

View File

@@ -0,0 +1,36 @@
#include "ui_drawing.hpp"
#ifdef OLED_128x32
void ui_draw_soldering_detailed_sleep(TemperatureType_t tipTemp) {
OLED::clearScreen();
OLED::setCursor(0, 0);
OLED::print(translatedString(Tr->SleepingAdvancedString), FontStyle::SMALL);
OLED::setCursor(0, 8);
OLED::print(translatedString(Tr->SleepingTipAdvancedString), FontStyle::SMALL);
OLED::printNumber(tipTemp, 3, FontStyle::SMALL);
if (getSettingValue(SettingsOptions::TemperatureInF)) {
OLED::print(SmallSymbolDegF, FontStyle::SMALL);
} else {
OLED::print(SmallSymbolDegC, FontStyle::SMALL);
}
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
printVoltage();
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
OLED::refresh();
}
void ui_draw_soldering_basic_sleep(TemperatureType_t tipTemp) {
OLED::clearScreen();
OLED::setCursor(0, 0);
OLED::print(LargeSymbolSleep, FontStyle::LARGE);
OLED::printNumber(tipTemp, 3, FontStyle::LARGE);
OLED::printSymbolDeg(FontStyle::EXTRAS);
OLED::refresh();
}
#endif

View File

@@ -0,0 +1,23 @@
#include "ui_drawing.hpp"
#ifdef OLED_128x32
void ui_draw_temperature_change(void) {
OLED::setCursor(0, 0);
if (OLED::getRotation()) {
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE);
} else {
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolMinus : LargeSymbolPlus, FontStyle::LARGE);
}
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
OLED::printNumber(getSettingValue(SettingsOptions::SolderingTemp), 3, FontStyle::LARGE);
OLED::printSymbolDeg(FontStyle::EXTRAS);
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
if (OLED::getRotation()) {
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolMinus : LargeSymbolPlus, FontStyle::LARGE);
} else {
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE);
}
}
#endif

View File

@@ -0,0 +1,17 @@
#include "OperatingModeUtilities.h"
#include "OperatingModes.h"
#include "SolderingCommon.h"
#include "TipThermoModel.h"
#ifdef OLED_128x32
void ui_draw_tip_temperature(bool symbol, const FontStyle font) {
// Draw tip temp handling unit conversion & tolerance near setpoint
TemperatureType_t Temp = getTipTemp();
OLED::printNumber(Temp, 3, font); // Draw the tip temp out
if (symbol) {
// For big font, can draw nice symbols, otherwise fall back to chars
OLED::printSymbolDeg(font == FontStyle::LARGE ? FontStyle::EXTRAS : font);
}
}
#endif

View File

@@ -0,0 +1,45 @@
#include "ui_drawing.hpp"
#ifdef OLED_128x32
void ui_draw_usb_pd_debug_state(const uint16_t vbus_sense_state, const uint8_t stateNumber) {
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
OLED::print(SmallSymbolPDDebug, FontStyle::SMALL); // Print Title
OLED::setCursor(0, 8); // second line
// Print the PD state machine
OLED::print(SmallSymbolState, FontStyle::SMALL);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
OLED::printNumber(stateNumber, 2, FontStyle::SMALL, true);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
if (vbus_sense_state == 2) {
OLED::print(SmallSymbolNoVBus, FontStyle::SMALL);
} else if (vbus_sense_state == 1) {
OLED::print(SmallSymbolVBus, FontStyle::SMALL);
}
}
void ui_draw_usb_pd_debug_pdo(const uint8_t entry_num, const uint16_t min_voltage, const uint16_t max_voltage, const uint16_t current_a_x100, const uint16_t wattage) {
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
OLED::print(SmallSymbolPDDebug, FontStyle::SMALL); // Print Title
OLED::setCursor(0, 8); // second line
OLED::printNumber(entry_num, 2, FontStyle::SMALL, true); // print the entry number
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
if (min_voltage > 0) {
OLED::printNumber(min_voltage, 2, FontStyle::SMALL, true); // print the voltage
OLED::print(SmallSymbolMinus, FontStyle::SMALL);
}
OLED::printNumber(max_voltage, 2, FontStyle::SMALL, true); // print the voltage
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
if (wattage) {
OLED::printNumber(wattage, 3, FontStyle::SMALL, true); // print the current in 0.1A res
OLED::print(SmallSymbolWatts, FontStyle::SMALL);
} else {
OLED::printNumber(current_a_x100 / 100, 2, FontStyle::SMALL, true); // print the current in 0.1A res
OLED::print(SmallSymbolDot, FontStyle::SMALL);
OLED::printNumber(current_a_x100 % 100, 2, FontStyle::SMALL, false); // print the current in 0.1A res
OLED::print(SmallSymbolAmps, FontStyle::SMALL);
}
}
#endif

View File

@@ -0,0 +1,21 @@
#include "ui_drawing.hpp"
#ifdef OLED_128x32
void ui_draw_warning_undervoltage(void) {
OLED::clearScreen();
OLED::setCursor(0, 0);
if (getSettingValue(SettingsOptions::DetailedSoldering)) {
OLED::print(translatedString(Tr->UndervoltageString), FontStyle::SMALL);
OLED::setCursor(0, 8);
OLED::print(translatedString(Tr->InputVoltageString), FontStyle::SMALL);
printVoltage();
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
} else {
OLED::print(translatedString(Tr->UVLOWarningString), FontStyle::LARGE);
}
OLED::refresh();
GUIDelay();
waitForButtonPress();
}
#endif

View File

@@ -0,0 +1,19 @@
#include "ui_drawing.hpp"
#ifdef OLED_128x32
uint8_t buttonAF[sizeof(buttonA)];
uint8_t buttonBF[sizeof(buttonB)];
uint8_t disconnectedTipF[sizeof(disconnectedTip)];
void ui_pre_render_assets(void) {
// Generate the flipped screen into ram for later use
// flipped is generated by flipping each row
for (int row = 0; row < 4; row++) {
for (int x = 0; x < 56; x++) {
buttonAF[(row * 56) + x] = buttonA[(row * 56) + (41 - x)];
buttonBF[(row * 56) + x] = buttonB[(row * 56) + (41 - x)];
disconnectedTipF[(row * 56) + x] = disconnectedTip[(row * 56) + (41 - x)];
}
}
}
#endif

View File

@@ -0,0 +1,22 @@
#include "Buttons.hpp"
#include "OperatingModeUtilities.h"
#ifdef OLED_128x32
extern TickType_t lastMovementTime;
#ifndef NO_SLEEP_MODE
void printCountdownUntilSleep(int sleepThres) {
/*
* Print seconds or minutes (if > 99 seconds) until sleep
* mode is triggered.
*/
TickType_t lastEventTime = lastButtonTime < lastMovementTime ? lastMovementTime : lastButtonTime;
TickType_t downCount = sleepThres - xTaskGetTickCount() + lastEventTime;
if (downCount > (99 * TICKS_SECOND)) {
OLED::printNumber(downCount / 60000 + 1, 2, FontStyle::SMALL);
OLED::print(SmallSymbolMinutes, FontStyle::SMALL);
} else {
OLED::printNumber(downCount / 1000 + 1, 2, FontStyle::SMALL);
OLED::print(SmallSymbolSeconds, FontStyle::SMALL);
}
}
#endif
#endif

View File

@@ -0,0 +1,10 @@
#include "ui_drawing.hpp"
#ifdef OLED_128x32
void printVoltage(void) {
uint32_t volt = getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0);
OLED::printNumber(volt / 10, 2, FontStyle::SMALL);
OLED::print(SmallSymbolDot, FontStyle::SMALL);
OLED::printNumber(volt % 10, 1, FontStyle::SMALL);
}
#endif

View File

@@ -0,0 +1,14 @@
#include "Buttons.hpp"
#include "OperatingModeUtilities.h"
#include "OperatingModes.h"
#ifdef OLED_128x32
bool warnUser(const char *warning, const ButtonState buttons) {
OLED::clearScreen();
OLED::printWholeScreen(warning);
// Also timeout after 5 seconds
if ((xTaskGetTickCount() - lastButtonTime) > TICKS_SECOND * 5) {
return true;
}
return buttons != BUTTON_NONE;
}
#endif

View File

@@ -0,0 +1,13 @@
#include "ui_drawing.hpp"
#ifdef OLED_96x16
void ui_draw_cjc_sampling(const uint8_t num_dots) {
OLED::setCursor(0, 0);
OLED::print(translatedString(Tr->CJCCalibrating), FontStyle::SMALL);
OLED::setCursor(0, 8);
OLED::print(SmallSymbolDot, FontStyle::SMALL);
for (uint8_t x = 0; x < num_dots; x++) {
OLED::print(SmallSymbolDot, FontStyle::SMALL);
}
}
#endif

View File

@@ -0,0 +1,94 @@
#include "OperatingModes.h"
#include "TipThermoModel.h"
#include "main.hpp"
#include "ui_drawing.hpp"
#ifdef OLED_96x16
extern osThreadId GUITaskHandle;
extern osThreadId MOVTaskHandle;
extern osThreadId PIDTaskHandle;
void ui_draw_debug_menu(const uint8_t item_number) {
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
OLED::print(SmallSymbolVersionNumber, FontStyle::SMALL); // Print version number
OLED::setCursor(0, 8); // second line
OLED::print(DebugMenu[item_number], FontStyle::SMALL);
switch (item_number) {
case 0: // Build Date
break;
case 1: // Device ID
{
uint64_t id = getDeviceID();
#ifdef DEVICE_HAS_VALIDATION_CODE
// If device has validation code; then we want to take over both lines of the screen
OLED::clearScreen(); // Ensure the buffer starts clean
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
OLED::print(DebugMenu[item_number], FontStyle::SMALL);
OLED::drawHex(getDeviceValidation(), FontStyle::SMALL, 8);
OLED::setCursor(0, 8); // second line
#endif
OLED::drawHex((uint32_t)(id >> 32), FontStyle::SMALL, 8);
OLED::drawHex((uint32_t)(id & 0xFFFFFFFF), FontStyle::SMALL, 8);
} break;
case 2: // ACC Type
OLED::print(AccelTypeNames[(int)DetectedAccelerometerVersion], FontStyle::SMALL);
break;
case 3: // Power Negotiation Status
OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL);
break;
case 4: // Input Voltage
printVoltage();
break;
case 5: // Temp in °C
OLED::printNumber(TipThermoModel::getTipInC(), 6, FontStyle::SMALL);
break;
case 6: // Handle Temp in °C
OLED::printNumber(getHandleTemperature(0) / 10, 6, FontStyle::SMALL);
OLED::print(SmallSymbolDot, FontStyle::SMALL);
OLED::printNumber(getHandleTemperature(0) % 10, 1, FontStyle::SMALL);
break;
case 7: // Max Temp Limit in °C
OLED::printNumber(TipThermoModel::getTipMaxInC(), 6, FontStyle::SMALL);
break;
case 8: // System Uptime
OLED::printNumber(xTaskGetTickCount() / TICKS_100MS, 8, FontStyle::SMALL);
break;
case 9: // Movement Timestamp
OLED::printNumber(lastMovementTime / TICKS_100MS, 8, FontStyle::SMALL);
break;
case 10: // Tip Resistance in Ω
OLED::printNumber(getTipResistanceX10() / 10, 6, FontStyle::SMALL); // large to pad over so that we cover ID left overs
OLED::print(SmallSymbolDot, FontStyle::SMALL);
OLED::printNumber(getTipResistanceX10() % 10, 1, FontStyle::SMALL);
break;
case 11: // Raw Tip in µV
OLED::printNumber(TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0), true), 8, FontStyle::SMALL);
break;
case 12: // Tip Cold Junction Compensation Offset in µV
OLED::printNumber(getSettingValue(SettingsOptions::CalibrationOffset), 8, FontStyle::SMALL);
break;
case 13: // High Water Mark for GUI
OLED::printNumber(uxTaskGetStackHighWaterMark(GUITaskHandle), 8, FontStyle::SMALL);
break;
case 14: // High Water Mark for Movement Task
OLED::printNumber(uxTaskGetStackHighWaterMark(MOVTaskHandle), 8, FontStyle::SMALL);
break;
case 15: // High Water Mark for PID Task
OLED::printNumber(uxTaskGetStackHighWaterMark(PIDTaskHandle), 8, FontStyle::SMALL);
break;
break;
#ifdef HALL_SENSOR
case 16: // Raw Hall Effect Value
{
int16_t hallEffectStrength = getRawHallEffect();
if (hallEffectStrength < 0) {
hallEffectStrength = -hallEffectStrength;
}
OLED::printNumber(hallEffectStrength, 6, FontStyle::SMALL);
} break;
#endif
default:
break;
}
}
#endif

View File

@@ -0,0 +1,57 @@
#include "ui_drawing.hpp"
#ifdef OLED_96x16
extern uint8_t buttonAF[sizeof(buttonA)];
extern uint8_t buttonBF[sizeof(buttonB)];
extern uint8_t disconnectedTipF[sizeof(disconnectedTip)];
void ui_draw_homescreen_detailed(TemperatureType_t tipTemp) {
if (isTipDisconnected()) {
if (OLED::getRotation()) {
// in right handed mode we want to draw over the first part
OLED::drawArea(54, 0, 42, 16, disconnectedTipF);
} else {
OLED::drawArea(0, 0, 42, 16, disconnectedTip);
}
if (OLED::getRotation()) {
OLED::setCursor(-1, 0);
} else {
OLED::setCursor(42, 0);
}
uint32_t Vlt = getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0);
OLED::printNumber(Vlt / 10, 2, FontStyle::LARGE);
OLED::print(LargeSymbolDot, FontStyle::LARGE);
OLED::printNumber(Vlt % 10, 1, FontStyle::LARGE);
if (OLED::getRotation()) {
OLED::setCursor(48, 8);
} else {
OLED::setCursor(91, 8);
}
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
} else {
if (!(getSettingValue(SettingsOptions::CoolingTempBlink) && (tipTemp > 55) && (xTaskGetTickCount() % 1000 < 300))) {
// Blink temp if setting enable and temp < 55°
// 1000 tick/sec
// OFF 300ms ON 700ms
ui_draw_tip_temperature(true, FontStyle::LARGE); // draw in the temp
}
if (OLED::getRotation()) {
OLED::setCursor(6, 0);
} else {
OLED::setCursor(73, 0); // top right
}
// draw set temp
OLED::printNumber(getSettingValue(SettingsOptions::SolderingTemp), 3, FontStyle::SMALL);
OLED::printSymbolDeg(FontStyle::SMALL);
if (OLED::getRotation()) {
OLED::setCursor(0, 8);
} else {
OLED::setCursor(67, 8); // bottom right
}
printVoltage(); // draw voltage then symbol (v)
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
}
}
#endif

View File

@@ -0,0 +1,62 @@
#include "ui_drawing.hpp"
#ifdef OLED_96x16
extern uint8_t buttonAF[sizeof(buttonA)];
extern uint8_t buttonBF[sizeof(buttonB)];
extern uint8_t disconnectedTipF[sizeof(disconnectedTip)];
void ui_draw_homescreen_simplified(TemperatureType_t tipTemp) {
bool tempOnDisplay = false;
bool tipDisconnectedDisplay = false;
if (OLED::getRotation()) {
OLED::drawArea(54, 0, 42, 16, buttonAF);
OLED::drawArea(12, 0, 42, 16, buttonBF);
OLED::setCursor(0, 0);
ui_draw_power_source_icon();
} else {
OLED::drawArea(0, 0, 42, 16, buttonA); // Needs to be flipped so button ends up
OLED::drawArea(42, 0, 42, 16, buttonB); // on right side of screen
OLED::setCursor(84, 0);
ui_draw_power_source_icon();
}
tipDisconnectedDisplay = false;
if (tipTemp > 55) {
tempOnDisplay = true;
} else if (tipTemp < 45) {
tempOnDisplay = false;
}
if (isTipDisconnected()) {
tempOnDisplay = false;
tipDisconnectedDisplay = true;
}
if (tempOnDisplay || tipDisconnectedDisplay) {
// draw temp over the start soldering button
// Location changes on screen rotation
if (OLED::getRotation()) {
// in right handed mode we want to draw over the first part
OLED::fillArea(55, 0, 41, 16, 0); // clear the area for the temp
OLED::setCursor(56, 0);
} else {
OLED::fillArea(0, 0, 41, 16, 0); // clear the area
OLED::setCursor(0, 0);
}
// If we have a tip connected draw the temp, if not we leave it blank
if (!tipDisconnectedDisplay) {
// draw in the temp
if (!(getSettingValue(SettingsOptions::CoolingTempBlink) && (xTaskGetTickCount() % 1000 < 300))) {
ui_draw_tip_temperature(false, FontStyle::LARGE); // draw in the temp
}
} else {
// Draw in missing tip symbol
if (OLED::getRotation()) {
// in right handed mode we want to draw over the first part
OLED::drawArea(54, 0, 42, 16, disconnectedTipF);
} else {
OLED::drawArea(0, 0, 42, 16, disconnectedTip);
}
}
}
}
#endif

View File

@@ -1,6 +1,7 @@
#include "OperatingModeUtilities.h"
#include "ui_drawing.hpp"
#ifdef OLED_96x16
void gui_drawBatteryIcon(void) {
void ui_draw_power_source_icon(void) {
#if defined(POW_PD) || defined(POW_QC) || defined(POW_PD_EXT)
if (!getIsPoweredByDCIN()) {
// On non-DC inputs we replace this symbol with the voltage we are operating on
@@ -44,3 +45,5 @@ void gui_drawBatteryIcon(void) {
}
#endif
}
#endif

View File

@@ -0,0 +1,59 @@
#include "ui_drawing.hpp"
#ifdef OLED_96x16
void ui_draw_soldering_profile_advanced(TemperatureType_t tipTemp, TemperatureType_t profileCurrentTargetTemp, uint32_t phaseElapsedSeconds, uint32_t phase, const uint32_t phaseTimeGoal) {
// print temperature
if (OLED::getRotation()) {
OLED::setCursor(48, 0);
} else {
OLED::setCursor(0, 0);
}
OLED::printNumber(tipTemp, 3, FontStyle::SMALL);
OLED::print(SmallSymbolSlash, FontStyle::SMALL);
OLED::printNumber(profileCurrentTargetTemp, 3, FontStyle::SMALL);
if (getSettingValue(SettingsOptions::TemperatureInF)) {
OLED::print(SmallSymbolDegF, FontStyle::SMALL);
} else {
OLED::print(SmallSymbolDegC, FontStyle::SMALL);
}
// print phase
if (phase > 0 && phase <= getSettingValue(SettingsOptions::ProfilePhases)) {
if (OLED::getRotation()) {
OLED::setCursor(36, 0);
} else {
OLED::setCursor(55, 0);
}
OLED::printNumber(phase, 1, FontStyle::SMALL);
}
// print time progress / preheat / cooldown
if (OLED::getRotation()) {
OLED::setCursor(42, 8);
} else {
OLED::setCursor(0, 8);
}
if (phase == 0) {
OLED::print(translatedString(Tr->ProfilePreheatString), FontStyle::SMALL);
} else if (phase > getSettingValue(SettingsOptions::ProfilePhases)) {
OLED::print(translatedString(Tr->ProfileCooldownString), FontStyle::SMALL);
} else {
OLED::printNumber(phaseElapsedSeconds / 60, 1, FontStyle::SMALL);
OLED::print(SmallSymbolColon, FontStyle::SMALL);
OLED::printNumber(phaseElapsedSeconds % 60, 2, FontStyle::SMALL, false);
OLED::print(SmallSymbolSlash, FontStyle::SMALL);
// blink if we can't keep up with the time goal
if (phaseElapsedSeconds < phaseTimeGoal + 2 || (xTaskGetTickCount() / TICKS_SECOND) % 2 == 0) {
OLED::printNumber(phaseTimeGoal / 60, 1, FontStyle::SMALL);
OLED::print(SmallSymbolColon, FontStyle::SMALL);
OLED::printNumber(phaseTimeGoal % 60, 2, FontStyle::SMALL, false);
}
}
}
#endif

View File

@@ -0,0 +1,44 @@
#include "power.hpp"
#include "ui_drawing.hpp"
#ifdef OLED_96x16
void ui_draw_soldering_basic_status(bool boostModeOn) {
OLED::setCursor(0, 0);
// We switch the layout direction depending on the orientation of the oled
if (OLED::getRotation()) {
// battery
ui_draw_power_source_icon();
// Space out gap between battery <-> temp
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
// Draw current tip temp
ui_draw_tip_temperature(true, FontStyle::LARGE);
// We draw boost arrow if boosting,
// or else gap temp <-> heat indicator
if (boostModeOn) {
OLED::drawSymbol(2);
} else {
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
}
// Draw heating/cooling symbols
OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average()));
} else {
// Draw heating/cooling symbols
OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average()));
// We draw boost arrow if boosting,
// or else gap temp <-> heat indicator
if (boostModeOn) {
OLED::drawSymbol(2);
} else {
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
}
// Draw current tip temp
ui_draw_tip_temperature(true, FontStyle::LARGE);
// Space out gap between battery <-> temp
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
ui_draw_power_source_icon();
}
}
#endif

View File

@@ -0,0 +1,69 @@
#include "power.hpp"
#include "ui_drawing.hpp"
#include <OperatingModes.h>
#ifdef OLED_96x16
void ui_draw_soldering_power_status(bool boost_mode_on) {
if (OLED::getRotation()) {
OLED::setCursor(50, 0);
} else {
OLED::setCursor(-1, 0);
}
ui_draw_tip_temperature(true, FontStyle::LARGE);
if (boost_mode_on) { // Boost mode is on
if (OLED::getRotation()) {
OLED::setCursor(34, 0);
} else {
OLED::setCursor(50, 0);
}
OLED::print(LargeSymbolPlus, FontStyle::LARGE);
} else {
#ifndef NO_SLEEP_MODE
if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) {
if (OLED::getRotation()) {
OLED::setCursor(32, 0);
} else {
OLED::setCursor(47, 0);
}
printCountdownUntilSleep(getSleepTimeout());
}
#endif
if (OLED::getRotation()) {
OLED::setCursor(32, 8);
} else {
OLED::setCursor(47, 8);
}
OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL, 2);
}
if (OLED::getRotation()) {
OLED::setCursor(0, 0);
} else {
OLED::setCursor(67, 0);
}
// Print wattage
{
uint32_t x10Watt = x10WattHistory.average();
if (x10Watt > 999) {
// If we exceed 99.9W we drop the decimal place to keep it all fitting
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
OLED::printNumber(x10WattHistory.average() / 10, 3, FontStyle::SMALL);
} else {
OLED::printNumber(x10WattHistory.average() / 10, 2, FontStyle::SMALL);
OLED::print(SmallSymbolDot, FontStyle::SMALL);
OLED::printNumber(x10WattHistory.average() % 10, 1, FontStyle::SMALL);
}
OLED::print(SmallSymbolWatts, FontStyle::SMALL);
}
if (OLED::getRotation()) {
OLED::setCursor(0, 8);
} else {
OLED::setCursor(67, 8);
}
printVoltage();
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
}
#endif

View File

@@ -0,0 +1,36 @@
#include "ui_drawing.hpp"
#ifdef OLED_96x16
void ui_draw_soldering_detailed_sleep(TemperatureType_t tipTemp) {
OLED::clearScreen();
OLED::setCursor(0, 0);
OLED::print(translatedString(Tr->SleepingAdvancedString), FontStyle::SMALL);
OLED::setCursor(0, 8);
OLED::print(translatedString(Tr->SleepingTipAdvancedString), FontStyle::SMALL);
OLED::printNumber(tipTemp, 3, FontStyle::SMALL);
if (getSettingValue(SettingsOptions::TemperatureInF)) {
OLED::print(SmallSymbolDegF, FontStyle::SMALL);
} else {
OLED::print(SmallSymbolDegC, FontStyle::SMALL);
}
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
printVoltage();
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
OLED::refresh();
}
void ui_draw_soldering_basic_sleep(TemperatureType_t tipTemp) {
OLED::clearScreen();
OLED::setCursor(0, 0);
OLED::print(LargeSymbolSleep, FontStyle::LARGE);
OLED::printNumber(tipTemp, 3, FontStyle::LARGE);
OLED::printSymbolDeg(FontStyle::EXTRAS);
OLED::refresh();
}
#endif

View File

@@ -0,0 +1,23 @@
#include "ui_drawing.hpp"
#ifdef OLED_96x16
void ui_draw_temperature_change(void) {
OLED::setCursor(0, 0);
if (OLED::getRotation()) {
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE);
} else {
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolMinus : LargeSymbolPlus, FontStyle::LARGE);
}
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
OLED::printNumber(getSettingValue(SettingsOptions::SolderingTemp), 3, FontStyle::LARGE);
OLED::printSymbolDeg(FontStyle::EXTRAS);
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
if (OLED::getRotation()) {
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolMinus : LargeSymbolPlus, FontStyle::LARGE);
} else {
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE);
}
}
#endif

View File

@@ -2,8 +2,9 @@
#include "OperatingModes.h"
#include "SolderingCommon.h"
#include "TipThermoModel.h"
#ifdef OLED_96x16
void gui_drawTipTemp(bool symbol, const FontStyle font) {
void ui_draw_tip_temperature(bool symbol, const FontStyle font) {
// Draw tip temp handling unit conversion & tolerance near setpoint
TemperatureType_t Temp = getTipTemp();
@@ -13,3 +14,4 @@ void gui_drawTipTemp(bool symbol, const FontStyle font) {
OLED::printSymbolDeg(font == FontStyle::LARGE ? FontStyle::EXTRAS : font);
}
}
#endif

View File

@@ -0,0 +1,45 @@
#include "ui_drawing.hpp"
#ifdef OLED_96x16
void ui_draw_usb_pd_debug_state(const uint16_t vbus_sense_state, const uint8_t stateNumber) {
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
OLED::print(SmallSymbolPDDebug, FontStyle::SMALL); // Print Title
OLED::setCursor(0, 8); // second line
// Print the PD state machine
OLED::print(SmallSymbolState, FontStyle::SMALL);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
OLED::printNumber(stateNumber, 2, FontStyle::SMALL, true);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
if (vbus_sense_state == 2) {
OLED::print(SmallSymbolNoVBus, FontStyle::SMALL);
} else if (vbus_sense_state == 1) {
OLED::print(SmallSymbolVBus, FontStyle::SMALL);
}
}
void ui_draw_usb_pd_debug_pdo(const uint8_t entry_num, const uint16_t min_voltage, const uint16_t max_voltage, const uint16_t current_a_x100, const uint16_t wattage) {
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
OLED::print(SmallSymbolPDDebug, FontStyle::SMALL); // Print Title
OLED::setCursor(0, 8); // second line
OLED::printNumber(entry_num, 2, FontStyle::SMALL, true); // print the entry number
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
if (min_voltage > 0) {
OLED::printNumber(min_voltage, 2, FontStyle::SMALL, true); // print the voltage
OLED::print(SmallSymbolMinus, FontStyle::SMALL);
}
OLED::printNumber(max_voltage, 2, FontStyle::SMALL, true); // print the voltage
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
if (wattage) {
OLED::printNumber(wattage, 3, FontStyle::SMALL, true); // print the current in 0.1A res
OLED::print(SmallSymbolWatts, FontStyle::SMALL);
} else {
OLED::printNumber(current_a_x100 / 100, 2, FontStyle::SMALL, true); // print the current in 0.1A res
OLED::print(SmallSymbolDot, FontStyle::SMALL);
OLED::printNumber(current_a_x100 % 100, 2, FontStyle::SMALL, false); // print the current in 0.1A res
OLED::print(SmallSymbolAmps, FontStyle::SMALL);
}
}
#endif

View File

@@ -0,0 +1,21 @@
#include "ui_drawing.hpp"
#ifdef OLED_96x16
void ui_draw_warning_undervoltage(void) {
OLED::clearScreen();
OLED::setCursor(0, 0);
if (getSettingValue(SettingsOptions::DetailedSoldering)) {
OLED::print(translatedString(Tr->UndervoltageString), FontStyle::SMALL);
OLED::setCursor(0, 8);
OLED::print(translatedString(Tr->InputVoltageString), FontStyle::SMALL);
printVoltage();
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
} else {
OLED::print(translatedString(Tr->UVLOWarningString), FontStyle::LARGE);
}
OLED::refresh();
GUIDelay();
waitForButtonPress();
}
#endif

View File

@@ -0,0 +1,19 @@
#include "ui_drawing.hpp"
#ifdef OLED_96x16
uint8_t buttonAF[sizeof(buttonA)];
uint8_t buttonBF[sizeof(buttonB)];
uint8_t disconnectedTipF[sizeof(disconnectedTip)];
void ui_pre_render_assets(void) {
// Generate the flipped screen into ram for later use
// flipped is generated by flipping each row
for (int row = 0; row < 2; row++) {
for (int x = 0; x < 42; x++) {
buttonAF[(row * 42) + x] = buttonA[(row * 42) + (41 - x)];
buttonBF[(row * 42) + x] = buttonB[(row * 42) + (41 - x)];
disconnectedTipF[(row * 42) + x] = disconnectedTip[(row * 42) + (41 - x)];
}
}
}
#endif

View File

@@ -1,5 +1,6 @@
#include "Buttons.hpp"
#include "OperatingModeUtilities.h"
#ifdef OLED_96x16
extern TickType_t lastMovementTime;
#ifndef NO_SLEEP_MODE
void printCountdownUntilSleep(int sleepThres) {
@@ -18,3 +19,4 @@ void printCountdownUntilSleep(int sleepThres) {
}
}
#endif
#endif

View File

@@ -1,8 +1,10 @@
#include "OperatingModeUtilities.h"
#include "ui_drawing.hpp"
#ifdef OLED_96x16
void printVoltage(void) {
uint32_t volt = getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0);
OLED::printNumber(volt / 10, 2, FontStyle::SMALL);
OLED::print(SmallSymbolDot, FontStyle::SMALL);
OLED::printNumber(volt % 10, 1, FontStyle::SMALL);
}
#endif

View File

@@ -1,6 +1,7 @@
#include "Buttons.hpp"
#include "OperatingModeUtilities.h"
#include "OperatingModes.h"
#ifdef OLED_96x16
bool warnUser(const char *warning, const ButtonState buttons) {
OLED::clearScreen();
OLED::printWholeScreen(warning);
@@ -10,3 +11,4 @@ bool warnUser(const char *warning, const ButtonState buttons) {
}
return buttons != BUTTON_NONE;
}
#endif

View File

@@ -0,0 +1,33 @@
#ifndef UI_DRAWING_UI_DRAWING_HPP_
#define UI_DRAWING_UI_DRAWING_HPP_
#include "Buttons.hpp"
#include "OLED.hpp"
#include "OperatingModeUtilities.h"
#include "configuration.h"
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
void ui_draw_warning_undervoltage(void);
void ui_draw_power_source_icon(void); // Draw a single character wide power source icon
void ui_draw_tip_temperature(bool symbol, const FontStyle font); // Draw tip temp, aware of conversions
bool warnUser(const char *warning, const ButtonState buttons); // Print a full screen warning to the user
void ui_draw_cjc_sampling(const uint8_t num_dots); // Draws the CJC info text and progress dots
void ui_draw_debug_menu(const uint8_t item_number); // Draws the debug menu state
void ui_draw_homescreen_detailed(TemperatureType_t tipTemp); // Drawing the home screen -- Detailed mode
void ui_draw_homescreen_simplified(TemperatureType_t tipTemp); // Drawing the home screen -- Simple mode
void ui_pre_render_assets(void); // If any assets need to be pre-rendered into ram
// Soldering mode
void ui_draw_soldering_power_status(bool boost_mode_on);
void ui_draw_soldering_basic_status(bool boostModeOn);
void ui_draw_soldering_detailed_sleep(TemperatureType_t tipTemp);
void ui_draw_soldering_basic_sleep(TemperatureType_t tipTemp);
void ui_draw_soldering_profile_advanced(TemperatureType_t tipTemp, TemperatureType_t profileCurrentTargetTemp, uint32_t phaseElapsedSeconds, uint32_t phase,const uint32_t phaseTimeGoal);
//Temp change
void ui_draw_temperature_change(void);
//USB-PD debug
void ui_draw_usb_pd_debug_state(const uint16_t vbus_sense_state, const uint8_t stateNumber) ;
void ui_draw_usb_pd_debug_pdo(const uint8_t entry_num, const uint16_t min_voltage, const uint16_t max_voltage, const uint16_t current_a_x100, const uint16_t wattage) ;
// Utils
void printVoltage(void);
#endif // UI_DRAWING_UI_DRAWING_HPP_

View File

@@ -1,6 +1,6 @@
#include "OperatingModes.h"
#include "ui_drawing.hpp"
OperatingMode performCJCC(const ButtonState buttons, guiContext *cxt) {
// Calibrate Cold Junction Compensation directly at boot, before internal components get warm.
@@ -19,14 +19,7 @@ OperatingMode performCJCC(const ButtonState buttons, guiContext *cxt) {
cxt->scratch_state.state1++;
cxt->scratch_state.state4 = xTaskGetTickCount();
}
OLED::setCursor(0, 0);
OLED::print(translatedString(Tr->CJCCalibrating), FontStyle::SMALL);
OLED::setCursor(0, 8);
OLED::print(SmallSymbolDot, FontStyle::SMALL);
for (uint8_t x = 0; x < (cxt->scratch_state.state1 / 4); x++) {
OLED::print(SmallSymbolDot, FontStyle::SMALL);
}
ui_draw_cjc_sampling(cxt->scratch_state.state1 / 4);
return OperatingMode::CJCCalibration;
}

View File

@@ -0,0 +1,20 @@
#include "OperatingModes.h"
#include "ui_drawing.hpp"
OperatingMode showDebugMenu(const ButtonState buttons, guiContext *cxt) {
ui_draw_debug_menu(cxt->scratch_state.state1);
if (buttons == BUTTON_B_SHORT) {
cxt->transitionMode = TransitionAnimation::Down;
return OperatingMode::HomeScreen;
} else if (buttons == BUTTON_F_SHORT) {
cxt->scratch_state.state1++;
#ifdef HALL_SENSOR
cxt->scratch_state.state1 = cxt->scratch_state.state1 % 17;
#else
cxt->scratch_state.state1 = cxt->scratch_state.state1 % 16;
#endif
}
return OperatingMode::DebugMenuReadout; // Stay in debug menu
}

View File

@@ -0,0 +1,72 @@
#include "Buttons.hpp"
#include "OperatingModes.h"
#include "ui_drawing.hpp"
bool showExitMenuTransition = false;
OperatingMode handleHomeButtons(const ButtonState buttons, guiContext *cxt) {
if (buttons != BUTTON_NONE && cxt->scratch_state.state1 == 0) {
return OperatingMode::HomeScreen; // Ignore button press
} else {
cxt->scratch_state.state1 = 1;
}
switch (buttons) {
case BUTTON_NONE:
// Do nothing
break;
case BUTTON_BOTH:
break;
case BUTTON_B_LONG:
cxt->transitionMode = TransitionAnimation::Up;
return OperatingMode::DebugMenuReadout;
break;
case BUTTON_F_LONG:
#ifdef PROFILE_SUPPORT
if (!isTipDisconnected()) {
cxt->transitionMode = TransitionAnimation::Left;
return OperatingMode::SolderingProfile;
} else {
return OperatingMode::HomeScreen;
}
#else
cxt->transitionMode = TransitionAnimation::Left;
return OperatingMode::TemperatureAdjust;
#endif
break;
case BUTTON_F_SHORT:
if (!isTipDisconnected()) {
cxt->transitionMode = TransitionAnimation::Left;
return OperatingMode::Soldering;
}
break;
case BUTTON_B_SHORT:
cxt->transitionMode = TransitionAnimation::Right;
return OperatingMode::SettingsMenu;
break;
default:
break;
}
return OperatingMode::HomeScreen;
}
OperatingMode drawHomeScreen(const ButtonState buttons, guiContext *cxt) {
currentTempTargetDegC = 0; // ensure tip is off
getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0);
uint32_t tipTemp = TipThermoModel::getTipInC();
// Setup LCD Cursor location
if (OLED::getRotation()) {
OLED::setCursor(50, 0);
} else {
OLED::setCursor(-1, 0);
}
if (getSettingValue(SettingsOptions::DetailedIDLE)) {
ui_draw_homescreen_detailed(tipTemp);
} else {
ui_draw_homescreen_simplified(tipTemp);
}
return handleHomeButtons(buttons, cxt);
}

View File

@@ -80,8 +80,7 @@ OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt);
OperatingMode showWarnings(const ButtonState buttons, guiContext *cxt); // Shows user warnings if required
// Common helpers
int8_t getPowerSourceNumber(void); // Returns number ID of power source
void renderHomeScreenAssets(void); // Called to act as start delay and used to render out flipped images for home screen graphics
int8_t getPowerSourceNumber(void); // Returns number ID of power source
extern bool heaterThermalRunaway;
#endif

View File

@@ -1,6 +1,7 @@
#include "FS2711.hpp"
#include "HUB238.hpp"
#include "OperatingModes.h"
#include "ui_drawing.hpp"
OperatingMode showWarnings(const ButtonState buttons, guiContext *cxt) {
// Display alert if settings were reset

View File

@@ -1,5 +1,5 @@
#include "OperatingModes.h"
#include "ui_drawing.hpp"
OperatingMode gui_SolderingSleepingMode(const ButtonState buttons, guiContext *cxt) {
#ifdef NO_SLEEP_MODE
return OperatingMode::Soldering;
@@ -28,31 +28,12 @@ OperatingMode gui_SolderingSleepingMode(const ButtonState buttons, guiContext *c
// draw the lcd
uint16_t tipTemp = getSettingValue(SettingsOptions::TemperatureInF) ? TipThermoModel::getTipInF() : TipThermoModel::getTipInC();
OLED::clearScreen();
OLED::setCursor(0, 0);
if (getSettingValue(SettingsOptions::DetailedSoldering)) {
OLED::print(translatedString(Tr->SleepingAdvancedString), FontStyle::SMALL);
OLED::setCursor(0, 8);
OLED::print(translatedString(Tr->SleepingTipAdvancedString), FontStyle::SMALL);
OLED::printNumber(tipTemp, 3, FontStyle::SMALL);
if (getSettingValue(SettingsOptions::TemperatureInF)) {
OLED::print(SmallSymbolDegF, FontStyle::SMALL);
} else {
OLED::print(SmallSymbolDegC, FontStyle::SMALL);
}
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
printVoltage();
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
ui_draw_soldering_detailed_sleep(tipTemp);
} else {
OLED::print(LargeSymbolSleep, FontStyle::LARGE);
OLED::printNumber(tipTemp, 3, FontStyle::LARGE);
OLED::printSymbolDeg(FontStyle::EXTRAS);
ui_draw_soldering_basic_sleep(tipTemp);
}
OLED::refresh();
GUIDelay();
if (!shouldBeSleeping()) {
return cxt->previousMode;
}

View File

@@ -1,6 +1,7 @@
#include "OperatingModes.h"
#include "SolderingCommon.h"
#include "ui_drawing.hpp"
// State 1 = button locking
// State 2 = boost mode
// State 3 = buzzer timer
@@ -107,44 +108,11 @@ OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt) {
// Draw in the screen details
if (getSettingValue(SettingsOptions::DetailedSoldering)) {
if (OLED::getRotation()) {
OLED::setCursor(50, 0);
} else {
OLED::setCursor(-1, 0);
}
gui_drawTipTemp(true, FontStyle::LARGE);
if (cxt->scratch_state.state2) { // Boost mode is on
if (OLED::getRotation()) {
OLED::setCursor(34, 0);
} else {
OLED::setCursor(50, 0);
}
OLED::print(LargeSymbolPlus, FontStyle::LARGE);
} else {
#ifndef NO_SLEEP_MODE
if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) {
if (OLED::getRotation()) {
OLED::setCursor(32, 0);
} else {
OLED::setCursor(47, 0);
}
printCountdownUntilSleep(getSleepTimeout());
}
#endif
if (OLED::getRotation()) {
OLED::setCursor(32, 8);
} else {
OLED::setCursor(47, 8);
}
OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL, 2);
}
detailedPowerStatus();
ui_draw_soldering_power_status(cxt->scratch_state.state2);
} else {
basicSolderingStatus(cxt->scratch_state.state2);
ui_draw_soldering_basic_status(cxt->scratch_state.state2);
}
// Check if we should bail due to undervoltage for example
if (checkExitSoldering()) {

View File

@@ -1,6 +1,7 @@
#include "OperatingModes.h"
#include "SolderingCommon.h"
#include "ui_drawing.hpp"
OperatingMode gui_solderingProfileMode(const ButtonState buttons, guiContext *cxt) {
/*
@@ -125,63 +126,10 @@ OperatingMode gui_solderingProfileMode(const ButtonState buttons, guiContext *cx
// Draw in the screen details
if (getSettingValue(SettingsOptions::DetailedSoldering)) {
// print temperature
if (OLED::getRotation()) {
OLED::setCursor(48, 0);
} else {
OLED::setCursor(0, 0);
}
OLED::printNumber(tipTemp, 3, FontStyle::SMALL);
OLED::print(SmallSymbolSlash, FontStyle::SMALL);
OLED::printNumber(profileCurrentTargetTemp, 3, FontStyle::SMALL);
if (getSettingValue(SettingsOptions::TemperatureInF)) {
OLED::print(SmallSymbolDegF, FontStyle::SMALL);
} else {
OLED::print(SmallSymbolDegC, FontStyle::SMALL);
}
// print phase
if (cxt->scratch_state.state1 > 0 && cxt->scratch_state.state1 <= getSettingValue(SettingsOptions::ProfilePhases)) {
if (OLED::getRotation()) {
OLED::setCursor(36, 0);
} else {
OLED::setCursor(55, 0);
}
OLED::printNumber(cxt->scratch_state.state1, 1, FontStyle::SMALL);
}
// print time progress / preheat / cooldown
if (OLED::getRotation()) {
OLED::setCursor(42, 8);
} else {
OLED::setCursor(0, 8);
}
if (cxt->scratch_state.state1 == 0) {
OLED::print(translatedString(Tr->ProfilePreheatString), FontStyle::SMALL);
} else if (cxt->scratch_state.state1 > getSettingValue(SettingsOptions::ProfilePhases)) {
OLED::print(translatedString(Tr->ProfileCooldownString), FontStyle::SMALL);
} else {
OLED::printNumber(phaseElapsedSeconds / 60, 1, FontStyle::SMALL);
OLED::print(SmallSymbolColon, FontStyle::SMALL);
OLED::printNumber(phaseElapsedSeconds % 60, 2, FontStyle::SMALL, false);
OLED::print(SmallSymbolSlash, FontStyle::SMALL);
// blink if we can't keep up with the time goal
if (phaseElapsedSeconds < cxt->scratch_state.state2 + 2 || (xTaskGetTickCount() / TICKS_SECOND) % 2 == 0) {
OLED::printNumber(cxt->scratch_state.state2 / 60, 1, FontStyle::SMALL);
OLED::print(SmallSymbolColon, FontStyle::SMALL);
OLED::printNumber(cxt->scratch_state.state2 % 60, 2, FontStyle::SMALL, false);
}
}
detailedPowerStatus();
ui_draw_soldering_profile_advanced(tipTemp, profileCurrentTargetTemp, phaseElapsedSeconds, cxt->scratch_state.state1, cxt->scratch_state.state2);
ui_draw_soldering_power_status(false);
} else {
basicSolderingStatus(false);
ui_draw_soldering_basic_status(false);
}
// Update the setpoints for the temperature

View File

@@ -1,4 +1,6 @@
#include "OperatingModes.h"
#include "ui_drawing.hpp"
OperatingMode gui_solderingTempAdjust(const ButtonState buttonIn, guiContext *cxt) {
currentTempTargetDegC = 0; // Turn off heater while adjusting temp
@@ -15,8 +17,6 @@ OperatingMode gui_solderingTempAdjust(const ButtonState buttonIn, guiContext *cx
}
}
OLED::setCursor(0, 0);
int16_t delta = 0;
switch (buttons) {
case BUTTON_NONE:
@@ -81,21 +81,7 @@ OperatingMode gui_solderingTempAdjust(const ButtonState buttonIn, guiContext *cx
}
setSettingValue(SettingsOptions::SolderingTemp, (uint16_t)newTemp);
}
if (OLED::getRotation()) {
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE);
} else {
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolMinus : LargeSymbolPlus, FontStyle::LARGE);
}
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
OLED::printNumber(getSettingValue(SettingsOptions::SolderingTemp), 3, FontStyle::LARGE);
OLED::printSymbolDeg(FontStyle::EXTRAS);
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
if (OLED::getRotation()) {
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolMinus : LargeSymbolPlus, FontStyle::LARGE);
} else {
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE);
}
ui_draw_temperature_change();
if (xTaskGetTickCount() - lastButtonTime > (TICKS_SECOND * 3)) {
saveSettings();

View File

@@ -0,0 +1,50 @@
#include "FS2711.hpp"
#include "OperatingModes.h"
#include "stdbool.h"
#include "ui_drawing.hpp"
#if POW_PD_EXT == 2
#ifdef HAS_POWER_DEBUG_MENU
OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) {
// Print out the USB-PD state
// Basically this is like the Debug menu, but instead we want to print out the PD status
uint16_t *screen = &(cxt->scratch_state.state1);
if (*screen > 7) {
*screen = 0;
}
if (*screen == 0) {
// Print the PD Debug state
fs2711_state_t state = FS2711::debug_get_state();
ui_draw_usb_pd_debug_state(0, state.pdo_num);
} else {
// Print out the Proposed power options one by one
uint16_t max_voltage = FS2711::debug_pdo_max_voltage(*screen - 1);
if (max_voltage == 0) {
*screen += 1;
} else {
uint16_t min_voltage = FS2711::debug_pdo_min_voltage(*screen - 1);
uint16_t current = FS2711::debug_pdo_source_current(*screen - 1);
uint16_t pdo_type = FS2711::debug_pdo_type(*screen - 1);
if (pdo_type != 1) {
min_voltage = 0;
}
ui_draw_usb_pd_debug_pdo(*screen, min_voltage / 1000, max_voltage / 1000, current * 1, 0);
}
}
OLED::refresh();
if (buttons == BUTTON_B_SHORT) {
return OperatingMode::InitialisationDone;
} else if (buttons == BUTTON_F_SHORT) {
*screen++;
}
return OperatingMode::UsbPDDebug;
}
#endif
#endif

View File

@@ -1,5 +1,5 @@
#include "OperatingModes.h"
#include "ui_drawing.hpp"
#ifdef POW_PD
#include "pd.h"
#ifdef HAS_POWER_DEBUG_MENU
@@ -7,25 +7,20 @@ OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) {
// Print out the USB-PD state
// Basically this is like the Debug menu, but instead we want to print out the PD status
uint16_t *screen = &(cxt->scratch_state.state1);
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
OLED::print(SmallSymbolPDDebug, FontStyle::SMALL); // Print Title
OLED::setCursor(0, 8); // second line
if ((*screen) == 0) {
// Print the PD state machine
OLED::print(SmallSymbolState, FontStyle::SMALL);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
OLED::printNumber(USBPowerDelivery::getStateNumber(), 2, FontStyle::SMALL, true);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
// Also print vbus mod status
uint8_t vbusState = 0;
if (USBPowerDelivery::fusbPresent()) {
if (USBPowerDelivery::negotiationComplete() || (xTaskGetTickCount() > (TICKS_SECOND * 10))) {
if (!USBPowerDelivery::isVBUSConnected()) {
OLED::print(SmallSymbolNoVBus, FontStyle::SMALL);
vbusState = 2;
} else {
OLED::print(SmallSymbolVBus, FontStyle::SMALL);
vbusState = 1;
}
}
}
ui_draw_usb_pd_debug_state(vbusState, USBPowerDelivery::getStateNumber());
} else {
// Print out the Proposed power options one by one
auto lastCaps = USBPowerDelivery::getLastSeenCapabilities();
@@ -63,25 +58,7 @@ OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) {
if (voltage_mv == 0) {
(*screen) += 1;
} else {
// print out this entry of the proposal
OLED::printNumber(*screen, 2, FontStyle::SMALL, true); // print the entry number
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
if (min_voltage > 0) {
OLED::printNumber(min_voltage / 1000, 2, FontStyle::SMALL, true); // print the voltage
OLED::print(SmallSymbolMinus, FontStyle::SMALL);
}
OLED::printNumber(voltage_mv / 1000, 2, FontStyle::SMALL, true); // print the voltage
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
if (wattage) {
OLED::printNumber(wattage, 3, FontStyle::SMALL, true); // print the current in 0.1A res
OLED::print(SmallSymbolWatts, FontStyle::SMALL);
} else {
OLED::printNumber(current_a_x100 / 100, 2, FontStyle::SMALL, true); // print the current in 0.1A res
OLED::print(SmallSymbolDot, FontStyle::SMALL);
OLED::printNumber(current_a_x100 % 100, 2, FontStyle::SMALL, false); // print the current in 0.1A res
OLED::print(SmallSymbolAmps, FontStyle::SMALL);
}
ui_draw_usb_pd_debug_pdo(*screen, min_voltage / 1000, voltage_mv / 1000, current_a_x100, wattage);
}
} else {
(*screen) = 0;

View File

@@ -0,0 +1,37 @@
#include "HUB238.hpp"
#include "OperatingModes.h"
#include "ui_drawing.hpp"
#if POW_PD_EXT == 1
#ifdef HAS_POWER_DEBUG_MENU
OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) {
// Print out the USB-PD state
// Basically this is like the Debug menu, but instead we want to print out the PD status
uint16_t *screen = &(cxt->scratch_state.state1);
if (*screen > 6) {
*screen = 0;
}
if (*screen == 0) {
// Print the PD Debug state
uint16_t temp = hub238_debug_state();
ui_draw_usb_pd_debug_state(0, temp);
} else {
// Print out the Proposed power options one by one
const uint8_t voltages[] = {5, 9, 12, 15, 18, 20};
uint16_t voltage = voltages[*screen - 1];
uint16_t currentx100 = hub238_getVoltagePDOCurrent(voltage);
ui_draw_usb_pd_debug_pdo(*screen, 0, voltage, currentx100, 0);
}
if (buttons == BUTTON_B_SHORT) {
return OperatingMode::InitialisationDone;
} else if (buttons == BUTTON_F_SHORT) {
*screen++;
}
return OperatingMode::UsbPDDebug;
}
#endif
#endif

View File

@@ -0,0 +1,16 @@
#ifndef OPERATING_MODE_UTILITIES_H_
#define OPERATING_MODE_UTILITIES_H_
#include "Buttons.hpp"
#include "OLED.hpp"
#include <stdbool.h>
void GUIDelay(); //
bool checkForUnderVoltage(void); //
uint32_t getSleepTimeout(void); //
bool shouldBeSleeping(); //
bool shouldShutdown(void); //
void printVoltage(void); //
bool checkForUnderVoltage(void); //
uint16_t min(uint16_t a, uint16_t b); //
void printCountdownUntilSleep(int sleepThres); //
#endif

View File

@@ -7,79 +7,10 @@
#include "Types.h"
#include "configuration.h"
#include "history.hpp"
#include "ui_drawing.hpp"
extern bool heaterThermalRunaway;
void detailedPowerStatus() {
if (OLED::getRotation()) {
OLED::setCursor(0, 0);
} else {
OLED::setCursor(67, 0);
}
// Print wattage
{
uint32_t x10Watt = x10WattHistory.average();
if (x10Watt > 999) {
// If we exceed 99.9W we drop the decimal place to keep it all fitting
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
OLED::printNumber(x10WattHistory.average() / 10, 3, FontStyle::SMALL);
} else {
OLED::printNumber(x10WattHistory.average() / 10, 2, FontStyle::SMALL);
OLED::print(SmallSymbolDot, FontStyle::SMALL);
OLED::printNumber(x10WattHistory.average() % 10, 1, FontStyle::SMALL);
}
OLED::print(SmallSymbolWatts, FontStyle::SMALL);
}
if (OLED::getRotation()) {
OLED::setCursor(0, 8);
} else {
OLED::setCursor(67, 8);
}
printVoltage();
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
}
void basicSolderingStatus(bool boostModeOn) {
OLED::setCursor(0, 0);
// We switch the layout direction depending on the orientation of the oled
if (OLED::getRotation()) {
// battery
gui_drawBatteryIcon();
// Space out gap between battery <-> temp
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
// Draw current tip temp
gui_drawTipTemp(true, FontStyle::LARGE);
// We draw boost arrow if boosting,
// or else gap temp <-> heat indicator
if (boostModeOn) {
OLED::drawSymbol(2);
} else {
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
}
// Draw heating/cooling symbols
OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average()));
} else {
// Draw heating/cooling symbols
OLED::drawHeatSymbol(X10WattsToPWM(x10WattHistory.average()));
// We draw boost arrow if boosting,
// or else gap temp <-> heat indicator
if (boostModeOn) {
OLED::drawSymbol(2);
} else {
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
}
// Draw current tip temp
gui_drawTipTemp(true, FontStyle::LARGE);
// Space out gap between battery <-> temp
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
gui_drawBatteryIcon();
}
}
bool checkExitSoldering(void) {
#ifdef POW_DC
// Undervoltage test

View File

@@ -3,8 +3,6 @@
#ifndef SOLDERING_COMMON_H_
#define SOLDERING_COMMON_H_
void detailedPowerStatus();
void basicSolderingStatus(bool boostModeOn);
bool checkExitSoldering();
TemperatureType_t getTipTemp(void);

View File

@@ -1,6 +1,7 @@
#include "Buttons.hpp"
#include "OperatingModeUtilities.h"
#include "configuration.h"
#include "ui_drawing.hpp"
#ifdef POW_DC
extern volatile TemperatureType_t currentTempTargetDegC;
// returns true if undervoltage has occured
@@ -15,21 +16,7 @@ bool checkForUnderVoltage(void) {
if (xTaskGetTickCount() > (TICKS_SECOND * 2)) {
if ((v < lookupVoltageLevel())) {
currentTempTargetDegC = 0;
OLED::clearScreen();
OLED::setCursor(0, 0);
if (getSettingValue(SettingsOptions::DetailedSoldering)) {
OLED::print(translatedString(Tr->UndervoltageString), FontStyle::SMALL);
OLED::setCursor(0, 8);
OLED::print(translatedString(Tr->InputVoltageString), FontStyle::SMALL);
printVoltage();
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
} else {
OLED::print(translatedString(Tr->UVLOWarningString), FontStyle::LARGE);
}
OLED::refresh();
GUIDelay();
waitForButtonPress();
ui_draw_warning_undervoltage();
return true;
}
}