Files
product-vamp/src/vamp_pico/main.cpp
T
khodowany 2a1aa2c67a UI
2026-09-30 18:23:25 -05:00

108 lines
3.9 KiB
C++

#include <pico/cyw43_arch.h>
#include <pico/stdlib.h>
#include <vamp_pico/display.hpp>
#include <vamp_pico/http_client.hpp>
#include <vamp_pico/input.hpp>
#include <vamp_pico/touch.hpp>
#include <vamp_protocol/page_control.hpp>
auto main() -> int {
stdio_init_all();
// 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();
auto remote = vamp_pico::remote_display_state{};
auto status = vamp_pico::link_status::CONNECTING;
auto gesture = vamp_protocol::gesture_state{};
auto scheduler = vamp_pico::request_scheduler{};
auto busy_until_ms = std::uint64_t{};
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 (!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();
}
}
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.title_image[0] != 0 && !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);
}
}
}
auto busy = now_ms < busy_until_ms || scheduler.queued() != 0U;
display.show_remote(status, remote, busy);
display.poll(now_ms);
sleep_ms(8);
}
}