Category Archives: LTE/3GPP

Updated 3GPP LTE and NAS APIs available

We have updated the 3GPP LTE and NAS ASN.1 API’s we have available for use with ASN1C. These API’s are available at the following URL:

There are 5G API’s available for releases 15 and 16, and LTE API’s available for releases 14 through 16.

The NAS API’s contain support for the latest release 16 versions of the TS 24.501, 24.301, and 24.008 specifications.

Improved TBCD and BCD Support for Java/C#

Our next release of ASN1C (v 7.3) will include improved support for TBCD and BCD strings for Java and C#.  In short, for these types, the toString/ToString function will return the TBCD/BCD interpretation of the octets, rather than merely their hexadecimal representation.  This also improves the print functionality.

TBCD stands for Telephony Binary-coded Decimal and BCD stands for Binary-coded Decimal.  So, what are TBCD and BCD strings?  They are OCTET STRINGS in which a series of digits or telephony digits are encoded, using one nibble (4 bits) per digit.  There isn’t an authoritative definition, but there are a few standards out there that provide definitions of TBCD or BCD and these are what we’ve followed, as described below.

As you will see in the following descriptions, TBCD and BCD strings are similar.  The differences are 1) the set of digit characters and 2) the ordering of the nibbles within the bytes.

TBCD Strings

For TBCD, we follow 3GPP 29.002.  This is also the document that happens to be referenced in the section on TBCD in the Wikipedia entry for BCD.  Here is how 29.002 defines TBCD:

