Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse Titan » Decoding J1939 name fails(decoding integer & bitstring records)
Decoding J1939 name fails [message #1828590] Sat, 13 June 2020 19:55 Go to next message
Michael Josenhans is currently offline Michael JosenhansFriend
Messages: 99
Registered: February 2016
Member
I try to decode the J1939 name octetstring.

See https://www.kvaser.com/about-can/higher-layer-protocols/j1939-introduction/, search for table 3.

Byte number in CAN message          Contents/Meaning
0                                   Identity number, LSB
1                                   Identity number
2   Bits 0-4:                       Identity number, MSB
    Bits 5-7:                       Manufacturer code, LSB
3                                   Manufacturer code, MSB
4   Bits 0-2:                       ECU instance
    Bits 3-7:                       Function instance
5                                   Function
6   Bit 0:                          Reserved bit
    Bits 1-7:                       Vehicle system
7   Bits 0-3:                       Vehicle system instance
    Bits 4-6:                       Industry group
    Bit 7:                          Arbitrary address bit


Please note that byte 0 to 7 are reveresed, byte 0 contains LSB.

I have tried 3 ways:


    1. Using encoding as bitstrings
    2. Using encoding as bitstrings and integers
    3. Using encoding as integers (preferred solution)


All fail. Using bitstring generates wrong data, while using integers (optionally with 1 Bit bitstrings) generates dynamic runtime errors because of missing data.

// This function reverses byte 0 to 7
function f_reverse_j1939_name(in J1939_NAME p_j1939_name) 
//runs on PTC_isobus_CT 
return J1939_NAME{
  var J1939_NAME v_j1939_name_reverse := 
  
  p_j1939_name[7]& p_j1939_name[6]& p_j1939_name[5]&
  p_j1939_name[4]& p_j1939_name[3]& p_j1939_name[2]& 
  p_j1939_name[1]& p_j1939_name[0];
  return v_j1939_name_reverse
}

testcase tc_dec_name_1() 
{

  var J1939_NAME j1939_name_reverse, j1939_name
  
  j1939_name_reverse := '3102032E003D0080'O
  
  j1939_name := f_reverse_j1939_name(j1939_name_reverse)

  log("j1939 name reverse:-------------------------")
  log(j1939_name_reverse)
  log("j1939 name----------------------------------")
  log(j1939_name)
  log("--------------------------------------------")
  log(f_decode_J1939_name(j1939_name))
  log("--------------------------------------------")
}



external function f_encode_J1939_name(in J1939_NAME_RECORD pdu) return octetstring 
with { extension "prototype(convert) encode(RAW)" }
external function f_decode_J1939_name(in octetstring data) return J1939_NAME_RECORD
with { extension "prototype(convert) decode(RAW)" }

type record J1939_NAME_RECORD{
  J1939_ARBITRARY_ADDRESS_BIT		arbitraryAddresssBit,  
  J1939_INDUSTRY_GROUP				industryGroup,
  J1939_VEHICLE_SYSTEM_INSTANCE	    vehicleSystemInstance,
  J1939_VEHICLE_SYSTEM				vehicleSystem,
  J1939_RESERVED                    reserved,
  J1939_FUNCTION					function_,
  J1939_FUNCTION_INSTANCE			functionInstance,
  J1939_ECU_INSTANCE				ecuInstance,
  J1939_MANUFACTURER_CODE           manufacturerCode,
  J1939_IDENTITY_NUMBER				identityNumber
} with { variant "FIELDORDER(msb)" }

// 1. Encoding as pure bitstrings
// to test uncomment this section and comment the other sections
//type	BIT1	J1939_ARBITRARY_ADDRESS_BIT
//type	BIT3	J1939_INDUSTRY_GROUP
//type	BIT4	J1939_VEHICLE_SYSTEM_INSTANCE
//type	BIT7	J1939_VEHICLE_SYSTEM
//type	BIT1	J1939_RESERVED
//type	BIT8	J1939_FUNCTION
//type	BIT5	J1939_FUNCTION_INSTANCE
//type	BIT3	J1939_ECU_INSTANCE
//type	BIT11	J1939_MANUFACTURER_CODE
//type	BIT21	J1939_IDENTITY_NUMBER
//type bitstring BIT21 length(21) with { variant "FIELDLENGTH(21)" };


// 2. Encoding as integers and bitstrings
// to test uncomment this section and comment the other sections
//type	BIT1		J1939_ARBITRARY_ADDRESS_BIT
//type	INT3BIT		J1939_INDUSTRY_GROUP
//type	INT4BIT		J1939_VEHICLE_SYSTEM_INSTANCE
//type	INT7BIT		J1939_VEHICLE_SYSTEM
//type	BIT1		J1939_RESERVED
//type	INT8BIT		J1939_FUNCTION
//type	INT5BIT		J1939_FUNCTION_INSTANCE
//type	INT3BIT		J1939_ECU_INSTANCE
//type	INT11BIT	J1939_MANUFACTURER_CODE
//type	INT21BIT	J1939_IDENTITY_NUMBER


// 3. Encoding as pure integers
// to test uncomment this section and comment the other sections
type	INT1BIT		J1939_ARBITRARY_ADDRESS_BIT
type	INT3BIT		J1939_INDUSTRY_GROUP
type	INT4BIT		J1939_VEHICLE_SYSTEM_INSTANCE
type	INT7BIT		J1939_VEHICLE_SYSTEM
type	INT1BIT		J1939_RESERVED
type	INT8BIT		J1939_FUNCTION
type	INT5BIT		J1939_FUNCTION_INSTANCE
type	INT3BIT		J1939_ECU_INSTANCE
type	INT11BIT	J1939_MANUFACTURER_CODE
type	INT21BIT	J1939_IDENTITY_NUMBER

type integer INT1BIT 	(0..1)			// 2^1-1
type integer INT3BIT 	(0..7)			// 2^3-1
type integer INT4BIT 	(0..15)			// 2^4-1
type integer INT5BIT 	(0..31)			// 2^5-1
type integer INT7BIT	(0..127)		// 2^7-1
type integer INT8BIT 	(0..255)		// 2^8-1
type integer INT11BIT 	(0..2047)		// 2^11-1
type integer INT21BIT 	(0..2097151)	// 2^21-1


Results of 1. (pure bitstrings)
21:49:09.293006 mtc USER Isobustest.ttcn:1035(testcase:tc_dec_name_1) j1939 name reverse:-------------------------
21:49:09.293036 mtc USER Isobustest.ttcn:1036(testcase:tc_dec_name_1) '3102032E003D0080'O
21:49:09.293090 mtc USER Isobustest.ttcn:1037(testcase:tc_dec_name_1) j1939 name----------------------------------
21:49:09.293127 mtc USER Isobustest.ttcn:1038(testcase:tc_dec_name_1) '80003D002E030231'O
21:49:09.293170 mtc USER Isobustest.ttcn:1039(testcase:tc_dec_name_1) --------------------------------------------
21:49:09.293211 mtc DEBUG Isobustest.ttcn:1040(testcase:tc_dec_name_1) f_decode_J1939_name(): Stream before decoding: '80003D002E030231'O
21:49:09.293263 mtc DEBUG Isobustest.ttcn:1040(testcase:tc_dec_name_1) f_decode_J1939_name(): Decoded @J1939.J1939_NAME_RECORD: { arbitraryAddresssBit := '1'B, industryGroup := '000'B, vehicleSystemInstance := '0000'B, vehicleSystem := '0000000'B, reserved := '0'B, function_ := '00111101'B, functionInstance := '00000'B, ecuInstance := '000'B, manufacturerCode := '00000101110'B, identityNumber := '001100010000001000011'B }
21:49:09.293205 mtc USER Isobustest.ttcn:1040(testcase:tc_dec_name_1) { arbitraryAddresssBit := '1'B, industryGroup := '000'B, vehicleSystemInstance := '0000'B, vehicleSystem := '0000000'B, reserved := '0'B, function_ := '00111101'B, functionInstance := '00000'B, ecuInstance := '000'B, manufacturerCode := '00000101110'B, identityNumber := '001100010000001000011'B }
21:49:09.293397 mtc USER Isobustest.ttcn:1041(testcase:tc_dec_name_1) --------------------------------------------

According to my understanding, the
identityNumber:= '001100010000001000011'B
is equal to '62043'O, which does not match with the names-octetstring. I would be expecting the identityNumber := '000110000001000110001'B wich is '30231'O.

As far as I could see, all other fields than the 11-bit manufacturerCode and 21-bit wide identityNumber seem to be ok. The identical error seems to exist in the decoder and encoder, as encoding the decoded octetstring provides the initial octetstring.


Results of 2. (integers and bitstrings)
21:36:42.900486 mtc PARALLEL Isobustest.ttcn:1026(testcase:tc_dec_name_1) Component type Isobustest.MTC_CT was initialized.
21:36:42.900547 mtc USER Isobustest.ttcn:1035(testcase:tc_dec_name_1) j1939 name reverse:-------------------------
21:36:42.900594 mtc USER Isobustest.ttcn:1036(testcase:tc_dec_name_1) '3102032E003D0080'O
21:36:42.900669 mtc USER Isobustest.ttcn:1037(testcase:tc_dec_name_1) j1939 name----------------------------------
21:36:42.900712 mtc USER Isobustest.ttcn:1038(testcase:tc_dec_name_1) '80003D002E030231'O
21:36:42.900770 mtc USER Isobustest.ttcn:1039(testcase:tc_dec_name_1) --------------------------------------------
21:36:42.900818 mtc DEBUG Isobustest.ttcn:1040(testcase:tc_dec_name_1) f_decode_J1939_name(): Stream before decoding: '80003D002E030231'O
21:36:42.900901 mtc ERROR Isobustest.ttcn:1040(testcase:tc_dec_name_1) Dynamic test case error: While RAW-decoding type '@J1939.J1939_NAME_RECORD': There are not enough bits in the buffer to decode type @J1939.J1939_NAME_RECORD.identityNumber (needed: 8, found: 6).
21:36:42.900969 mtc VERDICTOP Isobustest.ttcn:1040(testcase:tc_dec_name_1) setverdict(error): none -> error


Results of 3. (pure integers)
21:32:57.545204 mtc PARALLEL Isobustest.ttcn:1026(testcase:tc_dec_name_1) Component type Isobustest.MTC_CT was initialized.
21:32:57.545276 mtc USER Isobustest.ttcn:1035(testcase:tc_dec_name_1) j1939 name reverse:-------------------------
21:32:57.545325 mtc USER Isobustest.ttcn:1036(testcase:tc_dec_name_1) '3102032E003D0080'O
21:32:57.545392 mtc USER Isobustest.ttcn:1037(testcase:tc_dec_name_1) j1939 name----------------------------------
21:32:57.545426 mtc USER Isobustest.ttcn:1038(testcase:tc_dec_name_1) '80003D002E030231'O
21:32:57.545470 mtc USER Isobustest.ttcn:1039(testcase:tc_dec_name_1) --------------------------------------------
21:32:57.545515 mtc DEBUG Isobustest.ttcn:1040(testcase:tc_dec_name_1) f_decode_J1939_name(): Stream before decoding: '80003D002E030231'O
21:32:57.545571 mtc ERROR Isobustest.ttcn:1040(testcase:tc_dec_name_1) Dynamic test case error: While RAW-decoding type '@J1939.J1939_NAME_RECORD': There are not enough bits in the buffer to decode type @J1939.J1939_NAME_RECORD.manufacturerCode (needed: 8, found: 0).
21:32:57.545602 mtc VERDICTOP Isobustest.ttcn:1040(testcase:tc_dec_name_1) setverdict(error): none -> error


Attached are the main files (containg other content to be deleted) for testing.
  • Attachment: J1939.ttcn
    (Size: 3.78KB, Downloaded 73 times)
  • Attachment: Isobustest.ttcn
    (Size: 39.28KB, Downloaded 65 times)

[Updated on: Tue, 16 June 2020 08:52]

Report message to a moderator

Re: Decoding J1939 name fails [message #1828668 is a reply to message #1828590] Tue, 16 June 2020 09:09 Go to previous messageGo to next message
Michael Josenhans is currently offline Michael JosenhansFriend
Messages: 99
Registered: February 2016
Member
For way 1, I have tried it with bitstring values not equal to zero in order to see, which bitstrings are decoded correctly:

Name reverse:
3102032E193D0B93


Name:
930B3D192E030231


Name decodes according to gnome calculator "Taschenrechner" to bitstring:
1001001100001011001111010001100100101110000000110000001000110001

However the titan decoder decodes to:
{ arbitraryAddresssBit := '1'B, industryGroup := '001'B, vehicleSystemInstance := '0011'B, vehicleSystem := '0000101'B, reserved := '1'B, function_ := '00111101'B, functionInstance := '00011'B, ecuInstance := '001'B, manufacturerCode := '00000101110'B, identityNumber := '001100010000001000011'B }

Which corresponds to:
1001001100001011001111010001100100000101110001100010000001000011


Here it is possible to see, that only the bitstring fields manufacturerCode and identityNumber are decoded wrongly.

The other fields, which are all bitstring with less than 9-bit are decoded correctly. Thus I would guess that the decoding/alignment of bitstrings with more than 1-byte is incorrect in the titan bitstring encoder and decoder.

Re: Decoding J1939 name fails [message #1828755 is a reply to message #1828590] Thu, 18 June 2020 06:46 Go to previous messageGo to next message
Gábor Szalai is currently offline Gábor SzalaiFriend
Messages: 133
Registered: December 2015
Senior Member
Pure integers:
The filed length should be specified for integer because the length is not calculated automatically:

type integer INT1BIT 	(0..1) with { variant "FIELDLENGTH(1)"}			// 2^1-1
type integer INT3BIT 	(0..7)with { variant "FIELDLENGTH(3)"}			// 2^3-1
....


If the given field spawn more than one octet, the BYTEORDER attribute determines, which part of the field is in which octet:

manufacturerCode:

...aaa
bbbbbbbb

can be decoded as:
aaabbbbbbbb


or

bbbbbbbbaaa

depending on the BYTEODER attribute.
Try
type bitstring BIT21 length(21) with { variant "FIELDLENGTH(21); BYTEORDER(last)" };
or
type bitstring BIT21 length(21) with { variant "FIELDLENGTH(21); BYTEORDER(first)" };


Re: Decoding J1939 name fails [message #1828765 is a reply to message #1828755] Thu, 18 June 2020 09:02 Go to previous messageGo to next message
Michael Josenhans is currently offline Michael JosenhansFriend
Messages: 99
Registered: February 2016
Member
Yes. The following works:

external function f_encode_J1939_name(in J1939_NAME_RECORD pdu) return octetstring 
with { extension "prototype(convert) encode(RAW)" }
external function f_decode_J1939_name(in octetstring data) return J1939_NAME_RECORD
with { extension "prototype(convert) decode(RAW)" }

type record J1939_NAME_RECORD{
  J1939_ARBITRARY_ADDRESS_BIT       arbitraryAddresssBit,  
  J1939_INDUSTRY_GROUP              industryGroup,
  J1939_VEHICLE_SYSTEM_INSTANCE     vehicleSystemInstance,
  J1939_VEHICLE_SYSTEM              vehicleSystem,
  J1939_RESERVED                    reserved,
  J1939_FUNCTION                    function_,
  J1939_FUNCTION_INSTANCE           functionInstance,
  J1939_ECU_INSTANCE                ecuInstance,
  J1939_MANUFACTURER_CODE           manufacturerCode,
  J1939_IDENTITY_NUMBER             identityNumber
} with { variant "FIELDORDER(msb)" }

type	INT1BIT		J1939_ARBITRARY_ADDRESS_BIT
type	INT3BIT		J1939_INDUSTRY_GROUP
type	INT4BIT		J1939_VEHICLE_SYSTEM_INSTANCE
type	INT7BIT		J1939_VEHICLE_SYSTEM
type	INT1BIT		J1939_RESERVED
type	INT8BIT		J1939_FUNCTION
type	INT5BIT		J1939_FUNCTION_INSTANCE
type	INT3BIT		J1939_ECU_INSTANCE
type	INT11BIT	J1939_MANUFACTURER_CODE
type	INT21BIT	J1939_IDENTITY_NUMBER

type integer INT1BIT 	(0..1)          with { variant "FIELDLENGTH(1)"}                   // 2^1-1
type integer INT3BIT 	(0..7)          with { variant "FIELDLENGTH(3)"}                   // 2^3-1
type integer INT4BIT 	(0..15)         with { variant "FIELDLENGTH(4)"}                   // 2^4-1
type integer INT5BIT 	(0..31)         with { variant "FIELDLENGTH(5)"}                   // 2^5-1
type integer INT7BIT    (0..127)        with { variant "FIELDLENGTH(7)"}                   // 2^7-1
type integer INT8BIT 	(0..255)        with { variant "FIELDLENGTH(8)"}                   // 2^8-1
type integer INT11BIT 	(0..2047)       with { variant "FIELDLENGTH(11),BYTEORDER(last)"}  // 2^11-1
type integer INT21BIT 	(0..2097151)    with { variant "FIELDLENGTH(21),BYTEORDER(last)"}  // 2^21-1
Re: Decoding J1939 name fails [message #1828785 is a reply to message #1828765] Thu, 18 June 2020 14:21 Go to previous messageGo to next message
Michael Josenhans is currently offline Michael JosenhansFriend
Messages: 99
Registered: February 2016
Member
Is there now a way to reverse the order of the bytes in the J1939_NAME_RECORD for encoding. (The lowest byte is encoded first, the highest byte is encoded last.)

As seen here:

See https://www.kvaser.com/about-can/higher-layer-protocols/j1939-introduction/, search for table 3.

Byte number in CAN message          Contents/Meaning
0                                   Identity number, LSB
1                                   Identity number
2   Bits 0-4:                       Identity number, MSB
    Bits 5-7:                       Manufacturer code, LSB
3                                   Manufacturer code, MSB
4   Bits 0-2:                       ECU instance
    Bits 3-7:                       Function instance
5                                   Function
6   Bit 0:                          Reserved bit
    Bits 1-7:                       Vehicle system
7   Bits 0-3:                       Vehicle system instance
    Bits 4-6:                       Industry group
    Bit 7:                          Arbitrary address bit


Currently the highest byte is encoded first.

The same for the following defintion of the name:
type OCT8 		J1939_NAME
Re: Decoding J1939 name fails [message #1828871 is a reply to message #1828785] Sat, 20 June 2020 15:43 Go to previous messageGo to next message
Elemer Lelik is currently offline Elemer LelikFriend
Messages: 1120
Registered: January 2015
Senior Member
Hi Michael,

for the first structure you might be looking for the FIELDORDER attribute:

 FIELDORDER

Attribute syntax: FIELDORDER(<parameter>)

Parameters allowed: msb, lsb

Default value: lsb

Can be used with: record or set types. It can also be assigned to a group of fields of a record.

Description: The attribute specifies the order in which consecutive fields of a structured type are placed into octets. * msb: coded bitfields are concatenated within an octet starting from MSB, when a field stretches the octet boundary, it continues at the MSB of next the octet. * lsb: coded bitfields are concatenated within an octet starting from LSB, when a field stretches the octet boundary, it continues at the LSB of next the octet.

Comment: Fields within an octet must be coded with the same FIELDORDER.
Fields are always concatenated in increasing octet number direction.
FIELDORDER has a slightly different effect than order attributes. While the FIELDORDER shifts the location of coded bitfields inside octets, the order attributes describes the order of the bits within a bitfield.
There is NO connection between the effect of the FIELDORDER and the effects of the other order attributes.

Note
The attribute does not extend to lower level structures. If the same field order is desired for the fields of a lower level record/set, then that record/set also needs a FIELDORDER attribute.
Examples:

//Example number 1)
type record MyRec_lsb {
BIT1 field1,
BIT2 field2,
BIT3 field3,
BIT4 field4,
BIT6 field5
}

with { variant "FIELDORDER(lsb)" }
const MyRec_lsb c_pdu := {
field1:='1'B // bits of field1: a
field2:='00'B // bits of field2: b
field3:='111'B // bits of field3: c
field4:='0000'B // bits of field4: d
field5:='111111'B // bits of field5: e
}

//Encoding of c_pdu will result in:
// 00111001 ddcccbba
// 11111100 eeeeeedd
//Example number 2)

type record MyRec_msb {
BIT1 field1,
BIT2 field2,
BIT3 field3,
BIT4 field4,
BIT6 field5
}

with { variant "FIELDORDER(msb)" }
const MyRec_msb c_pdu2 := {
field1:='1'B // bits of field1: a
field2:='00'B // bits of field2: b
field3:='111'B // bits of field3: c
field4:='0000'B // bits of field4: d
field5:='111111'B // bits of field5: e
}

//Encoding of c_pdu2 will result in:
// 10011100 abbcccdd
// 00111111 ddeeeeee




while for the J1939_NAME , BITORDER should be used:

BITORDER

Attribute syntax: BITORDER(<parameter>)

Parameters allowed: msb, lsb

Default value: lsb

Can be used with: stand-alone types or the field of a record or set.

Description: This attribute specifies the order of the bits within an octet. When set to lsb, the first bit sent will be the least significant bit of the original byte. When set to msb, the first bit sent will be the most significant bit of the original byte. When applied to an octetstring using the extension bit mechanism, only the least significant 7 bits are reversed, the 8th bit is reserved for the extension bit.

Examples:





// Example number 1)
type octetstring OCT
with {
variant "BITORDER(lsb)"
}

const OCT c_oct := '123456'O

//The encoded bitfield: 01010110 00110100 00010010
// last octet^ ^first octet
// The buffer will have the following content:
// 00010010
// 00110100
// 01010110

//The encoding result in the octetstring '123456'O

//Example number 2)
type octetstring OCTrev
with {
variant "BITORDER(msb)"
}

const OCTrev c_octr := '123456'O

//The encoded bitfield: 01010110 00110100 00010010

// last octet^ ^first octet

//The buffer will have the following content:
// 01001000
// 00101100
// 01101010

//The encoding results in the octetstring '482C6A'O



Pls check the RAW Encoder and Decoder section of the Titan reference guide.


Best regards

Elemer

Re: Decoding J1939 name fails [message #1828888 is a reply to message #1828871] Sun, 21 June 2020 12:51 Go to previous messageGo to next message
Michael Josenhans is currently offline Michael JosenhansFriend
Messages: 99
Registered: February 2016
Member
Hi Elemer,

I looked these up in the reference guide and came to the conclusion, that this is not what is needed.
The BITORDER swaps the order of the bits, all I need is to swap the order of the bytes, according my understanding the order of the bits within each byte shall remain the same.

If J1939_NAME_RECORD or J1939_NAME encodes currently as '0123456789ABCDEF'O, it needs to encode instead as 'EFCDAB8967452301'O.

E.g. byte 7 and byte 0 are swapped, byte 6 and byte 1 are swapped, etc.

Michael
Re: Decoding J1939 name fails [message #1828890 is a reply to message #1828888] Sun, 21 June 2020 14:49 Go to previous messageGo to next message
Elemer Lelik is currently offline Elemer LelikFriend
Messages: 1120
Registered: January 2015
Senior Member
Hi MIchael,

Right; in this case you need the BYTEORDER attribute:

BYTEORDER

Attribute syntax: BYTEORDER(<parameter>)

Parameters allowed: first, last

Default value: first

Can be used with: stand-alone types or the field of a record or set.

Description: The attribute determines the order of the bytes in the encoded data.

first: The first octet placed first into the buffer.

last: The last octet placed first into the buffer.

Comment: The attribute has no effect on a single octet field.

Note
The attribute works differently for octetstring and integer types. The ordering of bytes is counted from left-to-right (starting from the MSB) in an octetstring but right-to-left (starting from the LSB) in an integer. Thus, the attribute BYTEORDER(first) for an octetstring results the same encoded value than BYTEORDER(last) for an integer having the same value.
Examples:

//Example number 1)
type octetstring OCT
with {
variant "BYTEORDER(first)"
}

const OCT c_oct := '123456'O
//The encoded bitfield: 01010110 00110100 00010010
// last octet^ ^first octet

The buffer will have the following content:
// 00010010
// 00110100
// 01010110

//The encoding will result in the octetstring '123456'O

//Example number 2)
type octetstring OCTrev
with {variant "BYTEORDER(last)"
}

const OCTrev c_octr := '123456'O
//The encoded bitfield: 01010110 00110100 00010010
// last octet^ ^first octet

//The buffer will have the following content:

// 01010110

// 00110100

// 00010010


Choosing the appropriate encoding variants as listed in the quoted paragraph should give you the desired result.


I hope this helps

Elemer
Re: Decoding J1939 name fails [message #1828894 is a reply to message #1828890] Sun, 21 June 2020 16:49 Go to previous messageGo to next message
Michael Josenhans is currently offline Michael JosenhansFriend
Messages: 99
Registered: February 2016
Member
Hi Elemer,

this is what I expected too.

The encoding for:
type OCT8 		J1939_NAME  with {variant "BYTEORDER(last)"}


works fine.

However for the record, the BYTEORDER attribute (last/first) has no impact on encoding:

type record J1939_NAME_RECORD{
  J1939_ARBITRARY_ADDRESS_BIT       arbitraryAddresssBitValue,  // selfConfigurableAddressValue
  J1939_INDUSTRY_GROUP              industryGroupValue,         // deviceClassInstanceValue 
  J1939_VEHICLE_SYSTEM_INSTANCE     vehicleSystemInstanceValue, // deviceClassInstanceValue
  J1939_VEHICLE_SYSTEM              vehicleSystemValue,
  J1939_RESERVED                    reservedValue,
  J1939_FUNCTION                    functionValue,
  J1939_FUNCTION_INSTANCE           functionInstanceValue,
  J1939_ECU_INSTANCE                ecuInstanceValue,
  J1939_MANUFACTURER_CODE           manufacturerCodeValue,
  J1939_IDENTITY_NUMBER             identityNumberValue
} with { variant "FIELDORDER(msb),BYTEORDER(last)" }


This matches the reference manual:

BYTEORDER
Attribute syntax: BYTEORDER(<parameter>)
Parameters allowed: first, last
Default value: first
Can be used with: stand-alone types or the field of a record or set.


Thus it can be applied on a field of a record, however not on the record itself.

Br,
Michael
Re: Decoding J1939 name fails [message #1828898 is a reply to message #1828894] Sun, 21 June 2020 17:28 Go to previous messageGo to next message
Elemer Lelik is currently offline Elemer LelikFriend
Messages: 1120
Registered: January 2015
Senior Member
Hi Michael,

can you send me a concrete example ( a template of type J1939_NAME_RECORD) indicating how would you like to encode it?

BR

Elemer
Re: Decoding J1939 name fails [message #1828900 is a reply to message #1828898] Sun, 21 June 2020 19:03 Go to previous messageGo to next message
Michael Josenhans is currently offline Michael JosenhansFriend
Messages: 99
Registered: February 2016
Member
Hi Elemer,

I have currently not a working template, as for the J1939 socket interface, the PGN becomes a seperate parameter. Thus, as I expect only e.g. vt2ecu messages on the socket interface, it might be sufficent to have an internal port for vt2ecu, one for ecu2vt and e.g. one for addressClaimed.

type record AddressClaimed
{
  J1939_NAME          name
} with { variant "" }


or

type record AddressClaimed
{
  J1939_NAME_RECORD         name
} with { variant "" }


type record Isobus_messageWithPGN {
J1939_PGN pgn,
Isobus_message pdu
}
with {
  variant (pdu) "CROSSTAG(
  etp_dt,                   pgn = '00C700'O;  //199
  etp_cm,                   pgn = '00C800'O;  //200
  vt2ecu,                   pgn = '00E600'O;  //230
  ecu2vt,                   pgn = '00E700'O;  //231
  requestForAddressClaimed, pgn = '00EA00'O;  //234
  tp_dt,                    pgn = '00EB00'O;  //235
  tp_cm,                    pgn = '00EC00'O;  //236
  networkMessage,           pgn = '00ED00'O;  //237
//  cannotClaimSourceAddress, pgn = '00EEFFFE'O;  //238 all and conjuction needed!!!!!!
  addressClaimed,           pgn = '00EEFF'O;  //238 all and conjuction needed!!!!!!
  commandedAddress,         pgn = '00FED8'O)" //254 all and conjuction needed!!!!!!
}


type union Isobus_message {
  ETP_DT                     etp_dt,  // extended TP data transfer
  ETP_CM                     etp_cm,  // extended TP connection management 
  VT2ECU                     vt2ecu,  // Message Virtual Terminal (VT) to ECU
  ECU2VT                     ecu2vt,  // Message ECU to Virtual Terminal (VT)
  RequestForAddressClaimed   requestForAddressClaimed,
  TP_DT                      tp_dt,   // TP data transfer
  TP_CM                      tp_cm,   // TP connection management
  NetworkMessage             networkMessage, // Network Message according ISO 11873-4
  CannotClaimSourceAddress   cannotClaimSourceAddress,
  AddressClaimed             addressClaimed,
  CommandedAddress           commandedAddress
  // other upper layer isobus protocols like Task Comtroller are added here ...
}
with { variant "" }


This is the J1939 record returned from socket interface:
type record SocketCAN_receive_j1939_message { // recieved J1939 message
  SocketCAN_socketid               id,
  SocketCAN_ifr                    ifr,
  J1939_PGN                        pgn,
  J1939_ADDR                       destAddr,
  J1939_NAME                       name,
  SocketCAN_J1939_PDU              pdu
}


Basically the J1939 connection setup works the following:

To set up a connection an address claim message is sent with the name (Bitorder last encoded) it contains also a 1 byte source address SA.
Then if a second connection is set up, the same procedure happens. If there are conflicts as they have choosen the same SA, the connection with the smaller NAME wins and the other has to assign a new SA and repeat this procedure. This called address claiming procedure.

The address claiming procedure could be implemented as a TTCN process. It is currently not implemented in TTCN, however there is an address claiming deamon (user space), that has to be started for each NAME, which keeps track of changing addresses. Thus if in parallel running the address claiming deamon, TTCN code has not to track of the address, it can use the NAME for addressing in the socket.

The kernel keeps track of the NAME, thus the socket interface can subscribe via bind to a PGN (optionally) , a NAME (optionally) and alternatively to a SA and then just receive the filtered messages e.g. for the subsribed NAME and PGN.

A typical procedure looks as following:
- The address is claimed for all names (NAME1 (VT), NAME2 (ecu) using addressClaim message.
- One device e.g. the VT sends a message to the global address (broadcast address, SA=0xFF) using a PGN e.g. ecu2vt. The name is given.
- The other side e.g. the ecu has subscribed to the global address receives its NAME1.
- Then the other side (the ecu) responds by setting up a socket and binding to the given NAME1 and sends a response message the NAME2 using its name, which are converted by the linux kernel driver to its source address SA and the destination addess DA of the j1939 can bus network.

For now, it looks to me that the PGN is kept seperate from the vt2ecu pdu and there is a different socket call for each PGN we are interested in. This works for ISOBUS, but it might not work of other J1939 devices, which may have hundereds of different PGNs at the same time. Thus when filtering the PGN by the kernel, there might be needed hundereds of open sockets and thus TTCN processes at the same time.

This is the way vt2ecu looks like:

type union VT2ECU
{
  // put all VT2ECU messages here
  SoftKeyActivationReq               softKeyActivationReq,
  ButtonActivationReq                buttonActivationReq,
  PointingEventReq                   pointingEventReq,
  VTSelectInputObjectReq             vtSelectInputObjectReq,
  .....
  ExtendedStoreVersionRes            extendedStoreVersionRes,
  ExtendedLoadVersionRes             extendedLoadVersionRes,
  ExtendedDeleteVersionRes           extendedDeleteVersionRes,
  GetVersionsRes                     getVersionsRes,
  VTUnsupportedVTFunctionInd         vtUnsupportedVTFunctionInd,
  VTStatusReq                        vtStatusReq
}
with {variant "TAG	(
  // put all VT2ECU messages here
  softKeyActivationReq,              vtfunction =   0; 
  buttonActivationReq,               vtfunction =   1;
  pointingEventReq,                  vtfunction =   2; 
  vtSelectInputObjectReq,            vtfunction =   3;
  vtESCReq,                          vtfunction =   4;
  vtChangeNumericValueReq,           vtfunction =   5;
  vtChangeActiveMaskReq,             vtfunction =   6;
  vtChangeSoftKeyMaskReq,            vtfunction =   7;
.....
  getVersionsRes,                    vtfunction = 224;
  vtUnsupportedVTFunctionInd,        vtfunction = 253;
  vtStatusReq, 	                     vtfunction = 254;)"
}


Re: Decoding J1939 name fails [message #1828902 is a reply to message #1828900] Sun, 21 June 2020 19:26 Go to previous messageGo to next message
Elemer Lelik is currently offline Elemer LelikFriend
Messages: 1120
Registered: January 2015
Senior Member
OK,

let's assume the following values:
arbitraryAddresssBitValue:=0'B
industryGroupValue:='111'B
vehicleSystemInstanceValue:='0000'
vehicleSystemValue:='1111111'B
reservedValue:='0'B
functionValue:='11111111'B
functionInstanceValue:='00000'B
ecuInstanceValue:='111'B
manufacturerCodeValue:='00000000111'B
identityNumberValue:='000001111111100000000'B



Could you please indicate how should this look encoded ?

BR

Elemer
Re: Decoding J1939 name fails [message #1828903 is a reply to message #1828902] Sun, 21 June 2020 19:51 Go to previous messageGo to next message
Michael Josenhans is currently offline Michael JosenhansFriend
Messages: 99
Registered: February 2016
Member
It sould be encoded as:
00000000 11111111 11100000 00000000 00000111 11111111 11111110 01110000


Here is an example I have created with the help of titan:

NAME as encoded:
'3102032E193D0B93'O

NAME as octetstring '
930B3D192E030231'O

NAME as record:
name := { arbitraryAddresssBitValue := 1, industryGroupValue := 1, vehicleSystemInstanceValue := 3, vehicleSystemValue := 5, reservedValue := 1, functionValue := 61, functionInstanceValue := 3, ecuInstanceValue := 1, manufacturerCodeValue := 368, identityNumberValue := 197169 }


To your example:
Re: Decoding J1939 name fails [message #1828904 is a reply to message #1828903] Sun, 21 June 2020 20:07 Go to previous messageGo to next message
Michael Josenhans is currently offline Michael JosenhansFriend
Messages: 99
Registered: February 2016
Member
Here is how the encoding works:
arbitraryAddresssBitValue       :='0'B                     "a"
industryGroupValue              :='111'B                   "bbb"
vehicleSystemInstanceValue      :='0000'                   "ccc"
vehicleSystemValue              :='1111111'B               "ddddddd"
reservedValue                   :='0'B                     "e"
functionValue                   :='11111111'B              "f"
functionInstanceValue           :='00000'B                 "ggggg"
ecuInstanceValue                :='111'B                   "hhh"
manufacturerCodeValue           :='00000000111'B           "iiiiiiiiiii"
identityNumberValue             :='000001111111100000000'B "jjjjjjjjjjjjjjjjjjjj"


jjjjjjjj jjjjjjjj iiiijjjj hiiiiiii fggggghh ddddddde abbbcccc

Steps:
1. Concatenate the bits
2. Goup it to bytes
3. Reverse the byteorder

Note: The order of the bits is not turned.
Re: Decoding J1939 name fails [message #1828909 is a reply to message #1828900] Mon, 22 June 2020 06:33 Go to previous messageGo to next message
Gábor Szalai is currently offline Gábor SzalaiFriend
Messages: 133
Registered: December 2015
Senior Member
The BYTEORDER sets the order of the bytes of the basic types only: *string, integer

The order of the bytes in the complex type, like set or record is determined by the order of the fields. So if you reverse the order of the fields, the byte order is effectively reversed. (The correct BYTEORDR attribute should be attached to the individual fields)
Re: Decoding J1939 name fails [message #1828918 is a reply to message #1828909] Mon, 22 June 2020 11:51 Go to previous messageGo to next message
Elemer Lelik is currently offline Elemer LelikFriend
Messages: 1120
Registered: January 2015
Senior Member
Hi Michael,

for

arbitraryAddresssBitValue       :='0'B                     "a"
industryGroupValue              :='111'B                   "bbb"
vehicleSystemInstanceValue      :='0000'                   "ccc"
vehicleSystemValue              :='1111111'B               "ddddddd"
reservedValue                   :='0'B                     "e"
functionValue                   :='11111111'B              "f"
functionInstanceValue           :='00000'B                 "ggggg"
ecuInstanceValue                :='111'B                   "hhh"
manufacturerCodeValue           :='00000000111'B           "iiiiiiiiiii"
identityNumberValue             :='000001111111100000000'B "jjjjjjjjjjjjjjjjjjjj"


encoding is more like

 jjjjjjjj   jjjjjjjj  iiijjjjj   iiiiiiii  fffffhhh   ffffffff   ddddddde abbbcccc

instead of
jjjjjjjj jjjjjjjj iiiijjjj hiiiiiii fggggghh ddddddde abbbcccc 
as indicated ;
pls. check and confirm

Pls try the following:



type record J1939_NAME_RECORD_A{
  J1939_IDENTITY_NUMBER             identityNumber,
  J1939_MANUFACTURER_CODE           manufacturerCode,
  J1939_ECU_INSTANCE                ecuInstance,
  J1939_FUNCTION_INSTANCE           functionInstance,
  J1939_FUNCTION                    function_,
  J1939_RESERVED                    reserved,
  J1939_VEHICLE_SYSTEM              vehicleSystem,
  J1939_VEHICLE_SYSTEM_INSTANCE     vehicleSystemInstance,
  J1939_INDUSTRY_GROUP              industryGroup,
  J1939_ARBITRARY_ADDRESS_BIT       arbitraryAddresssBit

}  with { variant "FIELDORDER(lsb)"  /* it has no effect here, added for visibility only */ 

variant (identityNumber) "BYTEORDER(first)"
variant (manufacturerCode) "BYTEORDER(first)" 
/* the following variants are not needed:  variant (ecuInstance) "BYTEORDER(first)"    
variant (functionInstance) "BYTEORDER(first)"
variant (function_) "BYTEORDER(first)"
variant (reserved) "BYTEORDER(first)"
variant (vehicleSystem) "BYTEORDER(first)"
variant (vehicleSystemInstance) "BYTEORDER(first)"
variant (industryGroup) "BYTEORDER(first)"
variant (arbitraryAddresssBit) "BYTEORDER(first)"
*/
}
template J1939_NAME_RECORD_A  t_name_A := { 
identityNumber := 65280,
manufacturerCode := 7, 
ecuInstance := 7, 
functionInstance := 0,
function_ := 255, 
reserved := 0, 
vehicleSystem := 127,
vehicleSystemInstance := 0, 
industryGroup := 7, 
arbitraryAddresssBit := 0

 }

template J1939_NAME_RECORD_A  t_name_A1 := { 
identityNumber := 197169,
manufacturerCode := 368, 
ecuInstance := 1, 
functionInstance := 3,
function_ := 61, 
reserved := 1, 
vehicleSystem := 5,
vehicleSystemInstance := 3, 
industryGroup := 1, 
arbitraryAddresssBit := 1

 }






should result in:

13:44:18.268737 RAWTest2.ttcn:147 ----------------------------------------------------------------------------------
13:44:18.268769 RAWTest2.ttcn:149 Encode '00FFE00007FFFE70'O
13:44:18.268818 RAWTest2.ttcn:151 EncodedBitstr '0000000011111111111000000000000000000111111111111111111001110000'B
13:44:18.268857 RAWTest2.ttcn:153 Decode{ identityNumber := 65280, manufacturerCode := 7, ecuInstance := 7, functionInstance := 0, function_ := 255, reserved := 0, vehicleSystem := 127, vehicleSystemInstance := 0, industryGroup := 7, arbitraryAddresssBit := 0 }
13:44:18.268898 RAWTest2.ttcn:157 ----------------------------------------------------------------------------------
13:44:18.268919 RAWTest2.ttcn:158 Encode '3102032E193D0B93'O
13:44:18.268947 RAWTest2.ttcn:160 EncodedBitstr '0011000100000010000000110010111000011001001111010000101110010011'B
13:44:18.268984 RAWTest2.ttcn:162 Decode{ identityNumber := 197169, manufacturerCode := 368, ecuInstance := 1, functionInstance := 3, function_ := 61, reserved := 1, vehicleSystem := 5, vehicleSystemInstance := 3, industryGroup := 1, arbitraryAddresssBit := 1 }



pls mind that there might be several paths to result in the same encoding.


I hope this helps

Elemer
Re: Decoding J1939 name fails [message #1828929 is a reply to message #1828918] Mon, 22 June 2020 15:10 Go to previous messageGo to next message
Michael Josenhans is currently offline Michael JosenhansFriend
Messages: 99
Registered: February 2016
Member
Hi Elemer,

my encoding was wrong. Your encoding was almost correct. Your encoding contains 'fffff' instead of 'ggggg'.
Here the correct encoding, which matches your encoding, execpt of the 'ggggg'.
arbitraryAddresssBitValue       :='0'B                     "a"
industryGroupValue              :='111'B                   "bbb"
vehicleSystemInstanceValue      :='0000'                   "cccc"
vehicleSystemValue              :='1111111'B               "ddddddd"
reservedValue                   :='0'B                     "e"
functionValue                   :='11111111'B              "ffffffff"
functionInstanceValue           :='00000'B                 "ggggg"
ecuInstanceValue                :='111'B                   "hhh"
manufacturerCodeValue           :='00000000111'B           "iiiiiiiiiii"
identityNumberValue             :='000001111111100000000'B "jjjjjjjjjjjjjjjjjjjjj"

Step 1: Concatenate the bits
abbbccccdddddddeffffffffggggghhhiiiiiiiiiiijjjjjjjjjjjjjjjjjjjjj

Step 2: Group into bytes
abbbcccc
ddddddde
ffffffff
ggggghhh
iiiiiiii
iiijjjjj
jjjjjjjj
jjjjjjjj

Step 3: Reverse the order of the bytes
jjjjjjjj
jjjjjjjj
iiijjjjj
iiiiiiii
ggggghhh
ffffffff
ddddddde
abbbcccc

Step 4: Concatenate the bytes again
jjjjjjjjjjjjjjjjiiijjjjjiiiiiiiiggggghhhffffffffdddddddeabbbcccc 

Your proposal was:
jjjjjjjjjjjjjjjjiiijjjjjiiiiiiiifffffhhhffffffffdddddddeabbbcccc
Re: Decoding J1939 name fails [message #1828934 is a reply to message #1828929] Mon, 22 June 2020 16:00 Go to previous messageGo to next message
Elemer Lelik is currently offline Elemer LelikFriend
Messages: 1120
Registered: January 2015
Senior Member
Hi Michael,

yes , for some reason I entered fffff instead of ggggg;

however the RAW encoding variant should work as it conforms , at least as far as I can see, to:

jjjjjjjjjjjjjjjjiiijjjjjiiiiiiiiggggghhhffffffffdddddddeabbbcccc
(not to jjjjjjjjjjjjjjjjiiijjjjjiiiiiiiifffffhhhffffffffdddddddeabbbcccc, which was a typo)

BR

Elemer

[Updated on: Mon, 22 June 2020 16:12]

Report message to a moderator

Re: Decoding J1939 name fails [message #1828953 is a reply to message #1828934] Tue, 23 June 2020 07:20 Go to previous message
Michael Josenhans is currently offline Michael JosenhansFriend
Messages: 99
Registered: February 2016
Member
Hi Elemer,

this now works for encoding of reverse byte order and normalbyte order. I need both.

type record J1939_NAME_RECORD{
  J1939_ARBITRARY_ADDRESS_BIT       arbitraryAddresssBit,  // selfConfigurableAddressValue
  J1939_INDUSTRY_GROUP              industryGroup,         // deviceClassInstanceValue 
  J1939_VEHICLE_SYSTEM_INSTANCE     vehicleSystemInstance, // deviceClassInstanceValue
  J1939_VEHICLE_SYSTEM              vehicleSystem,
  J1939_RESERVED                    reserved,
  J1939_FUNCTION                    function_,
  J1939_FUNCTION_INSTANCE           functionInstance,
  J1939_ECU_INSTANCE                ecuInstance,
  J1939_MANUFACTURER_CODE           manufacturerCode,
  J1939_IDENTITY_NUMBER             identityNumber
} with { variant "FIELDORDER(msb)" 
  variant (identityNumber) "BYTEORDER(last)"
  variant (manufacturerCode) "BYTEORDER(last)" 
}

type record J1939_NAME_RECORD_REVERSE_BYTE_ENCODING{
  J1939_IDENTITY_NUMBER             identityNumber,
  J1939_MANUFACTURER_CODE           manufacturerCode,
  J1939_ECU_INSTANCE                ecuInstance,
  J1939_FUNCTION_INSTANCE           functionInstance,
  J1939_FUNCTION                    function_,
  J1939_RESERVED                    reserved,
  J1939_VEHICLE_SYSTEM              vehicleSystem,
  J1939_VEHICLE_SYSTEM_INSTANCE     vehicleSystemInstance, // deviceClassInstanceValue
  J1939_INDUSTRY_GROUP              industryGroup,         // deviceClassInstanceValue 
  J1939_ARBITRARY_ADDRESS_BIT       arbitraryAddresssBit   // selfConfigurableAddressValue
}  with { variant "FIELDORDER(lsb)"  /* it has no effect here, added for visibility only */ 

  variant (identityNumber) "BYTEORDER(first)"
  variant (manufacturerCode) "BYTEORDER(first)" 
  /* the following variants are not needed:  
  variant (ecuInstance) "BYTEORDER(first)"    
  variant (functionInstance) "BYTEORDER(first)"
  variant (function_) "BYTEORDER(first)"
  variant (reserved) "BYTEORDER(first)"
  variant (vehicleSystem) "BYTEORDER(first)"
  variant (vehicleSystemInstance) "BYTEORDER(first)"
  variant (industryGroup) "BYTEORDER(first)"
  variant (arbitraryAddresssBit) "BYTEORDER(first)"
  */
}

type	INT1BIT		J1939_ARBITRARY_ADDRESS_BIT
type	INT3BIT		J1939_INDUSTRY_GROUP
type	INT4BIT		J1939_VEHICLE_SYSTEM_INSTANCE
type	INT7BIT		J1939_VEHICLE_SYSTEM
type	INT1BIT		J1939_RESERVED
type	INT8BIT		J1939_FUNCTION
type	INT5BIT		J1939_FUNCTION_INSTANCE
type	INT3BIT		J1939_ECU_INSTANCE
type	INT11BIT	J1939_MANUFACTURER_CODE
type	INT21BIT	J1939_IDENTITY_NUMBER

type integer INT1BIT 	(0..1)          with { variant "FIELDLENGTH(1)"}		           // 2^1-1
type integer INT3BIT 	(0..7)          with { variant "FIELDLENGTH(3)"}                   // 2^3-1
type integer INT4BIT 	(0..15)         with { variant "FIELDLENGTH(4)"}                   // 2^4-1
type integer INT5BIT 	(0..31)         with { variant "FIELDLENGTH(5)"}                   // 2^5-1
type integer INT7BIT    (0..127)        with { variant "FIELDLENGTH(7)"}                   // 2^7-1
type integer INT8BIT 	(0..255)        with { variant "FIELDLENGTH(8)"}                   // 2^8-1
type integer INT11BIT 	(0..2047)       with { variant "FIELDLENGTH(11),BYTEORDER(last)"}  // 2^11-1
type integer INT21BIT 	(0..2097151)    with { variant "FIELDLENGTH(21),BYTEORDER(last)"}  // 2^21-1


Thanks a lot.

Br,
Michael
Previous Topic:Eclipse Titan 7.1.0 release announcement
Next Topic:TTCN-3 NBIOT Test Case Execution using Eclipse Titan
Goto Forum:
  


Current Time: Tue Apr 23 11:14:58 GMT 2024

Powered by FUDForum. Page generated in 0.04839 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top