123-20 IRIG 106 Chapter10 Programmers Handbook
123-20 IRIG 106 Chapter10 Programmers Handbook
Telemetry Group
August 2020
Prepared by
TELEMETRY GROUP
RANGE COMMANDERS COUNCIL
Published by
Secretariat
Range Commanders Council
U.S. Army White Sands Missile Range,
New Mexico 88002-5110
This page intentionally left blank.
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Table of Contents
Foreword ....................................................................................................................................... ix
Acronyms ...................................................................................................................................... xi
Chapter 1. Scope.................................................................................................................... 1-1
1.1 General ............................................................................................................................. 1-1
1.2 Document Layout............................................................................................................. 1-1
1.3 Document Conventions .................................................................................................... 1-2
Chapter 2. Recorder Setup and Configuration .................................................................. 2-1
Chapter 3. Data Retrieval..................................................................................................... 3-1
3.1 Small Computer Systems Interface (SCSI) Protocol ....................................................... 3-1
3.1.1 Institute of Electrical and Electronics Engineers (IEEE) 1394 ............................ 3-5
3.1.2 Fibre Channel ....................................................................................................... 3-5
3.1.3 Internet Small Computer Systems Interface ........................................................ 3-5
3.2 Software Interface ............................................................................................................ 3-6
3.3 STANAG 4575 Directory ................................................................................................ 3-9
Chapter 4. Recorder Control ............................................................................................... 4-1
4.1 Serial Control ................................................................................................................... 4-1
4.2 Network Control .............................................................................................................. 4-1
Chapter 5. Data File Interpretation .................................................................................... 5-1
5.1 Overall Data File Organization ........................................................................................ 5-1
5.2 Overall Data Packet Organization ................................................................................... 5-2
5.3 Required header ............................................................................................................... 5-3
5.4 Optional secondary header ............................................................................................... 5-4
5.5 Data payload .................................................................................................................... 5-5
5.5.1 Type 0x00, Computer-Generated Data, Format 0 ............................................... 5-6
5.5.2 Type 0x01, Computer-Generated Data, Format 1 (Setup Record) ...................... 5-6
5.5.3 Type 0x02, Computer-Generated Data, Format 2 (Recording Events) ............... 5-8
5.5.4 Type 0x03, Computer-Generated Data, Format 3 (Recording Index) ............... 5-10
5.5.5 Type 0x04, Computer-Generated Data, Format 4 (Streaming
Configuration Records) ...................................................................................... 5-12
5.5.6 Type 0x05 - 0x07, Computer-Generated Data, Format 5 – Format 7................ 5-13
5.5.7 Type 0x08, PCM Data, Format 0 ....................................................................... 5-13
5.5.8 Type 0x09, PCM Data, Format 1 (IRIG 106 Chapter 4/8) ................................ 5-13
5.5.9 Type 0x0A, 0x0F PCM Data, Format 2 – Format 7 .......................................... 5-15
5.5.10 Type 0x10, Time Data, Format 0 ....................................................................... 5-15
5.5.11 Type 0x11, Time Data, Format 1 (IRIG/GPS/RTC).......................................... 5-15
5.5.12 Type 0x12, Time Data, Format 2 (Network Time) ............................................ 5-16
5.5.13 Type 0x13 - 0x17, Time Data, Format 3 – Format 7 ......................................... 5-17
5.5.14 Type 0x18, Military Standard (MIL-STD) 1553 Data, Format 0 ...................... 5-17
5.5.15 Type 0x19, MIL-STD-1553 Data, Format 1 (MIL-STD-1553B Data) ............. 5-17
iii
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
5.5.16 Type 0x1A, MIL-STD-1553 Data, Format 2 (16PP194 Bus) ........................... 5-18
5.5.17 Type 0x1B - 0x1F, MIL-STD-1553 Data, Format 3 - Format 7........................ 5-20
5.5.18 Type 0x20, Analog Data, Format 0 ................................................................... 5-20
5.5.19 Type 0x21, Analog Data, Format 1 (Analog Data) ........................................... 5-20
5.5.20 Type 0x22 - 0x27, Analog Data, Format 2 - Format 7 ...................................... 5-21
5.5.21 Type 0x28, Discrete Data, Format 0 .................................................................. 5-21
5.5.22 Type 0x29, Discrete Data, Format 1 (Discrete Data) ........................................ 5-21
5.5.23 Type 0x2A - 0x2F, Discrete Data, Format 2 - Format 7.................................... 5-22
5.5.24 Type 0x30, Message Data, Format 0 (Generic Message Data) ......................... 5-22
5.5.25 Type 0x31 - 0x37, Message Data, Format 1 - Format 7 .................................... 5-23
5.5.26 Type 0x38, ARINC 429 Data, Format 0 (ARINC429 Data) ............................. 5-23
5.5.27 Type 0x39 - 0x3F, ARINC 429 Data, Format 1 - Format 7 .............................. 5-24
5.5.28 Type 0x40, Video Data, Format 0 (MPEG-2/H.264 Video).............................. 5-24
5.5.29 Type 0x41, Video Data, Format 1 (ISO 13818-1 MPEG-2).............................. 5-25
5.5.30 Type 0x42, Video Data, Format 2 (ISO 14496 MPEG-4 Part 10
AVC/H.264) ....................................................................................................... 5-26
5.5.31 Type 0x43, Video Data, Format 3 (MJPEG) ..................................................... 5-27
5.5.32 Type 0x44, Video Data, Format 4 (MJPEG-2000) ............................................ 5-28
5.5.33 Type 0x45 - 0x47, Video Data, Format 5 - Format 7 ........................................ 5-29
5.5.34 Type 0x48, Image Data, Format 0 (Image Data) ............................................... 5-29
5.5.35 Type 0x49, Image Data, Format 1 (Still Imagery) ............................................. 5-29
5.5.36 Type 0x4A, Image Data, Format 2 (Dynamic Imagery) .................................... 5-30
5.5.37 Type 0x4B - 0x4F, Image Data, Format 3 - Format 7 ....................................... 5-31
5.5.38 Type 0x50, UART Data, Format 0 .................................................................... 5-31
5.5.39 Type 0x51 - 0x57, UART Data, Format 1 - Format 7 ....................................... 5-32
5.5.40 Type 0x58, IEEE-1394 Data, Format 0 (IEEE-1394 Transaction) .................... 5-32
5.5.41 Type 0x59, IEEE-1394 Data, Format 1 (IEEE-1394 Physical Layer) ............... 5-33
5.5.42 Type 0x5A - 0x5F, IEEE-1394 Data, Format 2 - Format 7 ............................... 5-34
5.5.43 Type 0x60, Parallel Data, Format 0 ................................................................... 5-34
5.5.44 Type 0x61 - 0x67, Parallel Data, Format 1 - Format 7 ...................................... 5-35
5.5.45 Type 0x68, Ethernet Data, Format 0 .................................................................. 5-36
5.5.46 Type 0x69, Ethernet Data, Format 1 .................................................................. 5-37
5.5.47 Type 0x6A - 0x6F, Ethernet Data, Format 2 - Format 7 ................................... 5-38
5.5.48 Type 0x70, TSPI/CTS Data, Format 0............................................................... 5-38
5.5.49 Type 0x71, TSPI/CTS Data, Format 1............................................................... 5-39
5.5.50 Type 0x72, TSPI/CTS Data, Format 2............................................................... 5-40
5.5.51 Type 0x73-0x77, TSPI/CTS Data, Format 3 – Format 7 ................................... 5-41
5.5.52 Type 0x78, Controller Area Network Bus ......................................................... 5-41
5.5.53 Type 0x79, Fibre Channel Data, Format 0 ........................................................ 5-42
5.5.54 Type 0x7A, Fibre Channel Data, Format 1........................................................ 5-43
5.5.55 Type 0x7B-0x7F, Fibre Channel Data, Formats 2-7 ......................................... 5-44
5.6 Time Interpretation ........................................................................................................ 5-44
5.7 Index and Event Records ............................................................................................... 5-45
5.8 Data Streaming............................................................................................................... 5-45
Chapter 6. Conformance to IRIG 106 ................................................................................. 6-1
iv
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Table of Figures
Figure 2-1. Example TMATS Attribute Tree ......................................................................... 2-2
Figure 2-2. TMATS Attribute Parser Example Code ............................................................. 2-3
Figure 3-1. SCSI INQUIRY CDB Structure .......................................................................... 3-2
Figure 3-2. SCSI CDB Control Field Structure ...................................................................... 3-2
Figure 3-3. SCSI INQUIRY Data Structure ........................................................................... 3-3
Figure 3-4. SCSI READ CAPACITY CDB Structure ........................................................... 3-4
Figure 3-5. SCSI READ CAPACITY Data Structure ............................................................ 3-4
Figure 3-6. SCSI READ(10) CDB Structure .......................................................................... 3-4
Figure 3-7. SCSI_PASS_THROUGH Structure .................................................................... 3-8
Figure 3-8. STANAG 4575 Directory Block Structure .......................................................... 3-9
v
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
vi
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Figure 5-38. Type 0x29 Discrete Data, Format 1 CSDW ...................................................... 5-21
Figure 5-39. Type 0x29 Discrete Data, Format 1 Message .................................................... 5-22
Figure 5-40. Type 0x30 Message Data, Format 0 CSDW ...................................................... 5-22
Figure 5-41. Type 0x30 Message Data, Format 0 Intra-Packet Header ................................. 5-23
Figure 5-42. Type 0x60 ARINC 429 Data, Format 0 CSDW ................................................ 5-23
Figure 5-43. Type 0x38 ARINC 429 Data, Format 0 Intra-Packet Data Header ................... 5-24
Figure 5-44. Type 0x38 ARINC 429 Data Format ................................................................. 5-24
Figure 5-45. Type 0x40 Video Data, Format 0 CSDW .......................................................... 5-25
Figure 5-46. Type 0x40 Video Data, Format 1 CSDW .......................................................... 5-26
Figure 5-47. Type 0x40 Video Data, Format 2 CSDW .......................................................... 5-27
Figure 5-48. Type 0x43 Video Data, Format 3 (MJPEG) CSDW.......................................... 5-27
Figure 5-49. Type 0x43 Video Data, Format 3 (MJPEG) Intra-packet Header ..................... 5-28
Figure 5-50. Type 0x44 Video Data, Format 3 (MJPEG-2000) CSDW ................................ 5-28
Figure 5-51. Type 0x44 Video Data, Format 4 (MJPEG-2000) Intra-packet Header ............ 5-29
Figure 5-52. Type 0x48 Image Data, Format 0 CSDW .......................................................... 5-29
Figure 5-53. Type 0x49 Image Data, Format 1 CSDW .......................................................... 5-30
Figure 5-54. Type 0x49 Image Data, Format 1 Intra-Packet Header ..................................... 5-30
Figure 5-55. Type 0x4A Image Data, Format 2 (Dynamic Imagery) CSDW ........................ 5-31
Figure 5-56. Type 0x4A Image Data, Format 2 (Dynamic Imagery) Intra-packet Header .... 5-31
Figure 5-57. Type 0x50 UART Data, Format 0 CSDW ......................................................... 5-31
Figure 5-58. Type 0x40 UART Data, Format 0 Intra-Packet Data Header ............................ 5-32
Figure 5-59. Type 0x58 IEEE-1394 Data, Format 0 CSDW .................................................. 5-33
Figure 5-60. Type 0x58 IEEE-1394 Data, Format 1 CSDW .................................................. 5-33
Figure 5-61. Type 0x59 IEEE-1394 Data, Format 1 Intra-Packet Header ............................. 5-34
Figure 5-62. Ampex DCRsi Interface ..................................................................................... 5-35
Figure 5-63. Type 0x60 Parallel Data, Format 0 CSDW ....................................................... 5-35
Figure 5-64. Type 0x68 Ethernet Data, Format 0 CSDW ...................................................... 5-36
Figure 5-65. Type 0x68 Ethernet Data, Format 0 Intra-Packet Header.................................. 5-36
Figure 5-66. Type 0x69 Ethernet Data, Format 1 CSDW ...................................................... 5-37
Figure 5-67. Type 0x69 Ethernet Data, Format 1 Intra-Packet Header.................................. 5-38
Figure 5-68. Type 0x70 TSPI/CTS Data, Format 0 CSDW ................................................... 5-39
Figure 5-69. Type 0x70 TSPI/CTS Data, Format 0 Intra-Packet Header .............................. 5-39
Figure 5-70. Type 0x71 TSPI/CTS Data, Format 1 CSDW ................................................... 5-39
Figure 5-71. Type 0x71 TSPI/CTS Data, Format 1 Intra-Packet Header .............................. 5-40
Figure 5-72. Type 0x72 TSPI/CTS Data, Format 2 CSDW ................................................... 5-41
Figure 5-73. Type 0x72 TSPI/CTS Data, Format 2 Intra-Packet Header .............................. 5-41
Figure 5-74. Type 0x78 CAN Bus CSDW ............................................................................. 5-41
Figure 5-75. Type 0x78 CAN Bus Intra-Packet Header......................................................... 5-42
Figure 5-76. Type 0x79 Fibre Channel, Format 0 CSDW ..................................................... 5-43
Figure 5-77. Type 0x79 Fibre Channel, Format 0 Intra-Packet Header ................................. 5-43
Figure 5-78. Type 0x7A Fibre Channel, Format 1 CSDW..................................................... 5-43
Figure 5-79. Type 0x7A Fibre Channel, Format 1 Intra-Packet Header ................................ 5-44
Figure 5-80. UDP Transfer Header Format 1, Non-Segmented Data .................................... 5-46
Figure 5-81. UDP Transfer Header Format 1, Segmented Data............................................. 5-47
Figure 5-82. UDP Transfer Header Format 2 ......................................................................... 5-47
Figure 5-83. UDP Transfer Header Format 3 ......................................................................... 5-47
vii
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Table of Tables
Table 1-1. Standard-Sized Variable Types............................................................................ 1-2
Table 1-2. Hungarian Notation Prefixes................................................................................ 1-2
Table 6-1. Physical Interface Requirements.......................................................................... 6-1
Table 6-2. Logical Interface Requirements ........................................................................... 6-2
Table A-1. Supported TMATS Code Values ........................................................................ A-1
viii
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Foreword
This handbook is intended to assist programmers to develop software for use with IRIG
106 standard instrumentation recorders. This handbook primarily addresses IRIG 106 Chapter 10
recorders, but also covers aspects of Chapter 6 and Chapter 9.
Task Lead: Mr. James P. Ferrill
Instrumentation Division
412 Test Engineering Group
307 Popson Dr.
Edwards AFB, CA 93524
E-Mail: [email protected]
ix
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
x
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Acronyms
ACTTS Air Combat Test and Training System
Ack Acknowledgement
ACMI Air Combat Maneuvering Instrumentation
ACTS Air Combat Training System
ANSI American National Standards Institute
API application programming interface
ASCII American Standard Code for Information Interchange
AVC Advanced Video Coding
CAN controller area network
CDB Command Descriptor Block
CSDW channel-specific data word
CTS Combat Training System
DCRsi Digital Cartridge Recording System
EAG European Air Group
ERTC Extended Relative Time Counter
FCP Fibre Channel Protocol
FC-PLDA Fibre Channel Private Loop SCSI Direct Attach
GCC Gnu Compiler Collection
GPS Global Positioning System
IAW in accordance with
ICD interface control document
IEEE Institute of Electrical and Electronics Engineers
IETF Internet Engineering Task Force
I/O input/output
IOCTL input/output control code
IP Internet Protocol
IPDH intra-packet data header
IPH intra-packet header
IPTS intra-packet time stamp
IRIG Inter-Range Instrumentation Group
iSCSI Internet Small Computer Systems Interface
IU information unit
KITS Kadena Interim Training System
KLV key-length-value
LBA logical block address
LUN logical unit number
MAC media access control
MBR master boot record
MIL-STD Military Standard
MTU maximum transfer unit
NMEA National Marine Electronics Association
NTP3 Network Time Protocol 3
PCM pulse code modulation
PDU protocol data unit
xi
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
xii
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
CHAPTER 1
Scope
1.1 General
The Telemetry Group of the Range Commanders Council (RCC) has developed the Inter-
Range Instrumentation Group (IRIG) 1061 standard for test range telemetry. The purpose of
IRIG 106 is to define a common framework for test range instrumentation primarily to ensure
test range interoperability. The RCC periodically revises and reissues IRIG 106. A specific
version of IRIG 106 is suffixed with the last two digits of the year it was released. For example
IRIG 106-07 refers to the version of IRIG 106 released in 2007.
The IRIG 106 is composed of 19 chapters, each devoted to a different element of the
telemetry system or process. One of the major topics of the IRIG 106 standard is Chapter 10, the
Digital Recording Standard.2 Chapter 10 defines the interfaces and operational requirements for
digital data recording devices. Chapter 10 also references elements of Chapter 6, Recorder &
Reproducer Command and Control3, and Chapter 9, Telemetry Attributes Transfer Standard4
(TMATS).
Chapter 10 is quite comprehensive in its scope. The purposes of this handbook are to
serve as an adjunct to the IRIG 106 standard to help the computer programmer write software for
operating IRIG 106 Chapter 10 standard digital recorders, and to analyze data from these
recorders. A prior working knowledge of Chapters 9 and 10, as well as applicable sections of
Chapter 6 is essential.
1
Range Commanders Council. Telemetry Standards. IRIG 106-20. July 2020. May be superseded by update.
Retrieved 11 August 2020. Available at https://www.trmc.osd.mil/wiki/download/attachments/105349356/106-
20_Telemetry_Standards.pdf.
2
Range Commanders Council. “Digital Recording Standard” in Telemetry Standards. IRIG 106-20 Chapter 10. July
2020. May be superseded by update. Retrieved 11 August 2020. Available at
https://www.trmc.osd.mil/wiki/download/attachments/105349356/chapter10.pdf.
3
Range Commanders Council. “Recorder & Reproducer Command and Control” in Telemetry Standards. IRIG 106-
20 Chapter 6. July 2020. May be superseded by update. Retrieved 11 August 2020. Available at
https://www.trmc.osd.mil/wiki/download/attachments/105349356/chapter6.pdf.
4
Range Commanders Council. “Telemetry Attributes Transfer Standard” in Telemetry Standards. IRIG 106-20
Chapter 9. July 2020. May be superseded by update. Retrieved 11 August 2020. Available at
https://www.trmc.osd.mil/wiki/download/attachments/105349356/Chapter9.pdf.
1-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
1-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
CHAPTER 2
2-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Attribute lines can be easily parsed using the string tokenizer function strtok() in the
C run time library. An example approach outline for TMATS parsing is shown in Figure 2-2.
The TMATS attribute line is stored in the null terminated character array szLine[]. The code
name string is pointed to by szCodeName and the data item value is pointed to by
szDataItem. Specific parsers are called for specific attribute types, indicated by the first letter
of the code name. After all TMATS attributes are read, they are linked into a hierarchical tree. A
more complete example of TMATS parsing is presented in Appendix D.
2-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
char szLine[2048];
char * szCodeName;
char * szDataItem;
// Split the line into left hand and right hand sides
szCodeName = strtok(szLine, ":");
szDataItem = strtok(NULL, ";");
There are two basic types of attribute code names: single entry and multiple entry.
Single-entry attributes are those for which there is only one data item and appear once in
TMATS. For example:
G\PN:EW EFFECTIVENESS;
Multiple-entry attributes may appear multiple times. They are distinguished by a numeric
identifier preceded by a hyphen. For example:
2-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
G\DSI-1:Aircraft;
G\DSI-2:Missile;
G\DSI-3:Target;
Some attributes can appear multiple times at multiple levels. For example, the Message
Data Sub-Channel Name attribute “R-x\MCNM-n-m” may appear associated with multiple
recorder groups (“x”), multiple message data channels (“n”), and with multiple subchannels
(“m”).
Chapter 9 identifies quite a few required TMATS attributes. These attributes are
necessary to ensure correct recorder setup and subsequent data interoperability. For correct
TMATS parsing and interpretation, an important required attribute is “G\106”. This attribute
identifies the version of IRIG 106 to use when interpreting the TMATS information. This
attribute only identifies the TMATS version. The overall recorder version is specified in the
TMATS setup record in the recorded data file described in Subsection 5.5.2.
Chapter 9 states that attributes may appear in any order. Chapter 10, however, requires
some specific TMATS comment attributes follow other specific modified TMATS attributes for
modified data files. This complicates TMATS machine parsing considerably. When reading and
decoding TMATS, a parser must maintain the most recent recorder data channel state so that
when a comment attribute is encountered, it can be associated with the correct recorder channel.
When writing TMATS, the appropriate comments must follow the appropriate attribute records.
See Chapter 10 for specific TMATS attribute position and order requirements.
Chapter 9 of IRIG 106-07 introduced support for TMATS to be represented in XML
format. Although XML TMATS was defined in 106-07 Chapter 9, there was no way to
distinguish traditional American Standard Code for Information Interchange (ASCII) TMATS
from XML TMATS in an IRIG 106-07 Setup Record packet. Chapter 10 of IRIG 106-09 added a
field to the Setup Record packet to indicate format of the TMATS record. The TMATS XML
format is implemented as a standard XML schema consisting of a collection of XML schema
definition (XSD) files. The TMATS XSDs can be viewed at the official RCC site. Although
XML TMATS is maintained in parallel with traditional ASCII TMATS, XML TMATS is not
widely supported in the test community.
The TMATS standard has evolved considerably from year to year. Appendix A is a chart
of legal TMATS attributes by IRIG 106 release year.
2-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
CHAPTER 3
Data Retrieval
3.1 Small Computer Systems Interface (SCSI) Protocol
Recorded data from a Chapter 10 recorder is retrieved by transferring it to a host
computer over one of several interfaces provided by the recorder. Chapter 10 requires that each
removable memory module (RMM) provide an IEEE 1394b data download port. Chapter 10 also
requires that each recorder provide either a Fibre Channel or IEEE 1394b data download port,
and optionally an Ethernet download port.
The protocol for data download over the various interface types is the SCSI block transfer
protocol. Overall SCSI operation is defined in the SCSI Architecture Model 2 (SAM-2)5
document. Common commands are defined in the SCSI Primary Commands (SPC-2)6 document.
Commands for block devices are defined in the SCSI Block Commands 2 (SBC-2)7 document.
The SCSI architecture is a client-server model. The client is the user application (the
“initiator”), requesting services (status, data, etc.) from the SCSI server device (the “target”). An
application client is independent of the underlying interconnect and SCSI transport protocol.
Each SCSI target is identified by a target device name. Targets are addressed using the target
device name. Different transports support different methods for uniquely naming SCSI targets.
Each target device also supports one or more logical unit numbers (LUNs), which are used to
support different services from a single SCSI target device. For example, an RMM provides disk
file access using LUN 0 and real-time clock access using LUN 1.
The SCSI architecture model defines a Command Descriptor Block (CDB) structure
along with associated user input/output (I/O) buffers. In order to issue a command to a SCSI
device, a CDB must be used. The SCSI protocol defines a large number of commands to support
a wide range of devices. The Chapter 10 standard only requires a small subset of the complete
SCSI command set to be implemented to support the RMM and remote data access block
transfer device. Acceptable lengths for CDBs can be 6, 10, 12, or 16 bytes. Chapter 10 currently
only requires 6- and 10-byte CDBs. Note that multi-byte CDB values such as logical block
address (LBA) are big-endian in the CDB and require writing to the CDB a byte at a time from a
little-endian processor to write the multi-byte values in proper order.
The SCSI INQUIRY command is used to query the SCSI device about its capabilities.
The structure for the INQUIRY CDB is shown in Figure 3-1. The structure for the Control field
is shown in Figure 3-2. The data download interface is required to support the standard
5
ISO/IEC. Information Technology – Small Computer System Interface (SCSI) Part 412: Architecture Model-2
(SAM-2). ISO/IEC 14776-412. October 2006. Retrieved 12 August 2019. Available for purchase at
https://www.iso.org/standard/39517.html.
6
ISO/IEC. Information Technology – Small Computer System Interface (SCSI) Part 452: SCSI Primary Commands-
2 (SPC-2). ISO/IEC 14776-452:2005. August 2005. Retrieved 12 August 2019. Available for purchase at
https://www.iso.org/standard/38775.html.
7
ISO/IEC. Information Technology – Small Computer System Interface (SCSI) Part 322: SCSI Block Commands-2
(SBC-2). ISO/IEC 14776-322:2007. February 2007. Retrieved 12 August 2019. Available for purchase at
https://www.iso.org/standard/42101.html.
3-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
INQUIRY response shown in Figure 3-3. Also required are the Supported Vital Product page,
Unit Serial Number page, and Device Identification page.
struct SuCdbInquiry
{
uint8_t uOpCode; // Operation code = 0x12
uint8_t bEVPD : 1; // Enable vital product data
uint8_t bCmdDt : 1; // Command support data
uint8_t Reserved1 : 6; //
uint8_t uPageOpCode; // Page or operation code
uint8_t Reserved2; //
uint8_t uAllocLength; // Allocation length
struct SuCdbControl suControl;
};
struct SuCdbControl
{
uint8_t bLink : 1;
uint8_t Obsolete : 1;
uint8_t bNACA : 1;
uint8_t Reserved : 3;
uint8_t uVendor : 2;
};
3-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SuCdbInquiryStdData
{
uint8_t uPeriphType : 5; // Peripheral device type
uint8_t uPeriphQual : 3; // Peripheral qualifier
uint8_t uReserved1 : 7;
uint8_t bRMB : 1; // Removable medium
uint8_t uVersion; // Version
uint8_t uFormat : 4; // Response data format
uint8_t bHiSup : 1; // Hierarchical support
uint8_t bNormACA : 1; // Support normal ACA bit
uint8_t uReserved2 : 1;
uint8_t bAERC : 1; // Asynch event reporting cap
uint8_t uAddLength; // Length of add parameters
uint8_t uReserved3 : 7;
uint8_t bSCCS : 1; // Embedded storage supported
uint8_t bAddr16 : 1; // Not used
uint8_t uReserved4 : 2;
uint8_t bMChngr : 1; // Medium changer
uint8_t bMultiP : 1; // Multi-port device
uint8_t bVS1 : 1; // Vendor specific
uint8_t bEncServ : 1; // Enclosure service
uint8_t bBQue : 1; // Basic queing
uint8_t bVS2 : 1; // Vendor specific
uint8_t bCmdQue : 1; // Command queuing supported
uint8_t uReserved5 : 1;
uint8_t bLinked : 1; // Linked commands supported
uint8_t bSync : 1; // Not used
uint8_t bWBus16 : 1; // Not used
uint8_t uReserved6 : 1;
uint8_t bRelAddr : 1; // Relative addressing supported
uint8_t uVendorID[8]; //
uint8_t uProductID[16]; //
uint8_t uProductRev[4]; //
};
The SCSI READ CAPACITY command is used to query the disk device about its size.
The structure for the READ CAPACITY CDB is shown in Figure 3-4. This command returns the
number of available logical blocks and the logical block size in bytes, shown in Figure 3-5. Note
that returned values are big-endian and must be byte swapped before they can be used on a little-
endian processor.
3-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SuCdbReadCapacity10
{
uint8_t uOpCode; // Operation code = 0x25
uint8_t uReserved1; //
uint8_t uLBA_3_MSB; // Logical block address, MSB
uint8_t uLBA_2; // Logical block address
uint8_t uLBA_1; // Logical block address
uint8_t uLBA_0_LSB; // Logical block address, LSB
uint8_t uReserved2; //
uint8_t uReserved3; //
uint8_t bPMI : 1; // Partial medium indicator
uint8_t uReserved3 : 7; //
struct SuCdbControl suControl;
};
struct SuCdbReadCapacityData
{
uint64_t uBlocks; // Logical blocks (big endian!)
uint64_t uBlockSize; // Block size (big endian!)
};
The SCSI READ command is used to read logical blocks of data from the disk device.
The SCSI protocol provides five different READ commands with various capabilities and sizes
of the CDB. The Chapter 10 standard only requires the 10-byte variant of the READ command.
The structure for the READ CDB is shown in Figure 3-6. This command returns the data from
the requested logical blocks.
struct SuCdbRead10
{
uint8_t uOpCode; // Operation code = 0x28
uint8_t bReserved1 : 1; //
uint8_t bFUA_NV : 1; // Force unit access non-volatile
uint8_t Reserved2 : 1; //
uint8_t bFUA : 1; // Force unit access
uint8_t bDPO : 1; // Disable page out
uint8_t bRdProtect : 3; // Read protect
uint8_t uLBA_3_MSB; // Logical block address, MSB
uint8_t uLBA_2; // Logical block address
uint8_t uLBA_1; // Logical block address
uint8_t uLBA_0_LSB; // Logical block address, LSB
uint8_t uGroupNum : 5; // Group number
uint8_t Reserved3 : 3; //
uint8_t uTransLength_1_MSB; // Transfer length, MSB
uint8_t uTransLength_0_LSB; // Transfer length, LSB
struct SuCdbControl suControl;
};
3-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
8
Institute of Electrical and Electronics Engineers. IEEE Standard for a High-Performance Serial Bus. IEEE 1394-
2008. New York: Institute of Electrical and Electronics Engineers, 2008.
9
Internet Engineering Task Force. “Multi-Protocol Label Switching (MPLS) Support of Differentiated Services.”
RFC 3270. May 2002. Updated by RFC 5462. Retrieved 12 August 2019. Available at
http://datatracker.ietf.org/doc/rfc3270/.
3-5
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
information to establish a TCP connection, and it uses the iSCSI target name information
to establish an iSCSI session. This discovery option is convenient for small iSCSI setups.
SendTargets: This mechanism assumes that the target's IP address and TCP port
information are already available to the initiator. The initiator then uses this information
to establish a discovery session to the network entity. The initiator then subsequently
issues the SendTargets text command to query information about the iSCSI targets
available at the particular network entity (IP address).
Zero-Configuration: This mechanism assumes that the initiator does not have any
information about the target. In this option, the initiator can either multicast discovery
messages directly to the targets or it can send discovery messages to storage name
servers. Currently, there are many general-purpose discovery frameworks available.
Service Location Protocol (RFC 260810) and Internet Storage Name Service (RFC
417111) are two popular discovery protocols.
Target discovery is not specified in Chapter 10.
When interfacing to a recorder, LUN 0 or LUN 32 is used for disk access while LUN 1 or
LUN 33 is used for command and control.
10
Internet Engineering Task Force. “Service Location Protocol, Version 2.” RFC 2608. June 1999. Updated by RFC
3224. Retrieved 12 August 2019. Available at http://datatracker.ietf.org/doc/rfc2608/.
11
Internet Engineering Task Force. “Internet Storage Name Service (iSNS).” RFC 4171. September 2005. May be
superseded by update. Retrieved 12 August 2019. Available at https://datatracker.ietf.org/doc/rfc4171/.
3-6
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
the SCSI port name is used, the Win32 application must set the proper PathId, TargetId,
and LUN in the SPT structure.
Once a valid handle to a SCSI device is obtained, then appropriate I/O buffers for the
requested IOCTL must be allocated and, in some cases, filled in correctly.
There are several IOCTLs that the SCSI port driver supports, including the following.
IOCTL_SCSI_GET_INQUIRY_DATA
IOCTL_SCSI_GET_CAPABILITIES
IOCTL_SCSI_PASS_THROUGH
IOCTL_SCSI_PASS_THROUGH_DIRECT
IOCTL_SCSI_GET_INQUIRY_DATA returns a SCSI_ADAPTER_BUS_INFO
structure for all devices that are on the SCSI bus. The structure member, BusData, is a structure
of type SCSI_BUS_DATA. It contains an offset to the SCSI Inquiry data, which is also stored as
a structure, SCSI_INQUIRY_DATA.
Within the SCSI_INQUIRY_DATA is a structure member named DeviceClaimed,
which indicates whether or not a class driver has claimed this particular SCSI device. If a device
is claimed, all SPT requests must be sent first through the class driver, which will typically pass
the request unmodified to the SCSI port driver. If the device is unclaimed, the SPT requests are
sent directly to the SCSI port driver.
For IOCTL_SCSI_GET_INQUIRY_DATA, data is only read from the device and not
sent. Set lpInBuffer to NULL and nInBufferSize to zero. The output buffer might be
quite large, as each SCSI device on the bus will provide data that will fill three structures for
each device: SCSI_ADAPTER_BUS_INFO, SCSI_BUS_DATA, and
SCSI_INQUIRY_DATA. Allocate a buffer that will hold the information for all the devices on
that particular SCSI adapter. Set lpOutBuffer to point to this allocated buffer and
nOutBufferSize to the size of the allocated buffer.
IOCTL_SCSI_GET_CAPABILITIES returns an IO_SCSI_CAPABILITIES
structure. This structure contains valuable information about the capabilities of the SCSI adapter.
Two items of note are the MaximumTransferLength, which is a byte value indicating the
largest data block that can be transferred in a single SCSI Request Block, and the
MaximumPhysicalPages, which is the maximum number of physical pages that a data
buffer can span.
The two IOCTLs IOCTL_SCSI_PASS_THROUGH and
IOCTL_SCSI_PASS_THROUGH_DIRECT allow SCSI CDBs to be sent from a Win32
application to a SCSI device. Depending on which IOCTL is sent, a corresponding pass through
structure is filled out by the Win32 application. IOCTL_SCSI_PASS_THROUGH uses the
structure SCSI_PASS_THROUGH. IOCTL_SCSI_PASS_THROUGH_DIRECT uses the
structure SCSI_PASS_THROUGH_DIRECT. The SCSI_PASS_THROUGH structure is shown
in Figure 3-7.
3-7
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SCSI_PASS_THROUGH
{
USHORT Length;
UCHAR ScsiStatus;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
UCHAR CdbLength;
UCHAR SenseInfoLength;
UCHAR DataIn;
ULONG DataTransferLength;
ULONG TimeOutValue;
ULONG DataBufferOffset;
ULONG SenseInfoOffset;
UCHAR Cdb[16];
}
3-8
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
the SenseInfo buffer from the beginning of the pass through structure. Finally, the 16
remaining bytes are for the CDB data. The format of this data must conform to the SCSI-2
standard (ISO/IEC 2006).
struct SuStanag4575DirBlock
{
uint8_t achMagicNumber[8] // "FORTYtwo"
uint8_t uRevNumber; // IRIG 106 Revision number
uint8_t uShutdown; // Dirty shutdown
uint16_t uNumEntries; // Number of file entries
uint32_t uBlockSize; // Bytes per block
uint8_t achVolName[32]; // Volume Name
uint64_t uFwdLink; // Forward link block
uint64_t uRevLink; // Reverse link block
struct SuStanag4575FileBlock asuFileEntry[4];
};
3-9
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SuStanag4575FileBlock
{
uint8_t achFileName[56]; // File name
uint64_t uFileStart; // File start block addr
uint64_t uFileBlkCnt; // File block count
uint64_t uFileSize; // File size in bytes
uint8_t uCreateDate[8]; // File create date
uint8_t uCreateTime[8]; // File create time
uint8_t uTimeType; // Date and time type
uint8_t achReserved[7]; //
uint8_t uCloseTime[8]; // File close time
};
A complete disk file directory is read starting at LBA 1. The first directory block is read
and all file entries in that block are read and decoded. Then the next directory block, LBA equal
to the value in uFwdLink, is read and decoded. Directory reading is finished when the
uFwdLink is equal to the current LBA. This algorithm is shown in Figure 3-10.
3-10
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
3-11
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
3-12
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
CHAPTER 4
Recorder Control
Recorders are controlled over a full duplex communications channel. Typically this
channel is an RS-232 or RS-422 serial communications port. Chapter 10 also allows control over
a recorder network channel.
The recorder command and control mnemonics language is defined in Chapter 6, with
further requirements in Chapter 10. Interaction with a recorder is in a command/control fashion.
That is, an external controller issues commands to a recorder over the command and control
channel, and the recorder issues a single status response message.
Some commands, such as .BIT, can take a significant amount of time to complete. The
proper method to determine when these commands complete is to issue multiple .STATUS
commands, checking the status complete field until it indicates the command has completed
processing.
4-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
for network-based control and status a recorder is required to implement the Telnet standard
defined in RFC 85412, RFC 85513, and RFC 118414 on TCP port 10610.
Although the full Telnet protocol is required for recorders, it is common for network
client software to connect to a recorder Telnet port via a simple TCP port connection without the
Telnet protocol negotiation.
12
Internet Engineering Task Force. “Telnet Protocol Specification.” RFC 854. May 1983. Updated by RFC 5198.
Retrieved 26 June 2019. Available at http://datatracker.ietf.org/doc/rfc854/.
13
Internet Engineering Task Force. “Telnet Option Specifications.” RFC 855. May 1983. May be superseded by
update. Retrieved 26 June 2019. Available at http://datatracker.ietf.org/doc/rfc855/.
14
Internet Engineering Task Force. “Telnet Linemode Option.” RFC 1184. March 2013. May be superseded by
update. Retrieved 26 June 2019. Available at http://datatracker.ietf.org/doc/rfc1184/.
4-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
CHAPTER 5
5-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
period as the data from the first channel and will have identical time stamps but will be recorded
after the first channel in the data file.
Starting with the IRIG 106-05 standard, recorders are only allowed to buffer data for a
maximum of 100 milliseconds and data packets must be written to disk within one second. This
ensures that data packets can only be out of time order by a maximum of one second. Be warned,
though, that the maximum amount of time data packets can be out of order for data files
produced before IRIG 106-05 is unbounded and it is not unusual to encounter data files with data
packets five or more seconds out of time order.
Example source code that demonstrates basic parsing of Chapter 10 data files can be
found in Appendix B. An example program that demonstrates reading and interpreting a Chapter
10 file can be found in Appendix C.
Data packets must contain data. They are not allowed to only contain filler, although
filler can be inserted into a data packet in the packet trailer before the checksum. This filler is
5-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
used to ensure data packet alignment on a four-byte boundary. Filler is also sometimes used to
keep packets from a particular channel the same length. The standard does not expressly prohibit
filler after the packet trailer but before the next data packet header, but inserting filler after the
last trailer is considered bad practice. Still, when reading data packets, set read buffer sizes based
on the value of the overall packet length found in the header. Do not make assumptions about
packet length based on the data length or from information in the data payload.
When reading linearly through a Chapter 10 data file, maintaining synchronization with
data packet boundaries is accomplished by using the packet length field in the header to read the
appropriate amount of data or to reposition the read pointer to the beginning of the next header.
In this case it is sufficient to check the value of the Sync field at the beginning of the header to
ensure the read pointer was positioned to the beginning of a data packet.
If there is an error in the data file or if the read pointer is repositioned to some place other
than the beginning of a data packet (for example to jump to the middle of a recorded data file),
then the beginning of a valid data packet must be found. Unfortunately the Chapter 10 standard
does not provide a way to definitively determine the beginning of a data packet in these
instances. Instead some heuristics must be applied.
Read the data file until the packet sync pattern (0xEB25) is found. (Normally the first
character of the packet sync pattern is found at a file offset that is an integer multiple of
four. If the data file is corrupted then the sync pattern may not fall on the normal four-
byte boundary. For the best results scan the file a byte at a time, ignoring the normal four-
byte alignment.)
When the Sync pattern is found then calculate and test the header checksum.
If a secondary header exists, calculate and test the secondary header checksum.
Calculate and test the data checksum.
When the packet sync pattern is found and all available checksums have been verified,
then there is a high probability that the beginning of the next valid data packet has been found.
5-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
The Channel ID field uniquely identifies the source of the data. The value of the Channel
ID field corresponds to the Track Number value of the TMATS “R” record. This field was
extended to five characters in the 2009 release of IRIG 106.
Typically only one packet data type is associated with a particular Channel ID, but this is
not a requirement of the Chapter 10 standard. An exception to this is Channel ID = 0, the
Channel ID used for internal, computer-generated format data packets. Prior to IRIG 106-13 it
was typical for Channel ID 0 to contain Computer-Generated Data, Format 0 setup records
(0x01), Computer-Generated Data, Format 1 recording events records (0x02), and Computer-
Generated Data, Format 3 recording index records (0x03).
With the release of IRIG 106-13 Channel 0 has been restricted to Computer-Generated
Data, Format 0 (TMATS setup) records only. With the release of IRIG 106-17 Channel 0 can
also contain Computer-Generated Data, Format 4 (TMATS Streaming Configuration) records.
Furthermore, any other channel containing a particular format of computer-generated data is only
allowed to have packets of that format.
The data payload format is interpreted based on the value of the Data Type field and the
Data Version field (sometimes incorrectly called Header Version) in the packet header. Each
packet data payload can only contain one type (e.g., 1553, PCM, etc.) of data. A Chapter 10
standard release will only contain data format and layout information for the latest Data Version.
The specific Data Version defined in a particular Chapter 10 release can be found in the “Data
Type Names and Descriptions” table. Be warned that future Chapter 10 releases may update or
change data format or layout, indicated by a different Data Version value in the header, but the
Chapter 10 release will not have information about the previous Data Versions. That information
can only be found in the previous Chapter 10 releases.
When processing a data file, it is common to only read the data packet header, determine
if the data portion is to be read (based on packet type or other information gleaned from the
header), and if not to be read skip ahead to the next header. Skipping the data portion and
jumping ahead to the next header is accomplished by using the packet length in the packet
header. Below is the algorithm for determining how many bytes to jump ahead in the file byte
stream to reposition the read pointer to the beginning of the next header.
Read the current primary header.
Determine relative file offset to the next header.
Offset = Packet Length - Primary Header Length (24)
Move read pointer.
5-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SuI106Ch10SecHeader_Ch4Time
{
uint16_t uUnused; //
uint16_t uHighBinTime; // High order time
uint16_t uLowBinTime; // Low order time
uint16_t uUSecs; // Microsecond time
uint16_t uReserved; //
uint16_t uSecChecksum; // Secondary Header Checksum
};
Figure 5-3. Optional Secondary Header Structure with IRIG 106 Ch 4 Time
Representation
struct SuI106Ch10SecHeader_1588Time
{
uint32_t uNanoSeconds; // Nano-seconds
uint32_t uSeconds; // Seconds
uint16_t uReserved; //
uint16_t uSecChecksum; // Secondary Header Checksum
};
Figure 5-4. Optional Secondary Header Structure with IEEE-1588 Time
Representation
struct SuI106Ch10SecHeader_ERTCTime
{
uint32_t uLSLW; // Least significant long word
uint32_t uMSLW; // Most significant long word
uint16_t uReserved; //
uint16_t uSecChecksum; // Secondary Header Checksum
};
Figure 5-5. Optional Secondary Header Structure with ERTC Time
Representantion
5-5
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SuIntrPacketTime_RTC
{
uint8_t aubyRelTime[6]; // 48 bit RTC
uint16_t uUnused; //
};
Figure 5-6. Intra-Packet Time Stamp, 48-bit RTC
struct SuIntrPacketTime_Ch4Time
{
uint16_t uUnused; //
uint16_t uHighBinTime; // High order time
uint16_t uLowBinTime; // Low order time
uint16_t uUSecs; // Microsecond time
};
Figure 5-7. Intra-Packet Time Stamp, IRIG 106 Ch 4 Binary
struct SuIntrPacketTime_1588Time
{
uint32_t uNanoSeconds; // Nano-seconds
uint32_t uSeconds; // Seconds
};
Figure 5-8. Intra-Packet Time Stamp, IEEE-1588
struct SuIntrPacketTime_ERTCTime
{
uint32_t uLSLW; // Least significant long word
uint32_t uMSLW; // Most significant long word
};
Figure 5-9. Intra-Packet Time Stamp, 64-bit ERTC
5-6
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Note that iCh10Ver and bConfigChange fields of the CSDW first appeared in 106-
07. Since unused fields are required to be zero filled, data files prior to IRIG 106-07 will have a
value of zero in the iCh10Ver field.
The bXMLFormat field first appeared in IRIG 106-09. When set the bXMLFormat flag
indicates the format of the TMATS setup record is in XML format. Although the traditional
TMATS format and XML TMATS formats are maintained in parallel and both are legal in all
cases, the XML TMATS version is uncommon. There is currently limited support for XML-
formatted TMATS.
The first data packet in a Chapter 10 data file must be a TMATS setup record. Under
certain conditions, TMATS setup records may also be found later in the same recorded data file.
In particular, subsequent TMATS records may occur during network data streaming of Chapter
10 data to allow network data users to learn the recorder configuration after recording and
streaming has begun. The bConfigChanged flag is used to indicate whether this TMATS
setup record is different than the previous TMATS setup record (i.e., the recorder configuration
changed) or whether it duplicates the previous TMATS setup record.
The data that follows the CSDW in the data packet is the TMATS setup information in
Chapter 9 format.
The TMATS fields change quite a bit from year to year. A summary of valid TMATS
fields for each IRIG 106 release is presented in Appendix A.
The 106-09 standard made considerable changes to the TMATS “S” records, the Message
Data Attributes Group. Numerous R Record fields were added to document recorder
configuration and track changes to edited data files. Message filtering for PCM and 1553 are
now supported. The 1553 recorder control is defined. Video time overlay is defined. Universal
Asynchronous Receiver and Transmitter (UART) subchannel interface parameters are defined.
Numerous “B” bus parameters were added.
The 106-11 standard added “R” group user-defined channel IDs and various event source
definitions. In the “P” group numerous PCM subframe definitions were replaced. The PCM
asynchronous data merge format parameters were defined. In the “D” group numerous subframe
parameter definitions were deleted.
The 106-13 standard added numerous “R” group additions to define channel groups,
drive groups, volumes, links, image sensor settings, and controller area network (CAN) bus
subchannels. In the “P” group CRC error checking parameters and fill bits were defined. The
“A” Pulse Amplitude Modulation (PAM) Attributes group was totally removed.
The 106-15 standard added a “G” group Message Digest Checksum for TMATS intregity
checking. In the “R” group analog subchannel enable was defined and Fibre Channel setup was
defined.
The 106-17 standard primarily added parameters to the “R” group to better define
Etherenet publishing. In the “P” and “D” groups superfluous “End Frame” parameters were
removed to better align usage with the XML TMATS standard.
5-7
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
There are various permutations of recorded events. In fact, there are enough permutations
that it makes sense to represent the data message layout in non-specific terms. Later, during
packet processing, generic data fields can be cast to their specific formats. Event data without
optional data (bIntraPckHdr = 0) is shown in Figure 5-13. Event data with optional data
(bIntraPckHdr = 1) is shown in Figure 5-14. The format for the event message itself is
shown in Figure 5-15.
struct SuEvents
{
uint8_t aubyIntPktTime[8]; // Intra-packet time stamp
struct SuEvents_Data suData; // Data about the event
};
Figure 5-13. Type 0x02 Computer-Generated Data, Format 2 (Events) Message
without Optional Data
struct SuEvents_with_Optional
{
uint8_t aubyIntPktTime[8]; // Intra-packet time stamp
uint64_t suIntrPktData; // Intra-packet data
struct SuEvents_Data suData; // Data about the event
};
Figure 5-14. Type 0x02 Computer-Generated Data, Format 2 (Events) Message
with Optional Data
struct SuEvents_Data
{
uint32_t uNumber : 12; // Event identification number
uint32_t uCount : 16; // Event count index
uint32_t bEventOccurence : 1; //
uint32_t uReserved : 3; // Time tag bits
};
Figure 5-15. Type 0x02 Computer-Generated Data, Format 2 (Events) Message
Data
5-8
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
The aubyIntPktTime field in the data structures of Figure 5-13 and Figure 5-14
represents event time in 48-bit relative time format derived from the RTC shown in Figure 5-6,
64-bit extended relative time format shown in Figure 5-9, absolute time in Chapter 4 format
shown in Figure 5-7, or IEEE-1588 time format shown in Figure 5-8.
If the event message includes the optional suIntrPktData IPH field, shown in the
data structure of Figure 5-14, this field holds the absolute time of the event. The format of this
data is the same as the Time Data Packet Format 1, depicted in Figure 5-16 and Figure 5-17.
Unfortunately Time Data Packet Format 1 represents time in more than one format and this data
format does not include a method to determine which time format is used in the IPH. For this
reason, this field should be used with caution, if used at all.
struct SuTime_MsgDayFmt
{
uint16_t uTmn : 4; // Tens of milliseconds
uint16_t uHmn : 4; // Hundreds of milliseconds
uint16_t uSn : 4; // Units of seconds
uint16_t uTSn : 3; // Tens of seconds
uint16_t Reserved1 : 1; // 0
uint16_t uMn : 4; // Units of minutes
uint16_t uTMn : 3; // Tens of minutes
uint16_t Reserved2 : 1; // 0
uint16_t uHn : 4; // Units of hours
uint16_t uTHn : 2; // Tens of Hours
uint16_t Reserved3 : 2; // 0
uint16_t uDn : 4; // Units of day number
uint16_t uTDn : 4; // Tens of day number
uint16_t uHDn : 2; // Hundreds of day number
uint16_t Reserved4 : 6; // 0
};
Figure 5-16. Type 0x11 Time Data, Format 1 Structure, Day Format
5-9
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SuTime_MsgDmyFmt
{
uint16_t uTmn : 4; // Tens of milliseconds
uint16_t uHmn : 4; // Hundreds of milliseconds
uint16_t uSn : 4; // Units of seconds
uint16_t uTSn : 3; // Tens of seconds
uint16_t Reserved1 : 1; // 0
uint16_t uMn : 4; // Units of minutes
uint16_t uTMn : 3; // Tens of minutes
uint16_t Reserved2 : 1; // 0
uint16_t uHn : 4; // Units of hours
uint16_t uTHn : 2; // Tens of Hours
uint16_t Reserved3 : 2; // 0
uint16_t uDn : 4; // Units of day number
uint16_t uTDn : 4; // Tens of day number
uint16_t uOn : 4; // Units of month number
uint16_t uTOn : 1; // Tens of month number
uint16_t Reserved4 : 3; // 0
uint16_t uYn : 4; // Units of year number
uint16_t uTYn : 4; // Tens of year number
uint16_t uHYn : 4; // Hundreds of year number
uint16_t uOYn : 2; // Thousands of year number
uint16_t Reserved5 : 2; // 0
};
Figure 5-17. Type 0x11 Time Data, Format 1 Structure, DMY Format
Data about the recorded event is found in the SuEvents_Data structure shown in
Figure 5-15. The particular event is identified by the uNumber field, which corresponds to the
recording event index number (i.e., the “n” value in “R-x\EV\ID-n”) in the TMATS setup
record for this recording. The uCount field is incremented each time this event occurs. The
bEventOccurence field indicates whether the event occurred during or between record
enable commands.
5-10
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
The layout of the CSDW is shown in Figure 5-18, and is a common format between root
and node index packets. The uIdxEntCount field is a count of the total number of indexes in
this packet. The bIntraPckHdr field indicates the presence of the optional IPH. The
bFileSize field indicates the presence of the optional file size field. The uIndexType field
indicates whether the indexes that follow are root or node indexes. If file size is present, it
follows the CSDW as an unsigned 64-bit value.
struct SuIndex_ChanSpec
{
uint32_t uIdxEntCount : 16; // Total number of indexes
uint32_t uReserved : 13;
uint32_t bIntraPckHdr : 1; // Intra-packet header present
uint32_t bFileSize : 1; // File size present
uint32_t uIndexType : 1; // Index type
};
Figure 5-18. Type 0x03 Computer-Generated Data, Format 3 (Index) CSDW
Node index packets are composed of a CSDW, an optional file size field, and multiple
node index structures.
Each node index structure is composed of an intra-packet time stamp (IPTS), an optional
IPH, and a node index entry data structure. The IPTS represents indexed packet data in 48-bit
relative time format derived from the RTC shown in Figure 5-6, 64-bit extended relative time
format shown in Figure 5-9, absolute time in Chapter 4 format shown in Figure 5-7, or IEEE-
1588 time format shown in Figure 5-8.
If the index message includes the optional IPH field, this field holds the absolute time of
the index. The format of this data is the same as the Time Data Packet Format 1, depicted in
Figure 5-16 and Figure 5-17. Unfortunately Time Data Packet Format 1 represents time in more
than one format and this data format does not include a method to determine which time format
is used in the IPH. For this reason, this field should be used with caution, if used at all.
The structure of the node index entry is shown in Figure 5-19. The uChannelID field is
the Channel ID of the indexed data packet. The uDataType field is the data type of the indexed
data packet. The uOffset field is an unsigned eight-byte value representing the offset from the
beginning of the data file to the indexed data packet. The uOffset field should always point to
the sync pattern (0xEB25) of the indexed data packet.
struct SuIndex_Data
{
uint32_t uChannelID : 16;
uint32_t uDataType : 8;
uint32_t uReserved : 8;
uint64_t uOffset;
};
Figure 5-19. Type 0x03 Computer-Generated Data, Format 3 (Index) Node
Index Entry
Root index packets are composed of a CSDW, an optional file size field, and multiple
root index entry structures. Root index structures provide information about and point to node
index packets described above. The last entry is actually a pointer to the previous root index.
5-11
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Each root index is composed of an IPTS, an optional IPH, and a node index data packet
offset value. The IPTS represents indexed packet data time in 48-bit relative time format derived
from the RTC shown in Figure 5-6, 64-bit extended relative time format shown in Figure 5-9,
absolute time in Chapter 4 format shown in Figure 5-7, or IEEE-1588 time format shown in
Figure 5-8.
If the root index message includes the optional IPH field, this field holds the absolute
time of the node index packet. The format of this data is the same as the Time Data Packet
Format 1, depicted in Figure 5-16 and Figure 5-17. Unfortunately Time Data Packet Format 1
represents time in more than one format and this data format does not include a method to
determine which time format is used in the IPH. For this reason, this field should be used with
caution, if used at all.
The node index offset field of the root index packet is an eight-byte unsigned value
representing the offset from the beginning of the data file to the node index packet.
The node index offset field of the last root index entry structure in a root index packet
doesn’t point to a node index packet. Instead this last file offset value points to the file offset
value of the previous root index packet. In this way a linked list of root index packets is created.
The first root index packet in the linked list is indicated by having a root index offset field value
that points to itself.
5-12
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
After the last TMATS segment is received, all segments can be concatenated to form a
complete record. If a checksum format packet is received this value of the checksum can be
compared with the computed SHA2-256 checksum of the reassembled TMATS record. The
layout of the checksum format data packet is shown in Figure 5-21. Keep in mind that checksum
data is in big-endian format.
struct SuStreamingConfig_Checksum
{
uint32_t auChecksum[8]; // Checksum bits 0 to 255
};
Figure 5-21. Type 0x04 Computer-Generated Data, Format 4 (Streaming
Configuration) Checksum Data
If a data channel currently has no data then data associated with this channel won’t be
seen. For this reason sometimes it is useful to have a list of data channels to expect in the data.
The iChannels field indicates the number of channels listed. The auChannelId array is the
array of 16-bit Channel IDs that are currently enabled and may be seen subsequently in the data
stream.
5.5.8 Type 0x09, PCM Data, Format 1 (IRIG 106 Chapter 4/8)
Format 1 PCM packets are used to record PCM data frames. Most PCM data is a serial
stream of bits from multiple interleaved data sources. Each data source generally operates at a
different data rate and has its digital data interleaved in a fixed, defined fashion. The data from
these multiplexed data sources are organized into major frames and minor frames. Format 1
PCM data records minor frames as integral units of data in packed and unpacked mode. In
general the PCM data packet will contain multiple PCM minor frame data messages. There is
5-13
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
extensive discussion of PCM in IRIG 106 Chapter 4,15 Chapter 8,16 and Appendix 4.A,17 as well
as RCC Document 119, Telemetry Applications Handbook.18
A PCM minor frame is recorded in one of three major modes: unpacked, packed, and
throughput. In unpacked mode, packing is disabled and each data word is padded with the
number of filler bits necessary to align the first bit of each word with the next 16-bit boundary in
the packet. In packed mode, packing is enabled and pad is not added to each data word; however,
filler bits may be required to maintain minor frame alignment on word boundaries. In throughput
mode, the PCM data are not frame synchronized so the first data bit in the packet can be any bit
in the major frame. Chapter 10 discusses these modes in greater detail.
The layout of the CSDW is shown in Figure 5-23. The uSyncOffset field is the value
of the byte offset into a major frame for the first data word in a packet, and is only valid in
unpacked mode. The bUnpackedMode, bPackedMode, and bThruMode flags indicate
unpacked mode, packed mode, and throughput mode respectively and are mutually exclusive.
The bAlignment flag indicates 16- or 32-bit alignment of minor frames and minor frame
fields. The uMajorFrStatus field indicates the lock status of the major frame. The
uMinorFrStatus indicates the lock status of the minor frame. The bMinorFrInd flag
indicates the first word of the packet is the beginning of a minor frame. The bMajorFrInd flag
indicates the first word of the packet is the beginning of a major frame. The bIntraPckHdr
flag indicates the presence of IPHs.
struct SuPcmF1_ChanSpec
{
uint32_t uSyncOffset : 18; // Sync offset
uint32_t bUnpackedMode : 1; // Packed mode flag
uint32_t bPackedMode : 1; // Unpacked mode flag
uint32_t bThruMode : 1; // Throughput mode flag
uint32_t bAlignment : 1; // 16/32-bit alignment flag
uint32_t Reserved1 : 2; //
uint32_t uMajorFrStatus : 2; // Major frame lock status
uint32_t uMinorFrStatus : 2; // Minor frame lock status
uint32_t bMinorFrInd : 1; // Minor frame indicator
uint32_t bMajorFrInd : 1; // Major frame indicator
uint32_t bIntraPckHdr : 1; // Intra-packet header flag
uint32_t Reserved2 : 1; //
};
Figure 5-23. Type 0x09 PCM Data, Format 1 CSDW
15
Range Commanders Council. “Pulse Code Modulation Standards” in Telemetry Standards. IRIG 106-20 Chapter
4. July 2020. May be superseded by update. Retrieved 11 August 2020. Available at
https://www.trmc.osd.mil/wiki/download/attachments/105349356/chapter4.pdf.
16
Range Commanders Council. “Digital Data Bus Acquisition Formatting Standard” in Telemetry Standards. IRIG
106-20 Chapter 8. July 2020. May be superseded by update. Retrieved 11 August 2020. Available at
https://www.trmc.osd.mil/wiki/download/attachments/105349356/chapter8.pdf.
17
Range Commanders Council. “Pulse Code Modulation Standards (Additional Information and
Recommendations)” in Telemetry Standards. IRIG 106-20 Chapter 4 Appendix A. July 2020. May be superseded by
update. Retrieved 11 August 2020. Available at
https://www.trmc.osd.mil/wiki/download/attachments/105349356/chapter4.pdf.
18
Range Commanders Council. Telemetry Applications Handbook. RCC 119-06. May 2006. May be superseded by
update. Retrieved 12 August 2019. Available https://www.trmc.osd.mil/wiki/download/attachments/105349396/119-
06.pdf.
5-14
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
The optional IPH and individual PCM minor frame messages follow the CSDW. The
format of the IPH is shown in Figure 5-24. The IPH, if present (indicated by bIntraPckHdr =
1), is an eight-byte representation of time in 48-bit relative time format derived from the RTC
shown in Figure 5-6, 64-bit extended relative time format shown in Figure 5-9, absolute time in
Chapter 4 format shown in Figure 5-7, or IEEE-1588 time format shown in Figure 5-8. The
uMajorFrStatus field indicates the lock status of the major frame. The uMinorFrStatus
indicates the lock status of the minor frame.
struct SuPcmF1_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t Reserved : 12; //
uint32_t uMajorFrStatus : 2; // Major frame lock status
uint32_t uMinorFrStatus : 2; // Minor frame lock status
uint32_t Reserved : 16; //
};
Figure 5-24. Type 0x09 PCM Data, Format 1 Intra-Packet Header
One minor frame of data follows the IPH. The length of the minor frame data is not
included in the data packet. The data length must be determined from the number of bits in a
minor frame specified in the TMATS parameter P-d\MF2. Minor frames will have padding bits
added to the end to make them 16- or 32-bit aligned depending on the value of the
bAlignment flag in the CSDW. Refer to the TMATS P-d format descriptions in Chapter 9 of
the 106.
5-15
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
The uTimeSrc field indicates that the source is for the time used. Note that this field
changed slightly between the 2004 and the 2005 release of Chapter 10. The uTimeFmt field is
used to indicate the nature and type of the source of external time applied to the recorder. The
uDateFmt field is used to determine how to interpret the time data that follows. Time
representation in Day (i.e., Day of the Year) format is shown in Figure 5-16. Time representation
in Day-Month-Year format is shown in Figure 5-17. The bLeapYear field in the CSDW is
useful to convert Day of the Year to Day and Month when the year is not known.
The uTimeStatus field indicates the status of the time source. Currently the status can
be Time Valid or Time Not Valid, although other values may be defined in the future. The
uTimeFmt field indicates the format and interpretation of the data portion of the packet that
follows.
The format of the data portion of the packet is shown in Figure 5-27.
struct SuTimeF2_Data
{
uint32_t uSeconds; // Integer time value
utin32_t uSubseconds; // Fractional part of time value
};
Figure 5-27. Type 0x12 Time Data, Format 2 Data Structure
With NTP3 and both IEEE-1588 data formats the uSeconds field represents the integer
value of time. The NTP3 standard time is in Universal Coordinated Time; uses an epoch of
January 1, 1900; and includes leap seconds. The IEEE-1588 standard formats are in International
Atomic Time; use an epoch of January 1, 1970; and don’t include leap seconds.
The fractional portion of time is in the uSubseconds field. The NTP standard
represents subsecond time as a fraction. The most significant bit of the uSubseconds field
represents a value of 0.5 seconds, etc. That is, there is an implied binary point between the 32-bit
uSeconds and 32-bit uSubseconds field. The IEEE-1588 standard represents subsecond
time in integer nano-seconds.
5-16
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
The individual 1553 messages follow the CSDW. Each 1553 message has an IPTS, an
IPDH data word, and then the actual 1553 message. The layout of the message header is shown
in Figure 5-29. The aubyIntPktTime field is an eight-byte value. The specific interpretation
of this field is determined by packet header flags. This time is in 48-bit relative time format
derived from the RTC shown in Figure 5-6, 64-bit extended relative time format shown in Figure
5-9, absolute time in Chapter 4 format shown in Figure 5-7, or IEEE-1588 time format shown in
Figure 5-8. Various bit flags and values are found in the IPH.
struct Su1553F1_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint16_t Reserved1 : 3; // Reserved
uint16_t bWordError : 1;
uint16_t bSyncError : 1;
uint16_t bWordCntError : 1;
uint16_t Reserved2 : 3;
uint16_t bRespTimeout : 1;
uint16_t bFormatError : 1;
uint16_t bRT2RT : 1;
uint16_t bMsgError : 1;
uint16_t iBusID : 1;
uint16_t Reserved3 : 2;
uint8_t uGapTime1;
uint8_t uGapTime2;
uint16_t uMsgLen;
};
Figure 5-29. Type 0x19 MIL-STD-1553 Data, Format 1 Intra-Packet Header
5-17
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
The amount of data that follows the IPH is variable. The data length in bytes is given in
the uMsgLen field and is necessary to determine the amount of additional data to read to
complete the message.
The layout and order of 1553 command word(s), status word(s), and data word(s) in the
recorded 1553 message is not fixed but rather is the same as it would be found “on the wire”. It's
not therefore possible to define a fixed data structure representation for the message data. The
first word in the data will always be a command word, but it will be necessary to use the
command word as well as the bRT2RT flag to determine the offsets of the other message
structures such as the status and data word(s). The layouts of the various types of 1553 messages
are shown in Figure 5-30. When calculating data word count, be careful to take Mode Codes and
word count wrap around into account. An algorithm to determine the number of data words in a
message is shown in C-like pseudo-code in Figure 5-31.
19
Lockheed Martin Corporation. “Advanced Weapons Multiplex Data Bus.” 8 June 2010. May be superseded by
update. Retrieved 3 June 2015. Available to RCC members with Private Portal access at
https://wsdmext.wsmr.army.mil/site/rccpri/Limited_Distribution_References/16PP362B.pdf.
5-18
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
The layout of the CSDW is show in Figure 5-33. The 16PP194 packet can contain
multiple bus transactions. The uMsgCnt field indicates the number of 16PP194 messages in the
packet.
struct Su1553F2_ChanSpec
{
uint32_t uMsgCnt; // Message count
};
Figure 5-33. Type 0x1A MIL-STD-1553 Data, Format 2 (16PP194) CSDW
The 16PP194 message word is 26 bits in length and consists of 16 data bits, 4 address
bits, 4 sub-address bits, a parity bit, and a sync bit. Only the 24 bits of data, address, and sub-
address values are mapped into the 16PP194 recorded data word. Sync and parity bits are not
recorded. The mapping of these bits is shown in Figure 5-34.
The layout of the recorded 16PP194 word is shown in Figure 5-35. The uDataWord
field contains the message data. The uRiuSubAddr field is the remote interface unit (RIU)
sub-address. The uRiuAddr field is the RIU address. The bParityError flag indicates a
parity error occurred during reception of the message. The bWordError flag indicates a
Manchester decoding error occurred during reception of the message. The uGap field indicates
5-19
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
the general range of gap time. The mapping of uGap values to gap time ranges can be found in
the Chapter 10 standard. The uBusID field indicates the bus on which the message occurred.
Bus identification can be found in the Chapter 10 standard. The layout of a complete 16PP194
transaction is shown in Figure 5-36.
struct Su16PP194_DataWord
{
uint16_t uDataWordHigh : 8; // Data word bits 24-17
uint16_t bParityError : 1; // Parity error
uint16_t bWordError : 1; // Word bit error
uint16_t uGap : 3; // Gap time
uint16_t uBusID : 3; // Bus ID
uint16_t uDataWordLow; // Data word bits 1-16
};
Figure 5-35. 16PP194 Word Layout
struct Su16PP194_Transaction
{
struct Su16PP194_Word suCommand;
struct Su16PP194_Word suResponse;
struct Su16PP194_Word suCommandEcho;
struct Su16PP194_Word suNoGo;
struct Su16PP194_Word suNoGoEcho;
struct Su16PP194_Word suStatus;
};
Figure 5-36. 16PP194 Transaction Layout
5-20
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SuAnalogF1_ChanSpec
{
uint32_t uMode : 2; // Packed or Unpacked
uint32_t uLength : 6; // Bits in A/D value
uint32_t uSubChan : 8; // Subchannel number
uint32_t uTotChan : 8; // Total number of subchannels
uint32_t uFactor : 4; // Sample rate exponent
uint32_t bSame : 1; // One/multiple CSDW
uint32_t iReserved : 3; //
};
Figure 5-37. Type 0x21 Analog Data, Format 1 CSDW
Sample rate, least significant bit value, offset, and other analog parameters are recorded
in the TMATS packet. The layout of the sequential samples is described in detail in the Chapter
10 standard.
The layout of the Discrete Data message is shown in Figure 5-39. Each message contains
a time stamp and the state of the discrete data input signals. The aubyIntPktTime field in the
data structures represents event time in 48-bit relative time format derived from the RTC shown
in Figure 5-6, 64-bit extended relative time format shown in Figure 5-9, absolute time in Chapter
4 format shown in Figure 5-7, or IEEE-1588 time format shown in Figure 5-8. Note that a
uLength value of zero indicates an actual length of 32 bits.
5-21
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SuDiscreteF1
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t suData; // Data about the event
};
Figure 5-39. Type 0x29 Discrete Data, Format 1 Message
Versions of Chapter 10 prior to the 2009 release incorrectly stated that bit 7 of the packet
flags (in the packet header) is used to determine if the intra-packet time is relative time or
absolute time. The correct bit to use is bit 6.
The layout of the Message Data message IPH is shown in Figure 5-41. Each header
contains a time stamp and some additional information about the data that follows in the
message. The aubyIntPktTime field in the intra-packet data structure represents event time
in 48-bit relative time format derived from the RTC shown in Figure 5-6, 64-bit extended
5-22
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
relative time format shown in Figure 5-9, absolute time in Chapter 4 format shown in Figure 5-7,
or IEEE-1588 time format shown in Figure 5-8. The uMsgLength value indicates the number
of data bytes in the message. The uSubChannel value identifies the specific subchannel from
which this data came. The message data immediately follows the IPH. Note that an even number
of bytes is allocated for message data. If the data contains an odd number of bytes, then one
unused filler byte is inserted at the end of the data. The bFmtError and bDataError flags
indicate that errors have occurred in the reception of the data. The recorded data may, therefore,
be invalid and unusable.
struct MessageF0_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t uMsgLength : 16; // Message length
uint32_t uSubChannel : 14; // Subchannel number
uint32_t bFmtError : 1; // Format error flag
uint32_t bDataError : 1; // Data error flag
};
Figure 5-41. Type 0x30 Message Data, Format 0 Intra-Packet Header
Individual ARINC 429 data messages follow the CSDW. Each message is preceded with
an IPDH followed by the ARINC 429 data word.
The layout of the ARINC 429 data message IPDH is shown in Figure 5-43. The
uGapTime field is the time between the beginning of the preceding bus word and the beginning
of the current bus word in 0.1-microsecond increments. The uBusSpeed field indicates the bit
rate of the recorded bus message. The bParityError flag indicates the presence of a parity
20
Aeronautical Radio, Inc. Mark 33 Digital Information Transfer System (DITS). ARINC 429. Annapolis: ARINC,
1995.
5-23
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
data error. The bFormatError flag indicates the presence of one of several types of data
format errors. The uBusNum field identifies the specific ARINC 429 bus associates with the
recorded data message.
struct SuArinc429F0_Header
{
uint32_t uGapTime : 20; // Gap Time
uint32_t Reserved : 1; //
uint32_t uBusSpeed : 1; // Bus Speed
uint32_t bParityError : 1; // Parity Error
uint32_t bFormatError : 1; // Data type
uint32_t uBusNum : 8; // Bus number
};
Figure 5-43. Type 0x38 ARINC 429 Data, Format 0 Intra-Packet Data Header
The layout of the individual ARINC 429 data words is shown in Figure 5-44. Refer to the
ARINC 429 standard for the interpretation of the specific data fields.
struct SuArinc429F0_Data
{
uint32_t uLabel : 8; // Label
uint32_t uSDI : 2; // Source/Destination ID
uint32_t uData : 19; // Data
uint32_t uSSM : 2; // Sign/Status Matrix
uint32_t uParity : 1; // Parity
};
Figure 5-44. Type 0x38 ARINC 429 Data Format
Note that the value in the uLabel field is stored as it is encountered on the bus, resulting
in the bits being in reverse order. To correctly interpret the uLabel field it is necessary to
reverse the bit ordering. Note also that when formatting the uLabel value for output the value
is commonly formatted in octal format.
21
International Telecommunications Union Telecommunication Standardization Sector. “Advanced Video Coding
for Generic Audiovisual Services.” ITU-T H.264. June 2019. May be superseded by update. Retrieved 13 August
2019. Available at https://www.itu.int/rec/T-REC-H.264.
5-24
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
(Data Version 0x03). It was reserved and zero filled in previous versions of Chapter 10. The
bKLV flag indicates the presence of key-length-value (KLV) metadata fields in the video data.
The bSRS flag indicates whether or not the embedded video clock is synchronized with the
RTC. The bIntraPckHdr flag indicates the presence of IPH data in each video data message.
The bET flag indicates the presence of embedded time in the video data.
struct SuVideoF0_ChanSpec
{
uint32_t Reserved : 24;
uint32_t uType : 4; // Payload type
uint32_t bKLV : 1; // KLV present
uint32_t bSRS : 1; // SCR/RTC Sync
uint32_t bIntraPckHdr : 1; // Intra-Packet Header
uint32_t bET : 1; // Embedded Time
};
Figure 5-45. Type 0x40 Video Data, Format 0 CSDW
All TS packets follow the CSDW. All TS packets are a fixed size of 188 bytes. If the
bIntraPckHdr flag is set, each TS packet will be preceded with an eight-byte IPTS. The
intra-packet time represents TS time in 48-bit relative time format derived from the RTC shown
in Figure 5-6, 64-bit extended relative time format shown in Figure 5-9, absolute time in Chapter
4 format shown in Figure 5-7, or IEEE-1588 time format shown in Figure 5-8. Format 0 does not
include a packet count. Instead the number of TS packets can be calculated from the size of the
data packet found in the Chapter 10 header.
Format 0 video data can be readily decoded with commonly available MPEG libraries
such as the open-source ffmpeg library. A 188-byte TS packet is best thought of as a contiguous
stream of 1504 bits. All TS packets are stored in Format 0 packets as a series of 16-bit words.
The first Format 0 data word holds the first 16 TS packet bits. The first TS packet, or bit 0, is the
left-most bit (most significant bit) in the first Format 0 packet word. Note that the description of
this bit-ordering alignment in a Format 0 packet has been frequently depicted wrong in the
various IRIG 106 Chapter 10 releases. Most MPEG decoder libraries such as ffmpeg commonly
take as input a 188-byte array of TS data. Due to the use of 16-bit words to store TS data in
Format 0 packets, TS data needs to be byte-swapped as it is read from a Chapter 10 data file and
put into a buffer for decoding by a software library expecting byte-aligned TS data.
22
ISO/IEC. Information Technology – Generic Coding of Moving Pictures and Associated Audio Information:
Systems. ISO/IEC 13818-1:2019. June 2019. Retrieved 13 August 2019. Available for purchase at
https://www.iso.org/standard/75928.html.
5-25
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
variable rate encoding. The bET flag indicates the presence of embedded time in the video data.
The uEPL value indicates the video packet encoding profile and level used. The
bIntraPckHdr flag indicates the presence of IPH data in each video data message. The bSRS
flag indicates whether or not the embedded video clock is synchronized with the RTC. The
bKLV flag indicates the presence of KLV metadata fields in the video data.
struct SuVideoF1_ChanSpec
{
uint32_t uPacketCnt : 12; // Number of packets
uint32_t uType : 1; // TS/PS type
uint32_t uMode : 1; // Const/Var mode
uint32_t bET : 1; // Embedded Time
uint32_t uEPL : 4; // Encoding Profile and Level
uint32_t bIntraPckHdr : 1; // Intra-Packet Header
uint32_t bSRS : 1; // SCR/RTC Sync
uint32_t bKLV : 1; // KLV present
uint32_t uReserved : 10;
};
Figure 5-46. Type 0x40 Video Data, Format 1 CSDW
The CSDW is followed by MPEG-2 PS or TS packets. All TS packets are a fixed length
of 188 bytes, but PS packets are variable length. If the bIntraPckHdr flag is set, each MPEG-
2 packet will be preceded with an eight-byte IPTS. The intra-packet time represents MPEG
packet time in 48-bit relative time format derived from the RTC shown in Figure 5-6, 64-bit
extended relative time format shown in Figure 5-9, absolute time in Chapter 4 format shown in
Figure 5-7, or IEEE-1588 time format shown in Figure 5-8.
Format 1 does not include a method to separate individual MPEG packets from within the
Format 1 packet other than determining the MPEG packet size from the MPEG packet data.
Determining MPEG packet size is fairly complicated and involves quite a bit of knowledge about
MPEG internal data structures. For this reason, the use of IPHs between MPEG packets should
be carefully considered. It could make decoding Format 1 packets quite complicated.
5.5.30 Type 0x42, Video Data, Format 2 (ISO 14496 MPEG-4 Part 10 AVC/H.264)
Video Data, Format 2 packets are used to record digitized video and associated audio
signals. Format 2 packets can support the complete MPEG-2 ISO/IEC 13818-1:2019 standard for
both PSs and TSs, and provides all H.264 (also known as MPEG-4 Part 10 and MPEG-4 AVC)
encoding levels and profiles.
The layout of the CSDW is shown in Figure 5-47. The uPacketCnt value is the
number of MPEG-2 packets in the data packet. The uType value indicates whether the video
packet is a PS or TS. The uMode value indicates whether the video packet uses constant or
variable rate encoding. The bET flag indicates the presence of embedded time in the video data.
The uEP value indicates the video packet encoding profile used. The bIntraPckHdr flag
indicates the presence of IPH data in each video data message. The bSRS flag indicates whether
or not the embedded video clock is synchronized with the RTC. The bKLV flag indicates the
presence of KLV metadata fields in the video data. The uEL value indicates the video packet
encoding profile and level used. The uAET field indicates the type of AVC/H.264 audio
encoding used.
5-26
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SuVideoF2_ChanSpec
{
uint32_t uPacketCnt : 12; // Number of packets
uint32_t uType : 1; // TS/PS type
uint32_t uMode : 1; // Const/Var mode
uint32_t bET : 1; // Embedded Time
uint32_t uEP : 4; // Encoding Profile
uint32_t bIntraPckHdr : 1; // Intra-Packet Header
uint32_t bSRS : 1; // SCR/RTC Sync
uint32_t bKLV : 1; // KLV present
uint32_t uEL : 4; // Encoding Level
uint32_t uAET : 1; // Audio Encoding Type
uint32_t uReserved : 5;
};
Figure 5-47. Type 0x40 Video Data, Format 2 CSDW
The CSDW is followed by MPEG-2 PS or TS packets. All TS packets are a fixed length
of 188 bytes, but PS packets are variable length. If the bIntraPckHdr flag is set, each MPEG-
2 packet will be preceded with an eight-byte IPTS. The intra-packet time represents MPEG
packet time in 48-bit relative time format derived from the RTC shown in Figure 5-6, 64-bit
extended relative time format shown in Figure 5-9, absolute time in Chapter 4 format shown in
Figure 5-7, or IEEE-1588 time format shown in Figure 5-8.
Format 2 does not include a method to separate individual MPEG packets from within the
Format 2 packet other than determining the MPEG packet size from the MPEG packet data.
Determining MPEG packet size is fairly complicated and involves quite a bit of knowledge about
MPEG internal data structures. For this reason, the use of IPHs between MPEG packets should
be carefully considered. It could make decoding Format 2 packets quite complicated.
23
ISO/IEC. “General sequential and progressive syntax”, Annex B, section B.2, in Information technology -- Digital
compression and coding of continuous-tone still images: Requirements and guidelines. ISO/IEC 10918-1:1994. May
be superseded by update. Geneva: International Organization for Standardization, 1994.
5-27
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
The CSDW is followed by MJPEG packets. If the bIntraPckHdr flag is set, each
MJPEG packet will be preceded with an IPH as shown in Figure 5-49. The intra-packet time
represents MJPEG packet time in 48-bit relative time format derived from the RTC shown in
Figure 5-6, 64-bit extended relative time format shown in Figure 5-9, absolute time in Chapter 4
format shown in Figure 5-7, or IEEE-1588 time format shown in Figure 5-8.. The uFrameLen
field holds the size in bytes of the MJPEG frame to follow.
struct SuVideoF3_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t uFrameLen; // Message data length
};
Figure 5-49. Type 0x43 Video Data, Format 3 (MJPEG) Intra-packet Header
Note that an even number of bytes is allocated for message data. If the data contains an
odd number of bytes, then one unused filler byte is inserted at the end of the data.
The CSDW is followed by MJPEG packets. If the bIntraPckHdr flag is set, each
MJPEG-2000 packet will be preceded with an IPH as shown in Figure 5-51. The intra-packet
time represents MJPEG-2000 packet time in 48-bit relative time format derived from the RTC
shown in Figure 5-6, 64-bit extended relative time format shown in Figure 5-9, absolute time in
Chapter 4 format shown in Figure 5-7, or IEEE-1588 time format shown in Figure 5-8. The
uFrameLen field holds the size in bytes of the MJPEG-2000 frame to follow.
24
ISO/IEC. Information technology: JPEG 2000 image coding system: motion JPEG 2000. ISO/IEC 15444-3:2007.
Geneva: International Organization for Standardization, 2007.
5-28
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SuVideoF4_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t uFrameLen; // Message data length
};
Figure 5-51. Type 0x44 Video Data, Format 4 (MJPEG-2000) Intra-packet
Header
Note that an even number of bytes is allocated for message data. If the data contains an
odd number of bytes, then one unused filler byte is inserted at the end of the data.
Individual image data messages follow the CSDW. Each message may have an optional
IPH followed by the image data. The IPH, if present (indicated by bIntraPckHdr = 1), is an
eight-byte representation of time in 48-bit relative time format derived from the RTC shown in
Figure 5-6, 64-bit extended relative time format shown in Figure 5-9, absolute time in Chapter 4
format shown in Figure 5-7, or IEEE-1588 time format shown in Figure 5-8.
The format of the image data portion of the packet is not specified in Chapter 10. The
image format is specified in the TMATS setup record attribute “R-x\SIT-n”. Note that an
even number of bytes is allocated for message data. If the data contains an odd number of bytes,
then one unused filler byte is inserted at the end of the data.
5-29
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
uSum value indicates if and how an image is segmented in the data packet. The uPart value
indicates which part of a possibly segmented image is contained in the data packet.
struct SuImageF1_ChanSpec
{
uint32_t uReserved : 23; // Reserved
uint32_t uFormat : 4; // Image format
uint32_t bIPH : 1; // Intra-packet header flag
uint32_t uSum : 2; // Packet segmentation
uint32_t uPart : 2; // Segmented packet part
};
Figure 5-53. Type 0x49 Image Data, Format 1 CSDW
Individual image data messages follow the CSDW. Each message may have an optional
IPH (indicated by bIntraPckHdr = 1) followed by the image data. The format of the IPH is
shown in Figure 5-54. The aubyIntPktTime value is an eight-byte representation of time in
48-bit relative time format derived from the RTC shown in Figure 5-6, 64-bit extended relative
time format shown in Figure 5-9, absolute time in Chapter 4 format shown in Figure 5-7, or
IEEE-1588 time format shown in Figure 5-8. The uMsgLength value indicates the length of
the following still image or segment.
struct SuImageF1_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t uMsgLength; // Message length
};
Figure 5-54. Type 0x49 Image Data, Format 1 Intra-Packet Header
The format of the image data portion of the packet is not specified in Chapter 10. The
image format is specified in the TMATS setup record attribute “R-x\SIT-n”. Note that an
even number of bytes is allocated for message data. If the data contains an odd number of bytes,
then one unused filler byte is inserted at the end of the data.
5-30
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SuImageF2_ChanSpec
{
uint32_t uReserved : 21; // Reserved
uint32_t uFormat : 6; // Image format
uint32_t bIPH : 1; // Intra-packet header flag
uint32_t uSum : 2; // Packet segmentation
uint32_t uPart : 2; // Segmented packet part
};
Figure 5-55. Type 0x4A Image Data, Format 2 (Dynamic Imagery) CSDW
Individual image data messages follow the CSDW. Each message may have an optional
IPH (indicated by bIntraPckHdr = 1) followed by the image data. The format of the IPH is
shown in Figure 5-56. The aubyIntPktTime value is an eight-byte representation of time in
48-bit relative time format derived from the RTC shown in Figure 5-6, 64-bit extended relative
time format shown in Figure 5-9, absolute time in Chapter 4 format shown in Figure 5-7, or
IEEE-1588 time format shown in Figure 5-8. The uMsgLength value indicates the length of
the following still image or segment.
struct SuImageF2_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t uMsgLength; // Message length
};
Figure 5-56. Type 0x4A Image Data, Format 2 (Dynamic Imagery) Intra-packet
Header
Note that an even number of bytes is allocated for message data. If the data contains an
odd number of bytes, then one unused filler byte is inserted at the end of the data.
5-31
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
The UART Data message may have an optional IPTS. If so, this time field will be an
eight-byte value. Time is represented in 48-bit relative time format derived from the RTC shown
in Figure 5-6, 64-bit extended relative time format shown in Figure 5-9, absolute time in Chapter
4 format shown in Figure 5-7, or IEEE-1588 time format shown in Figure 5-8.
The layout of the UART Data message IPDH is shown in Figure 5-58. The
uDataLength value indicates the number of data bytes in the message. The uSubChannel
value identifies the specific subchannel this data came from. The message data immediately
follows the IPDH. Note that an even number of bytes is allocated for UART data. If the data
contains an odd number of bytes, then one unused filler byte is inserted at the end of the data.
The bParityError flag indicate that errors have occurred in the reception of the data. The
recorded data may, therefore, be invalid and unusable.
struct SuUartF0_Header
{
uint16_t uDataLength : 16; // Length in bytes
uint16_t uSubchannel : 14; // Subchannel
uint16_t uReserved : 1;
uint16_t bParityError : 1; //Parity Error
};
Figure 5-58. Type 0x40 UART Data, Format 0 Intra-Packet Data Header
5-32
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
between video or audio frames, or any other point in the data stream the application may
consider appropriate.” The uTransCnt value is the number of separate transaction messages in
the data packet.
struct Su1394F0_ChanSpec
{
uint32_t uTransCnt : 16; // Transaction count
uint32_t Reserved : 9;
uint32_t uSyncCode : 4; // Synchronization code
uint32_t uPacketType : 3; // Packet body type
};
Figure 5-59. Type 0x58 IEEE-1394 Data, Format 0 CSDW
Type 0 and Type 1 data packets will not have an IPH. Type 2 data packets will have IPHs
between transaction data messages with the data packet. The Type 2 IPH is an eight-byte time
value. Time is represented in 48-bit relative time format derived from the RTC shown in Figure
5-6, 64-bit extended relative time format shown in Figure 5-9, absolute time in Chapter 4 format
shown in Figure 5-7, or IEEE-1588 time format shown in Figure 5-8.
The IEEE 1394 standards contain quite a bit of example code and data structures in the C
language to aid in data interpretation.
Individual 1394 data messages follow the CSDW. The format of the IPH is shown in
Figure 5-61. The aubyIntPktTime value is an eight-byte representation of time in 48-bit
relative time format derived from the RTC shown in Figure 5-6, 64-bit extended relative time
format shown in Figure 5-9, absolute time in Chapter 4 format shown in Figure 5-7, or IEEE-
1588 time format shown in Figure 5-8.. The uDataLength field is the length of the 1394 data
message in bytes. The bLBO flag indicates that some 1394 packets were lost by the bus monitor
due to an overflow in the local message buffer. The uTrfOvf value indicates a 1394 transfer
protocol error. The uStatus field indicates the value of the eight-bit bus status transfer from
the PHY to the link layer of the 1394 bus. Bus status transfers are used to signal a) bus reset
indication; b) arbitration reset gap indication (both even and odd); c) subaction gap indication;
5-33
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
and d) cycle start indication (both even and odd). See IEEE 1394b-200225 Section 17.8 for more
details about interpreting uStatus.
struct Su1394F1_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t uDataLength : 16; // Data length
uint32_t Reserved : 1; //
uint32_t bLBO : 1; // Local buffer overflow
uint32_t uTrfOvf : 2; // Transfer overflow
uint32_t uSpeed : 4; // Transmission speed
uint32_t uStatus : 8; // Status byte
};
Figure 5-61. Type 0x59 IEEE-1394 Data, Format 1 Intra-Packet Header
The complete 1394 bus data message follows the IPH. The length of the 1394 data
message is indicated in the IPH. If the data length is not a multiple of four, the data buffer will
contain padding bytes to align the buffer on a four-byte boundary. The IEEE 1394 standards
contain quite a bit of example code and data structures in the C language to aid in data
interpretation.
25
Institute of Electrical and Electronics Engineers. IEEE Standard for a High Performance Serial Bus: Amendment
2. IEEE 1394b-2002. New York: Institute of Electrical and Electronics Engineers, 2002.
5-34
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
The layout of the CSDW is shown in Figure 5-63. The uType field indicates the type or
size of parallel data stored. For values between 2 and 128, uType indicates the number of bits
per parallel data word. The value 254 indicates that the parallel data is in DCRsi format. Other
values are reserved. When the data type is not DCRsi the uScanNum field is reserved and will
have a value of 0x00. When the data type is DCRsi the uScanNum field contains the scan
number value of the first scan stored in the packet for DCRsi data.
struct SuParallelF0_ChanSpec
{
uint32_t uScanNum : 24; // Scan number
uint32_t uType : 8; // Data type
};
Figure 5-63. Type 0x60 Parallel Data, Format 0 CSDW
Recorded parallel data follows the CSDW. There is no IPH. For general-purpose packets,
bit padding is used to align recorded data on byte or word boundaries. There is no count for the
number of parallel data words following the CSDW. This must be calculated from the data
length in the header and the number of bytes per data word. See the Chapter 10 standard for
complete details.
5-35
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Individual Ethernet data messages follow the CSDW. The format of the IPH is shown in
Figure 5-65. The aubyIntPktTime value is an eight-byte representation of time in 48-bit
relative time format derived from the RTC shown in Figure 5-6, 64-bit extended relative time
format shown in Figure 5-9, absolute time in Chapter 4 format shown in Figure 5-7, or IEEE-
1588 time format shown in Figure 5-8.
struct SuEthernetF0_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t uMsgDataLen : 14; // Message data length
uint32_t bLengthError : 1; // Data length error
uint32_t bDataCrcError : 1; // Data CRC error
uint32_t uNetID : 8; // Network identifier
uint32_t uSpeed : 4; // Ethernet speed
uint32_t uContent : 2; // Captured data content
uint32_t bFrameError : 1; // Frame error
uint32_t bFrameCrcError : 1; // Frame CRC error
};
Figure 5-65. Type 0x68 Ethernet Data, Format 0 Intra-Packet Header
The uDataLen field is the length of the Ethernet data in bytes. The uNetID field is
used to uniquely identify the physical network attachment point. The IRIG 106-13 standard
introduced the bLengthError, bCRCError, and bFrameCRCError fields.
The uSpeed field indicates the bit rate at which the frame was captured by the recorder.
Early coaxial cable-based Ethernet networks (10BASE5 and 10BASE2) required all network
participants to operate at the same bit rate since they were sharing the same physical channel.
Most modern Ethernet network topologies (10BASE-T, 100BASE-TX, etc.) are a star
configuration with a single point-to-point link between the networked device and a network hub.
In this case the network bit rate is the bit rate negotiated between the device (e.g., the recorder)
5-36
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
and the network hub. In this star topology different devices can operate at different bit rates on
the same Ethernet network. The uSpeed field only indicates the bit rate of the link the data
recorder has with the network hub. It does not imply the speed of any other devices on the
network.
The uContent field indicates the type of data payload. The media access control
(MAC) content type (0x00) indicates Ethernet data link layer frames, including the destination
address, source address, type (in the case of Ethernet II) or length (in the case of IEEE 802.3),
data, and frame check sequence. The data link frame preamble is not included, nor are other
features of the physical layer, such as collisions or auto-negotiations. Content type (0x01)
indicates that only the data payload portion of the Ethernet frame is stored. The bFrameError
flag indicates that an unspecified error has occurred in the reception of the Ethernet frame.
Individual Ethernet data messages follow the CSDW. The format of the IPH is shown in
Figure 5-67. The aubyIntPktTime value is an eight-byte representation of time in 48-bit
relative time format derived from the RTC shown in Figure 5-6, 64-bit extended relative time
format shown in Figure 5-9, absolute time in Chapter 4 format shown in Figure 5-7, or IEEE-
1588 time format shown in Figure 5-8.
5-37
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SuEthernetF1_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t uFlagBits : 8; // Flag bits
uint32_t uErrorBits : 8; // Error bits
uint32_t uMsgDataLen : 16; // Message data length
uint32_t uVirtualLinkID : 16; // Virtual link
uint32_t Reserved1 : 16; //
uint8_t auSrcIP[4]; // Source IP address
uint8_t auDstIP[4]; // Source IP address
uint32_t uDstPort : 16; // Destination Port
uint32_t uSrcPort : 16; // Source Port
};
Figure 5-67. Type 0x69 Ethernet Data, Format 1 Intra-Packet Header
Ethernet Data, Format 1 packets only contain the UDP payload portion of the Ethernet
packet. Therefore IP parameters, such as source and destination IP addresses and source and
destination port numbers, are stored in the IPH. The ARINC-664 standard defines a 16-bit
Virtual Link value encoded into the Ethernet destination MAC address. This value is also stored
in the IPH.
26
National Marine Electronics Association. “NMEA 0183 Interface Standard.” V 4.11. November 2018. May be
superseded by update. Retrieved 13 August 2019. Available for purchase at
https://www.nmea.org/content/STANDARDS/NMEA_0183_Standard.
27
National Marine Electronics Association. “NMEA 0183-HS Interface Standard.” V 1.01. n.d. May be superseded
by update. Retrieved 10 August 2016. Available for purchase at
https://www.nmea.org/content/STANDARDS/NMEA_0183_Standard.
28
National Marine Electronics Association. “Standard for Serial-Data Networking of Marine Electronic Devices.”
Edition 3.101. March 2016. May be superseded by update. Retrieved 13 August 2019. Available for purchase at
https://www.nmea.org/content/STANDARDS/NMEA_2000.
29
Radio Technical Commission for Maritime Services. “Standard for Networked Transport of RTCM via Internet
Protocol (Ntrip).” RTCM 10410.1. Version 2.0 Amendment 1. June 2011. May be superseded by update. Retrieved
5-38
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SuTSPICTSF0_ChanSpec
{
uint32_t Reserved : 27;
uint32_t uType : 4; // Type of data
uint32_t bIPTS : 1; // Intra-Packet Time Stamp enabled
};
Figure 5-68. Type 0x70 TSPI/CTS Data, Format 0 CSDW
Individual data messages follow the CSDW. The format of the IPH is shown in Figure
5-69. The aubyIntPktTime value is an eight-byte representation of time in 48-bit relative
time format derived from the RTC shown in Figure 5-6, 64-bit extended relative time format
shown in Figure 5-9, absolute time in Chapter 4 format shown in Figure 5-7, or IEEE-1588 time
format shown in Figure 5-8. The uLength field specifies the length of the message in bytes.
struct SuTSPICTSF0_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t uLength : 16; // Message length
uint32_t Reserved : 16;
};
Figure 5-69. Type 0x70 TSPI/CTS Data, Format 0 Intra-Packet Header
struct SuTSPICTSF1_ChanSpec
{
uint32_t Reserved : 29;
uint32_t uContent : 2; // Packet contents
uint32_t bIPTS : 1; // Intra-Packet Time Stamp enabled
};
Figure 5-70. Type 0x71 TSPI/CTS Data, Format 1 CSDW
5-39
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Individual data messages follow the CSDW. The format of the IPH is shown in Figure
5-71. The aubyIntPktTime value is an eight-byte representation of time in 48-bit relative
time format derived from the RTC shown in Figure 5-6, 64-bit extended relative time format
shown in Figure 5-9, absolute time in Chapter 4 format shown in Figure 5-7, or IEEE-1588 time
format shown in Figure 5-8. The uLength field specifies the length of the message in bytes.
struct SuTSPICTSF1_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t uLength : 16; // Message length
uint32_t Reserved : 16;
};
Figure 5-71. Type 0x71 TSPI/CTS Data, Format 1 Intra-Packet Header
31
Range Instrumentation System Program Office, Air Armament Center. “Interface Specification for the USAF Air
Combat Test and Training System (ACTTS) Air-to-Ground, Air-to-Air, Ground-to-Air Data Links, and AIS
Recording Formats.” WMSP 98-01, Rev A, Chg 1. 19 May 2003. Retrieved 3 June 2015. Available to RCC
members with Private Portal access at
https://wsdmext.wsmr.army.mil/site/rccpri/Limited_Distribution_References/WMSP_98-01.doc.
5-40
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SuTSPICTSF2_ChanSpec
{
uint32_t Reserved : 27;
uint32_t uFormat : 4; // Format of data
uint32_t bIPTS : 1; // Intra-Packet Time Stamp enabled
};
Figure 5-72. Type 0x72 TSPI/CTS Data, Format 2 CSDW
Individual data messages follow the CSDW. The format of the IPH is shown in Figure
5-73. The aubyIntPktTime value is an eight-byte representation of time in 48-bit relative
time format derived from the RTC shown in Figure 5-6, 64-bit extended relative time format
shown in Figure 5-9, absolute time in Chapter 4 format shown in Figure 5-7, or IEEE-1588 time
format shown in Figure 5-8. The uLength field specifies the length of the message in bytes.
struct SuTSPICTSF2_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t uLength : 16; // Message length
uint32_t Reserved : 16;
};
Figure 5-73. Type 0x72 TSPI/CTS Data, Format 2 Intra-Packet Header
After the CSDW, CAN bus data is inserted into the packet. Each CAN bus message is
preceded by an IPH that has an IPDH and an IPTS. The IPDH is composed of an intra-packet
message header and an intra-packet ID word. The length of the IPH is fixed at 16 bytes (128 bits)
positioned contiguously, with the layout shown in Figure 5-75. The uMsgLength field contains
a binary value representing the length of the number of the valid bytes in the rest of the message
that follows the intra-packet message header. The message length will be 4-12 bytes (4 bytes for
the intra-packet ID word + 0-8 bytes data content of the CAN bus message). The
uSubchannel field contains a binary value that represents the subchannel number belonging
to the message that follows the ID word when the channel ID in the packet header defines a
group of subchannels. Zero means first and/or only subchannel, which is valid for the CAN bus.
The bFmtError flag indicates a message protocol error condition. The bDataError flag
indicates an error in the data such as a parity error. uCANBUsID is the standard 11-bit or
5-41
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
extended 29-bit CAN Bus ID address. The bRTR flag indicates a remote transfer request. The
bIDE flag indicates whether to use the extended CAN identifier:
0 = 11-bit standard CAN identifier (CAN ID word bits 10-0)
1 = 29-bit extended CAN identifier (CAN ID word bits 28-0)
struct SuCANBus_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t uMsgLength : 4; // Message length
uint32_t uReserved1 : 12;
uint32_t uSubChannel : 8 // Subchannel number
uint32_t uReserved2 : 6;
uint32_t bFmtError : 1; // Format error flag
uint32_t bDataError : 1; // Data error flag
uint32_t uCANBusID : 29; // CAN Bus ID
uint32_t uReserved3 : 1; //
uint32_t bRTR : 1; // Remote transfer request bit
uint32_t bIDE : 1; // Extended CAN identifier
};
Figure 5-75. Type 0x78 CAN Bus Intra-Packet Header
5-42
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Individual Fibre Channel data frame messages follow the CSDW. The format of the IPH
is shown in Figure 5-77. The aubyIntPktTime value is an eight-byte representation of time
in 48-bit relative time format derived from the RTC shown in Figure 5-6, 64-bit extended
relative time format shown in Figure 5-9, absolute time in Chapter 4 format shown in Figure 5-7,
or IEEE-1588 time format shown in Figure 5-8.
struct SuFibreChanF0_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t uFrameLen : 12; // Frame length in bytes
uint32_t uStartOfFrame : 4; // Start of frame delimiter
uint32_t uEndOfFrame : 3; // End of frame delimiter
uint32_t Reserved : 5;
uint32_t uTopology : 2; // Fibre Channel topology
uint32_t uContent : 2; // Fibre Channel frame content
uint32_t bNonStrippedMode : 1; // Stripped / Non-stripped mode flag
uint32_t bOverrunError : 1; // Overrun error flag
uint32_t bCrcError : 1; // CRC error flag
uint32_t bFramingError : 1; // Framing error flag
};
Figure 5-77. Type 0x79 Fibre Channel, Format 0 Intra-Packet Header
The uFrameLen field is the length of the data portion of the packet in bytes. Note that
in unstripped mode this value is the numer of bytes in the entire frame and should be a value
divisible by four. In stripped mode this value is the number of bytes in the data payload portion
of the frame. The uStartOfFrame and uEndOfFrame fields hold the values of the frame
delimeter fields in the physical frame. The uTopology field represents the topology of the
Fibre Channel. Currenly only passive topology is supported. The uContent field indicates
whether the data is a data frame or a link control frame. The bNonStrippedMode flag
indicates stripped or unstripped storage mode. The bOverrunError, bCrcError, and
bFramingError flags indicate their respective data error conditions.
5-43
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Individual Fibre Channel data frame messages follow the CSDW. The format of the IPH
is shown in Figure 5-79. The aubyIntPktTime value is an eight-byte representation of time
in 48-bit relative time format derived from the RTC shown in Figure 5-6, 64-bit extended
relative time format shown in Figure 5-9, absolute time in Chapter 4 format shown in Figure 5-7,
or IEEE-1588 time format shown in Figure 5-8.
struct SuFibreChanF1_Header
{
uint8_t aubyIntPktTime[8]; // Reference time
uint32_t uFrameLen : 12; // Frame length in bytes
uint32_t uStartOfFrame : 4; // Start of frame delimiter
uint32_t uEndOfFrame : 3; // End of frame delimiter
uint32_t Reserved : 10;
uint32_t bOverrunError : 1; // Overrun error flag
uint32_t bCrcError : 1; // CRC error flag
uint32_t bFramingError : 1; // Framing error flag
};
Figure 5-79. Type 0x7A Fibre Channel, Format 1 Intra-Packet Header
The uFrameLen field is the length of the data portion of the packet in bytes. In stripped
mode this value is the number of bytes in the data payload portion of the frame. The
uStartOfFrame and uEndOfFrame fields hold the values of the frame delimeter fields in
the physical frame. The bOverrunError, bCrcError, and bFramingError flags indicate
their respective data error conditions.
5-44
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
The IRIG 106-15 standard introduced a 64-bit ERTC, which is driven from a 1-GHz
clock, providing a time resolution of 1 nanosecond. Interpretation of the ERTC value is the same
as with the 48-bit 10-MHz RTC. The ERTC is stored in the optional packet secondary header.
32
Internet Engineering Task Force. “IANA Guidelines for IPv4 Multicast Address Assignments.” RFC 3171.
August 2001. Obsoleted by RFC 5771. Retrieved 13 August 2019. Available at
https://datatracker.ietf.org/doc/rfc3171/.
5-45
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
2365,33 Chapter 10 data streaming should be directed to multicast addresses in the local scope
address range 239.255.0.0 to 239.255.255.255.
All IP multicast packets are delivered by using the Ethernet MAC address range
01:00:5e:00:00:00 - 01:00:5e:7f:ff:ff. This is 23 bits of available address space. The lower 23 bits
of the 28-bit multicast IP address are mapped into the 23 bits of available Ethernet address space.
This means that there is ambiguity in delivering packets. If two hosts on the same subnet each
subscribe to a different multicast group whose address differs only in the first 5 bits, Ethernet
packets for both multicast groups will be delivered to both hosts, requiring the network software
in the hosts to discard the unrequired packets. If multiple multicast addresses are used, be careful
to choose multicast addresses that will result in different Ethernet multicast addresses.
Multicast data is filtered by the Ethernet controller hardware, only passing subscribed
packets to the software driver for decoding. This improves performance under high network
traffic loads. Ethernet controllers only have a limited number of multicast addresses they can
filter. A common hardware limitation is 16 multicast addresses. If a workstation needs to
subscribe to more multicast addresses than the Ethernet hardware can support, then all multicast
traffic is passed to the software driver for filtering, negating the benefit of multicast filtering in
hardware.
The size of a UDP packet is represented by a 16-bit value in the IPv4 IP and UDP
headers, but some software implementations treat this as a signed value with a maximum value
of 2^15 or 32,768. Because of this, the maximum size of a Chapter 10 streaming packet should
be no more than 32,724 bytes. Physical networks have a maximum transfer unit (MTU), which is
the largest data packet they can carry. If a UDP packet has a size larger than the network MTU, it
will be fragmented into smaller packets by the IP software driver before sending them over the
underlying physical network. The fragmented UDP packets are then reassembled into a larger
packet by the IP software driver at the receiving end. There is a performance penalty for this
fragmentation and reassembly. Better performance may be achieved by choosing a UDP packet
small enough to avoid fragmentation and reassembly. Regular Ethernet supports a maximum size
of 1500 bytes of data payload (IP header, UDP header, and UDP data) but some newer Ethernet
technologies support larger jumbo frames.
Chapter 10 data packets are sent in a UDP/IP packet by prepending a UDP transfer
header to the UDP data payload. Chapter 10 data packet(s) smaller than the 32-kb maximum size
will prepend the non-segmented UDP transfer header shown in Figure 5-80. A Chapter 10 data
packet larger than the 32-kb maximum size will need to be segmented before transmission, and
will prepend the segmented UDP transfer header shown in Figure 5-81. The IPv6 format
supports large data packets, negating the need for segmented data packets.
struct SuUDP_Transfer_Header_F1_NonSeg
{
uint32_t uFormat : 4; // Streaming version
uint32_t uMsgType : 4; // Type of message
uint32_t uSeqNum :24; // UDP sequence number
};
Figure 5-80. UDP Transfer Header Format 1, Non-Segmented Data
33
Internet Engineering Task Force. “Administratively Scoped IP Multicast.” RFC 2365. July 1998. May be
superseded by update. Retrieved 13 August 2019. Available at https://datatracker.ietf.org/doc/rfc2365/.
5-46
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
struct SuUDP_Transfer_Header_F1_Seg
{
uint32_t uFormat : 4; // Streaming version
uint32_t uMsgType : 4; // Type of message
uint32_t uUdpSeqNum :24; // UDP sequence number
uint32_t uChID :16; // Channel ID
uint32_t uChanSeqNum : 8; // Channel sequence number
uint32_t uReserved : 8;
uint32_t uSegmentOffset; // Segment offset
};
Figure 5-81. UDP Transfer Header Format 1, Segmented Data
5-47
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
5-48
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
CHAPTER 6
6-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
1 - Either Fibre Channel or IEEE 1394B is required for on-board recorders; other network
interfaces are optional. Ethernet is required for ground-based recorders; other network
interfaces are optional.
6-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Legend
(blank) Not used
X Used
R Required
O Only required if data type used
P Only required Data Packing Option (R-x\PDP-n) is Packed or Unpacked
Note: In the table below “R”, “O”, and “P” have only been entered for 2013, 2015, 2017,
and 2019.
Table A-1. Supported TMATS Code Values
TMATS Attribute Code 04 05 07 09 11 13 15 17 19
PROGRAM NAME G\PN X X X X X X X X X
TEST ITEM G\TA X X X X X X X X X
TMATS FILE NAME G\FN X X X X X X
IRIG 106 REVISION LEVEL G\106 X X X X X R R R R
ORIGINATION DATE G\OD X X X X X X X X X
REVISION NUMBER G\RN X X X X X X X X X
REVISION DATE G\RD X X X X X X X X X
UPDATE NUMBER G\UN X X X X X X X X X
UPDATE DATE G\UD X X X X X X X X X
TEST NUMBER G\TN X X X X X X X X X
NUMBER OF POINTS OF CONTACT G\POC\N X X X X X X X X X
NAME G\POC1-n X X X X X X X X X
AGENCY G\POC2-n X X X X X X X X X
ADDRESS G\POC3-n X X X X X X X X X
TELEPHONE G\POC4-n X X X X X X X X X
NUMBER OF DATA SOURCES G\DSI\N X X X X X R R R R
DATA SOURCE ID G\DSI-n X X X X X R R R R
DATA SOURCE TYPE G\DST-n X X X X X R R R R
DATA SOURCE SECURITY CLASSIFICATION G\DSC-n X X X X
TEST DURATION G\TI1 X X X X X X X X X
PRE-TEST REQUIREMENT G\TI2 X X X X X X X X X
POST-TEST REQUIREMENT G\TI3 X X X X X X X X X
SECURITY CLASSIFICATION G\SC X X X X X X X X X
MESSAGE DIGEST/CHECKSUM G\SHA X X X
COMMENTS G\COM X X X X X X X X X
DATA SOURCE ID T-x\ID X X X X X X O O O
TRANSMITTER ID T-x\TID X X X X X X X X X
A-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-5
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-6
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-7
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-8
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-9
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-10
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-11
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-12
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-13
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-14
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-15
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-16
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-17
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-18
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-19
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-20
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-21
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
A-22
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
B-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
irig106ch10.h -
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
****************************************************************************/
/** @file
IRIG 106 library core routines
*/
#ifndef _irig106ch10_h_
#define _irig106ch10_h_
#ifdef __cplusplus
namespace Irig106 {
extern "C" {
#endif
#include "config.h"
/*
* Macros and definitions
* ----------------------
*/
#if !defined(bTRUE)
#define bTRUE ((int)(1==1))
#define bFALSE ((int)(1==0))
#endif
B-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
B-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
B-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/// Read state is used to keep track of the next expected data file structure
typedef enum FileState
{
enClosed = 0,
enWrite = 1,
enReadUnsynced = 2,
enReadHeader = 3,
enReadData = 4,
enReadNetStream = 5,
} EnFileState;
/*
* Data structures
* ---------------
*/
#if defined(_MSC_VER)
#pragma pack(push)
#pragma pack(1)
#endif
/// IRIG 106 header and optional secondary header data structure
typedef PUBLIC struct SuI106Ch10Header_S
{
uint16_t uSync; ///< Packet Sync Pattern
uint16_t uChID; ///< Channel ID
uint32_t ulPacketLen; ///< Total packet length
uint32_t ulDataLen; ///< Data length
uint8_t ubyHdrVer; ///< Header Version
uint8_t ubySeqNum; ///< Sequence Number
uint8_t ubyPacketFlags; ///< PacketFlags
uint8_t ubyDataType; ///< Data type
uint8_t aubyRefTime[6]; ///< Reference time
uint16_t uChecksum; ///< Header Checksum
uint8_t abyTime[8]; ///< Time (start secondary header)
uint16_t uReserved; //
uint16_t uSecChecksum; ///< Secondary Header Checksum
#if !defined(__GNUC__)
} SuI106Ch10Header;
#else
} __attribute__ ((packed)) SuI106Ch10Header;
#endif
B-5
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
{
EnSortStatus enSortStatus;
SuInOrderPacketInfo * asuIndex;
int iArraySize;
int iArrayUsed;
int iArrayCurr; // Current position in index array
int64_t llNextReadOffset;
int iNumSearchSteps;
} SuInOrderIndex;
#if defined(_MSC_VER)
#pragma pack(pop)
#endif
/*
* Global data
* -----------
*/
/*
* Function Declaration
* --------------------
*/
// Open / Close
#if defined(IRIG_NETWORKING)
EnI106Status I106_CALL_DECL
enI106Ch10OpenStreamRead(
int * piI106Ch10Handle,
uint16_t uPort);
EnI106Status I106_CALL_DECL
enI106Ch10OpenStreamWrite(
int * piI106Ch10Handle,
B-6
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
uint32_t uIpAddress,
uint16_t uPort);
#endif
EnI106Status I106_CALL_DECL
enI106Ch10Close(
int iI106Handle);
// Read / Write
// ------------
EnI106Status I106_CALL_DECL
enI106Ch10ReadNextHeader(int iI106Ch10Handle,
SuI106Ch10Header * psuI106Hdr);
EnI106Status I106_CALL_DECL
enI106Ch10ReadNextHeaderFile(int iHandle,
SuI106Ch10Header * psuHeader);
EnI106Status I106_CALL_DECL
enI106Ch10ReadNextHeaderInOrder(int iHandle,
SuI106Ch10Header * psuHeader);
EnI106Status I106_CALL_DECL
enI106Ch10ReadPrevHeader(int iI106Ch10Handle,
SuI106Ch10Header * psuI106Hdr);
EnI106Status I106_CALL_DECL
enI106Ch10ReadData(int iI106Ch10Handle,
unsigned long ulBuffSize,
void * pvBuff);
EnI106Status I106_CALL_DECL
enI106Ch10ReadDataFile(int iHandle,
unsigned long ulBuffSize,
void * pvBuff);
EnI106Status I106_CALL_DECL
enI106Ch10WriteMsg(int iI106Ch10Handle,
SuI106Ch10Header * psuI106Hdr,
void * pvBuff);
EnI106Status I106_CALL_DECL
enI106Ch10FirstMsg(int iI106Ch10Handle);
EnI106Status I106_CALL_DECL
enI106Ch10LastMsg(int iI106Ch10Handle);
EnI106Status I106_CALL_DECL
enI106Ch10SetPos(int iI106Ch10Handle, int64_t llOffset);
EnI106Status I106_CALL_DECL
enI106Ch10GetPos(int iI106Ch10Handle, int64_t * pllOffset);
// Utilities
// ---------
int I106_CALL_DECL
B-7
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
iHeaderInit(SuI106Ch10Header * psuHeader,
unsigned int uChanID,
unsigned int uDataType,
unsigned int uFlags,
unsigned int uSeqNum);
int I106_CALL_DECL
iGetHeaderLen(SuI106Ch10Header * psuHeader);
uint32_t I106_CALL_DECL
uGetDataLen(SuI106Ch10Header * psuHeader);
uint16_t I106_CALL_DECL
uCalcHeaderChecksum(SuI106Ch10Header * psuHeader);
uint16_t I106_CALL_DECL
uCalcSecHeaderChecksum(SuI106Ch10Header * psuHeader);
uint32_t I106_CALL_DECL
uCalcDataBuffReqSize(uint32_t uDataLen, int iChecksumType);
EnI106Status I106_CALL_DECL
uAddDataFillerChecksum(SuI106Ch10Header * psuI106Hdr, unsigned char achData[]);
#ifdef __cplusplus
} // end namespace
} // end extern "C"
#endif
#endif
B-8
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
irig106ch10.c -
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <assert.h>
#if defined(__GNUC__)
#include <sys/io.h>
#else
#include <io.h>
#endif
#include "config.h"
#include "stdint.h"
#include "irig106ch10.h"
#include "i106_time.h"
B-9
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
#if defined(IRIG_NETWORKING)
#include "i106_data_stream.h"
#endif
#ifdef __cplusplus
namespace Irig106 {
#endif
/*
* Macros and definitions
* ----------------------
*/
/*
* Data structures
* ---------------
*/
/*
* Module data
* -----------
*/
SuI106Ch10Handle g_suI106Handle[MAX_HANDLES];
static int m_bHandlesInited = bFALSE;
/*
* Function Declaration
* --------------------
*/
void InitHandles();
int GetNextHandle();
/* ----------------------------------------------------------------------- */
EnI106Status I106_CALL_DECL
enI106Ch10Open(int * piHandle,
const char szFileName[],
EnI106Ch10Mode enMode)
{
int iReadCnt;
int iFlags;
int iFileMode;
uint16_t uSignature;
EnI106Status enStatus;
SuI106Ch10Header suI106Hdr;
B-10
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
g_suI106Handle[*piHandle].enFileState = enClosed;
g_suI106Handle[*piHandle].suInOrderIndex.enSortStatus = enUnsorted;
// If the first word isn't the sync value then return error
if (uSignature != IRIG106_SYNC)
{
close(g_suI106Handle[*piHandle].iFile);
g_suI106Handle[*piHandle].bInUse = bFALSE;
*piHandle = -1;
return I106_OPEN_ERROR;
}
B-11
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
if (I106_READ_IN_ORDER == enMode)
{
g_suI106Handle[*piHandle].suInOrderIndex.iArrayUsed = 0;
//vMakeInOrderIndex(*piHandle);
g_suI106Handle[*piHandle].suInOrderIndex.iArrayCurr = 0;
}
B-12
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
g_suI106Handle[*piHandle].enFileMode = enMode;
} // end if read mode
else
{
g_suI106Handle[*piHandle].enFileState = enClosed;
g_suI106Handle[*piHandle].enFileMode = I106_CLOSED;
g_suI106Handle[*piHandle].bInUse = bFALSE;
*piHandle = -1;
return I106_OPEN_ERROR;
}
return I106_OK;
}
/* ----------------------------------------------------------------------- */
#if defined(IRIG_NETWORKING)
EnI106Status I106_CALL_DECL
enI106Ch10OpenStreamRead(int * piHandle,
uint16_t uPort)
{
EnI106Status enStatus;
return enStatus;
}
/* ----------------------------------------------------------------------- */
EnI106Status I106_CALL_DECL
enI106Ch10OpenStreamWrite(
B-13
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
int * piHandle,
uint32_t uIpAddress,
uint16_t uPort)
{
EnI106Status enStatus;
return enStatus;
}
#endif
/* ----------------------------------------------------------------------- */
EnI106Status I106_CALL_DECL
enI106Ch10Close(int iHandle)
{
B-14
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
case I106_WRITE_NET_STREAM :
#if defined(IRIG_NETWORKING)
enI106_CloseNetStream(iHandle);
#endif
break;
return I106_OK;
}
/* ----------------------------------------------------------------------- */
// Get the next header. Depending on how the file was opened for reading,
// call the appropriate routine.
EnI106Status I106_CALL_DECL
enI106Ch10ReadNextHeader(int iHandle,
SuI106Ch10Header * psuHeader)
{
EnI106Status enStatus;
switch (g_suI106Handle[iHandle].enFileMode)
{
case I106_READ_NET_STREAM :
case I106_READ :
enStatus = enI106Ch10ReadNextHeaderFile(iHandle, psuHeader);
break;
case I106_READ_IN_ORDER :
if (g_suI106Handle[iHandle].suInOrderIndex.enSortStatus == enSorted)
enStatus = enI106Ch10ReadNextHeaderInOrder(iHandle, psuHeader);
else
enStatus = enI106Ch10ReadNextHeaderFile(iHandle, psuHeader);
break;
default :
enStatus = I106_WRONG_FILE_MODE;
break;
} // end switch on read mode
return enStatus;
}
/* ----------------------------------------------------------------------- */
B-15
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
// Get the next header in the file from the current position
EnI106Status I106_CALL_DECL
enI106Ch10ReadNextHeaderFile(int iHandle,
SuI106Ch10Header * psuHeader)
{
int iReadCnt;
int bReadHeaderWasOK;
int64_t llSkipSize;
int64_t llFileOffset;
EnI106Status enStatus;
case I106_OVERWRITE :
case I106_APPEND :
case I106_READ_IN_ORDER :
default :
return I106_WRONG_FILE_MODE;
break;
case I106_READ_NET_STREAM :
case I106_READ :
break;
} // end switch on read mode
case enWrite :
return I106_WRONG_FILE_MODE;
break;
case enReadHeader :
break;
case enReadData :
llSkipSize = g_suI106Handle[iHandle].ulCurrPacketLen -
g_suI106Handle[iHandle].ulCurrHeaderBuffLen -
g_suI106Handle[iHandle].ulCurrDataBuffReadPos;
if (g_suI106Handle[iHandle].enFileMode != I106_READ_NET_STREAM)
{
enStatus = enI106Ch10GetPos(iHandle, &llFileOffset);
if (enStatus != I106_OK)
B-16
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
return I106_SEEK_ERROR;
llFileOffset += llSkipSize;
case enReadUnsynced :
break;
B-17
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
B-18
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
// Read header was not OK so try again beyond previous read point
if (g_suI106Handle[iHandle].enFileMode != I106_READ_NET_STREAM)
{
enStatus = enI106Ch10GetPos(iHandle, &llFileOffset);
if (enStatus != I106_OK)
return I106_SEEK_ERROR;
return I106_OK;
} // end enI106Ch10ReadNextHeaderFile()
/* ----------------------------------------------------------------------- */
EnI106Status I106_CALL_DECL
enI106Ch10ReadNextHeaderInOrder(int iHandle,
SuI106Ch10Header * psuHeader)
{
// If we're at the end of the list then we are at the end of the file
if (psuIndex->iArrayCurr == psuIndex->iArrayUsed)
return I106_EOF;
B-19
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
// If the state was unsynced before but is synced now, figure out where in the
// index we are
if ((enSavedFileState == enReadUnsynced) && (g_suI106Handle[iHandle].enFileState
!= enReadUnsynced))
{
enI106Ch10GetPos(iHandle, &llOffset);
llOffset -= iGetHeaderLen(psuHeader);
psuIndex->iArrayCurr = 0;
while (psuIndex->iArrayCurr < psuIndex->iArrayUsed)
{
if (llOffset == psuIndex->asuIndex[psuIndex->iArrayCurr].llOffset)
break;
psuIndex->iArrayCurr++;
}
// if psuIndex->iArrayCurr == psuIndex->iArrayUsed then bad things happened
}
return enStatus;
} // end enI106Ch10ReadNextHeaderInOrder()
/* ----------------------------------------------------------------------- */
EnI106Status I106_CALL_DECL
enI106Ch10ReadPrevHeader(int iHandle,
SuI106Ch10Header * psuHeader)
{
int bStillReading;
int iReadCnt;
int64_t llCurrPos;
EnI106Status enStatus;
uint64_t llInitialBackup;
int iBackupAmount;
uint64_t llNextBuffReadPos;
uint8_t abyScanBuff[BACKUP_SIZE+HEADER_SIZE];
int iBuffIdx;
uint16_t uCheckSum;
case I106_OVERWRITE :
case I106_APPEND :
case I106_READ_IN_ORDER : // HANDLE THE READ IN ORDER MODE!!!!
case I106_READ_NET_STREAM :
B-20
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
default :
return I106_WRONG_FILE_MODE;
break;
case I106_READ :
break;
} // end switch on read mode
case enWrite :
return I106_WRONG_FILE_MODE;
break;
case enReadHeader :
case enReadData :
// Backup to a point just before the most recently read header.
// The amount to backup is the size of the previous header and the amount
// of data already read.
llInitialBackup = g_suI106Handle[iHandle].ulCurrHeaderBuffLen +
g_suI106Handle[iHandle].ulCurrDataBuffReadPos;
break;
case enReadUnsynced :
llInitialBackup = 0;
break;
} // end switch file state
// This puts us at the beginning of the most recently read header (or BOF)
enI106Ch10GetPos(iHandle, &llCurrPos);
llCurrPos = llCurrPos - llInitialBackup;
B-21
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
// Check to see if we're at the BOF. BTW, if we're at the beginning of a file
// and a valid header wasn't found then it IS a seek error.
if (llCurrPos == 0)
{
bStillReading = bFALSE;
enStatus = I106_SEEK_ERROR;
}
return enStatus;
} // end enI106Ch10ReadPrevHeader()
/* ----------------------------------------------------------------------- */
// Get the next header. Depending on how the file was opened for reading,
// call the appropriate routine.
EnI106Status I106_CALL_DECL
enI106Ch10ReadData(int iHandle,
unsigned long ulBuffSize,
void * pvBuff)
{
EnI106Status enStatus;
B-22
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
switch (g_suI106Handle[iHandle].enFileMode)
{
case I106_READ_NET_STREAM :
case I106_READ :
case I106_READ_IN_ORDER :
enStatus = enI106Ch10ReadDataFile(iHandle, ulBuffSize, pvBuff);
break;
default :
enStatus = I106_WRONG_FILE_MODE;
break;
return enStatus;
}
/* ----------------------------------------------------------------------- */
EnI106Status I106_CALL_DECL
enI106Ch10ReadDataFile(int iHandle,
unsigned long ulBuffSize,
void * pvBuff)
{
int iReadCnt;
unsigned long ulReadAmount;
case I106_OVERWRITE :
case I106_APPEND :
return I106_WRONG_FILE_MODE;
break;
} // end switch on read mode
case enWrite :
return I106_WRONG_FILE_MODE;
break;
case enReadData :
break;
B-23
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
default :
// MIGHT WANT TO SUPPORT THE "MORE DATA" METHOD INSTEAD
g_suI106Handle[iHandle].enFileState = enReadUnsynced;
return I106_READ_ERROR;
break;
} // end switch file state
return I106_OK;
} // end enI106Ch10ReadData()
/* ----------------------------------------------------------------------- */
EnI106Status I106_CALL_DECL
enI106Ch10WriteMsg(int iHandle,
SuI106Ch10Header * psuHeader,
void * pvBuff)
{
int iHeaderLen;
int iWriteCnt;
B-24
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
case I106_READ :
case I106_READ_IN_ORDER :
case I106_READ_NET_STREAM :
return I106_WRONG_FILE_MODE;
break;
} // end switch on read mode
return I106_OK;
}
/* -----------------------------------------------------------------------
* Move file pointer
* ----------------------------------------------------------------------- */
EnI106Status I106_CALL_DECL
enI106Ch10FirstMsg(int iHandle)
{
B-25
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
{
case I106_CLOSED :
return I106_NOT_OPEN;
break;
case I106_OVERWRITE :
case I106_APPEND :
case I106_READ_NET_STREAM :
default :
return I106_WRONG_FILE_MODE;
break;
case I106_READ_IN_ORDER :
g_suI106Handle[iHandle].suInOrderIndex.iArrayCurr = 0;
enI106Ch10SetPos(iHandle, 0L);
break;
case I106_READ :
enI106Ch10SetPos(iHandle, 0L);
break;
} // end switch on read mode
return I106_OK;
}
/* ----------------------------------------------------------------------- */
EnI106Status I106_CALL_DECL
enI106Ch10LastMsg(int iHandle)
{
EnI106Status enReturnStatus;
EnI106Status enStatus;
int64_t llPos;
SuI106Ch10Header suHeader;
int iReadCnt;
#if !defined(_MSC_VER)
struct stat suStatBuff;
#endif
case I106_OVERWRITE :
case I106_APPEND :
case I106_READ_NET_STREAM :
default :
return I106_WRONG_FILE_MODE;
break;
B-26
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
// If its opened for reading in order then just set the index pointer
// to the last index.
case I106_READ_IN_ORDER :
g_suI106Handle[iHandle].suInOrderIndex.iArrayCurr =
g_suI106Handle[iHandle].suInOrderIndex.iArrayUsed-1;
enReturnStatus = I106_OK;
break;
//if ((llPos % 4) != 0)
// return I106_SEEK_ERROR;
if (iReadCnt != HEADER_SIZE)
continue;
if (suHeader.uSync != IRIG106_SYNC)
continue;
B-27
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
break;
} // end switch on read mode
return enReturnStatus;
}
/* ----------------------------------------------------------------------- */
EnI106Status I106_CALL_DECL
enI106Ch10SetPos(int iHandle, int64_t llOffset)
{
case I106_OVERWRITE :
case I106_APPEND :
case I106_READ_NET_STREAM :
default :
return I106_WRONG_FILE_MODE;
break;
case I106_READ_IN_ORDER :
case I106_READ :
// Seek
#if defined(_WIN32)
{
__int64 llStatus;
llStatus = _lseeki64(g_suI106Handle[iHandle].iFile, llOffset, SEEK_SET);
}
#else
{
off64_t llStatus;
llStatus = lseek64(g_suI106Handle[iHandle].iFile, (off64_t)llOffset, SEEK_SET);
assert(llStatus >= 0);
}
#endif
return I106_OK;
}
B-28
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/* ----------------------------------------------------------------------- */
EnI106Status I106_CALL_DECL
enI106Ch10GetPos(int iHandle, int64_t *pllOffset)
{
case I106_READ_NET_STREAM :
default :
return I106_WRONG_FILE_MODE;
break;
case I106_READ_IN_ORDER :
case I106_READ :
case I106_OVERWRITE :
case I106_APPEND :
// Get position
#if defined(_WIN32)
*pllOffset = _telli64(g_suI106Handle[iHandle].iFile);
#else
{
*pllOffset = (int64_t)lseek64(g_suI106Handle[iHandle].iFile, (off64_t)0,
SEEK_CUR);
assert(*pllOffset >= 0);
}
#endif
break;
} // end switch on file mode
return I106_OK;
}
/* -----------------------------------------------------------------------
* Utilities
* ----------------------------------------------------------------------- */
/* Set packet header to some sane values. Be sure to fill in proper values for:
ulPacketLen
ulDataLen
ubyHdrVer
aubyRefTime
uChecksum
*/
int I106_CALL_DECL
iHeaderInit(SuI106Ch10Header * psuHeader,
B-29
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
return 0;
}
/* ----------------------------------------------------------------------- */
int I106_CALL_DECL
iGetHeaderLen(SuI106Ch10Header * psuHeader)
{
int iHeaderLen;
return iHeaderLen;
}
/* ----------------------------------------------------------------------- */
// Figure out data length including padding and any data checksum
uint32_t I106_CALL_DECL
uGetDataLen(SuI106Ch10Header * psuHeader)
{
int iDataLen;
return iDataLen;
}
B-30
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/* ----------------------------------------------------------------------- */
uint16_t I106_CALL_DECL
uCalcHeaderChecksum(SuI106Ch10Header * psuHeader)
{
int iHdrIdx;
uint16_t uHdrSum;
uint16_t * aHdr = (uint16_t *)psuHeader;
uHdrSum = 0;
for (iHdrIdx=0; iHdrIdx<(HEADER_SIZE-2)/2; iHdrIdx++)
uHdrSum += aHdr[iHdrIdx];
return uHdrSum;
}
/* ----------------------------------------------------------------------- */
uint16_t I106_CALL_DECL
uCalcSecHeaderChecksum(SuI106Ch10Header * psuHeader)
{
int iByteIdx;
uint16_t uHdrSum;
// MAKE THIS 16 BIT UNSIGNEDS LIKE ABOVE
unsigned char * auchHdrByte = (unsigned char *)psuHeader;
uHdrSum = 0;
for (iByteIdx=0; iByteIdx<SEC_HEADER_SIZE-2; iByteIdx++)
uHdrSum += auchHdrByte[iByteIdx+HEADER_SIZE];
return uHdrSum;
}
/* ----------------------------------------------------------------------- */
// Calculate and return the required size of the data buffer portion of the
// packet including checksum and appropriate filler for 4 byte alignment.
uint32_t I106_CALL_DECL
uCalcDataBuffReqSize(uint32_t uDataLen, int iChecksumType)
{
uint32_t uDataBuffLen;
B-31
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
break;
default :
uDataBuffLen = 0;
} // end switch iChecksumType
return uDataBuffLen;
}
/* ----------------------------------------------------------------------- */
// Add the filler and appropriate checksum to the end of the data buffer
// It is assumed that the buffer is big enough to hold additional filler
// and the checksum. Also fill in the header with the correct packet length.
EnI106Status I106_CALL_DECL
uAddDataFillerChecksum(SuI106Ch10Header * psuI106Hdr, unsigned char achData[])
{
uint32_t uDataIdx;
uint32_t uDataBuffSize;
uint32_t uFillSize;
int iChecksumType;
uint8_t *puSum8;
uint8_t *puData8;
uint16_t *puSum16;
uint16_t *puData16;
uint32_t *puSum32;
uint32_t *puData32;
B-32
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
break;
case I106CH10_PFLAGS_CHKSUM_16 :
puData16 = (uint16_t *)achData;
puSum16 = (uint16_t *)&achData[psuI106Hdr->ulDataLen+uFillSize-2];
for (uDataIdx=0; uDataIdx<(uDataBuffSize/2)-1; uDataIdx++)
{
*puSum16 += *puData16;
puData16++;
}
break;
case I106CH10_PFLAGS_CHKSUM_32 :
puData32 = (uint32_t *)achData;
puSum32 = (uint32_t *)&achData[psuI106Hdr->ulDataLen+uFillSize-4];
for (uDataIdx=0; uDataIdx<(uDataBuffSize/4)-1; uDataIdx++)
{
*puSum32 += *puData32;
puData32++;
}
break;
default :
break;
} // end switch iChecksumType
return I106_OK;
}
// -----------------------------------------------------------------------
switch (enStatus)
{
case I106_OK : szErrorMsg = "No error"; break;
case I106_OPEN_ERROR : szErrorMsg = "File open failed"; break;
case I106_OPEN_WARNING : szErrorMsg = "File open warning"; break;
case I106_EOF : szErrorMsg = "End of file"; break;
case I106_BOF : szErrorMsg = "Beginning of file"; break;
case I106_READ_ERROR : szErrorMsg = "Read error"; break;
case I106_WRITE_ERROR : szErrorMsg = "Write error"; break;
case I106_MORE_DATA : szErrorMsg = "More data available"; break;
case I106_SEEK_ERROR : szErrorMsg = "Seek error"; break;
case I106_WRONG_FILE_MODE : szErrorMsg = "Wrong file mode"; break;
case I106_NOT_OPEN : szErrorMsg = "File not open"; break;
case I106_ALREADY_OPEN : szErrorMsg = "File already open"; break;
case I106_BUFFER_TOO_SMALL : szErrorMsg = "Buffer too small"; break;
case I106_NO_MORE_DATA : szErrorMsg = "No more data"; break;
case I106_NO_FREE_HANDLES : szErrorMsg = "No free file handles"; break;
case I106_INVALID_HANDLE : szErrorMsg = "Invalid file handle"; break;
case I106_TIME_NOT_FOUND : szErrorMsg = "Time not found"; break;
case I106_HEADER_CHKSUM_BAD : szErrorMsg = "Bad header checksum"; break;
case I106_NO_INDEX : szErrorMsg = "No index"; break;
case I106_UNSUPPORTED : szErrorMsg = "Unsupported feature"; break;
case I106_BUFFER_OVERRUN : szErrorMsg = "Buffer overrun"; break;
case I106_INDEX_NODE : szErrorMsg = "Index node"; break;
case I106_INDEX_ROOT : szErrorMsg = "Index root"; break;
case I106_INDEX_ROOT_LINK : szErrorMsg = "Index root link"; break;
case I106_INVALID_DATA : szErrorMsg = "Invalid data"; break;
case I106_INVALID_PARAMETER : szErrorMsg = "Invalid parameter"; break;
B-33
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
return szErrorMsg;
}
// -----------------------------------------------------------------------
void InitHandles()
{
int iIdx;
// -----------------------------------------------------------------------
int GetNextHandle()
{
int iHandle;
int iIdx;
iHandle = -1;
for (iIdx=0; iIdx<MAX_HANDLES; iIdx++)
{
if (g_suI106Handle[iIdx].bInUse == bFALSE)
{
g_suI106Handle[iIdx].bInUse = bTRUE;
iHandle = iIdx;
break;
} // end if unused handle found
} // end looking for unused handle
return iHandle;
}
#ifdef __cplusplus
} // end namespace
#endif
B-34
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
i106_time.h -
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
****************************************************************************/
#ifndef _I106_TIME_H
#define _I106_TIME_H
//#include "irig106ch10.h"
#include <time.h>
#ifdef __cplusplus
namespace Irig106 {
extern "C" {
#endif
/*
* Macros and definitions
* ----------------------
*/
B-35
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/*
* Data structures
* ---------------
*/
B-36
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/*
* Global data
* -----------
*/
/*
* Function Declaration
* --------------------
*/
//EnI106Status I106_CALL_DECL
// enI106_SetRelTime(int iI106Ch10Handle,
// SuIrig106Time * psuTime,
// uint8_t abyRelTime[]);
B-37
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
EnI106Status I106_CALL_DECL
enI106_SetRelTime(int iI106Ch10Handle,
SuIrig106Time * psuTime,
uint8_t abyRelTime[]);
EnI106Status I106_CALL_DECL
enI106_Rel2IrigTime(int iI106Ch10Handle,
uint8_t abyRelTime[],
SuIrig106Time * psuTime);
EnI106Status I106_CALL_DECL
enI106_RelInt2IrigTime(int iI106Ch10Handle,
int64_t llRelTime,
SuIrig106Time * psuTime);
EnI106Status I106_CALL_DECL
enI106_Irig2RelTime(int iI106Ch10Handle,
SuIrig106Time * psuTime,
uint8_t abyRelTime[]);
EnI106Status I106_CALL_DECL
enI106_Ch4Binary2IrigTime(SuI106Ch4_Binary_Time * psuCh4BinaryTime,
SuIrig106Time * psuIrig106Time);
EnI106Status I106_CALL_DECL
enI106_IEEE15882IrigTime(SuIEEE1588_Time * psuIEEE1588Time,
SuIrig106Time * psuIrig106Time);
EnI106Status I106_CALL_DECL
vFillInTimeStruct(SuI106Ch10Header * psuHeader,
SuIntraPacketTS * psuIntraPacketTS,
SuTimeRef * psuTimeRef);
// Warning - array to int / int to array functions are little endian only!
void I106_CALL_DECL
vLLInt2TimeArray(int64_t * pllRelTime,
uint8_t abyRelTime[]);
void I106_CALL_DECL
vTimeArray2LLInt(uint8_t abyRelTime[],
int64_t * pllRelTime);
EnI106Status I106_CALL_DECL
enI106_SyncTime(int iI106Ch10Handle,
int bRequireSync, // Require external time sync
int iTimeLimit); // Max scan ahead time in seconds, 0 =
no limit
EnI106Status I106_CALL_DECL
enI106Ch10SetPosToIrigTime(int iI106Ch10Handle, SuIrig106Time * psuSeekTime);
// This is handy enough that we'll go ahead and export it to the world
uint32_t I106_CALL_DECL mkgmtime(struct tm * psuTmTime);
B-38
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
#ifdef __cplusplus
} // end extern "C"
} // end namespace i106
#endif
#endif
B-39
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
i106_time.c -
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <time.h>
#include "stdint.h"
#include "irig106ch10.h"
#include "i106_time.h"
#include "i106_decode_time.h"
#ifdef __cplusplus
namespace Irig106 {
#endif
/*
* Macros and definitions
* ----------------------
*/
/*
* Data structures
* ---------------
*/
B-40
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/*
* Module data
* -----------
*/
/*
* Function Declaration
* --------------------
*/
/* ----------------------------------------------------------------------- */
return I106_OK;
}
/* ----------------------------------------------------------------------- */
// Take a 6 byte relative time value (like the one in the IRIG header) and
// turn it into a real time based on the current reference IRIG time.
EnI106Status I106_CALL_DECL
enI106_Rel2IrigTime(int iI106Ch10Handle,
uint8_t abyRelTime[],
SuIrig106Time * psuTime)
{
int64_t llRelTime;
EnI106Status enStatus;
// Convert 6 byte time array to 16 bit int. This only works for
// positive time, but that shouldn't be a problem
llRelTime = 0L;
memcpy(&llRelTime, &abyRelTime[0], 6);
return enStatus;
}
B-41
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/* ----------------------------------------------------------------------- */
// Take a 64 bit relative time value and turn it into a real time based on
// the current reference IRIG time.
EnI106Status I106_CALL_DECL
enI106_RelInt2IrigTime(int iI106Ch10Handle,
int64_t llRelTime,
SuIrig106Time * psuTime)
{
int64_t uTimeDiff;
int64_t lFracDiff;
int64_t lSecDiff;
int64_t lSec;
int64_t lFrac;
// Now add the time difference to the last IRIG time reference
psuTime->ulFrac = (unsigned long)lFrac;
psuTime->ulSecs = (unsigned long)lSec;
psuTime->enFmt = m_asuTimeRef[iI106Ch10Handle].suIrigTime.enFmt;
return I106_OK;
}
/* ----------------------------------------------------------------------- */
// Take a real clock time and turn it into a 6 byte relative time.
EnI106Status I106_CALL_DECL
enI106_Irig2RelTime(int iI106Ch10Handle,
SuIrig106Time * psuTime,
uint8_t abyRelTime[])
{
int64_t llDiff;
int64_t llNewRel;
// Calculate time difference (LSB = 100 nSec) between the passed time
B-42
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
return I106_OK;
}
/* ----------------------------------------------------------------------- */
// Take a Irig Ch4 time value (like the one in a secondary IRIG header) and
// turn it into an Irig106 time
EnI106Status I106_CALL_DECL
enI106_Ch4Binary2IrigTime(SuI106Ch4_Binary_Time * psuCh4BinaryTime,
SuIrig106Time * psuIrig106Time)
{
psuIrig106Time->ulSecs = (unsigned long)
( (double)psuCh4BinaryTime->uHighBinTime * CH4BINARYTIME_HIGH_LSB_SEC
+ (unsigned long)psuCh4BinaryTime->uLowBinTime * CH4BINARYTIME_LOW_LSB_SEC );
psuIrig106Time->ulFrac = (unsigned long)psuCh4BinaryTime->uUSecs *
_100_NANO_SEC_IN_MICRO_SEC;
return I106_OK;
}
/* ----------------------------------------------------------------------- */
// Take a IEEE-1588 time value (like the one in a secondary IRIG header) and
// turn it into an Irig106 time
EnI106Status I106_CALL_DECL
enI106_IEEE15882IrigTime(SuIEEE1588_Time * psuIEEE1588Time,
SuIrig106Time * psuIrig106Time)
{
psuIrig106Time->ulSecs = (unsigned long)psuIEEE1588Time->uSeconds;
//Convert 'nanoseconds' to '100 nanoseconds'
psuIrig106Time->ulFrac = (unsigned long)psuIEEE1588Time->uNanoSeconds/100;
return I106_OK;
}
/* ------------------------------------------------------------------------ */
// Warning - array to int / int to array functions are little endian only!
void I106_CALL_DECL
vLLInt2TimeArray(int64_t * pllRelTime,
uint8_t abyRelTime[])
{
memcpy((char *)abyRelTime, (char *)pllRelTime, 6);
return;
B-43
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/* ------------------------------------------------------------------------ */
void I106_CALL_DECL
vTimeArray2LLInt(uint8_t abyRelTime[],
int64_t * pllRelTime)
{
*pllRelTime = 0L;
memcpy((char *)pllRelTime, (char *)abyRelTime, 6);
return;
}
/* ------------------------------------------------------------------------ */
// Read the data file from the current position to try to determine a valid
// relative time to clock time from a time packet.
EnI106Status I106_CALL_DECL
enI106_SyncTime(int iI106Ch10Handle,
int bRequireSync, // Require external time source sync
int iTimeLimit) // Max time to look in seconds
{
int64_t llCurrOffset;
int64_t llTimeLimit;
int64_t llCurrTime;
EnI106Status enStatus;
EnI106Status enRetStatus;
SuI106Ch10Header suI106Hdr;
SuIrig106Time suTime;
unsigned long ulBuffSize = 0;
void * pvBuff = NULL;
SuTimeF1_ChanSpec * psuChanSpecTime = NULL;
if (enStatus != I106_OK)
return enStatus;
B-44
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
else
llTimeLimit = 0;
if (enStatus != I106_OK)
{
enRetStatus = enStatus;
break;
}
B-45
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
return enRetStatus;
}
/* ----------------------------------------------------------------------- */
EnI106Status I106_CALL_DECL
enI106Ch10SetPosToIrigTime(int iHandle, SuIrig106Time * psuSeekTime)
{
uint8_t abySeekTime[6];
int64_t llSeekTime;
SuInOrderIndex * psuIndex = &g_suI106Handle[iHandle].suInOrderIndex;
int iUpperLimit;
int iLowerLimit;
int iSearchLoopIdx;
// If we don't already have it, figure out how many search steps
if (psuIndex->iNumSearchSteps == 0)
{
iUpperLimit = 1;
while (iUpperLimit < psuIndex->iArrayUsed)
{
iUpperLimit *= 2;
psuIndex->iNumSearchSteps++;
}
} // end if no search steps
B-46
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
iUpperLimit = psuIndex->iArrayUsed-1;
psuIndex->iArrayCurr = (iUpperLimit - iLowerLimit) / 2;
for (iSearchLoopIdx = 0;
iSearchLoopIdx < psuIndex->iNumSearchSteps;
iSearchLoopIdx++)
{
if (psuIndex->asuIndex[psuIndex->iArrayCurr].llTime > llSeekTime)
iUpperLimit = (iUpperLimit - iLowerLimit) / 2;
else if (psuIndex->asuIndex[psuIndex->iArrayCurr].llTime < llSeekTime)
iLowerLimit = (iUpperLimit - iLowerLimit) / 2;
else
break;
}
return I106_OK;
}
/* ------------------------------------------------------------------------ */
return szTime;
}
B-47
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/* ------------------------------------------------------------------------ */
// This function fills in the SuTimeRef structure with the "best" relative
// and/or absolute time stamp available from the packet header and intra-packet
// header (if available).
EnI106Status I106_CALL_DECL
vFillInTimeStruct(SuI106Ch10Header * psuHeader,
SuIntraPacketTS * psuIntraPacketTS,
SuTimeRef * psuTimeRef)
{
int iSecHdrTimeFmt;
B-48
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
*)psuIntraPacketTS, &(psuTimeRef->suIrigTime));
psuTimeRef->bAbsTimeValid = bTRUE;
break;
case I106CH10_PFLAGS_TIMEFMT_IEEE1588:
enI106_IEEE15882IrigTime((SuIEEE1588_Time *)psuIntraPacketTS,
&(psuTimeRef->suIrigTime));
psuTimeRef->bAbsTimeValid = bTRUE;
break;
default:
//Current reserved, should we have a default way to decode
break;
} // end switch on intra-packet time format
} // end else absolute time
} // end if intra-packet time stamp exists
return I106_OK;
}
/* ------------------------------------------------------------------------ */
/* Return the equivalent in seconds past 12:00:00 a.m. Jan 1, 1970 GMT
of the Greenwich Mean time and date in the exploded time structure `tm'.
The standard mktime() has the annoying "feature" of assuming that the
time in the tm structure is local time, and that it has to be corrected
for local time zone. In this library time is assumed to be UTC and UTC
only. To make sure no timezone correction is applied this time conversion
routine was lifted from the standard C run time library source. Interestingly
enough, this routine was found in the source for mktime().
This function does always put back normalized values into the `tm' struct,
parameter, including the calculated numbers for `tm->tm_yday',
`tm->tm_wday', and `tm->tm_isdst'.
// Number of leap years from 1970 to `y' (not including `y' itself).
#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
B-49
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
if (days < 0)
do
{
if (--months < 0)
{
--years;
months = 11;
}
days += monthlen(months, years);
} while (days < 0);
else
while (days >= monthlen(months, years))
{
days -= monthlen(months, years);
if (++months >= 12)
{
++years;
months = 0;
}
} // end while
B-50
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
return (uint32_t)-1;
#ifdef __cplusplus
} // end namespace i106
#endif
B-51
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
i106_decode_time.h -
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
****************************************************************************/
#ifndef _I106_DECODE_TIME_H
#define _I106_DECODE_TIME_H
//#include "irig106ch10.h"
#ifdef __cplusplus
namespace Irig106 {
extern "C" {
#endif
/*
* Macros and definitions
* ----------------------
*/
typedef enum
{
I106_TIMEFMT_IRIG_B = 0x00,
I106_TIMEFMT_IRIG_A = 0x01,
I106_TIMEFMT_IRIG_G = 0x02,
I106_TIMEFMT_INT_RTC = 0x03,
I106_TIMEFMT_GPS_UTC = 0x04,
I106_TIMEFMT_GPS_NATIVE = 0x05,
} EnI106TimeFmt;
B-52
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
typedef enum
{
I106_TIMESRC_INTERNAL = 0x00,
I106_TIMESRC_EXTERNAL = 0x01,
I106_TIMESRC_INTERNAL_RMM = 0x02,
I106_TIMESRC_NONE = 0x0F
} EnI106TimeSrc;
/*
* Data structures
* ---------------
*/
#if defined(_MSC_VER)
#pragma pack(push)
#pragma pack(1)
#endif
/* Time Format 1 */
B-53
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
typedef struct
{
uint16_t uTmn : 4; // Tens of milliseconds
uint16_t uHmn : 4; // Hundreds of milliseconds
uint16_t uSn : 4; // Units of seconds
uint16_t uTSn : 3; // Tens of seconds
uint16_t Reserved1 : 1; // 0
/* Time Format 2 */
B-54
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
#if !defined(__GNUC__)
} SuTimeF2_Data;
#else
} __attribute__ ((packed)) SuTimeF2_Data;
#endif
#if defined(_MSC_VER)
#pragma pack(pop)
#endif
/*
* Function Declaration
* --------------------
*/
EnI106Status I106_CALL_DECL
enI106_Decode_TimeF1(SuI106Ch10Header * psuHeader,
void * pvBuff,
SuIrig106Time * psuTime);
void I106_CALL_DECL
enI106_Decode_TimeF1_Buff(int iDateFmt,
int bLeapYear,
void * pvTimeBuff,
SuIrig106Time * psuTime);
EnI106Status I106_CALL_DECL
enI106_Encode_TimeF1(SuI106Ch10Header * psuHeader,
unsigned int uTimeSrc,
unsigned int uFmtTime,
unsigned int uFmtDate,
SuIrig106Time * psuTime,
void * pvBuffTimeF1);
#ifdef __cplusplus
}
}
#endif
#endif
B-55
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
i106_time.c -
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <time.h>
#include "stdint.h"
#include "irig106ch10.h"
#include "i106_time.h"
#include "i106_decode_time.h"
#ifdef __cplusplus
namespace Irig106 {
#endif
/*
* Macros and definitions
* ----------------------
*/
/*
* Data structures
* ---------------
*/
B-56
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/*
* Module data
* -----------
*/
/*
* Function Declaration
* --------------------
*/
/* ----------------------------------------------------------------------- */
return I106_OK;
}
/* ----------------------------------------------------------------------- */
// Take a 6 byte relative time value (like the one in the IRIG header) and
// turn it into a real time based on the current reference IRIG time.
EnI106Status I106_CALL_DECL
enI106_Rel2IrigTime(int iI106Ch10Handle,
uint8_t abyRelTime[],
SuIrig106Time * psuTime)
{
int64_t llRelTime;
EnI106Status enStatus;
// Convert 6 byte time array to 16 bit int. This only works for
// positive time, but that shouldn't be a problem
llRelTime = 0L;
memcpy(&llRelTime, &abyRelTime[0], 6);
return enStatus;
}
B-57
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/* ----------------------------------------------------------------------- */
// Take a 64 bit relative time value and turn it into a real time based on
// the current reference IRIG time.
EnI106Status I106_CALL_DECL
enI106_RelInt2IrigTime(int iI106Ch10Handle,
int64_t llRelTime,
SuIrig106Time * psuTime)
{
int64_t uTimeDiff;
int64_t lFracDiff;
int64_t lSecDiff;
int64_t lSec;
int64_t lFrac;
// Now add the time difference to the last IRIG time reference
psuTime->ulFrac = (unsigned long)lFrac;
psuTime->ulSecs = (unsigned long)lSec;
psuTime->enFmt = m_asuTimeRef[iI106Ch10Handle].suIrigTime.enFmt;
return I106_OK;
}
/* ----------------------------------------------------------------------- */
// Take a real clock time and turn it into a 6 byte relative time.
EnI106Status I106_CALL_DECL
enI106_Irig2RelTime(int iI106Ch10Handle,
SuIrig106Time * psuTime,
uint8_t abyRelTime[])
{
int64_t llDiff;
int64_t llNewRel;
// Calculate time difference (LSB = 100 nSec) between the passed time
B-58
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
return I106_OK;
}
/* ----------------------------------------------------------------------- */
// Take a Irig Ch4 time value (like the one in a secondary IRIG header) and
// turn it into an Irig106 time
EnI106Status I106_CALL_DECL
enI106_Ch4Binary2IrigTime(SuI106Ch4_Binary_Time * psuCh4BinaryTime,
SuIrig106Time * psuIrig106Time)
{
psuIrig106Time->ulSecs = (unsigned long)
( (double)psuCh4BinaryTime->uHighBinTime * CH4BINARYTIME_HIGH_LSB_SEC
+ (unsigned long)psuCh4BinaryTime->uLowBinTime * CH4BINARYTIME_LOW_LSB_SEC );
psuIrig106Time->ulFrac = (unsigned long)psuCh4BinaryTime->uUSecs *
_100_NANO_SEC_IN_MICRO_SEC;
return I106_OK;
}
/* ----------------------------------------------------------------------- */
// Take a IEEE-1588 time value (like the one in a secondary IRIG header) and
// turn it into an Irig106 time
EnI106Status I106_CALL_DECL
enI106_IEEE15882IrigTime(SuIEEE1588_Time * psuIEEE1588Time,
SuIrig106Time * psuIrig106Time)
{
psuIrig106Time->ulSecs = (unsigned long)psuIEEE1588Time->uSeconds;
//Convert 'nanoseconds' to '100 nanoseconds'
psuIrig106Time->ulFrac = (unsigned long)psuIEEE1588Time->uNanoSeconds/100;
return I106_OK;
}
/* ------------------------------------------------------------------------ */
// Warning - array to int / int to array functions are little endian only!
void I106_CALL_DECL
vLLInt2TimeArray(int64_t * pllRelTime,
uint8_t abyRelTime[])
{
memcpy((char *)abyRelTime, (char *)pllRelTime, 6);
return;
B-59
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/* ------------------------------------------------------------------------ */
void I106_CALL_DECL
vTimeArray2LLInt(uint8_t abyRelTime[],
int64_t * pllRelTime)
{
*pllRelTime = 0L;
memcpy((char *)pllRelTime, (char *)abyRelTime, 6);
return;
}
/* ------------------------------------------------------------------------ */
// Read the data file from the current position to try to determine a valid
// relative time to clock time from a time packet.
EnI106Status I106_CALL_DECL
enI106_SyncTime(int iI106Ch10Handle,
int bRequireSync, // Require external time source sync
int iTimeLimit) // Max time to look in seconds
{
int64_t llCurrOffset;
int64_t llTimeLimit;
int64_t llCurrTime;
EnI106Status enStatus;
EnI106Status enRetStatus;
SuI106Ch10Header suI106Hdr;
SuIrig106Time suTime;
unsigned long ulBuffSize = 0;
void * pvBuff = NULL;
SuTimeF1_ChanSpec * psuChanSpecTime = NULL;
if (enStatus != I106_OK)
return enStatus;
B-60
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
else
llTimeLimit = 0;
if (enStatus != I106_OK)
{
enRetStatus = enStatus;
break;
}
B-61
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
return enRetStatus;
}
/* ----------------------------------------------------------------------- */
EnI106Status I106_CALL_DECL
enI106Ch10SetPosToIrigTime(int iHandle, SuIrig106Time * psuSeekTime)
{
uint8_t abySeekTime[6];
int64_t llSeekTime;
SuInOrderIndex * psuIndex = &g_suI106Handle[iHandle].suInOrderIndex;
int iUpperLimit;
int iLowerLimit;
int iSearchLoopIdx;
// If we don't already have it, figure out how many search steps
if (psuIndex->iNumSearchSteps == 0)
{
iUpperLimit = 1;
while (iUpperLimit < psuIndex->iArrayUsed)
{
iUpperLimit *= 2;
psuIndex->iNumSearchSteps++;
}
} // end if no search steps
B-62
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
iUpperLimit = psuIndex->iArrayUsed-1;
psuIndex->iArrayCurr = (iUpperLimit - iLowerLimit) / 2;
for (iSearchLoopIdx = 0;
iSearchLoopIdx < psuIndex->iNumSearchSteps;
iSearchLoopIdx++)
{
if (psuIndex->asuIndex[psuIndex->iArrayCurr].llTime > llSeekTime)
iUpperLimit = (iUpperLimit - iLowerLimit) / 2;
else if (psuIndex->asuIndex[psuIndex->iArrayCurr].llTime < llSeekTime)
iLowerLimit = (iUpperLimit - iLowerLimit) / 2;
else
break;
}
return I106_OK;
}
/* ------------------------------------------------------------------------ */
return szTime;
}
B-63
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/* ------------------------------------------------------------------------ */
// This function fills in the SuTimeRef structure with the "best" relative
// and/or absolute time stamp available from the packet header and intra-packet
// header (if available).
EnI106Status I106_CALL_DECL
vFillInTimeStruct(SuI106Ch10Header * psuHeader,
SuIntraPacketTS * psuIntraPacketTS,
SuTimeRef * psuTimeRef)
{
int iSecHdrTimeFmt;
B-64
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
*)psuIntraPacketTS, &(psuTimeRef->suIrigTime));
psuTimeRef->bAbsTimeValid = bTRUE;
break;
case I106CH10_PFLAGS_TIMEFMT_IEEE1588:
enI106_IEEE15882IrigTime((SuIEEE1588_Time *)psuIntraPacketTS,
&(psuTimeRef->suIrigTime));
psuTimeRef->bAbsTimeValid = bTRUE;
break;
default:
//Current reserved, should we have a default way to decode
break;
} // end switch on intra-packet time format
} // end else absolute time
} // end if intra-packet time stamp exists
return I106_OK;
}
/* ------------------------------------------------------------------------ */
/* Return the equivalent in seconds past 12:00:00 a.m. Jan 1, 1970 GMT
of the Greenwich Mean time and date in the exploded time structure `tm'.
The standard mktime() has the annoying "feature" of assuming that the
time in the tm structure is local time, and that it has to be corrected
for local time zone. In this library time is assumed to be UTC and UTC
only. To make sure no timezone correction is applied this time conversion
routine was lifted from the standard C run time library source. Interestingly
enough, this routine was found in the source for mktime().
This function does always put back normalized values into the `tm' struct,
parameter, including the calculated numbers for `tm->tm_yday',
`tm->tm_wday', and `tm->tm_isdst'.
// Number of leap years from 1970 to `y' (not including `y' itself).
#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
B-65
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
if (days < 0)
do
{
if (--months < 0)
{
--years;
months = 11;
}
days += monthlen(months, years);
} while (days < 0);
else
while (days >= monthlen(months, years))
{
days -= monthlen(months, years);
if (++months >= 12)
{
++years;
months = 0;
}
} // end while
B-66
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
return (uint32_t)-1;
#ifdef __cplusplus
} // end namespace i106
#endif
B-67
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
****************************************************************************/
#ifndef _I106_DATA_STREAMING_H
#define _I106_DATA_STREAMING_H
#ifdef __cplusplus
namespace Irig106 {
extern "C" {
#endif
/*
* Macros and definitions
* ----------------------
*/
/*
* Data structures
* ---------------
*/
#if defined(_MSC_VER)
#pragma pack(push)
#pragma pack(1)
#endif
B-68
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
B-69
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
uint32_t uReserved : 8;
uint32_t uPktStartOffset : 16; ///< Start of Ch 11 packet
uint32_t uUdpSeqNum : 24; ///< UDP sequence number
uint32_t uSrcId : 8; ///< Source identifier
uint8_t achData[1]; ///< Start of Ch 10 data packet
#if !defined(__GNUC__)
} SuUDP_Transfer_Header_F3;
#else
} __attribute__ ((packed)) SuUDP_Transfer_Header_F3;
#endif
#if defined(_MSC_VER)
#pragma pack(pop)
#endif
/*
* Function Declaration
* --------------------
*/
// Open / Close
EnI106Status I106_CALL_DECL
enI106_OpenNetStreamRead(int iHandle,
uint16_t uPort);
EnI106Status I106_CALL_DECL
enI106_OpenNetStreamWrite(int iHandle,
uint32_t uIpAddress,
uint16_t uUdpPort);
EnI106Status I106_CALL_DECL
enI106_CloseNetStream(int iHandle);
// Read
// ----
int I106_CALL_DECL
enI106_ReadNetStream(int iHandle,
void * pvBuffer,
uint32_t uBuffSize);
EnI106Status I106_CALL_DECL
enI106_DumpNetStream(int iHandle);
EnI106Status I106_CALL_DECL
enI106_MoveReadPointer(int iHandle, long iRelOffset);
// Write
// -----
EnI106Status I106_CALL_DECL
enI106_WriteNetStream(
int iHandle,
void * pvBuffer,
uint32_t uBuffSize);
B-70
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
EnI106Status I106_CALL_DECL
enI106_WriteNetNonSegmented(
int iHandle,
void * pvBuffer,
uint32_t uBuffSize);
EnI106Status I106_CALL_DECL
enI106_WriteNetSegmented(
int iHandle,
void * pvBuffer,
uint32_t uBuffSize);
#ifdef __cplusplus
}
}
#endif
#endif
B-71
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
i106_data_stream.c -
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__GNUC__)
#define SOCKET int
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define SOCKADDR struct sockaddr
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#include <assert.h>
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows
headers
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mswsock.h>
#endif
B-72
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
#include "config.h"
#include "stdint.h"
#include "irig106ch10.h"
#include "i106_time.h"
#include "i106_data_stream.h"
#ifdef __cplusplus
namespace Irig106 {
#endif
/*
* Macros and definitions
* ----------------------
*/
/*
* Data structures
* ---------------
*/
/*
* Module data
* -----------
*/
/*
* Function Declaration
* --------------------
B-73
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
*/
/* ----------------------------------------------------------------------- */
// Open / Close
#ifdef MULTICAST
int iInterfaceIdx;
int iNumInterfaces;
#if defined(_MSC_VER)
// Initialize WinSock, request version 2.2
wVersionRequested = MAKEWORD(2, 2);
iResult = WSAStartup(wVersionRequested, &wsaData);
if (iResult != 0)
{
// printf("Unable to initialize Winsock 2.2\n");
return I106_OPEN_ERROR;
}
#endif
B-74
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
#ifdef MULTICAST
// Put the appropriate interface into multicast receive mode
iNumInterfaces = GetInterfaces(NetInterfaces, 10);
LocalInterfaceAddr.s_addr = inet_addr("192.0.0.0");
LocalInterfaceMask.s_addr = inet_addr("255.0.0.0");
IrigMulticastGroup.s_addr = inet_addr("239.0.1.1");
for (iInterfaceIdx = 0; iInterfaceIdx < iNumInterfaces; iInterfaceIdx++)
{
if ((NetInterfaces[iInterfaceIdx].s_addr & LocalInterfaceMask.s_addr) ==
LocalInterfaceAddr.s_addr)
{
join_source_group(m_suNetHandle[iHandle].suIrigSocket, IrigMulticastGroup,
NetInterfaces[iInterfaceIdx]);
break;
}
}
#endif
// Make sure the receive buffer is big enough for at least one UDP packet
m_suNetHandle[iHandle].ulRcvBufferLen = RCV_BUFFER_START_SIZE;
m_suNetHandle[iHandle].pchRcvBuffer = (char *)malloc(RCV_BUFFER_START_SIZE);
m_suNetHandle[iHandle].ulRcvBufferDataLen = 0L;
m_suNetHandle[iHandle].bBufferReady = bFALSE;
m_suNetHandle[iHandle].ulBufferPosIdx = 0L;
m_suNetHandle[iHandle].bGotFirstSegment = bFALSE;
m_suNetHandle[iHandle].enNetMode = I106_READ_NET_STREAM;
return I106_OK;
}
/* ----------------------------------------------------------------------- */
B-75
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
int iMaxMsgSizeLen;
#endif
#if defined(_MSC_VER)
WORD wVersionRequested;
WSADATA wsaData;
DWORD iMaxMsgSize;
#else
socklen_t iMaxMsgSize;
#endif
#if defined(_MSC_VER)
// Initialize WinSock, request version 2.2
wVersionRequested = MAKEWORD(2, 2);
iResult = WSAStartup(wVersionRequested, &wsaData);
if (iResult != 0)
{
// printf("Unable to initialize Winsock 2.2\n");
return I106_OPEN_ERROR;
}
#endif
#ifdef SO_MAX_MSG_SIZE
// getsockopt to retrieve the value of option SO_MAX_MSG_SIZE after a socket has
been created.
iMaxMsgSizeLen = sizeof(iMaxMsgSize);
iResult = getsockopt(m_suNetHandle[iHandle].suIrigSocket, SOL_SOCKET,
SO_MAX_MSG_SIZE, (char *)&iMaxMsgSize, &iMaxMsgSizeLen);
#else
iResult = 1;
#endif
if (iResult == 0)
{
B-76
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
m_suNetHandle[iHandle].enNetMode = I106_WRITE_NET_STREAM;
return I106_OK;
}
/* ----------------------------------------------------------------------- */
EnI106Status I106_CALL_DECL
enI106_CloseNetStream(int iHandle)
{
#ifdef MULTICAST
// Restore the appropriate interface out of multicast receive mode
iNumInterfaces = GetInterfaces(NetInterfaces, 10);
LocalInterfaceAddr.s_addr = inet_addr("192.0.0.0");
LocalInterfaceMask.s_addr = inet_addr("255.0.0.0");
IrigMulticastGroup.s_addr = inet_addr("224.0.0.1");
for (iInterfaceIdx = 0; iInterfaceIdx < iNumInterfaces; iInterfaceIdx++)
{
if ((NetInterfaces[iInterfaceIdx].s_addr & LocalInterfaceMask.s_addr) ==
LocalInterfaceAddr.s_addr)
{
leave_source_group(IrigSocket, IrigMulticastGroup,
NetInterfaces[iInterfaceIdx]);
break;
}
}
#endif
switch (m_suNetHandle[iHandle].enNetMode)
{
case I106_READ_NET_STREAM :
// Close the receive socket
#if defined(_MSC_VER)
closesocket(m_suNetHandle[iHandle].suIrigSocket);
WSACleanup();
#else
close(m_suNetHandle[iHandle].suIrigSocket);
#endif
// Free up allocated memory
free(m_suNetHandle[iHandle].pchRcvBuffer);
m_suNetHandle[iHandle].pchRcvBuffer = NULL;
m_suNetHandle[iHandle].ulRcvBufferLen = 0L;
break;
case I106_WRITE_NET_STREAM :
// Close the transmit socket
#if defined(_MSC_VER)
closesocket(m_suNetHandle[iHandle].suIrigSocket);
WSACleanup();
#else
close(m_suNetHandle[iHandle].suIrigSocket);
#endif
break;
default :
B-77
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
break;
} // end switch on enNetMode
return I106_OK;
}
// ------------------------------------------------------------------------
//! @brief Utility method for cross-platform recvmsg
//! @details Used by enI106_ReadNetStream to split a read across the
//! header buffer and a body buffer.
//! @param suSocket The SOCKET handle to recv from
//! @param[out] pvBuffer1 Pointer to the first buffer to fill
//! @param[in] ulBufLen1 Length of the first buffer, in bytes
//! @param[out] pvBuffer2 Pointer to the second buffer to fill
//! @param[in] ulBufLen2 Length of the second buffer, in bytes
//! @param[out] ulBytesRcvdOut Returns the number of bytes received and copied into
the buffers
//! @return I106_OK On success;
//! ulBytesRcvdOut contains the number of bytes read.
//! @return I106_MORE_DATA On a successful, but truncated, read;
//! ulBytesRcvdOut contains the actual number of bytes read. Some data was
lost.
//! @return I106_READ_ERROR On error;
//! ulBytesRcvdOut is undefined
static EnI106Status
RecvMsgSplit(SOCKET suSocket,
void * const pvBuffer1,
unsigned long ulBufLen1,
void * const pvBuffer2,
unsigned long ulBufLen2,
unsigned long * pulBytesRcvdOut)
#if defined(_MSC_VER)
{
WSABUF asuUdpRcvBuffs[2];
DWORD UdpRcvFlags = 0;
DWORD dwBytesRcvd = 0;
int iResult = 0;
if( 0 == iResult )
return I106_OK;
else
{
int const err = WSAGetLastError();
if( WSAEMSGSIZE == err )
return I106_MORE_DATA;
else
return I106_READ_ERROR;
B-78
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
}
}
#else
{
struct msghdr suMsgHdr = { 0 };
struct iovec asuUdpRcvBuffs[2];
const int UdpRcvFlags = 0;
ssize_t iResult = 0;
asuUdpRcvBuffs[0].iov_len = ulBufLen1;
asuUdpRcvBuffs[0].iov_base = (char *)pvBuffer1;
asuUdpRcvBuffs[1].iov_len = ulBufLen2;
asuUdpRcvBuffs[1].iov_base = (char *)pvBuffer2;
if (iResult < 0)
return I106_READ_ERROR;
else if( MSG_TRUNC == suMsgHdr.msg_flags )
return I106_MORE_DATA;
else
return I106_OK;
}
#endif
// ------------------------------------------------------------------------
//! @brief Utility method for dropping a peek'd bad packet
//! @details If enI106_ReadNetStream MSG_PEEK's a packet that is too small,
//! then we have to remove it from the socket buffer before we can bail.
//! Otherwise, the next MSG_PEEK will see the same bad packet.
static void
DropBadPacket(int iHandle)
{
char dummy;
// We don't care about the return value, we're failing anyways.
(void)recvfrom(m_suNetHandle[iHandle].suIrigSocket, &dummy, sizeof(dummy), 0, 0,
0);
}
// ------------------------------------------------------------------------
// Get the next header.
int I106_CALL_DECL
enI106_ReadNetStream(int iHandle,
void * pvBuffer,
unsigned int iBuffSize)
{
// The minimum packet size needed for a valid segmented message packet
enum { MIN_SEG_LEN = sizeof(SuUDP_Transfer_Header_Seg)-1 +
sizeof(SuI106Ch10Header) };
int iResult;
SuUDP_Transfer_Header_Seg suUdpSeg; // Same prefix unsegmented msg
B-79
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
SuI106Ch10Header * psuHeader;
// If we don't have a buffer ready to read from then read network packets
if (m_suNetHandle[iHandle].bBufferReady == bFALSE)
{
// Get ready for a new buffer of data
m_suNetHandle[iHandle].bBufferReady = bFALSE;
m_suNetHandle[iHandle].bGotFirstSegment = bFALSE;
m_suNetHandle[iHandle].ulBufferPosIdx = 0L;
if( iResult == -1 )
{
enI106_DumpNetStream(iHandle);
return -1;
}
// If I don't have at least enough for a common header then drop and bail
// We'll check length again later, which depends on the msg type
if( iResult < UDP_Transfer_Header_NonSeg_Len )
{
//printf("msg bytes (%d) < transfer header length (%d)\n",
//iResult, UDP_Transfer_Header_NonSeg_Len);
// Because we're peeking, we have to make sure to drop the bad packet.
DropBadPacket(iHandle);
enI106_DumpNetStream(iHandle);
continue;
}
B-80
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
{
case 0 : // Full packet(s)
//printf("Full - ");
iResult = RecvMsgSplit(m_suNetHandle[iHandle].suIrigSocket,
&suUdpSeg,
UDP_Transfer_Header_NonSeg_Len,
m_suNetHandle[iHandle].pchRcvBuffer,
m_suNetHandle[iHandle].ulRcvBufferLen,
&ulBytesRcvd);
if (I106_OK != iResult)
{
enI106_DumpNetStream(iHandle);
if( I106_READ_ERROR == iResult )
return -1;
else
continue;
}
m_suNetHandle[iHandle].ulRcvBufferDataLen = ulBytesRcvd -
UDP_Transfer_Header_NonSeg_Len;
m_suNetHandle[iHandle].bBufferReady = bTRUE;
m_suNetHandle[iHandle].ulBufferPosIdx = 0L;
break;
&(m_suNetHandle[iHandle].pchRcvBuffer[suUdpSeg.uSegmentOffset]),
m_suNetHandle[iHandle].ulRcvBufferLen -
suUdpSeg.uSegmentOffset,
&ulBytesRcvd);
}
B-81
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
if (I106_OK != iResult)
{
enI106_DumpNetStream(iHandle);
if( I106_READ_ERROR == iResult )
return -1;
else
continue;
}
psuHeader = (SuI106Ch10Header
*)m_suNetHandle[iHandle].pchRcvBuffer;
// If it's the first packet then figure out if our buffer is large
enough for the whole Ch10 packet
if (suUdpSeg.uSegmentOffset == 0)
{
if (psuHeader->ulPacketLen >
m_suNetHandle[iHandle].ulRcvBufferLen)
{
m_suNetHandle[iHandle].ulRcvBufferLen = psuHeader-
>ulPacketLen + 0x4000;
m_suNetHandle[iHandle].pchRcvBuffer = (char
*)realloc(m_suNetHandle[iHandle].pchRcvBuffer,m_suNetHandle[iHandle].ulRcvBufferLen);
psuHeader = (SuI106Ch10Header
*)m_suNetHandle[iHandle].pchRcvBuffer;
} // end if buffer too small for whole Ch 10 packet
m_suNetHandle[iHandle].bGotFirstSegment = bTRUE;
m_suNetHandle[iHandle].ulRcvBufferDataLen = psuHeader-
>ulPacketLen;
} // end if first packet
// If we've gotten the first and last packets then mark the buffer
as full and ready
if ((m_suNetHandle[iHandle].bGotFirstSegment == bTRUE) &&
// First UDP buffer
((suUdpSeg.uSegmentOffset + ulBytesRcvd -
UDP_Transfer_Header_Seg_Len) >= psuHeader->ulPacketLen)) // Last UDP buffer
{
//if ((suUdpSeg.uSegmentOffset + ulBytesRcvd - UDP_Transfer_Header_Seg_Len) >
psuHeader->ulPacketLen)
//printf("Last packet too long");
m_suNetHandle[iHandle].bBufferReady = bTRUE;
m_suNetHandle[iHandle].bGotFirstSegment = bFALSE;
m_suNetHandle[iHandle].ulBufferPosIdx = 0L;
} // end if got first and last packet
break;
default :
// The peek'd packet specifies some unknown/junk message type
// Toss this packet so the MSG_PEEK doesn't loop on it endlessly
DropBadPacket(iHandle);
enI106_DumpNetStream(iHandle);
B-82
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
continue;
} // end switch on UDP packet type
} // end while reading for a complete buffer
} // end if called and buffer not ready
return iCopySize;
}
// ------------------------------------------------------------------------
EnI106Status I106_CALL_DECL
enI106_DumpNetStream(int iHandle)
{
m_suNetHandle[iHandle].bBufferReady = bFALSE;
m_suNetHandle[iHandle].bGotFirstSegment = bFALSE;
m_suNetHandle[iHandle].ulBufferPosIdx = 0L;
return I106_OK;
}
// ------------------------------------------------------------------------
EnI106Status I106_CALL_DECL
enI106_MoveReadPointer(int iHandle, long iRelOffset)
{
long lNewPosition;
else
m_suNetHandle[iHandle].ulBufferPosIdx = (unsigned long)lNewPosition;
B-83
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
return I106_OK;
}
// ------------------------------------------------------------------------
EnI106Status I106_CALL_DECL
enI106_WriteNetStream(int iHandle,
void * pvBuffer,
uint32_t uBuffSize)
{
EnI106Status enStatus;
EnI106Status enReturnStatus;
void * pvCurrSendBuffPos;
uint32_t uCurrSendBuffLen;
SuI106Ch10Header * psuCurrCh10Header;
SuI106Ch10Header * psuNextCh10Header;
enReturnStatus = I106_OK;
// Step through IRIG packets until the length would exceed max UDP packet size
while (1==1)
{
// If current packet size > max then send segmented packet
if (psuCurrCh10Header->ulPacketLen > m_suNetHandle[iHandle].uMaxUdpSize)
{
// This big packet had better be the first one in our current send buffer
// assert(pvCurrSendBuffPos == psuCurrCh10Header);
assert(psuCurrCh10Header->uSync == 0xEB25);
B-84
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
break;
}
else
{
uCurrSendBuffLen = psuCurrCh10Header->ulPacketLen;
continue;
}
} // end if big segmented packet
// There is another buffer so let's check its size. If next packet would put
us over
// max size then send what we have
psuNextCh10Header = (SuI106Ch10Header *)((char *)psuCurrCh10Header +
psuCurrCh10Header->ulPacketLen);
// Might want to validate sync word, packet header checksum, and packet
checksum
assert(psuNextCh10Header->uSync == 0xEB25);
B-85
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
return enReturnStatus;
}
// ------------------------------------------------------------------------
EnI106Status I106_CALL_DECL
enI106_WriteNetNonSegmented(
int iHandle,
void * pvBuffer,
uint32_t uBuffSize)
{
EnI106Status enReturnStatus;
#if defined(_MSC_VER)
// SOCKET_ADDRESS suMsSendIpAddress;
WSAMSG suMsMsgInfo;
WSABUF suMsBuffInfo[2];
WSABUF suMsControl;
DWORD lBytesSent;
#endif
int iSendStatus;
SuUDP_Transfer_Header_NonSeg suUdpHeaderNonSeg;
enReturnStatus = I106_OK;
B-86
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
suMsMsgInfo.dwFlags = 0;
return enReturnStatus;
}
// ------------------------------------------------------------------------
EnI106Status I106_CALL_DECL
enI106_WriteNetSegmented(
int iHandle,
void * pvBuffer,
uint32_t uBuffSize)
{
EnI106Status enReturnStatus;
uint32_t uBuffIdx;
char * pchBuffer;
uint32_t uSendSize;
int iSendStatus;
SuI106Ch10Header * psuHeader;
#if defined(_MSC_VER)
WSAMSG suMsMsgInfo;
WSABUF suMsBuffInfo[2];
WSABUF suMsControl;
DWORD lBytesSent;
#endif
SuUDP_Transfer_Header_Seg suUdpHeaderSeg;
enReturnStatus = I106_OK;
memset(&suUdpHeaderSeg, 0, 12);
suUdpHeaderSeg.uVersion = 1;
suUdpHeaderSeg.uMsgType = 1;
suUdpHeaderSeg.uChID = psuHeader->uChID;
suUdpHeaderSeg.uChanSeqNum = psuHeader->ubySeqNum;
B-87
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
#else
// TODO - LINUX CODE
#endif
return enReturnStatus;
}
#ifdef __cplusplus
} // end namespace
#endif
B-88
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
****************************************************************************/
#ifndef _config_h_
#define _config_h_
#ifdef __cplusplus
extern "C" {
#endif
#if defined(_MSC_VER)
#define strcasecmp(s1, s2) _stricmp(s1, s2)
#define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n)
#pragma warning(disable : 4996)
#endif
B-89
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
#define I106_CALL_DECL
#ifdef __cplusplus
}
#endif
#endif
B-90
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/*==========================================================================
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include "config.h"
#include "stdint.h"
#include "irig106ch10.h"
#include "i106_time.h"
#include "i106_decode_time.h"
#include "i106_decode_1553f1.h"
C-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
#include "i106_decode_arinc429.h"
#include "i106_decode_tmats.h"
/*
* Macros and definitions
* ----------------------
*/
#if !defined(bTRUE)
#define bTRUE (1==1)
#define bFALSE (1==0)
#endif
/*
* Data structures
* ---------------
*/
/* These hold the number of messages of each type for the histogram. */
C-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
SuARINC429 * paARINC429;
unsigned long ul16PP194;
unsigned long ulDiscrete;
unsigned long ulParallel;
unsigned long ulMessage;
unsigned long ulImage;
unsigned long ulTSPI;
unsigned long ulCAN;
unsigned long ulFibreChan;
unsigned long ulARINC664;
unsigned long ulOther;
} SuChanInfo;
/*
* Module data
* -----------
*/
int m_bLogRT2RT;
int m_bVerbose;
unsigned char m_aArincLabelMap[0x100];
/*
* Function prototypes
* -------------------
*/
/* ------------------------------------------------------------------------ */
C-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
EnI106Status enStatus;
SuI106Ch10Header suI106Hdr;
Su1553F1_CurrMsg su1553Msg;
SuArinc429F0_CurrMsg suArincMsg;
SuTmatsInfo suTmatsInfo;
SuIrig106Time suIrigTime;
struct tm * psuTmTime;
char szTime[50];
char * szDateTimeFmt = "%m/%d/%Y %H:%M:%S";
char * szDayTimeFmt = "%j:%H:%M:%S";
char * szTimeFmt;
putenv("TZ=GMT0");
tzset();
/*
* Initialize the channel info array pointers to all NULL
*/
memset(apsuChanInfo, 0, sizeof(apsuChanInfo));
ulTotal = 0L;
ulReadErrors = 0L;
ulBadPackets = 0L;
/*
* Process the command line arguements
*/
if (argc < 2)
{
vUsage();
return 1;
}
switch (argv[iArgIdx][0])
{
C-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
default :
break;
} /* end flag switch */
break;
if (strlen(szInFile)==0)
{
vUsage();
return 1;
}
/*
* Opening banner
* --------------
*/
/*
* Opens file and get everything init'ed
* ------------------------------------
*/
C-5
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/*
* Loop until there are no more message whilst keeping track of all the
* various message counts.
* --------------------------------------------------------------------
*/
while (1==1)
{
C-6
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
ulTotal++;
if (m_bVerbose)
fprintf(stderr, "%8.8ld Messages \r",ulTotal);
C-7
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
vProcessTmats(&suTmatsInfo, apsuChanInfo);
}
break;
// If first 1553 message for this channel, setup the 1553 counts
if (apsuChanInfo[suI106Hdr.uChID]->psu1553Info == NULL)
{
apsuChanInfo[suI106Hdr.uChID]->psu1553Info =
malloc(sizeof(SuChanInfo1553));
memset(apsuChanInfo[suI106Hdr.uChID]->psu1553Info, 0x00,
sizeof(SuChanInfo1553));
}
apsuChanInfo[suI106Hdr.uChID]->psu1553Info->ulTotalIrigPackets++;
if (su1553Msg.psu1553Hdr->bRespTimeout != 0)
apsuChanInfo[suI106Hdr.uChID]->psu1553Info-
>ulErr1553Timeout++;
C-8
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
if (m_bLogRT2RT==bTRUE)
{
usPackedIdx = (su1553Msg.psuCmdWord2->uValue >> 5)
& 0x3FFF;
apsuChanInfo[suI106Hdr.uChID]->psu1553Info-
>aulMsgs[usPackedIdx]++;
} // end if logging RT to RT
} // end if RT to RT
break;
break;
C-9
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
default:
apsuChanInfo[suI106Hdr.uChID]->ulOther++;
break;
C-10
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
} /* End while */
/*
* Now print out the results of histogram.
* ---------------------------------------
*/
// vPrintTmats(&suTmatsInfo, psuOutFile);
/*
* Free dynamic memory.
*/
free(pvBuff);
pvBuff = NULL;
fclose(psuOutFile);
return 0;
}
C-11
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/* ------------------------------------------------------------------------ */
if (psuChanInfo->ulTMATS != 0)
fprintf(psuOutFile," TMATS %10lu\n", psuChanInfo->ulTMATS);
if (psuChanInfo->ulEvents != 0)
fprintf(psuOutFile," Events %10lu\n", psuChanInfo->ulEvents);
if (psuChanInfo->ulIndex != 0)
fprintf(psuOutFile," Index %10lu\n", psuChanInfo->ulIndex);
if (psuChanInfo->ulIrigTime != 0)
fprintf(psuOutFile," IRIG Time %10lu\n", psuChanInfo-
>ulIrigTime);
if (psuChanInfo->psu1553Info->bRT2RTFound == bTRUE)
{
fprintf(psuOutFile,"\n Warning - RT to RT transfers found in the
data\n");
if (m_bLogRT2RT == bTRUE)
fprintf(psuOutFile," Message total is NOT the sum of individual RT
totals\n");
else
fprintf(psuOutFile," Some transmit RTs may not be shown\n");
} // end if RT to RT
fprintf(psuOutFile," Totals - %ld Message in %ld good IRIG packets, %ld bad
packets\n",
C-12
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
psuChanInfo->psu1553Info->ulTotalBusMsgs,
psuChanInfo->psu1553Info->ulTotalIrigPackets,
psuChanInfo->psu1553Info->ulTotalIrigPacketErrors);
} // end if 1553 messages
if (psuChanInfo->ulPCM != 0)
fprintf(psuOutFile," PCM %10lu\n", psuChanInfo->ulPCM);
if (psuChanInfo->ulAnalog != 0)
fprintf(psuOutFile," Analog %10lu\n", psuChanInfo->ulAnalog);
if (psuChanInfo->paARINC429 != NULL)
{
unsigned int uBus;
unsigned int uLabel;
for (uBus=0; uBus<0x100; uBus++)
for (uLabel=0; uLabel<0x100; uLabel++)
{
if (psuChanInfo->paARINC429->aulMsgs[uBus][uLabel] != 0)
fprintf(psuOutFile," ARINC 429 Subchan %3u Label %3o Msgs
%10lu\n", uBus, uLabel,
psuChanInfo->paARINC429->aulMsgs[uBus][uLabel]);
}
}
if (psuChanInfo->ulMPEG2 != 0)
fprintf(psuOutFile," Video %10lu\n", psuChanInfo->ulMPEG2);
if (psuChanInfo->ulUART != 0)
fprintf(psuOutFile," UART %10lu\n", psuChanInfo->ulUART);
if (psuChanInfo->ulEthernet != 0)
fprintf(psuOutFile," Ethernet %10lu\n", psuChanInfo-
>ulEthernet);
if (psuChanInfo->ul16PP194 != 0)
fprintf(psuOutFile," 16PP194 %10lu\n", psuChanInfo->ul16PP194);
if (psuChanInfo->ulDiscrete != 0)
fprintf(psuOutFile," Discrete %10lu\n", psuChanInfo-
>ulDiscrete);
if (psuChanInfo->ulParallel != 0)
fprintf(psuOutFile," Parallel %10lu\n", psuChanInfo-
>ulParallel);
if (psuChanInfo->ulMessage != 0)
fprintf(psuOutFile," Message Data %10lu\n", psuChanInfo->ulMessage);
if (psuChanInfo->ulImage != 0)
fprintf(psuOutFile," Image %10lu\n", psuChanInfo->ulImage);
if (psuChanInfo->ulTSPI != 0)
fprintf(psuOutFile," TSPI %10lu\n", psuChanInfo->ulTSPI);
if (psuChanInfo->ulCAN != 0)
fprintf(psuOutFile," CAN Bus %10lu\n", psuChanInfo->ulCAN);
if (psuChanInfo->ulFibreChan != 0)
fprintf(psuOutFile," Fibre Channel %10lu\n", psuChanInfo-
>ulFibreChan);
C-13
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
if (psuChanInfo->ulARINC664 != 0)
fprintf(psuOutFile," ARINC 664 %10lu\n", psuChanInfo-
>ulARINC664);
if (psuChanInfo->ulUserDefined != 0)
fprintf(psuOutFile," User Defined %10lu\n", psuChanInfo-
>ulUserDefined);
if (psuChanInfo->ulOther != 0)
fprintf(psuOutFile," Other messages %10lu\n", psuChanInfo->ulOther);
fprintf(psuOutFile,"\n", psuChanInfo->ulOther);
return;
}
/* ------------------------------------------------------------------------ */
// G record
fprintf(psuOutFile,"Program Name - %s\n",psuTmatsInfo->psuFirstGRecord-
>szProgramName);
fprintf(psuOutFile,"IRIG 106 Rev - %s\n",psuTmatsInfo->psuFirstGRecord-
>szIrig106Rev);
fprintf(psuOutFile,"Channel Type Data Source \n");
fprintf(psuOutFile,"------- ------------ --------------------\n");
// Data sources
psuGDataSource = psuTmatsInfo->psuFirstGRecord->psuFirstGDataSource;
do {
if (psuGDataSource == NULL) break;
// R record info
psuRRecord = psuGDataSource->psuRRecord;
do {
if (psuRRecord == NULL) break;
iRIndex = psuRRecord->iIndex;
C-14
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
psuRRecord = psuRRecord->psuNext;
} while (bTRUE);
psuGDataSource = psuTmatsInfo->psuFirstGRecord->psuFirstGDataSource->psuNext;
} while (bTRUE);
return;
}
/* ------------------------------------------------------------------------ */
return;
}
C-15
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/* ------------------------------------------------------------------------ */
// The ARINC 429 label field is bit reversed. This array maps the ARINC
// label field to its non-reversed bretheren.
/* ------------------------------------------------------------------------ */
void vUsage(void)
{
printf("\nI106STAT "MAJOR_VERSION"."MINOR_VERSION" "__DATE__" "__TIME__"\n");
printf("Print totals by channel and message type from a Ch 10 data file\n");
printf("Freeware Copyright (C) 2006 Irig106.org\n\n");
printf("Usage: i106stat <input file> <output file> [flags]\n");
printf(" <filename> Input/output file names\n");
printf(" -r Log both sides of RT to RT transfers\n");
printf(" -v Verbose\n");
}
C-16
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
idmptmat - Read and dump a TMATS record from an IRIG 106 Ch 10 data file
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include “stdint.h”
#include “irig106ch10.h”
#include “i106_decode_tmats.h”
/*
* Macros and definitions
* ----------------------
D-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
*/
#if !defined(bTRUE)
#define bTRUE (1==1)
#define bFALSE (1==0)
#endif
/*
* Module data
* -----------
*/
/*
* Function prototypes
* -------------------
*/
/* ------------------------------------------------------------------------ */
int iI106Ch10Handle;
EnI106Status enStatus;
SuI106Ch10Header suI106Hdr;
putenv(“TZ=GMT0”);
tzset();
/*
* Process the command line arguements
*/
if (argc < 2) {
vUsage();
return 1;
}
D-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
switch (argv[iArgIdx][0])
{
default :
break;
} // end flag switch
break;
if (strlen(szInFile)==0)
{
vUsage();
return 1;
}
/*
* Opening banner
* --------------
*/
D-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/*
* Open file and get everything init'ed
* ------------------------------------
*/
/*
* Read the TMATS record
*/
if (enStatus != I106_OK)
{
fprintf(stderr, “ Error reading header : Status = %d\n”, enStatus);
return 1;
}
D-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
if (suI106Hdr.ubyDataType != I106CH10_DTYPE_TMATS)
{
fprintf(stderr, “ Error reading data : first message not TMATS”);
return 1;
}
// Generate output
fprintf(ptOutFile, “IDMPTMAT “MAJOR_VERSION”.”MINOR_VERSION”\n”);
fprintf(ptOutFile, “TMATS from file %s\n\n”, szInFile);
if (bRawOutput == bTRUE)
vDumpRaw(&suI106Hdr, pvBuff, ptOutFile);
if (bTreeOutput == bTRUE)
vDumpTree(&suI106Hdr, pvBuff, ptOutFile);
if (bChannelOutput == bTRUE)
vDumpChannel(&suI106Hdr, pvBuff, ptOutFile);
// Done so clean up
free(pvBuff);
pvBuff = NULL;
fclose(ptOutFile);
return 0;
}
/* ------------------------------------------------------------------------ */
return;
}
/* ------------------------------------------------------------------------ */
D-5
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
if (enStatus != I106_OK)
{
fprintf(stderr, “ Error processing TMATS record : Status = %d\n”, enStatus);
return;
}
// G record
fprintf(ptOutFile,
“(G) Program Name - %s\n”,suTmatsInfo.psuFirstGRecord->szProgramName);
fprintf(ptOutFile,
“(G) IRIG 106 Rev - %s\n”,suTmatsInfo.psuFirstGRecord->szIrig106Rev);
// Data sources
psuGDataSource = suTmatsInfo.psuFirstGRecord->psuFirstGDataSource;
do {
if (psuGDataSource == NULL) break;
// R record info
psuRRecord = psuGDataSource->psuRRecord;
do {
if (psuRRecord == NULL) break;
iRIndex = psuRRecord->iRecordNum;
fprintf(ptOutFile, “ (R-%i\\ID) Data Source ID - %s\n”,
iRIndex, psuRRecord->szDataSourceID);
psuRRecord = psuRRecord->psuNextRRecord;
} while (bTRUE);
psuGDataSource =
suTmatsInfo.psuFirstGRecord->psuFirstGDataSource->psuNextGDataSource;
} while (bTRUE);
D-6
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
return;
}
/* ------------------------------------------------------------------------ */
// G record
fprintf(ptOutFile,
“Program Name - %s\n”,suTmatsInfo.psuFirstGRecord->szProgramName);
fprintf(ptOutFile,
“IRIG 106 Rev - %s\n”,suTmatsInfo.psuFirstGRecord->szIrig106Rev);
fprintf(ptOutFile,
“Channel Type Enabled Data Source \n”);
fprintf(ptOutFile,
“------- ------------ -------- --------------------\n”);
// Data sources
psuGDataSource = suTmatsInfo.psuFirstGRecord->psuFirstGDataSource;
do {
if (psuGDataSource == NULL) break;
// R record info
psuRRecord = psuGDataSource->psuRRecord;
do {
if (psuRRecord == NULL) break;
iRIndex = psuRRecord->iRecordNum;
D-7
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
fprintf(ptOutFile, “\n”);
psuRDataSource = psuRDataSource->psuNextRDataSource;
} while (bTRUE);
psuRRecord = psuRRecord->psuNextRRecord;
} while (bTRUE);
psuGDataSource =
suTmatsInfo.psuFirstGRecord->psuFirstGDataSource->psuNextGDataSource;
} while (bTRUE);
return;
}
/* ------------------------------------------------------------------------ */
void vUsage(void)
{
printf(“\nIDMPTMAT - IDMPTMAT “MAJOR_VERSION”.”MINOR_VERSION” “__DATE__”
“__TIME__”\n”);
printf(“Read and output TMATS record from a Ch 10 data file\n”);
printf(“Freeware Copyright (C) 2006 Irig106.org\n\n”);
printf(“Usage: idmptmat <infile> <outfile> <flags>\n”);
printf(“ -c Output channel summary format (default)\n”);
printf(“ -t Output tree view format\n”);
printf(“ -r Output raw TMATS\n”);
return;
}
D-8
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/*==========================================================================
stat.c - Display some basic information about the channels within a Chapter 10
file.
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include “irig106ch10.h”
#include “stat_args.c”
#include “common.h”
typedef struct {
unsigned int type;
int id;
int packets;
E-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
} ChanSpec;
SuI106Ch10Header header;
int packets = 0, input_handle;
float byte_size = 0.0;
static ChanSpec * channels[0x10000];
E-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
channels[i]->packets = 0;
}
return quit(0);
}
E-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
E-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
“““
stat.py - Display some basic information about the channels within a
Chapter 10 file.
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
Options:
-c CHANNEL..., --channel CHANNEL... Specify channels to include(csv).
-e CHANNEL..., --exclude CHANNEL... Specify channels to ignore (csv).
-t TYPE, --type TYPE The types of data to show (csv, may \
be decimal or hex eg: 0x40).”““
F-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
if __name__ == '__main__':
F-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
“““
stat.py - Display some basic information about the channels within a
Chapter 10 file.
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
Options:
-c CHANNEL..., --channel CHANNEL... Specify channels to include(csv).
-e CHANNEL..., --exclude CHANNEL... Specify channels to ignore (csv).
-t TYPE, --type TYPE The types of data to show (csv, may \
be decimal or hex eg: 0x40).”““
G-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
if __name__ == '__main__':
G-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/*==========================================================================
copy.c - Copy all or part of a Chapter 10 file based on data types, channels,
etc.
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include “irig106ch10.h”
#include “copy_args.c”
#include “common.h”
H-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
SuI106Ch10Header header;
void * buffer = malloc(24);
// Copy TMATS
status = enI106Ch10ReadNextHeader(input_handle, &header);
if (status != I106_OK){
printf(“Finished”);
return quit(0);
}
buffer = realloc(buffer, header.ulPacketLen);
status = enI106Ch10ReadDataFile(input_handle, header.ulPacketLen, buffer);
if (status != I106_OK){
printf(“Error reading TMATS.”);
return quit(0);
}
int header_len = 24;
if (header.ubyPacketFlags & (0x1 << 7)){
header_len = 36;
}
fwrite(&header, header_len, 1, output);
fwrite(buffer, header.ulPacketLen - header_len, 1, output);
H-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
continue;
}
header_len = 24;
if (header.ubyPacketFlags & (0x1 << 7)){
header_len = 36;
}
fwrite(&header, header_len, 1, output);
fwrite(buffer, header.ulPacketLen, 1, output);
}
H-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
H-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
“““
copy.py - Copy all or part of a Chapter 10 file based on data types,
channels, etc.
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
Options:
-c CHANNEL..., --channel CHANNEL... Specify channels to include (csv).
-e CHANNEL..., --exclude CHANNEL... Specify channels to ignore (csv).
-t TYPE, --type TYPE The types of data to copy (csv, may\
be decimal or hex eg: 0x40)
-f --force Overwrite existing files.”““
I-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
if __name__ == '__main__':
i += 1
I-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
“““
copy.py - Copy all or part of a Chapter 10 file based on data types,
channels, etc.
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
Options:
-c CHANNEL..., --channel CHANNEL... Specify channels to include (csv).
-e CHANNEL..., --exclude CHANNEL... Specify channels to ignore (csv).
-t TYPE, --type TYPE The types of data to copy (csv, may\
be decimal or hex eg: 0x40)
-f --force Overwrite existing files.”““
import os
J-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
if __name__ == '__main__':
J-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/*==========================================================================
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <intrin.h>
#include “irig106ch10.h”
#include “dump_args.c”
#include “common.h”
// Byteswap a buffer.
void swap(char *p, int len) {
char tmp;
for (int i = 0; i < ((len / 2)); i++) {
tmp = p[i * 2];
p[i * 2] = p[(i * 2) + 1];
p[(i * 2) + 1] = tmp;
K-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
}
}
// Parse loop.
while (1){
K-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
if (out[header.uChID] == NULL){
printf(“Error opening output file: %s”, filename);
return quit(1);
}
}
return quit(0);
}
K-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
K-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
“““
dump.py - Export channel data based on channel ID or data type.
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
Options:
-o OUT, --output OUT The directory to place files \
[default: .].
-c CHANNEL..., --channel CHANNEL... Specify channels to include(csv).
-e CHANNEL..., --exclude CHANNEL... Specify channels to ignore (csv).
-t TYPE, --type TYPE The types of data to export (csv, may\
be decimal or hex eg: 0x40)
-f, --force Overwrite existing files.”““
L-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
if __name__ == '__main__':
args = docopt(__doc__)
out = {}
if PktIO.read_data() != Status.OK:
continue
data = PktIO.Buffer.raw[4:PktIO.Header.PacketLen - 4]
L-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
else:
# Write out raw packet body.
out[filename].write(data)
L-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
L-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
“““
dump.py - Export channel data based on channel ID or data type.
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
Options:
-o OUT, --output OUT The directory to place files \
[default: .].
-c CHANNEL..., --channel CHANNEL... Specify channels to include(csv).
-e CHANNEL..., --exclude CHANNEL... Specify channels to ignore (csv).
-t TYPE, --type TYPE The types of data to export (csv, may\
be decimal or hex eg: 0x40)
-f, --force Overwrite existing files.”““
import atexit
import os
M-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
if __name__ == '__main__':
out = {}
M-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
/*==========================================================================
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include “irig106ch10.h”
#include “reindex_args.c”
#include “common.h”
// Packet header
SuI106Ch10Header index_header;
index_header.uSync = 0xeb25;
N-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
index_header.uChID = 0;
index_header.ulPacketLen = 36 + (18 * packets_c);
index_header.ulDataLen = 12 + (18 * packets_c);
index_header.ubyHdrVer = 0x06;
index_header.ubySeqNum = seq;
index_header.ubyPacketFlags = 0;
index_header.ubyDataType = 0x03;
index_header.uChecksum = 0;
uint64_t sums = 0xeb25 + ((12 + (18 * packets_c)) * 2);
sums += 24 + 6 + seq + 3;
for (int i = 0; i <= 6; i++){
sums += index_header.aubyRefTime[i];
}
sums &= 0xffff;
index_header.uChecksum = (uint16_t)sums;
fwrite(&index_header, 24, 1, output);
// CSDW
int32_t csdw = 0;
csdw &= (1 << 31);
csdw &= (1 << 30);
fwrite(&csdw, 4, 1, output);
// File size
fwrite(&offset, 8, 1, output);
// Packets
for (int i = 0; i <= packets_c; i++){
SuI106Ch10Header packet = packets[i];
// IPTS
fwrite(&index_header.aubyRefTime, 1, 6, output);
// Index entry
int8_t filler = 0;
fwrite(&filler, 1, 1, output);
fwrite(&packet.ubyDataType, 1, 1, output);
fwrite(&packet.uChID, 2, 1, output);
fwrite(&offsets[i], 8, 1, output);
}
}
int increment(seq){
seq++;
if (seq > 0xFF){
seq = 0;
}
return seq;
}
N-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
int packets_c = 0;
SuI106Ch10Header packets_arr[20000];
int64_t offsets[20000];
SuI106Ch10Header last_packet;
int last_packet_at;
int node_seq = 0;
int64_t offset;
int *hdrptr;
int hdrlen;
// Parse loop.
while (1){
enI106Ch10GetPos(input_handle, &offset);
if (header.ubyDataType != 0x03){
hdrptr = &header;
if (header.ubyPacketFlags & (0x1 << 7)){
hdrlen = 36;
}
else {
hdrlen = 24;
}
last_packet = header;
//enI106Ch10GetPos(input_handle, &last_packet_at);
N-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
packets_c++;
packets_arr[packets_c] = header;
offsets[packets_c] = offset - header.ulPacketLen;
}
if (args.strip){
continue;
}
if (args.strip){
printf(“Stripped existing indices.”);
}
}
N-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
“““
reindex.py - Strip and (optionally) rebuild index packets for a Chapter 10
file.
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
Options:
-s, --strip Strip existing index packets and exit.
-f, --force Overwrite existing files.”““
O-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
packet = bytes()
# Header
values = [0xeb25,
0,
24 + 4 + (20 * len(packets)),
4 + (20 * len(packets)),
0x06,
seq,
0,
0x03] + list(packets[-1][0])
# CSDW
csdw = 0x0000
csdw &= 1 << 31
csdw &= 1 << 30
csdw += len(packets)
packet += struct.pack('I', csdw)
# Packets
for p in packets:
ipts = struct.pack('BBBBBB', *p[0])
index = struct.pack('xHHQ', p[1], p[2], p[4])
packet += ipts + index
packet = bytes()
# Header
values = [0xeb25,
0,
24 + 4 + 8 + 8 + (16 * len(packets)),
4 + 8 + 8 + (16 * len(packets)),
0x06,
seq,
0,
0x03] + list(last_packet[0])
O-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
# CSDW
csdw = 0x0000
csdw &= 1 << 30
csdw += len(nodes)
packet += struct.pack('I', csdw)
# Node Packets
for node in nodes:
ipts = struct.pack('BBBBBB', *last_packet[0])
offset = struct.pack('Q', pos - node)
packet += ipts + offset
if last is None:
last = pos
packet += struct.pack('Q', last)
def increment(seq):
“““Increment the sequence number or reset it.”““
seq += 1
if seq > 0xFF:
seq = 0
return seq
if __name__ == '__main__':
args = docopt(__doc__)
O-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
header = buffer(io.Header)[:]
out.write(header)
raw = io.Buffer.raw[:io.Header.PacketLen - len(header)]
out.write(raw)
# Final indices.
if packets:
offset, raw = gen_node(packets)
nodes.append(offset)
out.write(raw)
if nodes:
last_root, raw = gen_root(nodes, last_root, node_seq, last_packet)
out.write(raw)
if args['--strip']:
print 'Stripped existing indices.'
O-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
“““
reindex.py - Strip and (optionally) rebuild index packets for a Chapter 10
file.
* Neither the name Irig106.org nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
Options:
-s, --strip Strip existing index packets and exit.
-f, --force Overwrite existing files.”““
P-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
packet = bytes()
# Header
values = [0xeb25,
0,
24 + 4 + 8 + (20 * len(packets)),
4 + 8 + (20 * len(packets)),
0x06,
seq,
0,
0x03,
packets[-1].rtc_low,
packets[-1].rtc_high]
# CSDW
csdw = 0x0000
csdw &= 1 << 31
csdw &= 1 << 30
csdw += len(packets)
packet += struct.pack('I', csdw)
# Packets
for p in packets:
ipts = struct.pack('HH', p.rtc_low & 0xffff, p.rtc_high & 0xffff)
index = struct.pack('xHHQ', p.channel_id, p.data_type, p.pos)
packet += ipts + index
packet = bytes()
# Header
values = [0xeb25,
0,
24 + 4 + 8 + 8 + (16 * len(packets)),
4 + 8 + 8 + (16 * len(packets)),
0x06,
seq,
0,
0x03,
last_packet.rtc_low,
last_packet.rtc_high]
P-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
# CSDW
csdw = 0x0000
csdw &= 1 << 30
csdw += len(nodes)
packet += struct.pack('I', csdw)
# Node Packets
for node in nodes:
ipts = struct.pack('HH', last_packet.rtc_low & 0xffff,
last_packet.rtc_high & 0xffff)
offset = struct.pack('Q', pos - node)
packet += ipts + offset
if last is None:
last = last_packet.pos + last_packet.packet_length
packet += struct.pack('Q', last)
def increment(seq):
“““Increment the sequence number or reset it.”““
seq += 1
if seq > 0xFF:
seq = 0
return seq
if __name__ == '__main__':
args = docopt(__doc__)
raw = bytes(packet)
if len(raw) == packet.packet_length:
out.write(raw)
P-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
packets.append(packet)
# Final indices.
if packets:
offset, raw = gen_node(packets)
nodes.append(offset)
out.write(raw)
if nodes:
offset, raw = gen_root(nodes, last_root, node_seq, last_packet)
out.write(raw)
if args['--strip']:
print('Stripped existing indices.')
P-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
XML Mapping
Q.1 Introduction
This specification is a reply to the RCC change request CR031.
The intention of this specification is to have a way to define IRIG 106 Chapter 10 files
for testing purposes in a readable XML format. This would allow tools to convert between XML
and Chapter 10 back and forth. The focus of XML is readability and not memory efficiency or
processing efficiency. Therefore the area of application for this specification is the generation of
smaller test files (although nothing technically prevents having large files).
The conversion from XML to Chapter 10 opens these opportunities for example:
Setup of test data for the verification of Chapter 10 analysis software;
Preparation of exactly specified data sets for replay.
The conversion from Chapter 10 to XML opens these opportunities for example:
Chapter 10 files (for example from recorders under development) could be
converted to XML for closer inspection and to verify possible corrections (by
converting the manually corrected XML file back to Chapter 10);
Specific error cases can be created for test cases by converting real files to XML,
injecting the error and converting back for replay.
Q.2 Changes
See the XSD file for a brief change history.
Q.3 Concepts
This specification provides an XML schema that defines many but not all restrictions for
valid files. Having validated XML files is the precondition to any further conversion.
The XML files will basically be a sequence of Chapter 10 packets, each defined within
one XML Packet tag.
Within one Packet tag, optional secondary headers and data type specific content can be
placed.
Q.3.1 Raw data
Many places in the file allow the placement of raw data, for example for the creation of
undefined packet types or to create errors. If anything cannot be defined in a structured way by
the use of XML tags and attributes, it can still be defined by defining the raw data directly.
Q.3.2 Endianness
Chapter 10 files use little endian to encode attributes spanning over several bytes.
Therefore a checksum attribute defined as 0x12345678 shall be stored in the byte order 78 56 34
12. If any of the XML attributes separates the data in groups however, then little endian byte
order shall only be used within each group. For example if some raw data is defined as 16-bit
Q-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
hex words like “1234 5678”, then the data shall be stored in the order 34 12 78 56 because the
values form two groups and little endian only applies within the group 1234 and the group 5678.
Q.3.3 Auto values
Often attributes offer “auto-values”. This means that the user is not providing these
values but the conversion tool is supposed to do this. Often there will be three options:
Automatic calculation by conversion tool
Automatic calculation by conversion tool, modified somehow by users choice
(offset)
Fixed value (user provided content)
An example would be a checksum value, for which following situations could occur
The user omitted the value: The calculation will be automatic
The user provided a relative value like +5 or −12: The result of the automatic
calculation will be modified by +5 or −12 to create an invalid checksum.
The user provided a fixed value: The fixed value will be used
Auto-values require an explicit definition of what they relate to. An auto-value that is
calculating the number of MIL-STD 1553 messages within one packet for example requires
explicit definition of the MIL-STD 1553 messages via XML tags. Definitions via a block of raw
data will not count.
If you use a fixed value somewhere remember you need to update it manually when you
change other data.
Q.3.4 Hexadecimal vs decimal
There are attributes that require the data to be defined in hexadecimal and others that
require decimal data. Most attributes accept both. In this case, hexadecimal data shall be prefixed
by “0x”.
Q.3.5 Flag words
Data structures like flag words (like packet flags or CSDW) will be available to define as
a whole or with its sub elements. In general the definition for the flag word will be used as a base
that is then bitwise modified by the more specific sub elements within the flag word that are
explicitly defined in XML.
Example:
PacketFlags=“0xC4” RTCSyncError=“True”
The packet flags of 0xC4 indicate that secondary headers are present and used as
IEEE1588 intra-packet time. The RTCSyncError additionally sets the bit to indicate an RTC
sync error so the stored flag word becomes 0xE4.
Q.3.6 RTC
Packet RTCs have several options to define which are described in the XSD file. Here are
some examples.
Q-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Q-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Q-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Version 0.3:
- added IRIG 106-2015 version flags
- added CAN Bus definition
Version 0.2:
- renamed all CRC to checksum
- data CRC now requires 0x prefix
- Raw time definition in secondary headers
-->
<xs:element name="ch10">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:choice>
<xs:element name="Packet" type="cns:PacketType"/>
<xs:element name="ChannelDefaults"
type="cns:ChannelDefaultsType"/>
<xs:group ref="cns:RawDataGroup"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
R-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
<xs:attributeGroup ref="cns:dataTypeVersionDefinition"/>
<xs:attributeGroup ref="cns:packetFlagsDefinition"/>
<xs:attributeGroup ref="cns:dataTypeDefinition"/>
<xs:simpleType name="ChecksumType">
<xs:restriction base="xs:string">
<xs:pattern value="[\+\-]?(([0-9]+)|(0x[0-9a-fA-
F]+))"></xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="PacketRTCType">
<xs:annotation>
<xs:documentation>
R-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
<xs:simpleType name="DataTypeType">
<xs:restriction base="xs:string">
<xs:enumeration value="UART Format 0"/>
<xs:enumeration value="1553 Format 1"/>
<xs:enumeration value="ARINC-429 Format 0"/>
<xs:enumeration value="Time Format 1"/>
<xs:enumeration value="TMATS"/>
<xs:enumeration value="CAN Bus"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="DataTypeVersionType">
<xs:restriction base="xs:string">
<xs:enumeration value="106-04"/>
<xs:enumeration value="106-05"/>
<xs:enumeration value="106-07"/>
<xs:enumeration value="106-09"/>
<xs:enumeration value="106-11"/>
<xs:enumeration value="106-13"/>
<xs:enumeration value="106-15"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="SecondaryHeaderTimeFormatType">
<xs:restriction base="xs:string">
<xs:enumeration value="Chapter 4 Binary"/>
<xs:enumeration value="IEEE 1588"/>
<xs:enumeration value="ERTC"/>
<xs:enumeration value="Reserved"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ChecksumTypeType">
<xs:restriction base="xs:string">
<xs:enumeration value="Checksum0"/>
<xs:enumeration value="Checksum8"/>
<xs:enumeration value="Checksum16"/>
<xs:enumeration value="Checksum32"/>
</xs:restriction>
</xs:simpleType>
R-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
<xs:element name="TimeDataRelativeContent"
type="cns:TimeDataRelativeContentType" />
<xs:element name="TimeDataContent"
type="cns:TimeDataContentType" />
<xs:group ref="cns:RawDataGroup" />
</xs:choice>
</xs:sequence>
<xs:attribute name="MonthYearAvailable" type="cns:TrueType" />
<xs:attribute name="LeapYear" type="cns:TrueType" />
<xs:attribute name="TimeFormat" type="cns:TimeDataTimeFormatType" />
<xs:attribute name="TimeSource" type="cns:TimeDataTimeSourceType" />
<xs:attribute name="CSDW" type="cns:U32HexDec" />
</xs:complexType>
<xs:complexType name="TimeDataContentType">
<xs:attribute name="msec" type="xs:unsignedShort" use="optional" />
<xs:attribute name="sec" type="xs:unsignedByte" use="required" />
<xs:attribute name="min" type="xs:unsignedByte" use="required" />
<xs:attribute name="hrs" type="xs:unsignedByte" use="required" />
<xs:attribute name="day" type="xs:unsignedShort" use="required" />
<xs:attribute name="mth" type="xs:unsignedByte" use="optional" />
<xs:attribute name="year" type="xs:unsignedShort" use="optional" />
</xs:complexType>
<xs:complexType name="TimeDataRelativeContentType">
<xs:attribute name="OffsetMs" type="xs:long" use="required">
<xs:annotation>
<xs:documentation>
Offset to last properly defined time packet on same
channel in milliseconds.
This may wrap the year respecting the LeapYear
attribute definition or CSDW flag of the last properly defined time packet
on the same channel. Even if the year is wrapping the
leap year attribute shall not be altered for this packet but use defined state.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:simpleType name="TimeDataTimeFormatType">
<xs:restriction base="xs:string">
<xs:enumeration value="IRIG B" />
<xs:enumeration value="IRIG A" />
<xs:enumeration value="IRIG G" />
<xs:enumeration value="Internal" />
<xs:enumeration value="UTC Time From GPS" />
<xs:enumeration value="Native GPS Time" />
<xs:enumeration value="None" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TimeDataTimeSourceType">
<xs:restriction base="xs:string">
<xs:enumeration value="Internal" />
<xs:enumeration value="External" />
<xs:enumeration value="Internal From RMM" />
<xs:enumeration value="None" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="ChannelDefaultsType">
<xs:attribute name="ChannelID" type="cns:U16HexDec" use="required"/>
<xs:attributeGroup ref="cns:packetFlagsDefinition"/>
R-4
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
<xs:attributeGroup ref="cns:dataTypeDefinition"/>
<xs:attributeGroup ref="cns:dataTypeVersionDefinition"/>
</xs:complexType>
<xs:simpleType name="TMATSDataCh10VersionType">
<xs:restriction base="xs:string">
<xs:enumeration value="106-07" />
<xs:enumeration value="106-09" />
<xs:enumeration value="106-11" />
<xs:enumeration value="106-13" />
<xs:enumeration value="106-15" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="CANBusMessageType">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:group ref="cns:RawDataGroup" />
</xs:sequence>
R-5
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:complexType name="Mil1553MessageType">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:group ref="cns:RawDataGroup" />
</xs:sequence>
R-6
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
<xs:simpleType name="Mil1553TimeTagBitsType">
<xs:restriction base="xs:string">
<xs:enumeration value="Last Bit Of Last Word" />
<xs:enumeration value="First Bit Of First Word" />
<xs:enumeration value="Last Bit Of First Command" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="ARINC429MessageType">
<xs:attribute name="IPDH" type="cns:U32HexDec" />
<xs:attribute name="Subchannel" type="cns:U8HexDec" />
<xs:attribute name="FormatError" type="cns:TrueType" />
<xs:attribute name="ParityError" type="cns:TrueType" />
<xs:attribute name="HighSpeed" type="cns:TrueType" />
<xs:attribute name="GapTime" type="xs:unsignedInt" />
<xs:attribute name="Raw32" type="cns:U32HexDec">
<xs:annotation>
<xs:documentation>The raw bits including the parity.
If the Raw31 attribute is given, Raw32 shall be
ignored.
The state of the ParityError flag is not influenced.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Raw31" type="cns:U32HexDec">
<xs:annotation>
<xs:documentation>The raw bits excluding the parity.
The parity bit for the raw bits is generated
automatically to be correct unless the GenerateWrongParity attribute is set in which
case the parity bit is generated incorrect.
If the Raw31 attribute is given, Raw32 shall be
ignored.
The state of the ParityError flag is not influenced.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateWrongParity" type="cns:TrueType">
<xs:annotation>
R-7
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
<xs:complexType name="UARTMessageType">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:group ref="cns:RawDataGroup" />
</xs:sequence>
R-8
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
</xs:choice>
</xs:group>
<xs:attributeGroup name="dataTypeDefinition">
<xs:attribute name="DataTypeRaw" type="cns:U8HexDec"/>
<xs:attribute name="DataType" type="cns:DataTypeType">
<xs:annotation><xs:documentation>This takes precedence over
data_type_raw.</xs:documentation></xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:attributeGroup name="dataTypeVersionDefinition">
<xs:attribute name="DataTypeVersionRaw" type="cns:U8HexDec"/>
<xs:attribute name="DataTypeVersion" type="cns:DataTypeVersionType">
<xs:annotation><xs:documentation>This takes precedence over
data_type_version_raw.</xs:documentation></xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:attributeGroup name="packetFlagsDefinition">
<xs:attribute name="PacketFlags" type="cns:U8HexDec"/>
<xs:attribute name="SecondaryHeaderPresent" type="cns:TrueType"/>
<xs:attribute name="SecondaryHeaderTimeForIntraPacketTime"
type="cns:TrueType"/>
<xs:attribute name="RTCSyncError" type="cns:TrueType"/>
<xs:attribute name="DataOverflow" type="cns:TrueType"/>
<xs:attribute name="SecondaryHeaderTimeFormat"
type="cns:SecondaryHeaderTimeFormatType"/>
<xs:attribute name="ChecksumType" type="cns:ChecksumTypeType"/>
</xs:attributeGroup>
<xs:attributeGroup name="secondaryHeaderTimeDefinition">
<xs:attribute name="nsec" type="xs:unsignedShort" use="optional" />
<xs:attribute name="usec" type="xs:unsignedShort" use="optional" />
<xs:attribute name="msec" type="xs:unsignedShort" use="optional" />
<xs:attribute name="sec" type="xs:unsignedByte" use="optional" />
<xs:attribute name="min" type="xs:unsignedByte" use="optional" />
<xs:attribute name="hrs" type="xs:unsignedByte" use="optional" />
<xs:attribute name="day" type="xs:unsignedByte" use="optional" />
<xs:attribute name="mth" type="xs:unsignedByte" use="optional">
<xs:annotation>
<xs:documentation>If this attribute is used and no ERTC or
RawTime, a IEEE-1588 time is created</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="year" type="xs:unsignedShort" use="optional">
<xs:annotation>
<xs:documentation>If this attribute is used and no ERTC or
RawTime, a IEEE-1588 time is created</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ERTC" type="xs:unsignedLong">
<xs:annotation>
<xs:documentation>If this attribute is used it takes
precedence over
date/time but not RawTime. Any signed numbers
(including positive sign) will be
relative to the packet RTC (after extending the
packet RTC to 1ns
units). Numbers without sign are treated absolute
</xs:documentation>
R-9
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
</xs:annotation>
</xs:attribute>
<xs:attribute name="RawTime" type="cns:U64Hex">
<xs:annotation>
<xs:documentation>If this attribute is used it takes
precedence over
date/time and ERTC. It will place the defined
hexadecimal value into the 8 time bytes (little endian)
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:simpleType name="ASCIIStringType">
<xs:annotation>
<xs:documentation>
This represents a 7-Bit ASCII encoded string
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="\p{IsBasicLatin}*"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="HexBytesType">
<xs:annotation>
<xs:documentation>
This type represents a sequence of 8 bit hexadecimal values
separated by spaces. The values are stored in this sequence in the CH10 file. The
sequence may be empty.
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="([a-fA-F0-9]{2}( [a-fA-F0-
9]{2})*)|"></xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="HexWordsType">
<xs:annotation>
<xs:documentation>
This type represents a sequence of 16 bit hexadecimal
values separated by spaces. The values are stored in this sequence in the CH10 file.
When storing to the little endian CH10 file each value will be byte reversed. The
sequence may be empty.
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="([a-fA-F0-9]{4}( [a-fA-F0-
9]{4})*)|"></xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="HexLongWordsType">
<xs:annotation>
<xs:documentation>
This type represents a sequence of 32 bit hexadecimal
values separated by spaces. The values are stored in this sequence in the CH10 file.
When storing to the little endian CH10 file each value will be byte reversed. The
sequence may be empty.
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="([a-fA-F0-9]{8}( [a-fA-F0-
9]{8})*)|"></xs:pattern>
R-10
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TrueType">
<xs:annotation>
<xs:documentation>
This type is used for attributes that just have two states.
The false-state is indicated by omitting the attribute at all.
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:enumeration value="True"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="NoneType">
<xs:restriction base="xs:string">
<xs:enumeration value="None"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="RelativeU8HexDec">
<xs:annotation>
<xs:documentation>
This type represents a 8 bit unsigned integer that is
interpreted hexadecimal if the number is prefixed with 0x and decimal otherwise. The
first character is an optional + or - to indicate that the number shall be interpreted
relative to something (likely a calculated auto value).
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="[\+\-]?(([0-9]{1,3})|(0x[a-fA-F0-
9]{1,2}))"></xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="RelativeU16HexDec">
<xs:annotation>
<xs:documentation>
This type represents a 16 bit unsigned integer that is
interpreted hexadecimal if the number is prefixed with 0x and decimal otherwise. The
first character is an optional + or - to indicate that the number shall be interpreted
relative to something (likely a calculated auto value).
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="[\+\-]?(([0-9]{1,5})|(0x[a-fA-F0-
9]{1,4}))"></xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="RelativeU24HexDec">
<xs:annotation>
<xs:documentation>
This type represents a 24 bit unsigned integer that is
interpreted hexadecimal if the number is prefixed with 0x and decimal otherwise. The
first character is an optional + or - to indicate that the number shall be interpreted
relative to something (likely a calculated auto value).
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
R-11
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
<xs:pattern value="[\+\-]?(([0-9]{1,8})|(0x[a-fA-F0-
9]{1,6}))"></xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="RelativeU32HexDec">
<xs:annotation>
<xs:documentation>
This type represents a 32 bit unsigned integer that is
interpreted hexadecimal if the number is prefixed with 0x and decimal otherwise. The
first character is an optional + or - to indicate that the number shall be interpreted
relative to something (likely a calculated auto value).
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="[\+\-]?(([0-9]{1,10})|(0x[a-fA-F0-
9]{1,8}))"></xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="RelativeU64HexDec">
<xs:annotation>
<xs:documentation>
This type represents a 64 bit unsigned integer that is
interpreted hexadecimal if the number is prefixed with 0x and decimal otherwise. The
first character is an optional + or - to indicate that the number shall be interpreted
relative to something (likely a calculated auto value).
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="[\+\-]?(([0-9]{1,20})|(0x[a-fA-F0-
9]{1,16}))"></xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="U8HexDec">
<xs:annotation>
<xs:documentation>
This type represents a 8 bit unsigned integer that is
interpreted hexadecimal if it is prefixed with 0x and decimal otherwise.
</xs:documentation>
</xs:annotation>
<xs:union memberTypes="xs:unsignedByte cns:U8Hex" />
</xs:simpleType>
<xs:simpleType name="U8Hex">
<xs:restriction base="xs:string">
<xs:pattern value="0x[a-fA-F0-9]{1,2}"></xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="U16HexDec">
<xs:annotation>
<xs:documentation>
This type represents a 16 bit unsigned integer that is
interpreted hexadecimal if it is prefixed with 0x and decimal otherwise.
</xs:documentation>
</xs:annotation>
<xs:union memberTypes="xs:unsignedShort cns:U16Hex" />
</xs:simpleType>
<xs:simpleType name="U16Hex">
<xs:restriction base="xs:string">
R-12
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
<xs:pattern value="0x[a-fA-F0-9]{1,4}"></xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="U32HexDec">
<xs:annotation>
<xs:documentation>
This type represents a 32 bit unsigned integer that is
interpreted hexadecimal if it is prefixed with 0x and decimal otherwise.
</xs:documentation>
</xs:annotation>
<xs:union memberTypes="xs:unsignedInt cns:U32Hex" />
</xs:simpleType>
<xs:simpleType name="U32Hex">
<xs:restriction base="xs:string">
<xs:pattern value="0x[a-fA-F0-9]{1,8}"></xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="U64HexDec">
<xs:annotation>
<xs:documentation>
This type represents a 64 bit unsigned integer that is
interpreted hexadecimal if it is prefixed with 0x and decimal otherwise.
</xs:documentation>
</xs:annotation>
<xs:union memberTypes="xs:unsignedLong cns:U64Hex" />
</xs:simpleType>
<xs:simpleType name="U64Hex">
<xs:restriction base="xs:string">
<xs:pattern value="0x[a-fA-F0-9]{1,16}"></xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="U32HexDecNone">
<xs:annotation>
<xs:documentation>
This type allows the definitions like in U32HexDec but adds
the additional state "None" that is used to completely leave the 32 bits out
</xs:documentation>
</xs:annotation>
<xs:union memberTypes="cns:NoneType cns:U32HexDec" />
</xs:simpleType>
</xs:schema>
R-13
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
R-14
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Citations
Aeronautical Radio, Inc. Mark 33 Digital Information Transfer System (DITS). ARINC 429.
Annapolis: ARINC, 1995.
European Air Group. “European Air Group Interface Control Document for Post Mission
Interoperability.” DF29125 Draft A Issue 01. July 2004. Retrieved 13 August 2019.
Available to RCC members with Private Portal access at
https://www.trmc.osd.mil/wiki/download/attachments/114820287/DF29125.pdf
Institute of Electrical and Electronics Engineers. IEEE Standard for a High-Performance Serial
Bus. IEEE 1394-2008. New York: Institute of Electrical and Electronics Engineers, 2008.
———. Information Technology – Generic Coding of Moving Pictures and Associated Audio
Information: Systems. ISO/IEC 13818-1:2019. June 2019. Retrieved 13 August 2019.
Available for purchase at https://www.iso.org/standard/75928.html.
———. Information technology -- JPEG 2000 image coding system: motion JPEG 2000.
ISO/IEC 15444-3:2007. Geneva: International Organization for Standardization, 2007.
———. Information Technology – Small Computer System Interface (SCSI) Part 322: SCSI
Block Commands-2 (SBC-2). ISO/IEC 14776-322:2007. February 2007. Retrieved 12
August 2019. Available for purchase at https://www.iso.org/standard/42101.html..
———. Information Technology – Small Computer System Interface (SCSI) Part 412:
Architecture Model-2 (SAM-2). ISO/IEC 14776-412. October 2006. Retrieved 12 August
2019. Available for purchase at https://www.iso.org/standard/39517.html.
———. Information Technology – Small Computer System Interface (SCSI) Part 452: SCSI
Primary Commands-2 (SPC-2). ISO/IEC 14776-452:2005. August 2005. Retrieved 12
August 2019. Available for purchase at https://www.iso.org/standard/38775.html.
Internet Engineering Task Force. “Administratively Scoped IP Multicast.” RFC 2365. July 1998.
May be superseded by update. Retrieved 13 August 2019. Available at
https://datatracker.ietf.org/doc/rfc2365/.
S-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
———. “IANA Guidelines for IPv4 Multicast Address Assignments.” RFC 3171. August 2001.
Obsoleted by RFC 5771. Retrieved 13 August 2019. Available at
https://datatracker.ietf.org/doc/rfc3171/.
———. “Internet Storage Name Service (iSNS).” RFC 4171. September 2005. May be
superseded by update. Retrieved 12 August 2019. Available at
https://datatracker.ietf.org/doc/rfc4171/
———. “Service Location Protocol, Version 2.” RFC 2608. June 1999. Updated by RFC 3224.
Retrieved 12 August 2019. Available at http://datatracker.ietf.org/doc/rfc2608/.
———. “Telnet Linemode Option.” RFC 1184. March 2013. May be superseded by update.
Retrieved 26 June 2019. Available at http://datatracker.ietf.org/doc/rfc1184/.
———. “Telnet Option Specifications.” RFC 855. May 1983. May be superseded by update.
Retrieved 26 June 2019. Available at http://datatracker.ietf.org/doc/rfc855/.
———. “Telnet Protocol Specification.” RFC 854. May 1983. Updated by RFC 5198. Retrieved
26 June 2019. Available at http://datatracker.ietf.org/doc/rfc854/.
Lockheed Martin Corporation. “Advanced Weapons Multiplex Data Bus.” 8 June 2010. May be
superseded by update. Retrieved 3 June 2015. Available to RCC members with Private
Portal access at
https://www.trmc.osd.mil/wiki/download/attachments/114820295/16PP362B.pdf.
National Marine Electronics Association. “NMEA 0183 Interface Standard.” V 4.11. November
2018. May be superseded by update. Retrieved 13 August 2019. Available for purchase at
https://www.nmea.org/content/STANDARDS/NMEA_0183_Standard.
———. “NMEA 0183-HS Interface Standard.” V 1.01. n.d. May be superseded by update.
Retrieved 10 August 2016. Available for purchase at
https://www.nmea.org/content/STANDARDS/NMEA_0183_Standard.
———. “Standard for Serial-Data Networking of Marine Electronic Devices.” Edition 3.101.
March 2016. May be superseded by update. Retrieved 13 August 2019. Available for
purchase at https://www.nmea.org/content/STANDARDS/NMEA_2000.
Radio Technical Commission for Maritime Services. “Standard for Networked Transport of
RTCM via Internet Protocol (Ntrip).” RTCM 10410.1. Version 2.0 Amendment 1. June
2011. May be superseded by update. Retrieved 13 August 2019. Available for purchase at
http://www.rtcm.org/differential-global-navigation-satellite--dgnss--standards.html.
Range Commanders Council. “Digital Data Bus Acquisition Formatting Standard” in Telemetry
Standards. IRIG 106-20 Chapter 8. July 2020. May be superseded by update. Retrieved
S-2
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
———. “Digital Recording Standard” in Telemetry Standards. IRIG 106-20 Chapter 10. July
2020. May be superseded by update. Retrieved 11 August 2020. Available at
https://www.trmc.osd.mil/wiki/download/attachments/83068101/chapter10.pdf.
———. “Pulse Code Modulation Standards” in Telemetry Standards. IRIG 106-20 Chapter 4.
July 2020. May be superseded by update. Retrieved 11 August 2020. Available at
https://www.trmc.osd.mil/wiki/download/attachments/83068101/chapter4.pdf.
———. “Recorder & Reproducer Command and Control” in Telemetry Standards. IRIG 106-20
Chapter 6. July 2020. May be superseded by update. Retrieved 11 August 2020.
Available at
https://www.trmc.osd.mil/wiki/download/attachments/83068101/chapter6.pdf.
———. Telemetry Applications Handbook. RCC 119-06. May 2006. May be superseded by
update. Retrieved 12 August 2019. Available at
https://www.trmc.osd.mil/wiki/download/attachments/91391305/119-06.pdf.
———. “Telemetry Attributes Transfer Standard” in Telemetry Standards. IRIG 106-20 Chapter
9. July 2020. May be superseded by update. Retrieved 11 August 2020. Available at
https://www.trmc.osd.mil/wiki/download/attachments/83068101/Chapter9.pdf.
———. Telemetry Standards. IRIG 106-20. July 2020. May be superseded by update. Retrieved
11 August 2020. Available at
https://www.trmc.osd.mil/wiki/download/attachments/83068101/106-
20_Telemetry_Standards.pdf.
Range Instrumentation System Program Office, Air Armament Center. “Interface Specification
for the USAF Air Combat Test and Training System (ACTTS) Air-to-Ground, Air-to-
Air, Ground-to-Air Data Links, and AIS Recording Formats.” WMSP 98-01, Rev A, Chg
1. 19 May 2003. Retrieved 3 June 2015. Available to RCC members with Private Portal
access at
https://wsdmext.wsmr.army.mil/site/rccpri/Limited_Distribution_References/WMSP_98-
01.doc.
S-3
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
References
Department of Defense. “Digital Time Division Command/Response Multiplex Data Bus.” MIL-
STD-1553C. 28 February 2018. May be superseded by update. Retrieved 13 August
2019. Available at https://quicksearch.dla.mil/qsDocDetails.aspx?ident_number=36973.
———. “National Imagery Transmission Format Version 2.1 for the National Imagery
Transmission Format Standard.” MIL-STD-2500C Change 2. 2 January 2019. May be
superseded by update. Retrieved 13 August 2019. Available at
https://quicksearch.dla.mil/qsDocDetails.aspx?ident_number=112606.
Institute of Electrical and Electronics Engineers. IEEE Standard for Ethernet – Amendment 2:
Media Access Control Parameters, Physical Layers, and Management Parameters for
25Gb/s Operation. IEEE 802.3by-2016. September 2016. May be superseded by update.
Retrieved 13 August 2019. Available for purchase at
https://standards.ieee.org/findstds/standard/802.3by-2016.html.
———. Information technology -- Generic coding of moving pictures and associated audio
information -- Part 2: Video. ISO/IEC 13818:2-2013. October 2013. Retrieved 13 August
2019. Available for purchase at https://www.iso.org/standard/61152.html.
———. Information technology -- Generic coding of moving pictures and associated audio
information -- Part 3: Audio. ISO/IEC 13818:3-1998. April 1998. Retrieved 13 August
2019. Available for purchase at https://www.iso.org/standard/26797.html.
———. Information technology -- Small Computer System Interface (SCSI) -- Part 222: Fibre
Channel Protocol for SCSI, Second Version (FCP-2). ISO/IEC 14776-222:2005.
February 2005. Retrieved 13 August 2019. Available for purchase at
https://www.iso.org/standard/38379.html.
———. Information technology -- Small Computer System Interface (SCSI) -- Part 232: Serial
Bus Protocol-2 (SBP-2). ISO/IEC 14776:232:2001. November 2001. Retrieved 13
August 2019. Available for purchase at https://www.iso.org/standard/32329.html.
T-1
IRIG 106 Chapter 10 Programmers’ Handbook RCC 123-20 August 2020
Microsoft. Plug and Play Design Specification for IEEE 1394. Version 1.0b. October 1997. May
be superseded by update. Retrieved 13 August 2019. Available at
http://www.osdever.net/documents/PNP-Firewire-v1.0b.pdf.
Motion Imagery Standards Board. Motion Imagery Standards Profile. MISP-2016-2. February
2016. May be superseded by update. Retrieved 9 August 2016. Available at
http://www.gwg.nga.mil/misb/docs/misp/MISP-2016.2.pdf.
North Atlantic Treaty Organization. NATO Advanced Data Storage Interface Requirements and
Implementation Guide. AEDB-6 Ed. B V. 1. December 2014. May be superseded by
update. Retrieved 13 August 2019. Available at
https://nso.nato.int/nso/zPublic/ap/PROM/AEDP-06%20EDB%20V3%20E.pdf.
———. NATO Secondary Imagery Format (NSIF). AEDP-04 Ed. 2. V. 1. May 2013. May be
superseded by update. Retrieved 13 August 2019. Available at
https://nso.nato.int/nso/zPublic/ap/aedp-4(2).pdf.
Range Commanders Council. Test Methods For Telemetry Systems And Subsystems Volume 1 –
Test Methods for Vehicle Telemetry Systems. 118-12 V. 1. May 2012. May be superseded
by update. Retrieved 13 August 2019. Available at
https://www.trmc.osd.mil/wiki/download/attachments/91391275/118-
20_V1_Vehicle_TM_Systems.pdf.
* * * END OF STANDARD * * *
T-2