#include #include #include #include #include #include #include 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); } }