223 lines
5.2 KiB
C++
223 lines
5.2 KiB
C++
#include "cardslot.h"
|
|
#include "display.h"
|
|
#include "flash.h"
|
|
#include "icons.h"
|
|
#include "pixelstream.h"
|
|
|
|
#include <pico/binary_info.h>
|
|
#include <pico/stdlib.h>
|
|
#include <tusb.h>
|
|
|
|
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<PixelStream*>(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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|