Kennedn 2024-04-12 17:57:23 +00:00 zatwierdzone przez GitHub
commit fb7898f899
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
28 zmienionych plików z 1289 dodań i 0 usunięć

Wyświetl plik

@ -52,6 +52,7 @@ add_subdirectory(automation2040w)
add_subdirectory(plasma_stick)
add_subdirectory(plasma2040)
add_subdirectory(badger2040)
add_subdirectory(badger2040w)
add_subdirectory(tufty2040)
add_subdirectory(interstate75)
add_subdirectory(servo2040)

Wyświetl plik

@ -0,0 +1,6 @@
include(badger2040w_sleep.cmake)
include(badger2040w_drawing.cmake)
include(badger2040w_fonts.cmake)
include(badger2040w_image.cmake)
include(badger2040w_icon.cmake)
include(badger2040w_rtc.cmake)

Wyświetl plik

@ -0,0 +1,12 @@
set(OUTPUT_NAME badger2040w_drawing)
add_executable(${OUTPUT_NAME} badger2040w_drawing.cpp)
target_link_libraries(${OUTPUT_NAME}
badger2040w
hardware_spi
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})

Wyświetl plik

@ -0,0 +1,45 @@
#include "pico/stdlib.h"
#include <stdio.h>
#include "common/pimoroni_common.hpp"
#include "badger2040w.hpp"
using namespace pimoroni;
Badger2040W badger;
uint32_t time() {
absolute_time_t t = get_absolute_time();
return to_ms_since_boot(t);
}
int main() {
badger.init();
stdio_init_all();
printf("\n\n=======\nbadger2040 starting up\n\n");
badger.uc8151->set_update_speed(2);
badger.graphics->set_font("bitmap8");
badger.graphics->set_thickness(2);
char time_str[11];
while(true) {
badger.graphics->set_pen(15);
badger.graphics->clear();
badger.graphics->set_pen(0);
badger.graphics->rectangle(Rect(0,badger.DISPLAY_HEIGHT / 4,badger.DISPLAY_WIDTH,badger.DISPLAY_HEIGHT / 2));
badger.graphics->set_pen(15);
badger.graphics->rectangle(Rect(5,badger.DISPLAY_HEIGHT / 4 + 5,badger.DISPLAY_WIDTH - 10,badger.DISPLAY_HEIGHT / 2 - 10));
badger.graphics->set_pen(0);
sprintf(time_str, "%ld", time());
int32_t time_x_centered = (badger.DISPLAY_WIDTH - badger.graphics->measure_text(time_str, 2.0f)) / 2;
badger.graphics->text("Time since boot (ms)", Point(5, 10), badger.DISPLAY_WIDTH, 2.0f);
badger.graphics->text(time_str, Point(time_x_centered, badger.DISPLAY_HEIGHT / 2 - 8), badger.DISPLAY_WIDTH, 2.0f);
badger.update();
sleep_ms(5000);
}
}

Wyświetl plik

@ -0,0 +1,12 @@
set(OUTPUT_NAME badger2040w_fonts)
add_executable(${OUTPUT_NAME} badger2040w_fonts.cpp)
target_link_libraries(${OUTPUT_NAME}
badger2040w
hardware_spi
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})

Wyświetl plik

@ -0,0 +1,103 @@
#include "pico/stdlib.h"
#include <stdio.h>
#include <cstring>
#include <string>
#include <algorithm>
#include "pico/time.h"
#include "pico/platform.h"
#include "common/pimoroni_common.hpp"
#include "badger2040w.hpp"
using namespace pimoroni;
Badger2040W badger;
uint32_t time() {
absolute_time_t t = get_absolute_time();
return to_ms_since_boot(t);
}
std::array<std::string, 8> font_names = {
"sans", "sans_bold", "gothic", "cursive",
"cursive_bold", "serif", "serif_bold", "serif_italic"
};
int8_t selected_font = 0;
void draw() {
badger.graphics->set_pen(15);
badger.graphics->clear();
badger.graphics->set_font("sans");
for(int i = 0; i < int(font_names.size()); i++) {
std::string name = font_names[i];
if(selected_font == i) {
badger.graphics->set_pen(0);
badger.graphics->rectangle(Rect(0, i * 16, 80, 16));
badger.graphics->set_pen(15);
}else{
badger.graphics->set_pen(0);
}
badger.graphics->text(name, Point(2, i * 16 + 7), badger.DISPLAY_WIDTH, 0.4f);
}
badger.graphics->set_font(font_names[selected_font]);
badger.graphics->set_thickness(2);
badger.graphics->text("The quick", Point(90, 10), badger.DISPLAY_WIDTH, 0.80f);
badger.graphics->text("brown fox", Point(90, 32), badger.DISPLAY_WIDTH, 0.80f);
badger.graphics->text("jumped over", Point(90, 54), badger.DISPLAY_WIDTH, 0.80f);
badger.graphics->text("the lazy dog.", Point(90, 76), badger.DISPLAY_WIDTH, 0.80f);
badger.graphics->text("0123456789", Point(90, 98), badger.DISPLAY_WIDTH, 0.80f);
badger.graphics->text("!\"£$%^&*()", Point(90, 120), badger.DISPLAY_WIDTH, 0.80f);
badger.graphics->set_thickness(1);
badger.update();
}
int main() {
badger.init();
stdio_init_all();
printf("\n\n=======\nbadger2040 starting up\n\n");
badger.uc8151->set_update_speed(2);
uint32_t i = 0;
while(true) {
printf("> drawing..");
draw();
printf("done!\n");
printf("> waiting for a button press..");
badger.wait_for_press();
printf("done!\n");
if(badger.pressed(badger.DOWN)) {
printf("> down pressed\n");
selected_font++;
}
if(badger.pressed(badger.UP)) {
printf("> up pressed\n");
selected_font--;
}
if(badger.pressed(badger.C)) {
printf("> C pressed\n");
badger.halt();
}
selected_font = selected_font < 0 ? int(font_names.size()) - 1 : selected_font;
selected_font = selected_font >= int(font_names.size()) ? 0 : selected_font;
printf("> newly selected font is %s (%d)\n", font_names[selected_font].c_str(), selected_font);
i++;
}
}

