Reading first and second 4 bits of a byte from a rotary switch

Hi Guys,

I have two 12 position rotary switches on my physical dash and I am sending their position over CAN from my Link G4x as the last and second last 4 bits of an 8 byte frame.
So starting bit 56 I have 4 bits sending the status of switch#1, and from bit 60, I have 4 bits sending the status of switch #2.
In the CAN monitor in RD, I can see the values transmitted perfectly, but I just can’t get the value tags properly working. No matter what I do, the two inputs are basically swapped and I can’t really get my head around why.
Here is a snippet from the CAN XML:

<frame id="1004:2,0,1" endianess="big">
  <value name="Link: Exhaust Pressure" offset="1" length="2"></value>
  <value name="Link: MAF Temp" offset="3" length="2" conversion="V-50"></value>
  <value name="Link: PreIC Temp" offset="5" length="2" conversion="V-50"></value>
  <value name="Link: RSW1 txt" offset="7" length="1" startbit="0" bitcount="4" enum="0:0-Ign adv 20,1:1-Ign adv -20,2:2-Ign adv -25,3:3-Ign adv -30,4:4-Ign adv -35,5:5-Ign adv -40,6:6-Ign adv -45,7:7-Ign adv -50,8:8,9:9,10:10,11:11"></value>
  <value name="Link: RSW1 nbr" startbit="56" bitcount="4"></value>
  <value name="Link: RSW2" offset="7" length="1" startbit="4" bitcount="4" conversion="V" enum="0:0-OFF,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,10:10,11:11"></value>
  <value name="Link: RSW2 nbr" startbit="60" bitcount="4"></value>
</frame>

If I try offset and startbit=0, I could probably argue about endianess, but when I omit the offset and strictly specify the startbit as 56 and the lenth as 4, why on earth is it reading the the value from bit60 to bit63?
And even more, if I specify startbit as 60 and bitcount as 4, how come it reads the 4 bits before the startbit?
Thanks a lot for the help in advance
Béla

When you are working on single byte, endianness makes no difference as bits are always arranged the same in single byte.

Try this (edit, fixed the bitwise AND)

<frame id="1004:2,0,1" endianess="big">
  <value name="Link: RSW1 txt" offset="7" length="1" conversion="V>>4" enum="..."></value>
  <value name="Link: RSW1 nbr" offset="7" length="1" conversion="V>>4"></value>
  <value name="Link: RSW2" offset="7" length="1" conversion="V &amp; 0xF" enum="..."></value>
  <value name="Link: RSW2 nbr" offset="7" length="1" conversion="V &amp; 0xF"></value>
</frame>

In above, I only operate on single byte so its simpler to understand.

Yeah, that’s what I thought too, but forexample, in the G4x even for single byte it has an effect as the start bit is going to be left or the right of the bit stream, depending on endianess.

Thanks a lot for the help.
I understand the approach here, but unfortunately the masking doesn’t work.
RSW1 works nicely even without masking though, but if I add the masking, it doesn’t.
I read in one of the forum posts that bitwise operators wont work with decimal, so I tried with 0xF, but that did not work either.

Also, could you explain why the startbit/bitcount approach doesn’t work? I found that to be used in the gm_ls_can.xml on your github, so I assume it should.

Thanks again
Béla

You are right, the bitwise AND in RSW1 is not necessary as we are working on single byte. I updated the example.

I did test this on simulator. Bitwise AND works with either decimal or hexadecimal. The startbit/bitcount approach works too, but in this case I feel its much simpler this way.

Give me an example, what is the hex value of that frames last byte (on CAN monitor), and what are the switch positions at that stage and expected values.

I can’t really give a screenshot of the CAN monitor (if that is what you were asking for) as the values are jumping around so much that you can only see barely which bits of the last byte are changing, but I can tell you they are changing the way they should.

So here are the specifics:

  • address 3EC; last (most right) byte of the frame.
  • first 4 bits are RSW1, the other 4 bits are RSW2 and their decimal values are just simply equal to the position of the switch. So if any of the switches are set position 3 forexample, then the value transmitted will be 0011 on their respective 4 bits.
  • Now since these are both transmitted on the same byte, the value (without any conversion) is treated as a single byte number, so if both switches are set to position 3, then the data transmitted is 00110011, which is 51 decimal if I am not mistaking, and with xml value tag with the masking, that is exactly the number displayed on “RSW2 nbr”. So the masking has no effect on the input values.

I also thought, to bitshift the byte to left and then right, so the upper 4 bit values are truncated when the overflow happens (as the value length is set to 1), but that is not working either as it simply converts into a 2 byte number and the bitshift to the left just increases the decimal value to 256, 257, … which then is shifted back to the right and we are back where we started.

So far the only way I could get RSW2 to work is with startbit=“56” bitcount=“4” but again that value in theory should be RSW1 and not RSW2. RSW2 should be startbit=“60” bitcount=“4”.

What is the CAN byte value when RSW1 is at value 1 and RSW2 is at value 3?

00010011 = 19

So RSW1 is in topmost 4 bits, and RSW2 is in lowest 4.

This is a correct way to read (edit, fixed the bitwise AND)

<frame id="1004:2,0,1" endianess="big">
  <value name="Link: RSW1 txt" offset="7" length="1" conversion="V>>4" enum="..."></value>
  <value name="Link: RSW1 nbr" offset="7" length="1" conversion="V>>4"></value>
  <value name="Link: RSW2" offset="7" length="1" conversion="V &amp; 0xF" enum="..."></value>
  <value name="Link: RSW2 nbr" offset="7" length="1" conversion="V &amp; 0xF"></value>
</frame>

I tried that already, even with 0x0F, but as I said, the masking does not work. If i do this for RSW2, it simply reads the whole byte and in the case you asked about it display 19, instead of 3.

Doh, my mistake. As & character is reserved in XML, you have to write it as &

So here is the correct version:

<frame id="1004:2,0,1" endianess="big">
  <value name="Link: RSW1 txt" offset="7" length="1" conversion="V>>4" enum="..."></value>
  <value name="Link: RSW1 nbr" offset="7" length="1" conversion="V>>4"></value>
  <value name="Link: RSW2" offset="7" length="1" conversion="V &amp; 0xF" enum="..."></value>
  <value name="Link: RSW2 nbr" offset="7" length="1" conversion="V &amp; 0xF"></value>
</frame>

ok, now we are talking! :slight_smile: :slight_smile: :slight_smile:
give me 10 mins and I’ll test.

Awesome this worked like charm.
THANKS A LOT!

screenshot: https://1drv.ms/u/s!Ale4oyMCOgLThZMKJkBKQXrAM2HZdg

Now, can we get back to the bit level addressing of the data? I am just curious why that doesn’t work with the startbit and bitcount the way I would expect.

So, why startbit=56 and bitcount=4 results in pulling data from the 2nd 4 bits (right) of the concerned byte and why startbit=60 and bitcount=4 pulls the data from the 1st 4 bits (left) of the concerned byte?

That is because of endianness. RealDash always runs on little endian machine. Now imagine big endian, 64 bit value in single CAN frame:

0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88

If value is specified in XML to be 64 bit value, its converted to little endian:

0x88 0x77 0x66 0x55 0x44 0x33 0x22 0x11

RealDash applies the startbit and bitcount to the ‘raw’ received bytes, but exception to this is when startbit or bitcount does not align to 8 bit boundaries. In that case, the startbit and bitcount is applied after endianness conversion.

Ok, thanks.
I am not saying I fully understand yet, but I’ll try to model it based on your explanation.