Browse Source

Add support for pulse width patterning

Kevin Lee 3 months ago
parent
commit
462554fb91
3 changed files with 106 additions and 33 deletions
  1. 1 0
      README.md
  2. 24 0
      src/config/pen.rs
  3. 81 33
      src/ezcad/types.rs

+ 1 - 0
README.md

@@ -80,6 +80,7 @@ Field: !Loops 1
 Field: !Speed 100.0
 Field: !Power 10.0
 Field: !Frequency 1000
+Field: !PulseWidth 2 # Increment
 ```
 
 Exporting a pen to a file:

+ 24 - 0
src/config/pen.rs

@@ -6,6 +6,7 @@ use ezcad::{
 };
 use log::debug;
 use serde::{Deserialize, Serialize};
+use strum::IntoEnumIterator;
 
 const SPEED_MIN: f64 = 0.0;
 const SPEED_MAX: f64 = 100000.0;
@@ -170,6 +171,7 @@ pub enum PatternField {
     Speed(f64),
     Power(f64),
     Frequency(i32),
+    PulseWidth(u32),
 }
 
 impl PatternField {
@@ -200,6 +202,13 @@ impl PatternField {
                 );
                 PatternField::Frequency((*src.frequency).try_into().unwrap())
             }
+            PatternField::PulseWidth(_) => {
+                debug!(
+                    "Initial pulse width from pen #{} is {}ns",
+                    src_idx, *src.pulse_width
+                );
+                PatternField::PulseWidth(*src.pulse_width)
+            }
         };
 
         for (idx, dst) in pens {
@@ -245,6 +254,17 @@ impl PatternField {
                     );
                     PatternField::Frequency(value)
                 }
+                (PatternField::PulseWidth(prev), PatternField::PulseWidth(incr)) => {
+                    let mut pw = PulseWidth::iter();
+                    let _ = pw
+                        .find(|x| u32::from(*x) == prev)
+                        .expect("Unknown pulse width");
+
+                    let mut pw = pw.skip((*incr - 1).try_into().unwrap());
+                    let next: u32 = pw.next().expect("Pulse width out of bounds").into();
+                    debug!("Patching pulse width for pen #{} to {}ns", idx, next);
+                    PatternField::PulseWidth(next)
+                }
                 _ => unreachable!(),
             };
 
@@ -257,6 +277,10 @@ impl PatternField {
                     *dst.frequency = x.try_into().unwrap();
                     *dst.frequency_2 = x.try_into().unwrap();
                 }
+                PatternField::PulseWidth(x) => {
+                    *dst.pulse_width = x;
+                    *dst.pulse_width_2 = x.try_into().unwrap();
+                }
             }
 
             // Randomize pen color

+ 81 - 33
src/ezcad/types.rs

@@ -5,10 +5,9 @@ use std::{
 
 use binrw::{binrw, BinRead, BinWrite};
 use diff::{Diff, VecDiff};
-use num_enum::{IntoPrimitive, TryFromPrimitive};
 use rand::{thread_rng, Rng};
 use serde::{Deserialize, Serialize};
-use serde_repr::{Deserialize_repr, Serialize_repr};
+use strum::EnumIter;
 
 use crate::{array_of::ArrayOfPrimitive, field_of::FieldOf};
 
@@ -255,40 +254,89 @@ impl Default for ObjectType {
     }
 }
 
-#[derive(
-    Copy,
-    Clone,
-    Debug,
-    Diff,
-    PartialEq,
-    BinRead,
-    BinWrite,
-    strum::Display,
-    Serialize_repr,
-    Deserialize_repr,
-    IntoPrimitive,
-    TryFromPrimitive,
-)]
+#[derive(Copy, Clone, Debug, Diff, PartialEq, strum::Display, Serialize, Deserialize, EnumIter)]
 #[diff(attr(
     #[derive(Debug, PartialEq)]
 ))]
-#[brw(repr(u32))]
+#[serde(try_from = "u32")]
+#[serde(into = "u32")]
 #[repr(u32)]
 pub enum PulseWidth {
-    Ns2 = 2,
-    Ns4 = 4,
-    Ns6 = 6,
-    Ns8 = 8,
-    Ns12 = 12,
-    Ns20 = 20,
-    Ns30 = 30,
-    Ns45 = 45,
-    Ns60 = 60,
-    Ns80 = 80,
-    Ns100 = 100,
-    Ns150 = 150,
-    Ns200 = 200,
-    Ns250 = 250,
-    Ns350 = 350,
-    Ns500 = 500,
+    Ns2,
+    Ns4,
+    Ns6,
+    Ns8,
+    Ns12,
+    Ns20,
+    Ns30,
+    Ns45,
+    Ns60,
+    Ns80,
+    Ns100,
+    Ns150,
+    Ns200,
+    Ns250,
+    Ns350,
+    Ns500,
+}
+
+impl From<PulseWidth> for u32 {
+    fn from(value: PulseWidth) -> Self {
+        match value {
+            PulseWidth::Ns2 => 2,
+            PulseWidth::Ns4 => 4,
+            PulseWidth::Ns6 => 6,
+            PulseWidth::Ns8 => 8,
+            PulseWidth::Ns12 => 12,
+            PulseWidth::Ns20 => 20,
+            PulseWidth::Ns30 => 30,
+            PulseWidth::Ns45 => 45,
+            PulseWidth::Ns60 => 60,
+            PulseWidth::Ns80 => 80,
+            PulseWidth::Ns100 => 100,
+            PulseWidth::Ns150 => 150,
+            PulseWidth::Ns200 => 200,
+            PulseWidth::Ns250 => 250,
+            PulseWidth::Ns350 => 350,
+            PulseWidth::Ns500 => 500,
+        }
+    }
+}
+
+pub enum PulseWidthError {
+    Unsupported,
+}
+
+impl Display for PulseWidthError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            PulseWidthError::Unsupported => write!(f, "Unsupported pulse width value"),
+        }
+    }
+}
+
+impl TryFrom<u32> for PulseWidth {
+    type Error = PulseWidthError;
+
+    fn try_from(value: u32) -> Result<Self, Self::Error> {
+        match value {
+            2 => Ok(PulseWidth::Ns2),
+            4 => Ok(PulseWidth::Ns4),
+            6 => Ok(PulseWidth::Ns6),
+            8 => Ok(PulseWidth::Ns8),
+            12 => Ok(PulseWidth::Ns12),
+            20 => Ok(PulseWidth::Ns20),
+            30 => Ok(PulseWidth::Ns30),
+            45 => Ok(PulseWidth::Ns45),
+            60 => Ok(PulseWidth::Ns60),
+            80 => Ok(PulseWidth::Ns80),
+            100 => Ok(PulseWidth::Ns100),
+            150 => Ok(PulseWidth::Ns150),
+            200 => Ok(PulseWidth::Ns200),
+            250 => Ok(PulseWidth::Ns250),
+            350 => Ok(PulseWidth::Ns350),
+            500 => Ok(PulseWidth::Ns500),
+            _ => Err(PulseWidthError::Unsupported),
+        }
+    }
 }