Difference between revisions of "Technical topic: ASN.1 - An introduction to ACN"

From TASTE
Jump to: navigation, search
(Length determinant is in completely different subtree)
(Length determinant is in completely different subtree)
(35 intermediate revisions by the same user not shown)
Line 15: Line 15:
 
Here is a simple example, starting from a basic integer type:
 
Here is a simple example, starting from a basic integer type:
  
    MyInteger ::= INTEGER (0..7)
+
MyInteger ::= '''INTEGER''' (0..7)
 
 
  
 
If you choose to represent a data of this type using the ASN.1 PER, the encoding will be optimal: '''3 bits'''.
 
If you choose to represent a data of this type using the ASN.1 PER, the encoding will be optimal: '''3 bits'''.
Line 22: Line 21:
 
However, your protocol may say that this has to be encoded using 32 bits with a little endian representation. ACN offers the syntax for this:
 
However, your protocol may say that this has to be encoded using 32 bits with a little endian representation. ACN offers the syntax for this:
  
    MyInteger [size 32, endianness little, encoding pos-int]
+
MyInteger ['''size''' ''32'', '''endianness''' ''little'', '''encoding''' ''pos-int'']
  
  
Line 40: Line 39:
  
 
Please note a very important feature of ACN: encoding instructions are written in separate files, so that the original ASN.1 grammars remains unpolluted and therefore compatible with other ASN.1 tools.
 
Please note a very important feature of ACN: encoding instructions are written in separate files, so that the original ASN.1 grammars remains unpolluted and therefore compatible with other ASN.1 tools.
 
  
 
= ACN Overview  =
 
= ACN Overview  =
Line 50: Line 48:
 
Here is a simple ASN.1 grammar:
 
Here is a simple ASN.1 grammar:
  
  MYMOD DEFINITIONS AUTOMATIC TAGS::= BEGIN
+
  MYMOD '''DEFINITIONS''' ::= '''BEGIN'''
 
   
 
   
  MyInt ::= INTEGER (-100 .. 100)
+
  MyInt ::= '''INTEGER''' (-100 .. 100)
 
   
 
   
  MyInt2 ::= INTEGER (0 .. 1000)
+
  MyInt2 ::= '''INTEGER''' (0 .. 1000)
 
   
 
   
  MySeq ::= SEQUENCE {
+
  MySeq ::= '''SEQUENCE''' {
     a1 INTEGER (1..20),
+
     a1 '''INTEGER''' (1 .. 20),
     a2 INTEGER (-10 .. 20),
+
     a2 '''INTEGER''' (-10 .. 20),
 
     a3 MyInt,
 
     a3 MyInt,
 
     a4 MyInt2
 
     a4 MyInt2
 
  }
 
  }
  END
+
  '''END'''
  
<span id="_Ref263422634" class="anchor"></span>Listing 1: Sample ASN.1 grammar
+
Listing 1: Sample ASN.1 grammar
  
 
and here is an example ACN encoding for this grammar:
 
and here is an example ACN encoding for this grammar:
  
     MYMOD DEFINITIONS ::= BEGIN
+
     MYMOD '''DEFINITIONS''' ::= '''BEGIN'''
 
      
 
      
     --ACN allows constant definitions
+
     -- ACN allows constant definitions
 
      
 
      
     CONSTANT WORDSIZE ::= 32
+
     '''CONSTANT''' WORDSIZE ::= 32
 
      
 
      
     --We can make basic math with ACN constants
+
     -- We can make basic math with ACN constants
 
      
 
      
     CONSTANT LARGEST-INT ::= 2^^(WORDSIZE - 1)-1
+
     '''CONSTANT''' LARGEST-INT ::= 2^^(WORDSIZE - 1) - 1
 
      
 
      
     -- MyInt will be encoded as twos complement integer.
+
     -- MyInt will be encoded as twos complement integer.
     -- Size will be 1 byte
+
     -- Size will be 1 byte
 
      
 
      
     MyInt[size 8, encoding twos-complement]
+
     MyInt ['''size''' ''8'', '''encoding''' ''twos-complement'']
 
      
 
      
 
     -- If no encoding properties are present, then
 
     -- If no encoding properties are present, then
 
     -- encoding properties will be automatically populated
 
     -- encoding properties will be automatically populated
 
     -- so that the behavior matches the one of uPER i.e.
 
     -- so that the behavior matches the one of uPER i.e.
     -- size 10, encoding pos-int
+
     -- '''size''' ''10'', '''encoding''' ''pos-int''
 
      
 
      
 
     MyInt2 []
 
     MyInt2 []
