#ifndef STA_UTILS_LOGGER_TPP #define STA_UTILS_LOGGER_TPP #include #include namespace sta { template Logger::Logger(W25Qxx * flash, uint32_t startSec, uint32_t endSec) : flash_{flash}, start_{startSec}, end_{endSec}, address_{start_ * W25QXX_SECTOR_SIZE}, buffer_{0x00, }, ptr_ {0} { STA_ASSERT(flash != nullptr); STA_ASSERT(endAddr > startAddr); } template void Logger::write(T data) { uint8_t * bytes = (uint8_t*)(&data); uint8_t length = sizeof(data); // Bytes remaining until the page is full. uint8_t remaining = W25QXX_PAGE_SIZE - ptr_; // If the written data exceeds the remaining bytes in the page. if (ptr_ + length >= W25QXX_PAGE_SIZE) { std::memcpy(buffer_ + ptr_, bytes, remaining); flash_->pageProgram(address_, buffer_, W25QXX_PAGE_SIZE); bytes += remaining; length -= remaining; ptr_ = 0; address_ += W25QXX_PAGE_SIZE; // If a new sector was started, erase the new sector. if (address_ % W25QXX_SECTOR_SIZE == 0) { // If the size of the logger segment was exceeded, restart at the first sector. if (address_ / W25QXX_SECTOR_SIZE == end_) { address_ = start_ * W25QXX_SECTOR_SIZE; } flash_->sectorErase(address_); } } std::memcpy(buffer_ + ptr_, bytes, length); } template void Logger::clear() { address_ = start_ * W25QXX_SECTOR_SIZE; ptr_ = 0; for (uint32_t i = 0; i < end_ - start_; i++) { flash_->sectorErase((start_ + i) * W25QXX_SECTOR_SIZE); } } template size_t Logger::occupied() { return (address_ - start_ * W25QXX_SECTOR_SIZE) / sizeof(T); } template size_t Logger::remaining() { return (end_ * W25QXX_SECTOR_SIZE - address_) / sizeof(T); } template size_t Logger::length() { return (end_ - start_) * W25QXX_SECTOR_SIZE / sizeof(T); } template const T& Logger::operator[](std::size_t idx) { uint32_t address = start_ * W25QXX_SECTOR_SIZE + idx * sizeof(T); uint8_t buffer[sizeof(T)]; flash_->readData(address, buffer, sizeof(T)); return *((T*)buffer); } } // namespace sta #endif // STA_UTILS_LOGGER_TPP