Rhythm Selection & Cleanup
ci / checks (push) Successful in 1h16m10s

This commit is contained in:
khodowany
2026-09-26 02:50:22 -05:00
parent 4d6348d354
commit 9fd5abd075
91 changed files with 4692 additions and 2484 deletions
+75 -71
View File
@@ -8,96 +8,100 @@
#include <vamp_protocol/page_control.hpp>
namespace {
enum class link_status {
CONNECTING,
RETRYING,
CONNECTED,
};
auto color_for(link_status status) -> vamp_style::color {
switch (status) {
case link_status::CONNECTING:
return vamp_style::connecting;
case link_status::RETRYING:
return vamp_style::retrying;
case link_status::CONNECTED:
return vamp_style::connected;
}
return vamp_style::retrying;
}
auto render(vamp_pico::display &display, link_status status, vamp_pico::remote_display_state const &remote, std::bool_t busy = false) -> void {
display.show_remote(color_for(status), remote.title, remote.part, remote.page, remote.pages, remote.active, busy);
}
auto connect_wifi(vamp_pico::display &display) -> std::bool_t {
auto empty = vamp_pico::remote_display_state{};
render(display, link_status::CONNECTING, empty);
if (cyw43_arch_init() != 0) {
display.show_boot("WIFI", "ERROR", vamp_style::rgb565(vamp_style::danger));
return false;
}
cyw43_arch_enable_sta_mode();
while (cyw43_arch_wifi_connect_timeout_ms(VAMP_PICO_WIFI_SSID, VAMP_PICO_WIFI_PASSPHRASE, CYW43_AUTH_WPA2_AES_PSK, 15000) != 0) {
render(display, link_status::RETRYING, empty);
sleep_ms(2000);
render(display, link_status::CONNECTING, empty);
}
render(display, link_status::RETRYING, empty);
return true;
}
}
auto main() -> int {
stdio_init_all();
auto display = vamp_pico::display{};
// Artwork and network buffers live outside the Pico's small main stack.
static auto display = vamp_pico::display{};
static auto client = vamp_pico::http_client{};
auto touch = vamp_pico::touch_controller{};
display.init();
touch.init();
if (!connect_wifi(display)) {
while (true) {
sleep_ms(1000);
}
}
auto remote = vamp_pico::remote_display_state{};
auto status = link_status::RETRYING;
auto status = vamp_pico::link_status::CONNECTING;
auto gesture = vamp_protocol::gesture_state{};
auto scheduler = vamp_pico::request_scheduler{};
// Keep the owned request buffers off the Pico's small main stack.
static auto client = vamp_pico::http_client{};
auto busy_until_ms = std::uint64_t{};
render(display, status, remote);
auto wifi_ready = cyw43_arch_init() == 0;
if (wifi_ready) {
cyw43_arch_enable_sta_mode();
}
auto wifi_up = false;
auto joining = false;
auto retry_at_ms = std::uint64_t{};
auto join_started_ms = std::uint64_t{};
while (true) {
auto point = vamp_pico::touch_point{};
auto touching = touch.read(point);
auto now_ms = time_us_64() / 1000U;
auto link = CYW43_LINK_DOWN;
if (wifi_ready) {
cyw43_arch_lwip_begin();
link = cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA);
cyw43_arch_lwip_end();
}
if (link != CYW43_LINK_UP) {
if (wifi_up) {
client.cancel();
scheduler = vamp_pico::request_scheduler{};
retry_at_ms = now_ms + 2000U;
}
wifi_up = false;
if (joining && (link < 0 || now_ms - join_started_ms >= 15000U)) {
joining = false;
retry_at_ms = now_ms + 2000U;
}
if (wifi_ready && !joining && now_ms >= retry_at_ms) {
joining = cyw43_arch_wifi_connect_async(VAMP_PICO_WIFI_SSID, VAMP_PICO_WIFI_PASSPHRASE, CYW43_AUTH_WPA2_AES_PSK) == 0;
join_started_ms = now_ms;
retry_at_ms = now_ms + 2000U;
}
status = !wifi_ready ? vamp_pico::link_status::ERROR : joining ? vamp_pico::link_status::CONNECTING
: vamp_pico::link_status::OFFLINE;
} else {
wifi_up = true;
joining = false;
}
if (auto command = gesture.update(touching, now_ms); command) {
if (scheduler.enqueue(*command) == vamp_pico::enqueue_result::BUSY) {
if (!wifi_up || scheduler.enqueue(*command) == vamp_pico::enqueue_result::BUSY) {
busy_until_ms = now_ms + 1000U;
} else if (client.current_kind() == vamp_pico::request_kind::TITLE) {
// An image request is expendable; a command must not wait for its timeout.
client.cancel();
scheduler.cancel_title();
}
}
auto network = client.poll(now_ms);
if (network == vamp_pico::http_status::READY) {
auto result = client.take_result();
scheduler.complete(now_ms);
network = vamp_pico::http_status::IDLE;
if (result && result->success) {
remote = result->display;
status = link_status::CONNECTED;
} else {
status = link_status::RETRYING;
remote = vamp_pico::remote_display_state{};
if (wifi_up) {
auto network = client.poll(now_ms);
if (network == vamp_pico::http_status::READY) {
auto result = client.take_result();
scheduler.complete(now_ms);
network = vamp_pico::http_status::IDLE;
if (result && result->request.kind == vamp_pico::request_kind::TITLE) {
if (result->success && scheduler.queued() == 0U) {
display.accept_title(result->request.title_id.data(), client.title_image());
} else if (!result->success) {
display.reject_title(result->request.title_id.data());
}
} else if (result && result->success) {
remote = result->display;
status = vamp_pico::link_status::CONNECTED;
display.show_remote(status, remote);
if (remote.active && !display.title_ready()) {
scheduler.want_title(remote.title_image.data());
}
} else {
status = vamp_pico::link_status::OFFLINE;
}
}
if (network == vamp_pico::http_status::IDLE) {
if (auto request = scheduler.next(now_ms); request) {
client.start(*request, now_ms);
}
}
}
if (network == vamp_pico::http_status::IDLE) {
if (auto request = scheduler.next(now_ms); request) {
client.start(*request, now_ms);
}
}
render(display, status, remote, now_ms < busy_until_ms);
auto busy = now_ms < busy_until_ms || scheduler.queued() != 0U;
display.show_remote(status, remote, busy);
display.poll(now_ms);
sleep_ms(8);
}
}