Line 95: Line 93:
 
     MySeq [] {
 
     MySeq [] {
 
       a1 [],
 
       a1 [],
       a2 [size 32, encoding twos-complement, endianness little],
+
       a2 ['''size''' ''32'', '''encoding''' ''twos-complement'', '''endianness''' ''little''],
 
       a3 [],
 
       a3 [],
 
       a4 []
 
       a4 []
Line 101: Line 99:
 
     END
 
     END
  
<span id="_Ref263423576" class="anchor"></span>Listing 2: Sample ACN grammar for the ACN grammar of Listing 1
+
Listing 2: Sample ACN grammar for the ACN grammar of Listing 1
  
 
By looking at the above code example, we see the following:
 
By looking at the above code example, we see the following:
  
* For each ASN.1 module there is one ACN module with the same name.
+
* For each ASN.1 ''module'' there is one ACN ''module'' with the same name.
 +
 
 +
'''''NOTE'''''
 +
If the ASN.1 module imports types from other modules, they can be accessed with full path from the ACN module
 +
For instance if the ASN.1 module MYMOD contains the following statement:
 +
  IMPORTS Some-Type FROM Some-Module;
 +
Then the ACN module MYMOD can reference Some-Module.Some-Type (without an explicit import)
 +
 
 
* We can optionally define some integer constant values (WORDSIZE, LARGEST-INT etc) which can be referenced by the rest of the ACN specification.
 
* We can optionally define some integer constant values (WORDSIZE, LARGEST-INT etc) which can be referenced by the rest of the ACN specification.
 
* The ACN module contains the types (i.e. the type references) declared in the ASN.1 module followed by the encoding properties.
 
* The ACN module contains the types (i.e. the type references) declared in the ASN.1 module followed by the encoding properties.
Line 126: Line 131:
 
Syntax
 
Syntax
  
  size ''intExpr – the units are provided in the table below''
+
  '''size''' ''intExpr – the units are provided in the table below''
  
 
Examples
 
Examples
  
  size 10
+
  '''size''' ''10''
  size WORDSIZE/2 -- WORDSIZE is an ACN constant defined before
+
  '''size''' ''WORDSIZE / 2'' -- WORDSIZE is an ACN constant defined before
  
 
The following table lists the ASN.1 types where the fixed form can be applied as well as the corresponding count unit.
 
The following table lists the ASN.1 types where the fixed form can be applied as well as the corresponding count unit.
  
{|
+
{| class="wikitable"
 
! Asn1 Type
 
! Asn1 Type
 
! Count unit of intExpr
 
! Count unit of intExpr
Line 169: Line 174:
 
Syntax
 
Syntax
  
  size ''field''
+
  '''size''' ''field''
  
Example
+
Examples
  
{|
+
'''size''' ''length''        -- ''length'' is an integer field defined in the same scope with the encoded type
! size length
+
'''size''' ''header.length''  -- ''header'' is a sequence type defined in the same scope with the encoded type and which contains an integer type component named ''length''
! ''length'' is an integer field defined in the same scope with the encoded type
 
|-
 
| size header.length
 
| ''header'' is a sequence type defined in the same scope with the encoded type and which contains an integer type component named ''length''
 
|}
 
  
 
This form of size property can be applied to bit string, octet string, character strings and sequence/set of types.
 
This form of size property can be applied to bit string, octet string, character strings and sequence/set of types.
Line 187: Line 187:
 
This form is applicable only for IA5String and Numeric string types. In this case, the end of the string is determined by the presence of a null character (0). User may define the null terminated character with termination-pattern encoding property. Here are some examples:
 
This form is applicable only for IA5String and Numeric string types. In this case, the end of the string is determined by the presence of a null character (0). User may define the null terminated character with termination-pattern encoding property. Here are some examples:
  
  MyPDU ::= IA5String(SIZE(20))(FROM(&quot;A&quot;..&quot;Z&quot;|&quot;a&quot;..&quot;z&quot;|&quot; &quot;))
+
  MyPDU ::= '''IA5String''' (SIZE (20)) (FROM(&quot;A&quot;..&quot;Z&quot; | &quot;a&quot;..&quot;z&quot; | &quot; &quot;))
  
 
Listing 3: Sample ASN1 grammar to demostrate size null-terminared property
 
Listing 3: Sample ASN1 grammar to demostrate size null-terminared property
  
  MyPDU[encoding ASCII, size null-terminated]
+
  MyPDU ['''encoding''' ''ASCII'', '''size''' ''null-terminated'']       -- ASCII encoding, null terminated
-- ASCII encoding, null terminated
+
  MyPDU ['''encoding''' ''ASCII'', '''size''' ''null-terminated'', '''termination-pattern''' ''01'H'']  -- ASCII encoding with termination pattern
 
 
  MyPDU[encoding ASCII, size null-terminated, termination-pattern '01'H]
 
  -- ASCII encoding, null terminated, the termination pattern is the character 0x01
 
  
 
Listing 3: Sample ACN grammar to demostrate size null-terminared property
 
Listing 3: Sample ACN grammar to demostrate size null-terminared property
Line 205: Line 202:
 
Syntax
 
Syntax
  
  encoding ''encvalue''
+
  '''encoding''' ''encvalue''
  
 
where ''encvalue'' is one of pos-int, twos-complement, BCD, ASCII, IEEE754-1985-32 and IEEE754-1985-64
 
where ''encvalue'' is one of pos-int, twos-complement, BCD, ASCII, IEEE754-1985-32 and IEEE754-1985-64
Line 211: Line 208:
 
Example
 
Example
  
  encoding pos-int
+
  '''encoding''' ''pos-int''
  encoding BCD
+
  '''encoding''' ''BCD''
  
{|
+
{| class="wikitable"
 
! Encoding value
 
! Encoding value
 
! Applicable ASN.1 types
 
! Applicable ASN.1 types
Line 253: Line 250:
 
Syntax
 
Syntax
  
  endianness ''endianness-value''
+
  '''endianness''' ''endianness-value''
 
 
where ''endianness-value'' is big or little
 
  
 
Example
 
Example
  
  endianness little
+
  '''endianness''' ''little''
  endianness big (Default)
+
  '''endianness''' ''big'' -- Default
  
{|
+
{| class="wikitable"
 
! Encoding value
 
! Encoding value
 
! Applicable ASN.1 types
 
! Applicable ASN.1 types
Line 269: Line 264:
 
| Big
 
| Big
 
|
 
|
Integer, enumerated, Real
+
INTEGER, ENUMERATED, REAL
 
|
 
|
 
The 32 bit integer value 0xAABBCCDD will be transmitted as follows:
 
The 32 bit integer value 0xAABBCCDD will be transmitted as follows:
Line 277: Line 272:
 
| Little
 
| Little
 
|
 
|
Integer, enumerated, Real
+
INTEGER, ENUMERATED, REAL
 
|
 
|
 
The 32 bit integer value 0xAABBCCDD will be transmitted as follows:
 
The 32 bit integer value 0xAABBCCDD will be transmitted as follows:
Line 292: Line 287:
 
Syntax
 
Syntax
  
  align-to-next ''alignValue''
+
  '''align-to-next''' ''alignValue''
  
 
Example
 
Example
  
  align-to-next byte -- 8 bits
+
  '''align-to-next''' ''byte''  -- 8 bits
  align-to-next word 16 bits
+
  '''align-to-next''' ''word''  -- 16 bits
  align-to-next dword 32 bits
+
  '''align-to-next''' ''dword'' -- 32 bits
  
 
== encode-values property ==
 
== encode-values property ==
Line 304: Line 299:
 
This property can be applied only to enumerated types and controls whether the enumerant values will be encoded or their indexes. When present, the values (not indexes) of enumerants will be encoded.
 
This property can be applied only to enumerated types and controls whether the enumerant values will be encoded or their indexes. When present, the values (not indexes) of enumerants will be encoded.
  
Example
+
Syntax
  
  [encode-values]
+
  '''encode-values'''
  
 
== true-value and false-value properties ==
 
== true-value and false-value properties ==
Line 314: Line 309:
 
Syntax
 
Syntax
  
  true-value ''bitStringValue''
+
  '''true-value''' ''bitStringValue''
  false-value ''bitStringValue''
+
  '''false-value''' ''bitStringValue''
  
 
Example
 
Example
  
  true-value ''‘111’B''
+
  '''true-value''' ''‘111’B''
  false-value ''‘0’B''
+
  '''false-value''' ''‘0’B''
  
 
== present-when property ==
 
== present-when property ==
Line 330: Line 325:
 
Syntax
 
Syntax
  
  Present-when ''booleanFld''
+
  '''present-when''' ''booleanFld''
  
 
where ''booleanFld'' is a reference to a boolean field
 
where ''booleanFld'' is a reference to a boolean field
Line 336: Line 331:
 
Example
 
Example
  
  MySeq ::= SEQUENCE {
+
  MySeq ::= '''SEQUENCE''' {
     alpha INTEGER,
+
     alpha '''INTEGER''',
     gamma REAL OPTIONAL
+
     gamma '''REAL''' '''OPTIONAL'''
 
  }
 
  }
  
<span id="_Ref263422937" class="anchor"></span>Listing 3: Sample ASN.1 grammar
+
Listing 3: Sample ASN.1 grammar
  
 
  MySeq[] {
 
  MySeq[] {
     alpha [],
+
     alpha         [],
     beta BOOLEAN [],
+
     beta '''BOOLEAN''' [],
     gamma [present-when beta, encoding IEEE754-1985-64]
+
     gamma         ['''present-when''' ''beta'', '''encoding''' ''IEEE754-1985-64'']
 
  }
 
  }
 
   
 
   
Line 357: Line 352:
 
Syntax
 
Syntax
  
  Present-when ''booleanExpression''
+
  '''present-when''' ''booleanExpression''
  
 
where ''booleanExpression'' is a boolean expression which can contain one or more non optional ASN.1 fields (not ACN inserted fields).  
 
where ''booleanExpression'' is a boolean expression which can contain one or more non optional ASN.1 fields (not ACN inserted fields).  
Line 365: Line 360:
 
Example
 
Example
  
  MyPDU[]  {
+
  MyPDU []  {
     int1 [size 8, encoding pos-int],
+
     int1 ['''size''' ''8'', '''encoding''' ''pos-int''],
     enm [present-when (int1 <10 and int1%2 == 0) or (int1>=10 and int1 <=14) ]
+
     enm ['''present-when''' ''(int1 < 10 and int1%2 == 0) or (int1 >= 10 and int1 <= 14)'']
 
  }  
 
  }  
  
Line 376: Line 371:
 
Syntax
 
Syntax
  
  Present-when fld<sub>1</sub>==val<sub>1</sub> fld<sub>2</sub>==val<sub>2</sub> ... fld<sub>n</sub>==val­<sub>n</sub>
+
  '''present-when''' fld<sub>1</sub>==val<sub>1</sub> fld<sub>2</sub>==val<sub>2</sub> ... fld<sub>n</sub>==val­<sub>n</sub>
  
 
where fld<sub>i</sub> is a reference to a an integer or string field and val<sub>i</sub> is constant integer or string value.
 
where fld<sub>i</sub> is a reference to a an integer or string field and val<sub>i</sub> is constant integer or string value.
Line 382: Line 377:
 
Example
 
Example
  
  MYMOD DEFINITIONS AUTOMATIC TAGS::= BEGIN
+
  MYMOD '''DEFINITIONS''' ::= '''BEGIN'''
  COLOR-TYPE ::= INTEGER (0..255)
 
 
   
 
   
   COLOR-DATA ::= CHOICE {
+
  COLOR-TYPE ::= '''INTEGER''' (0..255)
     green INTEGER (1..10),
+
     red INTEGER (1..1000),
+
   COLOR-DATA ::= '''CHOICE''' {
     blue IA5String (SIZE(1..20))
+
     green '''INTEGER''' (1..10),
 +
     red   '''INTEGER''' (1..1000),
 +
     blue '''IA5String''' ('''SIZE'''(1..20))
 
   }  
 
   }  
 
   
 
   
   MySeq ::= SEQUENCE {
+
   MySeq ::= '''SEQUENCE''' {
 
     colorData COLOR-DATA
 
     colorData COLOR-DATA
 
   }
 
   }
   END
+
   '''END'''
  
 
Listing 5: Sample ASN.1 grammar
 
Listing 5: Sample ASN.1 grammar
  
  MYMOD DEFINITIONS ::= BEGIN
+
  MYMOD '''DEFINITIONS''' ::= '''BEGIN'''
 
   
 
   
   COLOR-TYPE [encoding pos-int, size 8]
+
   COLOR-TYPE ['''encoding''' ''pos-int'', '''size''' ''8'']
 
   
 
   
 
   MySeq [] {
 
   MySeq [] {
Line 409: Line 405:
 
   
 
   
 
   COLOR-DATA&lt;COLOR-TYPE:type1, COLOR-TYPE:type2&gt; [] {
 
   COLOR-DATA&lt;COLOR-TYPE:type1, COLOR-TYPE:type2&gt; [] {
     green [present-when type1==1 type2==10],
+
     green ['''present-when''' ''type1==1 type2==10''],
     red [present-when type1==20 type2==20],
+
     red   ['''present-when''' ''type1==20 type2==20''],
     blue [present-when type1==50 type2==20]
+
     blue ['''present-when''' ''type1==50 type2==20'']
 
   }
 
   }
 
   
 
   
Line 424: Line 420:
 
Syntax
 
Syntax
  
  determinant ''enumFld''
+
  '''determinant''' ''enumFld''
  
 
Example
 
Example
  
  MYMOD DEFINITIONS AUTOMATIC TAGS::= BEGIN
+
  MYMOD '''DEFINITIONS''' ::= '''BEGIN'''
 
   
 
   
  RGB ::= ENUMERATED {green, red, blue}
+
  RGB ::= '''ENUMERATED''' {green, red, blue}
  MySeq ::= SEQUENCE {
+
     beta      BOOLEAN,
+
  MySeq ::= '''SEQUENCE''' {
     colorData CHOICE {
+
     beta      '''BOOLEAN''',
       green REAL,
+
     colorData '''CHOICE''' {
       red  INTEGER,
+
       green '''REAL''',
       blue  IA5String (SIZE(1..20))
+
       red  '''INTEGER''',
 +
       blue  '''IA5String''' ('''SIZE'''(1..20))
 
     }
 
     }
 
  }
 
  }
  END
+
  '''END'''
  
 
<span id="_Ref263422989" class="anchor"></span>Listing 7: Sample ASN.1 grammar
 
<span id="_Ref263422989" class="anchor"></span>Listing 7: Sample ASN.1 grammar
  
  MYMOD DEFINITIONS ::= BEGIN
+
  MYMOD '''DEFINITIONS''' ::= '''BEGIN'''
 
   
 
   
 
  MySeq [] {
 
  MySeq [] {
 
     activeColor RGB [],
 
     activeColor RGB [],
     beta [],
+
     beta           [],
     colorData [determinant activeColor]
+
     colorData       ['''determinant''' ''activeColor'']
 
  }
 
  }
  END
+
  '''END'''
  
 
Listing 8: ACN grammar for ASN.1 grammar of Listing 7
 
Listing 8: ACN grammar for ASN.1 grammar of Listing 7
Line 506: Line 503:
  
  
In some cases, the value for the encoding properties “size”, “present-when” and “determinant-tag” may provided by be another field.  
+
In some cases, the value for the encoding properties “size” and “present-when” may provided by be another field.  
 
These fields do not carry semantic (i.e. application specific) information but are used only in the decoding and encoding processes.  
 
These fields do not carry semantic (i.e. application specific) information but are used only in the decoding and encoding processes.  
 
Therefore these fields may not exist in the ASN.1 grammar but introduced only in the ACN one.  
 
Therefore these fields may not exist in the ASN.1 grammar but introduced only in the ACN one.  
 
For example, Listing 3 can be modified as follows:
 
For example, Listing 3 can be modified as follows:
  
  MySeq ::= SEQUENCE {
+
  MySeq ::= '''SEQUENCE''' {
     alpha INTEGER,
+
     alpha '''INTEGER''',
     gamma REAL OPTIONAL
+
     gamma '''REAL OPTIONAL'''
 
  }
 
  }
  
Line 520: Line 517:
 
  Seq[] {
 
  Seq[] {
 
     alpha [],
 
     alpha [],
     beta BOOLEAN [], -- exists only in the ACN file, not the ASN.1 one
+
     beta '''BOOLEAN''' [], -- exists only in the ACN file
     gamma [present-when beta, encoding IEEE754-1985-64]
+
     gamma       ['''present-when''' ''beta'', '''encoding''' ''IEEE754-1985-64'']
 
  }
 
  }
  
Line 533: Line 530:
 
  T-tc-packetID []
 
  T-tc-packetID []
 
  {
 
  {
     ccsds-version-number NULL [pattern '000'B],
+
     ccsds-version-number '''NULL''' ['''pattern''' '000'B],
     packet-type NULL [pattern '1'B] ,
+
     packet-type         '''NULL''' ['''pattern''' '1'B] ,
     has-data-fieldhdr NULL [pattern '1'B],
+
     has-data-fieldhdr   '''NULL''' ['''pattern''' '1'B],
     apid []
+
     apid                     []
 
  }
 
  }
  
Line 549: Line 546:
  
 
To address this issue, ACN introduces three special attributes:
 
To address this issue, ACN introduces three special attributes:
* post-encoding-function
+
* '''post-encoding-function'''
* post-decoding-validator
+
* '''post-decoding-validator'''
* save-position
+
* '''save-position'''
  
 
The first two attributes (post-encoding-function, post-decoding-validator) are applicable only to  
 
The first two attributes (post-encoding-function, post-decoding-validator) are applicable only to  
 
SEQUENCE types while the save-position attribute to SEQUENCE components of NULL type.
 
SEQUENCE types while the save-position attribute to SEQUENCE components of NULL type.
  
Example
+
[[Example]]
 +
 
 +
in ASN.1:
 +
 
 +
Packet ::= '''SEQUENCE''' {
 +
  p-header T-Header,
 +
  p-body  T-Body
 +
}
  
 +
in ACN:
  
  Packet [post-encoding-function my-encoding-patcher, post-decoding-validator crc-validator]
+
  Packet ['''post-encoding-function''' ''my-encoding-patcher'', '''post-decoding-validator''' ''crc-validator'']
 
  {   
 
  {   
     p-header [],
+
     p-header                 [],
     body-length-in-bytes NULL [pattern '0000000000000000'B, save-position], -- 16 bits
+
     body-length-in-bytes '''NULL''' ['''pattern''' '0000000000000000'B, '''save-position'''], -- reserve 16 bits for storing the length
     p-body   [],
+
     p-body                   [],
     packet-crc32 NULL [pattern '00000000'H, save-position] -- 32 bits
+
     packet-crc32         '''NULL''' ['''pattern''' '00000000'H, '''save-position'''] -- reserve 32 bits for storing the CRC
 
  }
 
  }
 
   
 
   
Line 576: Line 581:
 
structure called Packet_extension_function_positions. This structure along with bitstream is passed as an argument
 
structure called Packet_extension_function_positions. This structure along with bitstream is passed as an argument
 
to two user-defined functions:
 
to two user-defined functions:
 - in the my-encoding-patcher at the end of the encoding (defined via the post-encoding-function attribute)
+
 
 - in the crc-validator at the end of decoding (defined via the post-decoding-validator attribute)
+
* in the my-encoding-patcher at the end of the encoding (defined via the post-encoding-function attribute)
 +
* in the crc-validator at the end of decoding (defined via the post-decoding-validator attribute)
  
 
The first function my-encoding-patcher will provide values in these two fields. The second function reads these
 
The first function my-encoding-patcher will provide values in these two fields. The second function reads these
Line 584: Line 590:
 
The complete code the example is at the following location
 
The complete code the example is at the following location
 
https://github.com/ttsiodras/asn1scc/tree/master/Docs/examples/calculate_crc
 
https://github.com/ttsiodras/asn1scc/tree/master/Docs/examples/calculate_crc
 +
 +
 +
For the ''length'' field, note that a (probably better) alternative is to specify the packet like this in ASN.1:
 +
 +
Packet ::= '''SEQUENCE''' {
 +
  p-header T-Header,
 +
  p-body  '''OCTET STRING''' ('''CONTAINING''' T-Body)
 +
}
 +
 +
With such a construct, you will get a Body size field computed "for free" by the compiler, and therefore you can use it in the ACN model:
 +
 +
Packet [] {
 +
  p-header        [],
 +
  p-size  '''INTEGER''' ['''size''' 16, '''encoding''' pos-int],
 +
  p-body          [size p-size]
 +
}
  
 
== Parameterized encodings and deep field access ==
 
== Parameterized encodings and deep field access ==
Line 607: Line 629:
  
 
  --ASN.1 DEFINITION
 
  --ASN.1 DEFINITION
  Packet ::= SEQUENCE {
+
  Packet ::= '''SEQUENCE''' {
     primaryHeader SEQUENCE {
+
     primaryHeader '''SEQUENCE''' {
         version INTEGER,
+
         version       '''INTEGER''',
         seqNr INTEGER,
+
         seqNr         '''INTEGER''',
         secHeaderFlag BOOLEAN
+
         secHeaderFlag '''BOOLEAN'''
 
     },
 
     },
     secondaryHeader SEQUENCE {...} OPTIONAL
+
     secondaryHeader '''SEQUENCE''' {...} '''OPTIONAL'''
 
  }
 
  }
  
 
  -- Encodings definition
 
  -- Encodings definition
 
  Packet [] {
 
  Packet [] {
     primaryHeader[] {
+
     primaryHeader [] {
         version [],
+
         version       [],
         seqNr [],
+
         seqNr         [],
 
         secHeaderFlag []
 
         secHeaderFlag []
 
     }
 
     }
     secondaryHeader [present-when '''primaryHeader.secHeaderFlag''']
+
     secondaryHeader ['''present-when''' ''primaryHeader.secHeaderFlag'']
 
  }
 
  }
  
Line 641: Line 663:
  
 
  -- ASN.1 DEFINITION
 
  -- ASN.1 DEFINITION
  TAP2File ::= SEQUENCE {
+
  TAP2File ::= '''SEQUENCE''' {
 
     --  nrCalls INTEGER,    << This field must not appear in the ASN.1 module
 
     --  nrCalls INTEGER,    << This field must not appear in the ASN.1 module
 
     data SourceData
 
     data SourceData
 
  }
 
  }
  SourceData ::= SEQUENCE {
+
 +
  SourceData ::= '''SEQUENCE''' {
 
     operatorID '''IA5String''' ('''SIZE''' (1..10),
 
     operatorID '''IA5String''' ('''SIZE''' (1..10),
 
     calls      '''SEQUENCE'''  ('''SIZE'''(1..100)) '''OF''' Call
 
     calls      '''SEQUENCE'''  ('''SIZE'''(1..100)) '''OF''' Call
Line 655: Line 678:
 
     data &lt;nrCalls&gt;  [] -- nrCalls is passed as a parameter in SourceData
 
     data &lt;nrCalls&gt;  [] -- nrCalls is passed as a parameter in SourceData
 
  }
 
  }
  SourceData&lt;INTEGER:nElements&gt; [] {
+
 +
  SourceData&lt;'''INTEGER''':nElements&gt; [] {
 
     -- nElements is a parameter used in encoding/decoding
 
     -- nElements is a parameter used in encoding/decoding
 
     -- passed in from the levels above (in this case, TAP2File level)
 
     -- passed in from the levels above (in this case, TAP2File level)
 
     operatorID [],
 
     operatorID [],
     calls      [size nElements] -- points to a parameter not a field
+
     calls      ['''size''' ''nElements''] -- points to a parameter not a field
 
  }
 
  }
  
Line 680: Line 704:
 
  -- ASN.1 DEFINITION
 
  -- ASN.1 DEFINITION
 
  TAP3File ::= '''SEQUENCE''' {
 
  TAP3File ::= '''SEQUENCE''' {
     header Header,
+
     hdr    Header,
 
     data  SourceData
 
     data  SourceData
 
  }
 
  }
  Header ::= SEQUENCE {
+
 +
  Header ::= '''SEQUENCE''' {
 
     operatorID '''IA5String''' ('''SIZE''' (1..10))
 
     operatorID '''IA5String''' ('''SIZE''' (1..10))
 
     --  nCalls is not a value that user can set. It must not be declared in the ASN.1 type
 
     --  nCalls is not a value that user can set. It must not be declared in the ASN.1 type
 
  }
 
  }
  SourceData ::= SEQUENCE {
+
 +
  SourceData ::= '''SEQUENCE''' {
 
     calls '''SEQUENCE''' ('''SIZE'''(1..100)) '''OF''' Call
 
     calls '''SEQUENCE''' ('''SIZE'''(1..100)) '''OF''' Call
 
  }
 
  }
Line 693: Line 719:
 
  -- ACN DEFINITION
 
  -- ACN DEFINITION
 
  TAP3File [] {
 
  TAP3File [] {
     header [] {},
+
     hdr [] {
     data  &lt;header.nCalls&gt; [] -– header.nCalls is passed as a parameter in SourceData
+
      operatorID    [],
 +
      nCalls INTEGER ['''size''' ''8'', '''encoding''' ''pos-int'']  -- << Introduce the count field here
 +
  },
 +
     data  &lt;hdr.nCalls&gt; [] -- hdr.nCalls is passed as a parameter in SourceData
 
  }
 
  }
  Header[]{
+
   
    operatorID    [],
+
-- Do not introduce the nCalls field to the Header encoding, as the actual value must
    nCalls INTEGER [size 8, encoding pos-int]  -- << Introduce the count field here
+
-- be provided from another source. Adding this field here would prevent a standalone
  }
+
-- encoding of the header, since the encoder would not know what value to use for the field.
  SourceData&lt;INTEGER:nElements&gt; [] -- parameters
+
Header[]
 +
   
 +
  SourceData&lt;'''INTEGER''':nElements&gt; [] -- parameters
 
  {
 
  {
     calls [size nElements] “size” points to a parameter, not a field
+
     calls ['''size''' ''nElements''] -- “size” points to a parameter, not a field
 
     <span id="_Ref243465359" class="anchor"></span>
 
     <span id="_Ref243465359" class="anchor"></span>
 
  }
 
  }
  
 
Listing 17: ACN grammar demonstrating parameterized encodings and deep field access
 
Listing 17: ACN grammar demonstrating parameterized encodings and deep field access

Revision as of 05:14, 26 April 2020

Introduction

ACN was created as a simple ASN.1-companion language allowing to describe custom binary encodings for complex data structures.

It is useful in the following case:

  • you need to implement a binary packet encoder/decoder for a legacy protocol
  • no standard ASN.1 encoding rules (PER, DER, XER, OER, JER...) fits
  • ECN, the Encoding Control Notation is too complicated or you have no tool available
  • the targeted encoding is not too complex

ACN works in pair with ASN.1 and provides various ways to customize the memory layout of data structures.

Here is a simple example, starting from a basic integer type:

MyInteger ::= INTEGER (0..7)

If you choose to represent a data of this type using the ASN.1 PER, the encoding will be optimal: 3 bits.

However, your protocol may say that this has to be encoded using 32 bits with a little endian representation. ACN offers the syntax for this:

MyInteger [size 32, endianness little, encoding pos-int]


ACN aims at being easy to read, powerful enough for real-life cases, and in general very efficient. The following sections detail all the possibilities offered by the language for the various ASN.1 data types. You will see that in several cases, ACN can decribe encodings that are even more compact than uPER.


Note that there are encoding specifications which are not covered by the scope of ACN. For example it is not meant to describe complex textual encodings. Avdanced encoding rules can only be expressed using a notation such as ECN or the non-ASN.1-based DFDL language. Of course with the extra power also comes an extra price - if you target an embedded platform with limited resources, these languages lack tool support.


If you provide to ESA's free ASN1SCC compiler an ASN.1 and ACN grammar, you will obtain:


  • C and SPARK/Ada code for data structures and binary encoders/decoders using no heap and no system calls
  • HTML documentation of the memory layout corresponding to your ACN specification
  • Automatic test cases that do a roundtrip encode-decode with 100% code coverage
  • Bridge to access the ASN.1 data model from various languages (Python, MicroPython, SDL, Simulink, and even VHDL) (via TASTE)

Please note a very important feature of ACN: encoding instructions are written in separate files, so that the original ASN.1 grammars remains unpolluted and therefore compatible with other ASN.1 tools.

ACN Overview

Every ASN.1 type has a set of encoding properties that can be set in order to achieve the desired binary encoding. These properties control certain aspects of the encoding process such as: the size of type being encoded, how values are encoded (twos-complement vs positive integer encoding, etc), the presence/absence of a certain field etc.

These properties are assigned to ASN.1 types using a pair of square brackets (“[“ and “]”) as seen in Listing 2. The encoding properties assignment is carried out in a separate file – the ACN file, so that the original ASN.1 grammar remains “clean” from encoding specifications.

Here is a simple ASN.1 grammar:

MYMOD DEFINITIONS ::= BEGIN

MyInt ::= INTEGER (-100 .. 100)

MyInt2 ::= INTEGER (0 .. 1000)

MySeq ::= SEQUENCE {
   a1 INTEGER (1 .. 20),
   a2 INTEGER (-10 .. 20),
   a3 MyInt,
   a4 MyInt2
}
END

Listing 1: Sample ASN.1 grammar

and here is an example ACN encoding for this grammar:

   MYMOD DEFINITIONS ::= BEGIN
    
   --  ACN allows constant definitions
    
   CONSTANT WORDSIZE ::= 32
   
   --  We can make basic math with ACN constants
   
   CONSTANT LARGEST-INT ::= 2^^(WORDSIZE - 1) - 1
   
   --  MyInt will be encoded as twos complement integer.
   --  Size will be 1 byte
   
   MyInt [size 8, encoding twos-complement]
   
   -- If no encoding properties are present, then
   -- encoding properties will be automatically populated
   -- so that the behavior matches the one of uPER i.e.
   -- size 10, encoding pos-int
   
   MyInt2 []
   
   -- encoding properties for types defined
   -- within constructed types (i.e. fields)
   
   MySeq [] {
      a1 [],
      a2 [size 32, encoding twos-complement, endianness little],
      a3 [],
      a4 []
   }
   END

Listing 2: Sample ACN grammar for the ACN grammar of Listing 1

By looking at the above code example, we see the following:

  • For each ASN.1 module there is one ACN module with the same name.
NOTE
If the ASN.1 module imports types from other modules, they can be accessed with full path from the ACN module
For instance if the ASN.1 module MYMOD contains the following statement:
  IMPORTS Some-Type FROM Some-Module; 
Then the ACN module MYMOD can reference Some-Module.Some-Type (without an explicit import)
  • We can optionally define some integer constant values (WORDSIZE, LARGEST-INT etc) which can be referenced by the rest of the ACN specification.
  • The ACN module contains the types (i.e. the type references) declared in the ASN.1 module followed by the encoding properties.
  • The encoding properties may be absent. (The pair of open close brackets [ ] must be present though). In this case, the encoding properties have values which are calculated as follows:
    • Referenced types inherit the properties of their base types
    • For non referenced types (or referenced types whose base types have no encoding properties), the encoding properties are automatically populated with such values as to mimic the behavior of uPER.
  • For types declared within constructed types such as SEQUENCE / CHOICE / SEQUENCE OF, the encoding properties are declared after the component names
  • The encoding properties are declared at type reference level. If a new type is declared in the ASN.1 grammar based on an existing type reference, then the new type inherits from the base type its encoding properties.

ACN Encoding Properties

size property

The size encoding property controls the size of the encoding type. It comes in three forms:

Fixed form

This form is used when the size of the encoded type is fixed and known at compile time

Syntax

size intExpr – the units are provided in the table below

Examples

size 10
size WORDSIZE / 2 -- WORDSIZE is an ACN constant defined before

The following table lists the ASN.1 types where the fixed form can be applied as well as the corresponding count unit.

Asn1 Type Count unit of intExpr
Integer Bits
Enumerated Bits
Bit String Bits
Octet String Octets
IA5String Characters
Numeric String Characters
Sequence/set Of Elements of sequence/set of

Table 1: ASN.1 types where the size property can be applied

Variable size with length specified in external field

This form of size property is functionally equivalent with the previous one. The main difference is that the length field is an external field provided in the ACN grammar

Syntax

size field

Examples

size length         -- length is an integer field defined in the same scope with the encoded type
size header.length  -- header is a sequence type defined in the same scope with the encoded type and which contains an integer type component named length

This form of size property can be applied to bit string, octet string, character strings and sequence/set of types.

Null terminated

This form is applicable only for IA5String and Numeric string types. In this case, the end of the string is determined by the presence of a null character (0). User may define the null terminated character with termination-pattern encoding property. Here are some examples:

MyPDU ::= IA5String (SIZE (20)) (FROM("A".."Z" | "a".."z" | " "))

Listing 3: Sample ASN1 grammar to demostrate size null-terminared property

MyPDU [encoding ASCII, size null-terminated]        -- ASCII encoding, null terminated
MyPDU [encoding ASCII, size null-terminated, termination-pattern 01'H]  -- ASCII encoding with termination pattern

Listing 3: Sample ACN grammar to demostrate size null-terminared property

encoding property

The encoding property can be applied only to integer, enumerated, real, IA5String and Numeric string types.

Syntax

encoding encvalue

where encvalue is one of pos-int, twos-complement, BCD, ASCII, IEEE754-1985-32 and IEEE754-1985-64

Example

encoding pos-int
encoding BCD
Encoding value Applicable ASN.1 types Remarks
pos-int Integer, enumerated The ASN.1 integer must have constraints so that only positive values are allowed. Otherwise the compiler will report an error.
twos-complement Integer, enumerated
ASCII Integer, enumerated, IA5String, NumericString The ASCII code of the sign symbol (‘+’ or ‘-‘) is encoded first (mandatory) followed by the ASCII codes of the decimal digits of the encoded value. For example, the value 456 will be encoded in the four ASCII codes: 42 (i.e. ‘+’), 52, 53, 54.
BCD Integer, enumerated The ASN.1 integer must have constraints so that only positive values are allowed. Otherwise the compiler will report an error.
IEEE754-1985-32 Real http://en.wikipedia.org/wiki/IEEE_754-1985
IEEE754-1985-64 Real (same link as above)

Table 2: ASN.1 properties where the encoding property can be applied

endianness property

The endianness property can be applied only to fix size integers (and in particular when the size is 16, 32 or 64 bits), enumerated and real types and determines the order of the encoded bytes. For more information please refer to http://en.wikipedia.org/wiki/Endianness

Syntax

endianness endianness-value

Example

endianness little
endianness big -- Default
Encoding value Applicable ASN.1 types Remarks
Big

INTEGER, ENUMERATED, REAL

The 32 bit integer value 0xAABBCCDD will be transmitted as follows:

0xAA, 0xBB, 0xCC, 0xDD
Little

INTEGER, ENUMERATED, REAL

The 32 bit integer value 0xAABBCCDD will be transmitted as follows:

0xDD , 0xCC , 0xBB, 0xAA

Table 3: endianness property description

align-to-next property

This property can be applied to any ASN.1 type, and allows the type to be encoded at the beginning of the next byte or word or double word of the encoded bit stream.

Syntax

align-to-next alignValue

Example

align-to-next byte  -- 8 bits
align-to-next word  -- 16 bits
align-to-next dword -- 32 bits

encode-values property

This property can be applied only to enumerated types and controls whether the enumerant values will be encoded or their indexes. When present, the values (not indexes) of enumerants will be encoded.

Syntax

encode-values

true-value and false-value properties

These two mutually exclusive properties can be applied only to Boolean types and determine what value will be used to encode TRUE or FALSE values.

Syntax

true-value bitStringValue
false-value bitStringValue

Example

true-value ‘111’B
false-value ‘0’B

present-when property

The present-when property is used in optional SEQUENCE components and in CHOICE alternatives

In the case of OPTIONAL components the syntax is as follows:

Syntax

present-when booleanFld

where booleanFld is a reference to a boolean field

Example

MySeq ::= SEQUENCE {
   alpha INTEGER,
   gamma REAL OPTIONAL
}

Listing 3: Sample ASN.1 grammar

MySeq[] {
   alpha         [],
   beta  BOOLEAN [],
   gamma         [present-when beta, encoding IEEE754-1985-64]
}

Listing 4: ACN grammar for ASN.1 grammar of Listing 3

In the above example, gamma field is present only when beta is TRUE.

In the case of optional sequence components, the present-when attibute can be followed by a boolean expression.

Syntax

present-when booleanExpression

where booleanExpression is a boolean expression which can contain one or more non optional ASN.1 fields (not ACN inserted fields). The expression can use int and real constants, non optional ASN.1 fields as well as the following operators:

+ - * / % <= < >= > and or

Example

MyPDU []  {
   int1	[size 8, encoding pos-int],
   enm		[present-when (int1 < 10 and int1%2 == 0) or (int1 >= 10 and int1 <= 14)]
} 

In the above example, enm is present when int1 is less than 10 and even number or when it is within range 10..14.

In the case of CHOICE alternatives the syntax is as follows

Syntax

present-when fld1==val1 fld2==val2 ... fldn==val­n

where fldi is a reference to a an integer or string field and vali is constant integer or string value.

Example

MYMOD DEFINITIONS ::= BEGIN

 COLOR-TYPE ::= INTEGER (0..255)

 COLOR-DATA ::= CHOICE {
    green INTEGER (1..10),
    red   INTEGER (1..1000),
    blue  IA5String (SIZE(1..20))
 } 

 MySeq ::= SEQUENCE {
   colorData COLOR-DATA
 }
 END

Listing 5: Sample ASN.1 grammar

MYMOD DEFINITIONS ::= BEGIN

 COLOR-TYPE [encoding pos-int, size 8]

 MySeq [] {
    activeColor1 COLOR-TYPE [],
    activeColor2 COLOR-TYPE [],
    colorData <activeColor1, activeColor2> []
 }

 COLOR-DATA<COLOR-TYPE:type1, COLOR-TYPE:type2> [] {
    green [present-when type1==1 type2==10],
    red   [present-when type1==20 type2==20],
    blue  [present-when type1==50 type2==20]
 }

END

Listing 6: ACN grammar for ASN.1 grammar of Listing 3

determinant property

The determinant property is an alternative (simpler) way to determine which choice alternative is encoded. The encoded choice alternative is determined by an external enumerated field which must have the same names in its enumerants as the names of the choice alternatives.

Syntax

determinant enumFld

Example

MYMOD DEFINITIONS ::= BEGIN

RGB ::= ENUMERATED {green, red, blue}

MySeq ::= SEQUENCE {
   beta      BOOLEAN,
   colorData CHOICE {
      green REAL,
      red   INTEGER,
      blue  IA5String (SIZE(1..20))
   }
}
END

Listing 7: Sample ASN.1 grammar

MYMOD DEFINITIONS ::= BEGIN

MySeq [] {
   activeColor RGB [],
   beta            [],
   colorData       [determinant activeColor]
}
END

Listing 8: ACN grammar for ASN.1 grammar of Listing 7

In the example above, the active alternative in colorData choice is determined by the enumerated field activeColor.

mapping-function property

The mapping-function property allows to apply a filter to integer values, with the possibility to provide the filter function in the target language (C or Ada). For example in the MIL-1553 encodings, the length determinants of size (1..32) arrays are encoded using 5 bits and the size 32 is encoded with value 0 (i.e. 0 means 32 elements):

MYMOD DEFINITIONS AUTOMATIC TAGS::= BEGIN
 LENG-DET ::= INTEGER (1..32)
 WORD ::= INTEGER (0..65535)
 Milbus ::= SEQUENCE {
    words32 SEQUENCE (SIZE(1..32)) OF WORD
 }
END

Listing 9: Sample ASN.1 grammar

MYMOD DEFINITIONS ::= BEGIN
 LENG-DET [encoding pos-int, size 5, mapping-function milbus2]
 WORD[]
 Milbus[] {
   length LENG-DET [],
   words32 [size length]
 }
END

Listing 10: ACN grammar

The user in that case has to provide the code for the filter function milbus2 (either in C or in Ada):

asn1SccSint milbus2_encode(asn1SccSint val) {
    return val == 32 ? 0 : val;
}
asn1SccSint milbus2_decode(asn1SccSint val) {
   return val == 0 ? 32 : val;
}

Listing 11: C filter function for milbus2 encoding

When calling the ASN.1 compiler, use the -mfm flag. Assuming the functions are defined in mapFunctions.c:

   $ asn1.exe -c -ACN -o c_out/ -atc -mfm mapFunctions a.asn1 a.acn

Listing 12: Invocation of ASN1SCC with custom filter functions

For convenience, the ASN1SCC runtime provides pre-defined filter functions. In particular for the above example the mapping-function milbus is available off-the-shelf. Others could be added on request if frequently used.

Advanced ACN features

Fields introduced in the ACN grammar

In some cases, the value for the encoding properties “size” and “present-when” may provided by be another field. These fields do not carry semantic (i.e. application specific) information but are used only in the decoding and encoding processes. Therefore these fields may not exist in the ASN.1 grammar but introduced only in the ACN one. For example, Listing 3 can be modified as follows:

MySeq ::= SEQUENCE {
   alpha INTEGER,
   gamma REAL OPTIONAL
}

Listing 13: The revised ASN.1 grammar of Listing 3. Field ‘beta’ is missing.

Seq[] {
   alpha [],
   beta BOOLEAN [], -- exists only in the ACN file
   gamma        [present-when beta, encoding IEEE754-1985-64]
}

Listing 14: Revised ACN grammar for the ASN.1 grammar of Listing 14. Field ‘beta’ along with the type (BOOLEAN) is introduced.

Please notice that field ‘beta’ does not exist in the ASN.1 grammar but it was introduced only in the ACN grammar.

Another way to introduce fields (e.g. for alignment, or to add a standard-imposed data pattern in the encoding) is to use the NULL construct with the “pattern” encoding:

T-tc-packetID []
{
   ccsds-version-number NULL [pattern '000'B],
   packet-type          NULL [pattern '1'B] ,
   has-data-fieldhdr    NULL [pattern '1'B],
   apid                      []
}

Encoding fields that depend on the encoding binary stream

There are cases where the value of some special purpose fields depend on the value of the encoding stream. For example, the CRC (Cyclic Redundancy Check) fields are commonly used in digital networks and provide a mechanism to the recipient to validate the correctness of the data. The problem though with a CRC field is that its value cannot be provided in advance, as with normal fields, but only when the encoding of the bitstream is completed. Another case is the length in bytes of the encoded packet or parts of the encoded packet.

To address this issue, ACN introduces three special attributes:

  • post-encoding-function
  • post-decoding-validator
  • save-position

The first two attributes (post-encoding-function, post-decoding-validator) are applicable only to SEQUENCE types while the save-position attribute to SEQUENCE components of NULL type.

Example

in ASN.1:

Packet ::= SEQUENCE {
  p-header T-Header,
  p-body   T-Body
}

in ACN:

Packet [post-encoding-function my-encoding-patcher, post-decoding-validator crc-validator]
{  
   p-header                  [],
   body-length-in-bytes NULL [pattern '0000000000000000'B, save-position], -- reserve 16 bits for storing the length
   p-body                    [],
   packet-crc32         NULL [pattern '00000000'H, save-position] -- reserve 32 bits for storing the CRC
}

The packet consists of a header and a body. Between the header and the body, there is a length field that contains the size in bytes of the body. At the end of the packet, there is a 32 bit CRC field which has been calculated over the complete packet. To fulfill the above requirements, the length field (body-length-in-bytes) and CRC field (packet-crc32) are declared as ACN inserted fields. In both fields, the save-position attribute is used. This attribute instructs the ASN.1 compiler to generate code that will save the current position in the encoding/decoding bitstream. The current position refers to the beginning of the field. This information is kept is special structure called Packet_extension_function_positions. This structure along with bitstream is passed as an argument to two user-defined functions:

  • in the my-encoding-patcher at the end of the encoding (defined via the post-encoding-function attribute)
  • in the crc-validator at the end of decoding (defined via the post-decoding-validator attribute)

The first function my-encoding-patcher will provide values in these two fields. The second function reads these two fields and compares these values with values calculated via the bitstream.

The complete code the example is at the following location https://github.com/ttsiodras/asn1scc/tree/master/Docs/examples/calculate_crc


For the length field, note that a (probably better) alternative is to specify the packet like this in ASN.1:

Packet ::= SEQUENCE {
  p-header T-Header,
  p-body   OCTET STRING (CONTAINING T-Body)
}

With such a construct, you will get a Body size field computed "for free" by the compiler, and therefore you can use it in the ACN model:

Packet [] {
  p-header         [],
  p-size   INTEGER [size 16, encoding pos-int],
  p-body           [size p-size]
}

Parameterized encodings and deep field access

There are cases where the length field of a sequence of (or choice determinant, or optionality determinant etc) is not at the same level (i.e. components of a common parent) as the sequence of itself. Actually there are three distinct cases:

  1. The length determinant is one or more levels more deeply than the SEQUENCE OF

  2. The SEQUENCE OF is one or more levels more deeply than the length determinant

  3. The length determinant and the SEQUENCE OF are located in completely different nodes which just have a common ancestor.

These three cases are explained in more detail in the following sub-paragraphs

Length determinant is below current node

This case is illustrated in Figure 1. Field secondaryHeader, which is optional, is present when the secHeaderFlag in the primaryHeader is true.

ClipCapIt-200424-091755.PNG
  1. Deep field access – case a.

The corresponding ASN.1 / ACN grammar is:

--ASN.1 DEFINITION
Packet ::= SEQUENCE {
   primaryHeader SEQUENCE {
       version       INTEGER,
       seqNr         INTEGER,
       secHeaderFlag BOOLEAN
   },
   secondaryHeader SEQUENCE {...} OPTIONAL
}
-- Encodings definition
Packet [] {
    primaryHeader [] {
       version       [],
       seqNr         [],
       secHeaderFlag []
    }
    secondaryHeader [present-when primaryHeader.secHeaderFlag]
}

Listing 15: ACN grammar demonstrating access to fields at different levels

As shown in the example above, to access a “deep field” located in a child structure we follow the C language notation i.e. fieldname.fieldname.fieldname etc. until we reach the field we want.

Length determinant is above current node

This is the case where the array (sequence of_ is one or more levels more deeply than the length determinant. For example, field “nrCalls”, which is a top level field, contains the number of calls in the array “calls” located under “SourceData”. Obviously, the “nrCalls” field is not accessible from the “calls” field. To overcome this issue, we must make the SourceData structure parameterized. This case is shown in Figure 2.

ClipCapIt-200424-091836.PNG
  1. Deep field access – case b.

The corresponding ASN.1 / ACN grammar is:

-- ASN.1 DEFINITION
TAP2File ::= SEQUENCE {
   --  nrCalls INTEGER,    << This field must not appear in the ASN.1 module
   data SourceData
}

SourceData ::= SEQUENCE {
   operatorID IA5String (SIZE (1..10),
   calls      SEQUENCE  (SIZE(1..100)) OF Call
}
-- ACN DEFINITION
TAP2File [] {
   nrCalls INTEGER [size 8, encoding pos-int],    -- << Introduce the count field here
   data <nrCalls>  [] -- nrCalls is passed as a parameter in SourceData
}

SourceData<INTEGER:nElements> [] {
   -- nElements is a parameter used in encoding/decoding
   -- passed in from the levels above (in this case, TAP2File level)
   operatorID [],
   calls      [size nElements] -- points to a parameter not a field
}

Listing 16: ACN grammar demonstrating parameterized encodings

Please note the “<>” in the encoding definition of the SourceData which contains the list with the encoding parameters (in this example, just one).

Length determinant is in completely different subtree

This case is the combination of the two previous cases. A typical case is depicted in Figure 3. In this example, field “nCalls”, which is located under “header” record, contains the number of calls in the “calls” array under “SourceData”.

Field nCalls (length determinant) and field calls (the SEQUENCE OF) are components of two sibling structures (Header, SourceData) and have no access to each other.

ClipCapIt-200424-091910.PNG
  1. Deep field access – case c.

To handle this case, we must apply the techniques of both previous cases. The corresponding ASN.1 / ACN grammar would be:

-- ASN.1 DEFINITION
TAP3File ::= SEQUENCE {
   hdr    Header,
   data   SourceData
}

Header ::= SEQUENCE {
   operatorID IA5String (SIZE (1..10))
   --  nCalls is not a value that user can set. It must not be declared in the ASN.1 type
}

SourceData ::= SEQUENCE {
   calls SEQUENCE (SIZE(1..100)) OF Call
}
-- ACN DEFINITION
TAP3File [] {
   hdr [] {
     operatorID     [],
     nCalls INTEGER [size 8, encoding pos-int]   -- << Introduce the count field here
  },
   data   <hdr.nCalls> [] -- hdr.nCalls is passed as a parameter in SourceData
}

-- Do not introduce the nCalls field to the Header encoding, as the actual value must
-- be provided from another source. Adding this field here would prevent a standalone
-- encoding of the header, since the encoder would not know what value to use for the field.
Header[]

SourceData<INTEGER:nElements> [] -- parameters
{
   calls [size nElements]  -- “size” points to a parameter, not a field
   
}

Listing 17: ACN grammar demonstrating parameterized encodings and deep field access