You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by ji...@apache.org on 2021/03/30 15:15:22 UTC

[daffodil] 06/09: Support choices in runtime2 code generator with restrictions

This is an automated email from the ASF dual-hosted git repository.

jinterrante pushed a commit to branch runtime2-2202
in repository https://gitbox.apache.org/repos/asf/daffodil.git

commit 80a95702696fe3bfcdc8f1e79592e988f5687830
Author: John Interrante <in...@research.ge.com>
AuthorDate: Wed Jan 27 16:56:07 2021 -0500

    Support choices in runtime2 code generator with restrictions
    
    Extend daffodil-runtime2's C code generator to support choices in DFDL
    schemas with restrictions (no anonymous/multiple choice groups, no
    backtracking or discrimination).  Refactoring the DPath expression
    compiler to generate C code will allow more choice dispatch key
    expressions to be supported later.  Refining the choice runtime
    structure and detecting anonymous choice groups will allow multiple
    choice groups to be inlined into parent elements later.
    
    An infoset element must have an xs:choice complex type defining a
    choice group.  The choice group must have a dfdl:choiceDispatchKey
    expression pointing to a preceding infoset element which must store an
    integral value.  Each alternative element in the choice group must
    have a dfdl:choiceBranchKey attribute containing only integer
    literals.  The C code generator makes some assumptions to simplify
    converting the choice dispatch expression to C code accessing a
    preceding infoset element:
    
     - the expression starts with '{xs:string( and ends with )}'
     - the expression returns the value of a previous element without
       changing the value in any way (except converting it to xs:string)
     - both the expression and the C code use only local names (for now...)
     - we can map the context node's path to a Unix-like slash path
     - all dpath operations look like Unix-like relative paths (../tag)
     - we can normalize the new path and convert it to C struct dot notation
     - we can store the dispatch value in an int64_t local variable safely
    
    Secondly, add/move some DFDL schemas contributed by collaborators
    along with their test cases and data files from daffodil-runtime2 to
    daffodil-test as requested by review.  Move runtime2's TDML support
    from daffodil-runtime2 to daffodil-tdml-processor and make changes to
    build.sbt and some tests to keep everything working.
    
    Thirdly, fix a test failure triggered by two threads calling
    CodeGenerator at the same time.
    
    Changelog:
    
    In build.sbt, don't make runtime2 depend on tdmlProc, instead make
    tdmlProc depend on runtime2 and test depend on runtime2's test classes
    so we can move some DFDL schemas and tests from runtime2 to test.
    Trim unnecessary C compile flags (note we don't use the .o files built
    by sbt-cc, we only want C compilation error/warning messages).
    
    In TestCLIGenerateC.scala, update path to TDML file that was renamed
    from TestRuntime2.dfdl.xsd to ex_nums.dfdl.xsd.
    
    In c/Makefile, put *.h files in HEADERS (not SOURCES) and trim
    -Wno-missing-field-initializers from CFLAGS since we've fixed all
    these warnings in the C code now.
    
    In daffodil_argp.c, fix warnings about missing field initializers.
    
    In daffodil_main.c, fix warnings about missing field initializers.
    
    In infoset.c, store offsets as size_t instead of ptrdiff_t since
    they're always positive numbers (can also store very large offsets
    without sign bit overflow).  Handle _choice member field with CHOICE
    typeCode appropriately (i.e., call ERD member function initChoice)
    when walking infoset with visitor methods.
    
    In infoset.h, add InitChoiceRD / initChoice to ERD member types /
    functions and CHOICE to TypeCode enumerations.  Store offsets as
    size_t instead of ptrdiff_t since they're always positive numbers.
    Define static constant NO_CHOICE as test to determine when _choice
    fields are uninitialized.
    
    In parsers.c/unparsers.c, reorder macro definitions slightly.
    
    Add NestedUnion.[ch] to show how C code can support choice complex
    types.  C code was generated from nested.dfdl.xsd schema using
    NestedUnion as the root element.
    
    In ex_nums.[ch], replace old generated code with new generated code.
    
    In CodeGenerator.scala, put a synchronized block around some
    FileSystem code to avoid calling FileSystems.newFileSystem
    concurrently when running TDML tests using runtime2.  Add scaladoc
    comments and remove -lpthread since we don't need to link C executable
    with it.
    
    In Runtime2CodeGenerator.scala, add braces to generateCode method.
    Note that I tried to detect choice groups when walking grammar objects
    in generateCode method but found out it was very difficult to detect
    them in that place while it was easier to detect them in
    ElementParseAndUnspecifiedLengthCodeGenerator.scala instead.
    
    In CodeGeneratorState.scala, rename qualifiedName function to erdName
    and improve it to qualify erdName with global complex type's name and
    append _ERD before returning erdName.  Update calls in rest of file
    accordingly.  Make addImplementation method generate new ERD member
    function initChoice.  Add choiceDispatchField function to convert a
    choiceDispatchKey expression into C struct dot notation for accessing
    the choiceDispatchKey expression's runtime value.  We'll need to
    refactor the DPath expression compiler to generate C code instead of
    using the choiceDispatchField function to handle more use cases later.
    Add new methods addBeforeSwitchStatements and addAfterSwitchStatements
    to generate declarations, ERD definitions, offset computations, ERD
    computations, init statements, initChoice statements, parse
    statements, and unparse statements needed to handle choices with
    several alternative branches.  Make addComplexTypeERD method include
    correct count and initChoice member function in ERDs containing
    alternative branches.  Make addComplexTypeStatements method generate C
    code (switch statement cases) for initChoice, parse, and unparse
    functions of complex types with alternative branches.  Make minor
    changes to addFieldDeclaration, generateCodeFile and
    generateCodeHeader methods to improve the generated C code.
    
    In ElementParseAndUnspecifiedLengthCodeGenerator.scala, call
    cgState.addBeforeSwitchStatements and cgState.addAfterSwitchStatements
    in right places to generate C code for elements having xs:choice
    complex types.
    
    Rename TestRuntime2.dfdl.xsd to ex_nums.dfdl.xsd.
    
    Rename TestRuntime2.tdml to ex_nums.tdml.  Update references to model
    ex_nums.dfdl.xsd and file ex_nums_unparse_runtime[12].xml.  Change
    defaultRoundTrip to "none" since every parse test is accompanied by an
    unparse test, making the extra work done by "onePass" redundant.
    Maybe we should keep defaultRoundTrip="onePass" and delete all the
    unparse tests, but it's nice to have debuggable entry points for both
    parse and unparse tests.
    
    Rename ex_nums_unparse1.xml to ex_nums_unparse_runtime1.xml to make it
    clearer the files are a pair of alternative infoset files for runtime1
    and runtime2, not a pair of alternative files for a choice group.
    
    Rename ex_nums_unparse2.xml to ex_nums_unparse_runtime2.xml.
    
    Add nested.dfdl.xsd with NestedUnion as a small example of a choice
    group using dfdl:choiceDispatchKey and dfdl:choiceBranchKey for
    development and testing.  Add nested.tdml with corresponding binary
    data files and unparse XML files to test NestedUnion in nested schema.
    
    In TDMLRunner.scala, update hardcoded class reference to
    org.apache.daffodil.tdml.processor.Runtime2TDMLDFDLProcessorFactory.
    
    Move Runtime2TDMLDFDLProcessor.scala from daffodil-runtime2 to
    daffodil-tdml-processor and put it in the same directory as
    DaffodilTDMLDFDLProcessor.scala.  Update the package and change the
    first class's name from TDMLDFDLProcessorFactory to
    Runtime2TDMLDFDLProcessorFactory.  Update all references to the new
    name of Runtime2TDMLDFDLProcessorFactory.  Remove [[...]] around
    Runtime2DataProcessor in a scaladoc comment since scaladoc can't find
    Runtime2DataProcessor after the move.
    
    Add or move the following DFDL schemas, test cases, and data files
    from daffodil-runtime2 to daffodil-test.  Note all of the Scala
    classes had to be put in daffodil-runtime2 because it is no longer
    possible for daffodil-runtime2 to run TDML tests itself due to the
    changes in build.sbt:
    
     - camera_state*
     - command*
     - egress_xdcc_bw*
     - ingress_xdcc_bw*
     - orion-command*
     - video_settings*
     - TestEgressXdccBw.scala
     - TestRuntime2.scala (and rename it to TestExNums.scala)
     - TestIngressXdccBw.scala
     - TestNested.scala
     - TestOrionCommand.scala (and add two test cases)
    
    Add egress_xdcc_bw.dfdl.xsd and ingress_xdcc_bw.dfdl.xsd from a
    collaborator who already gave permission for Apache license.  Add
    egress_xdcc_bw.tdml and ingress_xdcc_bw.tdml with corresponding parse
    binary data files and unparse XML files to test all choice
    alternatives in both schemas.
    
    In orion-command.dfdl.xsd, incorporate latest changes from
    collaborator to define global elements using global complex type
    declarations instead of nested complex type declarations.
    
    In orion-command.tdml, change defaultRoundTrip to "none" to avoid
    redundancy and speed up tests.  Add two more test cases (CameraState)
    and corresponding data files to test all orion-command messages.
    
    In choice-unparse2.tdml, change embedded schema name from "c" to "c1"
    to avoid conflict with daffodil-runtime2's "c" directory in its
    resources.
    
    Add TestEgressXdccBw.scala, TestIngressXdccBw.scala, and
    TestNested.scala to provide entry points for calling test cases.
    
    In Rat.scala, update paths of binary data files moved from
    daffodil-runtime2 to daffodil-test and add new binary data files.
---
 build.sbt                                          |  13 +-
 .../daffodil/generating/TestCLIGenerateC.scala     |   2 +-
 daffodil-runtime2/src/main/resources/c/Makefile    |  13 +-
 .../src/main/resources/c/libcli/daffodil_argp.c    |  19 +-
 .../src/main/resources/c/libcli/daffodil_main.c    |  10 +-
 .../src/main/resources/c/libruntime/infoset.c      |  16 +-
 .../src/main/resources/c/libruntime/infoset.h      |  38 +-
 .../src/main/resources/c/libruntime/parsers.c      |  17 +-
 .../src/main/resources/c/libruntime/unparsers.c    |  18 +-
 .../src/main/resources/examples/NestedUnion.c      | 410 ++++++++++
 .../examples/{ex_nums.h => NestedUnion.h}          |  59 +-
 .../src/main/resources/examples/ex_nums.c          | 357 +++------
 .../src/main/resources/examples/ex_nums.h          |   2 +-
 .../apache/daffodil/runtime2/CodeGenerator.scala   |  44 +-
 .../daffodil/runtime2/Runtime2CodeGenerator.scala  |   3 +-
 .../runtime2/generators/CodeGeneratorState.scala   | 271 ++++++-
 ...entParseAndUnspecifiedLengthCodeGenerator.scala |   4 +-
 .../{TestRuntime2.dfdl.xsd => ex_nums.dfdl.xsd}    |   0
 .../runtime2/{TestRuntime2.tdml => ex_nums.tdml}   |  44 +-
 ...s_unparse1.xml => ex_nums_unparse_runtime1.xml} |   0
 ...s_unparse2.xml => ex_nums_unparse_runtime2.xml} |   0
 .../org/apache/daffodil/runtime2/nested.dfdl.xsd   |  84 ++
 .../runtime2/{orion-command.tdml => nested.tdml}   |  62 +-
 .../daffodil/runtime2/nested_struct_parse.dat      | Bin 0 -> 36 bytes
 ...mmand_unparse.xml => nested_struct_unparse.xml} |  26 +-
 .../daffodil/runtime2/nested_union_parse_2.dat     | Bin 0 -> 16 bytes
 .../daffodil/runtime2/nested_union_parse_4.dat     | Bin 0 -> 28 bytes
 ...mand_unparse.xml => nested_union_unparse_2.xml} |  22 +-
 ...mand_unparse.xml => nested_union_unparse_4.xml} |  22 +-
 .../daffodil/runtime2/orion-command.dfdl.xsd       | 104 ---
 .../org/apache/daffodil/tdml/TDMLRunner.scala      |   2 +-
 .../processor}/Runtime2TDMLDFDLProcessor.scala     |  25 +-
 .../daffodil/runtime2/camera_state_parse.dat       | Bin 0 -> 11 bytes
 .../daffodil/runtime2/camera_state_unparse.xml     |  16 +-
 .../org/apache/daffodil/runtime2/command_parse.dat | Bin
 .../apache/daffodil/runtime2/command_unparse.xml   |   0
 .../daffodil/runtime2/egress_xdcc_bw.dfdl.xsd      | 244 ++++++
 .../apache/daffodil/runtime2/egress_xdcc_bw.tdml   | 300 +++++++
 .../daffodil/runtime2/egress_xdcc_bw_parse_11.dat  | Bin 0 -> 36 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_12.dat  | Bin 0 -> 28 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_13.dat  | Bin 0 -> 120 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_14.dat  | Bin 0 -> 28 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_15.dat  | Bin 0 -> 52 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_16.dat  | Bin 0 -> 28 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_17.dat  | Bin 0 -> 56 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_18.dat  | Bin 0 -> 28 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_19.dat  | Bin 0 -> 744 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_20.dat  | Bin 0 -> 28 bytes
 .../runtime2/egress_xdcc_bw_unparse_11.xml         |  38 +-
 .../runtime2/egress_xdcc_bw_unparse_12.xml         |  36 +-
 .../runtime2/egress_xdcc_bw_unparse_13.xml         | 137 ++++
 .../runtime2/egress_xdcc_bw_unparse_14.xml         |  36 +-
 .../runtime2/egress_xdcc_bw_unparse_15.xml         |  46 +-
 .../runtime2/egress_xdcc_bw_unparse_16.xml         |  36 +-
 .../runtime2/egress_xdcc_bw_unparse_17.xml         |  73 ++
 .../runtime2/egress_xdcc_bw_unparse_18.xml         |  36 +-
 .../runtime2/egress_xdcc_bw_unparse_19.xml         | 638 +++++++++++++++
 .../runtime2/egress_xdcc_bw_unparse_20.xml         |  36 +-
 .../daffodil/runtime2/ingress_xdcc_bw.dfdl.xsd     | 202 +++++
 .../apache/daffodil/runtime2/ingress_xdcc_bw.tdml  | 196 +++++
 .../runtime2/ingress_xdcc_bw_parse_111.dat         | Bin 0 -> 36 bytes
 .../runtime2/ingress_xdcc_bw_parse_112.dat         | Bin 0 -> 28 bytes
 .../runtime2/ingress_xdcc_bw_parse_113.dat         | Bin 0 -> 120 bytes
 .../runtime2/ingress_xdcc_bw_parse_114.dat         | Bin 0 -> 28 bytes
 .../runtime2/ingress_xdcc_bw_parse_115.dat         | Bin 0 -> 1184 bytes
 .../runtime2/ingress_xdcc_bw_parse_116.dat         | Bin 0 -> 28 bytes
 .../runtime2/ingress_xdcc_bw_unparse_111.xml       |  38 +-
 .../runtime2/ingress_xdcc_bw_unparse_112.xml       |  36 +-
 .../runtime2/ingress_xdcc_bw_unparse_113.xml       | 137 ++++
 .../runtime2/ingress_xdcc_bw_unparse_114.xml       |  36 +-
 .../runtime2/ingress_xdcc_bw_unparse_115.xml       | 859 +++++++++++++++++++++
 .../runtime2/ingress_xdcc_bw_unparse_116.xml       |  36 +-
 .../daffodil/runtime2/orion-command.dfdl.xsd       | 101 +++
 .../apache/daffodil/runtime2/orion-command.tdml    |  28 +-
 .../daffodil/runtime2/video_settings_parse.dat     | Bin
 .../daffodil/runtime2/video_settings_unparse.xml   |   0
 .../section15/choice_groups/choice-unparse2.tdml   |   8 +-
 .../daffodil/runtime2/TestEgressXdccBw.scala       |  54 ++
 .../org/apache/daffodil/runtime2/TestExNums.scala  |  16 +-
 .../daffodil/runtime2/TestIngressXdccBw.scala      |  46 ++
 .../org/apache/daffodil/runtime2/TestNested.scala  |  20 +-
 .../daffodil/runtime2/TestOrionCommand.scala       |   2 +
 project/Rat.scala                                  |  26 +-
 83 files changed, 4433 insertions(+), 767 deletions(-)

