use anyhow::{Result, ensure};
use crate::{
serde::{Deserializer, Serializer, SliceDeserializer},
units::{Milimeters, MilimetersPerMinute, Seconds},
};
use crate::goo::DELIMITER;
pub struct Layer {
pub pause: bool,
pub pause_position_z: Milimeters,
pub layer_position_z: Milimeters,
pub layer_exposure_time: Seconds,
pub layer_off_time: Seconds,
pub before_lift_time: Seconds,
pub after_lift_time: Seconds,
pub after_retract_time: Seconds,
pub lift_distance: Milimeters,
pub lift_speed: MilimetersPerMinute,
pub second_lift_distance: Milimeters,
pub second_lift_speed: MilimetersPerMinute,
pub retract_distance: Milimeters,
pub retract_speed: MilimetersPerMinute,
pub second_retract_distance: Milimeters,
pub second_retract_speed: MilimetersPerMinute,
pub light_pwm: u8,
pub data: Vec<u8>,
pub checksum: u8,
}
impl Layer {
pub fn serialize<T: Serializer>(&self, ser: &mut T) {
ser.write_u16_be(self.pause as u16);
ser.write_f32_be(self.pause_position_z.raw());
ser.write_f32_be(self.layer_position_z.raw());
ser.write_f32_be(self.layer_exposure_time.raw());
ser.write_f32_be(self.layer_off_time.raw());
ser.write_f32_be(self.before_lift_time.raw());
ser.write_f32_be(self.after_lift_time.raw());
ser.write_f32_be(self.after_retract_time.raw());
ser.write_f32_be(self.lift_distance.raw());
ser.write_f32_be(self.lift_speed.raw());
ser.write_f32_be(self.second_lift_distance.raw());
ser.write_f32_be(self.second_lift_speed.raw());
ser.write_f32_be(self.retract_distance.raw());
ser.write_f32_be(self.retract_speed.raw());
ser.write_f32_be(self.second_retract_distance.raw());
ser.write_f32_be(self.second_retract_speed.raw());
ser.write_u16_be(self.light_pwm as u16);
ser.write_bytes(DELIMITER);
ser.write_u32_be(self.data.len() as u32 + 2);
ser.write_bytes(&[0x55]);
ser.write_bytes(&self.data);
ser.write_u8(calculate_checksum(&self.data));
ser.write_bytes(DELIMITER);
}
pub fn deserialize(des: &mut SliceDeserializer) -> Result<Self> {
Ok(Self {
pause: des.read_u16_be() != 0,
pause_position_z: Milimeters::new(des.read_f32_be()),
layer_position_z: Milimeters::new(des.read_f32_be()),
layer_exposure_time: Seconds::new(des.read_f32_be()),
layer_off_time: Seconds::new(des.read_f32_be()),
before_lift_time: Seconds::new(des.read_f32_be()),
after_lift_time: Seconds::new(des.read_f32_be()),
after_retract_time: Seconds::new(des.read_f32_be()),
lift_distance: Milimeters::new(des.read_f32_be()),
lift_speed: MilimetersPerMinute::new(des.read_f32_be()),
second_lift_distance: Milimeters::new(des.read_f32_be()),
second_lift_speed: MilimetersPerMinute::new(des.read_f32_be()),
retract_distance: Milimeters::new(des.read_f32_be()),
retract_speed: MilimetersPerMinute::new(des.read_f32_be()),
second_retract_distance: Milimeters::new(des.read_f32_be()),
second_retract_speed: MilimetersPerMinute::new(des.read_f32_be()),
light_pwm: des.read_u16_be().min(255) as u8,
data: {
ensure!(des.read_slice(2) == DELIMITER);
let data_len = des.read_u32_be() as usize - 2;
ensure!(des.read_u8() == 0x55);
des.read_slice(data_len).to_vec() },
checksum: {
let checksum = des.read_u8();
ensure!(des.read_slice(2) == DELIMITER);
checksum
},
})
}
}
pub fn calculate_checksum(data: &[u8]) -> u8 {
let mut out = 0u8;
for &byte in data {
out = out.wrapping_add(byte);
}
!out
}