diff --git a/eeprom.hpp b/eeprom.hpp index 547470f..64f4e85 100644 --- a/eeprom.hpp +++ b/eeprom.hpp @@ -8,66 +8,103 @@ type EEMEM __##name; \ constexpr auto name = &__##name +#define EEARRAY(type, name, size) \ + type EEMEM __##name[size]; \ + constexpr auto name = __##name + +#define EEARRAY_SIZE(name) (sizeof(__##name) / sizeof(__##name[0])) + +namespace detail { + +template +constexpr T readEepromValue(const T *addr) +{ + if constexpr (type::is_integral_v) { + if constexpr (sizeof(T) == 1) { + return eeprom_read_byte(reinterpret_cast(addr)); + } else if constexpr (sizeof(T) == 2) { + return eeprom_read_word(reinterpret_cast(addr)); + } else if constexpr (sizeof(T) == 4) { + return eeprom_read_dword(reinterpret_cast(addr)); + } else if constexpr (sizeof(T) == 8) { + T number; + eeprom_read_block(&number, addr, sizeof(T)); + return number; + } + } else if constexpr (type::is_floating_point_v) { + static_assert(sizeof(T) == 4, "Only floats of size 4 are supported"); + return eeprom_read_float(reinterpret_cast(addr)); + } +} + +template +constexpr void readEepromArray(const T *addr, T *array) +{ + eeprom_read_block(array, addr, Size * sizeof(T)); +} + +template +constexpr void writeEepromValue(T *addr, const T &value) +{ + if constexpr (type::is_integral_v) { + if constexpr (sizeof(T) == 1) { + if constexpr (Update) { + eeprom_update_byte(reinterpret_cast(addr), value); + } else { + eeprom_write_byte(reinterpret_cast(addr), value); + } + } else if constexpr (sizeof(T) == 2) { + if constexpr (Update) { + eeprom_update_word(reinterpret_cast(addr), value); + } else { + eeprom_write_word(reinterpret_cast(addr), value); + } + } else if constexpr (sizeof(T) == 4) { + if constexpr (Update) { + eeprom_update_dword(reinterpret_cast(addr), value); + } else { + eeprom_write_dword(reinterpret_cast(addr), value); + } + } else if constexpr (sizeof(T) == 8) { + if constexpr (Update) { + eeprom_update_block(&value, addr, sizeof(T)); + } else { + eeprom_write_block(&value, addr, sizeof(T)); + } + } + } else if constexpr (type::is_floating_point_v) { + static_assert(sizeof(T) == 4, "Only floats of size 4 are supported"); + if constexpr (Update) { + eeprom_update_float(reinterpret_cast(addr), value); + } else { + eeprom_write_float(reinterpret_cast(addr), value); + } + } +} + +template +constexpr void writeEepromArray(T *addr, const T *array) +{ + if constexpr (Update) { + eeprom_update_block(array, addr, Size * sizeof(T)); + } else { + eeprom_write_block(array, addr, Size * sizeof(T)); + } +} + +} // namespace detail + template > class Eeprom { public: operator T() const { - if constexpr (type::is_integral_v) { - if constexpr (sizeof(T) == 1) { - return eeprom_read_byte(reinterpret_cast(Address)); - } else if constexpr (sizeof(T) == 2) { - return eeprom_read_word(reinterpret_cast(Address)); - } else if constexpr (sizeof(T) == 4) { - return eeprom_read_dword(reinterpret_cast(Address)); - } else if constexpr (sizeof(T) == 8) { - T number; - eeprom_read_block(&number, Address, sizeof(T)); - return number; - } - } else if constexpr (type::is_floating_point_v) { - static_assert(sizeof(T) == 4, "Only floats of size 4 are supported"); - return eeprom_read_float(reinterpret_cast(Address)); - } + return detail::readEepromValue(Address); } Eeprom &operator=(const T &other) { - if constexpr (type::is_integral_v) { - if constexpr (sizeof(T) == 1) { - if constexpr (Update) { - eeprom_update_byte(reinterpret_cast(Address), other); - } else { - eeprom_write_byte(reinterpret_cast(Address), other); - } - } else if constexpr (sizeof(T) == 2) { - if constexpr (Update) { - eeprom_update_word(reinterpret_cast(Address), other); - } else { - eeprom_write_word(reinterpret_cast(Address), other); - } - } else if constexpr (sizeof(T) == 4) { - if constexpr (Update) { - eeprom_update_dword(reinterpret_cast(Address), other); - } else { - eeprom_write_dword(reinterpret_cast(Address), other); - } - } else if constexpr (sizeof(T) == 8) { - if constexpr (Update) { - eeprom_update_block(&other, Address, sizeof(T)); - } else { - eeprom_write_block(&other, Address, sizeof(T)); - } - } - } else if constexpr (type::is_floating_point_v) { - static_assert(sizeof(T) == 4, "Only floats of size 4 are supported"); - if constexpr (Update) { - eeprom_update_float(reinterpret_cast(Address), other); - } else { - eeprom_write_float(reinterpret_cast(Address), other); - } - } - + detail::writeEepromValue(Address, other); return *this; } @@ -78,3 +115,37 @@ class Eeprom { static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Only sizes 1, 2, 4, and 8 are supported"); }; + +template > +class EepromArray { + private: + class AccessHelper; + + public: + constexpr size_t size() const + { + return Size; + } + + constexpr AccessHelper operator[](const size_t &idx) + { + return AccessHelper(idx); + } + + private: + class AccessHelper { + public: + AccessHelper(const size_t &idx) : m_idx(idx) {} + constexpr void operator=(const T &other) + { + detail::writeEepromValue(Address + m_idx, other); + } + constexpr operator T() const + { + return detail::readEepromValue(Address + m_idx); + } + + private: + const size_t m_idx; + }; +};