1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#![no_std]
extern crate bitfield;
extern crate byteorder;
extern crate num_traits;
pub mod driver;
pub mod master;
pub use master::Master;
#[derive(Debug)]
pub enum Error {
Timeout,
PhysicalBus,
Checksum,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct PID(u8);
impl PID {
pub fn from_id(id: u8) -> PID {
assert!(id < 64, "ID must be less than 64");
let p0 = (id & 0b10111).count_ones() as u8 & 0b1;
let p1 = ((id & 0b111010).count_ones() as u8 + 1) & 0b1;
PID(id | (p0 << 6u8) | (p1 << 7u8))
}
pub fn get(&self) -> u8 {
self.0
}
}
pub fn checksum(pid: PID, data: &[u8]) -> u8 {
let sum = data.iter().fold(pid.0 as u16, |sum, v| {
let sum = sum + *v as u16;
if sum >= 256 {
sum - 255
} else {
sum
}
});
!(sum as u8)
}
pub fn classic_checksum(data: &[u8]) -> u8 {
checksum(PID(0u8), data)
}
#[cfg(test)]
mod tests {
use super::*;
struct CheckSumTestData<'a> {
pid: PID,
data: &'a [u8],
checksum: u8,
}
#[test]
fn test_checksum() {
let test_data = [
CheckSumTestData {
pid: PID(0xDD),
data: &[0x01],
checksum: 0x21,
},
CheckSumTestData {
pid: PID(0x4A),
data: &[0x55, 0x93, 0xE5],
checksum: 0xE6,
},
CheckSumTestData {
pid: PID(0xBF),
data: &[0x40, 0xFF],
checksum: 0x00,
},
];
for d in &test_data {
assert_eq!(d.checksum, checksum(d.pid, d.data));
}
}
#[test]
fn test_pid_from_id() {
let test_data = [
(0, PID(0x80)),
(1, PID(0xC1)),
(2, PID(0x42)),
(25, PID(0x99)),
(27, PID(0x5B)),
(29, PID(0xDD)),
];
for d in &test_data {
assert_eq!(PID::from_id(d.0), d.1);
}
}
#[test]
#[should_panic]
fn test_pid_from_id_panic() {
PID::from_id(64);
}
}