feat(eink): landscape and portrait builds, 8x13 font in landscape

The L1 e-ink solo build splits in two, one per screen shape, so each
screen can be laid out for a single shape. Settings > Rotation now only
turns the screen upside down, and the joystick turns with it.

Landscape writes in misc-fixed 8x13 at the panel's own resolution
(EINK_LARGE_FONT); portrait keeps the 6x9. All drawing moves into
EinkGfxDisplay, which the panel driver and the simulator share; the
FreeSans fonts and the CRC32 library go.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-10-02 19:24:36 +02:00
co-authored by Claude Opus 5.5
parent a733b8bcf5
commit b0e24bb076
11 changed files with 2459 additions and 323 deletions
+7
View File
@@ -46,6 +46,13 @@
// would split the build the day this is flipped to 1.
#define FEAT_RX_POWERSAVE 0
// The display rotation at which the joystick's own up reads as up. An e-ink
// panel turned from it turns the joystick with it (UITask), on top of the
// Joystick setting. Unset, the build's own rotation: only a flip turns it.
#if defined(DISPLAY_ROTATION) && !defined(JOYSTICK_UPRIGHT_ROTATION)
#define JOYSTICK_UPRIGHT_ROTATION DISPLAY_ROTATION
#endif
namespace Features {
#if defined(EINK_DISPLAY_MODEL)
@@ -538,7 +538,7 @@ class SettingsScreen : public UIScreen {
#endif
#if FEAT_DISPLAY_ROTATION_SETTING
} else if (item == ROTATION) {
val("Rotation", rotLabel(p ? p->display_rotation : 0));
val("Rotation", rotLabel(p ? p->display_rotation - DISPLAY_ROTATION : 0));
#endif
#if FEAT_JOYSTICK_ROTATION_SETTING
} else if (item == JOY_ROTATION) {
@@ -1040,7 +1040,7 @@ public:
#endif
#if FEAT_DISPLAY_ROTATION_SETTING
if (_selected == ROTATION && p && (left || right || enter)) {
p->display_rotation = (p->display_rotation + (left ? 3 : 1)) & 3;
p->display_rotation ^= 2; // the build's shape, either way up
_task->applyRotation();
_dirty = true;
return true;
@@ -2803,6 +2803,9 @@ void UITask::loop() {
if (status_screen) ((StatusScreen*)status_screen)->sample(); // Status history lines, once a minute
#if UI_HAS_JOYSTICK
uint8_t joy_rot = _node_prefs ? _node_prefs->joystick_rotation : JOYSTICK_ROTATION;
#if FEAT_DISPLAY_ROTATION_SETTING && defined(JOYSTICK_UPRIGHT_ROTATION)
if (_node_prefs) joy_rot += (JOYSTICK_UPRIGHT_ROTATION - _node_prefs->display_rotation) & 3;
#endif
int ev = user_btn.check();
if (ev == BUTTON_EVENT_CLICK) {
if (back_btn.isPressed() && !_unlock_kb) {
@@ -3606,6 +3609,13 @@ void UITask::applyBrightness() {
void UITask::applyRotation() {
if (_display != NULL && _node_prefs != NULL) {
#if FEAT_DISPLAY_ROTATION_SETTING && defined(DISPLAY_ROTATION)
// Each build is laid out for one shape and only turns it upside down: a
// rotation of the other shape (a fresh device's 0, another build's, or
// from before the split) comes back to this build's own.
uint8_t& rot = _node_prefs->display_rotation;
if ((rot ^ DISPLAY_ROTATION) & 1) rot = DISPLAY_ROTATION & 3;
#endif
_display->setDisplayRotation(_node_prefs->display_rotation);
_next_refresh = 0;
}