Skip to content

Commit ea508db

Browse files
committed
Merge PR oxibus#17: Add decode and encode for Signal
2 parents 28368c6 + 4e629a9 commit ea508db

File tree

4 files changed

+207
-1
lines changed

4 files changed

+207
-1
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ travis-ci = { repository = "marcelbuesing/can-dbc", branch = "dev" }
1414
codecov = { repository = "marcelbuesing/can-dbc", branch = "dev", service = "github" }
1515

1616
[dependencies]
17-
derive-getters = "0.3"
17+
derive-getters = "0.5"
1818
nom = { version = "7.1", features = ["alloc"] }
19+
num = { version = "0.4", default-features = false }
1920
serde = { version = "1.0", optional = true }
2021
serde_derive = { version = "1.0", optional = true }
2122

src/extend/mod.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
mod signal;
2+
3+
use derive_getters::Getters;
4+
5+
/// DBC value
6+
#[derive(Debug, Clone, Getters)]
7+
pub struct Value {
8+
pub(crate) name: String,
9+
#[getter(rename = "raw_value")]
10+
#[getter(copy)]
11+
pub(crate) raw: u64,
12+
#[getter(copy)]
13+
pub(crate) offset: f64,
14+
#[getter(copy)]
15+
pub(crate) factor: f64,
16+
pub(crate) unit: String,
17+
}
18+
19+
unsafe impl Send for Value {}
20+
unsafe impl Sync for Value {}
21+
22+
impl Value {
23+
/// Get the value of the signal
24+
#[inline]
25+
pub fn value<T>(&self) -> T
26+
where
27+
T: num::NumCast + Default,
28+
{
29+
T::from(
30+
self.raw as f64 * self.factor + self.offset
31+
).unwrap_or_default()
32+
}
33+
/// Get the value and unit of the signal as a string
34+
#[inline]
35+
pub fn value_string<T>(&self) -> String
36+
where
37+
T: num::NumCast + Default + std::fmt::Display,
38+
{
39+
format!("{} {}", self.value::<T>(), self.unit)
40+
}
41+
}

src/extend/signal.rs

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
use crate::{ByteOrder, Signal, ValueType};
2+
use super::Value;
3+
4+
impl Signal {
5+
/// Decodes/Extracts a signal from the message data as a [`Value`]
6+
///
7+
/// # Params
8+
///
9+
/// * data: source data
10+
///
11+
/// # Return
12+
///
13+
/// [`Value`] if the size of signal is not zero
14+
pub fn decode_value(&self, data: &[u8]) -> Option<Value> {
15+
self.decode(data)
16+
.map(|v| Value {
17+
name: self.name.clone(),
18+
raw: v,
19+
offset: self.offset,
20+
factor: self.factor,
21+
unit: self.unit.clone(),
22+
})
23+
}
24+
25+
/// Decodes/Extracts a signal from the message data
26+
///
27+
/// # Params
28+
///
29+
/// * data: source data
30+
///
31+
/// # Return
32+
///
33+
/// Raw signal value if the size of signal is not zero
34+
pub fn decode(&self, data: &[u8]) -> Option<u64> {
35+
if self.signal_size == 0 {
36+
return None;
37+
}
38+
39+
let len = data.len();
40+
let mut result = 0;
41+
match self.byte_order {
42+
ByteOrder::LittleEndian => {
43+
let mut src_bit = self.start_bit as usize;
44+
let mut dst_bit = 0;
45+
for _ in 0..self.signal_size {
46+
/* copy bit */
47+
let index = src_bit / 8;
48+
if index >= len {
49+
return None;
50+
}
51+
if (data[index] & (1 << (src_bit % 8))) > 0 {
52+
result |= 1 << dst_bit;
53+
}
54+
55+
/* calculate next position */
56+
src_bit += 1;
57+
dst_bit += 1;
58+
}
59+
},
60+
ByteOrder::BigEndian => {
61+
let mut src_bit = self.start_bit as usize;
62+
let mut dst_bit = self.signal_size - 1;
63+
for _ in 0..self.signal_size {
64+
/* copy bit */
65+
let index = src_bit / 8;
66+
if index >= len {
67+
return None;
68+
}
69+
if (data[index] & (1 << (src_bit % 8))) > 0 {
70+
result |= 1 << dst_bit;
71+
}
72+
73+
/* calculate next position */
74+
if (src_bit % 8) == 0 {
75+
src_bit += 15;
76+
}
77+
else {
78+
src_bit -= 1;
79+
}
80+
dst_bit -= 1;
81+
}
82+
},
83+
}
84+
85+
match self.value_type() {
86+
ValueType::Signed => {
87+
if (result & (1 << (self.signal_size - 1))) > 0 {
88+
for i in self.signal_size..64 {
89+
result |= 1 << i;
90+
}
91+
}
92+
},
93+
ValueType::Unsigned => {}
94+
}
95+
96+
Some(result)
97+
}
98+
99+
/// Encodes a signal into the message data
100+
///
101+
/// # Params
102+
///
103+
/// * data: source data
104+
///
105+
/// * value: Raw signal value
106+
pub fn encode(&self, data: &mut Vec<u8>, value: u64) {
107+
if self.signal_size == 0 {
108+
return;
109+
}
110+
111+
match self.byte_order {
112+
ByteOrder::LittleEndian => {
113+
let mut src_bit = self.start_bit as usize;
114+
let mut dst_bit = 0;
115+
for _ in 0..self.signal_size {
116+
/* copy bit */
117+
let index = src_bit / 8;
118+
if index >= data.len() {
119+
data.resize(index + 1, 0);
120+
}
121+
if (value & 1 << dst_bit) > 0 {
122+
data[index] |= 1 << (src_bit % 8);
123+
}
124+
else {
125+
data[index] &= !(1 << (src_bit % 8));
126+
}
127+
128+
/* calculate next position */
129+
src_bit += 1;
130+
dst_bit += 1;
131+
}
132+
},
133+
ByteOrder::BigEndian => {
134+
let mut src_bit = self.start_bit as usize;
135+
let mut dst_bit = self.signal_size - 1;
136+
for _ in 0..self.signal_size {
137+
/* copy bit */
138+
let index = src_bit / 8;
139+
if index >= data.len() {
140+
data.resize(index + 1, 0);
141+
}
142+
if (value & 1 << dst_bit) > 0 {
143+
data[index] |= 1 << (dst_bit % 8);
144+
}
145+
else {
146+
data[index] &= !(1 << (src_bit % 8));
147+
}
148+
149+
/* calculate next position */
150+
if (src_bit % 8) == 0 {
151+
src_bit += 15;
152+
}
153+
else {
154+
src_bit -= 1;
155+
}
156+
dst_bit -= 1;
157+
}
158+
},
159+
}
160+
}
161+
}
162+

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ use std::convert::TryFrom;
4646
use derive_getters::Getters;
4747

4848
pub mod parser;
49+
mod extend;
50+
pub use extend::*;
4951

5052
#[cfg(test)]
5153
mod tests {

0 commit comments

Comments
 (0)