rytm_rs/object/sound/machine/
sy_chip.rs

1use crate::{
2    error::{ConversionError, ParameterError, RytmError},
3    object::pattern::plock::ParameterLockPool,
4    util::{
5        from_s_u16_t, get_u16_min_max_from_float_range, i8_to_u8_midpoint_of_u8_input_range,
6        scale_f32_to_u16, scale_u16_to_f32, to_s_u16_t_union_a,
7        u8_to_i8_midpoint_of_u8_input_range,
8    },
9    RytmError::OrphanTrig,
10};
11use derivative::Derivative;
12use parking_lot::Mutex;
13use rytm_rs_macro::{machine_parameters, parameter_range};
14use rytm_sys::ar_sound_t;
15use serde::{Deserialize, Serialize};
16use std::sync::Arc;
17
18#[machine_parameters(
19 lev: "0..=127" #1,
20 tun: "-24.0..=24.0" #2,
21 dec: "0..=127" #3,
22 of2: "-24..=24" #4,
23 of3: "-24..=24" #5,
24 of4: "-24..=24" #6,
25 // #7 wav: (manual impl) (0=sin,1=asin,2=tri,3=ssaw,4=saw,5=sqr,6=noise,7=anm1,8=anm2,9=anm3,10=anm4,11=anm5,12=pwm+,13=pwm-,14=triB,15=+tri,16=tri+,17=triX,18=sawB,19=+saw,20=saw+,21=sawX,22=sqrB,23=+sqr,24=sqr+,25=sqrX,26=tbl1,27=tbl2,28=tbl3,29=p1%..127=p99%)
26 // #8 spd: (manual impl)  (0=128T,1=128,2=64T,3=128d,4=64,5=32T,6=64d,7=32,8=16T,9=32d,10=16,11=8T,12=16d,13=8,14=4T,15=8d,16=4,17=2T,18=4d,19=2,20=1T,21=2d,22=1,23=1d,24=1.0Hz,25=1.56Hz,26=1.88Hz,27=2Hz,28=3.13Hz,29=3.75Hz,30=4Hz,31=5Hz,32=6.25Hz,33=7.5Hz,34=10Hz,35=12.5Hz,36=15Hz,37=20Hz,38=25Hz,39=30Hz,40=40Hz,41=50Hz,42=60Hz,43=75Hz,44=100Hz,45=120Hz,46=150Hz,47=180Hz,48=200Hz,49=240Hz,50=250Hz,51=300Hz,52=350Hz,53=360Hz,54=400Hz,55=420Hz,56=480Hz,57=240 5Hz,58=200 5Hz,59=150 5Hz,60=120 5Hz,61=100 5Hz,62=60 5Hz,63=50 5Hz,64=30 5Hz,65=25 5Hz)
27)]
28/// Parameters for the `SyChip` machine.
29#[derive(Derivative, Clone, Serialize, Deserialize)]
30#[derivative(Debug)]
31pub struct SyChipParameters {
32    lev: u8,
33    tun: f32,
34    dec: u8,
35    of2: i8,
36    of3: i8,
37    of4: i8,
38    wav: SyChipWaveform,
39    spd: SyChipSpeed,
40
41    #[derivative(Debug = "ignore")]
42    #[serde(skip)]
43    parameter_lock_pool: Option<Arc<Mutex<ParameterLockPool>>>,
44    assigned_track: Option<usize>,
45}
46
47impl Default for SyChipParameters {
48    fn default() -> Self {
49        Self {
50            lev: 100,
51            tun: 12.0,
52            dec: 42,
53            of2: 3,
54            of3: 7,
55            of4: 10,
56            wav: SyChipWaveform::default(),
57            spd: SyChipSpeed::default(),
58            parameter_lock_pool: None,
59            assigned_track: None,
60        }
61    }
62}
63
64impl SyChipParameters {
65    pub(crate) fn link_parameter_lock_pool(&mut self, pool: Arc<Mutex<ParameterLockPool>>) {
66        self.parameter_lock_pool = Some(pool);
67    }
68
69    pub(crate) fn apply_to_raw_sound(&self, raw_sound: &mut ar_sound_t) {
70        self.apply_to_raw_sound_values(raw_sound);
71
72        let wav: u8 = self.wav.into();
73        raw_sound.synth_param_7 = to_s_u16_t_union_a((wav as u16) << 8);
74
75        let spd: u8 = self.spd.into();
76        raw_sound.synth_param_8 = to_s_u16_t_union_a((spd as u16) << 8);
77    }
78
79    /// Sets the `wav` parameter.
80    pub fn set_wav(&mut self, wav: SyChipWaveform) {
81        self.wav = wav;
82    }
83
84    /// Returns the `wav` parameter.
85    pub const fn get_wav(&self) -> SyChipWaveform {
86        self.wav
87    }
88
89    /// Sets the parameter lock for the `wav` parameter.
90    pub fn plock_set_wav(&self, wav: SyChipWaveform, trig_index: usize) -> Result<(), RytmError> {
91        if let Some(ref pool) = self.parameter_lock_pool {
92            let assigned_track = self.assigned_track.ok_or(OrphanTrig)?;
93            pool.lock().set_basic_plock(
94                trig_index,
95                assigned_track as u8,
96                rytm_sys::AR_PLOCK_TYPE_MP6 as u8,
97                wav.into(),
98            )?;
99            return Ok(());
100        }
101        Err(OrphanTrig)
102    }
103
104    /// Gets the parameter lock for the `wav` parameter.
105    pub fn plock_get_wav(&self, trig_index: usize) -> Result<Option<SyChipWaveform>, RytmError> {
106        if let Some(ref pool) = self.parameter_lock_pool {
107            let assigned_track = self.assigned_track.ok_or(OrphanTrig)?;
108            let wav = pool.lock().get_basic_plock(
109                trig_index,
110                assigned_track as u8,
111                rytm_sys::AR_PLOCK_TYPE_MP6 as u8,
112            );
113            if let Some(wav) = wav {
114                return Ok(Some(wav.try_into()?));
115            }
116            return Ok(None);
117        }
118        Err(OrphanTrig)
119    }
120
121    /// Clears the parameter lock for the `wav` parameter if set.
122    pub fn plock_clear_wav(&self, trig_index: usize) -> Result<(), RytmError> {
123        if let Some(ref pool) = self.parameter_lock_pool {
124            let assigned_track = self.assigned_track.ok_or(OrphanTrig)?;
125            pool.lock().clear_basic_plock(
126                trig_index,
127                assigned_track as u8,
128                rytm_sys::AR_PLOCK_TYPE_MP6 as u8,
129            );
130            return Ok(());
131        }
132        Err(OrphanTrig)
133    }
134
135    /// Sets the `spd` parameter.
136    pub fn set_spd(&mut self, spd: SyChipSpeed) -> Result<(), RytmError> {
137        self.spd = spd;
138        Ok(())
139    }
140
141    /// Returns the `spd` parameter.
142    pub const fn get_spd(&self) -> SyChipSpeed {
143        self.spd
144    }
145
146    /// Sets the parameter lock for the `spd` parameter.
147    pub fn plock_set_spd(&self, spd: SyChipSpeed, trig_index: usize) -> Result<(), RytmError> {
148        if let Some(ref pool) = self.parameter_lock_pool {
149            let assigned_track = self.assigned_track.ok_or(OrphanTrig)?;
150            pool.lock().set_basic_plock(
151                trig_index,
152                assigned_track as u8,
153                rytm_sys::AR_PLOCK_TYPE_MP7 as u8,
154                spd.into(),
155            )?;
156            return Ok(());
157        }
158        Err(OrphanTrig)
159    }
160
161    /// Gets the parameter lock for the `spd` parameter.
162    pub fn plock_get_spd(&self, trig_index: usize) -> Result<Option<SyChipSpeed>, RytmError> {
163        if let Some(ref pool) = self.parameter_lock_pool {
164            let assigned_track = self.assigned_track.ok_or(OrphanTrig)?;
165            let spd = pool.lock().get_basic_plock(
166                trig_index,
167                assigned_track as u8,
168                rytm_sys::AR_PLOCK_TYPE_MP7 as u8,
169            );
170            if let Some(spd) = spd {
171                return Ok(Some(spd.try_into()?));
172            }
173            return Ok(None);
174        }
175        Err(OrphanTrig)
176    }
177
178    /// Clears the parameter lock for the `spd` parameter if set.
179    pub fn plock_clear_spd(&self, trig_index: usize) -> Result<(), RytmError> {
180        if let Some(ref pool) = self.parameter_lock_pool {
181            let assigned_track = self.assigned_track.ok_or(OrphanTrig)?;
182            pool.lock().clear_basic_plock(
183                trig_index,
184                assigned_track as u8,
185                rytm_sys::AR_PLOCK_TYPE_MP7 as u8,
186            );
187            return Ok(());
188        }
189        Err(OrphanTrig)
190    }
191
192    #[parameter_range(range = "track_index[opt]:0..=11")]
193    pub(crate) fn from_raw_sound(
194        raw_sound: &ar_sound_t,
195        track_index: Option<usize>,
196    ) -> Result<Self, RytmError> {
197        let output_tun_min: f32 = -24.;
198        let output_tun_max: f32 = 24.;
199        let (input_tun_min, input_tun_max) =
200            get_u16_min_max_from_float_range(output_tun_min, output_tun_max);
201
202        unsafe {
203            Ok(Self {
204                parameter_lock_pool: None,
205                assigned_track: track_index,
206                lev: (from_s_u16_t(raw_sound.synth_param_1) >> 8) as u8,
207                tun: scale_u16_to_f32(
208                    from_s_u16_t(raw_sound.synth_param_2),
209                    input_tun_min,
210                    input_tun_max,
211                    output_tun_min,
212                    output_tun_max,
213                ),
214                dec: (from_s_u16_t(raw_sound.synth_param_3) >> 8) as u8,
215                of2: u8_to_i8_midpoint_of_u8_input_range(
216                    (from_s_u16_t(raw_sound.synth_param_4) >> 8) as u8,
217                    0,
218                    127,
219                ),
220                of3: u8_to_i8_midpoint_of_u8_input_range(
221                    (from_s_u16_t(raw_sound.synth_param_5) >> 8) as u8,
222                    0,
223                    127,
224                ),
225                of4: u8_to_i8_midpoint_of_u8_input_range(
226                    (from_s_u16_t(raw_sound.synth_param_6) >> 8) as u8,
227                    0,
228                    127,
229                ),
230                wav: SyChipWaveform::try_from((from_s_u16_t(raw_sound.synth_param_7) >> 8) as u8)?,
231                spd: SyChipSpeed::try_from((from_s_u16_t(raw_sound.synth_param_8) >> 8) as u8)?,
232            })
233        }
234    }
235}
236
237#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
238pub enum SyChipWaveform {
239    Sin,
240    Asin,
241    #[default]
242    Tri,
243    Ssaw,
244    Saw,
245    Sqr,
246    Noise,
247    Anm1,
248    Anm2,
249    Anm3,
250    Anm4,
251    Anm5,
252    PwmPlus,
253    PwmMinus,
254    TriB,
255    TriPlus,
256    TriPlusPlus,
257    TriX,
258    SawB,
259    SawPlus,
260    SawPlusPlus,
261    SawX,
262    SqrB,
263    SqrPlus,
264    SqrPlusPlus,
265    SqrX,
266    Tbl1,
267    Tbl2,
268    Tbl3,
269    /// Pulse width is a percentage from 1 to 99.
270    Percentage(usize),
271}
272impl TryFrom<&str> for SyChipWaveform {
273    type Error = ConversionError;
274    fn try_from(wav: &str) -> Result<Self, Self::Error> {
275        match wav {
276            "sin" => Ok(Self::Sin),
277            "asin" => Ok(Self::Asin),
278            "tri" => Ok(Self::Tri),
279            "ssaw" => Ok(Self::Ssaw),
280            "saw" => Ok(Self::Saw),
281            "sqr" => Ok(Self::Sqr),
282            "noise" => Ok(Self::Noise),
283            "anm1" => Ok(Self::Anm1),
284            "anm2" => Ok(Self::Anm2),
285            "anm3" => Ok(Self::Anm3),
286            "anm4" => Ok(Self::Anm4),
287            "anm5" => Ok(Self::Anm5),
288            "pwm+" => Ok(Self::PwmPlus),
289            "pwm-" => Ok(Self::PwmMinus),
290            "trib" => Ok(Self::TriB),
291            "tri+" => Ok(Self::TriPlus),
292            "tri++" => Ok(Self::TriPlusPlus),
293            "trix" => Ok(Self::TriX),
294            "sawb" => Ok(Self::SawB),
295            "saw+" => Ok(Self::SawPlus),
296            "saw++" => Ok(Self::SawPlusPlus),
297            "sawx" => Ok(Self::SawX),
298            "sqrb" => Ok(Self::SqrB),
299            "sqr+" => Ok(Self::SqrPlus),
300            "sqr++" => Ok(Self::SqrPlusPlus),
301            "sqrx" => Ok(Self::SqrX),
302            "tbl1" => Ok(Self::Tbl1),
303            "tbl2" => Ok(Self::Tbl2),
304            "tbl3" => Ok(Self::Tbl3),
305            wav if !wav.is_empty() => {
306                let (value, _) = wav.split_once('%').ok_or_else(|| ConversionError::Range {
307                    value: wav.to_string(),
308                    type_name: "SyChipWaveform".into(),
309                })?;
310                let wav = value.parse::<usize>()?;
311                if !(1..=99).contains(&wav) {
312                    return Err(ConversionError::Range {
313                        value: wav.to_string(),
314                        type_name: "SyChipWaveform".into(),
315                    });
316                }
317                Ok(Self::Percentage(wav))
318            }
319            _ => Err(ConversionError::Range {
320                value: wav.to_string(),
321                type_name: "SyChipWaveform".into(),
322            }),
323        }
324    }
325}
326
327impl TryFrom<u8> for SyChipWaveform {
328    type Error = ConversionError;
329    fn try_from(wav: u8) -> Result<Self, Self::Error> {
330        match wav {
331            0 => Ok(Self::Sin),
332            1 => Ok(Self::Asin),
333            2 => Ok(Self::Tri),
334            3 => Ok(Self::Ssaw),
335            4 => Ok(Self::Saw),
336            5 => Ok(Self::Sqr),
337            6 => Ok(Self::Noise),
338            7 => Ok(Self::Anm1),
339            8 => Ok(Self::Anm2),
340            9 => Ok(Self::Anm3),
341            10 => Ok(Self::Anm4),
342            11 => Ok(Self::Anm5),
343            12 => Ok(Self::PwmPlus),
344            13 => Ok(Self::PwmMinus),
345            14 => Ok(Self::TriB),
346            15 => Ok(Self::TriPlus),
347            16 => Ok(Self::TriPlusPlus),
348            17 => Ok(Self::TriX),
349            18 => Ok(Self::SawB),
350            19 => Ok(Self::SawPlus),
351            20 => Ok(Self::SawPlusPlus),
352            21 => Ok(Self::SawX),
353            22 => Ok(Self::SqrB),
354            23 => Ok(Self::SqrPlus),
355            24 => Ok(Self::SqrPlusPlus),
356            25 => Ok(Self::SqrX),
357            26 => Ok(Self::Tbl1),
358            27 => Ok(Self::Tbl2),
359            28 => Ok(Self::Tbl3),
360            29..=127 => Ok(Self::Percentage(wav as usize - 28)),
361            _ => Err(ConversionError::Range {
362                value: wav.to_string(),
363                type_name: "SyChipWaveform".into(),
364            }),
365        }
366    }
367}
368
369impl From<SyChipWaveform> for u8 {
370    fn from(wav: SyChipWaveform) -> Self {
371        match wav {
372            SyChipWaveform::Sin => 0,
373            SyChipWaveform::Asin => 1,
374            SyChipWaveform::Tri => 2,
375            SyChipWaveform::Ssaw => 3,
376            SyChipWaveform::Saw => 4,
377            SyChipWaveform::Sqr => 5,
378            SyChipWaveform::Noise => 6,
379            SyChipWaveform::Anm1 => 7,
380            SyChipWaveform::Anm2 => 8,
381            SyChipWaveform::Anm3 => 9,
382            SyChipWaveform::Anm4 => 10,
383            SyChipWaveform::Anm5 => 11,
384            SyChipWaveform::PwmPlus => 12,
385            SyChipWaveform::PwmMinus => 13,
386            SyChipWaveform::TriB => 14,
387            SyChipWaveform::TriPlus => 15,
388            SyChipWaveform::TriPlusPlus => 16,
389            SyChipWaveform::TriX => 17,
390            SyChipWaveform::SawB => 18,
391            SyChipWaveform::SawPlus => 19,
392            SyChipWaveform::SawPlusPlus => 20,
393            SyChipWaveform::SawX => 21,
394            SyChipWaveform::SqrB => 22,
395            SyChipWaveform::SqrPlus => 23,
396            SyChipWaveform::SqrPlusPlus => 24,
397            SyChipWaveform::SqrX => 25,
398            SyChipWaveform::Tbl1 => 26,
399            SyChipWaveform::Tbl2 => 27,
400            SyChipWaveform::Tbl3 => 28,
401            SyChipWaveform::Percentage(wav) => wav as Self + 28,
402        }
403    }
404}
405
406#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
407pub enum SyChipSpeed {
408    _128T,
409    _128,
410    _64T,
411    _128D,
412    _64,
413    _32T,
414    _64D,
415    _32,
416    _16T,
417    _32D,
418    _16,
419    _8T,
420    _16D,
421    _8,
422    _4T,
423    _8D,
424    _4,
425    _2T,
426    _4D,
427    _2,
428    _1T,
429    _2D,
430    _1,
431    _1D,
432    _1_0Hz,
433    _1_56Hz,
434    _1_88Hz,
435    _2Hz,
436    _3_13Hz,
437    _3_75Hz,
438    _4Hz,
439    _5Hz,
440    _6_25Hz,
441    _7_5Hz,
442    _10Hz,
443    _12_5Hz,
444    _15Hz,
445    _20Hz,
446    _25Hz,
447    _30Hz,
448    _40Hz,
449    #[default]
450    _50Hz,
451    _60Hz,
452    _75Hz,
453    _100Hz,
454    _120Hz,
455    _150Hz,
456    _180Hz,
457    _200Hz,
458    _240Hz,
459    _250Hz,
460    _300Hz,
461    _350Hz,
462    _360Hz,
463    _400Hz,
464    _420Hz,
465    _480Hz,
466    _240S,
467    _200S,
468    _150S,
469    _120S,
470    _100S,
471    _60S,
472    _50S,
473    _30S,
474    _25S,
475}
476
477impl TryFrom<&str> for SyChipSpeed {
478    type Error = ConversionError;
479    fn try_from(spd: &str) -> Result<Self, Self::Error> {
480        match spd {
481            "128t" => Ok(Self::_128T),
482            "128" => Ok(Self::_128),
483            "64t" => Ok(Self::_64T),
484            "128d" => Ok(Self::_128D),
485            "64" => Ok(Self::_64),
486            "32t" => Ok(Self::_32T),
487            "64d" => Ok(Self::_64D),
488            "32" => Ok(Self::_32),
489            "16t" => Ok(Self::_16T),
490            "32d" => Ok(Self::_32D),
491            "16" => Ok(Self::_16),
492            "8t" => Ok(Self::_8T),
493            "16d" => Ok(Self::_16D),
494            "8" => Ok(Self::_8),
495            "4t" => Ok(Self::_4T),
496            "8d" => Ok(Self::_8D),
497            "4" => Ok(Self::_4),
498            "2t" => Ok(Self::_2T),
499            "4d" => Ok(Self::_4D),
500            "2" => Ok(Self::_2),
501            "1t" => Ok(Self::_1T),
502            "2d" => Ok(Self::_2D),
503            "1" => Ok(Self::_1),
504            "1d" => Ok(Self::_1D),
505            "1.0hz" => Ok(Self::_1_0Hz),
506            "1.56hz" => Ok(Self::_1_56Hz),
507            "1.88hz" => Ok(Self::_1_88Hz),
508            "2hz" => Ok(Self::_2Hz),
509            "3.13hz" => Ok(Self::_3_13Hz),
510            "3.75hz" => Ok(Self::_3_75Hz),
511            "4hz" => Ok(Self::_4Hz),
512            "5hz" => Ok(Self::_5Hz),
513            "6.25hz" => Ok(Self::_6_25Hz),
514            "7.5hz" => Ok(Self::_7_5Hz),
515            "10hz" => Ok(Self::_10Hz),
516            "12.5hz" => Ok(Self::_12_5Hz),
517            "15hz" => Ok(Self::_15Hz),
518            "20hz" => Ok(Self::_20Hz),
519            "25hz" => Ok(Self::_25Hz),
520            "30hz" => Ok(Self::_30Hz),
521            "40hz" => Ok(Self::_40Hz),
522            "50hz" => Ok(Self::_50Hz),
523            "60hz" => Ok(Self::_60Hz),
524            "75hz" => Ok(Self::_75Hz),
525            "100hz" => Ok(Self::_100Hz),
526            "120hz" => Ok(Self::_120Hz),
527            "150hz" => Ok(Self::_150Hz),
528            "180hz" => Ok(Self::_180Hz),
529            "200hz" => Ok(Self::_200Hz),
530            "240hz" => Ok(Self::_240Hz),
531            "250hz" => Ok(Self::_250Hz),
532            "300hz" => Ok(Self::_300Hz),
533            "350hz" => Ok(Self::_350Hz),
534            "360hz" => Ok(Self::_360Hz),
535            "400hz" => Ok(Self::_400Hz),
536            "420hz" => Ok(Self::_420Hz),
537            "480hz" => Ok(Self::_480Hz),
538            "240s" => Ok(Self::_240S),
539            "200s" => Ok(Self::_200S),
540            "150s" => Ok(Self::_150S),
541            "120s" => Ok(Self::_120S),
542            "100s" => Ok(Self::_100S),
543            "60s" => Ok(Self::_60S),
544            "50s" => Ok(Self::_50S),
545            "30s" => Ok(Self::_30S),
546            "25s" => Ok(Self::_25S),
547            _ => Err(ConversionError::Range {
548                value: spd.to_string(),
549                type_name: "SyChipSpeed".into(),
550            }),
551        }
552    }
553}
554
555impl TryFrom<u8> for SyChipSpeed {
556    type Error = ConversionError;
557    fn try_from(spd: u8) -> Result<Self, Self::Error> {
558        match spd {
559            0 => Ok(Self::_128T),
560            1 => Ok(Self::_128),
561            2 => Ok(Self::_64T),
562            3 => Ok(Self::_128D),
563            4 => Ok(Self::_64),
564            5 => Ok(Self::_32T),
565            6 => Ok(Self::_64D),
566            7 => Ok(Self::_32),
567            8 => Ok(Self::_16T),
568            9 => Ok(Self::_32D),
569            10 => Ok(Self::_16),
570            11 => Ok(Self::_8T),
571            12 => Ok(Self::_16D),
572            13 => Ok(Self::_8),
573            14 => Ok(Self::_4T),
574            15 => Ok(Self::_8D),
575            16 => Ok(Self::_4),
576            17 => Ok(Self::_2T),
577            18 => Ok(Self::_4D),
578            19 => Ok(Self::_2),
579            20 => Ok(Self::_1T),
580            21 => Ok(Self::_2D),
581            22 => Ok(Self::_1),
582            23 => Ok(Self::_1D),
583            24 => Ok(Self::_1_0Hz),
584            25 => Ok(Self::_1_56Hz),
585            26 => Ok(Self::_1_88Hz),
586            27 => Ok(Self::_2Hz),
587            28 => Ok(Self::_3_13Hz),
588            29 => Ok(Self::_3_75Hz),
589            30 => Ok(Self::_4Hz),
590            31 => Ok(Self::_5Hz),
591            32 => Ok(Self::_6_25Hz),
592            33 => Ok(Self::_7_5Hz),
593            34 => Ok(Self::_10Hz),
594            35 => Ok(Self::_12_5Hz),
595            36 => Ok(Self::_15Hz),
596            37 => Ok(Self::_20Hz),
597            38 => Ok(Self::_25Hz),
598            39 => Ok(Self::_30Hz),
599            40 => Ok(Self::_40Hz),
600            41 => Ok(Self::_50Hz),
601            42 => Ok(Self::_60Hz),
602            43 => Ok(Self::_75Hz),
603            44 => Ok(Self::_100Hz),
604            45 => Ok(Self::_120Hz),
605            46 => Ok(Self::_150Hz),
606            47 => Ok(Self::_180Hz),
607            48 => Ok(Self::_200Hz),
608            49 => Ok(Self::_240Hz),
609            50 => Ok(Self::_250Hz),
610            51 => Ok(Self::_300Hz),
611            52 => Ok(Self::_350Hz),
612            53 => Ok(Self::_360Hz),
613            54 => Ok(Self::_400Hz),
614            55 => Ok(Self::_420Hz),
615            56 => Ok(Self::_480Hz),
616            57 => Ok(Self::_240S),
617            58 => Ok(Self::_200S),
618            59 => Ok(Self::_150S),
619            60 => Ok(Self::_120S),
620            61 => Ok(Self::_100S),
621            62 => Ok(Self::_60S),
622            63 => Ok(Self::_50S),
623            64 => Ok(Self::_30S),
624            65 => Ok(Self::_25S),
625            _ => Err(ConversionError::Range {
626                value: spd.to_string(),
627                type_name: "SyChipSpeed".into(),
628            }),
629        }
630    }
631}
632
633impl From<SyChipSpeed> for u8 {
634    fn from(spd: SyChipSpeed) -> Self {
635        match spd {
636            SyChipSpeed::_128T => 0,
637            SyChipSpeed::_128 => 1,
638            SyChipSpeed::_64T => 2,
639            SyChipSpeed::_128D => 3,
640            SyChipSpeed::_64 => 4,
641            SyChipSpeed::_32T => 5,
642            SyChipSpeed::_64D => 6,
643            SyChipSpeed::_32 => 7,
644            SyChipSpeed::_16T => 8,
645            SyChipSpeed::_32D => 9,
646            SyChipSpeed::_16 => 10,
647            SyChipSpeed::_8T => 11,
648            SyChipSpeed::_16D => 12,
649            SyChipSpeed::_8 => 13,
650            SyChipSpeed::_4T => 14,
651            SyChipSpeed::_8D => 15,
652            SyChipSpeed::_4 => 16,
653            SyChipSpeed::_2T => 17,
654            SyChipSpeed::_4D => 18,
655            SyChipSpeed::_2 => 19,
656            SyChipSpeed::_1T => 20,
657            SyChipSpeed::_2D => 21,
658            SyChipSpeed::_1 => 22,
659            SyChipSpeed::_1D => 23,
660            SyChipSpeed::_1_0Hz => 24,
661            SyChipSpeed::_1_56Hz => 25,
662            SyChipSpeed::_1_88Hz => 26,
663            SyChipSpeed::_2Hz => 27,
664            SyChipSpeed::_3_13Hz => 28,
665            SyChipSpeed::_3_75Hz => 29,
666            SyChipSpeed::_4Hz => 30,
667            SyChipSpeed::_5Hz => 31,
668            SyChipSpeed::_6_25Hz => 32,
669            SyChipSpeed::_7_5Hz => 33,
670            SyChipSpeed::_10Hz => 34,
671            SyChipSpeed::_12_5Hz => 35,
672            SyChipSpeed::_15Hz => 36,
673            SyChipSpeed::_20Hz => 37,
674            SyChipSpeed::_25Hz => 38,
675            SyChipSpeed::_30Hz => 39,
676            SyChipSpeed::_40Hz => 40,
677            SyChipSpeed::_50Hz => 41,
678            SyChipSpeed::_60Hz => 42,
679            SyChipSpeed::_75Hz => 43,
680            SyChipSpeed::_100Hz => 44,
681            SyChipSpeed::_120Hz => 45,
682            SyChipSpeed::_150Hz => 46,
683            SyChipSpeed::_180Hz => 47,
684            SyChipSpeed::_200Hz => 48,
685            SyChipSpeed::_240Hz => 49,
686            SyChipSpeed::_250Hz => 50,
687            SyChipSpeed::_300Hz => 51,
688            SyChipSpeed::_350Hz => 52,
689            SyChipSpeed::_360Hz => 53,
690            SyChipSpeed::_400Hz => 54,
691            SyChipSpeed::_420Hz => 55,
692            SyChipSpeed::_480Hz => 56,
693            SyChipSpeed::_240S => 57,
694            SyChipSpeed::_200S => 58,
695            SyChipSpeed::_150S => 59,
696            SyChipSpeed::_120S => 60,
697            SyChipSpeed::_100S => 61,
698            SyChipSpeed::_60S => 62,
699            SyChipSpeed::_50S => 63,
700            SyChipSpeed::_30S => 64,
701            SyChipSpeed::_25S => 65,
702        }
703    }
704}