Public Access
The Notes App lists the files of /notes by their first line, newest first: n starts a note, Enter opens it, r renames its file, d deletes it after asking, s sorts by name. A new note's file is named after its first line. The editor wraps at spaces, 38 columns by 8 rows; Fn+arrows move through the wrapped text, Ctrl+A and Ctrl+E go to the ends of the line. There is no save key: the note is written five seconds after the last key, on Back, on leaving the App, when the screen turns off and before the device powers off. A save writes a temporary file and puts it in the note's place; a save cut short is put back, or offered, the next time. A note is up to 16 KB, held in one buffer reserved when it's opened: the file is read straight into it and typing never makes it grow. A failed allocation aborts on this device, and with IRC connected the largest free block is about 31 KB: a first version that copied the note once on loading restarted the device when a full note was opened with IRC connected. Editing files of any size is #47. The Storage App's text viewer gets `e`, which edits a text file up to 16 KB with the same editor unless the file is read-only. 439 host tests. Checked on the device: docs/milestones/F1.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
62 lines
2.1 KiB
C++
62 lines
2.1 KiB
C++
#include "power_service.h"
|
|
|
|
#include <M5Cardputer.h>
|
|
#include <esp_sleep.h>
|
|
|
|
#include "platform/pins.h"
|
|
|
|
namespace roro {
|
|
|
|
PowerService::PowerService(const Settings& settings)
|
|
: settings_(settings),
|
|
policy_(settings.getInt(Setting::DimTimeoutS) * 1000, settings.getInt(Setting::OffTimeoutS) * 1000) {}
|
|
|
|
void PowerService::start() {
|
|
pinMode(pins::kButtonG0, INPUT_PULLUP);
|
|
policy_.activity(millis());
|
|
applyScreen(ScreenState::On);
|
|
}
|
|
|
|
void PowerService::tick(uint32_t nowMs) {
|
|
policy_.setTimeouts(settings_.getInt(Setting::DimTimeoutS) * 1000,
|
|
settings_.getInt(Setting::OffTimeoutS) * 1000);
|
|
applyScreen(policy_.update(nowMs));
|
|
|
|
bool pressed = digitalRead(pins::kButtonG0) == LOW;
|
|
if (button_.update(pressed, nowMs) == ButtonAction::LongPress) powerOff();
|
|
}
|
|
|
|
void PowerService::applyScreen(ScreenState state) {
|
|
auto& display = M5Cardputer.Display;
|
|
int percent = settings_.getInt(Setting::Brightness);
|
|
int target = state == ScreenState::On ? percent : state == ScreenState::Dimmed ? percent / 4 : 0;
|
|
if (state == applied_ && target == appliedBrightness_) return;
|
|
|
|
if (state == ScreenState::Off)
|
|
display.sleep();
|
|
else if (applied_ == ScreenState::Off)
|
|
display.wakeup();
|
|
display.setBrightness(target * 255 / 100);
|
|
applied_ = state;
|
|
appliedBrightness_ = target;
|
|
}
|
|
|
|
void PowerService::powerOff() {
|
|
if (beforePowerOff) beforePowerOff();
|
|
auto& display = M5Cardputer.Display;
|
|
display.wakeup();
|
|
display.setBrightness(settings_.getInt(Setting::Brightness) * 255 / 100);
|
|
display.fillScreen(TFT_BLACK);
|
|
display.setTextColor(TFT_WHITE);
|
|
display.drawCenterString("Powering off", display.width() / 2, display.height() / 2 - 8);
|
|
// G0 wakes the device on a low level, so wait for release or it would wake immediately.
|
|
while (digitalRead(pins::kButtonG0) == LOW) delay(10);
|
|
delay(300);
|
|
display.sleep();
|
|
display.setBrightness(0);
|
|
esp_sleep_enable_ext0_wakeup(static_cast<gpio_num_t>(pins::kButtonG0), 0);
|
|
esp_deep_sleep_start();
|
|
}
|
|
|
|
} // namespace roro
|