-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDisplayManager.cpp
More file actions
189 lines (164 loc) · 6.54 KB
/
Copy pathDisplayManager.cpp
File metadata and controls
189 lines (164 loc) · 6.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// Copyright (c) 2025 Lytrix (Eelke Jager)
// Licensed under the PolyForm Noncommercial 1.0.0
// DisplayManager.cpp
#include "DisplayManager.h"
#include "TrackManager.h"
#include "ClockManager.h"
#include "Globals.h"
#include "SSD1322_Config.h"
#include "TrackUndo.h"
#include "Logger.h"
#include "Utils/NoteUtils.h"
#include "TickPhase.h"
#include "ControlSurfaceManager.h"
#include "NoteEditFocus.h"
#include "NoteEditSessionState.h"
#include "Utils/NoteEditDisplaySnapshot.h"
#include "MidiHandler.h"
#include "Utils/HotPathTelemetry.h"
#include "Utils/DebugSessionCapture.h"
#include "Utils/Diagnostics.h"
#include "Utils/DisplayWindowUtils.h"
#include "Utils/SlotFocusDisplay.h"
#include "TrackStateMachine.h"
#include "MidiButtonManager.h"
#include "MidiConfig.h"
#include "StorageManager.h"
#include "SlotLoadSession.h"
#include "SetBrowserOverlayPolicy.h"
#include "SetRevisionCatalog.h"
#include "RtcTime.h"
#include "HitlDisplayBridge.h"
#include "DisplayManagerInternal.h"
#if defined(__IMXRT1062__)
#define DISP_COLD_MEM FLASHMEM
#else
#define DISP_COLD_MEM
#endif
using namespace DisplayManagerInternal;
#include "DeferredSaveDisplayStatus.h"
#include "LooperState.h"
#include "SavedSetCatalog.h"
#include <algorithm>
#include <cstring>
#include <string>
#include <Font5x7Fixed.h>
#include <Font5x7FixedMono.h>
#if defined(SESSION_CAPTURE) && defined(__IMXRT1062__)
#define DISP_CAPTURE_MEM FLASHMEM
#else
#define DISP_CAPTURE_MEM
#endif
DMAMEM DisplayManager displayManager;
DisplayManager::DisplayManager() : _display() {
// Don't initialize SPI here - it will be done in setup()
}
// Helper function to clear the display buffer
void DisplayManager::clearDisplayBuffer() {
Serial.println("DisplayManager: Clearing display buffer");
_display.gfx.fill_buffer(_display.api.getFrameBuffer(), 0);
Serial.println("DisplayManager: Display buffer cleared");
Serial.println("DisplayManager: Displaying buffer");
_display.api.display();
Serial.println("DisplayManager: Display buffer displayed");
}
void DisplayManager::setup() {
Serial.println("DisplayManager: Setting up SSD1322 display...");
// Initialize display
_display.begin();
// Set buffer size and clear display
Serial.println("DisplayManager: Setting buffer size");
_display.gfx.set_buffer_size(DISPLAY_WIDTH, DISPLAY_HEIGHT);
clearDisplayBuffer();
}
void DisplayManager::update() {
#if defined(SESSION_CAPTURE) || HOT_PATH_TELEMETRY_ENABLED
const uint32_t telemetryStartUs = micros();
#endif
uint32_t now = millis();
if (bootScreenVisible_) {
if (!bootSetupComplete_ || now < bootScreenHoldUntilMs_) {
return;
}
bootScreenVisible_ = false;
}
uint32_t currentTick = clockManager.getCurrentTick();
const bool loadSaveActive = looperState.isLoadSaveModeActive();
if (!loadSaveActive && StorageManager::consumeRevisionLoadDisplayRefreshPending()) {
workspaceDisplayRefreshPending_ = true;
}
Track& selTrack = trackManager.getSelectedTrack();
const uint8_t displaySlot = trackManager.getSelectedSlotIndex(trackManager.getSelectedTrackIndex());
uint32_t displayTick = selTrack.getEffectivePlaybackTick(currentTick);
refreshAutoSaveBeforeLoadToast(now);
if (loadSaveActive && !loadSaveModeWasActive_) {
const bool preserveNavigation = SetBrowserOverlayPolicy::shouldPreserveOverlayNavigationOnEnter(
StorageManager::getSetBrowserOverlayPersistencePhase());
if (!preserveNavigation) {
StorageManager::resetSetBrowserOverlayNavigation();
loadSaveListSelection_ = 0;
loadSaveListScrollOffset_ = 0;
invalidateLoadSaveRevisionListCache();
}
if (!loadSaveListCacheValid_ && StorageManager::isOverlayCatalogReadAllowed()) {
refreshLoadSaveListCache();
}
invalidateLoadSaveDetailCache();
} else if (!loadSaveActive && loadSaveModeWasActive_) {
if (StorageManager::isRevisionLoadHeldForWorkspaceDirty()) {
StorageManager::cancelRevisionLoadRequest();
}
StorageManager::resetSetBrowserOverlayNavigation();
invalidateLoadSaveRevisionListCache();
invalidateLoadSaveDetailCache();
}
loadSaveModeWasActive_ = loadSaveActive;
applyWorkspaceDisplayRefreshPending(currentTick);
_display.gfx.fill_buffer(_display.api.getFrameBuffer(), 0);
if (loadSaveActive) {
drawLoadSaveView(now);
_display.api.display();
HOT_PATH_TELEMETRY_RECORD_DISPLAY_UPDATE(micros() - telemetryStartUs);
DIAG_TIMING_RECORD(DisplayUpdateTotal, micros() - telemetryStartUs);
return;
}
drawTrackStatus(trackManager.getSelectedTrackIndex(), now);
const DisplayNoteVec& frameNotes = resolveDisplayNotes(selTrack, displaySlot, displayTick);
#if defined(SESSION_CAPTURE)
maybeEmitDisplayCaptureOnChange(selTrack, displaySlot, displayTick, frameNotes);
#endif
drawPianoRoll(displayTick, selTrack, displaySlot, frameNotes);
drawSidebar(selTrack, displaySlot);
drawInfoArea(displayTick, selTrack, displaySlot, now);
drawNoteInfo(displayTick, selTrack, displaySlot, frameNotes);
_display.api.display();
#if defined(SESSION_CAPTURE)
{
static uint32_t dframeCounter = 0;
if (++dframeCounter % 30U == 0U) {
SC_DFRAME(static_cast<uint32_t>(frameNotes.size()),
static_cast<uint32_t>(micros() - telemetryStartUs), dframeCounter);
}
}
#endif
HOT_PATH_TELEMETRY_RECORD_DISPLAY_UPDATE(micros() - telemetryStartUs);
DIAG_TIMING_RECORD(DisplayUpdateTotal, micros() - telemetryStartUs);
// Acknowledge unconditionally: invalidateLiveDisplayCache raises the paint request with no
// note-edit precondition, so gating the ack on isNoteEditActive left it permanently raised
// outside a session. maybeUpdateDisplayForNoteEditSelection has no cadence gate, so the OLED
// then repainted every loop iteration — 152948 measured a 14 ms frame period against the
// 30 ms interval, ~93% of loop time here, from boot onward.
editManager.markNoteEditDisplayPainted();
}
#if defined(SESSION_CAPTURE)
namespace HitlDisplayBridge {
void confirmLoadSaveFocusedRow() { displayManager.confirmLoadSaveFocusedRow(); }
void adjustLoadSaveListSelection(int delta) { displayManager.adjustLoadSaveListSelection(delta); }
void openRevisionHistoryFromHitl(uint16_t setId) {
displayManager.openRevisionHistoryFromHitl(setId);
}
void navigateLoadSaveOverlayBackFromHitl() {
displayManager.navigateLoadSaveOverlayBackFromHitl();
}
} // namespace HitlDisplayBridge
#endif