Wyświetl plik

@ -0,0 +1,12 @@
set(OUTPUT_NAME badger2040w_icon)
add_executable(${OUTPUT_NAME} badger2040w_icon.cpp)
target_link_libraries(${OUTPUT_NAME}
badger2040w
hardware_spi
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})

Wyświetl plik

@ -0,0 +1,36 @@
#include "pico/stdlib.h"
#include <stdio.h>
#include "common/pimoroni_common.hpp"
#include "badger2040w.hpp"
#include "badger2040w_icon_demo_icons.hpp"
using namespace pimoroni;
Badger2040W badger;
int main() {
badger.init();
stdio_init_all();
printf("\n\n=======\nbadger2040 starting up\n\n");
badger.uc8151->set_update_speed(1);
badger.graphics->set_pen(15);
badger.graphics->clear();
auto iconsize = 40;
auto x_offset = 10;
for (auto x=0; x < (int)badger.DISPLAY_WIDTH / iconsize; x++) {
for (auto i=0; i < 3; i++) {
auto idx = (i + x) % 3;
badger.icon(iconsheet, idx, iconsize * 3, Rect(x_offset + x * iconsize, iconsize * i, iconsize, iconsize));
}
}
badger.update();
badger.halt();
}

Wyświetl plik

@ -0,0 +1,3 @@
static const uint8_t iconsheet[600] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x58, 0x00, 0x15, 0xff, 0x55, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc1, 0x81, 0x87, 0x80, 0x1f, 0xff, 0xe9, 0x7f, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x40, 0x0f, 0xff, 0xe5, 0x7f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x40, 0x17, 0xff, 0xd4, 0xff, 0xfc, 0x00, 0x00, 0xff, 0x00, 0x00, 0x02, 0x00, 0x18, 0x00, 0x40, 0x1f, 0xff, 0xea, 0xff, 0xfc, 0x00, 0x01, 0xff, 0x80, 0x00, 0x02, 0x00, 0x18, 0x00, 0x40, 0x0f, 0xff, 0xd2, 0x7f, 0xfc, 0x00, 0x07, 0xff, 0xe0, 0x00, 0x02, 0x01, 0x18, 0x00, 0x40, 0x17, 0xff, 0xa9, 0xff, 0xfc, 0x00, 0xff, 0xc7, 0xe0, 0x00, 0x01, 0x00, 0x99, 0x00, 0x80, 0x1f, 0xff, 0xca, 0x7f, 0xfc, 0x01, 0xff, 0x81, 0xf0, 0x00, 0x01, 0x00, 0x7e, 0x01, 0x00, 0x0f, 0xff, 0xa5, 0x7f, 0xfc, 0x03, 0xff, 0x80, 0xf8, 0x00, 0x00, 0xc0, 0x7e, 0x01, 0x00, 0x13, 0xff, 0xd2, 0xff, 0xfc, 0x07, 0xff, 0xb4, 0xf8, 0x00, 0x00, 0x20, 0xff, 0x06, 0x00, 0x0f, 0xff, 0xd4, 0xff, 0xfc, 0x07, 0xff, 0x84, 0xff, 0x80, 0x00, 0x3f, 0xc3, 0xfc, 0x00, 0x15, 0xff, 0x85, 0x7f, 0xfc, 0x07, 0xff, 0x81, 0xff, 0xc0, 0x00, 0x61, 0x00, 0x86, 0x00, 0x0a, 0xff, 0xe9, 0xff, 0xfc, 0x07, 0xff, 0xa3, 0xff, 0xe0, 0x00, 0xc1, 0x00, 0x82, 0x00, 0x15, 0x7f, 0x94, 0x7f, 0xfc, 0x07, 0xff, 0xf7, 0xff, 0xf0, 0x00, 0x83, 0x00, 0xc1, 0x00, 0x0a, 0xbf, 0x49, 0xff, 0xcc, 0x07, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x87, 0x81, 0xe1, 0x00, 0x1a, 0x7f, 0xa4, 0x7f, 0xa4, 0x03, 0xe0, 0x7f, 0xff, 0xf0, 0x01, 0x9c, 0x7e, 0x18, 0x80, 0x05, 0x7f, 0x22, 0xff, 0x54, 0x03, 0xe0, 0x1b, 0xff, 0xf0, 0x01, 0x30, 0x3c, 0x0c, 0x80, 0x15, 0x3f, 0x94, 0xdf, 0x14, 0x01, 0xe0, 0x00, 0x7f, 0xf0, 0x01, 0xe0, 0x18, 0x07, 0x80, 0x0a, 0xaf, 0xa2, 0x77, 0x4c, 0x00, 0x62, 0x00, 0x3f, 0xf0, 0x02, 0x60, 0x18, 0x02, 0x60, 0x0d, 0x3e, 0x95, 0xfe, 0x54, 0x00, 0x63, 0x00, 0x1f, 0xf0, 0x04, 0x40, 0x18, 0x02, 0x20, 0x16, 0xbf, 0xc8, 0xef, 0x2c, 0x00, 0xc0, 0x0c, 0x1f, 0xe0, 0x0c, 0x40, 0x18, 0x02, 0x20, 0x0b, 0x5f, 0xa2, 0x7e, 0x9c, 0x00, 0xc0, 0x0c, 0x1f, 0xc0, 0x08, 0x40, 0x18, 0x02, 0x10, 0x16, 0x9f, 0x95, 0x7c, 0x7c, 0x01, 0xde, 0x00, 0x3f, 0x00, 0x08, 0x60, 0x3c, 0x02, 0x10, 0x0f, 0x4f, 0x48, 0xfd, 0x5c, 0x01, 0xff, 0x80, 0x3e, 0x00, 0x08, 0x60, 0x76, 0x06, 0x30, 0x17, 0xd7, 0x92, 0xfa, 0xbc, 0x01, 0xf3, 0xf8, 0x3e, 0x00, 0x04, 0xf8, 0x81, 0xbf, 0x20, 0x07, 0xd7, 0x49, 0x79, 0xfc, 0x01, 0xf2, 0x3c, 0x7c, 0x00, 0x06, 0xff, 0x00, 0xf9, 0x60, 0x15, 0xf7, 0x52, 0xf7, 0xfc, 0x03, 0xf8, 0x0f, 0xfc, 0x00, 0x03, 0x0f, 0x00, 0x70, 0xc0, 0x0b, 0xfe, 0xad, 0x37, 0xfc, 0x01, 0xfc, 0x0f, 0xfc, 0x00, 0x03, 0x06, 0x00, 0x60, 0xc0, 0x07, 0xfa, 0xff, 0x57, 0xfc, 0x01, 0xfe, 0x7f, 0xf8, 0x00, 0x01, 0x02, 0x00, 0x40, 0x80, 0x13, 0xfa, 0xff, 0xaf, 0xfc, 0x01, 0xff, 0xff, 0xf0, 0x00, 0x01, 0x03, 0x00, 0x00, 0x80, 0x0a, 0xfd, 0xfb, 0xdf, 0xfc, 0x00, 0xff, 0xff, 0xf0, 0x00, 0x01, 0x01, 0x00, 0x80, 0x80, 0x0b, 0xfd, 0xff, 0xff, 0xfc, 0x00, 0xcf, 0xff, 0xe0, 0x00, 0x00, 0x81, 0x81, 0x81, 0x00, 0x07, 0xff, 0xff, 0xdf, 0xfc, 0x00, 0x4f, 0xff, 0xc0, 0x00, 0x00, 0xc1, 0xff, 0x83, 0x00, 0x10, 0xfe, 0xff, 0xff, 0xfc, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x63, 0xc3, 0x86, 0x00, 0x0b, 0xff, 0x7f, 0x7f, 0xfc, 0x00, 0x01, 0x8f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x78, 0x00, 0x05, 0x7f, 0xde, 0xff, 0xfc, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x14, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x00, 0x03, 0xbf, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x15, 0x7f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x01, 0xff, 0xff, 0xfb, 0xfc
};

