CanMessageHelper.h
Go to the documentation of this file.
1 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
2 
3 // -- BEGIN LICENSE BLOCK ----------------------------------------------
4 // This file is part of FZIs ic_workspace.
5 //
6 // This program is free software licensed under the LGPL
7 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
8 // You can find a copy of this license in LICENSE folder in the top
9 // directory of the source code.
10 //
11 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany
12 //
13 // -- END LICENSE BLOCK ------------------------------------------------
14 
15 //----------------------------------------------------------------------
22 //----------------------------------------------------------------------
23 
24 
25 
26 #ifndef _icl_hardware_can_CANMESSAGEHELPER_H
27 #define _icl_hardware_can_CANMESSAGEHELPER_H
28 
29 #include "icl_core/BaseTypes.h"
32 
33 namespace icl_hardware {
34 namespace can {
35 
36 
37 //implemented for data with max. length of 16
38 //no sure what structure data with more than 16 bit has
39 void constructCanMessageData(unsigned char *_data, int value, const unsigned int start_bit, const unsigned int signal_length, bool little_endian)
40 {
41  assert(start_bit > 0);
42  assert(signal_length > 0);
43  assert((start_bit-1)+signal_length <= 64);
44 
45  int64_t data = static_cast<int64_t>(value);
46  int offset = 0;
47 
48  if (little_endian)
49  {
50  unsigned int number_of_bytes = static_cast<unsigned int>(((signal_length-1)/8))+1;
51  int64_t tmp_data = 0;
52 
53  //change of byte position
54  for (unsigned int i= 0; i < number_of_bytes; ++i)
55  {
56  tmp_data <<= 8;
57  tmp_data |= (data & 0xFF);
58  data >>= 8;
59  }
60  data = tmp_data;
61 
62  if (signal_length < 8)
63  {
64  offset =2*(start_bit%8 == 0? 1:start_bit%8)-8;
65  }
66  }
67 
68  //bring the data to its right position
69  data <<= 64 - (start_bit-offset) - signal_length;
70 
71  //save data to provided adress
72  for (int i=7; i >= 0; --i)
73  {
74  _data[i] = static_cast<unsigned char>(data & 0xFF);
75  data >>= 8;
76  }
77 }
78 
79 double parseCanMessage(const tCanMessage &message, const unsigned int start_bit, const unsigned int signal_length, const bool little_endian, const bool signedness, const double factor, const double offset)
80 {
81  /*
82  * The "raw value" of a signal is the value as it is transmitted
83  * over the network. From cantools library
84  */
85  uint32_t rawValue = 0;
86 
87  /*
88  * compute some signal properties
89  *
90  * signal bit order:
91  *
92  * 7 6 5 4 3 2 1 0 offset
93  * bit
94  * 0 7 6 5 4 3 2 1 0
95  * 1 15 14 13 12 11 10 9 8
96  * 2 23 22 21 20 19 18 17 16
97  * 3 31 30 29 28 27 26 25 24
98  * 4 39 38 37 36 35 34 33 32
99  * 5 47 46 45 44 43 42 41 40
100  * 6 55 54 53 52 51 50 49 48
101  * 7 63 62 61 60 59 58 57 56
102  * |
103  * start_byte
104  *
105  * big endian place value exponent
106  * 15 14 13 12 <- start_byte
107  * 11 10 9 8 7 6 5 4
108  * 3 2 1 0 <- end_byte
109  *
110  * little endian place value exponent
111  * 3 2 1 0 <- start_byte
112  * 11 10 9 8 7 6 5 4
113  * 15 14 13 12 <- end_byte
114  */
115  uint8_t bit_len = signal_length;
116  uint8_t start_offset = (start_bit-1) & 7;
117  uint8_t start_byte = (start_bit-1) / 8;
118  uint8_t data;
119  int8_t work_byte;
120  uint8_t shift;
121 
122  /* align signal into ulong32 */
123  /* 0 = Big Endian, 1 = Little Endian */
124  if(little_endian == false) { /* big endian */
125  uint8_t end_byte = start_byte + (7 + bit_len - start_offset - 1)/8;
126  uint8_t end_offset = (start_offset - bit_len + 1) & 7;
127 
128  /* loop over all source bytes from start_byte to end_byte */
129  for(work_byte = start_byte; work_byte <= end_byte; work_byte++) {
130 /* fetch source byte */
131  data = message.data[work_byte];
132 
133 /* process source byte */
134  if(work_byte == start_byte && start_offset != 7) {
135  /* less that 8 bits in start byte? mask out unused bits */
136  data &= (uint8_t)~0 >> (7 - start_offset);
137  shift = start_offset + 1;
138  } else {
139  shift = 8; /* use all eight bits */
140  }
141  if(work_byte == end_byte && end_offset != 0) {
142  /* less that 8 bits in end byte? shift out unused bits */
143  data >>= end_offset;
144  shift -= end_offset;
145  }
146 
147 /* store processed byte */
148  rawValue <<= shift; /* make room for shift bits */
149  rawValue |= data; /* insert new bits at low position */
150  }
151  } else {
152  /* little endian - similar algorithm with reverse bit significance */
153  uint8_t end_byte = start_byte + (bit_len + start_offset - 1)/8;
154  uint8_t end_offset = (start_offset + bit_len - 1) & 7;
155 
156  for(work_byte = end_byte; work_byte >= start_byte; work_byte--) {
157  data = message.data[work_byte];
158  if(work_byte == end_byte && end_offset != 7) {
159  data &= (uint8_t)~0 >> (7 - end_offset);
160  shift = end_offset + 1;
161  } else {
162  shift = 8;
163  }
164  if(work_byte == start_byte && start_offset != 0) {
165  data >>= start_offset;
166  shift -= start_offset;
167  }
168  rawValue <<= shift;
169  rawValue |= data;
170  }
171  }
172 
173  double physicalValue;
174 
175  /* perform sign extension */
176  if(signedness && (bit_len < 32)) {
177  int32_t m = 1<< (bit_len-1);
178  rawValue = ((int32_t)rawValue ^ m) - m;
179  }
180 
181  /*
182  * Factor, Offset and Physical Unit
183  *
184  * The "physical value" of a signal is the value of the physical
185  * quantity (e.g. speed, rpm, temperature, etc.) that represents
186  * the signal.
187  * The signal's conversion formula (Factor, Offset) is used to
188  * transform the raw value to a physical value or in the reverse
189  * direction.
190  * [Physical value] = ( [Raw value] * [Factor] ) + [Offset]
191  */
192  if(signedness) {
193  physicalValue = (double)(int32_t)rawValue
194  * factor + offset;
195  } else {
196  physicalValue = (double) rawValue
197  * factor + offset;
198  }
199  return physicalValue;
200 }
201 
202 template <typename T>
203 static bool parseCanMessage(const tCanMessage &message,
204  const unsigned int start_bit,
205  const unsigned int signal_length,
206  const T factor,
207  const T offset,
208  const T lower_border,
209  const T upper_border,
210  const bool little_endian,
211  const bool signedness,
212  T &data)
213 {
214  data = static_cast<T>(parseCanMessage(message, start_bit, signal_length, little_endian, signedness, factor, offset));
215  if ( (data < lower_border) || (data > upper_border) )
216  {
217  return false;
218  }
219  return true;
220 }
221 
222 template <typename T>
223 static bool parseCanMessage(const tCanMessage &message,
224  const CanMatrixElement &matrix,
225  T &data)
226 {
227  data = static_cast<T>(parseCanMessage(message, matrix.start_bit, matrix.signal_length, matrix.little_endian, matrix.signedness, matrix.conversion, matrix.offset));
228  if ( (data < matrix.lower_border) || (data > matrix.upper_border) )
229  {
230  return false;
231  }
232  return true;
233 }
234 
235 }
236 }
237 
238 #endif // _icl_hardware_can_CANMESSAGEHELPER_H
signed int int32_t
unsigned int uint32_t
Implements a struct representing a can message.
Definition: tCanMessage.h:43
signed char int8_t
signed __int64 int64_t
This modul constructs a map of a can-mask-file the map can be request by getcanmatrix() ...
unsigned char uint8_t
Contains CAN driver interface functions.
void constructCanMessageData(unsigned char *_data, int value, const unsigned int start_bit, const unsigned int signal_length, bool little_endian)
double parseCanMessage(const tCanMessage &message, const unsigned int start_bit, const unsigned int signal_length, const bool little_endian, const bool signedness, const double factor, const double offset)


fzi_icl_can
Author(s):
autogenerated on Mon Jun 10 2019 13:17:02