#include "cardslot.h" #include CardSlot::CardSlot(lib::Flash& flash, uint16_t card_index) : card_index(card_index) { load_data(flash); } uint16_t CardSlot::get_image_start_page_index() const { return card_index * TOTAL_PAGE_COUNT + 1; } void CardSlot::mark_unused(lib::Flash& flash) { flash.read_page(card_index * TOTAL_PAGE_COUNT); flash.page()[0] &= 0xFE; flash.write_page(card_index * TOTAL_PAGE_COUNT); } void CardSlot::set_name(const uint8_t* name, uint8_t name_length) { if (name_length > 32) { name_length = 32; } memcpy(this->name, name, name_length); status.name_length = name_length; } void CardSlot::save_data(lib::Flash& flash) { // if we're saving data, the slot is in use status.in_use = true; uint32_t raw_status = (status.in_use << 0) | (status.name_length << 1) | (status.times_erased << (NAME_BITS + 1)); auto& page = flash.page(); page[0] = (raw_status >> 0) & 0xFF; page[1] = (raw_status >> 8) & 0xFF; page[2] = (raw_status >> 16) & 0xFF; page[3] = (raw_status >> 24) & 0xFF; memcpy(page + 4, name, status.name_length); flash.write_page(card_index * TOTAL_PAGE_COUNT); } void CardSlot::erase(lib::Flash& flash) { // 16 pages per sector, one command erases them all for (int i = 0; i < TOTAL_PAGE_COUNT; i += 16) { flash.erase_sector(card_index * TOTAL_PAGE_COUNT + i); } } bool CardSlot::is_used() const { return status.in_use; } uint32_t CardSlot::times_erased() const { return status.times_erased; } const uint8_t* CardSlot::get_name() const { return name; } uint8_t CardSlot::get_name_length() const { return status.name_length; } bool CardSlot::operator<=(const CardSlot& other) const { return status.times_erased <= other.status.times_erased; } bool CardSlot::operator>=(const CardSlot& other) const { return status.times_erased >= other.status.times_erased; } void CardSlot::each_pixel(lib::Flash& flash, void (*fn)(void*, uint8_t), void* userdata) { for (int page_index = 0; page_index < IMAGE_PAGE_COUNT; page_index++) { flash.read_page(get_image_start_page_index() + page_index); const auto& page = flash.page(); for (uint8_t value : page) { fn(userdata, value); } } } void CardSlot::load_data(lib::Flash& flash) { flash.read_page(card_index * TOTAL_PAGE_COUNT); const auto& page = flash.page(); const uint32_t raw_status = page[0] | (page[1] << 8) | (page[2] << 16) | (page[3] << 24); status.in_use = raw_status & 0x01; status.name_length = raw_status & 0x3E; status.times_erased = raw_status & 0xFFFFFFC0; memcpy(name, page + 4, status.name_length); } int32_t CardSlot::get_unused(lib::Flash& flash) { int min_unused = INT32_MAX; int min_unused_index = -1; for (int i = 0; i < MAX_CARDS; i++) { CardSlot c(flash, i); if (!c.is_used() && c.times_erased() < min_unused) { min_unused = c.times_erased(); min_unused_index = i; } } return min_unused_index; }