Wyświetl plik

@ -0,0 +1,12 @@
set(OUTPUT_NAME badger2040w_image)
add_executable(${OUTPUT_NAME} badger2040w_image.cpp)
target_link_libraries(${OUTPUT_NAME}
badger2040w
hardware_spi
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})

Wyświetl plik

@ -0,0 +1,51 @@
#include "pico/stdlib.h"
#include <stdio.h>
#include "common/pimoroni_common.hpp"
#include "badger2040w.hpp"
#include "badger2040w_image_demo_images.hpp"
using namespace pimoroni;
Badger2040W badger;
int main() {
badger.init();
stdio_init_all();
printf("\n\n=======\nbadger2040 starting up\n\n");
badger.uc8151->set_update_speed(2);
if(badger.pressed_to_wake(badger.A)) {
printf("> A pressed\n");
badger.image(shaun, Rect(0, 0, badger.DISPLAY_WIDTH, badger.DISPLAY_HEIGHT));
}
else if(badger.pressed_to_wake(badger.B)) {
printf("> B pressed\n");
badger.image(paul, Rect(0, 0, badger.DISPLAY_WIDTH, badger.DISPLAY_HEIGHT));
}
else if(badger.pressed_to_wake(badger.C)) {
printf("> C pressed\n");
badger.image(adam, Rect(0, 0, badger.DISPLAY_WIDTH, badger.DISPLAY_HEIGHT));
}
else {
printf("> No A/B/C key pressed\n");
badger.graphics->set_pen(15);
badger.graphics->clear();
badger.graphics->set_pen(0);
badger.graphics->set_font("sans");
badger.graphics->text("Press A, B, or C", Point(15, 65), badger.DISPLAY_WIDTH, 1.0f);
}
badger.update();
badger.halt();
}

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -0,0 +1,31 @@
set(WIFI_SSID "${WIFI_SSID}" CACHE INTERNAL "WiFi SSID")
set(WIFI_PASSWORD "${WIFI_PASSWORD}" CACHE INTERNAL "WiFi password")
if ("${WIFI_SSID}" STREQUAL "" OR "${WIFI_PASSWORD}" STREQUAL "")
message(WARNING "WIFI_SSID or WIFI_PASSWORD is not defined. Skipping rtc example.")
return()
endif()
set(OUTPUT_NAME badger2040w_rtc)
add_executable(${OUTPUT_NAME} badger2040w_rtc.cpp)
target_link_libraries(${OUTPUT_NAME}
badger2040w
hardware_spi
pico_cyw43_arch_lwip_threadsafe_background
)
target_include_directories(badger2040w_rtc PRIVATE
${CMAKE_CURRENT_LIST_DIR}
)
target_compile_definitions(badger2040w_rtc PRIVATE
WIFI_SSID=\"${WIFI_SSID}\"
WIFI_PASSWORD=\"${WIFI_PASSWORD}\"
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})

Wyświetl plik

