CanMessageHelper.h
Go to the documentation of this file.
00001 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
00002 
00003 // -- BEGIN LICENSE BLOCK ----------------------------------------------
00004 // This file is part of FZIs ic_workspace.
00005 //
00006 // This program is free software licensed under the LGPL
00007 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
00008 // You can find a copy of this license in LICENSE folder in the top
00009 // directory of the source code.
00010 //
00011 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany
00012 //
00013 // -- END LICENSE BLOCK ------------------------------------------------
00014 
00015 //----------------------------------------------------------------------
00022 //----------------------------------------------------------------------
00023 
00024 
00025 
00026 #ifndef _icl_hardware_can_CANMESSAGEHELPER_H
00027 #define _icl_hardware_can_CANMESSAGEHELPER_H
00028 
00029 #include "icl_core/BaseTypes.h"
00030 #include "icl_hardware_can/tCanMessage.h"
00031 #include "icl_hardware_can/tCanMatrixParser.h"
00032 
00033 namespace icl_hardware {
00034 namespace can {
00035 
00036 
00037 //implemented for data with max. length of 16
00038 //no sure what structure data with more than 16 bit has
00039 void constructCanMessageData(unsigned char *_data, int value, const unsigned int start_bit, const unsigned int signal_length, bool little_endian)
00040 {
00041   assert(start_bit > 0);
00042   assert(signal_length > 0);
00043   assert((start_bit-1)+signal_length <= 64);
00044 
00045   int64_t data = static_cast<int64_t>(value);
00046   int offset = 0;
00047 
00048   if (little_endian)
00049   {
00050     unsigned int number_of_bytes = static_cast<unsigned int>(((signal_length-1)/8))+1;
00051     int64_t tmp_data = 0;
00052 
00053     //change of byte position
00054     for (unsigned int i= 0; i < number_of_bytes; ++i)
00055     {
00056       tmp_data <<= 8;
00057       tmp_data |= (data & 0xFF);
00058       data >>= 8;
00059     }
00060     data = tmp_data;
00061 
00062     if (signal_length < 8)
00063     {
00064       offset =2*(start_bit%8 == 0? 1:start_bit%8)-8;
00065     }
00066   }
00067 
00068   //bring the data to its right position
00069   data <<= 64 - (start_bit-offset) - signal_length;
00070 
00071   //save data to provided adress
00072   for (int i=7; i >= 0; --i)
00073   {
00074     _data[i] = static_cast<unsigned char>(data & 0xFF);
00075     data >>= 8;
00076   }
00077 }
00078 
00079 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)
00080 {
00081   /*
00082    * The "raw value" of a signal is the value as it is transmitted
00083    * over the network. From cantools library
00084    */
00085   uint32_t rawValue   = 0;
00086 
00087   /*
00088    * compute some signal properties
00089    *
00090    * signal bit order:
00091    *
00092    *     7  6  5  4  3  2  1  0 offset
00093    *    bit
00094    * 0   7  6  5  4  3  2  1  0
00095    * 1  15 14 13 12 11 10  9  8
00096    * 2  23 22 21 20 19 18 17 16
00097    * 3  31 30 29 28 27 26 25 24
00098    * 4  39 38 37 36 35 34 33 32
00099    * 5  47 46 45 44 43 42 41 40
00100    * 6  55 54 53 52 51 50 49 48
00101    * 7  63 62 61 60 59 58 57 56
00102    * |
00103    * start_byte
00104    *
00105    * big endian place value exponent
00106    *                15 14 13 12   <- start_byte
00107    *    11 10  9  8  7  6  5  4
00108    *     3  2  1  0               <- end_byte
00109    *
00110    * little endian place value exponent
00111    *     3  2  1  0               <- start_byte
00112    *    11 10  9  8  7  6  5  4
00113    *                15 14 13 12   <- end_byte
00114    */
00115   uint8_t  bit_len      = signal_length;
00116   uint8_t  start_offset = (start_bit-1) & 7;
00117   uint8_t  start_byte   = (start_bit-1) / 8;
00118   uint8_t  data;
00119   int8_t  work_byte;
00120   uint8_t  shift;
00121 
00122   /* align signal into ulong32 */
00123   /* 0 = Big Endian, 1 = Little Endian */
00124   if(little_endian == false) { /* big endian */
00125     uint8_t  end_byte     = start_byte + (7 + bit_len - start_offset - 1)/8;
00126     uint8_t  end_offset   = (start_offset - bit_len + 1) & 7;
00127 
00128     /* loop over all source bytes from start_byte to end_byte */
00129     for(work_byte = start_byte; work_byte <= end_byte; work_byte++) {
00130 /* fetch source byte */
00131       data = message.data[work_byte];
00132 
00133 /* process source byte */
00134       if(work_byte == start_byte && start_offset != 7) {
00135   /* less that 8 bits in start byte? mask out unused bits */
00136         data &= (uint8_t)~0 >> (7 - start_offset);
00137         shift = start_offset + 1;
00138       } else {
00139         shift = 8; /* use all eight bits */
00140       }
00141       if(work_byte == end_byte && end_offset != 0) {
00142   /* less that 8 bits in end byte? shift out unused bits */
00143         data >>= end_offset;
00144         shift -= end_offset;
00145       }
00146 
00147 /* store processed byte */
00148       rawValue <<= shift; /* make room for shift bits */
00149       rawValue |= data;   /* insert new bits at low position */
00150     }
00151   } else {
00152     /* little endian - similar algorithm with reverse bit significance  */
00153     uint8_t  end_byte     = start_byte + (bit_len + start_offset - 1)/8;
00154     uint8_t  end_offset   = (start_offset + bit_len - 1) & 7;
00155 
00156     for(work_byte = end_byte; work_byte >= start_byte; work_byte--) {
00157       data = message.data[work_byte];
00158       if(work_byte == end_byte && end_offset != 7) {
00159         data &= (uint8_t)~0 >> (7 - end_offset);
00160         shift = end_offset + 1;
00161       } else {
00162         shift = 8;
00163       }
00164       if(work_byte == start_byte && start_offset != 0) {
00165         data >>= start_offset;
00166         shift -= start_offset;
00167       }
00168       rawValue <<= shift;
00169       rawValue |= data;
00170     }
00171   }
00172 
00173   double physicalValue;
00174 
00175   /* perform sign extension */
00176   if(signedness && (bit_len < 32)) {
00177     int32_t m = 1<< (bit_len-1);
00178     rawValue = ((int32_t)rawValue ^ m) - m;
00179   }
00180 
00181   /*
00182      * Factor, Offset and Physical Unit
00183      *
00184      * The "physical value" of a signal is the value of the physical
00185      * quantity (e.g. speed, rpm, temperature, etc.) that represents
00186      * the signal.
00187      * The signal's conversion formula (Factor, Offset) is used to
00188      * transform the raw value to a physical value or in the reverse
00189      * direction.
00190      * [Physical value] = ( [Raw value] * [Factor] ) + [Offset]
00191      */
00192   if(signedness) {
00193     physicalValue = (double)(int32_t)rawValue
00194         * factor + offset;
00195   } else {
00196     physicalValue = (double)        rawValue
00197         * factor + offset;
00198   }
00199   return physicalValue;
00200 }
00201 
00202 template <typename T>
00203 static bool parseCanMessage(const tCanMessage &message,
00204                             const unsigned int start_bit,
00205                             const unsigned int signal_length,
00206                             const T factor,
00207                             const T offset,
00208                             const T lower_border,
00209                             const T upper_border,
00210                             const bool little_endian,
00211                             const bool signedness,
00212                             T &data)
00213 {
00214   data = static_cast<T>(parseCanMessage(message, start_bit, signal_length, little_endian, signedness, factor, offset));
00215   if ( (data < lower_border) || (data > upper_border) )
00216   {
00217     return false;
00218   }
00219   return true;
00220 }
00221 
00222 template <typename T>
00223 static bool parseCanMessage(const tCanMessage &message,
00224                             const CanMatrixElement &matrix,
00225                             T &data)
00226 {
00227   data = static_cast<T>(parseCanMessage(message, matrix.start_bit, matrix.signal_length, matrix.little_endian, matrix.signedness, matrix.conversion, matrix.offset));
00228   if ( (data < matrix.lower_border) || (data > matrix.upper_border) )
00229   {
00230     return false;
00231   }
00232   return true;
00233 }
00234 
00235 }
00236 }
00237 
00238 #endif // _icl_hardware_can_CANMESSAGEHELPER_H


fzi_icl_can
Author(s):
autogenerated on Thu Jun 6 2019 20:26:01