108 lines
3.9 KiB
C++
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);
|
|
}
|
|
}
|