mod contact; use contact::ContactGroup; pub use contact::{ Contact, ContactIter, MAX_CONTACTS, MAX_CONTACT_CALLSIGN_LENGTH, MAX_CONTACT_NAME_LENGTH, }; use core::slice::from_raw_parts; use rp2040_flash::flash; const SECTOR_SIZE: usize = 4096; const FLASH_START: usize = 0x10000000; // First 6MB is for code const DATA_START: usize = FLASH_START + 6144 * 1024; // 2MB for data const DATA_END: usize = DATA_START + 2048 * 1024; const X25: crc::Crc<u16> = crc::Crc::<u16>::new(&crc::CRC_16_IBM_SDLC); pub struct Storage { contacts: ContactGroup, } impl Storage { pub fn new() -> Self { Self { contacts: ContactGroup::new(), } } // Punch through our contact methods pub fn new_contact(&self) -> Contact { self.contacts.new_contact() } pub fn save_contact(&mut self, contact: Contact) { let mut contacts = self.contacts; contacts.save_contact(self, contact); self.contacts = contacts; } pub fn delete_contact(&mut self, contact_id: usize) { let mut contacts = self.contacts; contacts.delete_contact(self, contact_id); self.contacts = contacts; } pub fn contacts(&self) -> ContactIter { self.contacts.contacts() } pub fn contacts_len(&self) -> usize { self.contacts.len() } fn write_data(&mut self, start_addr: usize, buf: &[u8]) { let start_sector = start_addr / SECTOR_SIZE; let num_sectors = buf.len() / SECTOR_SIZE + 1; let diff = start_addr % SECTOR_SIZE; for s in 0..num_sectors { let existing_start = if s == 0 { diff } else { 0 }; let existing_end = (diff + (s + 1) * SECTOR_SIZE).min(existing_start + buf.len()); let mut existing = self.read_slice((start_sector + s) * SECTOR_SIZE); let buf_start = (s * SECTOR_SIZE).min(buf.len()); let buf_end = (buf_start + SECTOR_SIZE).min(buf.len()); // only write if there's a difference if existing[existing_start..existing_end] != buf[buf_start..buf_end] { existing[existing_start..existing_end].copy_from_slice(&buf[buf_start..buf_end]); self.write_sector((start_sector + s) * SECTOR_SIZE, &existing); } } } fn read_slice<const N: usize>(&self, addr: usize) -> [u8; N] { assert!(addr >= DATA_START); assert!(addr + N < DATA_END); let sector = unsafe { from_raw_parts(addr as *mut u8, N) }; let mut buf = [0; N]; buf.copy_from_slice(sector); buf } fn write_sector(&mut self, start_addr: usize, buf: &[u8; 4096]) { let addr: u32 = (start_addr - FLASH_START).try_into().unwrap(); let sector_size = u32::try_from(SECTOR_SIZE).unwrap(); assert!(addr % sector_size == 0); cortex_m::interrupt::free(|_| unsafe { flash::flash_range_erase_and_program(addr, buf, true); }); } }