diff --git a/build.sbt b/build.sbt
index 489682b..b2fadab 100644
--- a/build.sbt
+++ b/build.sbt
@@ -64,7 +64,7 @@ lazy val runtime1Unparser = Project("daffodil-runtime1-unparser", file("daffodil
 val runtime2CFiles        = Library("libruntime2.a")
 lazy val runtime2         = Project("daffodil-runtime2", file("daffodil-runtime2")).configs(IntegrationTest)
                               .enablePlugins(CcPlugin)
-                              .dependsOn(core, core % "test->test", tdmlProc)
+                              .dependsOn(core, core % "test->test")
                               .settings(commonSettings)
                               .settings(publishArtifact in (Compile, packageDoc) := false)
                               .settings(
@@ -82,12 +82,7 @@ lazy val runtime2         = Project("daffodil-runtime2", file("daffodil-runtime2
                                     (Compile / resourceDirectory).value / "examples"
                                   )
                                 ),
-                                Compile / cFlags := (Compile / cFlags).value.withDefaultValue(Seq(
-                                  "-g",
-                                  "-Wall",
-                                  "-Wextra",
-                                  "-Wno-missing-field-initializers",
-                                ))
+                                Compile / cFlags := (Compile / cFlags).value.withDefaultValue(Seq("-Wall", "-Wextra"))
                               )
 
 lazy val core             = Project("daffodil-core", file("daffodil-core")).configs(IntegrationTest)
@@ -107,7 +102,7 @@ lazy val tdmlLib             = Project("daffodil-tdml-lib", file("daffodil-tdml-
                               .settings(commonSettings)
 
 lazy val tdmlProc         = Project("daffodil-tdml-processor", file("daffodil-tdml-processor")).configs(IntegrationTest)
-                              .dependsOn(tdmlLib, core)
+                              .dependsOn(tdmlLib, runtime2, core)
                               .settings(commonSettings)
 
 lazy val cli              = Project("daffodil-cli", file("daffodil-cli")).configs(IntegrationTest)
@@ -125,7 +120,7 @@ lazy val schematron       = Project("daffodil-schematron", file("daffodil-schema
                               .configs(IntegrationTest)
 
 lazy val test             = Project("daffodil-test", file("daffodil-test")).configs(IntegrationTest)
-                              .dependsOn(tdmlProc, udf % "test->test")
+                              .dependsOn(tdmlProc, runtime2 % "test->test", udf % "test->test")
                               .settings(commonSettings, nopublish)
                               //
                               // Uncomment the following line to run these tests 
diff --git a/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala b/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
index 6700b66..e94ebec 100644
--- a/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
+++ b/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
@@ -33,7 +33,7 @@ class TestCLIGenerateC {
   val daffodil: String = Util.binPath
   var outputDir: os.Path = _
   lazy val schemaFile: String = if (Util.isWindows) Util.cmdConvert(sf) else sf
-  val sf: String = Util.daffodilPath("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd")
+  val sf: String = Util.daffodilPath("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.dfdl.xsd")
 
   @Before def before(): Unit = {
     outputDir = os.temp.dir()
diff --git a/daffodil-runtime2/src/main/resources/c/Makefile b/daffodil-runtime2/src/main/resources/c/Makefile
index fd1cf8d..d8b9e90 100644
--- a/daffodil-runtime2/src/main/resources/c/Makefile
+++ b/daffodil-runtime2/src/main/resources/c/Makefile
@@ -17,12 +17,15 @@
 # Here's how to compile the C sources into a program for running
 # parse/unparse tests (.dat <-> .xml)
 
-SOURCES = libcli/*.[ch] libruntime/*.[ch]
 PROGRAM = ./daffodil
-CFLAGS = -g -Wall -Wextra -Wno-missing-field-initializers
-
-$(PROGRAM): $(SOURCES)
-	$(CC) $(CFLAGS) -I libcli -I libruntime $(SOURCES) -lmxml -o $(PROGRAM)
+HEADERS = libcli/*.h libruntime/*.h
+SOURCES = libcli/*.c libruntime/*.c
+INCLUDES = -I libcli -I libruntime
+CFLAGS = -g -Wall -Wextra
+LIBS = -lmxml
+
+$(PROGRAM): $(HEADERS) $(SOURCES)
+	$(CC) $(CFLAGS) $(INCLUDES) $(SOURCES) $(LIBS) -o $(PROGRAM)
 
 # Here's how to run parse/unparse tests (.dat <-> .xml, although you
 # will need to create the .dat and .xml files first)
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.c b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.c
index 0b4e911..ddc9b31 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.c
@@ -35,11 +35,12 @@ struct daffodil_parse_cli daffodil_parse = {
 
 static const struct argp_option parse_options[] = {
     {"infoset-type", 'I', "<infoset_type>", 0,
-     "Infoset type to output. Must be one of 'xml' or 'null'"},
+     "Infoset type to output. Must be one of 'xml' or 'null'", 0},
 
     {"output", 'o', "<file>", 0,
      "Write output to a given file. If not given or is -, output is written to "
-     "stdout"},
+     "stdout",
+     0},
 
     {0}};
 
@@ -62,6 +63,9 @@ static const struct argp parse_argp = {
     parse_handler,  // function to get these CLI options
     parse_args_doc, // short usage documentation
     parse_doc,      // long help documentation
+    0,              // child argps parsed after this argp
+    0,              // function to replace help messages
+    0               // domain name for translation lookup
 };
 
 // Handle callbacks to get our "daffodil parse" CLI options
@@ -128,11 +132,12 @@ struct daffodil_unparse_cli daffodil_unparse = {
 
 static const struct argp_option unparse_options[] = {
     {"infoset-type", 'I', "<infoset_type>", 0,
-     "Infoset type to unparse. Must be 'xml'"},
+     "Infoset type to unparse. Must be 'xml'", 0},
 
     {"output", 'o', "<file>", 0,
      "Write output to file. If not given or is -, output is written to "
-     "standard output"},
+     "standard output",
+     0},
 
     {0}};
 
@@ -155,6 +160,9 @@ static const struct argp unparse_argp = {
     unparse_handler,  // function to get these CLI options
     unparse_args_doc, // short usage documentation
     unparse_doc,      // long help documentation
+    0,                // child argps parsed after this argp
+    0,                // function to replace help messages
+    0                 // domain name for translation lookup
 };
 
 // Handle callbacks to get our "daffodil unparse" CLI options
@@ -243,6 +251,9 @@ static const struct argp daffodil_argp = {
     daffodil_handler,  // function to get these CLI options
     daffodil_args_doc, // short usage documentation
     daffodil_doc,      // long help documentation
+    0,                 // child argps parsed after this argp
+    0,                 // function to replace help messages
+    0                  // domain name for translation lookup
 };
 
 // Handle callbacks to get our "daffodil" CLI options
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c
index f915d9f..56320ff 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c
@@ -85,14 +85,15 @@ main(int argc, char *argv[])
             output = fopen_or_exit(output, daffodil_parse.outfile, "w");
 
             // Parse the input file into our infoset.
-            PState pstate = {input};
+            PState pstate = {input, NULL};
             root->erd->parseSelf(root, &pstate);
             continue_or_exit(pstate.error_msg);
 
             if (strcmp(daffodil_parse.infoset_converter, "xml") == 0)
             {
                 // Visit the infoset and print XML from it.
-                XMLWriter   xmlWriter = {xmlWriterMethods, output};
+                XMLWriter   xmlWriter = {
+                    xmlWriterMethods, output, {NULL, NULL, 0}};
                 const char *error_msg =
                     walkInfoset((VisitEventHandler *)&xmlWriter, root);
                 continue_or_exit(error_msg);
@@ -112,7 +113,8 @@ main(int argc, char *argv[])
             if (strcmp(daffodil_unparse.infoset_converter, "xml") == 0)
             {
                 // Initialize our infoset's values from the XML data.
-                XMLReader   xmlReader = {xmlReaderMethods, input, root};
+                XMLReader   xmlReader = {
+                    xmlReaderMethods, input, root, NULL, NULL};
                 const char *error_msg =
                     walkInfoset((VisitEventHandler *)&xmlReader, root);
                 continue_or_exit(error_msg);
@@ -124,7 +126,7 @@ main(int argc, char *argv[])
             }
 
             // Unparse our infoset to the output file.
-            UState ustate = {output};
+            UState ustate = {output, NULL};
             root->erd->unparseSelf(root, &ustate);
             continue_or_exit(ustate.error_msg);
         }
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
index d40c351..9377b87 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
@@ -127,19 +127,19 @@ walkInfosetNode(const VisitEventHandler *handler, const InfosetBase *infoNode)
     // Walk the node's children recursively
     const size_t      count = infoNode->erd->numChildren;
     const ERD **const childrenERDs = infoNode->erd->childrenERDs;
-    const ptrdiff_t * offsets = infoNode->erd->offsets;
+    const size_t *    offsets = infoNode->erd->offsets;
 
     for (size_t i = 0; i < count && !error_msg; i++)
     {
-        ptrdiff_t  offset = offsets[i];
-        const ERD *childERD = childrenERDs[i];
+        const size_t offset = offsets[i];
+        const ERD *  childERD = childrenERDs[i];
         // We use only one of these variables below depending on typeCode
         const InfosetBase *childNode =
             (const InfosetBase *)((const char *)infoNode + offset);
         const void *numLocation =
             (const void *)((const char *)infoNode + offset);
 
-        // Need to handle more element types
+        // Will need to handle more element types
         const enum TypeCode typeCode = childERD->typeCode;
         switch (typeCode)
         {
@@ -159,6 +159,14 @@ walkInfosetNode(const VisitEventHandler *handler, const InfosetBase *infoNode)
             error_msg =
                 handler->visitNumberElem(handler, childERD, numLocation);
             break;
+        case CHOICE:
+            // Point next ERD to choice of alternative elements' ERDs
+            if (!infoNode->erd->initChoice(infoNode, rootElement()))
+            {
+                error_msg =
+                    "Walk error: no match between choice dispatch key and any branch key";
+            }
+            break;
         }
     }
 
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
index d9b614c..404bf6d 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
@@ -18,17 +18,12 @@
 #ifndef INFOSET_H
 #define INFOSET_H
 
-#include <stddef.h>  // for ptrdiff_t, size_t
-#include <stdio.h>   // for FILE
+#include <stdbool.h>  // for bool
+#include <stddef.h>   // for size_t
+#include <stdio.h>    // for FILE
 
 // Prototypes needed for compilation
 
-struct ElementRuntimeData;
-struct InfosetBase;
-struct PState;
-struct UState;
-struct VisitEventHandler;
-
 typedef struct ElementRuntimeData ERD;
 typedef struct InfosetBase        InfosetBase;
 typedef struct PState             PState;
@@ -38,6 +33,8 @@ typedef struct VisitEventHandler  VisitEventHandler;
 typedef void (*ERDInitSelf)(InfosetBase *infoNode);
 typedef void (*ERDParseSelf)(InfosetBase *infoNode, PState *pstate);
 typedef void (*ERDUnparseSelf)(const InfosetBase *infoNode, UState *ustate);
+typedef bool (*InitChoiceRD)(const InfosetBase *infoNode,
+                             const InfosetBase *rootElement);
 
 typedef const char *(*VisitStartDocument)(const VisitEventHandler *handler);
 typedef const char *(*VisitEndDocument)(const VisitEventHandler *handler);
@@ -71,7 +68,8 @@ enum TypeCode
     PRIMITIVE_INT16,
     PRIMITIVE_INT8,
     PRIMITIVE_FLOAT,
-    PRIMITIVE_DOUBLE
+    PRIMITIVE_DOUBLE,
+    CHOICE
 };
 
 // ERD - element runtime data needed to parse/unparse objects
@@ -81,34 +79,35 @@ typedef struct ElementRuntimeData
     const NamedQName    namedQName;
     const enum TypeCode typeCode;
     const size_t        numChildren;
-    const ptrdiff_t *   offsets;
+    const size_t *      offsets;
     const ERD **        childrenERDs;
 
     const ERDInitSelf    initSelf;
     const ERDParseSelf   parseSelf;
     const ERDUnparseSelf unparseSelf;
+    const InitChoiceRD   initChoice;
 } ERD;
 
-// InfosetBase - representation of an infoset element
+// InfosetBase - metadata of an infoset element
 
 typedef struct InfosetBase
 {
     const ERD *erd;
 } InfosetBase;
 
-// PState - parser state while parsing input
+// PState - mutable state while parsing data
 
 typedef struct PState
 {
-    FILE *      stream;    // input to read from
+    FILE *      stream;    // input to read data from
     const char *error_msg; // to stop if an error happens
 } PState;
 
-// UState - unparser state while unparsing infoset
+// UState - mutable state while unparsing infoset
 
 typedef struct UState
 {
-    FILE *      stream;    // output to write to
+    FILE *      stream;    // output to write data to
     const char *error_msg; // to stop if an error happens
 } UState;
 
@@ -130,9 +129,10 @@ extern const char *get_erd_name(const ERD *erd);
 extern const char *get_erd_xmlns(const ERD *erd);
 extern const char *get_erd_ns(const ERD *erd);
 
-// rootElement - return a root element to walk while parsing or unparsing
+// rootElement - return an infoset's root element for parsing,
+// walking, or unparsing (implementation actually is generated in
+// generated_code.c, not defined in infoset.c)
 
-// (actual definition will be in generated_code.c, not infoset.c)
 extern InfosetBase *rootElement(void);
 
 // walkInfoset - walk an infoset and call VisitEventHandler methods
@@ -144,4 +144,8 @@ extern const char *walkInfoset(const VisitEventHandler *handler,
 
 extern const char *eof_or_error_msg(FILE *stream);
 
+// NO_CHOICE - value stored in an uninitialized _choice field
+
+static const size_t NO_CHOICE = (size_t)-1;
+
 #endif // INFOSET_H
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/parsers.c b/daffodil-runtime2/src/main/resources/c/libruntime/parsers.c
index 87a5f98..8d97b99 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/parsers.c
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/parsers.c
@@ -19,10 +19,16 @@
 #include <endian.h>  // for be32toh, be64toh, le32toh, le64toh, be16toh, le16toh
 #include <stdio.h>   // for fread, size_t
 
-// Macros to expand into functions below
+// Macros that are not defined by <endian.h>
+
+#define be8toh(var) var
+
+#define le8toh(var) var
+
+// Macros to define parse_<endian>_<type> functions
 
 #define define_parse_endian_real(endian, type, bits)                           \
-    extern void parse_##endian##_##type(type *number, PState *pstate)          \
+    void parse_##endian##_##type(type *number, PState *pstate)                 \
     {                                                                          \
         if (!pstate->error_msg)                                                \
         {                                                                      \
@@ -44,8 +50,7 @@
     }
 
 #define define_parse_endian_integer(endian, type, bits)                        \
-    extern void parse_##endian##_##type##bits(type##bits##_t *number,          \
-                                              PState *        pstate)          \
+    void parse_##endian##_##type##bits(type##bits##_t *number, PState *pstate) \
     {                                                                          \
         if (!pstate->error_msg)                                                \
         {                                                                      \
@@ -64,10 +69,6 @@
         }                                                                      \
     }
 
-#define be8toh(var) var
-
-#define le8toh(var) var
-
 // Define functions to parse binary real and integer numbers
 
 define_parse_endian_real(be, double, 64)
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.c b/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.c
index 93cddbd..b48bb5d 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.c
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.c
@@ -19,10 +19,16 @@
 #include <endian.h>  // for htobe32, htobe64, htole32, htole64, htobe16, htole16
 #include <stdio.h>   // for fwrite, size_t
 
-// Macros to expand into functions below
+// Macros that are not defined by <endian.h>
+
+#define htobe8(var) var
+
+#define htole8(var) var
+
+// Macros to define unparse_<endian>_<type> functions
 
 #define define_unparse_endian_real(endian, type, bits)                         \
-    extern void unparse_##endian##_##type(type number, UState *ustate)         \
+    void unparse_##endian##_##type(type number, UState *ustate)                \
     {                                                                          \
         if (!ustate->error_msg)                                                \
         {                                                                      \
@@ -44,8 +50,8 @@
     }
 
 #define define_unparse_endian_integer(endian, type, bits)                      \
-    extern void unparse_##endian##_##type##bits(type##bits##_t number,         \
-                                                UState *       ustate)         \
+    void unparse_##endian##_##type##bits(type##bits##_t number,                \
+                                         UState *       ustate)                \
     {                                                                          \
         if (!ustate->error_msg)                                                \
         {                                                                      \
@@ -64,10 +70,6 @@
         }                                                                      \
     }
 
-#define htobe8(var) var
-
-#define htole8(var) var
-
 // Define functions to unparse binary real and integer numbers
 
 define_unparse_endian_real(be, double, 64)
diff --git a/daffodil-runtime2/src/main/resources/examples/NestedUnion.c b/daffodil-runtime2/src/main/resources/examples/NestedUnion.c
new file mode 100644
index 0000000..da4a0a4
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/examples/NestedUnion.c
@@ -0,0 +1,410 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "NestedUnion.h"
+#include "parsers.h"    // for parse_be_double, parse_be_float, parse_be_int16, parse_be_int32, parse_be_int64, parse_be_int8, parse_be_uint16, parse_be_uint32, parse_be_uint64, parse_be_uint8, parse_le_double, parse_le_float, parse_le_int16, parse_le_int32, parse_le_int64, parse_le_int8, parse_le_uint16, parse_le_uint32, parse_le_uint64, parse_le_uint8
+#include "unparsers.h"  // for unparse_be_double, unparse_be_float, unparse_be_int16, unparse_be_int32, unparse_be_int64, unparse_be_int8, unparse_be_uint16, unparse_be_uint32, unparse_be_uint64, unparse_be_uint8, unparse_le_double, unparse_le_float, unparse_le_int16, unparse_le_int32, unparse_le_int64, unparse_le_int8, unparse_le_uint16, unparse_le_uint32, unparse_le_uint64, unparse_le_uint8
+#include <math.h>       // for NAN
+#include <stdbool.h>    // for bool, false, true
+#include <stddef.h>     // for NULL, size_t
+
+// Prototypes needed for compilation
+
+static void foo_initSelf(foo *instance);
+static void foo_parseSelf(foo *instance, PState *pstate);
+static void foo_unparseSelf(const foo *instance, UState *ustate);
+static void bar_initSelf(bar *instance);
+static void bar_parseSelf(bar *instance, PState *pstate);
+static void bar_unparseSelf(const bar *instance, UState *ustate);
+static void data_initSelf(data *instance);
+static bool data_initChoice(data *instance, const NestedUnion *rootElement);
+static void data_parseSelf(data *instance, PState *pstate);
+static void data_unparseSelf(const data *instance, UState *ustate);
+static void NestedUnion_initSelf(NestedUnion *instance);
+static void NestedUnion_parseSelf(NestedUnion *instance, PState *pstate);
+static void NestedUnion_unparseSelf(const NestedUnion *instance, UState *ustate);
+
+// Metadata singletons
+
+static const ERD tag_NestedUnionType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "tag", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD _choice_data_NestedUnionType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "_choice", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    CHOICE, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD a_FooType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "a", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD b_FooType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "b", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD c_FooType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "c", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const foo foo_compute_offsets;
+
+static const size_t foo_offsets[3] = {
+    (const char *)&foo_compute_offsets.a - (const char *)&foo_compute_offsets,
+    (const char *)&foo_compute_offsets.b - (const char *)&foo_compute_offsets,
+    (const char *)&foo_compute_offsets.c - (const char *)&foo_compute_offsets
+};
+
+static const ERD *foo_childrenERDs[3] = {
+    &a_FooType_ERD,
+    &b_FooType_ERD,
+    &c_FooType_ERD
+};
+
+static const ERD foo_data_NestedUnionType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "foo", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    COMPLEX, // typeCode
+    3, // numChildren
+    foo_offsets, // offsets
+    foo_childrenERDs, // childrenERDs
+    (ERDInitSelf)&foo_initSelf, // initSelf
+    (ERDParseSelf)&foo_parseSelf, // parseSelf
+    (ERDUnparseSelf)&foo_unparseSelf, // unparseSelf
+    NULL // initChoice
+};
+
+static const ERD x_BarType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "x", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_DOUBLE, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD y_BarType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "y", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_DOUBLE, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD z_BarType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "z", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_DOUBLE, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const bar bar_compute_offsets;
+
+static const size_t bar_offsets[3] = {
+    (const char *)&bar_compute_offsets.x - (const char *)&bar_compute_offsets,
+    (const char *)&bar_compute_offsets.y - (const char *)&bar_compute_offsets,
+    (const char *)&bar_compute_offsets.z - (const char *)&bar_compute_offsets
+};
+
+static const ERD *bar_childrenERDs[3] = {
+    &x_BarType_ERD,
+    &y_BarType_ERD,
+    &z_BarType_ERD
+};
+
+static const ERD bar_data_NestedUnionType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "bar", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    COMPLEX, // typeCode
+    3, // numChildren
+    bar_offsets, // offsets
+    bar_childrenERDs, // childrenERDs
+    (ERDInitSelf)&bar_initSelf, // initSelf
+    (ERDParseSelf)&bar_parseSelf, // parseSelf
+    (ERDUnparseSelf)&bar_unparseSelf, // unparseSelf
+    NULL // initChoice
+};
+
+static const data data_compute_offsets;
+
+static const size_t data_offsets[3] = {
+    (const char *)&data_compute_offsets._choice - (const char *)&data_compute_offsets,
+    (const char *)&data_compute_offsets.foo - (const char *)&data_compute_offsets,
+    (const char *)&data_compute_offsets.bar - (const char *)&data_compute_offsets
+};
+
+static const ERD *data_childrenERDs[3] = {
+    &_choice_data_NestedUnionType_ERD,
+    &foo_data_NestedUnionType_ERD,
+    &bar_data_NestedUnionType_ERD
+};
+
+static const ERD data_NestedUnionType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "data", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    COMPLEX, // typeCode
+    2, // numChildren
+    data_offsets, // offsets
+    data_childrenERDs, // childrenERDs
+    (ERDInitSelf)&data_initSelf, // initSelf
+    (ERDParseSelf)&data_parseSelf, // parseSelf
+    (ERDUnparseSelf)&data_unparseSelf, // unparseSelf
+    (InitChoiceRD)&data_initChoice // initChoice
+};
+
+static const NestedUnion NestedUnion_compute_offsets;
+
+static const size_t NestedUnion_offsets[2] = {
+    (const char *)&NestedUnion_compute_offsets.tag - (const char *)&NestedUnion_compute_offsets,
+    (const char *)&NestedUnion_compute_offsets.data - (const char *)&NestedUnion_compute_offsets
+};
+
+static const ERD *NestedUnion_childrenERDs[2] = {
+    &tag_NestedUnionType_ERD,
+    &data_NestedUnionType_ERD
+};
+
+static const ERD NestedUnion_ERD = {
+    {
+        "idl", // namedQName.prefix
+        "NestedUnion", // namedQName.local
+        "urn:idl:1.0", // namedQName.ns
+    },
+    COMPLEX, // typeCode
+    2, // numChildren
+    NestedUnion_offsets, // offsets
+    NestedUnion_childrenERDs, // childrenERDs
+    (ERDInitSelf)&NestedUnion_initSelf, // initSelf
+    (ERDParseSelf)&NestedUnion_parseSelf, // parseSelf
+    (ERDUnparseSelf)&NestedUnion_unparseSelf, // unparseSelf
+    NULL // initChoice
+};
+
+// Return a root element to be used for parsing or unparsing
+
+InfosetBase *
+rootElement(void)
+{
+    static bool initialized;
+    static NestedUnion root;
+    if (!initialized)
+    {
+        NestedUnion_initSelf(&root);
+        initialized = true;
+    }
+    return &root._base;
+}
+
+// Methods to initialize, parse, and unparse infoset nodes
+
+static void
+foo_initSelf(foo *instance)
+{
+    instance->_base.erd = &foo_data_NestedUnionType_ERD;
+    instance->a = 0xCCCCCCCC;
+    instance->b = 0xCCCCCCCC;
+    instance->c = 0xCCCCCCCC;
+}
+
+static void
+foo_parseSelf(foo *instance, PState *pstate)
+{
+    parse_be_int32(&instance->a, pstate);
+    parse_be_int32(&instance->b, pstate);
+    parse_be_int32(&instance->c, pstate);
+}
+
+static void
+foo_unparseSelf(const foo *instance, UState *ustate)
+{
+    unparse_be_int32(instance->a, ustate);
+    unparse_be_int32(instance->b, ustate);
+    unparse_be_int32(instance->c, ustate);
+}
+
+static void
+bar_initSelf(bar *instance)
+{
+    instance->_base.erd = &bar_data_NestedUnionType_ERD;
+    instance->x = NAN;
+    instance->y = NAN;
+    instance->z = NAN;
+}
+
+static void
+bar_parseSelf(bar *instance, PState *pstate)
+{
+    parse_be_double(&instance->x, pstate);
+    parse_be_double(&instance->y, pstate);
+    parse_be_double(&instance->z, pstate);
+}
+
+static void
+bar_unparseSelf(const bar *instance, UState *ustate)
+{
+    unparse_be_double(instance->x, ustate);
+    unparse_be_double(instance->y, ustate);
+    unparse_be_double(instance->z, ustate);
+}
+
+static void
+data_initSelf(data *instance)
+{
+    instance->_base.erd = &data_NestedUnionType_ERD;
+    instance->_choice = NO_CHOICE;
+    foo_initSelf(&instance->foo);
+    bar_initSelf(&instance->bar);
+}
+
+static bool
+data_initChoice(data *instance, const NestedUnion *rootElement)
+{
+    int64_t key = rootElement->tag;
+    switch (key)
+    {
+    case 1:
+    case 2:
+        instance->_choice = 0;
+        break;
+    case 3:
+    case 4:
+        instance->_choice = 1;
+        break;
+    default:
+        instance->_choice = NO_CHOICE;
+        break;
+    }
+
+    if (instance->_choice != NO_CHOICE)
+    {
+        const size_t choice = instance->_choice + 1; // skip the _choice field
+        const size_t offset = instance->_base.erd->offsets[choice];
+        const ERD *  childERD = instance->_base.erd->childrenERDs[choice];
+        InfosetBase *childNode = (InfosetBase *)((const char *)instance + offset);
+        childNode->erd = childERD;
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+static void
+data_parseSelf(data *instance, PState *pstate)
+{
+    instance->_base.erd->initChoice(&instance->_base, rootElement());
+    switch (instance->_choice)
+    {
+    case 0:
+        foo_parseSelf(&instance->foo, pstate);
+        break;
+    case 1:
+        bar_parseSelf(&instance->bar, pstate);
+        break;
+    default:
+        pstate->error_msg =
+            "Parse error: no match between choice dispatch key and any branch key";
+        break;
+    }
+}
+
+static void
+data_unparseSelf(const data *instance, UState *ustate)
+{
+    instance->_base.erd->initChoice(&instance->_base, rootElement());
+    switch (instance->_choice)
+    {
+    case 0:
+        foo_unparseSelf(&instance->foo, ustate);
+        break;
+    case 1:
+        bar_unparseSelf(&instance->bar, ustate);
+        break;
+    default:
+        ustate->error_msg =
+            "Unparse error: no match between choice dispatch key and any branch key";
+        break;
+    }
+}
+
+static void
+NestedUnion_initSelf(NestedUnion *instance)
+{
+    instance->_base.erd = &NestedUnion_ERD;
+    instance->tag = 0xCCCCCCCC;
+    data_initSelf(&instance->data);
+}
+
+static void
+NestedUnion_parseSelf(NestedUnion *instance, PState *pstate)
+{
+    parse_be_int32(&instance->tag, pstate);
+    data_parseSelf(&instance->data, pstate);
+}
+
+static void
+NestedUnion_unparseSelf(const NestedUnion *instance, UState *ustate)
+{
+    unparse_be_int32(instance->tag, ustate);
+    data_unparseSelf(&instance->data, ustate);
+}
+
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_nums.h b/daffodil-runtime2/src/main/resources/examples/NestedUnion.h
similarity index 57%
copy from daffodil-runtime2/src/main/resources/examples/ex_nums.h
copy to daffodil-runtime2/src/main/resources/examples/NestedUnion.h
index 9e2c1bb..4396cd7 100644
--- a/daffodil-runtime2/src/main/resources/examples/ex_nums.h
+++ b/daffodil-runtime2/src/main/resources/examples/NestedUnion.h
@@ -21,51 +21,40 @@
 #include "infoset.h"  // for InfosetBase
 #include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
 
-// Define some infoset structures
+// Define infoset structures
 
-typedef struct array
+typedef struct foo
 {
     InfosetBase _base;
-    int16_t     be_int16[3];
-    float       be_float[3];
-} array;
+    int32_t     a;
+    int32_t     b;
+    int32_t     c;
+} foo;
 
-typedef struct bigEndian
+typedef struct bar
 {
     InfosetBase _base;
-    double      be_double;
-    float       be_float;
-    uint64_t    be_uint64;
-    uint32_t    be_uint32;
-    uint16_t    be_uint16;
-    uint8_t     be_uint8;
-    int64_t     be_int64;
-    int32_t     be_int32;
-    int16_t     be_int16;
-    int8_t      be_int8;
-} bigEndian;
+    double      x;
+    double      y;
+    double      z;
+} bar;
 
-typedef struct littleEndian
+typedef struct data
 {
     InfosetBase _base;
-    uint64_t    le_uint64;
-    uint32_t    le_uint32;
-    uint16_t    le_uint16;
-    uint8_t     le_uint8;
-    int64_t     le_int64;
-    int32_t     le_int32;
-    int16_t     le_int16;
-    int8_t      le_int8;
-    float       le_float;
-    double      le_double;
-} littleEndian;
-
-typedef struct ex_nums
+    size_t      _choice; // choice of which union field to use
+    union
+    {
+        foo foo;
+        bar bar;
+    };
+} data;
+
+typedef struct NestedUnion
 {
     InfosetBase _base;
-    array array;
-    bigEndian bigEndian;
-    littleEndian littleEndian;
-} ex_nums;
+    int32_t     tag;
+    data data;
+} NestedUnion;
 
 #endif // GENERATED_CODE_H
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_nums.c b/daffodil-runtime2/src/main/resources/examples/ex_nums.c
index 7747006..fb6f98f 100644
--- a/daffodil-runtime2/src/main/resources/examples/ex_nums.c
+++ b/daffodil-runtime2/src/main/resources/examples/ex_nums.c
@@ -19,7 +19,8 @@
 #include "parsers.h"    // for parse_be_double, parse_be_float, parse_be_int16, parse_be_int32, parse_be_int64, parse_be_int8, parse_be_uint16, parse_be_uint32, parse_be_uint64, parse_be_uint8, parse_le_double, parse_le_float, parse_le_int16, parse_le_int32, parse_le_int64, parse_le_int8, parse_le_uint16, parse_le_uint32, parse_le_uint64, parse_le_uint8
 #include "unparsers.h"  // for unparse_be_double, unparse_be_float, unparse_be_int16, unparse_be_int32, unparse_be_int64, unparse_be_int8, unparse_be_uint16, unparse_be_uint32, unparse_be_uint64, unparse_be_uint8, unparse_le_double, unparse_le_float, unparse_le_int16, unparse_le_int32, unparse_le_int64, unparse_le_int8, unparse_le_uint16, unparse_le_uint32, unparse_le_uint64, unparse_le_uint8
 #include <math.h>       // for NAN
-#include <stddef.h>     // for NULL, ptrdiff_t
+#include <stdbool.h>    // for bool, false, true
+#include <stddef.h>     // for NULL, size_t
 
 // Prototypes needed for compilation
 
@@ -38,39 +39,29 @@ static void ex_nums_unparseSelf(const ex_nums *instance, UState *ustate);
 
 // Metadata singletons
 
-static const ERD be_int16_array_ex_nums__ERD = {
+static const ERD be_int16_array_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_int16", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT16, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_float_array_ex_nums__ERD = {
+static const ERD be_float_array_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_float", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_FLOAT, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
 static const array array_compute_offsets;
 
-static const ptrdiff_t array_offsets[6] = {
+static const size_t array_offsets[6] = {
     (const char *)&array_compute_offsets.be_int16[0] - (const char *)&array_compute_offsets,
     (const char *)&array_compute_offsets.be_int16[1] - (const char *)&array_compute_offsets,
     (const char *)&array_compute_offsets.be_int16[2] - (const char *)&array_compute_offsets,
@@ -80,182 +71,133 @@ static const ptrdiff_t array_offsets[6] = {
 };
 
 static const ERD *array_childrenERDs[6] = {
-    &be_int16_array_ex_nums__ERD,
-    &be_int16_array_ex_nums__ERD,
-    &be_int16_array_ex_nums__ERD,
-    &be_float_array_ex_nums__ERD,
-    &be_float_array_ex_nums__ERD,
-    &be_float_array_ex_nums__ERD
+    &be_int16_array_ex_nums_ERD,
+    &be_int16_array_ex_nums_ERD,
+    &be_int16_array_ex_nums_ERD,
+    &be_float_array_ex_nums_ERD,
+    &be_float_array_ex_nums_ERD,
+    &be_float_array_ex_nums_ERD
 };
 
-static const ERD array_ex_nums__ERD = {
+static const ERD array_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "array", // namedQName.local
         NULL, // namedQName.ns
     },
-    COMPLEX,                         // typeCode
-    6,                               // numChildren
-    array_offsets,                      // offsets
-    array_childrenERDs,                 // childrenERDs
-    (ERDInitSelf)&array_initSelf,       // initSelf
-    (ERDParseSelf)&array_parseSelf,     // parseSelf
+    COMPLEX, // typeCode
+    6, // numChildren
+    array_offsets, // offsets
+    array_childrenERDs, // childrenERDs
+    (ERDInitSelf)&array_initSelf, // initSelf
+    (ERDParseSelf)&array_parseSelf, // parseSelf
     (ERDUnparseSelf)&array_unparseSelf, // unparseSelf
+    NULL // initChoice
 };
 
-static const ERD be_double_bigEndian_ex_nums__ERD = {
+static const ERD be_double_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_double", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_DOUBLE, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_float_bigEndian_ex_nums__ERD = {
+static const ERD be_float_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_float", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_FLOAT, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_uint64_bigEndian_ex_nums__ERD = {
+static const ERD be_uint64_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_uint64", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT64, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_uint32_bigEndian_ex_nums__ERD = {
+static const ERD be_uint32_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_uint32", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT32, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_uint16_bigEndian_ex_nums__ERD = {
+static const ERD be_uint16_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_uint16", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT16, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_uint8_bigEndian_ex_nums__ERD = {
+static const ERD be_uint8_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_uint8", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT8, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_int64_bigEndian_ex_nums__ERD = {
+static const ERD be_int64_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_int64", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT64, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_int32_bigEndian_ex_nums__ERD = {
+static const ERD be_int32_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_int32", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT32, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_int16_bigEndian_ex_nums__ERD = {
+static const ERD be_int16_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_int16", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT16, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_int8_bigEndian_ex_nums__ERD = {
+static const ERD be_int8_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_int8", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT8, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
 static const bigEndian bigEndian_compute_offsets;
 
-static const ptrdiff_t bigEndian_offsets[10] = {
+static const size_t bigEndian_offsets[10] = {
     (const char *)&bigEndian_compute_offsets.be_double - (const char *)&bigEndian_compute_offsets,
     (const char *)&bigEndian_compute_offsets.be_float - (const char *)&bigEndian_compute_offsets,
     (const char *)&bigEndian_compute_offsets.be_uint64 - (const char *)&bigEndian_compute_offsets,
@@ -269,186 +211,137 @@ static const ptrdiff_t bigEndian_offsets[10] = {
 };
 
 static const ERD *bigEndian_childrenERDs[10] = {
-    &be_double_bigEndian_ex_nums__ERD,
-    &be_float_bigEndian_ex_nums__ERD,
-    &be_uint64_bigEndian_ex_nums__ERD,
-    &be_uint32_bigEndian_ex_nums__ERD,
-    &be_uint16_bigEndian_ex_nums__ERD,
-    &be_uint8_bigEndian_ex_nums__ERD,
-    &be_int64_bigEndian_ex_nums__ERD,
-    &be_int32_bigEndian_ex_nums__ERD,
-    &be_int16_bigEndian_ex_nums__ERD,
-    &be_int8_bigEndian_ex_nums__ERD
-};
-
-static const ERD bigEndian_ex_nums__ERD = {
+    &be_double_bigEndian_ex_nums_ERD,
+    &be_float_bigEndian_ex_nums_ERD,
+    &be_uint64_bigEndian_ex_nums_ERD,
+    &be_uint32_bigEndian_ex_nums_ERD,
+    &be_uint16_bigEndian_ex_nums_ERD,
+    &be_uint8_bigEndian_ex_nums_ERD,
+    &be_int64_bigEndian_ex_nums_ERD,
+    &be_int32_bigEndian_ex_nums_ERD,
+    &be_int16_bigEndian_ex_nums_ERD,
+    &be_int8_bigEndian_ex_nums_ERD
+};
+
+static const ERD bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "bigEndian", // namedQName.local
         NULL, // namedQName.ns
     },
-    COMPLEX,                         // typeCode
-    10,                               // numChildren
-    bigEndian_offsets,                      // offsets
-    bigEndian_childrenERDs,                 // childrenERDs
-    (ERDInitSelf)&bigEndian_initSelf,       // initSelf
-    (ERDParseSelf)&bigEndian_parseSelf,     // parseSelf
+    COMPLEX, // typeCode
+    10, // numChildren
+    bigEndian_offsets, // offsets
+    bigEndian_childrenERDs, // childrenERDs
+    (ERDInitSelf)&bigEndian_initSelf, // initSelf
+    (ERDParseSelf)&bigEndian_parseSelf, // parseSelf
     (ERDUnparseSelf)&bigEndian_unparseSelf, // unparseSelf
+    NULL // initChoice
 };
 
-static const ERD le_uint64_littleEndian_ex_nums__ERD = {
+static const ERD le_uint64_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_uint64", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT64, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_uint32_littleEndian_ex_nums__ERD = {
+static const ERD le_uint32_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_uint32", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT32, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_uint16_littleEndian_ex_nums__ERD = {
+static const ERD le_uint16_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_uint16", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT16, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_uint8_littleEndian_ex_nums__ERD = {
+static const ERD le_uint8_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_uint8", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT8, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_int64_littleEndian_ex_nums__ERD = {
+static const ERD le_int64_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_int64", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT64, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_int32_littleEndian_ex_nums__ERD = {
+static const ERD le_int32_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_int32", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT32, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_int16_littleEndian_ex_nums__ERD = {
+static const ERD le_int16_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_int16", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT16, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_int8_littleEndian_ex_nums__ERD = {
+static const ERD le_int8_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_int8", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT8, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_float_littleEndian_ex_nums__ERD = {
+static const ERD le_float_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_float", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_FLOAT, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_double_littleEndian_ex_nums__ERD = {
+static const ERD le_double_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_double", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_DOUBLE, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
 static const littleEndian littleEndian_compute_offsets;
 
-static const ptrdiff_t littleEndian_offsets[10] = {
+static const size_t littleEndian_offsets[10] = {
     (const char *)&littleEndian_compute_offsets.le_uint64 - (const char *)&littleEndian_compute_offsets,
     (const char *)&littleEndian_compute_offsets.le_uint32 - (const char *)&littleEndian_compute_offsets,
     (const char *)&littleEndian_compute_offsets.le_uint16 - (const char *)&littleEndian_compute_offsets,
@@ -462,71 +355,77 @@ static const ptrdiff_t littleEndian_offsets[10] = {
 };
 
 static const ERD *littleEndian_childrenERDs[10] = {
-    &le_uint64_littleEndian_ex_nums__ERD,
-    &le_uint32_littleEndian_ex_nums__ERD,
-    &le_uint16_littleEndian_ex_nums__ERD,
-    &le_uint8_littleEndian_ex_nums__ERD,
-    &le_int64_littleEndian_ex_nums__ERD,
-    &le_int32_littleEndian_ex_nums__ERD,
-    &le_int16_littleEndian_ex_nums__ERD,
-    &le_int8_littleEndian_ex_nums__ERD,
-    &le_float_littleEndian_ex_nums__ERD,
-    &le_double_littleEndian_ex_nums__ERD
-};
-
-static const ERD littleEndian_ex_nums__ERD = {
+    &le_uint64_littleEndian_ex_nums_ERD,
+    &le_uint32_littleEndian_ex_nums_ERD,
+    &le_uint16_littleEndian_ex_nums_ERD,
+    &le_uint8_littleEndian_ex_nums_ERD,
+    &le_int64_littleEndian_ex_nums_ERD,
+    &le_int32_littleEndian_ex_nums_ERD,
+    &le_int16_littleEndian_ex_nums_ERD,
+    &le_int8_littleEndian_ex_nums_ERD,
+    &le_float_littleEndian_ex_nums_ERD,
+    &le_double_littleEndian_ex_nums_ERD
+};
+
+static const ERD littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "littleEndian", // namedQName.local
         NULL, // namedQName.ns
     },
-    COMPLEX,                         // typeCode
-    10,                               // numChildren
-    littleEndian_offsets,                      // offsets
-    littleEndian_childrenERDs,                 // childrenERDs
-    (ERDInitSelf)&littleEndian_initSelf,       // initSelf
-    (ERDParseSelf)&littleEndian_parseSelf,     // parseSelf
+    COMPLEX, // typeCode
+    10, // numChildren
+    littleEndian_offsets, // offsets
+    littleEndian_childrenERDs, // childrenERDs
+    (ERDInitSelf)&littleEndian_initSelf, // initSelf
+    (ERDParseSelf)&littleEndian_parseSelf, // parseSelf
     (ERDUnparseSelf)&littleEndian_unparseSelf, // unparseSelf
+    NULL // initChoice
 };
 
 static const ex_nums ex_nums_compute_offsets;
 
-static const ptrdiff_t ex_nums_offsets[3] = {
+static const size_t ex_nums_offsets[3] = {
     (const char *)&ex_nums_compute_offsets.array - (const char *)&ex_nums_compute_offsets,
     (const char *)&ex_nums_compute_offsets.bigEndian - (const char *)&ex_nums_compute_offsets,
     (const char *)&ex_nums_compute_offsets.littleEndian - (const char *)&ex_nums_compute_offsets
 };
 
 static const ERD *ex_nums_childrenERDs[3] = {
-    &array_ex_nums__ERD,
-    &bigEndian_ex_nums__ERD,
-    &littleEndian_ex_nums__ERD
+    &array_ex_nums_ERD,
+    &bigEndian_ex_nums_ERD,
+    &littleEndian_ex_nums_ERD
 };
 
-static const ERD ex_nums__ERD = {
+static const ERD ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "ex_nums", // namedQName.local
         "http://example.com", // namedQName.ns
     },
-    COMPLEX,                         // typeCode
-    3,                               // numChildren
-    ex_nums_offsets,                      // offsets
-    ex_nums_childrenERDs,                 // childrenERDs
-    (ERDInitSelf)&ex_nums_initSelf,       // initSelf
-    (ERDParseSelf)&ex_nums_parseSelf,     // parseSelf
+    COMPLEX, // typeCode
+    3, // numChildren
+    ex_nums_offsets, // offsets
+    ex_nums_childrenERDs, // childrenERDs
+    (ERDInitSelf)&ex_nums_initSelf, // initSelf
+    (ERDParseSelf)&ex_nums_parseSelf, // parseSelf
     (ERDUnparseSelf)&ex_nums_unparseSelf, // unparseSelf
+    NULL // initChoice
 };
 
 // Return a root element to be used for parsing or unparsing
 
-extern InfosetBase *
+InfosetBase *
 rootElement(void)
 {
-    static ex_nums instance;
-    InfosetBase *root = &instance._base;
-    ex_nums__ERD.initSelf(root);
-    return root;
+    static bool initialized;
+    static ex_nums root;
+    if (!initialized)
+    {
+        ex_nums_initSelf(&root);
+        initialized = true;
+    }
+    return &root._base;
 }
 
 // Methods to initialize, parse, and unparse infoset nodes
@@ -534,13 +433,13 @@ rootElement(void)
 static void
 array_initSelf(array *instance)
 {
+    instance->_base.erd = &array_ex_nums_ERD;
     instance->be_int16[0] = 0xCCCC;
     instance->be_int16[1] = 0xCCCC;
     instance->be_int16[2] = 0xCCCC;
     instance->be_float[0] = NAN;
     instance->be_float[1] = NAN;
     instance->be_float[2] = NAN;
-    instance->_base.erd = &array_ex_nums__ERD;
 }
 
 static void
@@ -568,6 +467,7 @@ array_unparseSelf(const array *instance, UState *ustate)
 static void
 bigEndian_initSelf(bigEndian *instance)
 {
+    instance->_base.erd = &bigEndian_ex_nums_ERD;
     instance->be_double = NAN;
     instance->be_float = NAN;
     instance->be_uint64 = 0xCCCCCCCCCCCCCCCC;
@@ -578,7 +478,6 @@ bigEndian_initSelf(bigEndian *instance)
     instance->be_int32 = 0xCCCCCCCC;
     instance->be_int16 = 0xCCCC;
     instance->be_int8 = 0xCC;
-    instance->_base.erd = &bigEndian_ex_nums__ERD;
 }
 
 static void
@@ -614,6 +513,7 @@ bigEndian_unparseSelf(const bigEndian *instance, UState *ustate)
 static void
 littleEndian_initSelf(littleEndian *instance)
 {
+    instance->_base.erd = &littleEndian_ex_nums_ERD;
     instance->le_uint64 = 0xCCCCCCCCCCCCCCCC;
     instance->le_uint32 = 0xCCCCCCCC;
     instance->le_uint16 = 0xCCCC;
@@ -624,7 +524,6 @@ littleEndian_initSelf(littleEndian *instance)
     instance->le_int8 = 0xCC;
     instance->le_float = NAN;
     instance->le_double = NAN;
-    instance->_base.erd = &littleEndian_ex_nums__ERD;
 }
 
 static void
@@ -660,10 +559,10 @@ littleEndian_unparseSelf(const littleEndian *instance, UState *ustate)
 static void
 ex_nums_initSelf(ex_nums *instance)
 {
+    instance->_base.erd = &ex_nums_ERD;
     array_initSelf(&instance->array);
     bigEndian_initSelf(&instance->bigEndian);
     littleEndian_initSelf(&instance->littleEndian);
-    instance->_base.erd = &ex_nums__ERD;
 }
 
 static void
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_nums.h b/daffodil-runtime2/src/main/resources/examples/ex_nums.h
index 9e2c1bb..403da6b 100644
--- a/daffodil-runtime2/src/main/resources/examples/ex_nums.h
+++ b/daffodil-runtime2/src/main/resources/examples/ex_nums.h
@@ -21,7 +21,7 @@
 #include "infoset.h"  // for InfosetBase
 #include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
 
-// Define some infoset structures
+// Define infoset structures
 
 typedef struct array
 {
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
index 385657c..7756780 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
@@ -32,6 +32,11 @@ import org.apache.daffodil.util.Misc
 import org.apache.daffodil.xml.RefQName
 
 /**
+ * We need a mutux object for exclusive access to a code block
+  */
+private object mutex {}
+
+/**
  * Generates and compiles C source files from a DFDL schema encapsulated in a [[Root]].
  * Implements the [[DFDL.CodeGenerator]] trait to allow it to be called by Daffodil code.
  * @param root Provides the DFDL schema for code generation
@@ -43,8 +48,10 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
   private var diagnostics: Seq[Diagnostic] = Nil
   private var errorStatus: Boolean = false
 
-  // Writes C source files into a "c" subdirectory of the given output directory.
-  // Removes the "c" subdirectory if it existed before.  Returns the "c" subdirectory.
+  /**
+   * Writes C source files into a "c" subdirectory of the given output directory.
+   * Removes the "c" subdirectory if it existed before.  Returns the "c" subdirectory.
+  */
   override def generateCode(rootNS: Option[RefQName], outputDirArg: String): os.Path = {
     // Get the paths of the output directory and its code subdirectory
     val outputDir = os.Path(Paths.get(outputDirArg).toAbsolutePath)
@@ -55,19 +62,22 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
     os.remove.all(codeDir)
 
     // Copy our resource directory and all its C source files to our code subdirectory
+    // (using synchronized to avoid calling FileSystems.newFileSystem concurrently)
     val resourceUri = Misc.getRequiredResource("/c")
-    val fileSystem = if (resourceUri.getScheme == "jar") {
-      val env: java.util.Map[String, String] = Collections.emptyMap()
-      FileSystems.newFileSystem(resourceUri, env)
-    } else {
-      null
-    }
-    try {
-      val resourceDir = os.Path(if (fileSystem != null) fileSystem.getPath("/c") else Paths.get(resourceUri))
-      os.copy(resourceDir, codeDir)
+    mutex.synchronized {
+      val fileSystem = if (resourceUri.getScheme == "jar") {
+        val env: java.util.Map[String, String] = Collections.emptyMap()
+        FileSystems.newFileSystem(resourceUri, env)
+      } else {
+        null
+      }
+      try {
+        val resourceDir = os.Path(if (fileSystem != null) fileSystem.getPath("/c") else Paths.get(resourceUri))
+        os.copy(resourceDir, codeDir)
+      }
+      finally
+        if (fileSystem != null) fileSystem.close()
     }
-    finally
-      if (fileSystem != null) fileSystem.close()
 
     // Generate C code from the DFDL schema
     val rootElementName = rootNS.getOrElse(root.refQName).local
@@ -86,8 +96,10 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
     codeDir
   }
 
-  // Compiles any C source files inside the given code directory.  Returns the path
-  // of the newly created executable to use in TDML tests or somewhere else.
+  /**
+   * Compiles any C source files inside the given code directory.  Returns the path
+   * of the newly created executable to use in TDML tests or somewhere else.
+   */
   override def compileCode(codeDir: os.Path): os.Path = {
     // Get the path of the executable we will build
     val exe = if (isWindows) codeDir/"daffodil.exe" else codeDir/"daffodil"
@@ -96,7 +108,7 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
       // Assemble the compiler's command line arguments
       val compiler = pickCompiler
       val files = os.walk(codeDir).filter(_.ext == "c")
-      val libs = Seq("-lmxml", if (isWindows) "-largp" else "-lpthread")
+      val libs = if (isWindows) Seq("-largp", "-lmxml") else Seq("-lmxml")
 
       // Run the compiler in the code directory (if we found "zig cc"
       // as a compiler, it will cache previously built files in zig's
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala
index 65c2c1c..633cc28 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala
@@ -51,7 +51,7 @@ object Runtime2CodeGenerator
     with SeqCompCodeGenerator {
 
   @tailrec
-  def generateCode(gram: Gram, state: CodeGeneratorState): Unit =
+  def generateCode(gram: Gram, state: CodeGeneratorState): Unit = {
     gram match {
       case g: RootGrammarMixin => Runtime2CodeGenerator.generateCode(g.documentElement, state)
       case g: Prod if (g.guard) => Runtime2CodeGenerator.generateCode(g.gram, state)
@@ -70,6 +70,7 @@ object Runtime2CodeGenerator
       case _: CaptureValueLengthEnd => noop
       case _ => gram.SDE("Code generation not supported for: %s", Misc.getNameFromClass(gram))
     }
+  }
 
   private def noop: Unit = {
     // Not generating code here, but can use as a breakpoint
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
index a1db02c..5142db7 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
@@ -17,14 +17,19 @@
 
 package org.apache.daffodil.runtime2.generators
 
+import org.apache.daffodil.cookers.ChoiceBranchKeyCooker
 import org.apache.daffodil.dpath.NodeInfo
 import org.apache.daffodil.dpath.NodeInfo.PrimType
+import org.apache.daffodil.dsom.AbstractElementRef
+import org.apache.daffodil.dsom.Choice
 import org.apache.daffodil.dsom.ElementBase
+import org.apache.daffodil.dsom.GlobalComplexTypeDef
 import org.apache.daffodil.dsom.GlobalElementDecl
 import org.apache.daffodil.dsom.SchemaComponent
 import org.apache.daffodil.exceptions.ThrowsSDE
 import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
 
+import java.net.URI
 import scala.collection.mutable
 
 /**
@@ -37,12 +42,13 @@ class CodeGeneratorState {
   private val finalStructs = mutable.ArrayBuffer[String]()
   private val finalImplementation = mutable.ArrayBuffer[String]()
 
-  // Builds a name for the given element that needs to be unique in C file scope
-  private def qualifiedName(context: ElementBase): String = {
+  // Builds an ERD name for the given element that needs to be unique in C file scope
+  private def erdName(context: ElementBase): String = {
     def buildName(sc: SchemaComponent, sb: StringBuilder): StringBuilder = {
       sc match {
-        case gd: GlobalElementDecl => sb ++= gd.namedQName.local += '_'
         case eb: ElementBase => sb ++= eb.namedQName.local += '_'
+        case gd: GlobalElementDecl => sb ++= gd.namedQName.local += '_'
+        case ct: GlobalComplexTypeDef => sb ++= ct.namedQName.local += '_'
         case _ => // don't include other schema components in qualified name
       }
       sc.optLexicalParent.foreach {
@@ -50,7 +56,7 @@ class CodeGeneratorState {
       }
       sb
     }
-    val sb = buildName(context, new StringBuilder)
+    val sb = buildName(context, new StringBuilder) ++= "ERD"
     sb.toString()
   }
 
@@ -60,20 +66,36 @@ class CodeGeneratorState {
   def addImplementation(context: ElementBase): Unit = {
     val C = localName(context)
     val initStatements = structs.top.initStatements.mkString("\n")
+    val initChoiceStatements = structs.top.initChoiceStatements.mkString("\n")
     val parserStatements = structs.top.parserStatements.mkString("\n")
     val unparserStatements = structs.top.unparserStatements.mkString("\n")
+    val hasChoice = structs.top.initChoiceStatements.nonEmpty
+    val root = structs.elems.last.C
+    val prototypeInitChoice = if (hasChoice)
+      s"\nstatic bool ${C}_initChoice($C *instance, const $root *rootElement);"
+    else
+      ""
+    val implementInitChoice = if (hasChoice)
+      s"""
+         |static bool
+         |${C}_initChoice($C *instance, const $root *rootElement)
+         |{
+         |$initChoiceStatements
+         |}
+         |""".stripMargin
+    else
+      ""
     val prototypeFunctions =
-      s"""static void ${C}_initSelf($C *instance);
+      s"""static void ${C}_initSelf($C *instance);$prototypeInitChoice
          |static void ${C}_parseSelf($C *instance, PState *pstate);
          |static void ${C}_unparseSelf(const $C *instance, UState *ustate);""".stripMargin
-    prototypes += prototypeFunctions
     val functions =
       s"""static void
          |${C}_initSelf($C *instance)
          |{
          |$initStatements
          |}
-         |
+         |$implementInitChoice
          |static void
          |${C}_parseSelf($C *instance, PState *pstate)
          |{
@@ -86,6 +108,8 @@ class CodeGeneratorState {
          |$unparserStatements
          |}
          |""".stripMargin
+
+    prototypes += prototypeFunctions
     finalImplementation += functions
   }
 
@@ -105,17 +129,155 @@ class CodeGeneratorState {
     qnameInit
   }
 
+  /**
+   * We want to convert a choiceDispatchKey expression into C struct dot
+   * notation (rootElement->[subElement.field]) which will access the C
+   * struct field containing the choiceDispatchKey's runtime value.
+   *
+   * We make some assumptions to make generating the dot notation easier:
+   * - the expression starts with '{xs:string( and ends with )}'
+   * - the expression returns the value of a previous element without
+   *   changing the value in any way (except converting it to xs:string)
+   * - both the expression and the C code use only local names (for now...)
+   * - we can map the context node's path to a Unix-like slash path
+   * - all dpath operations look like Unix-like relative paths (../tag)
+   * - we can normalize the new path and convert it to C struct dot notation
+   * - we can store the accessed value in an int64_t local variable safely
+   */
+  private def choiceDispatchField(context: ElementBase): String = {
+    // We want to use SchemaComponent.scPath but it's private so duplicate it here (for now...)
+    def scPath(sc: SchemaComponent): Seq[SchemaComponent] = sc.optLexicalParent.map { scPath }.getOrElse(Nil) :+ sc
+    val localNames = scPath(context).map {
+      case er: AbstractElementRef => er.refQName.local
+      case e: ElementBase => e.namedQName.local
+      case ed: GlobalElementDecl => ed.namedQName.local
+      case _ => ""
+    }
+    val absoluteSlashPath = localNames.mkString("/")
+    val dispatchSlashPath = context.complexType.modelGroup match {
+      case choice: Choice if choice.isDirectDispatch =>
+        val expr = choice.choiceDispatchKeyEv.expr.toBriefXML()
+        val before = "'{xs:string("
+        val after = ")}'"
+        val relativePath = if (expr.startsWith(before) && expr.endsWith(after))
+          expr.substring(before.length, expr.length - after.length) else expr
+        val normalizedURI = new URI(absoluteSlashPath + "/" + relativePath).normalize
+        normalizedURI.getPath.substring(1)
+      case _ => ""
+    }
+    // Strip namespace prefixes since C code uses only local names (for now...)
+    val localDispatchSlashPath = dispatchSlashPath.replaceAll("/[^:]+:", "/")
+    val res = localDispatchSlashPath.replace('/', '.')
+    res
+  }
+
+  def addBeforeSwitchStatements(context: ElementBase): Unit = {
+    val erd = erdName(context)
+    val initStatement = s"    instance->_base.erd = &$erd;"
+
+    structs.top.initStatements += initStatement
+
+    val dispatchField = choiceDispatchField(context)
+    if (dispatchField.nonEmpty) {
+      val C = localName(context)
+      val declaration =
+        s"""    size_t      _choice; // choice of which union field to use
+           |    union
+           |    {""".stripMargin
+      val erdDef =
+        s"""static const ERD _choice_$erd = {
+           |    {
+           |        NULL, // namedQName.prefix
+           |        "_choice", // namedQName.local
+           |        NULL, // namedQName.ns
+           |    },
+           |    CHOICE, // typeCode
+           |    0, NULL, NULL, NULL, NULL, NULL, NULL
+           |};
+           |""".stripMargin
+      val offsetComputation = s"    (const char *)&${C}_compute_offsets._choice - (const char *)&${C}_compute_offsets"
+      val erdComputation = s"    &_choice_$erd"
+      val initStatement = s"    instance->_choice = NO_CHOICE;"
+      val initChoiceStatement =
+        s"""    int64_t key = rootElement->$dispatchField;
+           |    switch (key)
+           |    {""".stripMargin
+      val parseStatement =
+        s"""    instance->_base.erd->initChoice(&instance->_base, rootElement());
+           |    switch (instance->_choice)
+           |    {""".stripMargin
+      val unparseStatement =
+        s"""    instance->_base.erd->initChoice(&instance->_base, rootElement());
+           |    switch (instance->_choice)
+           |    {""".stripMargin
+
+      erds += erdDef
+      structs.top.declarations += declaration
+      structs.top.offsetComputations += offsetComputation
+      structs.top.erdComputations += erdComputation
+      structs.top.initStatements += initStatement
+      structs.top.initChoiceStatements += initChoiceStatement
+      structs.top.parserStatements += parseStatement
+      structs.top.unparserStatements += unparseStatement
+    }
+  }
+
+  def addAfterSwitchStatements(): Unit = {
+    if (structs.top.initChoiceStatements.nonEmpty) {
+      val declaration = s"    };"
+      val initChoiceStatement =
+        s"""    default:
+           |        instance->_choice = NO_CHOICE;
+           |        break;
+           |    }
+           |
+           |    if (instance->_choice != NO_CHOICE)
+           |    {
+           |        const size_t choice = instance->_choice + 1; // skip the _choice field
+           |        const size_t offset = instance->_base.erd->offsets[choice];
+           |        const ERD *  childERD = instance->_base.erd->childrenERDs[choice];
+           |        InfosetBase *childNode = (InfosetBase *)((const char *)instance + offset);
+           |        childNode->erd = childERD;
+           |        return true;
+           |    }
+           |    else
+           |    {
+           |        return false;
+           |    }""".stripMargin
+      val parseStatement =
+        s"""    default:
+           |        pstate->error_msg =
+           |            "Parse error: no match between choice dispatch key and any branch key";
+           |        break;
+           |    }""".stripMargin
+      val unparseStatement =
+        s"""    default:
+           |        ustate->error_msg =
+           |            "Unparse error: no match between choice dispatch key and any branch key";
+           |        break;
+           |    }""".stripMargin
+
+      structs.top.declarations += declaration
+      structs.top.initChoiceStatements += initChoiceStatement
+      structs.top.parserStatements += parseStatement
+      structs.top.unparserStatements += unparseStatement
+    }
+  }
+
   def addComplexTypeERD(context: ElementBase): Unit = {
     val C = localName(context)
-    val qn = qualifiedName(context)
+    val erd = erdName(context)
     val count = structs.top.offsetComputations.length
     val offsetComputations = structs.top.offsetComputations.mkString(",\n")
     val erdComputations = structs.top.erdComputations.mkString(",\n")
     val qnameInit = defineQNameInit(context)
+    val hasChoice = structs.top.initChoiceStatements.nonEmpty
+    val numChildren = if (hasChoice) 2 else count
+    val initChoice = if (hasChoice) s"(InitChoiceRD)&${C}_initChoice" else "NULL"
     val complexERD =
       s"""static const $C ${C}_compute_offsets;
          |
-         |static const ptrdiff_t ${C}_offsets[$count] = {
+         |static const size_t ${C}_offsets[$count] = {
          |$offsetComputations
          |};
          |
@@ -123,23 +285,24 @@ class CodeGeneratorState {
          |$erdComputations
          |};
          |
-         |static const ERD ${qn}_ERD = {
+         |static const ERD $erd = {
          |$qnameInit
-         |    COMPLEX,                         // typeCode
-         |    $count,                               // numChildren
-         |    ${C}_offsets,                      // offsets
-         |    ${C}_childrenERDs,                 // childrenERDs
-         |    (ERDInitSelf)&${C}_initSelf,       // initSelf
-         |    (ERDParseSelf)&${C}_parseSelf,     // parseSelf
+         |    COMPLEX, // typeCode
+         |    $numChildren, // numChildren
+         |    ${C}_offsets, // offsets
+         |    ${C}_childrenERDs, // childrenERDs
+         |    (ERDInitSelf)&${C}_initSelf, // initSelf
+         |    (ERDParseSelf)&${C}_parseSelf, // parseSelf
          |    (ERDUnparseSelf)&${C}_unparseSelf, // unparseSelf
+         |    $initChoice // initChoice
          |};
          |""".stripMargin
+
     erds += complexERD
   }
 
   def addStruct(context: ElementBase): Unit = {
     val C = localName(context)
-    val qn = qualifiedName(context)
     val declarations = structs.top.declarations.mkString("\n")
     val struct =
       s"""typedef struct $C
@@ -148,9 +311,8 @@ class CodeGeneratorState {
          |$declarations
          |} $C;
          |""".stripMargin
+
     finalStructs += struct
-    val initStatement = s"    instance->_base.erd = &${qn}_ERD;"
-    structs.top.initStatements += initStatement
   }
 
   def addSimpleTypeStatements(initStatement: String, parseStatement: String, unparseStatement: String): Unit = {
@@ -162,10 +324,31 @@ class CodeGeneratorState {
   def addComplexTypeStatements(child: ElementBase): Unit = {
     val C = localName(child)
     val e = child.name
+    val hasChoice = structs.top.initChoiceStatements.nonEmpty
+    val offset = if (hasChoice) child.position - 1 else -1
     val initStatement = s"    ${C}_initSelf(&instance->$e);"
-    val parseStatement = s"    ${C}_parseSelf(&instance->$e, pstate);"
-    val unparseStatement = s"    ${C}_unparseSelf(&instance->$e, ustate);"
+    val initChoiceStatement =
+      s"""        instance->_choice = $offset;
+         |        break;""".stripMargin
+    val parseStatement = if (hasChoice)
+      s"""    case $offset:
+         |        ${C}_parseSelf(&instance->$e, pstate);
+         |        break;""".stripMargin
+    else
+      s"    ${C}_parseSelf(&instance->$e, pstate);"
+    val unparseStatement = if (hasChoice)
+      s"""    case $offset:
+         |        ${C}_unparseSelf(&instance->$e, ustate);
+         |        break;""".stripMargin
+    else
+      s"    ${C}_unparseSelf(&instance->$e, ustate);"
+
     structs.top.initStatements += initStatement
+    if (hasChoice) {
+      structs.top.initChoiceStatements ++= ChoiceBranchKeyCooker.convertConstant(
+        child.choiceBranchKey, child, forUnparse = false).map { key => s"    case $key:"}
+      structs.top.initChoiceStatements += initChoiceStatement
+    }
     structs.top.parserStatements += parseStatement
     structs.top.unparserStatements += unparseStatement
   }
@@ -175,12 +358,12 @@ class CodeGeneratorState {
     structs.push(new ComplexCGState(C))
   }
 
-  def popComplexElement(context: ElementBase): Unit = {
+  def popComplexElement(): Unit = {
     structs.pop()
   }
 
   def addSimpleTypeERD(context: ElementBase): Unit = {
-    val qn = qualifiedName(context)
+    val erd = erdName(context)
     val qnameInit = defineQNameInit(context)
     val typeCode = context.optPrimType.get match {
       case PrimType.UnsignedLong => "PRIMITIVE_UINT64"
@@ -195,30 +378,25 @@ class CodeGeneratorState {
       case PrimType.Double => "PRIMITIVE_DOUBLE"
       case p: PrimType => context.SDE("PrimType %s not supported yet.", p.toString)
     }
-    val erd =
-      s"""static const ERD ${qn}_ERD = {
+    val erdDef =
+      s"""static const ERD $erd = {
          |$qnameInit
          |    $typeCode, // typeCode
-         |    0,               // numChildren
-         |    NULL,            // offsets
-         |    NULL,            // childrenERDs
-         |    NULL,            // initSelf
-         |    NULL,            // parseSelf
-         |    NULL,            // unparseSelf
+         |    0, NULL, NULL, NULL, NULL, NULL, NULL
          |};
          |""".stripMargin
-    erds += erd
+    erds += erdDef
     addComputations(context)
   }
 
   def addComputations(child: ElementBase): Unit = {
     val C = structs.top.C
     val e = localName(child)
-    val qn = qualifiedName(child)
+    val erd = erdName(child)
     val arraySize = if (child.occursCountKind == OccursCountKind.Fixed) child.maxOccurs else 0
     def addComputation(deref: String): Unit = {
       val offsetComputation = s"    (const char *)&${C}_compute_offsets.$e$deref - (const char *)&${C}_compute_offsets"
-      val erdComputation = s"    &${qn}_ERD"
+      val erdComputation = s"    &$erd"
       structs.top.offsetComputations += offsetComputation
       structs.top.erdComputations += erdComputation
     }
@@ -250,7 +428,10 @@ class CodeGeneratorState {
     }
     val e = child.name
     val arrayDef = if (child.occursCountKind == OccursCountKind.Fixed) s"[${child.maxOccurs}]" else ""
-    structs.top.declarations += s"    $definition $e$arrayDef;"
+    val indent = if (structs.top.initChoiceStatements.nonEmpty) "    " else ""
+    val declaration = s"$indent    $definition $e$arrayDef;"
+
+    structs.top.declarations += declaration
   }
 
   def generateCodeHeader: String = {
@@ -262,7 +443,7 @@ class CodeGeneratorState {
          |#include "infoset.h"  // for InfosetBase
          |#include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
 
-         |// Define some infoset structures
+         |// Define infoset structures
          |
          |$structs
          |#endif // GENERATED_CODE_H
@@ -279,7 +460,8 @@ class CodeGeneratorState {
          |#include "parsers.h"    // for parse_be_double, parse_be_float, parse_be_int16, parse_be_int32, parse_be_int64, parse_be_int8, parse_be_uint16, parse_be_uint32, parse_be_uint64, parse_be_uint8, parse_le_double, parse_le_float, parse_le_int16, parse_le_int32, parse_le_int64, parse_le_int8, parse_le_uint16, parse_le_uint32, parse_le_uint64, parse_le_uint8
          |#include "unparsers.h"  // for unparse_be_double, unparse_be_float, unparse_be_int16, unparse_be_int32, unparse_be_int64, unparse_be_int8, unparse_be_uint16, unparse_be_uint32, unparse_be_uint64, unparse_be_uint8, unparse_le_double, unparse_le_float, unparse_le_int16, unparse_le_int32, unparse_le_int64, unparse_le_int8, unparse_le_uint16, unparse_le_uint32, unparse_le_uint64, unparse_le_uint8
          |#include <math.h>       // for NAN
-         |#include <stddef.h>     // for NULL, ptrdiff_t
+         |#include <stdbool.h>    // for bool, false, true
+         |#include <stddef.h>     // for NULL, size_t
          |
          |// Prototypes needed for compilation
          |
@@ -290,13 +472,17 @@ class CodeGeneratorState {
          |$erds
          |// Return a root element to be used for parsing or unparsing
          |
-         |extern InfosetBase *
+         |InfosetBase *
          |rootElement(void)
          |{
-         |    static $rootElementName instance;
-         |    InfosetBase *root = &instance._base;
-         |    ${rootElementName}__ERD.initSelf(root);
-         |    return root;
+         |    static bool initialized;
+         |    static $rootElementName root;
+         |    if (!initialized)
+         |    {
+         |        ${rootElementName}_initSelf(&root);
+         |        initialized = true;
+         |    }
+         |    return &root._base;
          |}
          |
          |// Methods to initialize, parse, and unparse infoset nodes
@@ -316,6 +502,7 @@ class ComplexCGState(val C: String) {
   val offsetComputations = mutable.ArrayBuffer[String]()
   val erdComputations = mutable.ArrayBuffer[String]()
   val initStatements = mutable.ArrayBuffer[String]()
+  val initChoiceStatements = mutable.ArrayBuffer[String]()
   val parserStatements = mutable.ArrayBuffer[String]()
   val unparserStatements = mutable.ArrayBuffer[String]()
 }
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala
index b1157d1..26203f8 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala
@@ -40,6 +40,7 @@ trait ElementParseAndUnspecifiedLengthCodeGenerator {
       Runtime2CodeGenerator.generateCode(elementContentGram, cgState) // initSelf, parseSelf, unparseSelf
     } else {
       cgState.pushComplexElement(context)
+      cgState.addBeforeSwitchStatements(context) // switch statements for choices
       context.elementChildren.foreach { child =>
         if (!child.isSimpleType) {
           cgState.addComplexTypeStatements(child) // recursive calls to parse, unparse, init
@@ -48,10 +49,11 @@ trait ElementParseAndUnspecifiedLengthCodeGenerator {
         cgState.addFieldDeclaration(context, child) // struct member for child
         Runtime2CodeGenerator.generateCode(child.enclosedElement, cgState) // generate children too
       }
+      cgState.addAfterSwitchStatements() // switch statements for choices
       cgState.addStruct(context) // struct definition
       cgState.addImplementation(context) // initSelf, parseSelf, unparseSelf
       cgState.addComplexTypeERD(context) // ERD static initializer
-      cgState.popComplexElement(context)
+      cgState.popComplexElement()
     }
   }
 }
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.dfdl.xsd
similarity index 100%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd
rename to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.dfdl.xsd
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
similarity index 68%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml
rename to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
index 09021a3..3d12954 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
@@ -18,8 +18,8 @@
 
 <tdml:testSuite
   defaultImplementations="daffodil daffodil-runtime2"
-  defaultRoundTrip="onePass"
-  description="TDML tests for daffodil-runtime2"
+  defaultRoundTrip="none"
+  description="TDML tests for ex_nums"
   xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
   xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
   xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
@@ -37,27 +37,23 @@
   </tdml:defineConfig>
 
   <tdml:parserTestCase
-    config="config-runtime1"
-    description="ex_nums parse test with runtime1"
-    model="TestRuntime2.dfdl.xsd"
-    name="ex_nums_parse1"
-    root="ex_nums">
+    name="ex_nums_parse_runtime1"
+    model="ex_nums.dfdl.xsd"
+    config="config-runtime1">
     <tdml:document>
       <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse1.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime1.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    config="config-runtime1"
-    description="ex_nums unparse test with runtime1"
-    model="TestRuntime2.dfdl.xsd"
-    name="ex_nums_unparse1"
-    root="ex_nums">
+    name="ex_nums_unparse_runtime1"
+    model="ex_nums.dfdl.xsd"
+    config="config-runtime1">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse1.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime1.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
       <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
@@ -65,27 +61,23 @@
   </tdml:unparserTestCase>
 
   <tdml:parserTestCase
-    config="config-runtime2"
-    description="ex_nums parse test with runtime2"
-    model="TestRuntime2.dfdl.xsd"
-    name="ex_nums_parse2"
-    root="ex_nums">
+    name="ex_nums_parse_runtime2"
+    model="ex_nums.dfdl.xsd"
+    config="config-runtime2">
     <tdml:document>
       <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse2.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime2.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    config="config-runtime2"
-    description="ex_nums unparse test with runtime2"
-    model="TestRuntime2.dfdl.xsd"
-    name="ex_nums_unparse2"
-    root="ex_nums">
+    name="ex_nums_unparse_runtime2"
+    model="ex_nums.dfdl.xsd"
+    config="config-runtime2">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse2.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime2.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
       <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse1.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime1.xml
similarity index 100%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse1.xml
rename to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime1.xml
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse2.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime2.xml
similarity index 100%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse2.xml
rename to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime2.xml
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested.dfdl.xsd b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested.dfdl.xsd
new file mode 100644
index 0000000..2faebc7
--- /dev/null
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested.dfdl.xsd
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:idl="urn:idl:1.0" targetNamespace="urn:idl:1.0">
+  <xs:annotation>
+    <xs:appinfo source="http://www.ogf.org/dfdl/">
+      <dfdl:defineFormat name="defaults">
+        <dfdl:format alignment="8" alignmentUnits="bits" binaryBooleanFalseRep="0" binaryBooleanTrueRep="1" binaryFloatRep="ieee" binaryNumberCheckPolicy="lax" binaryNumberRep="binary" bitOrder="mostSignificantBitFirst" byteOrder="bigEndian" choiceLengthKind="implicit" encoding="utf-8" encodingErrorPolicy="replace" escapeSchemeRef="" fillByte="%#r20;" floating="no" ignoreCase="no" initiatedContent="no" initiator="" leadingSkip="0" lengthKind="implicit" lengthUnits="bits" occursCountKind= [...]
+      </dfdl:defineFormat>
+      <dfdl:format ref="idl:defaults"/>
+    </xs:appinfo>
+  </xs:annotation>
+
+  <xs:simpleType name="double" dfdl:length="64" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:double"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="int32" dfdl:length="32" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:int"/>
+  </xs:simpleType>
+
+  <xs:complexType name="FooType">
+    <xs:sequence>
+      <xs:element name="a" type="idl:int32"/>
+      <xs:element name="b" type="idl:int32"/>
+      <xs:element name="c" type="idl:int32"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="BarType">
+    <xs:sequence>
+      <xs:element name="x" type="idl:double"/>
+      <xs:element name="y" type="idl:double"/>
+      <xs:element name="z" type="idl:double"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="NestedStructType">
+    <xs:sequence>
+      <xs:element name="data">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="foo" type="idl:FooType"/>
+            <xs:element name="bar" type="idl:BarType"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="NestedUnionType">
+    <xs:sequence>
+      <xs:element name="tag" type="idl:int32"/>
+      <xs:element name="data">
+        <xs:complexType>
+          <xs:choice dfdl:choiceDispatchKey="{xs:string(../tag)}">
+            <xs:element name="foo" type="idl:FooType" dfdl:choiceBranchKey="1 2"/>
+            <xs:element name="bar" type="idl:BarType" dfdl:choiceBranchKey="3 4"/>
+          </xs:choice>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:element name="NestedStruct" type="idl:NestedStructType"/>
+
+  <xs:element name="NestedUnion" type="idl:NestedUnionType"/>
+
+</xs:schema>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested.tdml
similarity index 54%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
copy to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested.tdml
index 110322d..91adc0b 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested.tdml
@@ -19,8 +19,8 @@
 <tdml:testSuite
   defaultConfig="config-runtime2"
   defaultImplementations="daffodil daffodil-runtime2"
-  defaultRoundTrip="onePass"
-  description="TDML tests for orion-command"
+  defaultRoundTrip="none"
+  description="TDML tests for nested"
   xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
   xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
   xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
@@ -37,55 +37,57 @@
     </daf:tunables>
   </tdml:defineConfig>
 
-  <tdml:parserTestCase
-    description="orion-command Command parse test"
-    model="orion-command.dfdl.xsd"
-    name="command_parse"
-    root="Command">
+  <tdml:parserTestCase name="nested_struct_parse" model="nested.dfdl.xsd">
     <tdml:document>
-      <tdml:documentPart type="file">command_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">nested_struct_parse.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">command_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">nested_struct_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
-  <tdml:unparserTestCase
-    description="orion-command Command unparse test"
-    model="orion-command.dfdl.xsd"
-    name="command_unparse"
-    root="Command">
+  <tdml:unparserTestCase name="nested_struct_unparse" model="nested.dfdl.xsd">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">command_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">nested_struct_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">command_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">nested_struct_parse.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
-  <tdml:parserTestCase
-    description="orion-command VideoSettings parse test"
-    model="orion-command.dfdl.xsd"
-    name="video_settings_parse"
-    root="VideoSettings">
+  <tdml:parserTestCase name="nested_union_parse_2" model="nested.dfdl.xsd">
     <tdml:document>
-      <tdml:documentPart type="file">video_settings_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">nested_union_parse_2.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">video_settings_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">nested_union_unparse_2.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
-  <tdml:unparserTestCase
-    description="orion-command VideoSettings unparse test"
-    model="orion-command.dfdl.xsd"
-    name="video_settings_unparse"
-    root="VideoSettings">
+  <tdml:unparserTestCase name="nested_union_unparse_2" model="nested.dfdl.xsd">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">video_settings_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">nested_union_unparse_2.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">video_settings_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">nested_union_parse_2.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase name="nested_union_parse_4" model="nested.dfdl.xsd">
+    <tdml:document>
+      <tdml:documentPart type="file">nested_union_parse_4.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">nested_union_unparse_4.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase name="nested_union_unparse_4" model="nested.dfdl.xsd">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">nested_union_unparse_4.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">nested_union_parse_4.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_struct_parse.dat b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_struct_parse.dat
new file mode 100644
index 0000000..1782b59
Binary files /dev/null and b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_struct_parse.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_struct_unparse.xml
similarity index 75%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_struct_unparse.xml
index 9a1d4a1..89f2902 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_struct_unparse.xml
@@ -16,15 +16,17 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<idl:NestedStruct xmlns:idl="urn:idl:1.0">
+  <data>
+    <foo>
+      <a>1</a>
+      <b>2</b>
+      <c>3</c>
+    </foo>
+    <bar>
+      <x>4.5</x>
+      <y>5.5</y>
+      <z>6.5</z>
+    </bar>
+  </data>
+</idl:NestedStruct>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_2.dat b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_2.dat
new file mode 100644
index 0000000..08a4355
Binary files /dev/null and b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_2.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_4.dat b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_4.dat
new file mode 100644
index 0000000..a8d472c
Binary files /dev/null and b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_4.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_unparse_2.xml
similarity index 75%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_unparse_2.xml
index 9a1d4a1..fe089b3 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_unparse_2.xml
@@ -16,15 +16,13 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<idl:NestedUnion xmlns:idl="urn:idl:1.0">
+  <tag>2</tag>
+  <data>
+    <foo>
+      <a>1</a>
+      <b>2</b>
+      <c>3</c>
+    </foo>
+  </data>
+</idl:NestedUnion>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_unparse_4.xml
similarity index 75%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_unparse_4.xml
index 9a1d4a1..6688d57 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_unparse_4.xml
@@ -16,15 +16,13 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<idl:NestedUnion xmlns:idl="urn:idl:1.0">
+  <tag>4</tag>
+  <data>
+    <bar>
+      <x>1.5</x>
+      <y>2.5</y>
+      <z>3.5</z>
+    </bar>
+  </data>
+</idl:NestedUnion>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd
deleted file mode 100644
index 8b37108..0000000
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd
+++ /dev/null
@@ -1,104 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one or more
-  contributor license agreements.  See the NOTICE file distributed with
-  this work for additional information regarding copyright ownership.
-  The ASF licenses this file to You under the Apache License, Version 2.0
-  (the "License"); you may not use this file except in compliance with
-  the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
--->
-
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:idl="urn:idl:1.0" targetNamespace="urn:idl:1.0">
-  <xs:annotation>
-    <xs:appinfo source="http://www.ogf.org/dfdl/">
-      <dfdl:defineFormat name="defaults">
-        <dfdl:format alignment="8" alignmentUnits="bits" binaryBooleanFalseRep="0" binaryBooleanTrueRep="1" binaryFloatRep="ieee" binaryNumberCheckPolicy="lax" binaryNumberRep="binary" bitOrder="mostSignificantBitFirst" byteOrder="bigEndian" choiceLengthKind="implicit" encoding="utf-8" encodingErrorPolicy="replace" escapeSchemeRef="" fillByte="%#r20;" floating="no" ignoreCase="no" initiatedContent="no" initiator="" leadingSkip="0" lengthKind="implicit" lengthUnits="bits" occursCountKind= [...]
-      </dfdl:defineFormat>
-      <dfdl:format ref="idl:defaults"/>
-    </xs:appinfo>
-  </xs:annotation>
-  <xs:simpleType name="int8" dfdl:length="8" dfdl:lengthKind="explicit">
-    <xs:restriction base="xs:byte"/>
-  </xs:simpleType>
-  <xs:simpleType name="int16" dfdl:length="16" dfdl:lengthKind="explicit">
-    <xs:restriction base="xs:short"/>
-  </xs:simpleType>
-  <xs:simpleType name="uint8" dfdl:length="8" dfdl:lengthKind="explicit">
-    <xs:restriction base="xs:unsignedByte"/>
-  </xs:simpleType>
-  <xs:simpleType name="uint16" dfdl:length="16" dfdl:lengthKind="explicit">
-    <xs:restriction base="xs:unsignedShort"/>
-  </xs:simpleType>
-  <xs:simpleType name="uint32" dfdl:length="32" dfdl:lengthKind="explicit">
-    <xs:restriction base="xs:unsignedInt"/>
-  </xs:simpleType>
-  <xs:element name="Command">
-    <xs:complexType>
-      <xs:sequence>
-        <xs:element name="sync0" fixed="208" type="idl:uint8"/>
-        <xs:element name="sync1" fixed="13" type="idl:uint8"/>
-        <xs:element name="id" fixed="1" type="idl:uint8"/>
-        <xs:element name="length" fixed="7" type="idl:uint8"/>
-        <xs:element name="pan" type="idl:int16"/>
-        <xs:element name="tilt">
-          <xs:simpleType>
-            <xs:restriction base="idl:int16">
-              <xs:minInclusive value="-1396"/>
-              <xs:maxInclusive value="733"/>
-            </xs:restriction>
-          </xs:simpleType>
-        </xs:element>
-        <xs:element name="mode" fixed="80" type="idl:uint8"/>
-        <xs:element name="stabilized" fixed="0" type="idl:uint8"/>
-        <xs:element name="impulse" fixed="0" type="idl:uint8"/>
-        <xs:element name="checksum" type="idl:uint16"/>
-      </xs:sequence>
-    </xs:complexType>
-  </xs:element>
-  <xs:element name="CameraState">
-    <xs:complexType>
-      <xs:sequence>
-        <xs:element name="sync0" fixed="208" type="idl:uint8"/>
-        <xs:element name="sync1" fixed="13" type="idl:uint8"/>
-        <xs:element name="id" fixed="97" type="idl:uint8"/>
-        <xs:element name="length" fixed="5" type="idl:uint8"/>
-        <xs:element name="zoom" type="idl:int16"/>
-        <xs:element name="focus" type="idl:int16"/>
-        <xs:element name="index" fixed="0" type="idl:uint8"/>
-        <xs:element name="checksum" type="idl:uint16"/>
-      </xs:sequence>
-    </xs:complexType>
-  </xs:element>
-  <xs:element name="VideoSettings">
-    <xs:complexType>
-      <xs:sequence>
-        <xs:element name="sync0" fixed="208" type="idl:uint8"/>
-        <xs:element name="sync1" fixed="13" type="idl:uint8"/>
-        <xs:element name="id" fixed="98" type="idl:uint8"/>
-        <xs:element name="length" fixed="14" type="idl:uint8"/>
-        <xs:element name="destIp">
-          <xs:complexType>
-            <xs:sequence>
-              <xs:element name="item" minOccurs="4" maxOccurs="4" dfdl:occursCountKind="fixed" type="idl:uint8"/>
-            </xs:sequence>
-          </xs:complexType>
-        </xs:element>
-        <xs:element name="port" type="idl:uint16"/>
-        <xs:element name="bitrate" fixed="0" type="idl:uint32"/>
-        <xs:element name="ttl" fixed="0" type="idl:int8"/>
-        <xs:element name="streamType" fixed="0" type="idl:uint8"/>
-        <xs:element name="mjpegQuality" fixed="0" type="idl:uint8"/>
-        <xs:element name="saveSettingsAndTsPacketCount" fixed="0" type="idl:uint8"/>
-        <xs:element name="checksum" type="idl:uint16"/>
-      </xs:sequence>
-    </xs:complexType>
-  </xs:element>
-</xs:schema>
diff --git a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
index f11cd27..cebc082 100644
--- a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
+++ b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
@@ -479,7 +479,7 @@ abstract class TestCase(testCaseXML: NodeSeq, val parent: DFDLTestSuite)
     // Our TDMLDFDLProcessorFactory implementation is a tunable choice with three values.
     val className = tunableObj.tdmlImplementation match {
       case "daffodil" => "org.apache.daffodil.tdml.processor.TDMLDFDLProcessorFactory"
-      case "daffodil-runtime2" => "org.apache.daffodil.tdml.processor.runtime2.TDMLDFDLProcessorFactory"
+      case "daffodil-runtime2" => "org.apache.daffodil.tdml.processor.Runtime2TDMLDFDLProcessorFactory"
       case "ibm" => "org.apache.daffodil.tdml.processor.ibm.TDMLDFDLProcessorFactory"
     }
 
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/tdml/processor/runtime2/Runtime2TDMLDFDLProcessor.scala b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/processor/Runtime2TDMLDFDLProcessor.scala
similarity index 92%
rename from daffodil-runtime2/src/main/scala/org/apache/daffodil/tdml/processor/runtime2/Runtime2TDMLDFDLProcessor.scala
rename to daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/processor/Runtime2TDMLDFDLProcessor.scala
index a18698f..f150580 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/tdml/processor/runtime2/Runtime2TDMLDFDLProcessor.scala
+++ b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/processor/Runtime2TDMLDFDLProcessor.scala
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.daffodil.tdml.processor.runtime2
+package org.apache.daffodil.tdml.processor
 
 import org.apache.daffodil.api._
 import org.apache.daffodil.compiler.Compiler
@@ -23,13 +23,12 @@ import org.apache.daffodil.externalvars.Binding
 import org.apache.daffodil.runtime2.ParseResult
 import org.apache.daffodil.runtime2.Runtime2DataProcessor
 import org.apache.daffodil.runtime2.UnparseResult
-import org.apache.daffodil.tdml.processor._
 import org.apache.daffodil.xml.QName
 import org.apache.daffodil.xml.XMLUtils
 
 import scala.xml.Node
 
-final class TDMLDFDLProcessorFactory private(
+final class Runtime2TDMLDFDLProcessorFactory private(
   private var compiler: Compiler,
   private var checkAllTopLevel: Boolean,
   validateDFDLSchemasArg: Boolean)
@@ -37,7 +36,7 @@ final class TDMLDFDLProcessorFactory private(
 
   override def validateDFDLSchemas = validateDFDLSchemasArg
 
-  override type R = TDMLDFDLProcessorFactory
+  override type R = Runtime2TDMLDFDLProcessorFactory
 
   override def implementationName = "daffodil-runtime2"
 
@@ -49,7 +48,7 @@ final class TDMLDFDLProcessorFactory private(
     compiler: Compiler = compiler,
     checkAllTopLevel: Boolean = checkAllTopLevel,
     validateDFDLSchemas: Boolean = validateDFDLSchemas) =
-    new TDMLDFDLProcessorFactory(compiler, checkAllTopLevel, validateDFDLSchemas)
+    new Runtime2TDMLDFDLProcessorFactory(compiler, checkAllTopLevel, validateDFDLSchemas)
 
   /**
    * Deprecated methods must be implemented. Some are just stubs though now.
@@ -59,7 +58,7 @@ final class TDMLDFDLProcessorFactory private(
     compiler = compiler.withValidateDFDLSchemas(bool)
   }
 
-  override def withValidateDFDLSchemas(bool: Boolean): TDMLDFDLProcessorFactory = {
+  override def withValidateDFDLSchemas(bool: Boolean): Runtime2TDMLDFDLProcessorFactory = {
     copy(compiler = compiler.withValidateDFDLSchemas(bool))
   }
 
@@ -68,7 +67,7 @@ final class TDMLDFDLProcessorFactory private(
     compiler = compiler.withCheckAllTopLevel(checkAllTopLevel)
   }
 
-  override def withCheckAllTopLevel(checkAllTopLevel: Boolean): TDMLDFDLProcessorFactory = {
+  override def withCheckAllTopLevel(checkAllTopLevel: Boolean): Runtime2TDMLDFDLProcessorFactory = {
     copy(compiler = compiler.withCheckAllTopLevel(checkAllTopLevel))
   }
 
@@ -76,14 +75,14 @@ final class TDMLDFDLProcessorFactory private(
   override def setTunables(tunables: Map[String, String]): Unit =
     compiler = compiler.withTunables(tunables)
 
-  override def withTunables(tunables: Map[String, String]): TDMLDFDLProcessorFactory =
+  override def withTunables(tunables: Map[String, String]): Runtime2TDMLDFDLProcessorFactory =
     copy(compiler = compiler.withTunables(tunables))
 
   @deprecated("Use DaffodilTDMLDFDLProcessor.setExternalDFDLVariables.", "2.6.0")
   override def setExternalDFDLVariables(externalVarBindings: Seq[Binding]): Unit =
     compiler = compiler.withExternalDFDLVariablesImpl(externalVarBindings)
 
-  override def withExternalDFDLVariables(externalVarBindings: Seq[Binding]): TDMLDFDLProcessorFactory =
+  override def withExternalDFDLVariables(externalVarBindings: Seq[Binding]): Runtime2TDMLDFDLProcessorFactory =
     copy(compiler = compiler.withExternalDFDLVariablesImpl(externalVarBindings))
 
   @deprecated("Use arguments to getProcessor()", "2.6.0")
@@ -130,10 +129,10 @@ final class TDMLDFDLProcessorFactory private(
 }
 
 /**
- * Delegates all execution, error gathering, error access to the [[Runtime2DataProcessor]].
- * The responsibility of this class is just for TDML matching up. That is dealing with TDML
- * XML Infosets, feeding to the unparser, creating XML from the result created by the
- * [[Runtime2DataProcessor]]. All the "real work" is done by [[Runtime2DataProcessor]].
+ * Delegates all execution, error gathering, error access to the Runtime2DataProcessor.
+ * The responsibility of this class is just for TDML matching up. That is dealing with
+ * TDML XML Infosets, feeding to the unparser, creating XML from the result created by
+ * the Runtime2DataProcessor. All the "real work" is done by Runtime2DataProcessor.
  */
 class Runtime2TDMLDFDLProcessor(tempDir: os.Path, executable: os.Path) extends TDMLDFDLProcessor {
 
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_parse.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_parse.dat
new file mode 100644
index 0000000..83b308f
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_parse.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
similarity index 82%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
index 9a1d4a1..01f3fd0 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
@@ -16,15 +16,13 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
+<idl:CameraState xmlns:idl="urn:idl:1.0">
   <sync0>208</sync0>
   <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
+  <id>97</id>
+  <length>5</length>
+  <zoom>10</zoom>
+  <focus>10</focus>
+  <index>0</index>
   <checksum>30149</checksum>
-</idl:Command>
+</idl:CameraState>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat
similarity index 100%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat
rename to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
similarity index 100%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.dfdl.xsd
new file mode 100644
index 0000000..c847079
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.dfdl.xsd
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext" xmlns:gma="urn:gma:1.0" targetNamespace="urn:gma:1.0">
+
+ <xs:annotation>  
+  <xs:appinfo source="http://www.ogf.org/dfdl/">   
+   <dfdl:defineVariable name="ByteOrder" type="xs:string"/>   
+   <dfdl:defineFormat name="defaults">    
+    <dfdl:format alignment="1" alignmentUnits="bits" binaryBooleanFalseRep="0" binaryBooleanTrueRep="1" binaryCalendarEpoch="1970-01-01T00:00:00+00:00" binaryCalendarRep="bcd" binaryDecimalVirtualPoint="0" binaryFloatRep="ieee" binaryNumberCheckPolicy="lax" binaryNumberRep="binary" binaryPackedSignCodes="C D F C" calendarCenturyStart="53" calendarCheckPolicy="lax" calendarDaysInFirstWeek="4" calendarFirstDayOfWeek="Monday" calendarLanguage="en-US" calendarObserveDST="yes" calendarPattern [...]
+   </dfdl:defineFormat>   
+   <dfdl:format ref="gma:defaults" byteOrder="bigEndian"/>   
+  </xs:appinfo>  
+ </xs:annotation> 
+
+ <xs:element name="GapsPDU">  
+  <xs:complexType>   
+   <xs:choice>         <!-- no way to discriminate SDHBW or SDHBE, so uncomment one -->    
+    <!-- <xs:element ref="gma:SDHBEPDU" /> -->    
+    <xs:element ref="gma:SDHBWPDU"/>    
+   </xs:choice>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="SDHBWPDU">  
+  <xs:complexType>   
+   <xs:sequence>    
+    <xs:element ref="gma:SDHBWHeader"/>    
+    <xs:element ref="gma:ApplicationData"/>    
+    <xs:element ref="gma:GapsTrailer"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="SDHBWHeader">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="tag0" type="gma:gapsuint8"/>    
+    <xs:element name="tagm" type="gma:gapsuint8"/>    
+    <xs:element name="tags" type="gma:gapsuint8"/>    
+    <xs:element name="tagt" type="gma:gapsuint8"/>    
+    <xs:element name="len" type="gma:gapsuint16"/>    
+    <xs:element name="crc" type="gma:gapsuint16"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+
+ <xs:simpleType name="gapsdouble" dfdl:lengthKind="explicit" dfdl:length="8" dfdl:lengthUnits="bytes" dfdl:byteOrder="littleEndian">  
+  <xs:restriction base="xs:double"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsfloat" dfdl:lengthKind="explicit" dfdl:length="4" dfdl:lengthUnits="bytes" dfdl:byteOrder="littleEndian">  
+  <xs:restriction base="xs:float"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint64" dfdl:lengthKind="explicit" dfdl:length="64" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedLong"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint32" dfdl:lengthKind="explicit" dfdl:length="32" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedInt"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint16" dfdl:lengthKind="explicit" dfdl:length="16" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedShort"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint8" dfdl:lengthKind="explicit" dfdl:length="8" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedByte"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint64" dfdl:lengthKind="explicit" dfdl:length="64" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:long"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint32" dfdl:lengthKind="explicit" dfdl:length="32" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:int"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint16" dfdl:lengthKind="explicit" dfdl:length="16" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:short"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint8" dfdl:lengthKind="explicit" dfdl:length="8" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:byte"/>  
+ </xs:simpleType> 
+
+ <xs:element name="GapsTrailer">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="seq" type="gma:gapsuint32"/>    
+    <xs:element name="rqr" type="gma:gapsuint32"/>    
+    <xs:element name="oid" type="gma:gapsuint32"/>    
+    <xs:element name="mid" type="gma:gapsuint16"/>    
+    <xs:element name="crc" type="gma:gapsuint16"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+ <xs:element name="ApplicationData">  
+  <xs:complexType>   
+   <xs:choice dfdl:choiceDispatchKey="{xs:string(../gma:SDHBWHeader/tagt)}">
+    <xs:element dfdl:choiceBranchKey="11" ref="gma:NextRPC"/>
+    <xs:element dfdl:choiceBranchKey="12" ref="gma:Okay"/>
+    <xs:element dfdl:choiceBranchKey="13" ref="gma:Request_echo_component_heartbeats"/>
+    <xs:element dfdl:choiceBranchKey="14" ref="gma:Response_echo_component_heartbeats"/>
+    <xs:element dfdl:choiceBranchKey="15" ref="gma:Request_echo_pnt"/>
+    <xs:element dfdl:choiceBranchKey="16" ref="gma:Response_echo_pnt"/>
+    <xs:element dfdl:choiceBranchKey="17" ref="gma:Request_echo_requestISRMDetections"/>
+    <xs:element dfdl:choiceBranchKey="18" ref="gma:Response_echo_requestISRMDetections"/>
+    <xs:element dfdl:choiceBranchKey="19" ref="gma:Request_echo_updateMissionPlan"/>
+    <xs:element dfdl:choiceBranchKey="20" ref="gma:Response_echo_updateMissionPlan"/>
+   </xs:choice>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="NextRPC">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="mux" type="gma:gapsint32"/>    
+    <xs:element name="sec" type="gma:gapsint32"/>    
+    <xs:element name="typ" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Okay">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="x" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Request_echo_component_heartbeats">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ss" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="st" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Response_echo_component_heartbeats">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ret" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Request_echo_pnt">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="alt" type="gma:gapsdouble"/>    
+    <xs:element name="lat" type="gma:gapsdouble"/>    
+    <xs:element name="lon" type="gma:gapsdouble"/>    
+    <xs:element name="time" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Response_echo_pnt">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ret" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Request_echo_requestISRMDetections">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="phase" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Response_echo_requestISRMDetections">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ret" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Request_echo_updateMissionPlan">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="missionPlanId" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="actionsActiveCnt" type="gma:gapsint32"/>    
+    <xs:element name="actionsMaxCnt" type="gma:gapsint32"/>    
+    <xs:element name="actionId0" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="actionId1" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="actionId2" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="actionType0" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="actionType1" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="actionType2" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointId0" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointId1" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointId2" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="numberOfSensorWayPoints" type="gma:gapsint32"/>    
+    <xs:element name="sensorPlanId" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="vehiclePlanId" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="numberOfWayPoints" type="gma:gapsint32"/>    
+    <xs:element name="vehiclePlanId1" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointsActiveCnt" type="gma:gapsint32"/>    
+    <xs:element name="wayPointsMaxCnt" type="gma:gapsint32"/>    
+    <xs:element name="wayPointId20" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointId21" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointId22" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointId23" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointId24" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="x" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="5" maxOccurs="5"/>    
+    <xs:element name="y" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="5" maxOccurs="5"/>    
+    <xs:element name="z" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="5" maxOccurs="5"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Response_echo_updateMissionPlan">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ret" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+</xs:schema>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.tdml
new file mode 100644
index 0000000..2917c47
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.tdml
@@ -0,0 +1,300 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<tdml:testSuite
+  defaultConfig="config-runtime2"
+  defaultImplementations="daffodil daffodil-runtime2"
+  defaultRoundTrip="none"
+  description="TDML tests for egress_xdcc_bw"
+  xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
+  xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+  xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
+
+  <tdml:defineConfig name="config-runtime1">
+    <daf:tunables>
+      <daf:tdmlImplementation>daffodil</daf:tdmlImplementation>
+    </daf:tunables>
+  </tdml:defineConfig>
+
+  <tdml:defineConfig name="config-runtime2">
+    <daf:tunables>
+      <daf:tdmlImplementation>daffodil-runtime2</daf:tdmlImplementation>
+    </daf:tunables>
+  </tdml:defineConfig>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 11"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_11"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_11.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_11.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 11"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_11"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_11.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_11.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 12"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_12"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_12.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_12.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 12"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_12"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_12.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_12.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 13"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_13"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_13.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_13.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 13"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_13"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_13.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_13.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 14"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_14"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_14.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_14.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 14"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_14"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_14.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_14.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 15"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_15"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_15.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_15.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 15"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_15"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_15.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_15.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 16"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_16"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_16.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_16.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 16"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_16"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_16.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_16.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 17"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_17"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_17.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_17.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 17"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_17"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_17.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_17.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 18"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_18"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_18.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_18.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 18"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_18"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_18.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_18.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 19"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_19"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_19.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_19.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 19"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_19"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_19.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_19.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 20"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_20"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_20.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_20.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 20"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_20"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_20.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_20.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+</tdml:testSuite>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_11.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_11.dat
new file mode 100644
index 0000000..c1ffcc0
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_11.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_12.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_12.dat
new file mode 100644
index 0000000..121889b
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_12.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_13.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_13.dat
new file mode 100644
index 0000000..b69f70a
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_13.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_14.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_14.dat
new file mode 100644
index 0000000..1ee953f
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_14.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_15.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_15.dat
new file mode 100644
index 0000000..8e0a836
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_15.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_16.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_16.dat
new file mode 100644
index 0000000..dea81cd
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_16.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_17.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_17.dat
new file mode 100644
index 0000000..95080f1
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_17.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_18.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_18.dat
new file mode 100644
index 0000000..a911bdb
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_18.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_19.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_19.dat
new file mode 100644
index 0000000..b25d46e
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_19.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_20.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_20.dat
new file mode 100644
index 0000000..f5a69c1
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_20.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_11.xml
similarity index 59%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_11.xml
index 9a1d4a1..b9470e9 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_11.xml
@@ -16,15 +16,29 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>11</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:NextRPC>
+        <mux>6</mux>
+        <sec>7</sec>
+        <typ>8</typ>
+      </gma:NextRPC>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>9</seq>
+      <rqr>10</rqr>
+      <oid>11</oid>
+      <mid>12</mid>
+      <crc>13</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_12.xml
similarity index 62%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_12.xml
index 9a1d4a1..cb39c26 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_12.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>12</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Okay>
+        <x>6</x>
+      </gma:Okay>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_13.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_13.xml
new file mode 100644
index 0000000..5255b8b
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_13.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>0</tag0>
+      <tagm>12</tagm>
+      <tags>12</tags>
+      <tagt>13</tagt>
+      <len>112</len>
+      <crc>39795</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Request_echo_component_heartbeats>
+        <ss>77</ss>
+        <ss>80</ss>
+        <ss>88</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <st>114</st>
+        <st>101</st>
+        <st>97</st>
+        <st>100</st>
+        <st>121</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+      </gma:Request_echo_component_heartbeats>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>2743063952</seq>
+      <rqr>32652</rqr>
+      <oid>5</oid>
+      <mid>0</mid>
+      <crc>0</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_14.xml
similarity index 59%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_14.xml
index 9a1d4a1..43927ab 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_14.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>14</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Response_echo_component_heartbeats>
+        <ret>6</ret>
+      </gma:Response_echo_component_heartbeats>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_15.xml
similarity index 55%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_15.xml
index 0307283..51edd01 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_15.xml
@@ -16,22 +16,30 @@
   limitations under the License.
 -->
 
-<idl:VideoSettings xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>98</id>
-  <length>14</length>
-  <destIp>
-    <item>1</item>
-    <item>2</item>
-    <item>3</item>
-    <item>4</item>
-  </destIp>
-  <port>8080</port>
-  <bitrate>0</bitrate>
-  <ttl>0</ttl>
-  <streamType>0</streamType>
-  <mjpegQuality>0</mjpegQuality>
-  <saveSettingsAndTsPacketCount>0</saveSettingsAndTsPacketCount>
-  <checksum>3073</checksum>
-</idl:VideoSettings>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>0</tag0>
+      <tagm>12</tagm>
+      <tags>12</tags>
+      <tagt>15</tagt>
+      <len>44</len>
+      <crc>46626</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Request_echo_pnt>
+        <alt>0.10000000000000001</alt>
+        <lat>29.50464225007952</lat>
+        <lon>-116.00761807405785</lon>
+        <time>1611604087</time>
+      </gma:Request_echo_pnt>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>0</seq>
+      <rqr>2415922672</rqr>
+      <oid>32652</oid>
+      <mid>0</mid>
+      <crc>0</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_16.xml
similarity index 60%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_16.xml
index 9a1d4a1..dc3838a 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_16.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>16</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Response_echo_pnt>
+        <ret>6</ret>
+      </gma:Response_echo_pnt>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_17.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_17.xml
new file mode 100644
index 0000000..89cbd87
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_17.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>0</tag0>
+      <tagm>12</tagm>
+      <tags>12</tags>
+      <tagt>17</tagt>
+      <len>48</len>
+      <crc>63809</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Request_echo_requestISRMDetections>
+        <phase>102</phase>
+        <phase>105</phase>
+        <phase>110</phase>
+        <phase>100</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+      </gma:Request_echo_requestISRMDetections>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>4</seq>
+      <rqr>0</rqr>
+      <oid>1684957542</oid>
+      <mid>0</mid>
+      <crc>0</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_18.xml
similarity index 59%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_18.xml
index 9a1d4a1..0351bf4 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_18.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>18</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Response_echo_requestISRMDetections>
+        <ret>6</ret>
+      </gma:Response_echo_requestISRMDetections>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_19.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_19.xml
new file mode 100644
index 0000000..8322148
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_19.xml
@@ -0,0 +1,638 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>0</tag0>
+      <tagm>12</tagm>
+      <tags>12</tags>
+      <tagt>19</tagt>
+      <len>736</len>
+      <crc>43460</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Request_echo_updateMissionPlan>
+        <missionPlanId>105</missionPlanId>
+        <missionPlanId>100</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <actionsActiveCnt>2</actionsActiveCnt>
+        <actionsMaxCnt>3</actionsMaxCnt>
+        <actionId0>97</actionId0>
+        <actionId0>99</actionId0>
+        <actionId0>49</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId1>97</actionId1>
+        <actionId1>99</actionId1>
+        <actionId1>50</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionType0>102</actionType0>
+        <actionType0>105</actionType0>
+        <actionType0>110</actionType0>
+        <actionType0>100</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType1>102</actionType1>
+        <actionType1>105</actionType1>
+        <actionType1>120</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <wayPointId0>119</wayPointId0>
+        <wayPointId0>112</wayPointId0>
+        <wayPointId0>49</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId1>119</wayPointId1>
+        <wayPointId1>112</wayPointId1>
+        <wayPointId1>50</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <numberOfSensorWayPoints>1</numberOfSensorWayPoints>
+        <sensorPlanId>105</sensorPlanId>
+        <sensorPlanId>100</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <vehiclePlanId>105</vehiclePlanId>
+        <vehiclePlanId>100</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <numberOfWayPoints>3</numberOfWayPoints>
+        <vehiclePlanId1>105</vehiclePlanId1>
+        <vehiclePlanId1>100</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <wayPointsActiveCnt>4</wayPointsActiveCnt>
+        <wayPointsMaxCnt>5</wayPointsMaxCnt>
+        <wayPointId20>119</wayPointId20>
+        <wayPointId20>112</wayPointId20>
+        <wayPointId20>48</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId21>119</wayPointId21>
+        <wayPointId21>112</wayPointId21>
+        <wayPointId21>49</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId22>119</wayPointId22>
+        <wayPointId22>112</wayPointId22>
+        <wayPointId22>50</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId23>119</wayPointId23>
+        <wayPointId23>112</wayPointId23>
+        <wayPointId23>51</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId24>96</wayPointId24>
+        <wayPointId24>69</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>-116</wayPointId24>
+        <wayPointId24>-116</wayPointId24>
+        <wayPointId24>127</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>80</wayPointId24>
+        <wayPointId24>69</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>-116</wayPointId24>
+        <wayPointId24>-116</wayPointId24>
+        <wayPointId24>127</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <x>29.800000000000001</x>
+        <x>30</x>
+        <x>30.300000000000001</x>
+        <x>30.5</x>
+        <x>-1</x>
+        <y>-116.5</y>
+        <y>-117</y>
+        <y>-117.5</y>
+        <y>-117.7</y>
+        <y>-2.2392049343947951E+307</y>
+        <z>0.10000000000000001</z>
+        <z>0.20000000000000001</z>
+        <z>0.29999999999999999</z>
+        <z>0.40000000000000002</z>
+        <z>-2.2392049343935337E+307</z>
+      </gma:Request_echo_updateMissionPlan>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>25705</seq>
+      <rqr>0</rqr>
+      <oid>0</oid>
+      <mid>0</mid>
+      <crc>0</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_20.xml
similarity index 59%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_20.xml
index 9a1d4a1..484a0cd 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_20.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>20</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Response_echo_updateMissionPlan>
+        <ret>6</ret>
+      </gma:Response_echo_updateMissionPlan>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.dfdl.xsd
new file mode 100644
index 0000000..3460b20
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.dfdl.xsd
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext" xmlns:gma="urn:gma:1.0" targetNamespace="urn:gma:1.0"> 
+
+ <xs:annotation>  
+  <xs:appinfo source="http://www.ogf.org/dfdl/">   
+   <dfdl:defineVariable name="ByteOrder" type="xs:string"/>   
+   <dfdl:defineFormat name="defaults">    
+    <dfdl:format alignment="1" alignmentUnits="bits" binaryBooleanFalseRep="0" binaryBooleanTrueRep="1" binaryCalendarEpoch="1970-01-01T00:00:00+00:00" binaryCalendarRep="bcd" binaryDecimalVirtualPoint="0" binaryFloatRep="ieee" binaryNumberCheckPolicy="lax" binaryNumberRep="binary" binaryPackedSignCodes="C D F C" calendarCenturyStart="53" calendarCheckPolicy="lax" calendarDaysInFirstWeek="4" calendarFirstDayOfWeek="Monday" calendarLanguage="en-US" calendarObserveDST="yes" calendarPattern [...]
+   </dfdl:defineFormat>   
+   <dfdl:format ref="gma:defaults" byteOrder="bigEndian"/>   
+  </xs:appinfo>  
+ </xs:annotation> 
+
+ <xs:element name="GapsPDU">  
+  <xs:complexType>   
+   <xs:choice>         <!-- no way to discriminate SDHBW or SDHBE, so uncomment one -->    
+    <!-- <xs:element ref="gma:SDHBEPDU" /> -->    
+    <xs:element ref="gma:SDHBWPDU"/>    
+   </xs:choice>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="SDHBWPDU">  
+  <xs:complexType>   
+   <xs:sequence>    
+    <xs:element ref="gma:SDHBWHeader"/>    
+    <xs:element ref="gma:ApplicationData"/>    
+    <xs:element ref="gma:GapsTrailer"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="SDHBWHeader">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="tag0" type="gma:gapsuint8"/>    
+    <xs:element name="tagm" type="gma:gapsuint8"/>    
+    <xs:element name="tags" type="gma:gapsuint8"/>    
+    <xs:element name="tagt" type="gma:gapsuint8"/>    
+    <xs:element name="len" type="gma:gapsuint16"/>    
+    <xs:element name="crc" type="gma:gapsuint16"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+
+ <xs:simpleType name="gapsdouble" dfdl:lengthKind="explicit" dfdl:length="8" dfdl:lengthUnits="bytes" dfdl:byteOrder="littleEndian">  
+  <xs:restriction base="xs:double"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsfloat" dfdl:lengthKind="explicit" dfdl:length="4" dfdl:lengthUnits="bytes" dfdl:byteOrder="littleEndian">  
+  <xs:restriction base="xs:float"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint64" dfdl:lengthKind="explicit" dfdl:length="64" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedLong"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint32" dfdl:lengthKind="explicit" dfdl:length="32" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedInt"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint16" dfdl:lengthKind="explicit" dfdl:length="16" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedShort"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint8" dfdl:lengthKind="explicit" dfdl:length="8" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedByte"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint64" dfdl:lengthKind="explicit" dfdl:length="64" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:long"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint32" dfdl:lengthKind="explicit" dfdl:length="32" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:int"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint16" dfdl:lengthKind="explicit" dfdl:length="16" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:short"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint8" dfdl:lengthKind="explicit" dfdl:length="8" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:byte"/>  
+ </xs:simpleType> 
+
+ <xs:element name="GapsTrailer">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="seq" type="gma:gapsuint32"/>    
+    <xs:element name="rqr" type="gma:gapsuint32"/>    
+    <xs:element name="oid" type="gma:gapsuint32"/>    
+    <xs:element name="mid" type="gma:gapsuint16"/>    
+    <xs:element name="crc" type="gma:gapsuint16"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+ <xs:element name="ApplicationData">  
+  <xs:complexType>   
+   <xs:choice dfdl:choiceDispatchKey="{xs:string(../gma:SDHBWHeader/tagt)}">
+    <xs:element dfdl:choiceBranchKey="111" ref="gma:NextRPC"/>
+    <xs:element dfdl:choiceBranchKey="112" ref="gma:Okay"/>
+    <xs:element dfdl:choiceBranchKey="113" ref="gma:Request_echo_component_heartbeats"/>
+    <xs:element dfdl:choiceBranchKey="114" ref="gma:Response_echo_component_heartbeats"/>
+    <xs:element dfdl:choiceBranchKey="115" ref="gma:Request_echo_recieveISRMDetections"/>
+    <xs:element dfdl:choiceBranchKey="116" ref="gma:Response_echo_recieveISRMDetections"/>
+   </xs:choice>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="NextRPC">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="mux" type="gma:gapsint32"/>    
+    <xs:element name="sec" type="gma:gapsint32"/>    
+    <xs:element name="typ" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Okay">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="x" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Request_echo_component_heartbeats">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ss" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="st" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Response_echo_component_heartbeats">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ret" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Request_echo_recieveISRMDetections">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="detectsActiveCnt" type="gma:gapsint32"/>    
+    <xs:element name="detectsMaxCnt" type="gma:gapsint32"/>    
+    <xs:element name="TGT_ISRM_ID0" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="TGT_ISRM_ID1" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="TGT_ISRM_ID2" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="TGT_ISRM_ID3" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="TGT_ISRM_ID4" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="TGT_ISRM_ID5" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="TGT_ISRM_ID6" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="TGT_ISRM_ID7" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="alt" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="8" maxOccurs="8"/>    
+    <xs:element name="bearing" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="8" maxOccurs="8"/>    
+    <xs:element name="classification0" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="classification1" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="classification2" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="classification3" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="classification4" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="classification5" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="classification6" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="classification7" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="confidence" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="8" maxOccurs="8"/>    
+    <xs:element name="lat" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="8" maxOccurs="8"/>    
+    <xs:element name="lon" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="8" maxOccurs="8"/>    
+    <xs:element name="speed" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="8" maxOccurs="8"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Response_echo_recieveISRMDetections">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ret" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+</xs:schema>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.tdml
new file mode 100644
index 0000000..9fbadfd
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.tdml
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<tdml:testSuite
+  defaultConfig="config-runtime2"
+  defaultImplementations="daffodil daffodil-runtime2"
+  defaultRoundTrip="none"
+  description="TDML tests for ingress_xdcc_bw"
+  xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
+  xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+  xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
+
+  <tdml:defineConfig name="config-runtime1">
+    <daf:tunables>
+      <daf:tdmlImplementation>daffodil</daf:tdmlImplementation>
+    </daf:tunables>
+  </tdml:defineConfig>
+
+  <tdml:defineConfig name="config-runtime2">
+    <daf:tunables>
+      <daf:tdmlImplementation>daffodil-runtime2</daf:tdmlImplementation>
+    </daf:tunables>
+  </tdml:defineConfig>
+
+  <tdml:parserTestCase
+    description="ingress_xdcc_bw parse test 111"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_parse_111"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_111.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_111.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="ingress_xdcc_bw unparse test 111"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_unparse_111"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_111.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_111.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="ingress_xdcc_bw parse test 112"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_parse_112"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_112.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_112.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="ingress_xdcc_bw unparse test 112"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_unparse_112"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_112.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_112.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="ingress_xdcc_bw parse test 113"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_parse_113"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_113.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_113.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="ingress_xdcc_bw unparse test 113"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_unparse_113"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_113.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_113.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="ingress_xdcc_bw parse test 114"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_parse_114"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_114.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_114.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="ingress_xdcc_bw unparse test 114"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_unparse_114"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_114.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_114.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="ingress_xdcc_bw parse test 115"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_parse_115"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_115.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_115.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="ingress_xdcc_bw unparse test 115"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_unparse_115"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_115.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_115.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="ingress_xdcc_bw parse test 116"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_parse_116"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_116.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_116.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="ingress_xdcc_bw unparse test 116"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_unparse_116"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_116.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_116.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+</tdml:testSuite>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_111.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_111.dat
new file mode 100644
index 0000000..db1d6df
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_111.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_112.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_112.dat
new file mode 100644
index 0000000..98e6287
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_112.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_113.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_113.dat
new file mode 100644
index 0000000..233baae
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_113.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_114.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_114.dat
new file mode 100644
index 0000000..b24e8d4
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_114.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_115.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_115.dat
new file mode 100644
index 0000000..b3e5ce3
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_115.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_116.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_116.dat
new file mode 100644
index 0000000..c2dcc79
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_116.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_111.xml
similarity index 59%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_111.xml
index 9a1d4a1..8c085be 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_111.xml
@@ -16,15 +16,29 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>111</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:NextRPC>
+        <mux>6</mux>
+        <sec>7</sec>
+        <typ>8</typ>
+      </gma:NextRPC>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>9</seq>
+      <rqr>10</rqr>
+      <oid>11</oid>
+      <mid>12</mid>
+      <crc>13</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_112.xml
similarity index 62%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_112.xml
index 9a1d4a1..fc690e8 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_112.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>112</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Okay>
+        <x>6</x>
+      </gma:Okay>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_113.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_113.xml
new file mode 100644
index 0000000..2585bac
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_113.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>0</tag0>
+      <tagm>111</tagm>
+      <tags>111</tags>
+      <tagt>113</tagt>
+      <len>112</len>
+      <crc>48734</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Request_echo_component_heartbeats>
+        <ss>82</ss>
+        <ss>68</ss>
+        <ss>82</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <st>114</st>
+        <st>101</st>
+        <st>97</st>
+        <st>100</st>
+        <st>121</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+      </gma:Request_echo_component_heartbeats>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>4076848528</seq>
+      <rqr>32610</rqr>
+      <oid>5</oid>
+      <mid>0</mid>
+      <crc>0</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_114.xml
similarity index 59%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_114.xml
index 9a1d4a1..e1457db 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_114.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>114</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Response_echo_component_heartbeats>
+        <ret>6</ret>
+      </gma:Response_echo_component_heartbeats>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_115.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_115.xml
new file mode 100644
index 0000000..c84d1dd
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_115.xml
@@ -0,0 +1,859 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>0</tag0>
+      <tagm>111</tagm>
+      <tags>111</tags>
+      <tagt>115</tagt>
+      <len>1176</len>
+      <crc>1984</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Request_echo_recieveISRMDetections>
+        <detectsActiveCnt>2</detectsActiveCnt>
+        <detectsMaxCnt>8</detectsMaxCnt>
+        <TGT_ISRM_ID0>49</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>55</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>53</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>57</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>56</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>48</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID1>52</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>50</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>50</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>56</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>55</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>50</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <alt>0</alt>
+        <alt>0</alt>
+        <alt>-2.2363310143334415E+307</alt>
+        <alt>-2.236435215127047E+307</alt>
+        <alt>-2.2363310143043182E+307</alt>
+        <alt>-1.5966722476277758E+293</alt>
+        <alt>-2.2363220410727081E+307</alt>
+        <alt>-2.2363310143063459E+307</alt>
+        <bearing>-1</bearing>
+        <bearing>-1</bearing>
+        <bearing>-2.2363310143048291E+307</bearing>
+        <bearing>-3.3189020416553621E+148</bearing>
+        <bearing>0</bearing>
+        <bearing>-5.1093511924088827E+294</bearing>
+        <bearing>-2.2363310143043182E+307</bearing>
+        <bearing>-7.0592328879678846E+299</bearing>
+        <classification0>99</classification0>
+        <classification0>97</classification0>
+        <classification0>114</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification1>112</classification1>
+        <classification1>101</classification1>
+        <classification1>114</classification1>
+        <classification1>115</classification1>
+        <classification1>111</classification1>
+        <classification1>110</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>-128</classification3>
+        <classification3>119</classification3>
+        <classification3>58</classification3>
+        <classification3>61</classification3>
+        <classification3>100</classification3>
+        <classification3>127</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>46</classification3>
+        <classification3>115</classification3>
+        <classification3>112</classification3>
+        <classification3>101</classification3>
+        <classification3>101</classification3>
+        <classification3>100</classification3>
+        <classification3>100</classification3>
+        <classification3>101</classification3>
+        <classification3>110</classification3>
+        <classification3>99</classification3>
+        <classification3>101</classification3>
+        <classification3>116</classification3>
+        <classification3>105</classification3>
+        <classification3>111</classification3>
+        <classification3>110</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification4>-32</classification4>
+        <classification4>49</classification4>
+        <classification4>0</classification4>
+        <classification4>-104</classification4>
+        <classification4>98</classification4>
+        <classification4>127</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>-48</classification4>
+        <classification4>49</classification4>
+        <classification4>0</classification4>
+        <classification4>-104</classification4>
+        <classification4>98</classification4>
+        <classification4>127</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>45</classification4>
+        <classification4>49</classification4>
+        <classification4>46</classification4>
+        <classification4>48</classification4>
+        <classification4>46</classification4>
+        <classification4>49</classification4>
+        <classification4>51</classification4>
+        <classification4>56</classification4>
+        <classification4>51</classification4>
+        <classification4>55</classification4>
+        <classification4>52</classification4>
+        <classification4>52</classification4>
+        <classification4>52</classification4>
+        <classification4>51</classification4>
+        <classification4>49</classification4>
+        <classification4>50</classification4>
+        <classification4>56</classification4>
+        <classification4>48</classification4>
+        <classification4>49</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>127</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>32</classification5>
+        <classification5>-109</classification5>
+        <classification5>127</classification5>
+        <classification5>-71</classification5>
+        <classification5>-1</classification5>
+        <classification5>-1</classification5>
+        <classification5>-1</classification5>
+        <classification5>-1</classification5>
+        <classification5>-48</classification5>
+        <classification5>-106</classification5>
+        <classification5>127</classification5>
+        <classification5>-71</classification5>
+        <classification5>98</classification5>
+        <classification5>127</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>96</classification5>
+        <classification5>-106</classification5>
+        <classification5>127</classification5>
+        <classification5>-71</classification5>
+        <classification5>98</classification5>
+        <classification5>127</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>-32</classification5>
+        <classification5>49</classification5>
+        <classification5>0</classification5>
+        <classification5>-104</classification5>
+        <classification5>98</classification5>
+        <classification5>127</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>-48</classification5>
+        <classification5>49</classification5>
+        <classification5>0</classification5>
+        <classification5>-104</classification5>
+        <classification5>98</classification5>
+        <classification5>127</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification6>-40</classification6>
+        <classification6>-30</classification6>
+        <classification6>82</classification6>
+        <classification6>62</classification6>
+        <classification6>100</classification6>
+        <classification6>127</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>-96</classification6>
+        <classification6>-109</classification6>
+        <classification6>127</classification6>
+        <classification6>-71</classification6>
+        <classification6>98</classification6>
+        <classification6>127</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>80</classification6>
+        <classification6>-109</classification6>
+        <classification6>127</classification6>
+        <classification6>-71</classification6>
+        <classification6>98</classification6>
+        <classification6>127</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>-62</classification6>
+        <classification6>35</classification6>
+        <classification6>122</classification6>
+        <classification6>62</classification6>
+        <classification6>100</classification6>
+        <classification6>127</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>96</classification6>
+        <classification6>118</classification6>
+        <classification6>67</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>-96</classification6>
+        <classification6>-109</classification6>
+        <classification6>127</classification6>
+        <classification6>-71</classification6>
+        <classification6>98</classification6>
+        <classification6>127</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>64</classification6>
+        <classification6>-106</classification6>
+        <classification6>127</classification6>
+        <classification6>-71</classification6>
+        <classification6>98</classification6>
+        <classification6>127</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>23</classification6>
+        <classification6>37</classification6>
+        <classification6>122</classification6>
+        <classification6>62</classification6>
+        <classification6>100</classification6>
+        <classification6>127</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification7>-48</classification7>
+        <classification7>-106</classification7>
+        <classification7>127</classification7>
+        <classification7>-71</classification7>
+        <classification7>98</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <classification7>-88</classification7>
+        <classification7>-109</classification7>
+        <classification7>127</classification7>
+        <classification7>-71</classification7>
+        <classification7>98</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <classification7>16</classification7>
+        <classification7>-109</classification7>
+        <classification7>127</classification7>
+        <classification7>-71</classification7>
+        <classification7>98</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <classification7>80</classification7>
+        <classification7>35</classification7>
+        <classification7>122</classification7>
+        <classification7>62</classification7>
+        <classification7>100</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <classification7>-112</classification7>
+        <classification7>42</classification7>
+        <classification7>0</classification7>
+        <classification7>-104</classification7>
+        <classification7>98</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <classification7>-96</classification7>
+        <classification7>-109</classification7>
+        <classification7>127</classification7>
+        <classification7>-71</classification7>
+        <classification7>98</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <classification7>48</classification7>
+        <classification7>-109</classification7>
+        <classification7>127</classification7>
+        <classification7>-71</classification7>
+        <classification7>98</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <classification7>112</classification7>
+        <classification7>35</classification7>
+        <classification7>122</classification7>
+        <classification7>62</classification7>
+        <classification7>100</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <confidence>0.8304254412651062</confidence>
+        <confidence>0.84350341558456421</confidence>
+        <confidence>-2.236331014302019E+307</confidence>
+        <confidence>0</confidence>
+        <confidence>-2.2363310143025299E+307</confidence>
+        <confidence>-7.0592328879678846E+299</confidence>
+        <confidence>-2.2364351717587783E+307</confidence>
+        <confidence>-2.236435215244131E+307</confidence>
+        <lat>32.730128382409546</lat>
+        <lat>30.730832492300745</lat>
+        <lat>0</lat>
+        <lat>-2.229577558811266E+307</lat>
+        <lat>-2.2363220410652995E+307</lat>
+        <lat>-2.2363310143107049E+307</lat>
+        <lat>-2.236331014301508E+307</lat>
+        <lat>-2.236435213899717E+307</lat>
+        <lon>-117.14324935960397</lon>
+        <lon>-117.13837444312801</lon>
+        <lon>-2.2363310143002307E+307</lon>
+        <lon>-2.2364352132486419E+307</lon>
+        <lon>-1</lon>
+        <lon>-2.2363310143107049E+307</lon>
+        <lon>-2.3316027292373177E+304</lon>
+        <lon>-3.3189020416553621E+148</lon>
+        <speed>-1</speed>
+        <speed>-1</speed>
+        <speed>-2.2363310143109603E+307</speed>
+        <speed>-2.2363220410729635E+307</speed>
+        <speed>-2.2363310142994643E+307</speed>
+        <speed>-2.2364352136680718E+307</speed>
+        <speed>-1</speed>
+        <speed>-2.2363310143107049E+307</speed>
+      </gma:Request_echo_recieveISRMDetections>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>0</seq>
+      <rqr>0</rqr>
+      <oid>0</oid>
+      <mid>0</mid>
+      <crc>0</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_116.xml
similarity index 59%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
rename to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_116.xml
index 9a1d4a1..b7010c5 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_116.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>116</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Response_echo_recieveISRMDetections>
+        <ret>6</ret>
+      </gma:Response_echo_recieveISRMDetections>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd
new file mode 100644
index 0000000..4034d39
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:idl="urn:idl:1.0" targetNamespace="urn:idl:1.0">
+  <xs:annotation>
+    <xs:appinfo source="http://www.ogf.org/dfdl/">
+      <dfdl:defineFormat name="defaults">
+        <dfdl:format alignment="8" alignmentUnits="bits" binaryBooleanFalseRep="0" binaryBooleanTrueRep="1" binaryFloatRep="ieee" binaryNumberCheckPolicy="lax" binaryNumberRep="binary" bitOrder="mostSignificantBitFirst" byteOrder="bigEndian" choiceLengthKind="implicit" encoding="utf-8" encodingErrorPolicy="replace" escapeSchemeRef="" fillByte="%#r20;" floating="no" ignoreCase="no" initiatedContent="no" initiator="" leadingSkip="0" lengthKind="implicit" lengthUnits="bits" occursCountKind= [...]
+      </dfdl:defineFormat>
+      <dfdl:format ref="idl:defaults"/>
+    </xs:appinfo>
+  </xs:annotation>
+  <xs:simpleType name="int8" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:byte"/>
+  </xs:simpleType>
+  <xs:simpleType name="int16" dfdl:length="16" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:short"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint8" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedByte"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint16" dfdl:length="16" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedShort"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint32" dfdl:length="32" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedInt"/>
+  </xs:simpleType>
+  <xs:complexType name="CommandType">
+    <xs:sequence>
+      <xs:element name="sync0" fixed="208" type="idl:uint8"/>
+      <xs:element name="sync1" fixed="13" type="idl:uint8"/>
+      <xs:element name="id" fixed="1" type="idl:uint8"/>
+      <xs:element name="length" fixed="7" type="idl:uint8"/>
+      <xs:element name="pan" type="idl:int16"/>
+      <xs:element name="tilt">
+        <xs:simpleType>
+          <xs:restriction base="idl:int16">
+            <xs:minInclusive value="-1396"/>
+            <xs:maxInclusive value="733"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:element>
+      <xs:element name="mode" fixed="80" type="idl:uint8"/>
+      <xs:element name="stabilized" fixed="0" type="idl:uint8"/>
+      <xs:element name="impulse" fixed="0" type="idl:uint8"/>
+      <xs:element name="checksum" type="idl:uint16"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="Command" type="idl:CommandType"/>
+  <xs:complexType name="CameraStateType">
+    <xs:sequence>
+      <xs:element name="sync0" fixed="208" type="idl:uint8"/>
+      <xs:element name="sync1" fixed="13" type="idl:uint8"/>
+      <xs:element name="id" fixed="97" type="idl:uint8"/>
+      <xs:element name="length" fixed="5" type="idl:uint8"/>
+      <xs:element name="zoom" type="idl:int16"/>
+      <xs:element name="focus" type="idl:int16"/>
+      <xs:element name="index" fixed="0" type="idl:uint8"/>
+      <xs:element name="checksum" type="idl:uint16"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="CameraState" type="idl:CameraStateType"/>
+  <xs:complexType name="VideoSettingsType">
+    <xs:sequence>
+      <xs:element name="sync0" fixed="208" type="idl:uint8"/>
+      <xs:element name="sync1" fixed="13" type="idl:uint8"/>
+      <xs:element name="id" fixed="98" type="idl:uint8"/>
+      <xs:element name="length" fixed="14" type="idl:uint8"/>
+      <xs:element name="destIp">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="item" minOccurs="4" maxOccurs="4" dfdl:occursCountKind="fixed" type="idl:uint8"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+      <xs:element name="port" type="idl:uint16"/>
+      <xs:element name="bitrate" fixed="0" type="idl:uint32"/>
+      <xs:element name="ttl" fixed="0" type="idl:int8"/>
+      <xs:element name="streamType" fixed="0" type="idl:uint8"/>
+      <xs:element name="mjpegQuality" fixed="0" type="idl:uint8"/>
+      <xs:element name="saveSettingsAndTsPacketCount" fixed="0" type="idl:uint8"/>
+      <xs:element name="checksum" type="idl:uint16"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="VideoSettings" type="idl:VideoSettingsType"/>
+</xs:schema>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
similarity index 78%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
rename to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
index 110322d..4b44391 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
@@ -19,7 +19,7 @@
 <tdml:testSuite
   defaultConfig="config-runtime2"
   defaultImplementations="daffodil daffodil-runtime2"
-  defaultRoundTrip="onePass"
+  defaultRoundTrip="none"
   description="TDML tests for orion-command"
   xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
   xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
@@ -38,6 +38,32 @@
   </tdml:defineConfig>
 
   <tdml:parserTestCase
+    description="orion-command CameraState parse test"
+    model="orion-command.dfdl.xsd"
+    name="camera_state_parse"
+    root="CameraState">
+    <tdml:document>
+      <tdml:documentPart type="file">camera_state_parse.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">camera_state_unparse.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="orion-command CameraState unparse test"
+    model="orion-command.dfdl.xsd"
+    name="camera_state_unparse"
+    root="CameraState">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">camera_state_unparse.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">camera_state_parse.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
     description="orion-command Command parse test"
     model="orion-command.dfdl.xsd"
     name="command_parse"
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat
similarity index 100%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat
rename to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
similarity index 100%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
rename to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice-unparse2.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice-unparse2.tdml
index 921ee19..6939000 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice-unparse2.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice-unparse2.tdml
@@ -24,7 +24,7 @@
   xmlns:fn="http://www.w3.org/2005/xpath-functions" 
   xmlns:ex="http://example.com">
 
-  <tdml:defineSchema name="c" elementFormDefault="unqualified">
+  <tdml:defineSchema name="c1" elementFormDefault="unqualified">
     
     <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
     <dfdl:format ref="ex:GeneralFormat" lengthKind="delimited"/>
@@ -48,7 +48,7 @@
 
 
     
-<tdml:unparserTestCase name="choice_with_array_branch1" root="e" model="c">
+<tdml:unparserTestCase name="choice_with_array_branch1" root="e" model="c1">
 
   <tdml:document>1;</tdml:document>
 
@@ -62,7 +62,7 @@
   
 </tdml:unparserTestCase>
 
-<tdml:unparserTestCase name="choice_with_array_branch2" root="e" model="c">
+<tdml:unparserTestCase name="choice_with_array_branch2" root="e" model="c1">
 
   <tdml:document>1;2;</tdml:document>
 
@@ -77,7 +77,7 @@
   
 </tdml:unparserTestCase>
 
-<tdml:unparserTestCase name="choice_with_array_branch3" root="e" model="c">
+<tdml:unparserTestCase name="choice_with_array_branch3" root="e" model="c1">
 
   <tdml:document>b</tdml:document>
 
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestEgressXdccBw.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestEgressXdccBw.scala
new file mode 100644
index 0000000..9865d40
--- /dev/null
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestEgressXdccBw.scala
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.runtime2
+
+import org.apache.daffodil.tdml.Runner
+import org.junit.AfterClass
+import org.junit.Test
+
+object TestEgressXdccBw {
+  val testDir = "/org/apache/daffodil/runtime2/"
+  val runner = Runner(testDir, "egress_xdcc_bw.tdml")
+
+  @AfterClass def shutDown(): Unit = { runner.reset }
+}
+
+class TestEgressXdccBw {
+  import TestEgressXdccBw._
+
+  @Test def test_egress_xdcc_bw_parse_11(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_11") }
+  @Test def test_egress_xdcc_bw_unparse_11(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_11") }
+  @Test def test_egress_xdcc_bw_parse_12(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_12") }
+  @Test def test_egress_xdcc_bw_unparse_12(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_12") }
+  @Test def test_egress_xdcc_bw_parse_13(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_13") }
+  @Test def test_egress_xdcc_bw_unparse_13(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_13") }
+  @Test def test_egress_xdcc_bw_parse_14(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_14") }
+  @Test def test_egress_xdcc_bw_unparse_14(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_14") }
+  @Test def test_egress_xdcc_bw_parse_15(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_15") }
+  @Test def test_egress_xdcc_bw_unparse_15(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_15") }
+  @Test def test_egress_xdcc_bw_parse_16(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_16") }
+  @Test def test_egress_xdcc_bw_unparse_16(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_16") }
+  @Test def test_egress_xdcc_bw_parse_17(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_17") }
+  @Test def test_egress_xdcc_bw_unparse_17(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_17") }
+  @Test def test_egress_xdcc_bw_parse_18(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_18") }
+  @Test def test_egress_xdcc_bw_unparse_18(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_18") }
+  @Test def test_egress_xdcc_bw_parse_19(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_19") }
+  @Test def test_egress_xdcc_bw_unparse_19(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_19") }
+  @Test def test_egress_xdcc_bw_parse_20(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_20") }
+  @Test def test_egress_xdcc_bw_unparse_20(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_20") }
+}
diff --git a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala
similarity index 67%
copy from daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
copy to daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala
index 719acae..ba5a060 100644
--- a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala
@@ -21,18 +21,18 @@ import org.junit.Test
 import org.apache.daffodil.tdml.Runner
 import org.junit.AfterClass
 
-object TestRuntime2 {
+object TestExNums {
   val testDir = "/org/apache/daffodil/runtime2/"
-  val runner = Runner(testDir, "TestRuntime2.tdml")
+  val runner = Runner(testDir, "ex_nums.tdml")
 
   @AfterClass def shutDown(): Unit = { runner.reset }
 }
 
-class TestRuntime2 {
-  import TestRuntime2._
+class TestExNums {
+  import TestExNums._
 
-  @Test def test_ex_nums_parse1(): Unit = { runner.runOneTest("ex_nums_parse1") }
-  @Test def test_ex_nums_unparse1(): Unit = { runner.runOneTest("ex_nums_unparse1") }
-  @Test def test_ex_nums_parse2(): Unit = { runner.runOneTest("ex_nums_parse2") }
-  @Test def test_ex_nums_unparse2(): Unit = { runner.runOneTest("ex_nums_unparse2") }
+  @Test def test_ex_nums_parse_runtime1(): Unit = { runner.runOneTest("ex_nums_parse_runtime1") }
+  @Test def test_ex_nums_unparse_runtime1(): Unit = { runner.runOneTest("ex_nums_unparse_runtime1") }
+  @Test def test_ex_nums_parse_runtime2(): Unit = { runner.runOneTest("ex_nums_parse_runtime2") }
+  @Test def test_ex_nums_unparse_runtime2(): Unit = { runner.runOneTest("ex_nums_unparse_runtime2") }
 }
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestIngressXdccBw.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestIngressXdccBw.scala
new file mode 100644
index 0000000..f612f17
--- /dev/null
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestIngressXdccBw.scala
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information ringarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.runtime2
+
+import org.apache.daffodil.tdml.Runner
+import org.junit.AfterClass
+import org.junit.Test
+
+object TestIngressXdccBw {
+  val testDir = "/org/apache/daffodil/runtime2/"
+  val runner = Runner(testDir, "ingress_xdcc_bw.tdml")
+
+  @AfterClass def shutDown(): Unit = { runner.reset }
+}
+
+class TestIngressXdccBw {
+  import TestIngressXdccBw._
+
+  @Test def test_ingress_xdcc_bw_parse_111(): Unit = { runner.runOneTest("ingress_xdcc_bw_parse_111") }
+  @Test def test_ingress_xdcc_bw_unparse_111(): Unit = { runner.runOneTest("ingress_xdcc_bw_unparse_111") }
+  @Test def test_ingress_xdcc_bw_parse_112(): Unit = { runner.runOneTest("ingress_xdcc_bw_parse_112") }
+  @Test def test_ingress_xdcc_bw_unparse_112(): Unit = { runner.runOneTest("ingress_xdcc_bw_unparse_112") }
+  @Test def test_ingress_xdcc_bw_parse_113(): Unit = { runner.runOneTest("ingress_xdcc_bw_parse_113") }
+  @Test def test_ingress_xdcc_bw_unparse_113(): Unit = { runner.runOneTest("ingress_xdcc_bw_unparse_113") }
+  @Test def test_ingress_xdcc_bw_parse_114(): Unit = { runner.runOneTest("ingress_xdcc_bw_parse_114") }
+  @Test def test_ingress_xdcc_bw_unparse_114(): Unit = { runner.runOneTest("ingress_xdcc_bw_unparse_114") }
+  @Test def test_ingress_xdcc_bw_parse_115(): Unit = { runner.runOneTest("ingress_xdcc_bw_parse_115") }
+  @Test def test_ingress_xdcc_bw_unparse_115(): Unit = { runner.runOneTest("ingress_xdcc_bw_unparse_115") }
+  @Test def test_ingress_xdcc_bw_parse_116(): Unit = { runner.runOneTest("ingress_xdcc_bw_parse_116") }
+  @Test def test_ingress_xdcc_bw_unparse_116(): Unit = { runner.runOneTest("ingress_xdcc_bw_unparse_116") }
+}
diff --git a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestNested.scala
similarity index 60%
rename from daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
rename to daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestNested.scala
index 719acae..08201e2 100644
--- a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestNested.scala
@@ -17,22 +17,24 @@
 
 package org.apache.daffodil.runtime2
 
-import org.junit.Test
 import org.apache.daffodil.tdml.Runner
 import org.junit.AfterClass
+import org.junit.Test
 
-object TestRuntime2 {
+object TestNested {
   val testDir = "/org/apache/daffodil/runtime2/"
-  val runner = Runner(testDir, "TestRuntime2.tdml")
+  val runner: Runner = Runner(testDir, "nested.tdml")
 
   @AfterClass def shutDown(): Unit = { runner.reset }
 }
 
-class TestRuntime2 {
-  import TestRuntime2._
+class TestNested {
+  import TestNested._
 
-  @Test def test_ex_nums_parse1(): Unit = { runner.runOneTest("ex_nums_parse1") }
-  @Test def test_ex_nums_unparse1(): Unit = { runner.runOneTest("ex_nums_unparse1") }
-  @Test def test_ex_nums_parse2(): Unit = { runner.runOneTest("ex_nums_parse2") }
-  @Test def test_ex_nums_unparse2(): Unit = { runner.runOneTest("ex_nums_unparse2") }
+  @Test def test_nested_struct_parse(): Unit = { runner.runOneTest("nested_struct_parse") }
+  @Test def test_nested_struct_unparse(): Unit = { runner.runOneTest("nested_struct_unparse") }
+  @Test def test_nested_union_parse_2(): Unit = { runner.runOneTest("nested_union_parse_2") }
+  @Test def test_nested_union_unparse_2(): Unit = { runner.runOneTest("nested_union_unparse_2") }
+  @Test def test_nested_union_parse_4(): Unit = { runner.runOneTest("nested_union_parse_4") }
+  @Test def test_nested_union_unparse_4(): Unit = { runner.runOneTest("nested_union_unparse_4") }
 }
diff --git a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
similarity index 89%
rename from daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
rename to daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
index 939d9ca..9cf4546 100644
--- a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
@@ -31,6 +31,8 @@ object TestOrionCommand {
 class TestOrionCommand {
   import TestOrionCommand._
 
+  @Test def test_camera_state_parse(): Unit = { runner.runOneTest("camera_state_parse") }
+  @Test def test_camera_state_unparse(): Unit = { runner.runOneTest("camera_state_unparse") }
   @Test def test_command_parse(): Unit = { runner.runOneTest("command_parse") }
   @Test def test_command_unparse(): Unit = { runner.runOneTest("command_unparse") }
   @Test def test_video_settings_parse(): Unit = { runner.runOneTest("video_settings_parse") }
diff --git a/project/Rat.scala b/project/Rat.scala
index 2b646d2..4c88ef5 100644
--- a/project/Rat.scala
+++ b/project/Rat.scala
@@ -107,9 +107,10 @@ object Rat {
     file("daffodil-japi/src/test/resources/test/japi/myData16.dat"),
     file("daffodil-japi/src/test/resources/test/japi/myData19.dat"),
     file("daffodil-japi/src/test/resources/test/japi/myDataBroken.dat"),
-    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat"),
     file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_parse.dat"),
-    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat"),
+    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_struct_parse.dat"),
+    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_2.dat"),
+    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_4.dat"),
     file("daffodil-sapi/src/test/resources/test/sapi/01very_simple.txt"),
     file("daffodil-sapi/src/test/resources/test/sapi/myData.dat"),
     file("daffodil-sapi/src/test/resources/test/sapi/myData2.dat"),
@@ -123,6 +124,27 @@ object Rat {
     file("daffodil-tdml-lib/src/test/resources/test/tdml/test.txt"),
     file("daffodil-tdml-processor/src/test/resources/test/tdml/test.bin"),
     file("daffodil-tdml-processor/src/test/resources/test/tdml/test.txt"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_parse.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.dfdl"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_11.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_12.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_13.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_14.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_15.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_16.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_17.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_18.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_19.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_20.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.dfdl"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_111.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_112.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_113.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_114.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_115.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_116.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat"),
     file("daffodil-test/src/test/resources/org/apache/daffodil/section00/general/ext_file.txt"),
     file("daffodil-test/src/test/resources/org/apache/daffodil/section00/general/ext_file2.txt"),
     file("daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/blobs/blob_01.bin"),