@ -0,0 +1,238 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "badger2040w.hpp"
#include "common/pimoroni_common.hpp"
#include "lwip/dns.h"
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "pico/cyw43_arch.h"
#include "pico/stdlib.h"
#define NTP_SERVER "pool.ntp.org"
using namespace pimoroni;
Badger2040W badger;
typedef void (*ntp_callback_t)(datetime_t *datetime, void *arg);
static volatile bool ntp_time_set = false;
typedef struct NTP_T_ {
ip_addr_t ntp_server_address;
struct udp_pcb *ntp_pcb;
alarm_id_t ntp_failure_alarm;
ntp_callback_t ntp_callback;
void *ntp_callback_arg;
} NTP_T;
#define NTP_MSG_LEN 48
#define NTP_PORT 123
#define NTP_DELTA 2208988800 // seconds between 1 Jan 1900 and 1 Jan 1970
#define NTP_FAILURE_TIME (5 * 1000)
static void ntp_convert_epoch(const time_t *epoch, datetime_t *datetime) {
struct tm *timeinfo = localtime(epoch);
datetime->year = timeinfo->tm_year + 1900;
datetime->month = timeinfo->tm_mon + 1;
datetime->day = timeinfo->tm_mday;
datetime->dotw = timeinfo->tm_wday;
datetime->hour = timeinfo->tm_hour;
datetime->min = timeinfo->tm_min;
datetime->sec = timeinfo->tm_sec;
}
// Called with results of operation
static void ntp_result(NTP_T *state, int status, time_t *result) {
if (state->ntp_failure_alarm > 0) {
cancel_alarm(state->ntp_failure_alarm);
state->ntp_failure_alarm = 0;
}
if (status == 0 && result) {
datetime_t datetime;
ntp_convert_epoch(result, &datetime);
if (state->ntp_callback) {
state->ntp_callback(&datetime, state->ntp_callback_arg);
}
} else {
if (state->ntp_callback) {
state->ntp_callback(NULL, state->ntp_callback_arg);
}
}
free(state);
}
// Make an NTP request
static void ntp_request(NTP_T *state) {
cyw43_arch_lwip_begin();
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, NTP_MSG_LEN, PBUF_RAM);
uint8_t *req = (uint8_t *)p->payload;
memset(req, 0, NTP_MSG_LEN);
req[0] = 0x1b;
udp_sendto(state->ntp_pcb, p, &state->ntp_server_address, NTP_PORT);
pbuf_free(p);
cyw43_arch_lwip_end();
}
static int64_t ntp_failed_handler(alarm_id_t id, void *user_data) {
NTP_T *state = (NTP_T *)user_data;
printf("ntp request failed\n");
ntp_result(state, -1, NULL);
return 0;
}
// Call back with a DNS result
static void ntp_dns_found(const char *hostname, const ip_addr_t *ipaddr, void *arg) {
NTP_T *state = (NTP_T *)arg;
if (ipaddr) {
state->ntp_server_address = *ipaddr;
printf("ntp address %s\n", ipaddr_ntoa(ipaddr));
ntp_request(state);
} else {
printf("ntp dns request failed\n");
ntp_result(state, -1, NULL);
}
}
// NTP data received
static void ntp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) {
NTP_T *state = (NTP_T *)arg;
uint8_t mode = pbuf_get_at(p, 0) & 0x7;
uint8_t stratum = pbuf_get_at(p, 1);
// Check the result
if (ip_addr_cmp(addr, &state->ntp_server_address) && port == NTP_PORT && p->tot_len == NTP_MSG_LEN &&
mode == 0x4 && stratum != 0) {
uint8_t seconds_buf[4] = {0};
pbuf_copy_partial(p, seconds_buf, sizeof(seconds_buf), 40);
uint32_t seconds_since_1900 = seconds_buf[0] << 24 | seconds_buf[1] << 16 | seconds_buf[2] << 8 | seconds_buf[3];
uint32_t seconds_since_1970 = seconds_since_1900 - NTP_DELTA;
time_t epoch = seconds_since_1970;
ntp_result(state, 0, &epoch);
} else {
printf("invalid ntp response\n");
ntp_result(state, -1, NULL);
}
pbuf_free(p);
}
// Perform initialisation
static NTP_T *ntp_init(ntp_callback_t callback, void *arg) {
NTP_T *state = (NTP_T *)calloc(1, sizeof(NTP_T));
if (!state) {
printf("failed to allocate state\n");
return NULL;
}
state->ntp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
if (!state->ntp_pcb) {
printf("failed to create pcb\n");
free(state);
return NULL;
}
state->ntp_callback = callback;
state->ntp_callback_arg = arg;
udp_recv(state->ntp_pcb, ntp_recv, state);
return state;
}
void ntp_get_time(ntp_callback_t callback, void *arg) {
NTP_T *state = ntp_init(callback, arg);
if (!state)
return;
// Set alarm in case udp request is lost
state->ntp_failure_alarm = add_alarm_in_ms(NTP_FAILURE_TIME, ntp_failed_handler, state, true);
cyw43_arch_lwip_begin();
int err = dns_gethostbyname(NTP_SERVER, &state->ntp_server_address, ntp_dns_found, state);
cyw43_arch_lwip_end();
if (err == ERR_OK) { // dns record retrieved from cache
ntp_request(state);
} else if (err != ERR_INPROGRESS) { // ERR_INPROGRESS means the dns callback is pending
printf("dns request failed\n");
ntp_result(state, -1, NULL);
}
}
void ntp_callback(datetime_t *datetime, void *arg) {
if (datetime == NULL) {
ntp_time_set = true;
return;
}
printf("Got datetime from NTP\n");
badger.pcf85063a->set_datetime(datetime);
rtc_set_datetime(datetime);
// Flag that NTP callback has concluded
ntp_time_set = true;
}
void retrieve_time(bool from_ntp) {
ntp_time_set = false;
// Check if RTC has been initialised previously, if not get the internet time via NTP
if (from_ntp) {
printf("Retrieving time from NTP\n");
ntp_get_time(ntp_callback, NULL);
// Block until the callback sets datetime
while (!ntp_time_set) {
tight_loop_contents();
}
} else {
printf("Retrieving time from RTC\n");
// Retrieve stored time from external RTC
datetime_t datetime = badger.pcf85063a->get_datetime();
// Store time in internal RTC
rtc_set_datetime(&datetime);
}
}
int main() {
badger.init();
rtc_init();
stdio_init_all();
printf("\n\n=======\nbadger2040 starting up\n\n");
badger.graphics->set_font("bitmap8");
badger.graphics->set_thickness(2);
cyw43_arch_init();
cyw43_arch_enable_sta_mode();
if (cyw43_arch_wifi_connect_blocking(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK)) {
printf("Failed to connect to wifi, halting\n");
badger.halt();
}
// External RTC has 1 free byte, we can use this to determine whether the time has been set previously
if (!badger.pcf85063a->get_byte()) {
retrieve_time(true);
// Set the external RTC free byte so we can later determine if it has been initalized
badger.pcf85063a->set_byte(1);
} else {
retrieve_time(false);
}
char time_str[32];
datetime_t datetime;
while (true) {
badger.graphics->set_pen(15);
badger.graphics->clear();
badger.graphics->set_pen(0);
rtc_get_datetime(&datetime);
sprintf(time_str, "%02d/%02d/%02d %02d:%02d\n", datetime.day, datetime.month, datetime.year, datetime.hour, datetime.min);
int32_t time_x_centered = (badger.DISPLAY_WIDTH - badger.graphics->measure_text(time_str, 2.0f)) / 2;
badger.graphics->text("Time (GMT+0)", Point(5, 10), badger.DISPLAY_WIDTH, 2.0f);
badger.graphics->text(time_str, Point(time_x_centered, badger.DISPLAY_HEIGHT / 2 - 8), badger.DISPLAY_WIDTH, 2.0f);
badger.update();
// Wait for next minute before redrawing
do {
rtc_get_datetime(&datetime);
} while(datetime.sec != 0);
}
}

