+75
-71
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user