From 625f9e6ff3e08a7a4f12641e48e5e4b79732f0b6 Mon Sep 17 00:00:00 2001 From: Stephen D <webmaster@scd31.com> Date: Mon, 13 May 2024 20:42:39 -0300 Subject: [PATCH] wip --- src/controller.rs | 32 ++++++++++---------- src/gui/contact_view.rs | 28 +++++++++--------- src/storage.rs | 65 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 88 insertions(+), 37 deletions(-) diff --git a/src/controller.rs b/src/controller.rs index ac79f9f..aadc0a8 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -65,11 +65,16 @@ impl View { pub fn from_contact_options_id( id: usize, contact_id: usize, - mut contacts: ContactIter, + storage: &Storage, ) -> Option<Self> { + let mut contacts = storage.contacts(); + match id { 0 => { - let contact = contacts.nth(contact_id).unwrap_or(Contact::empty()).clone(); + let contact = contacts + .nth(contact_id) + .unwrap_or_else(|| storage.new_contact()) + .clone(); Some(View::ContactView( ContactView::new(contact, false), contact_id, @@ -77,7 +82,10 @@ impl View { } 1 => { - let contact = contacts.nth(contact_id).unwrap_or(Contact::empty()).clone(); + let contact = contacts + .nth(contact_id) + .unwrap_or_else(|| storage.new_contact()) + .clone(); Some(View::ContactView( ContactView::new(contact, true), contact_id, @@ -183,24 +191,18 @@ impl Element for Controller { (View::Contacts(c), KeyCode::Touchpad) => { if c.selected() == self.storage.contacts_len() { - // TODO flash - // self.contacts.contacts.push(Contact::default()).unwrap(); - // Go direct to edit page self.cur_view = - View::from_contact_options_id(1, c.selected(), self.storage.contacts()) - .unwrap(); + View::from_contact_options_id(1, c.selected(), &self.storage).unwrap(); } else { self.cur_view = View::new_contact_options(c.selected()); } } (View::ContactOptions(c, contact_id), KeyCode::Touchpad) => { - if let Some(new_view) = View::from_contact_options_id( - c.selected(), - *contact_id, - self.storage.contacts(), - ) { + if let Some(new_view) = + View::from_contact_options_id(c.selected(), *contact_id, &self.storage) + { self.cur_view = new_view; } } @@ -216,8 +218,8 @@ impl Element for Controller { } (View::ContactView(cv, contact_id), KeyCode::Back) => { - // TODO save contact - // self.storage.contacts().contacts[*contact_id] = cv.contact(); + self.storage.save_contact(cv.contact()); + self.cur_view = View::new_contact_options(*contact_id) } diff --git a/src/gui/contact_view.rs b/src/gui/contact_view.rs index 09429de..2c721ab 100644 --- a/src/gui/contact_view.rs +++ b/src/gui/contact_view.rs @@ -77,24 +77,22 @@ impl ContactView { } } - pub fn contact(&self) -> Contact { + pub fn contact(&mut self) -> Contact { if self.editable { - Contact { - callsign: self - .callsign - .get_text() - .try_into() - .unwrap_or_else(|_| self.contact.callsign.clone()), - ssid: self.ssid.get_text().parse().unwrap_or(self.contact.ssid), - name: self - .name - .get_text() - .try_into() - .unwrap_or_else(|_| self.contact.name.clone()), + if let Ok(callsign) = self.callsign.get_text().try_into() { + self.contact.callsign = callsign; + } + + if let Ok(ssid) = self.ssid.get_text().parse() { + self.contact.ssid = ssid; + } + + if let Ok(name) = self.name.get_text().try_into() { + self.contact.name = name; } - } else { - self.contact.clone() } + + self.contact.clone() } } diff --git a/src/storage.rs b/src/storage.rs index c27ae3b..ce12a39 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -29,6 +29,19 @@ impl Storage { } } + pub fn save_contact(&mut self, contact: Contact) { + let len = self.contact_header.num_contacts; + + // if id isn't less than the len, we're inserting a new contact + if contact.id >= usize::from(len) { + assert!(usize::from(len) < MAX_CONTACTS); + self.contact_header.num_contacts += 1; + self.contact_header.write(&self); + } + + contact.write(&self); + } + pub fn contacts(&self) -> ContactIter { ContactIter::new(self.contact_header.num_contacts.into()) } @@ -36,6 +49,22 @@ impl Storage { pub fn contacts_len(&self) -> usize { self.contact_header.num_contacts.into() } + + // Note - calling this twice without saving one + // will cause a duplicate ID + // We don't increment the len until the contact is actually saved + pub fn new_contact(&self) -> Contact { + Contact { + callsign: String::new(), + ssid: 0, + name: String::new(), + id: usize::from(self.contact_header.num_contacts), + } + } + + fn write_data(&self, start_addr: usize, buf: &[u8]) { + todo!() + } } // Up to 100 contacts @@ -46,7 +75,7 @@ struct ContactHeader { impl ContactHeader { fn read() -> Self { - let bytes = unsafe { from_raw_parts(CONTACT_HEADER_START as *mut u8, CONTACT_LENGTH) }; + let bytes = unsafe { from_raw_parts(CONTACT_HEADER_START as *mut u8, CONTACT_HEADER_SIZE) }; let num_contacts = bytes[0]; let checksum_expected = u16::from_le_bytes([bytes[1], bytes[2]]); // CRC checksum is very overkill right now @@ -59,6 +88,15 @@ impl ContactHeader { Self { num_contacts: 0 } } } + + fn write(&self, storage: &Storage) { + let mut buf = [0; CONTACT_HEADER_SIZE]; + buf[0] = self.num_contacts; + let checksum = X25.checksum(&[self.num_contacts]); + buf[1..].copy_from_slice(&checksum.to_le_bytes()); + + storage.write_data(CONTACT_HEADER_START, &buf); + } } #[derive(Clone)] @@ -66,6 +104,7 @@ pub struct Contact { pub callsign: String<MAX_CONTACT_CALLSIGN_LENGTH>, pub ssid: u8, pub name: String<MAX_CONTACT_NAME_LENGTH>, + id: usize, } impl Contact { @@ -101,15 +140,27 @@ impl Contact { callsign, ssid, name, + id: idx, }) } - pub fn empty() -> Self { - Self { - callsign: String::new(), - ssid: 0, - name: String::new(), - } + fn write(&self, storage: &Storage) { + let start_addr = CONTACT_HEADER_START + CONTACT_HEADER_SIZE + self.id * CONTACT_LENGTH; + + let mut buf = [0; CONTACT_LENGTH]; + buf[0] = self.callsign.len().try_into().unwrap(); + buf[1] = self.name.len().try_into().unwrap(); + buf[2] = self.ssid; + + let callsign_bytes = self.callsign.as_bytes(); + let name_bytes = self.name.as_bytes(); + buf[3..(3 + callsign_bytes.len())].copy_from_slice(&callsign_bytes); + buf[(3 + MAX_CONTACT_NAME_LENGTH)..(3 + MAX_CONTACT_NAME_LENGTH + name_bytes.len())] + .copy_from_slice(name_bytes); + let checksum = X25.checksum(&buf[..(CONTACT_LENGTH - 2)]); + buf[(CONTACT_LENGTH - 2)..].copy_from_slice(&checksum.to_le_bytes()); + + storage.write_data(start_addr, &buf); } } -- GitLab