Wyświetl plik

@ -0,0 +1,12 @@
set(OUTPUT_NAME badger2040w_sleep)
add_executable(${OUTPUT_NAME} badger2040w_sleep.cpp)
target_link_libraries(${OUTPUT_NAME}
badger2040w
hardware_spi
)
# enable usb output
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
pico_add_extra_outputs(${OUTPUT_NAME})

Wyświetl plik

@ -0,0 +1,68 @@
#include "pico/stdlib.h"
#include <stdio.h>
#include <cstring>
#include <string>
#include <algorithm>
#include "pico/time.h"
#include "pico/platform.h"
#include "common/pimoroni_common.hpp"
#include "badger2040w.hpp"
using namespace pimoroni;
// this simple example tells you which button was used to wake up
// Badger2040W and then immediately halts again on another button press
Badger2040W badger;
int main() {
badger.init();
badger.uc8151->set_update_speed(2);
// find which button was used to wake up
std::string button = "";
std::string message = "started up.";
if(badger.pressed_to_wake(badger.A)) { button += "A"; }
if(badger.pressed_to_wake(badger.B)) { button += "B"; }
if(badger.pressed_to_wake(badger.C)) { button += "C"; }
if(badger.pressed_to_wake(badger.D)) { button += "D"; }
if(badger.pressed_to_wake(badger.E)) { button += "E"; }
if(button != "") {
message = "woken up by button " + button + ".";
}
badger.graphics->set_thickness(2);
badger.graphics->set_pen(15);
badger.graphics->clear();
badger.graphics->set_pen(0);
badger.graphics->text(message, Point(10, 20), 286, 2);
badger.graphics->text("(press any button to go to sleep.)", Point(10, 100), 200, 2);
badger.update();
badger.led(255);
badger.wait_for_press();
badger.graphics->set_pen(15);
badger.graphics->clear();
badger.graphics->set_pen(0);
badger.graphics->text("going back to sleep...", Point(10, 20), 200, 3);
badger.graphics->text("z", Point(220, 50), 200, 3);
badger.graphics->text("z", Point(235, 30), 200, 4);
badger.graphics->text("z", Point(255, 5), 200, 5);
badger.graphics->text("(press any button to wake up.)", Point(10, 100), 200, 2);
badger.update();
while (badger.uc8151->is_busy()) {
sleep_ms(10);
}
badger.led(0);
badger.halt();
// proof we halted, the LED will not turn on
badger.led(255);
}

Wyświetl plik

