Skip to content

Unpack signal for CAN FD messages #67

@Uight

Description

@Uight

If the dbc file contains CAN-FD messages that can be longer than 64 bit the unpack functions are not usable.
Also i think most can implementations work by giving you a byte array for the received data anyway (peak, innodisk, esd to name a few).

Therefor i adjusted the unpack signals method like this:

    /// <summary>
    /// Get start bit Little Endian
    /// </summary>
    private static byte GetStartBitLE(Signal signal, int messageByteCount = 8)
    {
        var startByte = (byte)(signal.StartBit / 8);
        return (byte)(8 * messageByteCount - (signal.Length + 8 * startByte + (8 * (startByte + 1) - (signal.StartBit + 1)) % 8));
    }

And then adjust the code from before to

    /// <summary>
    /// Function to unpack a signal from a CAN data message
    /// </summary>
    /// <param name="receiveMessage">The message data</param>
    /// <param name="signal">Signal containing dbc information</param>
    /// <returns>Returns a double value representing the unpacked signal</returns>
    private static double RxSignalUnpack(byte[] receiveMessage, Signal signal)
    {
        var bitMask = signal.BitMask();
        var startBit = signal.StartBit;
        
        if (!signal.Intel())
        {
            receiveMessage = receiveMessage.Reverse().ToArray();
            startBit = GetStartBitLE(signal, receiveMessage.Length);
        }
        
        // Unpack signal
        var receiveMessageBitArray = new BitArray(receiveMessage);
        receiveMessageBitArray.RightShift(startBit);
        receiveMessageBitArray.Length = 64; //Fill up to 64 if shorter or cut to length 64
        receiveMessageBitArray.And(new BitArray(BitConverter.GetBytes(bitMask)));
        
        var tempArray = new byte[8];
        receiveMessageBitArray.CopyTo(tempArray, 0);
        var iVal = BitConverter.ToInt64(tempArray, 0);

        // Manage sign bit (if signed)
        if (signal.ValueType == DbcValueType.Signed)
        {
            iVal -= ((iVal >> (signal.Length - 1)) != 0) ? (1L << signal.Length) : 0L;
        }
        else if (signal.ValueType == DbcValueType.IEEEFloat)
        {
            return (FloatConverter.AsFloatingPoint((int)iVal) * signal.Factor + signal.Offset);
        }
        else if (signal.ValueType == DbcValueType.IEEEDouble)
        {
            return (DoubleConverter.AsFloatingPoint(iVal) * signal.Factor + signal.Offset);
        }

        // Apply scaling
        return ((double)(iVal * (decimal)signal.Factor + (decimal)signal.Offset));
    }

this seems to work in a manual test.
i tried to reuse most of the code. Probably is also not the fasted solution but should work.

Problem with this is that the BitArray.ShiftRight() is not available in all targeted frameworks. For .net461 there is no solution for .netstandard2.0 you could upgrade the solution to .netstandard2.1.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingenhancementNew feature or request

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions