32 : pwm_buzzer_(pwm_buzzer),
33 gpio_user_button_1_(gpio_user_button_1),
34 gpio_user_button_2_(gpio_user_button_2),
40 inference_(inference) {
42 std::this_thread::sleep_for(std::chrono::milliseconds(6000));
49 sensor_manager_.Init(ads1115_, aht20_, bmp280_, gui_);
53 inference_handler_.Init(
54 inference_, &mode_manager_, gui_, pwm_buzzer_,
55 [
this](
int duration) { StartTimer(duration); },
56 [
this]() { StopTimer(); });
60 gpio_user_button_1_, gpio_user_button_2_, pwm_buzzer_, gui_,
63 if (mode_manager_.IsStopwatchRunning())
68 [
this]() { StopTimer(); });
74 auto now = std::chrono::system_clock::now();
75 std::time_t t = std::chrono::system_clock::to_time_t(now);
76 std::tm* local_time = std::localtime(&t);
77 int hour = local_time->tm_hour;
78 int minute = local_time->tm_min;
84 auto mode = mode_manager_.GetMode();
85 bool landscape = mode_manager_.IsLandscape();
88 case ModeManager::Mode::TIME:
96 case ModeManager::Mode::HUMIDITY:
99 static_cast<uint8_t
>(sensor_manager_.GetHumidity()));
102 case ModeManager::Mode::TEMPERATURE:
104 gui_->RenderTemperature(
static_cast<uint8_t
>(
105 sensor_manager_.GetCompensatedTemperature()));
108 case ModeManager::Mode::STOPWATCH: {
110 int64_t display_sec = mode_manager_.GetStopwatchSeconds();
111 if (display_sec >= 100 * 60 - 1) display_sec = 100 * 60 - 1;
116 case ModeManager::Mode::TIMER: {
118 int64_t remaining = mode_manager_.GetRemainingTimerSeconds();
121 if (remaining == 0 && mode_manager_.IsTimerRunning()) {
122 pwm_buzzer_->
PlayNote(PWM::NoteName::C, 8, 1000);
124 mode_manager_.StopTimer();
130 }
else if (mode_manager_.IsTimerRunning()) {
133 int target_grid_down_count =
134 128 -
static_cast<int>(128.0f *
static_cast<float>(remaining) /
136 mode_manager_.GetMaxTimerDuration()));
137 target_grid_down_count = std::clamp(target_grid_down_count, 0, 128);
140 if (target_grid_down_count > gui_->
grid_down_.Count()) {
141 SandGrid::MoveSand(&gui_->grid_up_, &gui_->
grid_down_,
152 std::cout <<
"Unknown mode\n";
156 std::this_thread::sleep_for(std::chrono::milliseconds(5));
160 std::cout <<
"[FluxSand::UnitTest] Starting application unit test...\n";
162 auto t0 = std::chrono::high_resolution_clock::now();
165 for (
int i = 0; i <= static_cast<int>(ModeManager::Mode::TIMER); ++i) {
166 ModeManager::Mode mode =
static_cast<ModeManager::Mode
>(i);
167 std::cout << std::format(
" [Test] Simulating mode: {}\n", i);
170 mode_manager_.SetMode(mode);
172 case ModeManager::Mode::STOPWATCH:
173 mode_manager_.StartStopwatch();
175 case ModeManager::Mode::TIMER:
176 mode_manager_.StartTimer(30);
182 auto start = std::chrono::high_resolution_clock::now();
184 auto end = std::chrono::high_resolution_clock::now();
186 std::chrono::duration<float, std::milli>(end - start).count();
187 std::cout << std::format(
" → Run() completed in {:.2f} ms\n", elapsed);
190 auto t1 = std::chrono::high_resolution_clock::now();
191 float total = std::chrono::duration<float, std::milli>(t1 - t0).count();
192 std::cout << std::format(
193 "[FluxSand::UnitTest] ✅ All modes tested in {:.2f} ms\n", total);
198 void StartStopwatch() { mode_manager_.StartStopwatch(); }
199 void StopStopwatch() { mode_manager_.StopStopwatch(); }
202 void StartTimer(
int duration_sec) {
203 mode_manager_.StartTimer(duration_sec);
206 void StopTimer() { mode_manager_.StopTimer(); }
210 Gpio* gpio_user_button_1_;
211 Gpio* gpio_user_button_2_;