@ -0,0 +1,136 @@
#!/usr/bin/env python3
"""
Converts images into a format suitable for display on Badger 2040.
Optionally resizes images to 296x128 to fit the display.
Crunches images down to dithered, 1bit colour depth.
Outputs either in raw binary format or as a .py file for embedding into MicroPython.
Output to py functionality is borrwed from data_to_py.py, Copyright (c) 2016 Peter Hinch
"""
import io
import argparse
from PIL import Image, ImageEnhance
from pathlib import Path
PY_HEADER = """# Code generated by convert.py.
"""
PY_FOOTER = """_mvdata = memoryview(_data)
def data():
return _mvdata
"""
parser = argparse.ArgumentParser(description='Converts images into the format used by Badger2040.')
parser.add_argument('file', nargs="+", help='input files to convert')
parser.add_argument('--out_dir', type=Path, default=None, help='output directory')
parser.add_argument('--binary', action="store_true", help='output binary file for MicroPython')
parser.add_argument('--py', action="store_true", help='output .py file for MicroPython embedding')
parser.add_argument('--resize', action="store_true", help='force images to 296x128 pixels')
options = parser.parse_args()
class ByteWriter(object):
bytes_per_line = 16
def __init__(self, stream, varname):
self.stream = stream
self.stream.write('{} =\\\n'.format(varname))
self.bytecount = 0 # For line breaks
def _eol(self):
self.stream.write("'\\\n")
def _eot(self):
self.stream.write("'\n")
def _bol(self):
self.stream.write("b'")
# Output a single byte
def obyte(self, data):
if not self.bytecount:
self._bol()
self.stream.write('\\x{:02x}'.format(data))
self.bytecount += 1
self.bytecount %= self.bytes_per_line
if not self.bytecount:
self._eol()
# Output from a sequence
def odata(self, bytelist):
for byt in bytelist:
self.obyte(byt)
# ensure a correct final line
def eot(self): # User force EOL if one hasn't occurred
if self.bytecount:
self._eot()
self.stream.write('\n')
def convert_image(img):
if options.resize:
img = img.resize((296, 128)) # resize
try:
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(2.0)
except ValueError:
pass
img = img.convert("1") # convert to black and white
return img
def write_stream(header, footer, ip_stream, op_stream):
op_stream.write(header)
op_stream.write('\n')
data = ip_stream.read()
bw_data = ByteWriter(op_stream, '_data')
bw_data.odata(data)
bw_data.eot()
op_stream.write(footer)
# create map of images based on input filenames
for input_filename in options.file:
with Image.open(input_filename) as img:
img = convert_image(img)
image_name = Path(input_filename).stem
w, h = img.size
output_data = [~b & 0xff for b in list(img.tobytes())]
if options.binary:
if options.out_dir is not None:
output_filename = (options.out_dir / image_name).with_suffix(".bin")
else:
output_filename = Path(input_filename).with_suffix(".bin")
print(f"Saving to {output_filename}, {w}x{h}")
with open(output_filename, "wb") as out:
out.write(bytearray(output_data))
elif options.py:
if options.out_dir is not None:
output_filename = (options.out_dir / image_name).with_suffix(".py")
else:
output_filename = Path(input_filename).with_suffix(".py")
print(f"Saving to {output_filename}, {w}x{h}")
with open(output_filename, "w") as out:
write_stream(PY_HEADER, PY_FOOTER, io.BytesIO(bytes(output_data)), out)
else:
image_code = '''\
static const uint8_t {image_name}[{count}] = {{
{byte_data}
}};
'''.format(image_name=image_name, count=len(output_data), byte_data=", ".join(str(b) for b in output_data))
print(image_code)

Wyświetl plik

@ -0,0 +1,154 @@
#! /usr/bin/python3
# -*- coding: utf-8 -*-
# The MIT License (MIT)
#
# Copyright (c) 2016 Peter Hinch
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import argparse
import sys
import os
# UTILITIES FOR WRITING PYTHON SOURCECODE TO A FILE
# ByteWriter takes as input a variable name and data values and writes
# Python source to an output stream of the form
# my_variable = b'\x01\x02\x03\x04\x05\x06\x07\x08'\
# Lines are broken with \ for readability.
class ByteWriter(object):
bytes_per_line = 16
def __init__(self, stream, varname):
self.stream = stream
self.stream.write('{} =\\\n'.format(varname))
self.bytecount = 0 # For line breaks
def _eol(self):
self.stream.write("'\\\n")
def _eot(self):
self.stream.write("'\n")
def _bol(self):
self.stream.write("b'")
# Output a single byte
def obyte(self, data):
if not self.bytecount:
self._bol()
self.stream.write('\\x{:02x}'.format(data))
self.bytecount += 1
self.bytecount %= self.bytes_per_line
if not self.bytecount:
self._eol()
# Output from a sequence
def odata(self, bytelist):
for byt in bytelist:
self.obyte(byt)
# ensure a correct final line
def eot(self): # User force EOL if one hasn't occurred
if self.bytecount:
self._eot()
self.stream.write('\n')
# PYTHON FILE WRITING
STR01 = """# Code generated by data_to_py.py.
version = '0.1'
"""
STR02 = """_mvdata = memoryview(_data)
def data():
return _mvdata
"""
def write_func(stream, name, arg):
stream.write('def {}():\n return {}\n\n'.format(name, arg))
def write_data(op_path, ip_path):
try:
with open(ip_path, 'rb') as ip_stream:
try:
with open(op_path, 'w') as op_stream:
write_stream(ip_stream, op_stream)
except OSError:
print("Can't open", op_path, 'for writing')
return False
except OSError:
print("Can't open", ip_path)
return False
return True
def write_stream(ip_stream, op_stream):
op_stream.write(STR01)
op_stream.write('\n')
data = ip_stream.read()
bw_data = ByteWriter(op_stream, '_data')
bw_data.odata(data)
bw_data.eot()
op_stream.write(STR02)
# PARSE COMMAND LINE ARGUMENTS
def quit(msg):
print(msg)
sys.exit(1)
DESC = """data_to_py.py
Utility to convert an arbitrary binary file to Python source.
Sample usage:
data_to_py.py image.jpg image.py
"""
if __name__ == "__main__":
parser = argparse.ArgumentParser(__file__, description=DESC,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('infile', type=str, help='Input file path')
parser.add_argument('outfile', type=str,
help='Path and name of output file. Must have .py extension.')
args = parser.parse_args()
if not os.path.isfile(args.infile):
quit("Data filename does not exist")
if not os.path.splitext(args.outfile)[1].upper() == '.PY':
quit('Output filename must have a .py extension.')
print('Writing Python file.')
if not write_data(args.outfile, args.infile):
sys.exit(1)
print(args.outfile, 'written successfully.')

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 44 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 8.1 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 49 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 46 KiB

Wyświetl plik

@ -0,0 +1,89 @@
#ifndef _LWIPOPTS_EXAMPLE_COMMONH_H
#define _LWIPOPTS_EXAMPLE_COMMONH_H
// Common settings used in most of the pico_w examples
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details)
// allow override in some examples
#ifndef NO_SYS
#define NO_SYS 1
#endif
// allow override in some examples
#ifndef LWIP_SOCKET
#define LWIP_SOCKET 0
#endif
#if PICO_CYW43_ARCH_POLL
#define MEM_LIBC_MALLOC 1
#else
// MEM_LIBC_MALLOC is incompatible with non polling versions
#define MEM_LIBC_MALLOC 0
#endif
#define MEM_ALIGNMENT 4
#define MEM_SIZE 1600
#define MEMP_NUM_TCP_SEG 16
#define MEMP_NUM_ARP_QUEUE 30
#define PBUF_POOL_SIZE 16
#define LWIP_ARP 1
#define LWIP_ETHERNET 1
#define LWIP_ICMP 1
#define LWIP_RAW 1
#define TCP_WND (4 * TCP_MSS)
#define TCP_MSS 536
#define TCP_SND_BUF (2 * TCP_MSS)
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_LINK_CALLBACK 1
#define LWIP_NETIF_HOSTNAME 1
#define LWIP_NETCONN 0
#define MEM_STATS 1
#define SYS_STATS 1
#define MEMP_STATS 1
#define LINK_STATS 1
// #define ETH_PAD_SIZE 2
#define LWIP_CHKSUM_ALGORITHM 3
#define LWIP_DHCP 1
#define LWIP_IPV4 1
#define LWIP_TCP 1
#define LWIP_UDP 1
#define LWIP_DNS 1
#define LWIP_TCP_KEEPALIVE 1
#define LWIP_NETIF_TX_SINGLE_PBUF 1
#define DHCP_DOES_ARP_CHECK 0
#define LWIP_DHCP_DOES_ACD_CHECK 0
#ifndef NDEBUG
#define LWIP_DEBUG 1
#define LWIP_STATS 1
#define LWIP_STATS_DISPLAY 1
#endif
#define ETHARP_DEBUG LWIP_DBG_OFF
#define NETIF_DEBUG LWIP_DBG_OFF
#define PBUF_DEBUG LWIP_DBG_OFF
#define API_LIB_DEBUG LWIP_DBG_OFF
#define API_MSG_DEBUG LWIP_DBG_OFF
#define SOCKETS_DEBUG LWIP_DBG_OFF
#define ICMP_DEBUG LWIP_DBG_OFF
#define INET_DEBUG LWIP_DBG_OFF
#define IP_DEBUG LWIP_DBG_OFF
#define IP_REASS_DEBUG LWIP_DBG_OFF
#define RAW_DEBUG LWIP_DBG_OFF
#define MEM_DEBUG LWIP_DBG_OFF
#define MEMP_DEBUG LWIP_DBG_OFF
#define SYS_DEBUG LWIP_DBG_OFF
#define TCP_DEBUG LWIP_DBG_OFF
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
#define TCP_RTO_DEBUG LWIP_DBG_OFF
#define TCP_CWND_DEBUG LWIP_DBG_OFF
#define TCP_WND_DEBUG LWIP_DBG_OFF
#define TCP_FR_DEBUG LWIP_DBG_OFF
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
#define TCP_RST_DEBUG LWIP_DBG_OFF
#define UDP_DEBUG LWIP_DBG_OFF
#define TCPIP_DEBUG LWIP_DBG_OFF
#define PPP_DEBUG LWIP_DBG_OFF
#define SLIP_DEBUG LWIP_DBG_OFF
#define DHCP_DEBUG LWIP_DBG_OFF
#endif /* __LWIPOPTS_H__ */

