126 lines
3.0 KiB
C++
126 lines
3.0 KiB
C++
#include "cardslot.h"
|
|
|
|
#include <cstring>
|
|
|
|
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;
|
|
}
|