1414#include " common/Config.h"
1515#include " common/DoubleBuffer.h"
1616#include " domain/DataStore.h"
17- #include " domain/TripLogic .h"
17+ #include " domain/TripState .h"
1818#include " domain/VoltageMonitor.h"
1919#include " hardware/Clock.h"
2020#include " hardware/Gnss.h"
21- #include " ui/FrameLogic.h"
22- #include " ui/UI.h"
21+ #include " ui/DisplayFrame.h"
22+ #include " ui/Input.h"
23+ #include " ui/Renderer.h"
24+ #include < LowPower.h>
2325
2426class App {
2527private:
2628 Gnss gnss;
2729 Clock systemClock;
2830 DataStore dataStore;
2931 VoltageMonitor voltageMonitor;
30- UI userInterface;
32+ Input input;
33+ Renderer renderer;
3134
3235 Mode currentMode = Mode::SPD_TIM;
3336
3437 DoubleBuffer<TripState> tripBuffer;
3538 DoubleBuffer<DisplayFrame> frameBuffer;
3639 DoubleBuffer<SaveData> saveBuffer;
3740
38- unsigned long currentTime = 0 ;
39- GnssData currentGnss = {};
40- Input::Event currentButton = Input::Event::NONE;
41- SpGnssTime currentClock = {};
42- float currentVoltage = 0 .0f ;
41+ unsigned long currentTime = 0 ;
42+ GnssData currentGnss = {};
43+ Input::Event currentButton = Input::Event::NONE;
4344
4445 unsigned long lastSaveMs = 0 ;
4546 unsigned long lastUiUpdateMs = 0 ;
4647
47- bool gnssInitialized = false ;
48-
4948public:
50- /* *
51- * @brief アプリケーションの初期化
52- * @return true: 全モジュールの初期化成功, false: いずれかのモジュールが失敗
53- */
54- bool begin () {
55- // GNSS初期化(失敗してもアプリは継続可能)
56- gnssInitialized = gnss.begin ();
57- if (!gnssInitialized) {
58- // GNSSが使えなくても他の機能は動作可能
59- // ログ出力やLED点滅などで警告を出すことも検討
60- }
49+ App () : input(Config::Pins::BUTTON_SELECT, Config::Pins::BUTTON_PAUSE) {}
50+
51+ void begin () {
52+ if (!renderer.begin ()) shutdown ();
53+ input.begin ();
54+ if (!gnss.begin ()) shutdown ();
6155
6256 systemClock.begin ();
6357 voltageMonitor.begin ();
64- userInterface.begin ();
6558 loadFromStorage ();
66-
67- return gnssInitialized; // メイン機能の状態を返す
6859 }
6960
7061 void update () {
@@ -74,88 +65,83 @@ class App {
7465 }
7566
7667private:
68+ void shutdown () {
69+ LowPower.begin ();
70+ LowPower.deepSleep (0 );
71+ }
72+
7773 void loadFromStorage () {
7874 SaveData saved = dataStore.load ();
79-
80- TripState state;
81- state.resetAll ();
82- state.distance .total = saved.totalDistance ;
83- state.distance .trip = saved.tripDistance ;
84- state.time .moving = saved.movingTimeMs ;
85- state.speed .max = saved.maxSpeed ;
86-
87- tripBuffer.initialize (state);
75+ tripBuffer.initialize (TripState (saved));
8876 saveBuffer.initialize (saved);
8977 lastSaveMs = millis ();
9078 }
9179
9280 void collectInputs () {
93- currentTime = millis ();
94- currentButton = userInterface.getInputEvent ();
95- currentClock = systemClock.now ();
96- currentVoltage = voltageMonitor.update ();
81+ currentTime = millis ();
82+ currentButton = input.update ();
9783
9884 bool updated = gnss.update ();
99- currentGnss.status = updated ? UpdateStatus::Updated : UpdateStatus::NoChange ;
85+ currentGnss.updated = updated;
10086 currentGnss.navData = gnss.navData ;
10187
102- if (updated && (SpFixMode)currentGnss.navData .posFixMode != FixInvalid) {
103- systemClock.sync (currentGnss.navData .time );
88+ if (updated) {
89+ const SpFixMode fixMode = (SpFixMode)currentGnss.navData .posFixMode ;
90+ if (fixMode == Fix2D || fixMode == Fix3D) { systemClock.sync (currentGnss.navData .time ); }
10491 }
10592 }
10693
10794 void updateState () {
108- tripBuffer.prepare ();
109- tripBuffer.current ().resetMeta ();
110-
111- if (currentButton != Input::Event::NONE) {
112- if (handleButton ()) return ;
113- }
114-
115- TripLogic::computeTrip (tripBuffer.current (), currentGnss, currentTime);
95+ if (currentButton != Input::Event::NONE) handleButton ();
96+ tripBuffer.apply (TripState (tripBuffer.current (), currentGnss, currentTime));
11697 }
11798
118- bool handleButton () {
99+ void handleButton () {
119100 TripState &state = tripBuffer.current ();
120101
121102 switch (currentButton) {
122103 case Input::Event::SELECT:
123- currentMode = static_cast <Mode>((static_cast <int >(currentMode) + 1 ) % 3 );
124- state.forceUpdate ();
104+ currentMode = rotateMode (currentMode);
125105 break ;
126106
127107 case Input::Event::PAUSE:
128- state.status =
129- state.isPaused () ? TripStateBase::Status::Stopped : TripStateBase::Status::Paused;
130- state.forceUpdate ();
108+ state.status = state.isPaused () ? TripState::Status::Stopped : TripState::Status::Paused;
131109 break ;
132110
133111 case Input::Event::RESET:
134112 applyReset (currentMode);
135113 break ;
136114
137115 case Input::Event::RESET_LONG:
138- state.resetAll ();
139- dataStore.clear ();
140- userInterface.showResetMessage ();
141- frameBuffer.initialize (DisplayFrame ());
142- saveBuffer.initialize (createSaveData (state, 0 .0f ));
143- return true ;
116+ resetAllData ();
117+ break ;
144118
145119 default :
146120 break ;
147121 }
148- return false ;
122+ }
123+
124+ static Mode rotateMode (Mode mode) {
125+ return static_cast <Mode>((static_cast <int >(mode) + 1 ) % Config::UI::MODE_COUNT);
126+ }
127+
128+ void resetAllData () {
129+ TripState &state = tripBuffer.current ();
130+ state.clearAllData ();
131+ dataStore.clear ();
132+ renderer.showResetMessage ();
133+ frameBuffer.initialize (DisplayFrame ());
134+ saveBuffer.initialize (SaveData (state, 0 .0f ));
149135 }
150136
151137 void applyReset (Mode mode) {
152138 TripState &state = tripBuffer.current ();
153139 switch (mode) {
154140 case Mode::SPD_TIM:
155- state.resetTrip ();
141+ state.clearTripData ();
156142 break ;
157143 case Mode::AVG_ODO:
158- state.resetAll ();
144+ state.clearAllData ();
159145 break ;
160146 case Mode::MAX_CLK:
161147 state.resetMaxSpeed ();
@@ -171,47 +157,36 @@ class App {
171157 void outputToDisplay () {
172158 if (!shouldUpdateUI ()) return ;
173159
174- DisplayFrame nextFrame =
175- FrameLogic::buildFrame (tripBuffer.current (), currentGnss, currentClock, currentMode);
176-
160+ SpGnssTime nowClock = systemClock.now ();
161+ DisplayFrame nextFrame (tripBuffer.current (), currentGnss, nowClock, currentMode);
177162 if (frameBuffer.apply (nextFrame)) {
178- userInterface. draw (frameBuffer.current ());
163+ renderer. render (frameBuffer.current ());
179164 lastUiUpdateMs = currentTime;
180165 }
181166 }
182167
183168 bool shouldUpdateUI () const {
184- return (currentButton != Input::Event::NONE) ||
185- (currentTime - lastUiUpdateMs >= Config::UI::UPDATE_INTERVAL_MS) ||
186- TripLogic::isChanged (tripBuffer.previous (), tripBuffer.current ()) ||
187- (currentGnss.status == UpdateStatus::Updated);
169+ const bool hasButtonInput = (currentButton != Input::Event::NONE);
170+ const bool intervalElapsed = (currentTime - lastUiUpdateMs >= Config::UI::UPDATE_INTERVAL_MS);
171+ const bool stateChanged = (tripBuffer.previous () != tripBuffer.current ());
172+ const bool gnssUpdated = currentGnss.updated ;
173+ return hasButtonInput || intervalElapsed || stateChanged || gnssUpdated;
188174 }
189175
190176 void outputToStorage () {
191177 if (!shouldSave ()) return ;
178+ float currentVoltage = voltageMonitor.update ();
179+ TripState &state = tripBuffer.current ();
180+ state.updateAverageSpeed ();
192181
193- SaveData nextSave = createSaveData (tripBuffer.current (), currentVoltage);
194-
195- if (saveBuffer.apply (nextSave)) { dataStore.save (saveBuffer.current ()); }
182+ SaveData nextSave (state, currentVoltage);
183+ if (saveBuffer.apply (nextSave)) dataStore.save (saveBuffer.current ());
196184 lastSaveMs = currentTime;
197185 }
198186
199187 bool shouldSave () const {
200188 const bool shouldUpdate = (currentTime - lastSaveMs >= DataStore::SAVE_INTERVAL_MS);
201- const bool gnssStable = ( currentGnss.status == UpdateStatus::NoChange) ;
189+ const bool gnssStable = ! currentGnss.updated ;
202190 return shouldUpdate && gnssStable;
203191 }
204-
205- static SaveData createSaveData (const TripState &state, float voltage) {
206- SaveData data;
207- data.magicNumber = SAVE_DATA_MAGIC_NUMBER;
208- data.totalDistance = state.distance .total ;
209- data.tripDistance = state.distance .trip ;
210- data.movingTimeMs = state.time .moving ;
211- data.maxSpeed = state.speed .max ;
212- data.voltage = voltage;
213- data.updateStatus = state.updateStatus ;
214- data.crc = 0 ;
215- return data;
216- }
217192};
0 commit comments