1#![allow(missing_docs)]
2use bilge::prelude::*;
3
4#[bitsize(8)]
6#[derive(DebugBits, FromBits, PartialEq, Clone, Copy)]
7pub(crate) struct Command {
8 pub page: PageNumber,
10
11 id: u3,
13
14 pub rw: CommandType,
16}
17
18impl Default for Command {
19 fn default() -> Self {
20 Self::from(0b0101_0000)
21 }
22}
23
24impl Command {
25 #[must_use]
27 pub fn with_page(mut self, page: PageNumber) -> Self {
28 self.set_page(page);
29 Self::from(self.value)
30 }
31
32 #[must_use]
34 pub fn with_rw(mut self, rw: CommandType) -> Self {
35 self.set_rw(rw);
36 Self::from(self.value)
37 }
38}
39
40#[bitsize(4)]
42#[derive(Debug, FromBits, PartialEq, PartialOrd)]
43pub(crate) enum PageNumber {
44 #[fallback]
46 Pg0,
47
48 Pg1,
50
51 Pg2,
53}
54
55#[bitsize(1)]
57#[derive(Debug, FromBits, PartialEq, PartialOrd)]
58pub(crate) enum CommandType {
59 Write,
61
62 Read,
64}
65
66#[derive(Debug, PartialEq, PartialOrd)]
68pub(crate) enum Register {
69 Pwm,
71
72 Scaling,
74
75 Configuration,
77
78 GlobalCurrentControl,
80
81 PullDownUpResistorSelection,
86
87 Open,
90
91 TemperatureStatus,
93
94 SpreadSpectrum,
96
97 Reset,
99}
100
101impl Register {
102 pub fn page(&self) -> PageNumber {
104 match *self {
105 Self::Pwm => PageNumber::Pg0,
106 Self::Scaling => PageNumber::Pg1,
107 _ => PageNumber::Pg2,
108 }
109 }
110}
111
112impl From<Register> for u8 {
113 fn from(reg: Register) -> Self {
114 match reg {
115 Register::Configuration => 0x00,
116 Register::Pwm | Register::Scaling | Register::GlobalCurrentControl => 0x01,
117 Register::PullDownUpResistorSelection => 0x02,
118 Register::Open => 0x03,
119 Register::TemperatureStatus => 0x24,
120 Register::SpreadSpectrum => 0x25,
121 Register::Reset => 0x2F,
122 }
123 }
124}
125
126#[bitsize(8)]
128#[derive(DebugBits, FromBits, PartialEq, Clone, Copy)]
129pub struct Configuration {
130 pub ssd: bool,
132
133 pub osde: Open,
135
136 reserved: u1,
137
138 pub sws: SwxSetting,
140}
141
142impl Default for Configuration {
143 fn default() -> Self {
144 Self::from(0b0000_1000)
153 }
154}
155
156impl Configuration {
157 #[must_use]
159 pub fn with_ssd(mut self, ssd: bool) -> Self {
160 self.set_ssd(ssd);
161 Self::from(self.value)
162 }
163
164 #[must_use]
166 pub fn with_osde(mut self, osde: Open) -> Self {
167 self.set_osde(osde);
168 Self::from(self.value)
169 }
170
171 #[must_use]
173 pub fn with_sws(mut self, sws: SwxSetting) -> Self {
174 self.set_sws(sws);
175 Self::from(self.value)
176 }
177}
178
179#[bitsize(2)]
181#[derive(Debug, FromBits, PartialEq, PartialOrd)]
182pub enum Open {
183 #[fallback]
185 Disabled,
186
187 EnableOpen,
189
190 EnableShort,
192}
193
194#[bitsize(4)]
196#[derive(Debug, FromBits, PartialEq, PartialOrd)]
197pub enum SwxSetting {
198 #[fallback]
200 Sw11,
201
202 Sw10,
204
205 Sw9,
207
208 Sw8,
210
211 Sw7,
213
214 Sw6,
216
217 Sw5,
219
220 Sw4,
222
223 Sw3,
225
226 Sw2,
228
229 None,
231}
232
233#[bitsize(8)]
235#[derive(DebugBits, FromBits, PartialEq, Clone, Copy)]
236pub struct GlobalCurrentControl(u8);
237impl Default for GlobalCurrentControl {
238 fn default() -> Self {
239 Self::from(0b0000_0000)
240 }
241}
242
243#[bitsize(8)]
245#[derive(DebugBits, FromBits, PartialEq, Clone, Copy)]
246pub struct PullDownUpResistorSelection {
247 pub cspur: Resistor,
249
250 reserved: u1,
251
252 pub swpdr: Resistor,
254
255 pub phc: bool,
257}
258
259impl Default for PullDownUpResistorSelection {
260 fn default() -> Self {
261 Self::from(0b0011_0011)
262 }
263}
264
265impl PullDownUpResistorSelection {
266 #[must_use]
268 pub fn with_cspur(mut self, cspur: Resistor) -> Self {
269 self.set_cspur(cspur);
270 Self::from(self.value)
271 }
272
273 #[must_use]
275 pub fn with_swpdr(mut self, swpdr: Resistor) -> Self {
276 self.set_swpdr(swpdr);
277 Self::from(self.value)
278 }
279
280 #[must_use]
282 pub fn with_phc(mut self, phc: bool) -> Self {
283 self.set_phc(phc);
284 Self::from(self.value)
285 }
286}
287
288#[bitsize(3)]
290#[derive(Debug, FromBits, PartialEq, PartialOrd)]
291pub enum Resistor {
292 None,
294
295 R0_5kOffOnly,
297
298 R1_0kOffOnly,
300
301 R2_0kOffOnly,
303
304 R1_0k,
306
307 R2_0k,
309
310 R4_0k,
312
313 R8_0k,
315}
316
317#[bitsize(8)]
319#[derive(DebugBits, FromBits, PartialEq, Clone, Copy)]
320pub struct TemperatureStatus {
321 pub trof: ThermalRollOff,
323
324 pub ts: TemperaturePoint,
326
327 reserved: u4,
328}
329
330impl Default for TemperatureStatus {
331 fn default() -> Self {
332 Self::from(0b0000_0000)
333 }
334}
335
336impl TemperatureStatus {
337 #[must_use]
339 pub fn with_trof(mut self, trof: ThermalRollOff) -> Self {
340 self.set_trof(trof);
341 Self::from(self.value)
342 }
343
344 #[must_use]
346 pub fn with_ts(mut self, ts: TemperaturePoint) -> Self {
347 self.set_ts(ts);
348 Self::from(self.value)
349 }
350}
351
352#[bitsize(2)]
354#[derive(Debug, FromBits, PartialEq, PartialOrd)]
355pub enum ThermalRollOff {
356 P100,
358
359 P75,
361
362 P55,
364
365 P30,
367}
368
369#[bitsize(2)]
371#[derive(Debug, FromBits, PartialEq, PartialOrd)]
372pub enum TemperaturePoint {
373 D140,
375
376 D120,
378
379 D100,
381
382 D90,
384}
385
386#[bitsize(8)]
388#[derive(DebugBits, FromBits, PartialEq, Clone, Copy)]
389pub struct SpreadSpectrum {
390 pub clt: CycleTime,
392
393 pub rng: Range,
395
396 pub ssp: bool,
398
399 reserved: u1,
400
401 pub sync: Sync,
403}
404
405impl Default for SpreadSpectrum {
406 fn default() -> Self {
407 Self::from(0b0000_0000)
408 }
409}
410
411impl SpreadSpectrum {
412 #[must_use]
414 pub fn with_clt(mut self, clt: CycleTime) -> Self {
415 self.set_clt(clt);
416 Self::from(self.value)
417 }
418
419 #[must_use]
421 pub fn with_rng(mut self, rng: Range) -> Self {
422 self.set_rng(rng);
423 Self::from(self.value)
424 }
425
426 #[must_use]
428 pub fn with_ssp(mut self, ssp: bool) -> Self {
429 self.set_ssp(ssp);
430 Self::from(self.value)
431 }
432
433 #[must_use]
435 pub fn with_sync(mut self, sync: Sync) -> Self {
436 self.set_sync(sync);
437 Self::from(self.value)
438 }
439}
440
441#[bitsize(2)]
443#[derive(Debug, FromBits, PartialEq, PartialOrd)]
444pub enum CycleTime {
445 U1980,
447
448 U1200,
450
451 U820,
453
454 U660,
456}
457
458#[bitsize(2)]
460#[derive(Debug, FromBits, PartialEq, PartialOrd)]
461pub enum Range {
462 P5,
464
465 P15,
467
468 P24,
470
471 P34,
473}
474
475#[bitsize(2)]
477#[derive(Debug, FromBits, PartialEq, PartialOrd)]
478pub enum Sync {
479 #[fallback]
481 Disabled,
482
483 Slave = 0b10,
485
486 Master,
488}
489
490#[cfg(test)]
491mod tests {
492 use super::*;
493
494 #[test]
495 fn default_command() {
496 let cmd = Command::default();
497 assert_eq!(cmd.value, 0x50);
498 }
499
500 #[test]
501 fn modify_page() {
502 let cmd = Command::default().with_page(PageNumber::Pg1);
503 assert_eq!(cmd.value, 0x51);
504 }
505
506 #[test]
507 fn modify_rw() {
508 let cmd = Command::default().with_rw(CommandType::Write);
509 assert_eq!(cmd.value, 0x50);
510 }
511
512 #[test]
513 fn default_configuration() {
514 let cfg = Configuration::default();
515 assert_eq!(cfg.value, 0x8);
516 }
517
518 #[test]
519 fn modify_ssd() {
520 let cfg = Configuration::default().with_ssd(true);
521 assert_eq!(cfg.value, 0x9);
522 }
523
524 #[test]
525 fn modify_osde() {
526 let cfg = Configuration::default().with_osde(Open::EnableShort);
527 assert_eq!(cfg.value, 0xC);
528 }
529
530 #[test]
531 fn modify_sws() {
532 let cfg = Configuration::default().with_sws(SwxSetting::Sw5);
533 assert_eq!(cfg.value, 0x68);
534 }
535
536 #[test]
537 fn default_pur_pdr() {
538 let pur_pdr = PullDownUpResistorSelection::default();
539 assert_eq!(pur_pdr.value, 0x33);
540 }
541
542 #[test]
543 fn modify_cspur() {
544 let pur_pdr = PullDownUpResistorSelection::default().with_cspur(Resistor::R2_0k);
545 assert_eq!(pur_pdr.value, 0x35);
546 }
547
548 #[test]
549 fn modify_swpdr() {
550 let pur_pdr = PullDownUpResistorSelection::default().with_swpdr(Resistor::R8_0k);
551 assert_eq!(pur_pdr.value, 0x73);
552 }
553
554 #[test]
555 fn default_temperature() {
556 let temperature = TemperatureStatus::default();
557 assert_eq!(temperature.value, 0x0);
558 }
559
560 #[test]
561 fn modify_trof() {
562 let temperature = TemperatureStatus::default().with_trof(ThermalRollOff::P55);
563 assert_eq!(temperature.value, 0x2);
564 }
565
566 #[test]
567 fn modify_ts() {
568 let temperature = TemperatureStatus::default().with_ts(TemperaturePoint::D120);
569 assert_eq!(temperature.value, 0x4);
570 }
571
572 #[test]
573 fn default_spread_spectrum() {
574 let spread_spectrum = SpreadSpectrum::default();
575 assert_eq!(spread_spectrum.value, 0x0);
576 }
577
578 #[test]
579 fn modify_clt() {
580 let spread_spectrum = SpreadSpectrum::default().with_clt(CycleTime::U660);
581 assert_eq!(spread_spectrum.value, 0x3);
582 }
583
584 #[test]
585 fn modify_rng() {
586 let spread_spectrum = SpreadSpectrum::default().with_rng(Range::P15);
587 assert_eq!(spread_spectrum.value, 0x4);
588 }
589
590 #[test]
591 fn modify_ssp() {
592 let spread_spectrum = SpreadSpectrum::default().with_ssp(true);
593 assert_eq!(spread_spectrum.value, 0x10);
594 }
595
596 #[test]
597 fn modify_sync() {
598 let spread_spectrum = SpreadSpectrum::default().with_sync(Sync::Master);
599 assert_eq!(spread_spectrum.value, 0xC0);
600 }
601}