gondola_core/packets/
pdu_packet.rs

1// This file is part of gaps-online-software and published 
2// under the GPLv3 license
3
4use crate::prelude::*;
5
6#[derive(Debug, Copy, Clone)]
7#[cfg_attr(feature="pybindings", pyclass)]
8pub struct PduChannel {
9  vpower_acc  : i64,
10  vbus        : i32,
11  vsense      : i32,
12  vbus_avg    : i32,
13  vsense_avg  : i32,
14  vpower      : i32
15}
16
17impl PduChannel {
18  pub fn new() -> Self {
19    Self {
20      vpower_acc  : 0,
21      vbus        : 0,
22      vsense      : 0,
23      vbus_avg    : 0,
24      vsense_avg  : 0,
25      vpower      : 0
26    }
27  }
28}
29
30#[cfg(feature="pybindings")]
31#[pymethods]
32impl PduChannel {
33
34  #[getter]
35  fn get_vpower_acc(&self) -> i64  {
36    self.vpower_acc 
37  } 
38  #[getter] 
39  fn get_vbus(&self) -> i32 {
40    self.vbus 
41  }
42  #[getter] 
43  fn get_vsense(&self) -> i32 {
44    self.vsense 
45  }
46  #[getter]
47  fn get_vbus_avg(&self) -> i32 {
48    self.vbus_avg 
49  }
50  #[getter]
51  fn get_vsense_avg(&self) -> i32 {
52    self.vsense_avg 
53  }
54  #[getter]
55  fn get_vpower(&self) -> i32 {
56    self.vpower
57  }
58}
59
60#[cfg_attr(feature="pybindings", pyclass)]
61#[derive(Debug, Copy, Clone)]
62pub struct Pac1934 {
63  ctrl            : i32,
64  acc_count       : i32,
65  channels        : [PduChannel; 4],
66  // FIXME - this might not get de serialized 
67  // properly
68  channel_dis     : i32,
69  neg_pwr         : i32,
70  slow            : i32,
71  ctrl_act        : i32,
72  channel_dis_act : i32,
73  neg_pwr_act     : i32,
74  ctrl_lat        : i32,
75  channel_dis_lat : i32,
76  neg_pwr_lat     : i32,
77  pid             : i32,
78  mid             : i32,
79  rev             : i32,
80}
81
82impl Pac1934 {
83
84  pub fn new() -> Self {
85    Self {
86      ctrl            : 0,
87      acc_count       : 0,
88      channels        : [PduChannel::new(); 4],
89      channel_dis     : 0,
90      neg_pwr         : 0,
91      slow            : 0,
92      ctrl_act        : 0,
93      channel_dis_act : 0,
94      neg_pwr_act     : 0,
95      ctrl_lat        : 0,
96      channel_dis_lat : 0,
97      neg_pwr_lat     : 0,
98      pid             : 0,
99      mid             : 0,
100      rev             : 0,
101    }
102  }
103  
104  pub fn from_bytestream(stream: &Vec<u8>,
105                         pos: &mut usize)
106    -> Result<Self, SerializationError> {
107    let mut pac       = Pac1934::new();
108    // size of a packet is 88 
109    if stream.len() < 88 {
110      return Err(SerializationError::StreamTooShort);
111    }
112    pac.ctrl         = parse_u8(stream, pos) as i32; 
113    let acc_count_a  = parse_u8(stream, pos) as u64;
114    let acc_count_b  = parse_u8(stream, pos) as u64; 
115    let acc_count_c  = parse_u8(stream, pos) as u64; 
116    pac.acc_count    = (acc_count_a << 16 | acc_count_b << 8 | acc_count_c) as i32;
117    for ch in &mut pac.channels {
118      let vpower_acc_a = parse_u8(stream, pos) as u64;
119      let vpower_acc_b = parse_u8(stream, pos) as u64;
120      let vpower_acc_c = parse_u8(stream, pos) as u64;
121      let vpower_acc_d = parse_u8(stream, pos) as u64;
122      let vpower_acc_e = parse_u8(stream, pos) as u64;
123      let vpower_acc_f = parse_u8(stream, pos) as u64;
124      ch.vpower_acc    = (vpower_acc_a << 40 | vpower_acc_b << 32 | vpower_acc_c << 24 | vpower_acc_d << 16 | vpower_acc_e << 8 | vpower_acc_f) as i64;
125      let vbus_a       = parse_u8(stream, pos) as u64;
126      let vbus_b       = parse_u8(stream, pos) as u64;
127      ch.vbus          = (vbus_a << 8 | vbus_b) as i32;
128      let vsense_a     = parse_u8(stream, pos) as u64;
129      let vsense_b     = parse_u8(stream, pos) as u64;
130      ch.vsense        = (vsense_a << 8 | vsense_b) as i32; 
131      let vbus_avg_a   = parse_u8(stream, pos) as u64;
132      let vbus_avg_b   = parse_u8(stream, pos) as u64;
133      ch.vbus_avg      = (vbus_avg_a << 8 | vbus_avg_b) as i32;
134      let vsense_avg_a = parse_u8(stream, pos) as u64;
135      let vsense_avg_b = parse_u8(stream, pos) as u64;
136      ch.vsense_avg    = (vsense_avg_a | vsense_avg_b) as i32;
137      let vpower_a     = parse_u8(stream, pos) as u64;
138      let vpower_b     = parse_u8(stream, pos) as u64;
139      let vpower_c     = parse_u8(stream, pos) as u64; 
140      let vpower_d     = parse_u8(stream, pos) as u64;
141      ch.vpower        = (vpower_a << 24 | vpower_b << 16 | vpower_c << 8 | vpower_d) as i32;
142    }
143    pac.channel_dis     = parse_u8(stream, pos) as i32;
144    pac.neg_pwr         = parse_u8(stream, pos) as i32;
145    pac.slow            = parse_u8(stream, pos) as i32;
146    pac.ctrl_act        = parse_u8(stream, pos) as i32;
147    pac.channel_dis_act = parse_u8(stream, pos) as i32;
148    pac.neg_pwr_act     = parse_u8(stream, pos) as i32;
149    pac.ctrl_lat        = parse_u8(stream, pos) as i32;
150    pac.channel_dis_lat = parse_u8(stream, pos) as i32;
151    pac.neg_pwr_lat     = parse_u8(stream, pos) as i32;
152    pac.pid             = parse_u8(stream, pos) as i32;
153    pac.mid             = parse_u8(stream, pos) as i32;
154    pac.rev             = parse_u8(stream, pos) as i32;
155    Ok(pac)
156  }
157}
158
159#[cfg(feature="pybindings")]
160#[pymethods]
161impl Pac1934 {
162
163  #[getter]
164  fn get_ctrl(&self) -> i32 {
165    self.ctrl 
166  }
167
168  #[getter]
169  fn get_acc_count(&self) -> i32 {
170    self.acc_count 
171  }
172
173  #[getter]
174  fn get_channel_dis(&self) -> i32 {
175    self.channel_dis 
176  }
177
178  #[getter]
179  fn get_neg_pwr(&self) -> i32 {
180    self.neg_pwr 
181  }
182
183  #[getter]
184  fn get_slow(&self) -> i32 {
185    self.slow 
186  }
187
188  #[getter]
189  fn get_ctrl_act(&self) -> i32 {
190    self.ctrl_act 
191  }
192
193  #[getter]
194  fn get_channel_dis_act(&self) -> i32 {
195    self.channel_dis_act 
196  }
197
198  #[getter]
199  fn neg_pwr_act(&self) -> i32 {
200    self.neg_pwr_act 
201  }
202
203  #[getter]
204  fn get_ctrl_lat(&self) -> i32 {
205    self.ctrl_lat 
206  }
207
208  #[getter]
209  fn get_channel_dis_lat(&self) -> i32 {
210    self.channel_dis_lat
211  }
212
213  #[getter]
214  fn get_neg_pwr_lat(&self) -> i32 {
215    self.neg_pwr_lat 
216  }
217
218  #[getter]
219  fn get_pid(&self) -> i32 {
220    self.pid 
221  }
222
223  #[getter] 
224  fn get_mid(&self) -> i32 {
225    self.mid 
226  }
227  //      channels        : [PduChannel::new(); 4],
228}
229
230
231#[cfg_attr(feature="pybindings", pyclass)]
232#[derive(Debug, Copy, Clone)]
233pub struct PduHKPacket {
234  pub header           : TelemetryPacketHeader,
235  pub pdu_type         : i32,
236  pub pdu_id           : i32,
237  pub ads7828_voltages : [i32;8],
238  pub pacs             : [Pac1934;2],
239  pub vbat             : i32,
240  pub pdu_count        : i32,
241  pub error            : i32,
242}
243
244impl PduHKPacket {
245  
246  pub fn new() -> Self {
247    Self {
248      header           : TelemetryPacketHeader::new(),
249      pdu_type         : 0,
250      pdu_id           : 0,
251      ads7828_voltages : [0;8],
252      pacs             : [Pac1934::new();2],
253      vbat             : 0,
254      pdu_count        : 0,
255      error            : 0,
256    }
257  }
258
259  pub fn from_bytestream(stream: &Vec<u8>,
260                         pos: &mut usize)
261    -> Result<Self, SerializationError> {
262    let mut pdu       = PduHKPacket::new();
263    // size of a packet is 218 
264    if stream.len() < 218 {
265      return Err(SerializationError::StreamTooShort);
266    }
267    pdu.header   = TelemetryPacketHeader::from_bytestream(stream, pos)?;
268    pdu.pdu_type = parse_u8(stream, pos) as i32;
269    pdu.pdu_id   = parse_u8(stream, pos) as i32;
270    //         pdu_type = b(i); i += 1;
271//         pdu_id = b(i); i += 1;
272
273    Ok(pdu)
274  }
275}
276
277//impl Serialization for PduHKPacket {
278//}
279
280#[cfg(feature="pybindings")]
281#[pymethods]
282impl PduHKPacket {
283
284  #[getter]
285  fn get_header(&self) -> TelemetryPacketHeader {
286    self.header.clone()
287  }
288
289  #[getter]
290  fn get_pdu_type(&self) -> i32 {
291    self.pdu_type 
292  }
293
294  #[getter]
295  fn get_pdu_id(&self) -> i32 {
296    self.pdu_id 
297  }
298
299  #[getter]
300  fn get_vbat(&self) -> i32 {
301    self.vbat 
302  }
303
304  #[getter]
305  fn get_pdu_count(&self) -> i32 {
306    self.pdu_count 
307  }
308
309  #[getter] 
310  fn get_error(&self) -> i32 {
311    self.error
312  }
313  //ads7828_voltages : [i32;8],
314  //pacs             : [Pac1934;2],
315
316
317}
318
319//
320//namespace pdu
321//{
322//   struct pac_1934
323//   {
324//      int ctrl;
325//      int acc_count;
326//      struct channel
327//      {
328//         int64_t vpower_acc;
329//         int vbus;
330//         int vsense;
331//         int vbus_avg;
332//         int vsense_avg;
333//         int vpower;
334//      };
335//      std::array<channel, 4> channels;
336//      int channel_dis;
337//      int neg_pwr;
338//      int slow;
339//      int ctrl_act;
340//      int channel_dis_act;
341//      int neg_pwr_act;
342//      int ctrl_lat;
343//      int channel_dis_lat;
344//      int neg_pwr_lat;
345//      int pid;
346//      int mid;
347//      int rev;
348//
349//      template <typename T>
350//      int parse(T bytes, int i)
351//      {
352//         const int expected_size = 88;
353//         if((bytes.size() - i) < expected_size)
354//            return -1;
355//         int i_start = i;
356//         auto b = [&bytes](int i){return static_cast<uint64_t>(bytes[i]);};
357//         ctrl = b(i); i += 1;
358//         acc_count = (b(i) << 16) | (b(i+1) << 8) | b(i+2); i += 3;
359//         for(auto& ch : channels) {ch.vpower_acc = (b(i) << 40) | (b(i+1) << 32) | (b(i+2) << 24) | (b(i+3) << 16) | (b(i+4) << 8) | b(i+5); i += 6;}
360//         for(auto& ch : channels) {ch.vbus = (b(i) << 8) | b(i+1); i += 2;}
361//         for(auto& ch : channels) {ch.vsense = (b(i) << 8) | b(i+1); i += 2;}
362//         for(auto& ch : channels) {ch.vbus_avg = (b(i) << 8) | b(i+1); i += 2;}
363//         for(auto& ch : channels) {ch.vsense_avg = (b(i) << 8) | b(i+1); i += 2;}
364//         for(auto& ch : channels) {ch.vpower = (b(i) << 24) | (b(i+1) << 16) | (b(i+2) << 8) | b(i+3); i += 4;}
365//         channel_dis = b(i); i += 1;
366//         neg_pwr = b(i); i += 1;
367//         slow = b(i); i += 1;
368//         ctrl_act = b(i); i += 1;
369//         channel_dis_act = b(i); i += 1;
370//         neg_pwr_act = b(i); i += 1;
371//         ctrl_lat = b(i); i += 1;
372//         channel_dis_lat = b(i); i += 1;
373//         neg_pwr_lat = b(i); i += 1;
374//         pid = b(i); i += 1;
375//         mid = b(i); i += 1;
376//         rev = b(i); i += 1;
377//         assert((i - i_start) == expected_size);
378//         return expected_size;
379//
380//      }
381//   };
382//   struct hkp_packet
383//   {
384//      bfsw::header header;
385//      int pdu_type;
386//      int pdu_id;
387//      std::array<int,8> ads7828_voltages;
388//      std::array<pac_1934,2> pacs;
389//      int vbat;
390//      int pdu_count;
391//      int error;
392//      template <typename T> int unpack(const T& bytes, size_t i)
393//      {
394//         const int expected_size = 218;
395//         if((bytes.size() - i) < expected_size)
396//            return -1;
397//         size_t i_start {i};
398//         int rc;
399//         rc = header.unpack(bytes, i);
400//         if(rc < 0)
401//            return -100 + rc;
402//         else
403//            i += rc;
404//         auto b = [&bytes](int i){return static_cast<uint64_t>(bytes[i]);};
405//         pdu_type = b(i); i += 1;
406//         pdu_id = b(i); i += 1;
407//         for(auto& voltage : ads7828_voltages)
408//         {
409//            voltage = (b(i) << 8) | b(i+1); 
410//            i += 2;
411//         }
412//         for(auto& pac : pacs)
413//         {
414//            int rc = pac.parse(bytes,i);
415//            if(rc < 0)
416//            {
417//               spdlog::warn("hkp_packet::parse(): failed while parsing pac1934 data. rc = {}", rc);
418//               return -3;
419//            }
420//            else
421//            {
422//               i += rc;
423//            }
424//         }
425//         //NOTE: old code had vbat bytes little endian, but everything else is big endian.
426//         //from my testing with pdu, i know that this value wasn't reading properly
427//         //i assumed it was an issue with the board (wrong reistors or something)
428//         //but maybe it was just an endianness error.
429//         //vbat = (b(i) << 8) | b(i+1); i += 2;
430//         vbat = (b(i+1) << 8) | b(i); i += 2;
431//         i += 2;
432//         pdu_count = b(i); i += 1;
433//         error = b(i); i += 1;
434//	 i += 5; //ACK\r\n
435//         assert((i - i_start) == expected_size);
436//         return expected_size;
437//      }
438//      void print()
439//      {
440//         fmt::print("pdu_type: {}\n", pdu_type);
441//         fmt::print("pdu_id: {}\n", pdu_id);
442//
443//         for(auto& pac : pacs)
444//         {
445//            fmt::print("pac.pid: {}\n", pac.pid);
446//            fmt::print("pac.mid: {}\n", pac.mid);
447//            fmt::print("pac.rev: {}\n", pac.rev);
448//         }
449//         fmt::print("pdu_count: {}\n", pdu_count);
450//      }
451//   };
452
453