-- This type (Telephony Binary Coded Decimal String) is used to
-- represent several digits from 0 through 9, *, #, a, b, c, two
-- digits per octet, each digit encoded 0000 to 1001 (0 to 9),
-- 1010 (*), 1011 (#), 1100 (a), 1101 (b) or 1110 (c); 1111 used
-- as filler when there is an odd number of digits.
-- bits 8765 of octet n encoding digit 2n
-- bits 4321 of octet n encoding digit 2(n-1) +1

To summarize the characteristics for 3GPP 29.002 TBCD-STRING:
• Uses characters 0-9,*,#,a-c.
• F nibble is used as filler when there is an odd number of digits.
• The low nibble contains the first digit.

Note that 3GPP 24.008 § “Called party BCD number” specifies the same encoding, though it simply refers to it as “BCD”.  24.008 also calls for BCD in § “Mobile Identity” (for the  IMSI, IMEI and IMEISV), (presumably) meaning BCD as defined in §, i.e. TBCD.

BCD Strings

For BCD, we have followed the TAP3 (GSM TD.57) specification of BCD.  Here is how they define BCD:

-- The BCDString data type (Binary Coded Decimal String) is used to represent 
-- several digits from 0 through 9, a, b, c, d, e. 
-- Two digits are encoded per octet. The four leftmost bits of the octet represent 
-- the first digit while the four remaining bits represent the following digit. 
-- A single f must be used as a filler when the total number of digits to be 
-- encoded is odd. 
-- No other filler is allowed.

To summarize the characteristics of TAP3 BCDString:

• Uses characters 0-9,a-e.
• F nibble is used as filler when there is an odd number of digits.
• The high nibble contains the first digit.


Q.825 was another candidate for a definition of TBCD strings.  At this point, we haven’t added special support for it.  This section merely points out the differences between Q.825 TBCD-STRING and 3GPP 29.002 TBCD-STRING.  The differences are:

  • In Q.825, TBCD-STRING is defined as part of an OCTET STRING, not as a standalone type.  Prior to the TBCD-STRING content, the OCTET STRING contains an odd/even indicator octet, and, in some cases, another octet.
  • Q.825 orders the nibbles differently.
  • Q.825 uses the F nibble to mark the end of the TBCD string (“end of pulsing signal-ST”)
  • Q.825 uses the 0 nibble as filler when there is an odd number of digits.  So, in some cases, a zero nibble is merely filler, but in other cases it is a ‘0’ digit.  [Note: we’re not sure why Q.825 specifies that filler is required when there is an odd number of digits; it seem it should be required when there is an even number of digits.  By our reading, “123” would map to 0x123F (no filler), while “1234” would map to 0x12340F (filler).]


New 5G NR (New Radio) 3GPP/LTE APIs available

We have added the new 3GPP/LTE 5G NR (New Radio) ASN.1 API’s for use with ASN1C.  These 5G API’s are extended sample programs that contain the complete ASN.1 specifications extracted from the relevant 3GPP 5G standard documents.  The API’s are available at the following URL (“LTE ASN.1 APIs” tab):

There are API’s available for 3GPP release 15 of the different 5G AP specification types.  API’s are currently available for LTE-RRC 5G NR, E1AP 5G NR, F1AP 5G NR, NGAP 5G NR, and XnAP 5G NR LTE ASN.1 specifications.

Additionally, the existing 3GPP LTE APIs (such as S1AP, e.g.) have been updated to their latest releases (rel 14 or 15).

Finally, support for specification TS 24.501 (NAS protocol for 5G Systems) has been added to the NAS DLL.  Support for the SDK add-on will be included in the next release of ASN1C.

Compact code generation in ASN1C

ASN.1 is used in a lot of different areas and a new area that is within the Internet of Things (IoT).  In particular Narrowband IoT (NB-IoT) uses ASN.1 UPER-based messaging.

One characteristic of these devices is they are small, so code size is critical.  We have been working on ways to make our ASN1C generated code and run-time libraries as compact as possible for applications such as these.   In our latest ASN1C v7.2.1 patch release, we are now including a new set of compact libraries for Linux.  These can be found in the c/lib_compact directories.  They are built with gcc using maximum space optimization settings and with a lot of non-critical code stripped out.  The compact libraries are roughly 25% smaller than the standard libraries.

In addition to using the compact libraries, additional steps can be taken to reduce the size of the generated code.  We touched on some of these in a past blog post entitled “Optimizing PER Encoding and Code Footprint“.  We would also recommend using the following command-line options (the equivalent GUI option is in parentheses):

  • -compact  (Generate compact code)
  • -noinit  (uncheck the Generate Initialization Functions checkbox)
  • -noenumconvert (do not generate enum-to-string conversion functions – should only be enabled if print functions are generated)

Other options that you may or may not be able use:

  • -lax (Do not generate constraint checks)
  • -strict-size (Interpret size constraints strictly)

If all of these measures are employed, users could potentially see the size of their application reduced by one half or more.


Performance Improvements in ASN1C v7.2

One of the new features announced in the release of ASN1C v7.2 was improved C/C++ PER encode and decode performance.  This blog post provides some details on the improvements.

We measured a number of different messages types, but two that stood out were the improvement in encoding and decoding unaligned PER messages for LTE RRC and DSRC – two commonly used specifications.   For LTE, we encoded a sample of DL-DCCH-Message messages.  For DSRC, a set of BasicSafetyMessage messages were used.

The time in milliseconds to decode and encode 100000 records between v71x and v72x is shown in the following charts:

The chart on the left shows decoding and on the right encoding.  As can be seen, decoding performance for LTE RRC improved by over 100% while for DSRC, the gain was approximately 50%.  Encoding performances gains were not as dramatic with improvements of 28% and 18% respectively.

So to what to attribute these gains?  The main improvement was in doing calculations that were being done in the run-time to be done at compile time and thus generating simpler code for things such as constraint checking.  Similar improvements were made in the generation of code specifically targeted as “unaligned PER” (or UPER as it is commonly known) through the use of the -uper command-line option.  This resulted in the removal of code that checked for aligned or unaligned PER at run-time.

Finally, we introduced a new kind of simplified memory management called static memory blocks that contains some limitations on use but which is much faster because rather than having to carve up blocks, it simply always sequentially allocates going forward.  Further details on this are available at the following URL: