-2

Using CAN communications with a DBC as database, there are two different ways of encoding integer signals to the 64bit (8 byte) message data: Intel and Motorola.
To convert the 8 byte of message data to the distinct signals, I first want to use a bitmask to "scope" only the interesting bits and afterwards do some shift operations to get the number the signal is representing.
Here I am only interested in the bitmask generation:
Intel (also known as little-endian) is pretty straight forward: you take the startbit and iterate up to startBit + length setting every bit in your 64bit mask to 1 that you come by:

uint64_t generateBitmask(Signal* signal) {
    uint64_t bitmask = 0;
    uint64_t one = 1;
    int startBit = signal->startbit;
    int endBit = startBit + signal->length;

    if(signal->byteOrder == INTEL) {
        for(int i = startBit; i < endBit; ++i)
        {
            bitmask |= (one << i);
        }
    }
    return bitmask;
}

With motorola (big-endian) based numbers it is a bit more complicated:
since the byteorder (NOT the bitorder) is swapped, the (according to the index) lowest byte might contain "gaps" on the upper bits while the highest (indexed) byte might have a "gaps" on the lower end of the byte (see signal MOTO_20 in image; bits 22/23 and 32/33 are not part of the signal although they are sourrounded by bits that are).

I am searching for a way to calculate this bitmask based on start bit and length of the respective signal. Please find two examples for motorola-based signals layed out in a CAN frame in the image below. Start bits and lengths are given under the image.

The bitmask is supposed to be corresponding to what a CAN bus message layout using a dbc would look like (image as example): every bit of a signal that is marked in the image is supposed to be 1:
example MOTO_20: 00000000 00000000 00000000 11111000 11111111 01111111 00000000 00000000
example MOTO_16: 00000000 00000000 00000000 00000000 00000000 00000000 11111111 11111111
The signal MOTO_20 has startbit 34 and length 20
The signal MOTO_16 has startbit 8 and length 16

Message Layout

mxcd
  • 1,954
  • 2
  • 25
  • 38
  • do you want us to write code for you? – Iłya Bursov Sep 26 '17 at 16:22
  • What is the question here? – scohe001 Sep 26 '17 at 16:25
  • @IlyaBursov no, but I want an an anser to my question of how to approach this problem with an efficient yet elegant algorithm. I tried it all day long and every time I ended up having multiple if/else clauses still missing one special case I didn't cover – mxcd Sep 26 '17 at 16:26
  • @scohe001 First line in the text: "I am searching for an algorithm..." Sorry if this isn't clear enough... I'll edit the question – mxcd Sep 26 '17 at 16:28
  • @maximilian009 your edit helps, but what is the ideal output of this function for some input? What's stopping you from hardcoding the bit mask? – scohe001 Sep 26 '17 at 17:50
  • @scohe001edited the question with two examples from the image hardcoding is not a good idea since the dbc that stores the can bus information can change and the bitmasks are supposed to be calculated out of these informations – mxcd Sep 26 '17 at 18:00
  • @maximilian009 Okay but how did you know where the 0's are? You say it should "corresponding to the image," do you want to make a program that uses CV to analyze an image input? What is the input that you're taking to get that output? Saying "it should match the picture" is all fine and dandy if you just want one output (for hardcoding) but it sounds like you don't. – scohe001 Sep 26 '17 at 18:04
  • @scohe001 It is supposed to be matching what is expected on CAN bus using a dbc that gives you start bit and length of the signal. The image is just a screenshot out of CANdb++ that shows you an example layout of a message – mxcd Sep 26 '17 at 18:10
  • @maximilian009 You say that the mask " might have a 'gaps.'" How do you know? How can you tell when your only input is start bit and signal length? – scohe001 Sep 26 '17 at 18:13
  • @scohe001 I know it because of the bytes the signal is filling. Let's say you have startbit 14: Then bits 14 and 15 are 1 and the rest of the byte is not because this is LSB. Reverse happens on the MSB – mxcd Sep 26 '17 at 18:24
  • @maximilian009 What does that have to do with Least or Most Significant Bit? I'm not sure what your logic is for these "gaps" – scohe001 Sep 26 '17 at 18:32
  • I figured it out by now... You take the bytes used and swap the order of them. the first can start somewhere in the middle, the last can end somewhere in the middle. When you swap the byte order back you have a gap inbetween – mxcd Sep 26 '17 at 18:56
  • And you still have not asked a question. `I am searching for ...` is not a question, you are just making a statement. If you have an actual question, the ask it - do not just imply the question, make sure that you have actually asked it outright. – JK. Sep 28 '17 at 08:25

1 Answers1

-1

I figured it out by focusing on the "gaps" that form within the bitfield and only putting a 1 in the result when there is no gap:

uint64_t generateBitmask(int startBit, int length) {
    uint64_t result = 0;
    int startByte = startBit / 8;
    int byteLength = length % 8 == 0 ? length / 8 : length / 8 + 1;
    int lowerGapStart = startBit % 8;
    int upperGapStart = (7 + (length - ((byteLength * 8) - (lowerGapStart)))) % 8;

    for (int i = startByte; i > startByte - byteLength; --i) {
        for (int j = 0; j < 8; ++j) {
            if (i == startByte && j < lowerGapStart ||
                i == startByte - byteLength + 1 && j > upperGapStart) {
                continue;
            } else {
                bitmask |= (one << (i * 8) + j);
            }
        }
    }
    return result;
}
mxcd
  • 1,954
  • 2
  • 25
  • 38