#include "cardslot.h" #include "display.h" #include "flash.h" #include "menu.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, 8)); bi_decl(bi_ptr_int32(0x1111, 2, BUTTON_MIDDLE, 0)); bi_decl(bi_ptr_int32(0x1111, 2, BUTTON_RIGHT, 20)); 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_CMC, GETTING_COLORS, GETTING_NAME_LENGTH, GETTING_NAME, GETTING_IMAGE }; struct { struct { uint8_t buffer[32]; uint8_t size; uint8_t written; } name; uint8_t cmc; uint8_t colors; 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(); absolute_time_t previous_time = last_press; menus::push_menu(display); while (true) { absolute_time_t current = get_absolute_time(); float dt = absolute_time_diff_us(previous_time, current) / 1000000.0f; if (!gpio_get(BUTTON_LEFT) && absolute_time_diff_us(last_press, current) > 1000 * 1000) { menus::get_current_menu()->onLeftPressed(); last_press = current; } if (!gpio_get(BUTTON_MIDDLE) && absolute_time_diff_us(last_press, current) > 1000 * 1000) { menus::get_current_menu()->onMenuPressed(); last_press = current; } if (!gpio_get(BUTTON_RIGHT) && absolute_time_diff_us(last_press, current) > 1000 * 1000) { menus::get_current_menu()->onRightPressed(); last_press = current; } tud_task(); menus::get_current_menu()->onTick(dt); previous_time = current; } } 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_CMC; rx.card_index = CardSlot::get_unused(flash); } else if (rx.state == RX::GETTING_CMC) { rx.state = RX::GETTING_COLORS; rx.cmc = buffer[read] > 20 ? 20 : buffer[read]; read += 1; } else if (rx.state == RX::GETTING_COLORS) { rx.state = RX::GETTING_NAME_LENGTH; rx.colors = buffer[read] & 0b11111; read += 1; } else if (rx.state == RX::GETTING_NAME_LENGTH) { rx.state = RX::GETTING_NAME; rx.name.size = buffer[read] > 32 ? 32 : buffer[read]; 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.set_cmc(rx.cmc); slot.set_colors(rx.colors); slot.save_data(flash); } } } else if (rx.state == RX::GETTING_IMAGE) { 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; } } } } }