ionpak-thermostat/firmware/src/config.rs

94 lines
2.5 KiB
Rust

use eeprom;
use crc::crc32;
use smoltcp::wire::{IpCidr, IpAddress};
const MAGIC: u8 = 0x54;
struct EepromReader {
buffer: [u8; eeprom::BLOCK_LEN]
}
impl EepromReader {
fn new() -> EepromReader {
EepromReader {
buffer: [0; eeprom::BLOCK_LEN]
}
}
fn read_payload_block<'a>(&'a mut self, block: u16) -> bool {
eeprom::read_block(&mut self.buffer, block);
if self.buffer[0] != MAGIC {
return false;
}
let len = self.buffer.len();
let cksum = self.buffer[len-4] as u32 | (self.buffer[len-3] as u32) << 8 |
(self.buffer[len-2] as u32) << 16 | (self.buffer[len-1] as u32) << 24;
if crc32::checksum_ieee(&self.buffer[0..len-4]) != cksum {
return false;
}
true
}
fn read_payload<'a>(&'a mut self) -> Result<&'a [u8], ()> {
let mut ok = self.read_payload_block(0);
if !ok {
ok = self.read_payload_block(1);
}
if ok {
Ok(&self.buffer[1..self.buffer.len()-4])
} else {
Err(())
}
}
}
fn write_eeprom_payload(payload: &[u8]) {
let mut buffer: [u8; eeprom::BLOCK_LEN] = [0; eeprom::BLOCK_LEN];
buffer[0] = MAGIC;
buffer[1..payload.len()+1].copy_from_slice(payload);
let len = buffer.len();
let cksum = crc32::checksum_ieee(&buffer[0..len-4]);
buffer[len-4] = cksum as u8;
buffer[len-3] = (cksum >> 8) as u8;
buffer[len-2] = (cksum >> 16) as u8;
buffer[len-1] = (cksum >> 24) as u8;
eeprom::write_block(&buffer, 0);
eeprom::write_block(&buffer, 1);
}
pub struct Config {
pub ip: IpCidr,
}
impl Config {
pub fn new() -> Config {
Config {
ip: IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24)
}
}
pub fn load(&mut self) {
let mut reader = EepromReader::new();
let payload = reader.read_payload();
if payload.is_ok() {
let payload = payload.unwrap();
self.ip = IpCidr::new(
IpAddress::v4(payload[0], payload[1], payload[2], payload[3]),
payload[4])
}
}
pub fn save(&self) {
match self.ip {
IpCidr::Ipv4(ipv4) => {
let mut payload: [u8; 5] = [0; 5];
payload[0..4].copy_from_slice(&ipv4.address().0);
payload[4] = ipv4.prefix_len();
write_eeprom_payload(&payload);
}
_ => panic!("unsupported network address")
};
}
}