Wyświetl plik

@ -30,6 +30,7 @@ add_subdirectory(automation2040w)
add_subdirectory(plasma_stick)
add_subdirectory(plasma2040)
add_subdirectory(badger2040)
add_subdirectory(badger2040w)
add_subdirectory(tufty2040)
add_subdirectory(servo2040)
add_subdirectory(motor2040)

Wyświetl plik

@ -0,0 +1 @@
include(badger2040w.cmake)

Wyświetl plik

@ -0,0 +1,32 @@
if(NOT TARGET uc8151)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/uc8151/uc8151.cmake)
endif()
if(NOT TARGET pico_graphics)
include(${CMAKE_CURRENT_LIST_DIR}/../../libraries/pico_graphics/pico_graphics.cmake)
endif()
if(NOT TARGET pcf85063a)
include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/pcf85063a/pcf85063a.cmake)
endif()
if(NOT TARGET pimoroni_i2c)
include(${CMAKE_CURRENT_LIST_DIR}/../../common/pimoroni_i2c.cmake)
endif()
set(LIB_NAME badger2040w)
add_library(${LIB_NAME} INTERFACE)
target_sources(${LIB_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/${LIB_NAME}.cpp
)
target_include_directories(${LIB_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
# Pull in pico libraries that we need
target_link_libraries(${LIB_NAME} INTERFACE
uc8151
pcf85063a
pico_graphics
pico_stdlib
hardware_pwm
pimoroni_i2c)

Wyświetl plik

@ -0,0 +1,152 @@
#include <string.h>
#include <math.h>
#include "hardware/pwm.h"
#include "hardware/watchdog.h"
#include "pimoroni_i2c.hpp"
#include "badger2040w.hpp"
namespace pimoroni {
void Badger2040W::init() {
gpio_set_function(ENABLE_3V3, GPIO_FUNC_SIO);
gpio_set_dir(ENABLE_3V3, GPIO_OUT);
gpio_put(ENABLE_3V3, 1);
gpio_set_function(A, GPIO_FUNC_SIO);
gpio_set_dir(A, GPIO_IN);
gpio_set_pulls(A, false, true);
gpio_set_function(B, GPIO_FUNC_SIO);
gpio_set_dir(B, GPIO_IN);
gpio_set_pulls(B, false, true);
gpio_set_function(C, GPIO_FUNC_SIO);
gpio_set_dir(C, GPIO_IN);
gpio_set_pulls(C, false, true);
gpio_set_function(D, GPIO_FUNC_SIO);
gpio_set_dir(D, GPIO_IN);
gpio_set_pulls(D, false, true);
gpio_set_function(E, GPIO_FUNC_SIO);
gpio_set_dir(E, GPIO_IN);
gpio_set_pulls(E, false, true);
// PCF85063a handles the initialisation of the RTC GPIO pin
pcf85063a = std::make_unique<PCF85063A>(new I2C(I2C_BG_SDA, I2C_BG_SCL), (uint)RTC);
// read initial button states
uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E) | (1UL << RTC);
_wake_button_states |= gpio_get_all() & mask;
// led control pin
pwm_config cfg = pwm_get_default_config();
pwm_set_wrap(pwm_gpio_to_slice_num(LED), 65535);
pwm_init(pwm_gpio_to_slice_num(LED), &cfg, true);
gpio_set_function(LED, GPIO_FUNC_PWM);
led(0);
// Initialise display driver and pico graphics library
uc8151 = std::make_unique<UC8151>(DISPLAY_WIDTH, DISPLAY_HEIGHT, ROTATE_0);
graphics = std::make_unique<PicoGraphics_Pen1BitY>(DISPLAY_WIDTH, DISPLAY_HEIGHT, nullptr);
}
void Badger2040W::halt() {
gpio_put(ENABLE_3V3, 0);
// If running on USB we will not actually power down, so emulate the behaviour
// of battery powered badge by listening for a button press and then resetting
// Note: Don't use wait_for_press as that waits for the button to be release and
// we want the reboot to complete before the button is released.
update_button_states();
while(_button_states == 0) {
update_button_states();
}
watchdog_reboot(0, 0, 0);
}
void Badger2040W::update_button_states() {
uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E) | (1UL << RTC);
_button_states = gpio_get_all() & mask;
}
uint32_t Badger2040W::button_states() {
return _button_states;
}
void Badger2040W::imageRow(const uint8_t *data, Rect rect) {
for(auto x = 0; x < rect.w; x++) {
// work out byte offset in source data
uint32_t o = (x >> 3);
// extract bitmask for this pixel
uint32_t bm = 0b10000000 >> (x & 0b111);
// set pixel color
graphics->set_pen(data[o] & bm ? 0 : 15);
// draw the pixel
graphics->set_pixel(Point(x + rect.x, rect.y));
}
}
// Display a portion of an image (icon sheet) at rect
void Badger2040W::icon(const uint8_t *data, int index, int sheet_width, Rect rect) {
for(auto y = 0; y < rect.h; y++) {
const uint8_t *scanline = data + ((y * sheet_width) >> 3) + ((rect.w * index) >> 3);
imageRow(scanline, Rect(rect.x, y + rect.y, rect.w, 0));
}
}
// Display an image at rect
void Badger2040W::image(const uint8_t *data, Rect rect) {
for(auto y = 0; y < rect.h; y++) {
const uint8_t *scanline = data + ((y * rect.w) >> 3);
imageRow(scanline, Rect(rect.x, y + rect.y, rect.w, 0));
}
}
// Display an image that covers the entire screen
void Badger2040W::image(const uint8_t *data) {
image(data, Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
}
void Badger2040W::partial_update(Rect region) {
uc8151->partial_update(graphics.get(), region);
}
void Badger2040W::update() {
uc8151->update(graphics.get());
}
void Badger2040W::led(uint8_t brightness) {
// set the led brightness from 1 to 256 with gamma correction
float gamma = 2.8;
uint16_t v = (uint16_t)(pow((float)(brightness) / 256.0f, gamma) * 65535.0f + 0.5f);
pwm_set_gpio_level(LED, v);
}
bool Badger2040W::pressed(uint8_t button) {
return (_button_states & (1UL << button)) != 0;
}
bool Badger2040W::pressed_to_wake(uint8_t button) {
return (_wake_button_states & (1UL << button)) != 0;
}
void Badger2040W::wait_for_press() {
update_button_states();
while(_button_states == 0) {
update_button_states();
tight_loop_contents();
}
uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E) | (1UL << RTC);
while(gpio_get_all() & mask) {
tight_loop_contents();
}
}
}

Wyświetl plik

@ -0,0 +1,70 @@
#pragma once
#include <string>
#include <memory>
#include "drivers/uc8151/uc8151.hpp"
#include "drivers/pcf85063a/pcf85063a.hpp"
#include "libraries/pico_graphics/pico_graphics.hpp"
namespace pimoroni {
class Badger2040W {
protected:
uint32_t _button_states = 0;
uint32_t _wake_button_states = 0;
private:
void imageRow(const uint8_t *data, Rect rect);
public:
std::unique_ptr<UC8151> uc8151;
std::unique_ptr<PicoGraphics_Pen1BitY> graphics;
std::unique_ptr<PCF85063A> pcf85063a;
uint DISPLAY_WIDTH = 296;
uint DISPLAY_HEIGHT = 128;
Badger2040W(){};
void init();
void update();
void partial_update(Rect region);
void halt();
// state
void led(uint8_t brightness);
// inputs (buttons: A, B, C, D, E, USER)
bool pressed(uint8_t button);
bool pressed_to_wake(uint8_t button);
void wait_for_press();
void update_button_states();
uint32_t button_states();
void icon(const uint8_t *data, int index, int sheet_width, Rect rect);
void image(const uint8_t *data, Rect rect);
void image(const uint8_t *data);
public:
enum pin {
RTC = 8,
A = 12,
B = 13,
C = 14,
D = 15,
E = 11,
UP = 15, // alias for D
DOWN = 11, // alias for E
CS = 17,
CLK = 18,
MOSI = 19,
DC = 20,
RESET = 21,
BUSY = 26,
VBUS_DETECT = 24,
LED = 22,
BATTERY = 29,
ENABLE_3V3 = 10
};
};
}