use super::{Eeprom, EepromRecord};
use byteorder::{BigEndian, ByteOrder};
use defmt::error;
use embedded_storage::nor_flash::NorFlash;
use packed_struct::prelude::*;
pub(crate) const EEPROM_MAGIC: u16 = 0xFEE6;
const EEPROM_DISABLED_MAGIC: u16 = 0xFFFF;
const MAGIC_ADDR: u16 = 0;
const MAGIC_SIZE: usize = 2;
const DEFAULT_LAYER_START: usize = 2;
const DEFAULT_LAYER_SIZE: usize = 1;
const KEYMAP_CONFIG_ADDR: u16 = 3;
const KEYMAP_CONFIG_SIZE: usize = 2;
const BACKLIGHT_CONFIG_ADDR: u16 = 5;
const BACKLIGHT_CONFIG_SIZE: usize = 1;
const AUDIO_CONFIG_ADDR: u16 = 6;
const AUDIO_CONFIG_SIZE: usize = 1;
const RGB_CONFIG_ADDR: u16 = 7;
const RGB_CONFIG_SIZE: usize = 5;
const LAYOUT_OPTION_ADDR: u16 = 12;
const LAYOUT_OPTION_SIZE: usize = 4;
pub(crate) const DYNAMIC_KEYMAP_ADDR: u16 = 16;
impl<F: NorFlash, const EEPROM_SIZE: usize> Eeprom<F, EEPROM_SIZE> {
pub(crate) fn init_with_default_config(&mut self) {
self.set_enable(true);
self.set_default_layer(0);
self.set_keymap_config(EeKeymapConfig::default());
self.set_backlight_config(EeBacklightConfig::default());
self.set_audio_config(EeAudioConfig::default());
self.set_rgb_light_config(EeRgbLightConfig::default());
self.set_layout_option(0);
}
pub(crate) fn init_with_config(&mut self, config: Eeconfig) {
self.set_enable(config.eeprom_enable);
self.set_default_layer(config.default_layer);
self.set_keymap_config(config.keymap_config);
self.set_backlight_config(config.backlight_config);
self.set_audio_config(config.audio_config);
self.set_rgb_light_config(config.rgb_light_config);
self.set_layout_option(config.layout_option);
}
pub(crate) fn set_enable(&mut self, enabled: bool) {
let magic = if enabled {
EEPROM_MAGIC
} else {
EEPROM_DISABLED_MAGIC
};
let mut buf = [0xFF; 2];
BigEndian::write_u16(&mut buf, magic);
self.write_byte(0, &mut buf);
}
pub(crate) fn get_magic(&mut self) -> u16 {
let mut bytes = [0_u8; 4];
match self
.storage
.read(self.storage_config.start_addr, &mut bytes)
{
Ok(_) => {
let record = EepromRecord::from_bytes(bytes);
record.data
}
Err(_) => EEPROM_DISABLED_MAGIC,
}
}
pub(crate) fn set_default_layer(&mut self, default_layer: u8) {
self.write_byte(DEFAULT_LAYER_START as u16, &[default_layer]);
}
pub(crate) fn get_default_layer(&self) -> u8 {
self.cache[DEFAULT_LAYER_START]
}
pub(crate) fn set_keymap_config(&mut self, config: EeKeymapConfig) {
let mut buf = match config.pack() {
Ok(b) => b,
Err(_) => {
error!("Pack keymap config error");
[0xFF; 2]
}
};
self.write_byte(KEYMAP_CONFIG_ADDR, &mut buf);
}
pub(crate) fn get_keymap_config(&self) -> Option<EeKeymapConfig> {
match EeKeymapConfig::unpack_from_slice(
self.read_byte(KEYMAP_CONFIG_ADDR, KEYMAP_CONFIG_SIZE),
) {
Ok(config) => Some(config),
Err(_) => {
error!("Unpack keymap config error");
None
}
}
}
pub(crate) fn set_backlight_config(&mut self, config: EeBacklightConfig) {
let mut buf = match config.pack() {
Ok(b) => b,
Err(_) => {
error!("Pack backlight config error");
[0xFF; 1]
}
};
self.write_byte(BACKLIGHT_CONFIG_ADDR, &mut buf);
}
pub(crate) fn get_backlight_config(&self) -> Option<EeBacklightConfig> {
match EeBacklightConfig::unpack_from_slice(
self.read_byte(BACKLIGHT_CONFIG_ADDR, BACKLIGHT_CONFIG_SIZE),
) {
Ok(config) => Some(config),
Err(_) => {
error!("Unpack backlight config error");
None
}
}
}
pub(crate) fn set_audio_config(&mut self, config: EeAudioConfig) {
let mut buf = match config.pack() {
Ok(b) => b,
Err(_) => {
error!("Pack audio config error");
[0xFF; 1]
}
};
self.write_byte(AUDIO_CONFIG_ADDR, &mut buf);
}
pub(crate) fn get_audio_config(&self) -> Option<EeAudioConfig> {
match EeAudioConfig::unpack_from_slice(self.read_byte(AUDIO_CONFIG_ADDR, AUDIO_CONFIG_SIZE))
{
Ok(config) => Some(config),
Err(_) => {
error!("Unpack audio config error");
None
}
}
}
pub(crate) fn set_rgb_light_config(&mut self, config: EeRgbLightConfig) {
let mut buf = match config.pack() {
Ok(b) => b,
Err(_) => {
error!("Pack rgb light config error");
[0xFF; 5]
}
};
self.write_byte(RGB_CONFIG_ADDR, &mut buf);
}
pub(crate) fn get_rgb_light_config(&self) -> Option<EeRgbLightConfig> {
match EeRgbLightConfig::unpack_from_slice(self.read_byte(RGB_CONFIG_ADDR, RGB_CONFIG_SIZE))
{
Ok(config) => Some(config),
Err(_) => {
error!("Unpack rgb light config error");
None
}
}
}
pub(crate) fn set_layout_option(&mut self, option: u32) {
let mut buf = [0xFF; 4];
BigEndian::write_u32(&mut buf, option);
self.write_byte(LAYOUT_OPTION_ADDR, &mut buf);
}
pub(crate) fn get_layout_option(&self) -> u32 {
BigEndian::read_u32(self.read_byte(LAYOUT_OPTION_ADDR, LAYOUT_OPTION_SIZE))
}
}
#[derive(Default)]
pub struct Eeconfig {
eeprom_enable: bool,
default_layer: u8,
keymap_config: EeKeymapConfig,
backlight_config: EeBacklightConfig,
audio_config: EeAudioConfig,
rgb_light_config: EeRgbLightConfig,
layout_option: u32,
}
#[derive(PackedStruct, Debug, Default)]
#[packed_struct(bit_numbering = "msb0", bytes = "2")]
pub(crate) struct EeKeymapConfig {
#[packed_field(bits = "0")]
swap_control_capslock: bool,
#[packed_field(bits = "1")]
capslock_to_control: bool,
#[packed_field(bits = "2")]
swap_lalt_lgui: bool,
#[packed_field(bits = "3")]
swap_ralt_rgui: bool,
#[packed_field(bits = "4")]
no_gui: bool,
#[packed_field(bits = "5")]
swap_grave_esc: bool,
#[packed_field(bits = "6")]
swap_backslash_backspace: bool,
#[packed_field(bits = "7")]
nkro: bool,
#[packed_field(bits = "8")]
swap_lctl_lgui: bool,
#[packed_field(bits = "9")]
swap_rctl_rgui: bool,
#[packed_field(bits = "10")]
oneshot_enable: bool,
#[packed_field(bits = "11")]
swap_escape_capslock: bool,
#[packed_field(bits = "12")]
autocorrect_enable: bool,
_reserved: ReservedOne<packed_bits::Bits<3>>,
}
#[derive(PackedStruct, Debug, Default)]
#[packed_struct(bit_numbering = "msb0")]
pub(crate) struct EeBacklightConfig {
#[packed_field(bits = "0")]
enable: bool,
#[packed_field(bits = "1")]
breathing: bool,
#[packed_field(bits = "2")]
reserved: bool,
#[packed_field(bits = "3..=7")]
level: u8,
}
#[derive(PackedStruct, Debug, Default)]
#[packed_struct(bit_numbering = "msb0")]
pub(crate) struct EeAudioConfig {
#[packed_field(bits = "0")]
enable: bool,
#[packed_field(bits = "1")]
clicky_enable: bool,
#[packed_field(bits = "2..=7")]
level: u8,
}
#[derive(PackedStruct, Debug, Default)]
#[packed_struct(bit_numbering = "msb0")]
pub(crate) struct EeRgbLightConfig {
#[packed_field(bits = "0")]
enable: bool,
#[packed_field(bits = "1..=7")]
mode: u8,
#[packed_field(bits = "8..=15")]
hue: u8,
#[packed_field(bits = "16..=23")]
sat: u8,
#[packed_field(bits = "24..=31")]
val: u8,
#[packed_field(bits = "32..=39")]
speed: u8,
}