#include "cardslot.h" #include "display.h" #include "flash.h" #include "icons.h" #include "pixelstream.h" #include #include #include using namespace lib; namespace { bi_decl(bi_program_feature_group(0x1111, 0, "Display Pinout")); bi_decl(bi_ptr_int32(0x1111, 0, DISPLAY_SCK, 2)); bi_decl(bi_ptr_int32(0x1111, 0, DISPLAY_TX, 3)); bi_decl(bi_ptr_int32(0x1111, 0, DISPLAY_CS, 5)); bi_decl(bi_ptr_int32(0x1111, 0, DISPLAY_DC, 6)); bi_decl(bi_program_feature_group(0x1111, 1, "Flash Pinout")); bi_decl(bi_ptr_int32(0x1111, 1, FLASH_SCK, 26)); bi_decl(bi_ptr_int32(0x1111, 1, FLASH_TX, 27)); bi_decl(bi_ptr_int32(0x1111, 1, FLASH_RX, 28)); bi_decl(bi_ptr_int32(0x1111, 1, FLASH_CS, 29)); bi_decl(bi_program_feature_group(0x1111, 2, "Buttons")); bi_decl(bi_ptr_int32(0x1111, 2, BUTTON_LEFT, 20)); bi_decl(bi_ptr_int32(0x1111, 2, BUTTON_MIDDLE, 0)); bi_decl(bi_ptr_int32(0x1111, 2, BUTTON_RIGHT, 8)); Display display(DISPLAY_SCK, DISPLAY_TX, DISPLAY_CS, DISPLAY_DC, 120000000); Flash flash(FLASH_SCK, FLASH_TX, FLASH_RX, FLASH_CS, 70000000); enum class RX { WAITING, GETTING_NAME, GETTING_IMAGE }; struct { struct { uint8_t buffer[32]; uint8_t size; uint8_t written; } name; struct { size_t written = 0; uint16_t page_index = 0; } image; RX state = RX::WAITING; int32_t card_index = 0; } rx; } int main() { gpio_set_function(BUTTON_LEFT, GPIO_FUNC_SIO); gpio_set_function(BUTTON_MIDDLE, GPIO_FUNC_SIO); gpio_set_function(BUTTON_RIGHT, GPIO_FUNC_SIO); gpio_set_dir(BUTTON_LEFT, GPIO_IN); gpio_set_dir(BUTTON_MIDDLE, GPIO_IN); gpio_set_dir(BUTTON_RIGHT, GPIO_IN); gpio_pull_up(BUTTON_LEFT); gpio_pull_up(BUTTON_MIDDLE); gpio_pull_up(BUTTON_RIGHT); tusb_rhport_init_t dev_init = { .role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO }; tud_init(0); uint16_t card_index = 0; absolute_time_t last_press = get_absolute_time(); const auto& pixel_fn = [](void* pixels, uint8_t data) { static_cast(pixels)->write(data); }; { auto pixels = display.pixels(); CardSlot(flash, 0).each_pixel(flash, pixel_fn, &pixels); } while (true) { absolute_time_t current = get_absolute_time(); if (!gpio_get(BUTTON_LEFT) && absolute_time_diff_us(last_press, current) > 1000 * 10) { do { card_index -= 1; if (card_index >= CardSlot::MAX_CARDS) { card_index = CardSlot::MAX_CARDS - 1; } } while (!CardSlot(flash, card_index).is_used()); auto pixels = display.pixels(); CardSlot(flash, card_index).each_pixel(flash, pixel_fn, &pixels); last_press = current; } if (!gpio_get(BUTTON_RIGHT) && absolute_time_diff_us(last_press, current) > 1000 * 10) { do { card_index += 1; if (card_index >= CardSlot::MAX_CARDS) { card_index = 0; } } while (!CardSlot(flash, card_index).is_used()); auto pixels = display.pixels(); CardSlot(flash, card_index).each_pixel(flash, pixel_fn, &pixels); last_press = current; } tud_task(); } } void tud_vendor_rx_cb(uint8_t itf, const uint8_t* buffer, uint16_t bufsize) { for (size_t read = 0; read < bufsize;) { if (rx.state == RX::WAITING) { // special command to mark all as unused if (buffer[0] == 0x42) { for (int i = 0; i < CardSlot::MAX_CARDS; i++) { CardSlot slot(flash, i); slot.mark_unused(flash); } return; } rx.state = RX::GETTING_NAME; rx.card_index = CardSlot::get_unused(flash); rx.name.size = buffer[0] > 32 ? 32 : buffer[0]; rx.name.written = 0; read += 1; } else if (rx.state == RX::GETTING_NAME) { size_t copy_size = bufsize - read < rx.name.size - rx.name.written ? bufsize - read : rx.name.size - rx.name.written; memcpy(rx.name.buffer + rx.name.written, buffer + read, copy_size); read += copy_size; rx.name.written += copy_size; if (rx.name.written == rx.name.size) { rx.state = RX::GETTING_IMAGE; rx.image.written = 0; rx.image.page_index = CardSlot(flash, rx.card_index).get_image_start_page_index(); if (rx.card_index >= 0) { CardSlot slot(flash, rx.card_index); slot.erase(flash); slot.set_name(rx.name.buffer, rx.name.size); slot.save_data(flash); } } } else { size_t copy_size = bufsize - read < Flash::Page::SIZE - rx.image.written ? bufsize - read : Flash::Page::SIZE - rx.image.written; memcpy(flash.page() + rx.image.written, buffer + read, copy_size); read += copy_size; rx.image.written += copy_size; if (rx.image.written == 256) { if (rx.card_index >= 0) { flash.write_page(rx.image.page_index); } rx.image.page_index += 1; rx.image.written = 0; if (rx.image.page_index - CardSlot(flash, rx.card_index).get_image_start_page_index() == CardSlot::IMAGE_PAGE_COUNT) { rx.state = RX::WAITING; } } } } }