Revision 226ce0dab5018739e8793d5cc421a5e39590e51b authored by Ron Burkey on 24 September 2021, 13:52:10 UTC, committed by Ron Burkey on 24 September 2021, 13:52:10 UTC
1 parent efa5595
Raw File
developer.html
<!DOCTYPE doctype PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
    <title>Virtual AGC Developer-Info Page</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="author" content="Ron Burkey">
    <link rel="icon" type="image/png" href="favicon.png">
    <meta name="author" content="Ron Burkey">
    <script type="text/javascript" src="Header.js"></script>
  </head>
  <body style="background-image: url(gray3.jpg);">
    <script type="text/javascript">
document.write(headerTemplate.replace("@TITLE@","Developer Info").replace("@SUBTITLE@","For those wishing to modify or interface to Virtual AGC software"))
</script>
    <h2>Contents</h2>
    <ul>
      <li><a href="#Contributing_Changes_Back_to_the_Virtual">Contributing
Changes
          Back to the Virtual AGC Project</a><br>
      </li>
      <li><a href="#Interfacing_yaAGC_to_yaDSKY_or_Other">Interfacing
          yaAGC to yaDSKY, yaAGS to yaDEDA, or Other Simulated Hardware,
          in General</a></li>
      <ul>
        <li><a href="#Using_LM_Hardware-Simulation_Programs">Using LM
            Hardware-Simulation Programs with Multiple AGCs or the AGS</a></li>
        <li><a href="#Use_of_yaAGC_as_Embedded_Software">Use of yaAGC as
            Embedded Software</a></li>
      </ul>
      <li><a href="#sendrecv_Protocol"><span style="font-family:
            monospace;">send/recv</span> Protocol</a></li>
      <ul>
        <li><a href="#yaAGC_vs._yaAGS_Packets">yaAGC vs. yaAGS Packets</a></li>
        <li><a href="#Packets_for_Socket_Implementation_of_AGS">Packets
            for Socket Implementation of AGS I/O System</a></li>
        <li><a href="#Working_with_the_DEDA">Working with the DEDA</a><br>
        </li>
        <li><a href="#Packets_for_Socket_Implementation_of_AGC">Packets
            for Socket Implementation of AGC I/O System</a></li>
        <li><a href="#Input-Channel_Bitmasks">yaAGC Input-Channel
            Bitmasks</a></li>
        <li><a href="#Fictitious_IO_Channels">Fictitious I/O Channels</a><br>
        </li>
      </ul>
      <li><a href="#IO_Channel_Specifics">yaAGC I/O-Channel Specifics</a></li>
      <ul>
        <li><a href="#Table_of_IO_Channels">Table of yaAGC I/O channels</a><br>
        </li>
      </ul>
      <li><a href="#A_Template_Program_for_Creating_Simple">A Template
          Program for Creating Simple yaAGC Peripherals</a><br>
      </li>
      <li><a href="#Internals_of_the_yaDSKY_Program">Internals of the
          yaDSKY/yaDSKY2 Program<br>
        </a></li>
      <ul>
        <li><a href="#Interface_to_yaAGC">Interface to yaAGC</a></li>
        <li><a href="#Software_Architecture">Software Architecture</a></li>
        <li><a href="#GUI">GUI</a></li>
        <li><a href="#Indicator_Legends_and_Configuration_">Indicator
            Legends and Configuration (ini) file</a></li>
      </ul>
      <li><a href="#libyaAGC.a">Virtual AGC Library API</a></li>
      <ul>
        <li><a href="#Useful_AGC_Datatypes_and_Constants">Useful
            Datatypes and Constants</a></li>
        <li><a href="#AGC_CPU-to-Peripheral_Interconnections">CPU-to-Peripheral
Interconnections
            API</a></li>
        <li><a href="#AGC_CPU-Engine_API">AGC CPU-Engine API</a></li>
        <li><strike><a href="#AGC_Backtrace_API">AGC Backtrace API</a></strike></li>
        <li><a href="#AGC_Utility_API_">Utility API</a></li>
        <li><a href="#Downlink_Lists">Downlink Lists</a><br>
        </li>
        <li><a href="#An_Example%3A_The_Simplest_Possible_AGC">An
            Example:&nbsp; The Simplest Possible AGC Emulation Made from
            Library Functions</a></li>
        <li><a href="#Another">Another Example:&nbsp; A Simple AGC
            Peripheral Emulation Made from Library Functions</a></li>
      </ul>
      <li><a href="#CoreFormat">Format of a yaAGC Core-Rope Image File</a></li>
      <li><a href="#Format_of_a_yaAGS_Core_Image_File">Format of a yaAGS
          Core Image File</a><br>
      </li>
    </ul>
    <hr style="width: 100%; height: 2px;">
    <h2><a name="Contributing_Changes_Back_to_the_Virtual"
        id="Contributing_Changes_Back_to_the_Virtual"></a>Contributing
      Changes Back to the Virtual AGC Project</h2>
    Most software provided by the Virtual AGC project, other than the
    original AGC/AEA code, is provided under the terms of the GNU GPL
    version 2 license.&nbsp; Under the provisions of the license, you
    are free to modify and use the code however you like, for your own
    use, but that if you redistribute the modified code you must make
    the full modified source available to those receiving the binary
    executables.<br>
    <br>
    On the other hand, the GPL does not require you to contribute your
    changes back to the Virtual AGC project itself.&nbsp; From my
    standpoint, contributing the changes back is generally a good idea
    as long as they do not cause any kind of regression.&nbsp; If you
    develop any code with the intention of contributing it to the
    Virtual AGC project, you should read about the <a
      href="volunteer.html#Coding">desired characteristics of such
      contributions and of your interactions with the project</a>.<br>
    <br>
    <hr style="width: 100%; height: 2px;">
    <h2><a name="Interfacing_yaAGC_to_yaDSKY_or_Other"
        id="Interfacing_yaAGC_to_yaDSKY_or_Other"></a>Interfacing yaAGC
      to yaDSKY, yaAGS to yaDEDA, or Other Simulated Hardware, in
      General</h2>
    The method used by <span style="font-weight: bold;">yaAGC</span> or
    <span style="font-weight: bold;">yaAGS</span> to interface to
    virtual hardware, such as <span style="font-weight: bold;">yaDSKY</span>
    or <span style="font-weight: bold;">yaDSKY2</span>, has been chosen
    to be as generic as possible (to promote portability). For example,
    the same method is used virtually unchanged on Linux, MS Windows,
    and Mac OS X.<br>
    <br>
    At the same time, the system is as modular as possible, with <span
      style="font-weight: bold;">yaAGC</span> and <span
      style="font-weight: bold;">yaDSKY</span> being separate standalone
    programs running on the same computer or (theoretically) on
    different computers. This promotes the possibility of changing or
    even completely replacing <span style="font-weight: bold;">yaDSKY</span>—or
of
    introducing new stand-alone programs for simulating other Apollo
    hardware—without changing <span style="font-weight: bold;">yaAGC</span>
    itself.&nbsp; In fact, this has already been done with such
    alternative implementations as <span style="font-weight: bold;">yaDSKY</span>
    and <span style="font-weight: bold;">yaDSKY2</span>.&nbsp; &nbsp;
    In what follows I'll use the term "yaDSKY" to refer interchangeably
    to yaDSKY and it replacement <span style="font-weight: bold;">yaDSKY2</span>,
    "yaDEDA" to refer interchangeably to <span style="font-weight:
      bold;">yaDEDA</span> and <span style="font-weight: bold;">yaDEDA2</span>,
    and "yaACA" to refer interchangeably to <span style="font-weight:
      bold;">yaACA</span> and <span style="font-weight: bold;">yaACA2</span>.&nbsp;
As
    far as interoperability requirements are concerned, these
    alternatives are drop-in replacements for each other.<br>
    <br>
    <span style="font-weight: bold;">yaAGC</span> and <span
      style="font-weight: bold;">yaDSKY</span> are, respectively, a
    server and client communicating with each other over an IP network
    via the mechanism of sockets. At boot time, the <span
      style="font-weight: bold;">yaDSKY</span> client (or clients for
    other simulated hardware) connects to the <span style="font-weight:
      bold;">yaAGC</span> server. The only necessity for a client
    program representing a hardware simulation is to be able to connect
    to the corrrect port on the server, and to communicate input or
    output data in an acceptable format.&nbsp; (But the socket interface
    could be replaced with relatively little effort—say, to a
    shared-memory interface.&nbsp; <a
      href="#AGC_CPU-to-Peripheral_Interconnections">See below</a>.)<br>
    <br>
    The real AGC received input from hardware, or outputted control
    signals to hardware, by means of instructions which accessed "i/o
    channels" in distinction to main memory. <span style="font-weight:
      bold;">yaAGC</span> mimics this behavior by simply translating
    "output channel" assembly-language instructions to server
    broadcasts, and by making data received from clients available to
    subsequent "input channel" assembly-language instructions. Except
    for a few i/o channels that correspond to known functionality within
    the AGC itself, <span style="font-weight: bold;">yaAGC</span> can
    thus interact with simulated hardware in a completely generic way,
    without assigning any interpretation to the data other than the
    interpretations assigned by the <span style="font-weight: bold;">Luminary</span>,
    <span style="font-weight: bold;">Colossus</span>, or other Apollo
    software being executed by it.<br>
    <br>
    This method does impose certain response-time limitations on AGC
    i/o, but does not impose any practical bandwidth limitation.<br>
    <br>
    By default, the <span style="font-weight: bold;">yaAGC</span>
    server listens for new connections on ports 19697-19706. (This can
    be changed by a command-line switch in invoking <span
      style="font-weight: bold;">yaAGC</span>.) Similarly, hardware
    simulations like <span style="font-weight: bold;">yaDSKY</span>
    attempt to connect to port 19697 at boot time. By default, the
    clients assume that the server is running on the same machine as
    they are (i.e., on "localhost"), but are able to change their
    assumptions about the server's IP address and about the port number
    with command-line switches.<br>
    <br>
    This socket mechanism is almost completely generic at the
    application-programmer's level, and has been chosen for precisely
    that reason. In other words, it can be used on UNIX-like systems and
    on Microsoft Windows almost without change. For more information,
    I'd suggest looking at the <span style="font-weight: bold;">yaAGC</span>
    source code, and (if you develop in a UNIX-like environment) at `man
    2 socket', `man 2 send', `man 2 recv', etc.&nbsp; Or, look at the
    helpfiles in the Win32 SDK. Essentially the only differences between
    Linux and Win32 versions involve initialization of the socket
    system, and of configuring the communication to be non-blocking.<br>
    <h3><a name="Using_LM_Hardware-Simulation_Programs"
        id="Using_LM_Hardware-Simulation_Programs"></a>Using LM
      Hardware-Simulation Programs with Multiple AGCs or the AGS<br>
    </h3>
    Note that some of the LM hardware could be placed under control of <span
      style="font-style: italic;">either</span> the LM AGC or the CM
    AGC; also, the two AGCs could be interconnected to exchange the
    setup-data of the two. To simulate such a situation, it will (of
    course) be necessary to run two copies of <span style="font-weight:
      bold;">yaAGC</span> simultaneously, at different port addresses.
    Simulation software for such hardware will obviously want to connect
    to both <span style="font-weight: bold;">yaAGC</span> servers, and
    to apply some rationale as to which of them to listen to at any
    given time. Since I don't presently plan to <span
      style="font-style: italic;">personally</span> implement such
    additional simulations, the details are left as an exercise to the
    reader.<br>
    <br>
    However, to avoid conflict or confusion among developers, I would
    suggest the following <span style="font-style: italic;">default</span>
    use of ports:<br>
    <ul>
      <li>CM AGC (<span style="font-weight: bold;">yaAGC</span> acting
        as a server):&nbsp; Listens to ports 19697-19706.</li>
      <ul>
        <li>Commander's DSKY (<span style="font-weight: bold;">yaDSKY</span>
          acting as client):&nbsp; Port 19697.</li>
        <li>Navigation DSKY (<span style="font-weight: bold;">yaDSKY</span>
          acting as client):&nbsp; Port 19698.</li>
        <li>LM AGC (<span style="font-weight: bold;">yaAGC</span> acting
          as client):&nbsp; Port 19699.</li>
        <li>Mission control (<span style="font-weight: bold;">yaTelemetry</span>
          acting as client):&nbsp; Port 19700.</li>
        <li>IMU:&nbsp; Port 19701.</li>
        <li>AOT:&nbsp; Port 19702.</li>
        <li><span style="font-weight: bold;">VirtualAGC</span> digital
          uplink:&nbsp; Port 19706.<br>
        </li>
      </ul>
      <li>LM AGC (<span style="font-weight: bold;">yaAGC</span> acting
        as a server):&nbsp; Listens to ports 19797-19806.</li>
      <ul>
        <li>DSKY (<span style="font-weight: bold;">yaDSKY</span> acting
          as client):&nbsp; Port 19797.</li>
        <li>Mission control (<span style="font-weight: bold;">yaTelemetry</span>
          acting as client):&nbsp; Port 19800.</li>
        <li>IMU:&nbsp; Port 19801.</li>
        <li>AOT:&nbsp; Port 19802.</li>
        <li>ACA: Port 19803.</li>
        <li>AGS (<span style="font-weight: bold;">yaAGS</span> acting as
          a client):&nbsp; Port 19804.</li>
        <li><span style="font-weight: bold;">VirtualAGC</span> digital
          uplink:&nbsp; Port 19806.<br>
        </li>
      </ul>
      <li>LM AGS (<span style="font-weight: bold;">yaAGS</span> acting
        as a server):&nbsp; Listens to ports 19897-19906</li>
      <ul>
        <li>DEDA (<span style="font-weight: bold;">yaDEDA</span> acting
          as client):&nbsp; Port 19897.</li>
        <li><span style="font-weight: bold;">VirtualAGC</span> digital
          uplink:&nbsp; Port 19906.<br>
        </li>
      </ul>
    </ul>
    Note that for the case of communication between the AGC and AGS, it
    is necessary to use either <span style="font-weight: bold;">yaAGC</span>
    socket protocol or <span style="font-weight: bold;">yaAGS</span>
    socket protocol to exchange data.&nbsp; We choose in this case to
    allow <span style="font-weight: bold;">yaAGS</span> to use <span
      style="font-weight: bold;">yaAGC</span> protocol.&nbsp; A similar
    situation may arise where the AGC and AGS use the same peripheral
    device—for example, receiving the same gimbal-angle
    increment/decrement pulses.&nbsp; Rather than forcing the peripheral
    device to output the same data in two different protocols, it is
    more reasonable for <span style="font-weight: bold;">yaAGS</span>
    simply to interpret <span style="font-weight: bold;">yaAGC</span>
    protocol.<br>
    <br>
    Obviously, suggestions for improvement are welcomed.<br>
    <h3><a name="Use_of_yaAGC_as_Embedded_Software"
        id="Use_of_yaAGC_as_Embedded_Software"></a>Use of yaAGC as
      Embedded Software</h3>
    This is quite simple, in principle. If your embedded system is
    running a POSIX-compliant operating system, you can just go ahead
    and run <span style="font-weight: bold;">yaAGC</span>.&nbsp; And
    since the Raspberry Pi have become ubiquitous, and cheap, and
    usually run a version of Linux anyway, this is frankly the preferred
    embedded solution for most people.&nbsp; Including me!<br>
    <br>
    If not — if,
    for example, you have no operating system and want to run a "bare
    metal" version of <b>yaAGC</b> — here's what you need to
    do:<br>
    <br>
    Provide replacements for the <span style="font-family: monospace;">send</span>
    and <span style="font-family: monospace;">recv</span> functions, so
    that when <span style="font-weight: bold;">yaAGC</span> issues
    these commands, the appropriate hardware is controlled. Also,
    provided stubs for other socket-related functions like <span
      style="font-family: monospace;">socket</span>, so that they don't
    do anything.&nbsp; Alternately, replace the <span
      style="font-family: monospace;">ChannelInput</span>, <span
      style="font-family: monospace;">ChannelOutput</span>, and <span
      style="font-family: monospace;">ChannelRoutine</span> functions,
    as described below.<br>
    <br>
    Instead of using the main program provided with <span
      style="font-weight: bold;">yaAGC</span>, you'll instead use
    libyaAGC.a as a library and provide your own main function. Provide
    startup code to initialize any hardware peripherals you're
    providing, and to issue timer interrupts every 11.7&nbsp; μs. Your
    own main function doesn't really need to do any more than this.<br>
    <br>
    Upon receiving a timer interrupt, vector to the <span
      style="font-family: monospace;">agc_engine</span> function. This
    will result in one AGC memory cycle occurring every 11.7&nbsp; μs.,
    and of the simulated software (<span style="font-weight: bold;">Luminary</span>,
    <span style="font-weight: bold;">Colossus</span>, or whatever)
    issuing <span style="font-family: monospace;">send</span> or <span
      style="font-family: monospace;">recv</span> commands (or <span
      style="font-family: monospace;">ChannelOutput</span> and <span
      style="font-family: monospace;">ChannelInput</span> commands) to
    interact with whatever hardware you've provided.<br>
    <h2><a name="sendrecv_Protocol" id="sendrecv_Protocol"></a><span
        style="font-family: monospace;">send</span>/<span
        style="font-family: monospace;">recv</span> Protocol</h2>
    As mentioned above, <span style="font-weight: bold;">yaAGC</span>
    and <span style="font-weight: bold;">yaAGS</span> send data to
    simulated hardware using the <span style="font-family: monospace;">send</span>
    function, and the simulated hardware receives it using the <span
      style="font-family: monospace;">recv</span> function and vice
    versa. Every write to an "output channel" by the AGC or AGS results
    in a <span style="font-family: monospace;">send</span>. (Or, to
    improve bandwidth by reducing overhead, multiple output-channel
    writes can be ganged into a single <span style="font-family:
      monospace;">send</span>.) It only remains to understand the format
    of the transmitted data.&nbsp; If for some reason you can't abide
    this approach, replace the <span style="font-family: monospace;">ChannelInput</span>,
    <span style="font-family: monospace;">ChannelOutput</span>, and <span
      style="font-family: monospace;">ChannelRoutine</span> functions as
    described below to eliminate the socket-based interface.<br>
    <h3><a name="yaAGC_vs._yaAGS_Packets" id="yaAGC_vs._yaAGS_Packets"></a>yaAGC
vs.
      yaAGS Packets</h3>
    The <span style="font-weight: bold;">yaAGC</span> and <span
      style="font-weight: bold;">yaAGS</span> programs each use a system
    of 4-byte packets for i/o.&nbsp; The packets of the two programs are
    distinguishable by the two-bit "signatures" that appear in the
    most-significant bits of each byte.&nbsp; Therefore, both types of
    packets can appear on the same socket connection, without fear of
    misinterpretation.&nbsp; This is important, for example, on the
    socket connection by which the <span style="font-weight: bold;">yaAGC</span>
    and <span style="font-weight: bold;">yaAGC</span> intercommunicate.<br>
    <br>
    The signature bits of a <span style="font-weight: bold;">yaAGC</span>
    packet look like<br>
    <div style="text-align: center;"> <span style="font-family:
        monospace;">00xxxxxx 01xxxxxx 10xxxxxx 11xxxxxx</span><br>
    </div>
    whereas the signature bits of a <span style="font-weight: bold;">yaAGS</span>
    packet look like<br>
    <div style="text-align: center;"> <span style="font-family:
        monospace;">00xxxxxx 11xxxxxx 10xxxxxx 01xxxxxx</span><br>
    </div>
    <br>
    Obviously there is some room here for defining additional types of
    packets in the future, just by insuring that the 00 signature byte
    always comes first, and rearranging the other three signature
    bytes.&nbsp; Note also that in order to determine whether connected
    peripheral clients (such as the DSKY) have disconnected, <b>yaAGC</b>/<b>yaAGS</b>
    occasionally "ping" all of the connected clients, using abnormal
    packets of the form<br>
    <br>
    <div align="center"><tt>11111111 11111111 11111111 11111111</tt> (or
      just a single <tt>11111111</tt> for older versions)<br>
      <div align="left"><br>
        It's occasionally useful in program develop to capture the data
        streams.&nbsp; I'm sure there are many tools for doing so.&nbsp;
        On Linux, I find the <b>socat</b> and <b>hexdump</b> tools to
        be useful.&nbsp; For example, to capture the datastream being
        emitted from <b>yaAGC</b> as configured with the ports usually
        used for the LM, I find the following command helpful:<br>
      </div>
      <br>
    </div>
    <div align="center"><tt>socat TCP:127.0.0.1:19799 | hexdump -C</tt><br>
    </div>
    <br>
    <span style="font-weight: bold;">yaAGS</span> packets and <span
      style="font-weight: bold;">yaAGC</span> packets are further
    defined in the following sections.<br>
    <h3><a name="Packets_for_Socket_Implementation_of_AGS"
        id="Packets_for_Socket_Implementation_of_AGS"></a>Packets for
      Socket Implementation of AGS I/O System</h3>
    Packets input or output by <span style="font-weight: bold;">yaAGS</span>
    for implementation of the i/o system are of the form, as represented
    in bits:<br>
    <br>
    <div style="text-align: center;"> <span style="font-family:
        monospace;">00tttttt 11dddddd 10dddddd 01dddddd</span><br>
    </div>
    <br>
    The field <span style="font-family: monospace;">tttttt</span>
    represents the type of the packet (00-77 octal), whereas the 18-bit
    field <span style="font-family: monospace;">dddddddddddddddddd</span>
    represents the packet's data.<br>
    <br>
    Specifically, the <span style="font-family: monospace;">tttttt</span>
    field is interpreted as follows (all numbers in octal):<br>
    <br>
    <table summary="" style="text-align: left;" cellspacing="2"
      cellpadding="2" border="1">
      <tbody>
        <tr>
          <td style="font-weight: bold; vertical-align: middle;"> <span
              style="font-family: monospace;">tttttt</span></td>
          <td style="font-weight: bold; vertical-align: middle;">I/O
            Direction<br>
          </td>
          <td style="font-weight: bold; vertical-align: middle;">I/O
            Address<br>
          </td>
          <td style="font-weight: bold; vertical-align: middle;">
            Significant Bits<br>
          </td>
          <td style="font-weight: bold; vertical-align: middle;">
            Interpretation<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">00<br>
          </td>
          <td style="vertical-align: middle;">Input (to CPU)<br>
          </td>
          <td style="vertical-align: middle;">2001<br>
          </td>
          <td style="vertical-align: middle;">15<br>
          </td>
          <td style="vertical-align: middle;">PGNS theta integrator.<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">01<br>
          </td>
          <td style="vertical-align: middle;">Input</td>
          <td style="vertical-align: middle;">2002<br>
          </td>
          <td style="vertical-align: middle;">15<br>
          </td>
          <td style="vertical-align: middle;">PGNS phi integrator.<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">02<br>
          </td>
          <td style="vertical-align: middle;">Input</td>
          <td style="vertical-align: middle;">2004<br>
          </td>
          <td style="vertical-align: middle;">15<br>
          </td>
          <td style="vertical-align: middle;">PGNS psi integrator.<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">03<br>
          </td>
          <td style="vertical-align: middle;">Input</td>
          <td style="vertical-align: middle;">2010<br>
          </td>
          <td style="vertical-align: middle;">n/a<br>
          </td>
          <td style="vertical-align: middle;">(Not used)<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">04<br>
          </td>
          <td style="vertical-align: middle;">Input</td>
          <td style="vertical-align: middle;">2020<br>
          </td>
          <td style="vertical-align: middle;">8 + 8<br>
          </td>
          <td style="vertical-align: middle;"> Discrete Input Word
            1.&nbsp; The bit positions are as follows.&nbsp; Note that
            only the bits labeled "discrete" actually appear in the i/o
            register at address 2020.&nbsp; The bits labeled "mask" are
            used to indicate which of the "discrete" bits are
            valid.&nbsp; In other words, the only bits of i/o register
            2020 that change are those with a "mask" of 1.&nbsp; The
            bits with a mask of 0 do not change.&nbsp; This scheme is
            used because different peripheral devices, connected to the
            CPU on different sockets, may control different
            discretes.&nbsp; Thus, several different peripherals might
            send the CPU Discrete Input Word 1 packets, each affecting
            only the bits of i/o register that are specifically under
            their control, without any conflict.<br>
            <br>
            <span style="font-weight: bold;">Note:</span>&nbsp; The
            discrete inputs are active when 0 and inactive when 1.&nbsp;
            The mask bits are active when 1 and inactive when 0.<br>
            <br>
            <table summary="" style="text-align: left; margin-left:
              auto; margin-right: auto;" cellspacing="2" cellpadding="2"
              border="1">
              <tbody>
                <tr>
                  <td style="font-weight: bold; vertical-align: middle;">
                    Bitmask<br>
                    (octal)<br>
                  </td>
                  <td style="font-weight: bold; vertical-align: middle;">
                    Interpretation<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">200000</td>
                  <td style="vertical-align: middle;">Downlink Telemetry
                    Stop discrete.&nbsp; Note that <span
                      style="font-weight: bold;">yaAGS</span> will <span
                      style="font-style: italic;">automatically</span>
                    activate this flag when&nbsp; a downlink telemetry
                    word is received, so there is no need to set it
                    separately.<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">100000</td>
                  <td style="vertical-align: middle;">Output Telemetry
                    Stop discrete<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">040000</td>
                  <td style="vertical-align: middle;">Follow-Up discrete<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">020000</td>
                  <td style="vertical-align: middle;">Automatic discrete<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">010000</td>
                  <td style="vertical-align: middle;">Descent Engine On
                    discrete<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">004000</td>
                  <td style="vertical-align: middle;">Ascent Engine On
                    discrete<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">002000</td>
                  <td style="vertical-align: middle;">Abort discrete<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">001000</td>
                  <td style="vertical-align: middle;">Abort Stage
                    discrete<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: top;">000200<br>
                  </td>
                  <td style="vertical-align: top;">Downlink Telemetry
                    Stop mask<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: top;">000100<br>
                  </td>
                  <td style="vertical-align: top;">Output Telemetry Stop
                    mask<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: top;">000040<br>
                  </td>
                  <td style="vertical-align: top;">Follow-Up mask<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: top;">000020<br>
                  </td>
                  <td style="vertical-align: top;">Automatic mask<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: top;">000010<br>
                  </td>
                  <td style="vertical-align: top;">Descent Engine On
                    mask<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: top;">000004<br>
                  </td>
                  <td style="vertical-align: top;">Ascent Engine On mask<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: top;">000002<br>
                  </td>
                  <td style="vertical-align: top;">Abort mask<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: top;">000001<br>
                  </td>
                  <td style="vertical-align: top;">Abort Stage mask<br>
                  </td>
                </tr>
              </tbody>
            </table>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">05<br>
          </td>
          <td style="vertical-align: middle;">Input</td>
          <td style="vertical-align: middle;">2040<br>
          </td>
          <td style="vertical-align: middle;">7 + 7<br>
          </td>
          <td style="vertical-align: middle;"> Discrete Input Word
            2.&nbsp; The bit positions are as follows.&nbsp; The "mask"
            bits vs. the "discrete" bits are explained above.<br>
            <br>
            <span style="font-weight: bold;">Note:</span>&nbsp; The
            discrete inputs are active when 0 and inactive when 1.&nbsp;
            The mask bits are active when 1 and inactive when 0.<br>
            <br>
            <table summary="" style="text-align: left; margin-left:
              auto; margin-right: auto;" cellspacing="2" cellpadding="2"
              border="1">
              <tbody>
                <tr>
                  <td style="font-weight: bold; vertical-align: middle;">
                    Bitmask<br>
                    (octal)<br>
                  </td>
                  <td style="font-weight: bold; vertical-align: middle;">
                    Interpretation<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">200000</td>
                  <td style="vertical-align: middle;">GSE Discrete 1</td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">100000<br>
                  </td>
                  <td style="vertical-align: middle;">GSE Discrete 2</td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">040000</td>
                  <td style="vertical-align: middle;">GSE Discrete 3<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">020000</td>
                  <td style="vertical-align: middle;">DEDA Clear
                    discrete<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">010000</td>
                  <td style="vertical-align: middle;">DEDA Hold discrete<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">004000</td>
                  <td style="vertical-align: middle;">DEDA Enter
                    discrete<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">002000</td>
                  <td style="vertical-align: middle;">DEDA Readout
                    discrete<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: top;">000200<br>
                  </td>
                  <td style="vertical-align: top;">GSE mask 1<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: top;">000100<br>
                  </td>
                  <td style="vertical-align: top;">GSE mask 2<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: top;">000040<br>
                  </td>
                  <td style="vertical-align: top;">GSE mask 3</td>
                </tr>
                <tr>
                  <td style="vertical-align: top;">000020<br>
                  </td>
                  <td style="vertical-align: top;">DEDA Clear mask<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: top;">000010<br>
                  </td>
                  <td style="vertical-align: top;">DEDA Hold mask<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: top;">000004<br>
                  </td>
                  <td style="vertical-align: top;">DEDA Enter mask<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: top;">000002<br>
                  </td>
                  <td style="vertical-align: top;">DEDA Readout mask<br>
                  </td>
                </tr>
              </tbody>
            </table>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">06<br>
          </td>
          <td style="vertical-align: middle;">Input</td>
          <td style="vertical-align: middle;">2100<br>
          </td>
          <td style="vertical-align: middle;">n/a<br>
          </td>
          <td style="vertical-align: middle;">(Not used)<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">07<br>
          </td>
          <td style="vertical-align: middle;">Input</td>
          <td style="vertical-align: middle;">2200<br>
          </td>
          <td style="vertical-align: middle;">4<br>
          </td>
          <td style="vertical-align: middle;">DEDA<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">10<br>
          </td>
          <td style="vertical-align: middle;">Input</td>
          <td style="vertical-align: middle;">6001<br>
          </td>
          <td style="vertical-align: middle;">n/a<br>
          </td>
          <td style="vertical-align: middle;">(Not used)<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">11<br>
          </td>
          <td style="vertical-align: middle;">Input</td>
          <td style="vertical-align: middle;">6002<br>
          </td>
          <td style="vertical-align: middle;">11<br>
          </td>
          <td style="vertical-align: middle;">delta-integral-q
            counter.&nbsp; This register is automatically reset after
            being read by the CPU (with an <span style="font-family:
              monospace;">INP</span> instruction).<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">12<br>
          </td>
          <td style="vertical-align: middle;">Input</td>
          <td style="vertical-align: middle;">6004<br>
          </td>
          <td style="vertical-align: middle;">11<br>
          </td>
          <td style="vertical-align: middle;">delta-integral-r
            counter.&nbsp; This register is automatically reset after
            being read by the CPU (with an <span style="font-family:
              monospace;">INP</span> instruction).</td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">13<br>
          </td>
          <td style="vertical-align: middle;">Input</td>
          <td style="vertical-align: middle;">6010<br>
          </td>
          <td style="vertical-align: middle;">11<br>
          </td>
          <td style="vertical-align: middle;">delta-integral-p
            counter.&nbsp; This register is automatically reset after
            being read by the CPU (with an <span style="font-family:
              monospace;">INP</span> instruction).</td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">14<br>
          </td>
          <td style="vertical-align: middle;">Input</td>
          <td style="vertical-align: middle;">6020<br>
          </td>
          <td style="vertical-align: middle;">11<br>
          </td>
          <td style="vertical-align: middle;">delta-V<sub>x</sub>
            counter.&nbsp; This register is automatically reset after
            being read by the CPU (with an <span style="font-family:
              monospace;">INP</span> instruction).</td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">15<br>
          </td>
          <td style="vertical-align: middle;">Input</td>
          <td style="vertical-align: middle;">6040<br>
          </td>
          <td style="vertical-align: middle;">11<br>
          </td>
          <td style="vertical-align: middle;">delta-V<sub>y</sub>
            counter.&nbsp; This register is automatically reset after
            being read by the CPU (with an <span style="font-family:
              monospace;">INP</span> instruction).</td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">16<br>
          </td>
          <td style="vertical-align: middle;">Input</td>
          <td style="vertical-align: middle;">6100<br>
          </td>
          <td style="vertical-align: middle;">11<br>
          </td>
          <td style="vertical-align: middle;">delta-V<sub>z</sub>
            counter.&nbsp; This register is automatically reset after
            being read by the CPU (with an <span style="font-family:
              monospace;">INP</span> instruction).</td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">17<br>
          </td>
          <td style="vertical-align: middle;">Input</td>
          <td style="vertical-align: middle;">6200<br>
          </td>
          <td style="vertical-align: middle;">18<br>
          </td>
          <td style="vertical-align: middle;">Downlink Telemetry.&nbsp;
            After this register is read by the CPU (with an <span
              style="font-family: monospace;">INP</span> instruction),
            the Downlink Telemetry Stop discrete (see above) is
            automatically reset.</td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">20<br>
          </td>
          <td style="vertical-align: middle;">Output (from CPU)<br>
          </td>
          <td style="vertical-align: middle;">2001<br>
          </td>
          <td style="vertical-align: middle;">10<br>
          </td>
          <td style="vertical-align: middle;">sin theta.&nbsp; Can be
            negative (requires sign-extension to full 18-bit value).</td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">21<br>
          </td>
          <td style="vertical-align: middle;">Output</td>
          <td style="vertical-align: middle;">2002<br>
          </td>
          <td style="vertical-align: middle;">10<br>
          </td>
          <td style="vertical-align: middle;">cos theta.&nbsp; Can be
            negative (requires sign-extension to full 18-bit value).</td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">22<br>
          </td>
          <td style="vertical-align: middle;">Output</td>
          <td style="vertical-align: middle;">2004<br>
          </td>
          <td style="vertical-align: middle;">10<br>
          </td>
          <td style="vertical-align: middle;">sin phi.&nbsp; Can be
            negative (requires sign-extension to full 18-bit value).</td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">23<br>
          </td>
          <td style="vertical-align: middle;">Output</td>
          <td style="vertical-align: middle;">2010<br>
          </td>
          <td style="vertical-align: middle;">10<br>
          </td>
          <td style="vertical-align: middle;">cos phi.&nbsp; Can be
            negative (requires sign-extension to full 18-bit value).</td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">24<br>
          </td>
          <td style="vertical-align: middle;">Output</td>
          <td style="vertical-align: middle;">2020<br>
          </td>
          <td style="vertical-align: middle;">10<br>
          </td>
          <td style="vertical-align: middle;">sin psi.&nbsp; Can be
            negative (requires sign-extension to full 18-bit value).</td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">25<br>
          </td>
          <td style="vertical-align: middle;">Output</td>
          <td style="vertical-align: middle;">2040<br>
          </td>
          <td style="vertical-align: middle;">10<br>
          </td>
          <td style="vertical-align: middle;">cos psi.&nbsp; Can be
            negative (requires sign-extension to full 18-bit value).</td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">26<br>
          </td>
          <td style="vertical-align: middle;">Output</td>
          <td style="vertical-align: middle;">2100<br>
          </td>
          <td style="vertical-align: middle;">n/a<br>
          </td>
          <td style="vertical-align: middle;">(Not used)<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">27<br>
          </td>
          <td style="vertical-align: middle;">Output</td>
          <td style="vertical-align: middle;">2200<br>
          </td>
          <td style="vertical-align: middle;">4<br>
          </td>
          <td style="vertical-align: middle;">DEDA<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">30<br>
          </td>
          <td style="vertical-align: middle;">Output</td>
          <td style="vertical-align: middle;">6001<br>
          </td>
          <td style="vertical-align: middle;">10<br>
          </td>
          <td style="vertical-align: middle;">E<sub>x</sub>.&nbsp; Can
            be negative (requires sign-extension to full 18-bit value).</td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">31<br>
          </td>
          <td style="vertical-align: middle;">Output</td>
          <td style="vertical-align: middle;">6002<br>
          </td>
          <td style="vertical-align: middle;">10<br>
          </td>
          <td style="vertical-align: middle;">E<sub>y</sub>.&nbsp; Can
            be negative (requires sign-extension to full 18-bit value).</td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">32<br>
          </td>
          <td style="vertical-align: middle;">Output</td>
          <td style="vertical-align: middle;">6004<br>
          </td>
          <td style="vertical-align: middle;">10<br>
          </td>
          <td style="vertical-align: middle;">E<sub>z</sub>.&nbsp; Can
            be negative (requires sign-extension to full 18-bit value).<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">33<br>
          </td>
          <td style="vertical-align: middle;">Output</td>
          <td style="vertical-align: middle;">6010<br>
          </td>
          <td style="vertical-align: middle;">15<br>
          </td>
          <td style="vertical-align: middle;">Altitude, Altitude
            Rate.&nbsp; Can be negative (requires sign-extension to full
            18-bit value).<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">34<br>
          </td>
          <td style="vertical-align: middle;">Output</td>
          <td style="vertical-align: middle;">6020<br>
          </td>
          <td style="vertical-align: middle;">9<br>
          </td>
          <td style="vertical-align: middle;">Lateral Velocity.&nbsp;
            Can be negative (requires sign-extension to full 18-bit
            value).<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">35<br>
          </td>
          <td style="vertical-align: middle;">Output</td>
          <td style="vertical-align: middle;">6040<br>
          </td>
          <td style="vertical-align: middle;">n/a<br>
          </td>
          <td style="vertical-align: middle;">(Not used)<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">36<br>
          </td>
          <td style="vertical-align: middle;">Output</td>
          <td style="vertical-align: middle;">6100<br>
          </td>
          <td style="vertical-align: middle;">18<br>
          </td>
          <td style="vertical-align: middle;">Output Telemetry Word
            2.&nbsp; The full "Output Telemetry Word" is a 24 bit value,
            comprising "Output Telemetry Word 1" and "Output Telemetry
            Word 2".&nbsp; Bits 0-17 are stored in Output Telemetry Word
            2 and bits 6-23 are stored in Output Telemetry Word 1, so
            there is some overlap between the two.&nbsp; These
            overlapping fields are supposed to be logically-OR'd
            together.<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">37<br>
          </td>
          <td style="vertical-align: middle;">Output</td>
          <td style="vertical-align: middle;">6200<br>
          </td>
          <td style="vertical-align: middle;">18<br>
          </td>
          <td style="vertical-align: middle;">Output Telemetry Word
            1.&nbsp; (See above.)<br>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle;">40<br>
          </td>
          <td style="vertical-align: middle;">Output<br>
          </td>
          <td style="vertical-align: middle;">24XX<br>
            25XX<br>
            26XX<br>
            30XX<br>
            64XX<br>
            70XX<br>
          </td>
          <td style="vertical-align: middle;">11<br>
          </td>
          <td style="vertical-align: middle;"> Output discretes.&nbsp;
            This is a <span style="font-style: italic;">combination</span>
            of all discretes output by the CPU.&nbsp; The packet is
            output any time one of the discretes changes state
            internally to the CPU, which is any time i/o occurs to one
            of the associated i/o addresses.&nbsp; The output discretes
            are mapped into the output word as follows, in terms of the
            bits that represent their states.<br>
            <br>
            <span style="font-weight: bold;">Note:</span>&nbsp;&nbsp; To
            be consistent with the discrete inputs (above), these bits
            are 0 when active and 1 when inactive.<br>
            <br>
            <table summary="" style="text-align: left; margin-left:
              auto; margin-right: auto;" cellspacing="2" cellpadding="2"
              border="1">
              <tbody>
                <tr>
                  <td style="font-weight: bold; vertical-align: middle;">
                    Bitmask<br>
                    (octal)<br>
                  </td>
                  <td style="font-weight: bold; vertical-align: middle;">
                    Discrete<br>
                  </td>
                  <td style="font-weight: bold; vertical-align: middle;">
                    Address<br>
                    for<br>
                    Set<br>
                  </td>
                  <td style="font-weight: bold; vertical-align: middle;">
                    Address<br>
                    for<br>
                    Reset<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">000001<br>
                  </td>
                  <td style="vertical-align: middle;">Ripple Carry
                    Inhibit<br>
                  </td>
                  <td style="vertical-align: middle;">2410<br>
                  </td>
                  <td style="vertical-align: middle;">3010<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">000002<br>
                  </td>
                  <td style="vertical-align: middle;"> Altitude<br>
                  </td>
                  <td style="vertical-align: middle;">2420<br>
                  </td>
                  <td style="vertical-align: middle;">3040*<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">000004<br>
                  </td>
                  <td style="vertical-align: middle;">Altitude Rate<br>
                  </td>
                  <td style="vertical-align: middle;">2440<br>
                  </td>
                  <td style="vertical-align: middle;">3040<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">000010<br>
                  </td>
                  <td style="vertical-align: middle;">DEDA Shift In<br>
                  </td>
                  <td style="vertical-align: middle;">2500<br>
                  </td>
                  <td style="vertical-align: middle;">n/a**<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">000020<br>
                  </td>
                  <td style="vertical-align: middle;">DEDA Shift Out<br>
                  </td>
                  <td style="vertical-align: middle;">2600<br>
                  </td>
                  <td style="vertical-align: middle;">n/a**<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">000040<br>
                  </td>
                  <td style="vertical-align: middle;">GSE Discrete 4<br>
                  </td>
                  <td style="vertical-align: middle;">6401<br>
                  </td>
                  <td style="vertical-align: middle;">7001<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">000100<br>
                  </td>
                  <td style="vertical-align: middle;">GSE Discrete 5<br>
                  </td>
                  <td style="vertical-align: middle;">6402<br>
                  </td>
                  <td style="vertical-align: middle;">7002<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">000200<br>
                  </td>
                  <td style="vertical-align: middle;">GSE Discrete 6<br>
                  </td>
                  <td style="vertical-align: middle;">6404<br>
                  </td>
                  <td style="vertical-align: middle;">7004<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">000400<br>
                  </td>
                  <td style="vertical-align: middle;">Test Mode Failure<br>
                  </td>
                  <td style="vertical-align: middle;">6410<br>
                  </td>
                  <td style="vertical-align: middle;">7010<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">001000<br>
                  </td>
                  <td style="vertical-align: middle;">Engine Off<br>
                  </td>
                  <td style="vertical-align: middle;">6420<br>
                  </td>
                  <td style="vertical-align: middle;">7020<br>
                  </td>
                </tr>
                <tr>
                  <td style="vertical-align: middle;">002000<br>
                  </td>
                  <td style="vertical-align: middle;">Engine On<br>
                  </td>
                  <td style="vertical-align: middle;">6440<br>
                  </td>
                  <td style="vertical-align: middle;">7040<br>
                  </td>
                </tr>
                <tr>
                  <td colspan="4" rowspan="1" style="vertical-align:
                    top;">*The Altitude discrete is documented as being<br>
                    reset by writing to i/o address 3040, but it's easy<br>
                    to come to the conclusion that that's a misprint,<br>
                    and that 3020 is the correct address.&nbsp; I don't<br>
                    think it's a misprint.&nbsp; I think 3040 is
                    correct.<br>
                  </td>
                </tr>
                <tr>
                  <td colspan="4" rowspan="1" style="vertical-align:
                    top;">**These outputs are automatically reset by the<br>
                    CPU, and therefore it is assumed that they are<br>
                    always inactive unless specifically seen to be<br>
                    active.<br>
                  </td>
                </tr>
              </tbody>
            </table>
          </td>
        </tr>
      </tbody>
    </table>
    <br>
    The input registers marked as "counters" or "integrators" don't
    receive their values directly from the date fields of the i/o
    packets.&nbsp; Rather, the packet's data field contains a code that
    indicates the kind of operation to be performed, as follows.&nbsp;
    Note that the difference between the "integrators" and "counters" is
    that counters merely increment (by one), whereas "integrators" can
    be zeroed or can count up or down (by one).<br>
    <br>
    <div style="margin-left: 40px;">
      <table summary="" cellspacing="2" cellpadding="2" border="1">
        <tbody>
          <tr>
            <td>0</td>
            <td rowspan="1">Clears the register</td>
          </tr>
          <tr>
            <td>1<br>
            </td>
            <td rowspan="1">Increments the register</td>
          </tr>
          <tr>
            <td>777777 (-1)<br>
            </td>
            <td rowspan="1">Decrements the register</td>
          </tr>
        </tbody>
      </table>
    </div>
    <br>
    We actually implement this so that 0 clears the register, but any
    other value simply adds to the register.&nbsp; (The value will be
    automatically scaled so that increments of +/-1 automatically apply
    at the least-significant bit of the counter or integrator register,
    regardless of how many bits of precision the register has.<br>
    <h3><a name="Working_with_the_DEDA" id="Working_with_the_DEDA"></a>Working
with
      the DEDA</h3>
    Working with the DEDA is somewhat trickier from a developer's
    standpoint than working with the DSKY.&nbsp; The DSKY is simply a
    dumb terminal, so every depression of a key generates a message to
    the CPU, and every lighting of an indicator or a digit is the direct
    response of the DSKY to a message from the CPU.&nbsp; The DEDA is
    more complex, and contains more intelligence than the DSKY.&nbsp; It
    is more similar to a terminal that buffers entire lines of
    data.&nbsp; To avoid data loss, it is strongly advised to follow
    this paradigm if you want to implement your own DEDA or a
    replacement for the socket interface.<br>
    <br>
    Let's consider the interaction between the true AEA and DEDA (as
    opposed to <span style="font-weight: bold;">yaAGS</span> and <span
      style="font-weight: bold;">yaDEDA</span>).<br>
    <br>
    The first thing to know about the AEA-DEDA interaction is that data
    is not spontaneously transferred between the AEA and DEDA.&nbsp;
    (Actually, depression of the CLR key or the HOLD key is immediately
    communicated to the CPU, so we won't worry about those simple cases
    any further.)&nbsp; Every 4-bit transfer, in either direction, is
    triggered explicitly by the program running in the AEA as follows:<br>
    <ul>
      <li>To output 4 bits of data, the software loads data into the
        DEDA shift register (i/o address 2200) and then the DEDA Shift
        Out discrete bit is set (software outputs anything to i/o
        address 2600).&nbsp; The DEDA Shift Out bit is automatically
        reset without any action by the software.&nbsp; The shift
        operation takes 80 microseconds to complete, so the DEDA shift
        register and DEDA Shift Out/In bits shouldn't be messed with for
        80 microseconds.<br>
      </li>
      <li>&nbsp;To input 4 bits of data, the software sets the DEDA
        Shift In discrete bit (software outputs anything to i/o address
        2500), waits for the shift operation to complete (80
        microseconds), and then reads data from the DEDA shift register
        (i/o address 2200).&nbsp; The DEDA Shift In bit is automatically
        reset without any action by the software.</li>
    </ul>
    Next, you should know that no data transfers between the AEA and
    DEDA are actually 4-bits long, so each transfer consists of a packet
    of the 4-bit transfers described above.&nbsp; There are three types
    of data transfers between the AEA and DEDA:<br>
    <ol>
      <li>Transfer of a 3-octal-digit address from the DEDA to the
        AEA.&nbsp; From the user standpoint, the following key sequence
        is used:&nbsp; CLEAR <span style="font-style: italic;">OctalDigit</span><span
          style="font-style: italic;">OctalDigit</span> <span
          style="font-style: italic;">OctalDigit</span> READOUT.&nbsp;
        The DEDA buffers the 3-octal-digit address and causes the digits
        to appear in the 3-digit top display.&nbsp; It is the appearance
        of the DEDA Readout discrete input that triggers the AEA
        software to ask for three 4-bit transfers to input the
        data.&nbsp; The digits of the address are transmitted in the
        left-to-right order, and are encoded as you might expect:&nbsp;
        0000 for '0', 0001 for '1', 0010 for '2', and so on.<br>
      </li>
      <li>Transfer of a 3-octal-digit address plus 5-signed-digit data
        from the DEDA to the AEA.&nbsp; From the user standpoint, the
        following key sequence is used:&nbsp; CLEAR <span
          style="font-style: italic;">OctalDigit</span> <span
          style="font-style: italic;">OctalDigit</span> <span
          style="font-style: italic;">OctalDigit</span> +/- <span
          style="font-style: italic;">Digit</span> <span
          style="font-style: italic;">Digit</span> <span
          style="font-style: italic;">Digit</span> <span
          style="font-style: italic;">Digit</span> <span
          style="font-style: italic;">Digit</span> ENTR.&nbsp; Either
        octal or decimal digits may be used; the AEA software will
        determine the interpretation of the data (octal vs. decimal) on
        the basis of the 3-octal-digit address.&nbsp; This DEDA
        automatically mirrors the address and data into the top 3-digit
        display and bottom 5-digit (plus sign) display as it is
        entered.&nbsp; It is the appearance of the DEDA Enter discrete
        input that triggers the AEA software to ask for the nine 4-bit
        transfers to input the data.&nbsp; The numerical data is coded
        as you might expect.&nbsp; The '+' sign is encoded as 0 and the
        '-' sign is encoded as 1.<br>
      </li>
      <li>Transfer of a 3-octal-digit address plus 5-signed-digit data
        from the AEA to the DEDA.&nbsp; When the DEDA receives this
        data, it simply overwrites the numerical displays.&nbsp; The
        data is encoded exactly as described in #2 above.&nbsp; A binary
        code of 1111 may appear in place of any digit or the +/- sign,
        and indicates that that digit of the display is blanked.<br>
      </li>
    </ol>
    The AEA has no way to set the OPR ERR indicator.&nbsp; This is
    handled by the intelligence of the DEDA itself.&nbsp; Any
    key-sequence by the astronauts other than #1 or #2 above will cause
    the OPR ERR to light.&nbsp; When the OPR ERR lamp is lit, any
    subsequent data transfers to the AEA via the DEDA shift register are
    1111, which is not a legal value otherwise.&nbsp; The OPR ERR lamp
    is cleared only by hitting the CLEAR key.<br>
    <br>
    Now let's consider how this affects emulation of the CPU and the
    DEDA.&nbsp; The problem which this causes us is that it is very
    difficult to meet the timing constraints if the <span
      style="font-weight: bold;">yaAGS</span>-to-<span
      style="font-weight: bold;">yaDEDA</span> interaction closely
    models what has been described above.&nbsp; There is only an 80
    microsecond window from the time the CPU requests DEDA
    shift-register data, and the time that data must be available to the
    CPU.&nbsp; This sounds as if it is a problem with the socket
    interface, but actually it is a problem with the fact that <span
      style="font-weight: bold;">yaAGS</span> and <span
      style="font-weight: bold;">yaDEDA</span> are separate programs,
    probably running on the same physical CPU.&nbsp; It is therefore
    necessary to buffer incoming <span style="font-weight: bold;">yaDEDA</span>
    data within the <span style="font-weight: bold;">yaAGS</span>
    program, and to provide the interactions described within the <span
      style="font-weight: bold;">yaAGS</span> program, between the CPU
    and the buffer.&nbsp; Because I implemented yaDEDA prior to
    realizing that this was a problem, the interaction between the <span
      style="font-weight: bold;">yaAGS</span> data buffer and <span
      style="font-weight: bold;">yaDEDA</span> also uses this same
    sequence of operations.&nbsp; This explanation seems rather
    incoherent to me, but I can't think of a better way to describe it
    right now; I'll try to improve the description later.<br>
    <h3><a name="Packets_for_Socket_Implementation_of_AGC"
        id="Packets_for_Socket_Implementation_of_AGC"></a>Packets for
      Socket Implementation of AGC I/O System</h3>
    The format is quite simple: each data packet consists of 4 bytes,
    arranged in bit-fields as follows (in order of transmission):<br>
    <br>
    <div style="text-align: center;"> <span style="font-family:
        monospace;">00utpppp 01pppddd 10dddddd 11dddddd</span><br>
    </div>
    <br>
    The AGC theoretically use i/o-channel addresses from 0-511
    (decimal), so a 9-bit code would uniquely identifies any i/o port.
    It turns out that a much smaller range i/o-channel addresses was
    actually used, so we provide merely an 7-bit code <span
      style="font-family: monospace;">ppppppp</span> for identifying the
    i/o port. Similarly, <span style="font-family: monospace;">dddddddddddddddd</span>
    is the 15-bit data code. In all cases, the most-significant bit is
    the leftmost one. The LM used only channels&nbsp; 0-35 (octal). I've
    not yet found a comprehensive list of CM i/o channels; if such a
    list extends beyond&nbsp;&nbsp; 0-177 (octal), then this scheme will
    have to be altered.&nbsp; (But that seems unlikely.)<br>
    <br>
    The bit <span style="font-family: monospace;">t</span> is always
    zero for i/o channel operations.&nbsp; However, the CPU receives
    additional inputs that cannot be accessed via i/o channel
    operations.&nbsp; These additional inputs are signals from the
    spacecraft, which the CPU's "hardware" interprets as requests to
    automatically alter its various counter registers.&nbsp; We set <span
      style="font-family: monospace;">t=1</span> to indicate a packet
    that represents such a counter-modification request signal.&nbsp; In
    this case, <span style="font-family: monospace;">ppppppp</span>
    represents the counter number (which should be in the range 32-60
    octal), and <span style="font-family: monospace;">dddddddddddddddd</span>
    is the type of "unprogrammed sequence" which should be applied to
    the counter.&nbsp; (Admittedly, the allowable counter registers and
    unprogrammed-sequence operations that apply to them should be
    incorporated into <span style="font-weight: bold;">yaAGC</span>,
    but since I'm not sure yet what they all are, I provide this
    more-flexible approach instead.)&nbsp; For a list of the available
    counter registers and the list of available "unprogrammed
    sequences", refer to the <a
      href="assembly_language_manual.html#CPU_Architecture_Registers">CPU
Architecture
      section of the assembly-language manual</a>.&nbsp;
    Numerically, unprogrammed sequences are represented as follows:<br>
    <br>
    <div style="text-align: center;">
      <table summary="" style="text-align: left; margin-left: auto;
        margin-right: auto;" cellspacing="2" cellpadding="2" border="1">
        <tbody>
          <tr>
            <td style="font-weight: bold; text-align: center;
              vertical-align: middle;"> Unprogrammed<br>
              Sequence<br>
            </td>
            <td style="font-weight: bold; text-align: center;
              vertical-align: middle;"> <span style="font-family:
                monospace;"><span style="font-family: monospace;">dddddddddddddddd<br>
                </span></span> (octal)</td>
            <td style="vertical-align: top;"><br>
              <span style="font-weight: bold;">Comment</span><br>
            </td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> PINC<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 000<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> PCDU (slow)<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 001<br>
            </td>
            <td style="vertical-align: top;">(20051017 and later.)&nbsp;
              If the target counter is CDUX, CDUY, or CDUZ,&nbsp; <span
                style="font-weight: bold;">yaAGC</span> buffers these
              commands and applies them to the counter at a rate of 400
              counts per second.<br>
            </td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> MINC<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 002<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> MCDU (slow)<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 003<br>
            </td>
            <td style="vertical-align: top;">(20051017 and later.)&nbsp;
              If the target counter is CDUX, CDUY, or CDUZ,&nbsp; <span
                style="font-weight: bold;">yaAGC</span> buffers these
              commands and applies them to the counter at a rate of 400
              counts per second.</td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> DINC<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 004<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> SHINC<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 005<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> SHANC<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 006<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> INOTRD<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 007<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> INOTLD<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 010<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> FETCH<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 011<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> STORE<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 012<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> GOJ<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 013<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> TCSAJ<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 014<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> POUT<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 015<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> MOUT<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 016<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="font-family: monospace; text-align: center;
              vertical-align: middle;"> ZOUT<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 017<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;
              font-family: monospace;"> n/a<br>
            </td>
            <td style="vertical-align: top; text-align: center;"> 020<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;
              font-family: monospace;"> PCDU (fast)<br>
            </td>
            <td style="vertical-align: top; text-align: center;"> 021<br>
            </td>
            <td style="vertical-align: top;">(20051017 and later.)&nbsp;
              If the target counter is CDUX, CDUY, or CDUZ,&nbsp; <span
                style="font-weight: bold;">yaAGC</span> buffers these
              commands and applies them to the counter at a rate of 6400
              counts per second.</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;
              font-family: monospace;"> n/a<br>
            </td>
            <td style="vertical-align: top; text-align: center;"> 022<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;
              font-family: monospace;"> MCDU (fast)<br>
            </td>
            <td style="vertical-align: top; text-align: center;"> 023<br>
            </td>
            <td style="vertical-align: top;">(20051017 and later.)&nbsp;
              If the target counter is CDUX, CDUY, or CDUZ,&nbsp; <span
                style="font-weight: bold;">yaAGC</span> buffers these
              commands and applies them to the counter at a rate of 6400
              counts per second.</td>
          </tr>
        </tbody>
      </table>
      <div style="text-align: left;"> <br>
        (As an example, the CPU might receive a <span
          style="font-family: monospace;">DINC</span> message for a
        certain counter, which would cause it to update the counter,
        which might cause it to output a <span style="font-family:
          monospace;">POUT</span> message indicating that the counter
        was still positive, none of which would be under program
        control.)<br>
      </div>
    </div>
    <br>
    The bit <span style="font-family: monospace;">u</span> is covered
    in the following section. For i/o-channel operations by the CPU, or
    for counter-pulse inputs, this bit is 0.<br>
    <br>
    As many 4-byte packets as desired may be packed into a single send.
    Of course, this must be done judiciously: you have to ask yourself,
    for example, what the <span style="font-weight: bold;">yaAGC</span>
    is likely to do if receives within a single transmission both a
    packet indicating that a given input signal is turned on and another
    packet saying it has now been turned off.<br>
    <br>
    The same protocol is used by the client as by the server, since
    there is no possibility of confusing data from the two.<br>
    <br>
    Though it isn't really a significant point, since <span
      style="font-weight: bold;">yaAGC</span> is long past the point of
    being used in a high-reliability environment, the protocol has been
    designed to be fairly robust: it is always possible to distinguish
    the ordering of bytes within a packet (in case bytes are lost in
    transmission), so that corrupted packets can in some cases be
    discarded.<br>
    <h3><a name="Input-Channel_Bitmasks" id="Input-Channel_Bitmasks"></a>yaAGC
Input-Channel
      Bitmasks</h3>
    The bit <span style="font-family: monospace;">u</span> in the <span
      style="font-family: monospace;">send/recv</span> protocol doesn't
    relate to anything in the AGC, but rather addresses a potential flaw
    in the socket-based scheme for interconnecting the various
    simulations.<br>
    <br>
    Consider the following possibility. Suppose that two or more
    hardware-simulation programs communicate with the <span
      style="font-family: monospace;">yaAGC</span>, but that one of the
    input channels is used by two different hardware-simulations. In
    other words, suppose that there are input channels for which some of
    the bit positions are controlled by one of the hardware simulations,
    while other of the bit positions are controlled by another of the
    hardware simulations.<br>
    <br>
    As a concrete example, consider LM input channel 32 (octal). Bit 14
    of that channel indicates that the PROCEED key is pressed (which
    would relate to the DSKY simulation), whereas bit positions 1-10
    relate to engines (and not the DSKY simulation; let's say that they
    relate to an "engine simulation"). Now, we don't want messages from
    <span style="font-weight: bold;">yaDSKY</span> on channel 32 (octal)
    to affect these engine bits, nor do we want messages from the engine
    simulation to affect the PROCEED-key bit.<br>
    <br>
    The workaround for this problem is to allow the various hardware
    simulations to optionally send <span style="font-weight: bold;">yaAGC</span>
    a bitmask for each channel, telling <span style="font-weight:
      bold;">yaAGC</span> which bit positions of the channel it intends
    to affect. Whenever <span style="font-weight: bold;">yaAGC</span>
    receives an input-channel message from a hardare simulation, it
    applies the bitmask to the data, and only looks at the data bits
    that correspond to that bitmask.<br>
    <br>
    A hardware simulation informs <span style="font-weight: bold;">yaAGC</span>
    of a desired bitmask by transmitting a message with <span
      style="font-family: monospace;">u</span>=1. Such a message does
    not convey input-channel data; rather, it sets the bitmask for
    channel <span style="font-family: monospace;">ppppppp</span> to <span
      style="font-family: monospace;">ddddddddddddddd</span>. The
    bitmask is specific to the hardware simulation transmitting it only,
    and stays in effect forever—or at least until another message with <span
      style="font-family: monospace;">u</span>=1 is received for that
    channel. So typically, the hardware simulation would want to
    transmit the bitmasks just once, immediately upon connecting to <span
      style="font-weight: bold;">yaAGC</span>. However, they could
    theoretically be sent prior to every message.<br>
    <br>
    By default, all bitmasks are 77777 (octal), meaning that every
    hardware simulation is capable of affecting every bit-position in
    every input channel it chooses to transmit. If the socket connection
    between a hardware simulation and <span style="font-weight: bold;">yaAGC</span>
    is broken, so that the hardware simulation program needs to
    reconnect, the bitmasks for that socket are all reset to the
    default, and therefore need to be resent by the hardware simulation
    upon reconnection.<br>
    <br>
    In terms of the concrete example described above, <span
      style="font-weight: bold;">yaDSKY</span> would want to set a
    bitmask of 20000 (octal) for channel 32 (octal), to limit its
    effects to bit 14, while a LM engine simulation would want to set a
    bitmask of 01777 (octal)&nbsp; for that channel, to limit its
    effects to bits 1-10.<br>
    <br>
    Finally, note that packets transmitted by <span style="font-weight:
      bold;">yaAGC</span> always have <span style="font-family:
      monospace;">u</span>=0. It is expected that the individual
    hardware simulations are clever enough to figure out for themselves
    which bits of the output channels are applicable.<br>
    <h3><a name="Fictitious_IO_Channels" id="Fictitious_IO_Channels"></a>Fictitious
I/O
      Channels</h3>
    For the purpose of communicating various types of information
    to/from <span style="font-weight: bold;">yaAGC</span> which do not
    fall under the classification of true i/o channels or counter
    registers, I've invented various fictitious i/o channels that exist
    only within <span style="font-weight: bold;">yaAGC</span> and do
    not exist in the true AGC.&nbsp; These fictitious i/o channels are
    listed in the table below.<br>
    <br>
    <table summary="" style="text-align: left; width: 100%;"
      cellspacing="2" cellpadding="2" border="1">
      <tbody>
        <tr>
          <td style="font-weight: bold; text-align: center;
            vertical-align: bottom;"> I/O Channel Address (octal)<br>
          </td>
          <td style="font-weight: bold; text-align: center;
            vertical-align: bottom;"> Input/Output<br>
          </td>
          <td style="font-weight: bold; text-align: center;
            vertical-align: bottom;"> Description<br>
          </td>
        </tr>
        <tr>
          <td style="text-align: center; vertical-align: middle;"> 0177<br>
          </td>
          <td style="vertical-align: middle;">Output from CPU<br>
          </td>
          <td style="vertical-align: middle;">Used for simulating the
            3200 pulse-per-second signal emitted by the CPU for torquing
            the gyro during IMU fine alignment.&nbsp; Described fully in
            the discussion of i/o channel 014 below.<br>
          </td>
        </tr>
        <tr>
          <td style="text-align: center; vertical-align: middle;"> 0176<br>
          </td>
          <td style="vertical-align: middle;">Output from CPU<br>
          </td>
          <td style="vertical-align: middle;">Used for simulating the
            3200 pulse-per-second signal emitted by the CPU in response
            to counts placed in the CDUZCMD counter register (052)
            during IMU coarse alignment.&nbsp; Described fully in the
            discussion of i/o channel 014 below.</td>
        </tr>
        <tr>
          <td style="text-align: center; vertical-align: middle;"> 0175<br>
          </td>
          <td style="vertical-align: middle;">Output from CPU<br>
          </td>
          <td style="vertical-align: middle;">Same, but for CDUYCMD
            (051).<br>
          </td>
        </tr>
        <tr>
          <td style="text-align: center; vertical-align: middle;"> 0174<br>
          </td>
          <td style="vertical-align: middle;">Output from CPU<br>
          </td>
          <td style="vertical-align: middle;">Same, but for CDUXCMD
            (050).<br>
          </td>
        </tr>
        <tr>
          <td style="text-align: center; vertical-align: middle;"> 0173<br>
          </td>
          <td style="vertical-align: middle;">Input to CPU<br>
          </td>
          <td style="vertical-align: middle;"> This is for simulating
            the digital uplink.&nbsp; The data payload of input channel
            0173 is deposited directly in the INLINK counter register
            (045), and at the same time an UPRUPT interrupt is
            triggered.&nbsp; Valid data has one of the following
            bit-patterns:<br>
            <div style="text-align: center;"> <span style="font-family:
                monospace;">00000 00000 00000<br>
              </span> <span style="font-style: italic;">or</span><br>
              <span style="font-family: monospace;">ccccc CCCCC ccccc</span><br>
            </div>
            where <span style="font-family: monospace;">CCCCC</span>
            indicates the logical complement of <span
              style="font-family: monospace;">ccccc</span>.&nbsp; (In
            other words, the 15-bit data contains 3 copies of the same
            5-bit field, one of which is complemented.)&nbsp; The
            all-zero pattern is used by the ground-station for clearing
            the INLINK register after detection of error.&nbsp; In the
            other pattern, the <span style="font-family: monospace;">ccccc</span>
            field is supposed to be one of the values used by the DSKY
            for communicating keystrokes to the AGC.&nbsp; (Refer to the
            discussion of input channel 015 below.)&nbsp; That is to
            say, the ground-station sends data to the AGC in the form of
            DSKY keystrokes which have been redundantly encoded to aid
            error-detection.<br>
            <br>
            Incidentally, for experimentation, the <span
              style="font-weight: bold;">yaDSKY</span> program has a
            setting (--test-uplink) which causes it to communicate
            keystrokes to <span style="font-weight: bold;">yaAGC</span>
            via the digital uplink rather than its normal channel 015.<br>
            <br>
            <span style="font-weight: bold;">Note:</span>&nbsp; No
            similar mechanism is needed for telemetry downlinks, because
            downlinks are already handled perfectly well by the normal
            CPU output-channel mechanism.&nbsp; Output channel 013, bit
            7, contains the "downlink telemetry word order bit", output
            channel 034 contains the first downlink telemetry data word,
            and output channel 035 contains the second downlink
            telemetry data word.&nbsp; These three items together
            comprise the 31 bits for each downlinked word.&nbsp; (The
            real AGC added parity bits and filler bits to form 40 bits
            of data, but those are pretty irrelevant to the simulated
            CPU.)&nbsp; Transfer of the LM state-vector to the AEA (P47)
            is also handled by this mechanism.&nbsp; I'm not sure yet
            how transfer of the state-vector between the CM AGC and the
            LM AGC (V66) is handled; I'm beginning to think it was
            downlinked to a ground station, translated, and then
            uplinked.<br>
          </td>
        </tr>
        <tr>
          <td style="text-align: center; vertical-align: middle;"> 0172<br>
          </td>
          <td style="vertical-align: middle; text-align: left;"> Output
            from CPU<br>
          </td>
          <td style="vertical-align: middle;">Used for driving the
            optics shaft angle.&nbsp; If a count is loaded into the
            CPU's OPTXCMD counter register (054), and the appropriate
            drive bit is set (bit 11 of channel 014, see below), then
            the count in the OPTXCMD register is simply output as
            channel 0172, and the OPTXCMD register is zeroed.<br>
          </td>
        </tr>
        <tr>
          <td style="text-align: center; vertical-align: middle;"> 0171<br>
          </td>
          <td style="vertical-align: middle; text-align: left;"> Output
            from CPU<br>
          </td>
          <td style="vertical-align: middle;">Used for driving the
            optics trunnion angle.&nbsp; If a count is loaded into the
            CPU's OPTYCMD counter register (053), and the appropriate
            drive bit is set (bit 12 of channel 014, see below), then
            the count in the OPTYCMD register is simply output as
            channel 0171, and the OPTYCMD register is zeroed.</td>
        </tr>
        <tr>
          <td style="text-align: center; vertical-align: middle;"> 0170<br>
          </td>
          <td style="vertical-align: middle;">i/o<br>
          </td>
          <td style="vertical-align: middle;">Holds a count in
            1's-complement format, in the range -57 to +57, indicating
            the displacement of the rotational hand controller (RHC) in
            the roll axis.&nbsp; <span style="font-weight: bold;">yaAGC</span>
            places this value directly into the RHCR counter register
            (044).&nbsp; <span style="font-weight: bold;">yaAGC</span>
            also immediately re-emits this as an output channel, for the
            benefit of programs like <span style="font-weight: bold;">yaAGS</span>
            or <span style="font-weight: bold;">LM_Simulator</span>
            that need to know the activity of the RHC.<br>
          </td>
        </tr>
        <tr>
          <td style="text-align: center; vertical-align: middle;"> 0167<br>
          </td>
          <td style="vertical-align: middle;">i/o<br>
          </td>
          <td style="vertical-align: middle;">Same, but for the yaw axis
            (RHCY counter register, 043).<br>
          </td>
        </tr>
        <tr>
          <td style="text-align: center; vertical-align: middle;"> 0166<br>
          </td>
          <td style="vertical-align: middle;">i/o<br>
          </td>
          <td style="vertical-align: middle;">Same, but for the pitch
            axis (RHCP counter register, 042).<br>
          </td>
        </tr>
        <tr>
          <td style="text-align: center; vertical-align: middle;"> 0165<br>
          </td>
          <td style="vertical-align: middle;">Output from CPU<br>
          </td>
          <td style="vertical-align: middle;"> (Version 20050903 and
            after.)&nbsp; A "heartbeat" signal output from time to time
            by the CPU.&nbsp; Contains the current value of the TIME1
            counter register.&nbsp; TIME1 increments every 10 ms., but
            it should not be assumed that channel 0165 is output every
            10 ms.&nbsp; By default, it is output every 20 ticks of
            TIME1, and thus is output every 200 ms. of simulated
            time.&nbsp; (The default can be overridden using the
            "--heartbeat" command-line parameter of <span
              style="font-weight: bold;">yaAGC</span>.)&nbsp; Channel
            0165&nbsp; may be output more often, at the occurrence of
            critical events such as the thrusters firing or ceasing to
            fire, for which more exact timing is needed.&nbsp;
            Conversely, it may be output less often if the CPU is being
            run faster than real time (see below).&nbsp; But it is
            guaranteed to be output at least once every 16383 ticks of
            TIME1.&nbsp; Note that TIME1 wraps around after 16384
            ticks.&nbsp; Thus if the <span style="font-style: italic;">same</span>
            value is output twice in succession, it means that <span
              style="font-style: italic;">no</span> time (or at least no
            timer tick) has elapsed between the two outputs.<br>
            <br>
            Client software which has an awareness of time, such as <span
              style="font-weight: bold;">LM_Simulator</span>, <span
              style="font-weight: bold;">yaUniverse</span>, <span
              style="font-weight: bold;">yaAGS</span>, etc., should use
            channel 0165 as a timebase, rather than the system clock of
            the PC.&nbsp; If so, several advantages will be realized:<br>
            <ul>
              <li>The simulation can be sped up or slowed down simply by
                speeding up or slowing down <span style="font-weight:
                  bold;">yaAGC</span>.&nbsp; Client software will
                automatically adjust to <span style="font-weight:
                  bold;">yaAGC</span>'s speed.</li>
              <li>The simulated peripherals will be automatically paused
                or resumed if the simulated CPU is halted or resumed
                through its "--debug" interface.<br>
              </li>
            </ul>
          </td>
        </tr>
        <tr>
          <td style="vertical-align: middle; text-align: center;"> 0164<br>
          </td>
          <td style="vertical-align: middle;">Input to CPU<br>
          </td>
          <td style="vertical-align: middle;">(Version 20050903 and
            after.)&nbsp; Used to set the ratio of simulated time to
            real time.&nbsp; The value is in hundredths, so a value of 1
            means to run at 1/100 speed, a value of 10 means to run at
            1/10 speed, a value of 100 means to run in real time, and so
            on.&nbsp; Typical values would be 1, 2, 5, 10, 20, 50, 100,
            200, 500, 1000, 2000, 5000, and 10000.&nbsp; The largest
            possible value is 16383, which means to run at 163.83
            speed.&nbsp; At startup, the CPU defaults to running in real
            time (100), unless overridden by the "--speed" command-line
            parameter of <span style="font-weight: bold;">yaAGC</span>.<br>
            <br>
            The special value of 0 is used to halt the simulated CPU,
            which will remain halted until a non-zero value is input.<br>
            <br>
            If simulated peripherals use output channel 0165 rather than
            the PC clock as time base (see above), then these timing
            changes automatically propagate throughout the simulation,
            and are not confined to the CPU.<br>
          </td>
        </tr>
        <tr>
          <td valign="middle" align="center">0163<br>
          </td>
          <td valign="middle">Output from CPU to DSKY<br>
          </td>
          <td valign="top">This channel provides correct handling of
            signals which, due to hardware-implementation factors, are
            not provided to the DSKY precisely according to the values
            the AGC writes to the associated output channels (011 and
            013).&nbsp; In other words, it accounts for hardware
            handling of the signals after leaving the AGC's output
            registers.&nbsp; For example, channel 10 has KEY REL and
            OPER ERR bits that tell whether the KEY REL and OPER ERR
            signals are logically active or not, but don't account for
            the fact that in addition to the logical state of the
            signals, they are modulated by a square wave (to induce
            flashing) before reaching the DSKY. Channel 163 models this
            flashing.<br>
            <ul>
              <li>Bit 1: AGC warning</li>
              <li>Bit 4: TEMP lamp<br>
              </li>
              <li>Bit 5: KEY REL lamp<br>
              </li>
              <li>Bit 6: VERB/NOUN flash</li>
              <li>Bit 7: OPER ERR lamp</li>
              <li>Bit 8: RESTART lamp</li>
              <li>Bit 9: STBY lamp</li>
              <li>Bit 10: EL off<br>
              </li>
            </ul>
          </td>
        </tr>
      </tbody>
    </table>
    <br>
    <h2><a name="IO_Channel_Specifics" id="IO_Channel_Specifics"></a>yaAGC
I/O
      Channel Specifics</h2>
    The real AGC CPU interfaced with peripheral hardware by means of
    instructions that access "i/o channels" rather than main memory.<br>
    <br>
    In this section, I describe the exact assumptions used in Virtual
    AGC about the assignment of I/O channels to simulated hardware. Or
    to put it differently, I present information about how the real AGC
    assigned I/O channels, but I don't bother too much about channels
    for which I am not providing simulated hardware. In some cases, the
    channel interpretations differ between the LM and CM (or for all I
    know, from one Apollo mission to the next), so I try to document the
    differences, where I can, by adding document references
    underlined.&nbsp; For example, <span style="text-decoration:
      underline;">LC</span> would mean that both reference documents <span
      style="text-decoration: underline;">L</span> and <span
      style="text-decoration: underline;">C</span> supported the
    interpretation.<br>
    <br>
    The following documents are referenced:<br>
    <br>
    <span style="text-decoration: underline;">L</span><br>
    <div style="margin-left: 40px;"> Lunar-Module, Luminary 131 (1C)
      program listing. Within that listing, i/o channels are summarize
      on pp. 59-65; the "PINBALL" program, which drives the DSKY, lists
      DSKY bitcodes on pp. 403-404.<br>
    </div>
    <span style="text-decoration: underline;">C</span><br>
    <div style="margin-left: 40px;"> (At some point, will be a
      command-module program listing, but I haven't actually worked with
      it yet.)<br>
    </div>
    <h3><a name="Table_of_IO_Channels" id="Table_of_IO_Channels"></a>Table
of
      I/O Channels</h3>
    Output Channel 10 (octal)<br>
    <div style="margin-left: 40px;"> Used for driving the DSKY's
      7-segment displays. Each time a value is output in channel 10
      (octal) , it controls a pair of 7-segment displays. The output
      code contains both an identifier of the 7-segment pair which is
      supposed to be controlled, and the data which is supposed to be
      displayed in that pair.<br>
      <br>
      <div style="text-align: center;"> <img
          src="yaAGC-7segpositions.jpg" title="" alt="Output-code
          positions." style="width: 202px; height: 339px;" width="202"
          height="339"><br>
      </div>
    </div>
    <br>
    <div style="margin-left: 40px;"> Hopefully, the accompanying figure
      will clarify which 7-segment displays (and sign bits) appear at
      various positions on the DSKY. The 15-bit code output in i/o
      channel 10 (octal) can be represented in bit-fields as <span
        style="font-family: monospace;">AAAABCCCCCDDDDD</span>, where <span
        style="font-family: monospace;">AAAA</span> indicates the
      digit-pair, <span style="font-family: monospace;">B</span> sets
      or resets a +/- sign, <span style="font-family: monospace;">CCCCC</span>
      is the value for the left-hand digit of the pair, and <span
        style="font-family: monospace;">DDDDD</span> is the value for
      the right-hand digit of the pair.&nbsp; By the way, it is unclear
      to me how the +/- signs can be blanked, using the commands
      outlined below. It seems as though it would involve sending two
      output-channel commands, (say) with both 1+ and 1- bits zeroed.
      (That is the approach taken in <span style="font-weight: bold;">yaDSKY</span>:
      for each sign bit, the most recent 1+ and 1- flags are saved. If
      both are 0, then the +/- sign is blank; if 1+ is set and 1- is
      not, then the '+' sign is displayed; if just the 1- flag is set,
      or if both 1+ and 1- flags are set, the '-' sign is displayed.)<br>
      <br>
      <table summary="" style="width: 90%; text-align: left;
        margin-left: auto; margin-right: auto;" cellspacing="2"
        cellpadding="2" border="1">
        <tbody>
          <tr>
            <th style="text-align: center; vertical-align: middle;"> <span
                style="font-family: monospace;">AAAA</span><br>
            </th>
            <th style="text-align: center; vertical-align: middle;"> <span
                style="font-family: monospace;">B</span><br>
            </th>
            <th style="text-align: center; vertical-align: middle;"> <span
                style="font-family: monospace;">CCCCC</span><br>
              Represents<br>
            </th>
            <th style="text-align: center; vertical-align: middle;"> <span
                style="font-family: monospace;">DDDDD</span><br>
              Represents<br>
            </th>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              1011 (binary) = 11 (decimal)<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> <br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit M1<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit M2<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              1010 (binary) = 10 (decimal)</td>
            <td style="text-align: center; vertical-align: middle;"> <br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit V1<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit V2<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              1001 (binary) = 9 (decimal)</td>
            <td style="text-align: center; vertical-align: middle;"> <br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit N1<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit N2<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              1000 (binary) = 8 (decimal)</td>
            <td style="text-align: center; vertical-align: middle;"> <br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> <br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit 11<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              0111 (binary) = 7 (decimal)</td>
            <td style="text-align: center; vertical-align: middle;"> 1+<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit 12<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit 13<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              0110 (binary) = 6 (decimal)</td>
            <td style="text-align: center; vertical-align: middle;"> 1-<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit 14<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit 15<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              0101 (binary) = 5 (decimal)</td>
            <td style="text-align: center; vertical-align: middle;"> 2+<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit 21<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit 22<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              0100 (binary) = 4 (decimal)</td>
            <td style="text-align: center; vertical-align: middle;"> 2-<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit 23<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit 24<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              0011 (binary) = 3 (decimal)</td>
            <td style="text-align: center; vertical-align: middle;"> <br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit 25<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit 31<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              0010 (binary) = 2 (decimal)</td>
            <td style="text-align: center; vertical-align: middle;"> 3+<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit 32<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit 33<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              0001 (binary)&nbsp; = 1 (decimal)</td>
            <td style="text-align: center; vertical-align: middle;"> 3-<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit 34<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Digit 35<br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;">1100
              (binary) = 12 (decimal)</td>
            <td colspan="3" rowspan="1" style="vertical-align: top;">
              This is an exception, departing from the <span
                style="font-family: monospace;">BCCCCCDDDDD</span>
              pattern.&nbsp; Instead:<br>
              <ul>
                <li>Bit 1 lights the "PRIO DISP" indicator.</li>
                <li>Bit 2 lights the "NO DAP" indicator.<br>
                </li>
                <li>Bit 3 lights the&nbsp; "VEL" indicator.<br>
                </li>
                <li>Bit 4 lights the "NO ATT" indicator.</li>
                <li>Bit 5 lights the&nbsp; "ALT" indicator.<br>
                </li>
                <li>Bit 6 lights the "GIMBAL LOCK" indicator.</li>
                <li>Bit 8 lights the "TRACKER" indicator.</li>
                <li>Bit 9 lights the "PROG" indicator.<br>
                </li>
              </ul>
            </td>
          </tr>
        </tbody>
      </table>
      <br>
      <table summary="" style="width: 50%; text-align: left;
        margin-left: auto; margin-right: auto;" cellspacing="2"
        cellpadding="2" border="1">
        <tbody>
          <tr>
            <th style="text-align: center; vertical-align: middle;">
              Value for<br>
              <span style="font-family: monospace;">CCCCC</span> or <span
                style="font-family: monospace;">DDDDD</span><br>
            </th>
            <th style="text-align: center; vertical-align: middle;">
              Displays as<br>
            </th>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              00000 (binary) = 0 (decimal)<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              Blank<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              10101 (binary) = 21 (decimal)<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 0<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              00011 (binary) = 3 (decimal)<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 1<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              11001 (binary) = 25 (decimal)<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 2<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              11011 (binary) = 27 (decimal)<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 3<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              01111 (binary) = 15 (decimal)<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 4<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              11110 (binary) = 30 (decimal)<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 5<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              11100 (binary) = 28 (decimal)<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 6<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              10011 (binary) = 19 (decimal)<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 7<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              11101 (binary) = 29 (decimal)<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 8<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              11111 (binary) = 31 (decimal)<br>
            </td>
            <td style="text-align: center; vertical-align: middle;"> 9<br>
            </td>
          </tr>
        </tbody>
      </table>
      <br>
    </div>
    <div style="margin-left: 40px;">
      <div style="text-align: center;">
        <div style="text-align: left;"> For example, to display "+12345"
          in Register 1, the DSKY would receive the following words on
          output channel 10 (octal) :<br>
        </div>
        &nbsp;100000000000011, 011111100111011, 011000111111110 (all
        binary).<br>
      </div>
      <br>
      <a name="APOLO"></a>Incidentally, you may wonder — given that the
      <tt>CCCCC</tt> and <tt>DDDDD</tt> fields that determine what the
      7-segment displays show have 32 possible values, but that we've
      only shown 11 of them above — what the <i>other</i> possible 21
      display patterns are?&nbsp; For example, recalling that there only
      five 7-segment displays per grouping, you might think it would be
      possible to spell out the wordlet <br>
      <br>
      <div align="center"><img alt="" src="APOLO.png" width="322"
          height="90"><br>
      </div>
      <br>
      Hugh Blair-Smith actually made this amusing suggestion.&nbsp; But,
      alas, it is not possible. The page of the DSKY's electrical
      schematics that defines what patterns can be displayed is <a
href="https://archive.org/stream/acelectroniclmma00acel_0#page/n358/mode/1up">found
        here</a>, (look at relays K5, K4, ..., K1 in the
      schematic).&nbsp; All 32 of the possible patterns implied by that
      schematic have been traced out, and are shown in the leftmost
      image below (click to enlarge).&nbsp; As you can see, there is
      some duplication, so there are not even 32 distinct displayable
      patterns after all.&nbsp; Bruno Muller was kind enough to verify
      these patterns on his hardware DSKY emulator, and his are the
      right-hand images below.&nbsp; We were both a little surprised to
      find the theoretical and actual patterns to be in complete
      agreement.<br>
      <br>
      <div align="center"><a href="traceDSKY.png"><img title="Click to
            enlarge" alt="" src="traceDSKY-small.png" width="383"
            height="269" border="2"></a> &nbsp; &nbsp; <img alt=""
          src="traceDSKYA.jpg" width="646" height="269"><br>
      </div>
      <br>
    </div>
    Output Channel 11 (octal)<br>
    <div style="margin-left: 40px;"> Contains various flag bits used for
      driving individual indicator lamps, and for other purposes.&nbsp;
      Bits 1-7 are latching, while bits 8-15 are presumably one-time
      strobes. The bits which are relevant to proposed Virtual AGC
      software are:<br>
      <br>
      <table summary="" style="width: 60%; text-align: left;
        margin-left: auto; margin-right: auto;" cellspacing="2"
        cellpadding="2" border="1">
        <tbody>
          <tr>
            <th style="text-align: center; vertical-align: middle;">
              Output Bit<br>
            </th>
            <th style="vertical-align: middle; text-align: center;">
              Usage<br>
            </th>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 2<br>
            </td>
            <td style="vertical-align: middle; text-align: left;"> DSKY:
              Lights the "COMP ACTY" indicator.<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 3<br>
            </td>
            <td style="vertical-align: middle; text-align: left;">
              DSKY:&nbsp; Lights the "UPLINK ACTY" indicator.<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 4<br>
            </td>
            <td style="vertical-align: middle; text-align: left;"> DSKY:
              Lights the "TEMP" indicator. But see the "fictitious" i/o
              channel 163 discussed earlier on this page.<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 5<br>
            </td>
            <td style="vertical-align: middle; text-align: left;"> DSKY:
              Lights the "KEY REL" indicator.&nbsp; But see the
              "fictitious" i/o channel 163 discussed earlier on this
              page.<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 6<br>
            </td>
            <td style="vertical-align: middle; text-align: left;"> DSKY:
              Flashes the VERB/NOUN display areas.&nbsp; This means to
              flash the digits in the NOUN and VERB areas. But see the
              "fictitious" i/o channel 163 discussed earlier on this
              page. </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 7<br>
            </td>
            <td style="vertical-align: middle; text-align: left;"> DSKY:
              Lights the "OPR ERR" indicator.&nbsp; But see the
              "fictitious" i/o channel 163 discussed earlier on this
              page.</td>
          </tr>
        </tbody>
      </table>
      <br>
    </div>
    Output Channel 12 (octal)<br>
    <div style="margin-left: 40px;">
      <table summary="" style="width: 60%; text-align: left;
        margin-left: auto; margin-right: auto;" cellspacing="2"
        cellpadding="2" border="1">
        <tbody>
          <tr>
            <th style="text-align: center; vertical-align: middle;">
              Output<br>
              Bit<br>
            </th>
            <th style="text-align: center; vertical-align: middle;"> CM<br>
              Usage<br>
            </th>
            <td style="vertical-align: top; text-align: center;"> <span
                style="font-weight: bold;">LM</span><br
                style="font-weight: bold;">
              <span style="font-weight: bold;">Usage</span><br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 1<br>
            </td>
            <td style="vertical-align: middle; text-align: left;"> Zero
              Optics CDU<br>
            </td>
            <td style="vertical-align: top;">Zero RR CDU<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 2<br>
            </td>
            <td style="vertical-align: middle; text-align: left;">
              Enable Optics Error Counter<br>
            </td>
            <td style="vertical-align: top;">Enable RR Error Counter<br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 3<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
            <td style="vertical-align: top;">Horizontal Velocity Low
              Scale<br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 4<br>
            </td>
            <td style="vertical-align: top;">Coarse Align Enable<br>
            </td>
            <td style="vertical-align: top;">(Same as CM)</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 5<br>
            </td>
            <td style="vertical-align: top;">Zero IMU CDU's<br>
            </td>
            <td style="vertical-align: top;">(Same as CM)</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 6<br>
            </td>
            <td style="vertical-align: top;">Enable IMU Error Counters<br>
            </td>
            <td style="vertical-align: top;">(Same as CM)</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 7<br>
            </td>
            <td style="vertical-align: top;">TVC Enable<br>
            </td>
            <td style="vertical-align: top;">Display Inertial Data<br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 8<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 9<br>
            </td>
            <td style="vertical-align: top;">Enable SIVB Takeover</td>
            <td style="vertical-align: top;">+Pitch Gimbal Trim</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 10<br>
            </td>
            <td style="vertical-align: top;">Zero Optics</td>
            <td style="vertical-align: top;">-Pitch Gimbal Trim</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 11<br>
            </td>
            <td style="vertical-align: top;">Disengage Optics DAC</td>
            <td style="vertical-align: top;">+Roll Gimbal Trim</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 12<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
            <td style="vertical-align: top;">-Roll Gimbal Trim</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 13<br>
            </td>
            <td style="vertical-align: top;">SIVB Inj Sequence Start</td>
            <td style="vertical-align: top;">LR Pos Command</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 14<br>
            </td>
            <td style="vertical-align: top;">SIVB Cutoff</td>
            <td style="vertical-align: top;">RR Enable Auto Track</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 15<br>
            </td>
            <td style="vertical-align: top;">ISS Turn-on Delay Completed<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
    <br>
    <br>
    Output Channel 13 (octal)<br>
    <div style="margin-left: 40px;">
      <table summary="" style="width: 60%; text-align: left;
        margin-left: auto; margin-right: auto;" cellspacing="2"
        cellpadding="2" border="1">
        <tbody>
          <tr>
            <th style="text-align: center; vertical-align: middle;">
              Output Bit<br>
            </th>
            <th style="text-align: center; vertical-align: middle;">
              Usage<br>
            </th>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 10<br>
            </td>
            <td style="vertical-align: middle; text-align: left;">
              DSKY:&nbsp; Tests alarms and DSKY lights. But see the
              "fictitious" i/o channel 163 discussed earlier on this
              page.</td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 11<br>
            </td>
            <td style="vertical-align: middle; text-align: left;">
              DSKY:&nbsp; Lights the "STANDBY" indicator. But see the
              "fictitious" i/o channel 163 discussed earlier on this
              page. </td>
          </tr>
        </tbody>
      </table>
      <br>
      The other bits of this channel will not be described here, as they
      do not relate to any simulations currently planned for Virtual
      AGC.<br>
    </div>
    <br>
    Output Channel 14 (octal)<br>
    <div style="margin-left: 40px;"> This channel contains the following
      bits:<br>
      <table summary="" style="width: 60%; text-align: left;
        margin-left: auto; margin-right: auto;" cellspacing="2"
        cellpadding="2" border="1">
        <tbody>
          <tr>
            <td style="vertical-align: top; font-weight: bold;
              text-align: center;"> Output<br>
              Bit<br>
            </td>
            <td style="vertical-align: top; font-weight: bold;
              text-align: center;"> CM<br>
              Usage<br>
            </td>
            <td style="vertical-align: top; font-weight: bold;
              text-align: center;"> LM<br>
              Usage<br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 1<br>
            </td>
            <td style="vertical-align: top;">(Not used)<br>
            </td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 2<br>
            </td>
            <td style="vertical-align: top;">(Not used)</td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 3<br>
            </td>
            <td style="vertical-align: top;">(Not used)</td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 4<br>
            </td>
            <td style="vertical-align: top;">(Not used)</td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 5<br>
            </td>
            <td style="vertical-align: top;">(Not used)</td>
            <td style="vertical-align: top;"><br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 6<br>
            </td>
            <td style="vertical-align: top;">Gyro Enable<br>
            </td>
            <td style="vertical-align: top;">(Same as CM)<br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 7<br>
            </td>
            <td style="vertical-align: top;">Gyro Selection b*<br>
            </td>
            <td style="vertical-align: top;">(Same as CM)</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 8<br>
            </td>
            <td style="vertical-align: top;">Gyro Selection a*<br>
            </td>
            <td style="vertical-align: top;">(Same as CM)</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 9<br>
            </td>
            <td style="vertical-align: top;">Gyro Sign Minus<br>
            </td>
            <td style="vertical-align: top;">(Same as CM)</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 10<br>
            </td>
            <td style="vertical-align: top;">Gyro Activity<br>
            </td>
            <td style="vertical-align: top;">(Same as CM)</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 11<br>
            </td>
            <td style="vertical-align: top;">Drive OCDU Shaft<br>
            </td>
            <td style="vertical-align: top;">(Same as CM)</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 12<br>
            </td>
            <td style="vertical-align: top;">Drive OCDU Trunnion<br>
            </td>
            <td style="vertical-align: top;">(Same as CM)</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 13<br>
            </td>
            <td style="vertical-align: top;">Drive IMU CDU Z<br>
            </td>
            <td style="vertical-align: top;">(Same as CM)</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 14<br>
            </td>
            <td style="vertical-align: top;">Drive IMU CDU Y<br>
            </td>
            <td style="vertical-align: top;">(Same as CM)</td>
          </tr>
          <tr>
            <td style="vertical-align: top; text-align: center;"> 15<br>
            </td>
            <td style="vertical-align: top;">Drive IMU CDU X<br>
            </td>
            <td style="vertical-align: top;">(Same as CM)</td>
          </tr>
          <tr>
            <td colspan="3" rowspan="1" style="vertical-align: top;">
              *The "Gyro Selection a" and "Gyro Selection b" registers
              are paired together as follows:<br>
              <ul>
                <li>If a=0 and b=0, then no gyro is being driven.</li>
                <li>If a=0 and b=1, then the X gyro is being driven.</li>
                <li>if a=1 and b=0, then the Y gyro is being driven.</li>
                <li>if a=1 and b=1, then the Z gyro is being driven.<br>
                </li>
              </ul>
            </td>
          </tr>
        </tbody>
      </table>
      <br>
      The gyro activity in IMU fine-alignment presents a special problem
      for the recommended socket interface between the CPU and
      peripherals—and, I suppose, any other reasonable interface—in that
      the method the CPU uses to drive the gyros is to output a 3200
      pulse-per-second signal when the Gyro Activity output bit is
      active, with the assumption that the gyros will know how many of
      the gyro-driving pulses have been emitted.&nbsp; This leaves the
      software emulating the gyro with the problem of determining the <span
        style="font-style: italic;">exact</span> number of pulses, which
      it cannot really do without some additional assistance.&nbsp;
      (Thanks to Stephan Hotto for pointing this out.)&nbsp; I therefore
      provide a workaround for this problem, which should be useful
      regardless of the nature of the interface between the emulated CPU
      and gyro, and should be insensitive to halting the CPU with the
      debugger.&nbsp; The method is to implement a fictitious output
      port which does not appear in the actual CPU, that has the
      following properties:<br>
      <ul>
        <li>The address of the fictitious "Gyro Pulse" i/o channel is
          0177 (octal).&nbsp; Under appropriate conditions (see below)
          this fictitious i/o channel is output by the <span
            style="font-weight: bold;">yaAGC</span> program
          automatically, transparently to the <span style="font-weight:
            bold;">Colossus</span> or <span style="font-weight: bold;">Luminary</span>
          program.<br>
        </li>
        <li>The 15-bit data (<span style="font-family: monospace;">ddd
            dddddd dddddd</span>) of the channel is subdivided into 2
          parts:&nbsp; the most-significant 4 bits are the same as bits
          6-9 of channel 14, and the least-significant 11 bits contain a
          count of the number of gyro pulses since the last time channel
          177 was output.&nbsp; (Bit 15 will be the same as "Gyro Sign
          Minus", bit 14 will be "Gyro Selection a", bit 13 will be
          "Gyro Selection b", and bit 12 will be "Gyro Enable".)<br>
        </li>
        <li>Channel 177 is output while Gyro Activity is 1 and the
          GYROCTR counter register is non-zero, nominally every 1/4
          second.&nbsp; (The count will nominally be 01440, out of a
          maximum allowable 03777.)&nbsp; The GYROCTR register is
          decremented by the number of pulsed emitted when this happens.<br>
        </li>
        <li>If any of bits 6-10 in channel 14 change, channel 177 is
          output immediately with either the remainder of the pulses
          from GYROCTR or else a pro-rated number of pulses based on
          elapsed time.<br>
        </li>
      </ul>
    </div>
    <div style="margin-left: 40px;"> For IMU Coarse Alignment, the IMU
      CDU X,Y,Z bits (13,14,15) bits present similar difficulties.&nbsp;
      When the IMU CDU drive bits are set, the number of output pulses
      specified by the CDUXCMD, CDUYCMD, and CDUZCMD registers
      (addresses 50,51,52) is supposed to be emitted.&nbsp; These pulses
      are supposed to be emitted in bursts of 192 pulses each (at 3200
      pulses per second, thus occupying 60 ms.), with gaps of 540 ms.
      between bursts.&nbsp; It is rather inefficient in emulation terms
      to emit individual pulses at 3200 pps, so we implement this as
      follows:<br>
      <ul>
        <li>We define new fictitious,&nbsp; i/o channels at addresses
          0174, 0175, and 0176 (octal), for the X, Y, and Z axes
          respectively.&nbsp; The <span style="font-weight: bold;">yaAGC</span>
          program automatically writes to these output channels every
          600 ms. as long as any of the Drive IMU CDU bits in channel 14
          are active while the corresponding CDUxCMD registers are
          non-zero.</li>
        <li>The 15-bit data (<span style="font-family: monospace;">ddd
            dddddd dddddd</span>) of the channel is the number of IMU
          CDU drive pulses since the last time the fictitious channel
          was output.&nbsp; The most-significant bit indicates the
          direction of movement (0 is positive and 1 is negative), while
          the least-significant 14 bits represent the count.&nbsp; For
          example, 192 in the positive direction would be 000 000011
          000000, while 192 in the negative direction would be 100
          000011 000000.<br>
        </li>
        <li>Usually, the pulse-count will be 192 (decimal).&nbsp;
          However, at the end of the drive sequence, there will
          generally be a smaller count.<br>
        </li>
        <li>The CDUxCMD registers 50,51,52 will automatically be counted
          down by <span style="font-weight: bold;">yaAGC</span>.&nbsp;
          Also, the IMU CDU drive bits will be automatically reset to 0
          when the sequence completes.&nbsp; I <span style="font-style:
            italic;">hope</span> this corresponds to real AGC's
          behavior, but I don't really know.</li>
      </ul>
      Note that <span style="font-weight: bold;">yaAGC</span> does not
      attempt to condition this behavior on bits 4 &amp; 6 of channel
      12, which are normally supposed to be prerequisites for the IMU
      CDU drive sequence.&nbsp; In other words, the pulses will be
      output regardless of the settings of bits 4 &amp; 6 of channel 12.<br>
    </div>
    <br>
    Input Channel 15 (octal)<br>
    <div style="margin-left: 40px;"> Used for inputting keystrokes from
      the DSKY. There are 19 keys, and a 5-bit keycode appears in bits
      5-1 of this input channel.&nbsp; A keystroke triggers interrupt
      #5, causing the software to examine the channel. However, the
      interrupt mechanism occurs entirely within <span
        style="font-weight: bold;">yaAGC</span>, and should not be of
      concern to a DSKY developer. I believe that the keycode appears
      when the key is newly pressed, and then disappears, but I can't
      prove that at the moment.<br>
      <br>
      <table summary="" style="width: 50%; text-align: left;
        margin-left: auto; margin-right: auto;" cellspacing="2"
        cellpadding="2" border="1">
        <tbody>
          <tr>
            <th style="text-align: center; vertical-align: middle;"> Key<br>
            </th>
            <th style="text-align: center; vertical-align: middle;">
              Keycode<br>
            </th>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 0<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              10000 (binary) = 16 (decimal) = 20 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 1<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              00001 (binary) = 1 (decimal) = 1 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 2<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              00010 (binary) = 2 (decimal) = 2 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 3<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              00011 (binary) = 3 (decimal) = 3 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 4<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              00100 (binary) = 4 (decimal) = 4 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 5<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              00101 (binary) = 5 (decimal) = 5 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 6<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              00110 (binary) = 6 (decimal) = 6 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 7<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              00111 (binary) = 7 (decimal) = 7 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 8<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              01000 (binary) = 8 (decimal) = 10 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> 9<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              01001 (binary) = 9 (decimal) = 11 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              VERB<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              10001 (binary) = 17 (decimal) = 21 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              RSET<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              10010 (binary) = 18 (decimal) = 22 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> KEY
              REL<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              11001 (binary) = 25 (decimal) = 31 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> +<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              11010 (binary) = 26 (decimal) = 32 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> -<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              11011 (binary) = 27 (decimal) = 33 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              ENTR<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              11100 (binary) = 28 (decimal) = 34 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> CLR<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              11110 (binary) = 30 (decimal) = 36 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;">
              NOUN<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              11111 (binary) = 31 (decimal) = 37 (octal)<br>
            </td>
          </tr>
          <tr>
            <td style="text-align: center; vertical-align: middle;"> PRO
              or STBY<br>
            </td>
            <td style="text-align: center; vertical-align: middle;">
              (See below.)<br>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
    <br>
    Input Channel 32 (octal)<br>
    <div style="margin-left: 40px;"> Bit 14 set indicates that the PRO
      (STBY) key is currently pressed.&nbsp; The logic is inverted, so
      that the bit becomes 0 when the key is pressed, and is 1 when the
      key is not pressed.<br>
      <br>
      The other bits of this channel relate to the engines, and will not
      be described here since Virtual AGC presently includes no engine
      simulations.<br>
    </div>
    <h2><a name="A_Template_Program_for_Creating_Simple"></a>A Template
      Program for Creating Simple yaAGC Peripherals</h2>
    <p><a href="#Internals_of_the_yaDSKY_Program">The <i>next</i>
        section</a> discusses some design details of a fairly
      substantial simulated peripheral device, the DSKY.&nbsp; However,
      the learning curve is somewhat steep, and sometimes one simply
      wants to throw something together quickly without the burden of
      dealing with cross-platform graphical toolsets, C++, and so on.<br>
    </p>
    <p>There is a very bare-bones Python 3 program, <a
href="https://github.com/virtualagc/virtualagc/blob/master/piPeripheral/piPeripheral.py">piPeripheral.py</a>,
      which can be adapted to create simple peripheral devices that
      don't need to be high-performance.&nbsp; What this program does is
      connect to a running instance of <b>yaAGC</b> — which it
      hardcodes as host "localhost" at port 19798, though you can change
      that if necessary — and handles all of the network packets
      associated with the AGC's i/o channels.&nbsp; Whenever the AGC
      writes to an output channel, it calls a function<br>
    </p>
    <div align="center"><tt>outputFromAGC(channel, value)</tt><br>
    </div>
    <p>which you are free to handle however you like.&nbsp; Conversely,
      from time to time it calls the function<br>
    </p>
    <div align="center"><tt>inputsForAGC()</tt><br>
    </div>
    <p>Again, you are free to fill up <tt>inputsForAGC()</tt> with any
      content you like, and the program will automatically send that
      content from <tt>inputsForAGC()</tt> to the AGC, to appear in its
      input channels.&nbsp; Specifically, <tt>inputsForAGC()</tt> must
      return a Python "list" which contains Python "3-tuples" describing
      the data for whatever input channels you want to change:<br>
    </p>
    <p align="center"><tt>[ (<i>CHANNEL0</i>,<i>VALUE0</i>,<i>MASK0</i>),
        (<i>CHANNEL1</i>,<i>VALUE1</i>,<i>MASK1</i>), ...]</tt><br>
    </p>
    <p>where the "channels" are the input-channel numbers, the "values"
      are the values to write into those input channels, and the "masks"
      are bit-masks determining which of the bits in the values are
      valied. The output list may be empty, in which case there is
      currently no new data to write to the AGC.&nbsp; For example, <tt>[(0o15,0o31,0o37)]</tt>
      would indicated that the lowest 5 bits of channel 15 (octal) were
      valid, and that the value of those bits were 11001 (binary), which
      collectively indicate that the KEY REL key on a DSKY was
      pressed.&nbsp; (In Python 3, octal constants are prefixed by
      "0o".)<br>
    </p>
    <p>There is a second Python 3 program, <a
href="https://github.com/virtualagc/virtualagc/blob/master/piPeripheral/piDSKY.py">piDSKY.py</a>,
      which fleshes out the <tt>outputFromAGC()</tt> and <tt>inputsForAGC()</tt>
      functions in piPeripheral.py, illustrating how to use
      piPeripheral.py to create a simple DSKY.&nbsp; The actual
      operation of piDSKY.py is very simple, in that it simply accepts
      keyboard commands in place of a DSKY keypad (namely the keys
      0123456789+-VNCPKR and Enter) and displays incoming DSKY
      output-channel writes from the AGC as simple text messages on
      stdout.<br>
    </p>
    <h2><a name="Internals_of_the_yaDSKY_Program"
        id="Internals_of_the_yaDSKY_Program"></a>Internals of the
      yaDSKY/yaDSKY2 Program</h2>
    Anyone interested in creating additional back-end hardware
    simulations for <span style="font-weight: bold;">yaAGC</span>, or
    in altering or replacing the <span style="font-weight: bold;">yaDSKY</span>
    program, will probably be interested in the architecture and other
    internal details of <span style="font-weight: bold;">yaDSKY</span>.&nbsp;
    <span style="font-weight: bold;">yaDSKY</span> is actually an
    extremely simple program to understand and to modify. Though
    targeted for a UNIX-type operating environment (such as Linux), all
    design tradeoffs have been made in favor of simplicity and
    portability, as opposed to performance or aesthetics.<br>
    <h3><a name="Interface_to_yaAGC" id="Interface_to_yaAGC"></a>Interface
to
      yaAGC</h3>
    As mentioned earlier, the AGC interacted with hardware such as the
    DSKY through the AGC's "i/o channel" mechanism. The i/o-channel
    mechanism, in turn, either drove control signals through wires or
    else received signals from peripheral devices through wires.<br>
    <br>
    For simulation purposes, the "wires" (and hence the AGC i/o
    channels) are replaced by the mechanism of "sockets".&nbsp; <span
      style="font-weight: bold;">yaAGC</span> acts as a "server" to
    which client simulations like <span style="font-weight: bold;">yaDSKY</span>
    can connect. By default, <span style="font-weight: bold;">yaAGC</span>
    listens for connections on 5 ports, 19697-19701. One
    simulated-hardware client can connect on each port, so up to 5
    hardware simulations can be attached to the simulated computer at
    any time. (The number 5 is arbitrary, and can be increased by
    recompilation of <span style="font-weight: bold;">yaAGC</span>.)<br>
    <br>
    <span style="font-weight: bold;">yaAGC</span> does not distinguish
    between the ports, so any type of hardware simulation—if there ever
    is more than one—can connect on any port. Or, multiple simulations
    of the same kind can connect. For example, two or more DSKY
    simulations can be run at the same time from one AGC simulation.<br>
    <h3><a name="Software_Architecture" id="Software_Architecture"></a>Software
      Architecture</h3>
    The <span style="font-weight: bold;">yaDSKY</span> program is
    event-driven. What this means, in essence, is that when a keyboard
    key is pressed in the simulation, the <span style="font-weight:
      bold;">yaDSKY</span> client transmits a message via socket to the
    <span style="font-weight: bold;">yaAGC</span> server; <span
      style="font-weight: bold;">yaAGC</span> interprets this message as
    data on an "input channel". Similarly, when <span
      style="font-weight: bold;">yaAGC</span> wishes to put data on an
    "output channel", it transmits a message via socket to <span
      style="font-weight: bold;">yaDSKY</span> (and other clients); <span
      style="font-weight: bold;">yaDSKY</span> interprets this message
    in terms of the desired conditions of its indicator lights, and
    drives those lights accordingly. These actions all take place in the
    source file callbacks.c.<br>
    <br>
    For portability and reliability purposes, the design choice has been
    made additionally to have a function (called <span
      style="font-family: monospace;">Pulse</span>, in main.c) which is
    executed at regular intervals—nominally, every 50 milliseconds. This
    function handles establishing a connection from the server, or
    disconnecting from it. Also, it polls for new incoming socket data.<br>
    <br>
    Some functions which are used in common with the <span
      style="font-weight: bold;">yaAGC</span> program—namely, some
    socket-manipulation functions and some functions for creating or
    parsing the data packets passed through the sockets—appear in the <span
      style="font-weight: bold;">yaAGC</span> source code rather than in
    the <span style="font-weight: bold;">yaDSKY</span> source code. In
    building <span style="font-weight: bold;">yaAGC</span>, both a
    stand-alone program and a linkable library (libyaAGC.a) are created.
    A hardware-simulation like <span style="font-weight: bold;">yaDSKY</span>
    can use these functions by linking to the library. The available
    library functions are described below.<br>
    <h3><a name="GUI" id="GUI"></a>GUI</h3>
    As may be deduced from the description above, <span
      style="font-weight: bold;">yaDSKY</span>'s graphical user
    interface is highly independent of any underlying computations or
    communications which are occurring. It hardly matters what method is
    used to create the GUI. Basically, any graphical toolkit having the
    following features can be used:<br>
    <ul>
      <li>Pushbutton widgets with graphical legends.</li>
      <li>Pixel-map widgets which can be loaded from files at runtime.</li>
      <li>The ability to execute a function at regular intervals.<br>
      </li>
    </ul>
    For <span style="font-weight: bold;">yaDSKY</span>, the <span
      style="font-weight: bold;">gtk+</span> graphical toolkit (2.0 or
    higher) was used, and the <span style="font-weight: bold;">Glade</span>
    tool (2.0 or higher) was used to create the GUI.&nbsp; It was
    subsequently realized that the choice of <span style="font-weight:
      bold;">gtk+</span> had compromised portability to the Mac OS X
    platform and even (to a certain extent) to the MS Windows
    platform.&nbsp; This was one of the motivations for replacement of <span
      style="font-weight: bold;">yaDSKY</span> by the program <span
      style="font-weight: bold;">yaDSKY2</span>.&nbsp; <span
      style="font-weight: bold;">yaDSKY2</span> is instead based on the
    <span style="font-weight: bold;">wxWidgets</span> toolkit (2.8.9 or
    higher), with the <span style="font-weight: bold;">wxGlade</span>
    tool being used to create the GUI.<br>
    <br>
    Similar considerations have resulted in replacement of the <span
      style="font-weight: bold;">gtk+</span> based <span
      style="font-weight: bold;">yaDEDA</span> program by the <span
      style="font-weight: bold;">wxWidgets</span> based <span
      style="font-weight: bold;">yaDEDA2</span> program, replacement of
    the <span style="font-weight: bold;">Allegro</span> based <span
      style="font-weight: bold;">yaACA</span> program by the <span
      style="font-weight: bold;">wxWidgets</span> based <span
      style="font-weight: bold;">yaACA2</span> program, and creation
    from scratch of the <span style="font-weight: bold;">wxWidgets</span>
    based <span style="font-weight: bold;">VirtualAGC</span>
    program.&nbsp; As of March 2009, <span style="font-weight: bold;">wxWidgets</span>
    is the sole cross-platform GUI toolkit being used, and all of the
    programs based on other toolkits are kept as legacy code but no
    longer maintained.<br>
    <h3><a name="Indicator_Legends_and_Configuration_"
        id="Indicator_Legends_and_Configuration_"></a>Indicator Legends
      and Configuration (ini) file<br>
    </h3>
    <div style="text-align: center;"> <img src="yaAGC-indpositions.jpg"
        title="" alt="Indicator positions." style="width: 195px; height:
        329px;" width="195" height="329"><br>
      <br>
    </div>
    The indicator legends in the upper-left quadrant of the <span
      style="font-weight: bold;">yaDSKY</span> panel are not hard-coded
    into <span style="font-weight: bold;">yaDSKY</span>, but rather are
    provided as a set of graphics files. Therefore, they can be changed
    at runtime, to indicate the differences between an LM simulation vs.
    a CM simulation, or possibly the differences between different
    Apollo missions.<br>
    <br>
    There are two graphics files for each indicator—one lit and one
    dark. Therefore, each set of legends consists of 28 graphics
    files.&nbsp; These graphic files, along with the graphic file for
    the PRO key (i.e., the keypad key between CLR and KEY REL) and the
    relationships of the indicator lamps to CPU "output channels", is
    controlled by a configuration file loaded by <span
      style="font-weight: bold;">yaDSKY</span> at startup.&nbsp; By
    default, the configuration file is LM.ini, but additional
    configuration files (CM.ini and CM0.ini at this writing) also exist,
    and may be selected on the <span style="font-weight: bold;">yaDSKY</span>
    command line.&nbsp; Full explanation of creation/modification of
    configuration files appears in the comments within LM.ini.<br>
    <br>
    The indicator-lamp graphics files are in the XPM format, and are
    84×40 RGB. (I created the distribution files using The GIMP.) For
    the purpose of building <span style="font-weight: bold;">yaDSKY</span>,
    all graphic files need to be stored in the directory
    yaDSKY/src/pixmaps (assuming that <span style="font-weight: bold;">yaDSKY</span>
    source code is in a directory named yaDSKY.)&nbsp; Furthermore, the
    graphics need to be installed in a particular directory to be
    accessible by <span style="font-weight: bold;">yaDSKY</span> at
    runtime; if <span style="font-weight: bold;">yaDSKY</span> is built
    as the distribution version is built, this directory is
    /usr/local/share/yadsky/pixmaps, but copying the graphic files into
    this directory is automatically done with "make install".<br>
    <h2><a name="libyaAGC.a" id="libyaAGC.a"></a>Virtual AGC Library API<br>
    </h2>
    If for some reason you don't care to use the provided <span
      style="font-weight: bold;">yaAGC</span>/<span style="font-weight:
      bold;">yaDSKY/yaAGS/yaDEDA</span> software but wish to use the
    underlying CPU simulation engine, or if you want to create add-ons
    to Virtual AGC without hacking, you can simplify your work by
    building a C program around the functions provided in the library
    libyaAGC.a.&nbsp; Undoubtedly, the library can also be trivially
    modified to allow use by C++ programs.&nbsp; To use the library
    functions, simply <span style="font-family: monospace;">#include
      "agc_engine.h"</span> and then add "<span style="font-family:
      monospace;">-lyaAGC</span>" to your <span style="font-weight:
      bold;">gcc</span> command-line.<br>
    <br>
    Note that the debug interface (breakpoints, single-stepping, etc.)
    is provided by the <span style="font-weight: bold;">yaAGC</span>
    application program rather than by the library, so if you want a
    debug interface you'll have to implement your own.&nbsp; The only
    exception to this is that backtrace functionality is built into the
    library.<br>
    <h3><a name="Useful_AGC_Datatypes_and_Constants"
        id="Useful_AGC_Datatypes_and_Constants"></a>Useful Datatypes and
      Constants</h3>
    <span style="font-family: monospace;">agc_t</span> (<span
      style="font-weight: bold;">yaAGC</span>)<span style="font-family:
      monospace;"><br>
      <br>
    </span> This datatype is a structure intended to hold all
    information about the current state of the emulated AGC CPU, such as
    the contents of memory, the contents of i/o registers, and so
    forth.&nbsp; Pointers to this structure are passed explicitly to all
    functions in the library which need to know the CPU state.&nbsp;
    Placing all of this information in a structure, rather than keeping
    it as global data, makes it much easier to write a monolithic
    program that simultaneously emulates multiple AGCs, such as a CM AGC
    and an LM AGC.&nbsp; Eventually, I'll probably describe a lot of the
    fields in this structure; for right now, just take a look at
    agc_engine.h if you want to know more.<br>
    <br>
    <span style="font-family: monospace;">int8_t</span>, <span
      style="font-family: monospace;">int16_t</span>, <span
      style="font-family: monospace;">uint16_t</span> (<span
      style="font-weight: bold;">yaAGC</span> /<span style="font-weight:
      bold;">yaAGS</span>/peripherals)<br>
    <br>
    In most cases when an integer is needed, the software employs the
    native <span style="font-family: monospace;">int</span> or <span
      style="font-family: monospace;">unsigned</span> datatypes.&nbsp;
    However, where it is important to know the exact integer precision,
    the <span style="font-family: monospace;">int8_t</span>, <span
      style="font-family: monospace;">int16_t</span>, or <span
      style="font-family: monospace;">uint16_t</span> datatypes are
    used.&nbsp; In particular, emulated memory (including CPU central
    registers and counter registers) are of the <span
      style="font-family: monospace;">int16_t</span> datatype.&nbsp; <span
      style="font-weight: bold; color: rgb(0, 0, 0);">Important note:</span><span
      style="color: rgb(0, 0, 0);">&nbsp; In most cases, data stored in</span><span
      style="font-family: monospace; color: rgb(0, 0, 0);">int16_t</span><span
      style="color: rgb(0, 0, 0);">format for use in <span
        style="font-weight: bold;">yaAGC</span> will be in the
      1's-complement format used by the AGC CPU rather than in the
      (probably) 2's-complement format used by your native CPU.&nbsp;
      (This is not a problem with 2's-complement <span
        style="font-weight: bold;">yaAGS</span> internal data.)&nbsp;
      Therefore, when operations are performed on</span> <span
      style="font-family: monospace; color: rgb(0, 0, 0);">int16_t</span><span
      style="color: rgb(0, 0, 0);">data, you must take special care
      to insure that the operations are appropriate to AGC
      integers.&nbsp; For example, if you had two integers <span
        style="font-family: monospace;">i1</span> and <span
        style="font-family: monospace;">i2</span> in AGC format, the
      C-language operation <span style="font-family: monospace;">i1+i2</span>
      will often not produce the correct sum in AGC format; the
      appropriate operation would instead be <span style="font-family:
        monospace;">AddSP16(i1,i2)</span> (see below).&nbsp; Another
      very important point to understand is the concept of
      "overflow".&nbsp; Integers in AGC format are 1's complement
      integers occupying the least significant 15 bits of an <span
        style="font-family: monospace;">int16_t</span> value.&nbsp; The
      16th bit is usually an exact copy of the 15th bit.&nbsp; However,
      if there is <span style="font-style: italic;">overflow</span>
      from an operation, then the 15th and 16th bits are opposites, <span
        style="font-style: italic;">and it is the 16th bit which is
        considered to be the correct sign</span>.&nbsp; With
      2's-complement arithmetic, we normally allow additive overflow to
      occur in such a way that incrementing the largest positive number
      rolls around to the largest negative number.&nbsp; With AGC
      1's-complement arithmetic, however, incrementing the largest
      positive number rolls around to +0 "with overflow".&nbsp; Consider
      the following simple example:&nbsp; The largest possible positive
      value of an AGC single-precision integer is 2<sup>14</sup>-1=16383.&nbsp;
Therefore,
      the operation of 16383+1 will overflow.&nbsp; In terms
      of bits, this operation results in 01 000000 000000.&nbsp; The
      mismatch between the most significant bits is an indication of
      overflow.&nbsp; The actual value is given by the 16th bit and the
      lowest 14 bits, or +0.&nbsp; To "overflow correct" this value
      would be to eliminate the overflow mismatch by copying bit 16 into
      bit 15.&nbsp; There is a value in many cases to retaining the
      overflow without correcting it, and many AGC instructions do not
      correct the overflow; however, an explanation of all the things
      you can do with non-overflow-corrected values is a bit beyond our
      scope here.</span>
    <h3><a name="AGC_CPU-to-Peripheral_Interconnections"
        id="AGC_CPU-to-Peripheral_Interconnections"></a>CPU-to-Peripheral
Interconnections
      API</h3>
    This is perhaps the most important part of the AGC API, because it
    is disatisfaction with (or lack of understanding of) Virtual AGC's
    CPU-to-peripheral interface which most commonly causes people to
    hack <span style="font-weight: bold;">yaAGC</span> rather than
    interfacing to it gracefully, and thus depriving themselves of
    easily using future improvements to the software.&nbsp; As described
    above, the default CPU-to-peripheral interface involves using <span
      style="font-weight: bold;">yaAGC</span> as a server for socket
    connections, and the peripheral devices (such as <span
      style="font-weight: bold;">yaDSKY</span>) as clients.&nbsp; This
    socket interface has many advantages, not least of which being that
    it is very portable and reasonably-elegantly emulates the wired
    connections of the original hardware.&nbsp; However, if for some
    reason the socket interface is ineffective or distasteful for your
    purposes, you can completely replace it by some other type of
    interface (such as shared memory) simply by replacing 3 library
    functions.&nbsp; In fact, you don't even need to replace them in the
    library:&nbsp; Just create and link in your own versions of these
    functions, and the linker won't even both to try and load the
    default functions from the library; start with the file NullAPI.c
    and fill in the template functions I've provided there with whatever
    you like!&nbsp;&nbsp; Then rebuild <span style="font-weight: bold;">yaAGC</span>
    and <span style="font-weight: bold;">yaDSKY</span> using these new
    functions.&nbsp; <span style="font-style: italic;">Voila</span>!&nbsp;
New
    <span style="font-weight: bold;">yaAGC</span>-to-<span
      style="font-weight: bold;">yaDSKY</span> interface with no code
    changes directly in <span style="font-weight: bold;">yaAGC</span>
    or <span style="font-weight: bold;">yaDSKY</span>!<br>
    <br>
    <span style="font-family: monospace;">void ChannelOutput (agc_t *
      State, int Channel, int Value);</span> (<span style="font-weight:
      bold;">yaAGC</span> only)<br>
    <span style="font-family: monospace;"><br>
    </span> The simulated AGC CPU calls this function whenever it wants
    to write output data to an "i/o channel", other than i/o channels 1
    and 2, which are overlapped with the L and Q central
    registers.&nbsp; For example, in an embedded design, this would
    physically control the individual electrical signals comprising the
    i/o port.&nbsp; In my recommended socket-based design, data is
    streamed out a socket connection from a port.&nbsp;&nbsp;<br>
    <br>
    In a customized version, <span style="font-style: italic;">for
      example</span>, data might be written to a shared memory array,
    and other execution threads might be woken up to process the changed
    data.&nbsp;&nbsp; A factor people sometimes forget when they
    visualize the CPU's output space as an array of shared memory is
    that your virtual peripherals need to react to every change of the
    shared memory array.&nbsp; Consider, for example, the case of the
    i/o registers used to interface the CPU to the DSKY.&nbsp; If your
    CPU writes data to these registers and then overwrites that data
    before your simulated DSKY can read it, then your DSKY's display
    will act very erratically, and won't display all the data it's
    supposed to.&nbsp; (That's another virtue of the socket interface,
    by the way:&nbsp; No data is lost through overwriting.)<br>
    <br>
    Note also that some output channels are latched by relays external
    to the CPU.&nbsp; For example, 4 bits of channel 10 (octal) select
    one of 16 rows of latches.&nbsp; Therefore, the 15-bit channel 10 is
    effectively 16 separate 11-bit registers.&nbsp; You may need to
    account for this in your model.<br>
    <br>
    <span style="font-family: monospace;">int ChannelInput (agc_t *
      State);</span> (<span style="font-weight: bold;">yaAGC</span>
    only)<span style="font-family: monospace;"><br>
    </span> <span style="font-family: monospace;"><br>
    </span> The simulated AGC CPU calls this function to check for input
    data once for each call to <span style="font-family: monospace;">agc_engine</span>
    (see below).&nbsp; This input data may be of two kinds:<br>
    <ol>
      <li>Data available on an "i/o channel"; in this case, a value of 0
        should be returned; you can handle as much or as little data of
        this kind in any given invocation.&nbsp; But remember that if
        you process more than one datum targeted at the same i/o
        register, there's no chance at all that the simulated CPU can
        react to anything other than the final datum.<br>
      </li>
      <li>A request for an "unprogrammed sequence" to automatically
        increment or decrement a counter.&nbsp; In this case a value of
        1 should be returned.&nbsp; The function must return immediately
        upon one of these requests, in order to preserve accurate system
        timing.</li>
    </ol>
    The former type of data is supposed to be directly written to the
    array <span style="font-family: monospace;">State-&gt;InputChannel[]</span>,
    while the latter is supposed to call the function <span
      style="font-family: monospace;">UnprogrammedIncrement()</span>
    (see below) to handle the actual incrementing.&nbsp; <span
      style="font-family: monospace;">ChannelInput()</span> has the
    responsibility of raising an interrupt-request flag (in the array <span
      style="font-family: monospace;">State-&gt;InterruptRequests[]</span>)
    if the i/o channel data is supposed to cause an interrupt.&nbsp; (An
    example would be if the input data represented a DSKY
    keystroke.)&nbsp; Interrupt-raising due to overflow of counters is
    handled automatically by the function <span style="font-family:
      monospace;">UnprogrammedIncrement()</span> and doesn't need to be
    addressed directly.<br>
    <br>
    For example, in an embedded design, this input data would reflect
    the physical states of individual electrical signals.&nbsp; In my
    recommended socket-interface, the data is taken from the incoming
    stream of a socket connection to a port.&nbsp; In a customized
    version, <span style="font-style: italic;">for example</span>, data
    might indicate changes in a shared memory array partially controlled
    by other execution threads.&nbsp;&nbsp;<br>
    <br>
    <span style="font-weight: bold;">Note:</span>&nbsp; You are
    guaranteed that <span style="font-weight: bold;">yaAGC</span>
    processes at least one AGC instruction between any two calls to <span
      style="font-family: monospace;">ChannelInput</span>.<br>
    <br style="font-family: monospace;">
    <span style="font-family: monospace;">void ChannelRoutine (agc_t
      *State);</span> (<span style="font-weight: bold;">yaAGC</span>
    only)<br>
    <br>
    This function is just called every so often by the AGC CPU.&nbsp;
    You can use it for anything that might require routine but
    infrequent processing by your i/o interconnection model.&nbsp; For
    example, in my recommended socket-interface, it is used for
    establishing and retiring client/server socket connections.&nbsp;
    There are no good reasons that I know of why this would be needed
    otherwise, so you might just want to let this function return
    immediately.<br>
    <br>
    <span style="font-family: monospace;">int CallSocket (char
      *hostname, unsigned short portnum);</span> (peripherals)<br>
    <br>
    This function is not needed if you replace the default socket
    interface by another interface of your own devising, as described
    above.&nbsp; The function is called by a client program (such as an
    emulated peripheral) to establish a socket connection to a <span
      style="font-weight: bold;">yaAGC</span> or <span
      style="font-weight: bold;">yaAGS</span> server.&nbsp; The return
    value is the socket number, or else -1 on error.&nbsp; If -1 is
    returned, then the variable <span style="font-family: monospace;">ErrorCodes</span>
    will contain one of the following:<br>
    <div style="margin-left: 40px;">
      <table summary="" style="text-align: left;" cellspacing="2"
        cellpadding="2" border="1">
        <tbody>
          <tr>
            <td style="vertical-align: top;">0x301<br>
            </td>
            <td style="vertical-align: top;">Unable to resolve host.<br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top;">0x302<br>
            </td>
            <td style="vertical-align: top;">Unable to create socket.<br>
            </td>
          </tr>
          <tr>
            <td style="vertical-align: top;">0x303<br>
            </td>
            <td style="vertical-align: top;">Unable to make connection
              on&nbsp; socket.<br>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
    You need to retain the returned socket number, so that you can use
    it with the <span style="font-family: monospace;">send</span> and <span
      style="font-family: monospace;">recv</span> functions to actually
    send and receive data.<br>
    <br>
    <span style="font-family: monospace;">int FormIoPacket (int Channel,
      int Value, unsigned char *Packet);</span> (<span
      style="font-weight: bold;">yaAGC</span>/peripherals)<br>
    <br>
    This function constructs an i/o-channel packet or a counter
    increment/decrement packet in the <span style="font-weight: bold;">yaAGC</span>
    format.&nbsp; For i/o-channel operations, the function takes an i/o
    channel number (<span style="font-family: monospace;">Channel</span>,
    in the range 0-127) and a 15-bit value for it (<span
      style="font-family: monospace;">Value</span>), and constructs a
    4-byte packet (<span style="font-family: monospace;">Packet</span>)
    in a form suitable for transmission to/from <span
      style="font-weight: bold;">yaAGC</span> via the <span
      style="font-family: monospace;">send</span> function.&nbsp; Space
    for the packet must have been allocated by the calling
    program.&nbsp; The packet is as specified above:<br>
    <br>
    <div style="text-align: center;"> <span style="font-family:
        monospace;">00utpppp 01pppddd 10dddddd 11dddddd</span><br>
    </div>
    <br>
    The <span style="font-family: monospace;">Channel</span> parameter
    is actually the field <span style="font-family: monospace;">utppppppp</span>,
    so it is not always an i/o channel number.&nbsp;&nbsp; Recall that
    if <span style="font-family: monospace;">t</span> is set, then the
    command conveys an i/o channel bitmask rather than i/o channel data,
    whereas if <span style="font-family: monospace;">u</span> is set,
    then the command is a counter increment/decrement operation rather
    than an i/o-channel operation.<br>
    <br>
    The function returns 0 on success, or non-zero otherwise.<br>
    <br>
    <span style="font-family: monospace;">int FormIoPacketAGS (int Type,
      int Data, unsigned char *Packet);</span> (<span
      style="font-weight: bold;">yaAGS</span>/peripherals)<br>
    <br>
    This function constructs an i/o-channel packet packet in the <span
      style="font-weight: bold;">yaAGS</span> format.&nbsp; The function
    takes a 6-bit packet type number and 18-bit type-dependent data (<a
      href="#Packets_for_Socket_Implementation_of_AGS">as described
      above</a>), and constructs a 4-byte packet (<span
      style="font-family: monospace;">Packet</span>) in a form suitable
    for transmission to/from <span style="font-weight: bold;">yaAGS</span>
    via the <span style="font-family: monospace;">send</span>
    function.&nbsp; Space for the packet must have been allocated by the
    calling program.&nbsp;<br>
    <br>
    The function returns 0 on success, or non-zero otherwise.<br>
    <br style="font-family: monospace;">
    <span style="font-family: monospace;">int ParseIoPacket (unsigned
      char *Packet, int *Channel, int *Value, int *uBit);</span> (<span
      style="font-weight: bold;">yaAGC</span>/peripherals)<br>
    <br>
    This function is the opposite of <span style="font-family:
      monospace;">FormIoPacket</span>:&nbsp; A 4-byte packet (<span
      style="font-family: monospace;">Packet</span>) representing&nbsp;
    <span style="font-weight: bold;">yaAGC</span> channel i/o can be
    converted to an integer channel-number and value.&nbsp; Returns 0 on
    success or non-zero otherwise.<br>
    <br>
    <span style="font-family: monospace;">int ParseIoPacketAGS (unsigned
      char *Packet, int *Type, int *Data);</span> (<span
      style="font-weight: bold;">yaAG</span>S/peripherals)<br>
    <br>
    This function is the opposite of <span style="font-family:
      monospace;">FormIoPacketAGS</span>:&nbsp; A 4-byte packet (<span
      style="font-family: monospace;">Packet</span>) representing&nbsp;
    <span style="font-weight: bold;">yaAGS</span> channel i/o can be
    converted to an integer channel-type and data.&nbsp; Returns 0 on
    success or non-zero otherwise.<br>
    <br>
    <span style="font-style: italic;">The library contains additional
      socket-based functions beyond those described, but I won'd bother
      to document them.&nbsp; There's no reason to use them directly,
      since their usage is adequately encapsulated by the functions
      listed above.</span><br>
    <h3><a name="AGC_CPU-Engine_API" id="AGC_CPU-Engine_API"></a>AGC
      CPU-Engine API<br>
    </h3>
    <span style="font-family: monospace;">int agc_engine_init (agc_t *
      State, const char *RomImage, const char *CoreDump, int
      AllOrErasable);</span> (<span style="font-weight: bold;">yaAGC</span>
    only)<br>
    <br>
    You must call this function to initialize an AGC simulation.&nbsp;
    After <span style="font-family: monospace;">agc_engine_init</span>
    finishes, it has filled in the <span style="font-family:
      monospace;">agc_t</span> structure <span style="font-family:
      monospace;">State</span>.&nbsp; This is something that has to be
    done prior to simulating the execution of any AGC instructions,
    since this state structure is used by many Virtual AGC library
    functions.&nbsp; If you are simulating several AGC CPUs
    simultaneously, you will need to have a state structure for each
    CPU, and you will need to call <span style="font-family:
      monospace;">agc_engine_init()</span> for each state structure.
    &nbsp; <span style="font-family: monospace;">RomImage</span> and <span
      style="font-family: monospace;">CoreDump</span> are the names of
    files containing the information needed to initialize the state
    structure.&nbsp; <span style="font-family: monospace;">RomImage</span>,
    as you may expect, is the name of a <a href="#CoreFormat">core-rope
      image file</a>, and is <span style="font-style: italic;">required</span>
    since otherwise the CPU will have no program.&nbsp; <span
      style="font-family: monospace;">CoreDump</span>, on the other
    hand, is optional and is usually <span style="font-family:
      monospace;">NULL</span>.&nbsp; It is the name of a core-dump file
    previously created with the function <span style="font-family:
      monospace;">MakeCoreDump()</span> (see below), and contains the
    complete state of the CPU:&nbsp; erasable memory, i/o channels,
    etc.&nbsp; If a core-dump file is used, then the CPU can begin
    executing in exactly the state it was in when the core-dump file was
    created; otherwise, erasable memory, i/o channels, etc., are
    initialized to some safe values.&nbsp; <tt>AllOrErasable</tt> is
    used to indicate whether it is the entirety of the CPU state that is
    initialized (if <tt>AllOrErasable</tt> non-zero) or if it is merely
    the erasable memory (<tt>AllOrErasable</tt> zero) that is
    initialized by the core-dump file.<br>
    <br>
    Returns:<br>
    <div style="margin-left: 40px;"> 0 — Success.<br>
      1 — Core-rope image file not found.<br>
      2 — Core-rope image file larger than core memory.<br>
      3 — Core-rope image file size is odd.<br>
      4 — <span style="font-family: monospace;">agc_t</span> structure
      pointer is <span style="font-family: monospace;">NULL</span>.<br>
      5 — File-read error.<br>
      6 — Core-dump file not found.<br>
    </div>
    <br>
    <span style="font-weight: bold;">Note:</span>&nbsp; The true AGC's
    erasable memory was retained with power off, so it would be a more
    accurate emulation if <span style="font-weight: bold;">yaAGC</span>
    saved erasable memory to a file upon exiting, and restored it upon
    starting.&nbsp; It's likely that there are ways to terminate the <b>yaAGC</b>
    program abnormally that bypass saving an image of erasable
    memory.&nbsp; But you can make your own simulated CPU that does so,
    by means of the Virtual AGC Library functions.<br>
    <br>
    <span style="font-family: monospace;">void MakeCoreDump (agc_t *
      State, const char *CoreDump);</span> (<span style="font-weight:
      bold;">yaAGC</span> only)<br style="font-family: monospace;">
    <br>
    You can call this function to create a core-dump file which can be
    read later by <span style="font-family: monospace;">agc_engine_init()</span>
    as described above.&nbsp; <span style="font-family: monospace;">CoreDump</span>
    is the name of the file that will be created.<br>
    <br>
    <span style="font-family: monospace;">int agc_engine (agc_t *
      State);</span> (<span style="font-weight: bold;">yaAGC</span>
    only)<br>
    <br>
    Call this function to execute one machine-cycle of the
    simulation.&nbsp; Use <span style="font-family: monospace;">agc_engine_init()</span>
    prior to the first call of <span style="font-family: monospace;">agc_engine()</span>
    to initialize <span style="font-family: monospace;">State</span>,
    and then call <span style="font-family: monospace;">agc_engine()</span>
    thereafter every (simulated) 11.7 microseconds if you want to
    preserve accurate system timing.&nbsp; If you don't care about
    accurate timing, call <span style="font-family: monospace;">agc_engine()</span>
    as often or as seldom as you like.&nbsp; <span style="font-family:
      monospace;">agc_engine()</span> will modify <span
      style="font-family: monospace;">State</span> and will call <span
      style="font-family: monospace;">ChannelInput()</span> and <span
      style="font-family: monospace;">ChannelOutput()</span> (see above)
    as needed to perform i/o.&nbsp; Counters will be incremented or
    decremented automatically, if <span style="font-family: monospace;">ChannelInput()</span>
    is implemented properly.<br>
    <br>
    Returns 0 on success and non-zero on failure, but I'm not sure if
    there are any circumstances under which this function can fail.<br>
    <br>
    <span style="font-family: monospace;">void UnprogrammedIncrement
      (agc_t *State, int Counter, int IncType);</span> (<span
      style="font-weight: bold;">yaAGC</span> only)<br>
    <br>
    This function can be called (but usually only by the <span
      style="font-family: monospace;">ChannelInput</span> function) to
    increment/decrement a counter register.&nbsp; <span
      style="font-family: monospace;">Counter</span> is the address of
    the counter register, and should be in the range 32-60
    (octal).&nbsp; <span style="font-family: monospace;">IncType</span>
    is the type of increment/decrement to be performed, <a
      href="#Packets_for_Socket_Implementation_of_AGC">as described
      above</a>.&nbsp; Presently, only types 0-6 (<span
      style="font-family: monospace;">PINC</span>, <span
      style="font-family: monospace;">PCDU</span>, <span
      style="font-family: monospace;">MINC</span>, <span
      style="font-family: monospace;">MCDU</span>, <span
      style="font-family: monospace;">DINC</span>, <span
      style="font-family: monospace;">SHINC</span>, <span
      style="font-family: monospace;">SHANC</span>) are supported.&nbsp;
    The function will set interrupt-request flags as needed, for those
    registers that interrupt upon overflow, but this has not yet been
    implemented (as of 2005-05-18).<br>
    <br>
    <span style="font-family: monospace;">int AddSP16 (int Addend1, int
      Addend2);</span> (<span style="font-weight: bold;">yaAGC</span>
    only)<br>
    <br>
    Add two integers in AGC format, returning a value also in AGC
    format.&nbsp; The returned value may contain "overflow" (see <span
      style="font-family: monospace;">int16_t</span> above).&nbsp;
    Though <span style="font-family: monospace;">int</span> datatypes
    are used, only the least-significant 16 bits are used, so the result
    may be copied into an <span style="font-family: monospace;">int16_t</span>
    variable without loss.<br>
    <br>
    <span style="font-family: monospace;">int16_t OverflowCorrected (int
      Value);</span> (<span style="font-weight: bold;">yaAGC</span>
    only)<br>
    <br>
    Returns the "overflow corrected" value of an integer in AGC
    format.&nbsp; (See <span style="font-family: monospace;">int16_t</span>
    above.)<br>
    <br>
    <span style="font-family: monospace;">int SignExtend (int16_t Word);</span>
    (<span style="font-weight: bold;">yaAGC</span> only)<br>
    <br>
    Copies the 15th bit of an integer in AGC format into the 16th
    bit.&nbsp; The significance of an operation like this is that only
    the CPU's <span style="font-family: monospace;">A</span>, <span
      style="font-family: monospace;">L</span>, and <span
      style="font-family: monospace;">Q</span> registers are capable of
    holding the 16th or "overflow" bit (see <span style="font-family:
      monospace;">int16_t</span> above), and therefore data from all
    other memory locations in the AGC address space must be
    sign-extended when copied to those registers.&nbsp; (Even though the
    datatypes used by the AGC emulator engine are 16 bits for every
    memory location, it is an invalid assumption that those memory
    locations are capable of holding overflow, and is an assumption
    would cause the emulator to fail mysteriously.)<br>
    <br>
    <span style="font-family: monospace;">int ReadIO (agc_t * State, int
      Address);</span> (<span style="font-weight: bold;">yaAGC</span>
    only)<br>
    <br>
    Reads an i/o channel, from the CPU's perspective.&nbsp; This
    function really reads only the memory array of the emulated
    CPU.&nbsp; Input data from i/o channels appears asynchronously and
    is transparently written into this mirror array without any
    intervention from the programmer.&nbsp; <span style="font-weight:
      bold;">Note:</span>&nbsp; It's important to use this function
    rather than reading the mirror array directly, since the function
    accounts for the fact that the L and Q registers appear in both i/o
    space and erasable-memory space.<br>
    <br>
    <span style="font-family: monospace;">void CpuWriteIO (agc_t *
      State, int Address, int Value);</span> (<span style="font-weight:
      bold;">yaAGC</span> only)<br>
    <br>
    (Note that there is a function called <span style="font-family:
      monospace;">WriteIO</span> as well.&nbsp; It's not the function
    you want.&nbsp; Use this one instead)&nbsp; Writes an i/o channel,
    from the CPU's perspective.&nbsp; This function not only writes the
    memory array of the emulated CPU, but also performs the <span
      style="font-family: monospace;">ChannelOutput</span> that
    physically outputs the data.&nbsp; <span style="font-weight: bold;">Note:</span>&nbsp;
It's
    important to use this function rather than reading the mirror
    array directly, since the function accounts for the fact that the L
    and Q registers appear in both i/o space and erasable-memory
    space.&nbsp; It also provides the bookkeeping needed for output
    channel 010, which really corresponds to 16 output ports implemented
    with latches external to the CPU.<br>
    <h3><a name="AGC_Backtrace_API" id="AGC_Backtrace_API"></a><strike>AGC
Backtrace
        API</strike></h3>
    <strike> To understand what "backtraces" are and why you might want
      to use them, refer to the explanation of debugging on the </strike><strike><a
        href="yaAGC.html">yaAGC page</a></strike><strike>.</strike><strike><br>
    </strike><strike> </strike><strike><br>
    </strike><strike> </strike><strike><span style="font-family:
        monospace;">void BacktraceAdd (agc_t *State, int Cause);</span></strike><strike>
      (</strike><strike><span style="font-weight: bold;">yaAGC</span></strike><strike>
      only)</strike><strike><br>
    </strike><strike> </strike><strike><br>
    </strike><strike> For debugging purposes, this function adds a new
      backtrace point to a circular buffer used to hold the list of
      backtraces.&nbsp; The oldest entries are transparently
      overwritten.&nbsp; The </strike><strike><span style="font-family:
        monospace;">Cause</span></strike><strike> parameter is used as
      follows:</strike><strike><br>
    </strike><strike> </strike>
    <div style="margin-left: 40px;">
      <table summary="" style="text-align: left;" cellspacing="2"
        cellpadding="2" border="1">
        <tbody>
          <tr>
            <td style="vertical-align: top;"><strike>0</strike><strike><br>
              </strike> </td>
            <td style="vertical-align: top;"><strike>The backtrace point
                is in normal code.</strike></td>
          </tr>
          <tr>
            <td style="vertical-align: top;"><strike>1-10</strike><strike><br>
              </strike> </td>
            <td style="vertical-align: top;"><strike>The backtrace point
                is an interrupt vector.</strike></td>
          </tr>
          <tr>
            <td style="vertical-align: top;"><strike>255</strike><strike><br>
              </strike> </td>
            <td style="vertical-align: top;"><strike>The backtrace point
                is a RESUME after interrupt.</strike></td>
          </tr>
        </tbody>
      </table>
    </div>
    <strike> When </strike><strike><span style="font-family:
        monospace;">Cause</span></strike><strike>==255 is encountered,
      all backtrace points back to (and including) the vector to the
      interrupt are removed.&nbsp; The reason for this is that otherwise
      the array will quickly become completely full of interrupt code,
      and all backtrace points to foreground code will be completely
      lost.</strike><strike><br>
    </strike><strike> </strike><strike><br>
    </strike><strike> </strike><strike><span style="font-family:
        monospace;">int BacktraceRestore (agc_t *State, int n);</span></strike><strike>
      (</strike><strike><span style="font-weight: bold;">yaAGC</span></strike><strike>
      only)</strike><strike><br>
    </strike><strike> </strike><strike><br>
    </strike><strike> Restores the state of the system from entry </strike><strike><span
        style="font-family: monospace;">n</span></strike><strike> in the
      backtrace buffer.&nbsp; 0 is the most recent backtrace added, 1
      the next-most recent, and so forth.&nbsp; The restoration is
      complete, from the standpoint of the CPU, in that all memory, i/o
      channels, and internals (like the interrupt masks used for
      debugging) are restored.&nbsp; However, any peripheral devices
      will not be automatically restored, since the sequence of
      i/o-channel operations needed to do so is not known to the
      system.&nbsp; Returns 0 on success or non-zero on error.</strike><strike><br>
    </strike><strike> </strike><strike><br>
    </strike><strike> </strike><strike><span style="font-family:
        monospace;">void BacktraceDisplay (agc_t *State);</span></strike><strike>
      (</strike><strike><span style="font-weight: bold;">yaAGC</span></strike><strike>
      only)</strike><strike><br>
    </strike><strike> </strike><strike><br>
    </strike><strike> Displays (i.e., </strike><strike><span
        style="font-family: monospace;">printf</span></strike><strike>s)
      the contents of the backtrace circular buffer.&nbsp; The main use
      of this is to allow the user to select the </strike><strike><span
        style="font-family: monospace;">n</span></strike><strike>
      parameter for use with </strike><strike><span style="font-family:
        monospace;">BacktraceRestore</span></strike><strike> (see
      above).</strike><br>
    <h3><a name="Downlink_Lists" id="Downlink_Lists"></a>Downlink Lists</h3>
    The AGC provides digital downlinks for 13 different types of
    "downlink lists".&nbsp; One of these lists, the "AGS
    Initialization/Update list" was used by the AGC to initialize the
    AGS.&nbsp; The other types of downlink lists were strictly for the
    benefit of the ground stations, and were used to display telemetry
    information.&nbsp; <span style="font-style: italic;">Unfortunately,</span>
    I have been unable to obtain any information about the exact visual
    appearance of these telemetry displays.&nbsp; For that reason, and
    because I know that if you are trying to integrate Virtual AGC into
    a spacecraft-simulation system you probably don't want to use the
    same mechanism for creating a telemetry display as I do, I've
    provided code for parsing the downlink lists, but have made the
    inclusion/exclusion of all data fields, the location of those fields
    on the display, and the physical mechanism for displaying the data
    completely flexible, and modifiable at runtime.&nbsp;&nbsp; The
    method I've provided may seem complex; but if you consider that each
    of the 13 types of downlink lists has between 100 and 200 different
    types of data fields, you should conclude that it is a lot easier to
    use what I've provided than to take care of it all yourself.<br>
    <br>
    If you want more information on downlink-lists in general, refer to
    our <a
      href="links2.html#GSOPs">Document Library page</a>.<br>
    <br>
    <span style="font-family: monospace;"><span style="font-family:
        monospace;">#include "agc_engine.h"</span><br>
    </span> <span style="font-family: monospace;">void
      DecodeDigitalDownlink (int Channel, int Value, int CmOrLm);<br>
    </span><br>
    This function completely handles all buffering, parsing, and
    formatting of downlink-lists.&nbsp; Simply call it with appropriate
    i/o channel address and value every time the CPU writes to output
    channels 013, 034, or 035.&nbsp; The variable <span
      style="font-family: monospace;">CmOrLm</span> is 1 for the CM or 0
    for the LM.&nbsp; (The <span style="font-weight: bold;">yaDSKY</span>
    program already does so, if started with the "--test-downlink"
    command-line switch.)&nbsp; The default behavior is simply to print
    each downlink list as it arrives to the standard output, which is
    assumed to be an ANSI terminal of at least 80 columns and 43
    rows.&nbsp; If this behavior suits you, then you need do nothing
    more.&nbsp; If, on the other hand, you wish to customize the
    behavior, then read on.<br>
    <br>
    <span style="font-family: monospace;">#include "agc_engine.h"<br>
      /*<br>
      &nbsp; By including agc_engine.h, you get the following stuff.<br>
      &nbsp; #define SWIDTH 160&nbsp;&nbsp; &nbsp;&nbsp;
      &nbsp;&nbsp;&nbsp; // Maximum display width<br>
      &nbsp; #define SHEIGHT
      100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Maximum
      display height<br>
      &nbsp; char Sbuffer[SHEIGHT][SWIDTH + 1];<br>
    </span> <span style="font-family: monospace;">&nbsp; typedef void
      Swrite_t (void);<br>
      */<br>
      extern Swrite_t *SwritePtr;<br>
    </span><br>
    Changing <span style="font-family: monospace;">SwritePtr</span>
    allows you to change the physical destination of the display-data
    for the downlink lists.&nbsp; After the <span style="font-family:
      monospace;">DecodeDigitalDownlink</span> function parses the
    downlink list, it formats the various fields of the list and
    "outputs" them to the memory array <span style="font-family:
      monospace;">Sbuffer</span>.&nbsp; After the complete downlink list
    has been processed, <span style="font-family: monospace;">DecodeDigitalDownlink</span>
    then calls the function pointed to by <span style="font-family:
      monospace;">SwritePtr</span> to physically output the contents of
    <span style="font-family: monospace;">Sbuffer</span>.&nbsp; If you
    don't like the default behavior of writing to an ANSI terminal,
    simply make <span style="font-family: monospace;">SwritePtr</span>
    point to your own display function, and your own function can
    dispose of the contents of <span style="font-family: monospace;">Sbuffer</span>
    as you like.&nbsp; (<span style="font-family: monospace;">Sbuffer</span>
    contains nul-terminated strings, one for each text-row of the
    display.)&nbsp;&nbsp; However, this only changes where the output is
    physically written, and doesn't change the positioning or formatting
    of any of the data fields on the display.&nbsp; To do that, read on.<br>
    <br>
    <span style="font-family: monospace;">#include "agc_engine.h"<br>
      /*<br>
      &nbsp; By including agc_engine.h, you get the following stuff.<br>
      &nbsp; #define DL_CM_POWERED_LIST 0<br>
      &nbsp; #define DL_LM_ORBITAL_MANEUVERS 1<br>
      &nbsp; #define DL_CM_COAST_ALIGN 2<br>
      &nbsp; #define DL_LM_COAST_ALIGN 3<br>
      &nbsp; #define DL_CM_RENDEZVOUS_PRETHRUST 4<br>
      &nbsp; #define DL_LM_RENDEZVOUS_PRETHRUST 5<br>
      &nbsp; #define DL_CM_PROGRAM_22 6<br>
      &nbsp; #define DL_LM_DESCENT_ASCENT 7<br>
      &nbsp; #define DL_LM_LUNAR_SURFACE_ALIGN 8<br>
      &nbsp; #define DL_CM_ENTRY_UPDATE 9<br>
      &nbsp; #define DL_LM_AGS_INITIALIZATION_UPDATE 10<br>
      &nbsp; typedef enum {<br>
      &nbsp;&nbsp;&nbsp; FMT_SP, FMT_DP, FMT_OCT, FMT_2OCT, FMT_DEC,
      FMT_2DEC<br>
      &nbsp; } Format_t;<br>
      &nbsp; typedef char *Sformat_t (int IndexIntoList, int Scale,
      Format_t Format);<br>
      &nbsp; typedef struct {<br>
      &nbsp;&nbsp;&nbsp; int IndexIntoList;&nbsp;&nbsp;&nbsp; // if -1,
      then is a spacer.<br>
      &nbsp;&nbsp;&nbsp; char Name[65];<br>
      &nbsp;&nbsp;&nbsp; int Scale;<br>
      &nbsp;&nbsp;&nbsp; Format_t Format;<br>
      &nbsp;&nbsp;&nbsp; Sformat_t *Formatter;<br>
      &nbsp;&nbsp;&nbsp; int Row;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
      // If 0,0, then just "next" position.<br>
      &nbsp;&nbsp;&nbsp; int Col;<br>
      &nbsp; } FieldSpec_t;<br>
      &nbsp; typedef struct {<br>
      &nbsp; &nbsp; char Title[SWIDTH + 1];<br>
      &nbsp;&nbsp;&nbsp; FieldSpec_t FieldSpecs[MAX_DOWNLINK_LIST];<br>
      &nbsp; } DownlinkListSpec_t;<br>
    </span> <span style="font-family: monospace;"><span
        style="font-family: monospace;"><span style="font-family:
          monospace;">&nbsp; #define DEFAULT_SWIDTH 79&nbsp;&nbsp; //
          Default display width<br>
          &nbsp; #define DEFAULT_SHEIGHT 42&nbsp; // Default display
          height</span><br>
      </span></span> <span style="font-family: monospace;">*/<br>
      extern DownlinkListSpec_t *DownlinkListSpecs[13];<br>
    </span> <span style="font-family: monospace;"><span
        style="font-family: monospace;"><span style="font-family:
          monospace;">extern int Sheight, Swidth;</span><br>
      </span></span> <span style="font-family: monospace;"><br>
    </span> Changing <span style="font-family: monospace;">Sheight</span>,
    <span style="font-family: monospace;">Swidth</span>, and the entries
    of <span style="font-family: monospace;">DownlinkListSpecs</span>
    allows you to change the positioning and formatting of the fields
    from the downlink list.&nbsp; You can change the size of the canvas
    by changing the variables <span style="font-family: monospace;">Sheight</span>
    and <span style="font-family: monospace;">Swidth</span> (which are
    by default <span style="font-family: monospace;">DEFAULT_SHEIGHT</span>
    and <span style="font-family: monospace;">DEFAULT_SWIDTH</span>),
    as long as you don't make them larger than <span
      style="font-family: monospace;">SHEIGHT</span> and <span
      style="font-family: monospace;">SWIDTH</span>, respectively.<br>
    <br>
    The way <span style="font-family: monospace;">DecodeDigitalDownlink</span>
    parses and formats the fields of any individual downlink list is
    determined by an array of entries of type <span style="font-family:
      monospace;">DownlinkListSpec_t</span>.&nbsp; Furthermore, the
    array <span style="font-family: monospace;">DownlinkListSpecs[]</span>
    determine which specification is used for each type of downlink
    list.&nbsp; For example, <span style="font-family: monospace;">*DownlinkListSpecs[DL_LM_ORBITAL_MANEUVERS]</span>
    is the specification for the LM Orbital Maneuvers downlink
    list.&nbsp; So by using the <span style="font-family: monospace;">DownlinkListSpecs[]</span>
    array, you can modify the existing specifications, or even
    completely replace them with your own.&nbsp; The exceptions to this
    are the LM Erasable Dump list and the CM Erasable Dump list; you
    don't get the option of customizing those, and just have to take
    what I give you and like it.<br>
    <br>
    Each individual downlist is specified by a <span
      style="font-family: monospace;">Title</span>, printed at the top
    of the list, along with the specifications for each individual
    field.&nbsp; Each field has the following characteristics:<br>
    <ul>
      <li>The <span style="font-family: monospace;">IndexIntoList</span>,
        which tells where the datum is positioned in the downlink
        list.&nbsp; This index is from zero, and points to the 15-bit
        words in the downlink list.&nbsp; (The Apollo documentation, on
        the other hand, references pairs of 15-bit words, and indexes
        them from 1.&nbsp; For example, for us, index 0 is the
        downlink-list ID, and index 1 is the downlink-list
        syncword.&nbsp; In the Apollo docs, index 1 is a double-word
        consisting of the ID and syncword together.)</li>
      <li>The <span style="font-family: monospace;">Name</span>, which
        is a string printed immediately to the left of the datum.&nbsp;
        For example, "TIG=".</li>
      <li>The <span style="font-family: monospace;">Scale</span>, which
        is number that is multiplied with the datum.</li>
      <li>The <span style="font-family: monospace;">Format</span> (one
        of <span style="font-family: monospace;">FMT_SP</span>, <span
          style="font-family: monospace;">FMT_DP</span>, etc.) which
        determines the methods used to convert from the AGC internal
        representation to a displayable value.&nbsp; (In general, these
        should not be changed.)</li>
      <li><span style="font-family: monospace;">Formatter</span> is
        usually a <span style="font-family: monospace;">NULL</span>
        pointer, in which case it is ignored.&nbsp; However, there may
        be cases in which the formatting scheme described above is
        simply inadequate, and you'd like to plug in a function of your
        own to do the formatting.&nbsp; Examples of this would be:&nbsp;
        picking bitfields out of flagwords, changing the scaling based
        on other downlinked data, etc.&nbsp; So if <span
          style="font-family: monospace;">Formatter</span> is not <span
          style="font-family: monospace;">NULL</span>, then <span
          style="font-family: monospace;">DecodeDigitalDownlink</span>
        uses the function you've provided to obtain a pointer to the
        formatted string, and does not attempt scaling or any other
        interpretation of the data.&nbsp; Your function must allocate
        space to store the formatted string, and merely returns a
        pointer to it.&nbsp; You are guaranteed that the string is
        buffered before the next call to any of your formatting
        functions.&nbsp; Your function should return <span
          style="font-family: monospace;">NULL</span> if the field
        should be left out entirely.&nbsp; The <span
          style="font-family: monospace;">IndexToList</span>, <span
          style="font-family: monospace;">Scale</span>, and <span
          style="font-family: monospace;">Format</span> fields are
        passed to your function as a courtesy, in case you should find
        it convenient to reuse the function several times.&nbsp; Also,
        there are several other utility functions, described below,
        which are useful within <span style="font-family: monospace;">Formatter</span>
        functions.<br>
      </li>
      <li>The <span style="font-family: monospace;">Row</span> and <span
          style="font-family: monospace;">Col</span>, which determine
        where on the display screen the field should be printed.&nbsp;
        0,0 is the upper-left corner, however 0,0 is the position in
        which the <span style="font-family: monospace;">Title</span> is
        printed and should not be used.&nbsp; In fact, 0,0 is used in a
        special way, and is interpreted simply as 20 spaces to the right
        of the previous field, with automatic wraparound to the next
        line where needed.&nbsp; This convention is used in all the
        default specifications, to make it easier on me.&nbsp;
        Therefore, customizing the specifications may be as simple as
        writing non-zero <span style="font-family: monospace;">Row</span>,<span
          style="font-family: monospace;">Col</span> coordinates into
        the existing specifications at runtime.&nbsp;&nbsp; A
        complementary convention I used to make creation of the default
        lists easier is that if <span style="font-family: monospace;">IndexIntoList</span>
        is -1, it is interpreted as meaning to skip 20 spaces but not to
        print anything.</li>
    </ul>
    <span style="font-family: monospace;"><span style="font-family:
        monospace;">double GetDP (int *Ptr, int Scale);<br>
        double GetSP (int *Ptr, int Scale);<br>
      </span></span><br>
    These functions convert either an AGC single precision (SP) or
    double precision (DP) value (pointed to by <span
      style="font-family: monospace;">Ptr</span>) as a floating-point
    number in the native format of the target computer.&nbsp; Usually
    the pointer points somewhere in the downlink list, but it does not
    necessarily have to.<br>
    <br>
    <span style="font-family: monospace;">void PrintDP (int *Ptr, int
      Scale, int row, int col);<br>
      void PrintSP (int *Ptr, int Scale, int row, int col);<br>
      <br>
    </span> These functions are the same as GetDP and GetSP, except that
    they additionally format the floating-point number as a string, and
    print it to the output buffer.<br>
    <h3><a name="AGC_Utility_API_" id="AGC_Utility_API_"></a>Utility API<br>
    </h3>
    <span style="font-family: monospace;">FILE *rfopen (const char
      *Filename, const char *mode);</span> (<span style="font-weight:
      bold;">yaAGC</span>/<span style="font-weight: bold;">yaAGS</span>/peripherals)<br>
    <br>
    This is just like the regular C-library <span style="font-family:
      monospace;">fopen</span> function, except that accounts for the
    directory preferences of <span style="font-weight: bold;">yaAGC</span><span
      style="font-style: italic;">et al</span>.&nbsp; It first
    attempts to open the file with the name as given.&nbsp; If that
    fails, it prepends the name of the directory where the Virtual AGC
    executables were installed and tries again.&nbsp; This allows you
    (for example) to do things like <span style="font-family:
      monospace;">rfopen("Luminary131.bin","rb")</span> without worrying
    where Luminary131.bin has been installed.<br>
    <h3><a name="An_Example:_The_Simplest_Possible_AGC"
        id="An_Example:_The_Simplest_Possible_AGC"></a>An Example:&nbsp;
      The Simplest Possible AGC Emulation Made from Library Functions</h3>
    <div style="margin-left: 40px;"> <span style="font-family:
        monospace;">// I haven't actually *tried* this, but in theory
        ...</span><br>
      <span style="font-family: monospace;">// Here's a little program
        that simply runs an AGC simulation</span><br>
      <span style="font-family: monospace;">// as fast as it possibly
        can. Of course, that's pretty darned</span><br>
      <span style="font-family: monospace;">// fast.&nbsp; The usage,
        assuming you build an executable named</span><br>
      <span style="font-family: monospace;">// "FastAGC", would be
        something like this:</span><br>
      <span style="font-family: monospace;">//&nbsp;&nbsp;&nbsp; FastAGC
        Luminary131.bin</span><br>
      <br>
      <span style="font-family: monospace;">#include "agc_engine.h"</span><br>
      <span style="font-family: monospace;">static agc_t State;</span><br>
      <br>
      <span style="font-family: monospace;">int</span><br>
      <span style="font-family: monospace;">main (int argc, char
        *argv[])</span><br>
      <span style="font-family: monospace;">{</span><br>
      <span style="font-family: monospace;">&nbsp; int ReturnValue;</span><br>
      <span style="font-family: monospace;">&nbsp; if (argc &lt; 2)</span><br>
      <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; return
        (1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
//
        No command-line arguments!</span><br>
      <span style="font-family: monospace;">&nbsp; ReturnValue =
        agc_engine_init (&amp;State, argv[1], NULL);</span><br>
      <span style="font-family: monospace;">&nbsp; if (ReturnValue)</span><br>
      <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; return
        (ReturnValue);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Error
        initializing!</span><br>
      <span style="font-family: monospace;">&nbsp; // Run the thing
        really fast!</span><br>
      <span style="font-family: monospace;">&nbsp; while (1)</span><br>
      <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
        agc_engine (&amp;State);</span><br>
      <span style="font-family: monospace;">}</span><br>
      <br>
      <span style="font-family: monospace;">// Simpler than you
        expected, I bet.</span> </div>
    <h3><a name="Another" id="Another"></a>Another Example:&nbsp; A
      Simple AGC Peripheral Emulation Made from Library Functions<br>
    </h3>
    <div style="margin-left: 40px;"> <span style="font-family:
        monospace;"><span style="font-family: monospace;">// I haven't
          actually *tried* this, but in theory ...</span><br>
      </span><span style="font-family: monospace;">// This will simply
        increment a counter register once per second.<br>
        // The PINC sequence is used, so the counter is assumed to be
        2's-complement.<br>
        // Usage:<br>
        //&nbsp;&nbsp; 1st command-line arg:&nbsp;&nbsp; Name or ip
        address of yaAGC server.<br>
        //&nbsp;&nbsp; 2nd command-line arg:&nbsp;&nbsp; Port number to
        use.<br>
        //&nbsp;&nbsp; 3rd command-line arg:&nbsp;&nbsp; Number of
        counter register in decimal.<br>
        <br>
        #include &lt;stdlib.h&gt;<br>
        #include &lt;time.h&gt;<br>
        #include "yaAGC.h"<br>
        #include "agc_engine.h"<br>
        &nbsp;&nbsp;&nbsp;<br>
        int<br>
        main (int argc, char *argv[])<br>
        {<br>
      </span> <span style="font-family: monospace;"><span
          style="font-family: monospace;">&nbsp; int ConnectionSocket,
          CounterRegister;<br>
          &nbsp; time_t t, tNext;<br>
          &nbsp; unsigned char Packet[4];<br>
          <br>
        </span></span> <span style="font-family: monospace;">&nbsp; if
        (argc &lt; 4)<br>
        &nbsp;&nbsp;&nbsp; return (1);&nbsp;&nbsp; &nbsp;&nbsp;
        &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; // Not enough
        command-line arguments!<br>
        &nbsp; CounterRegister = atoi (argv[3]);<br>
        &nbsp; if (CounterRegister &lt; 032 || CounterRegister &gt; 060)<br>
        &nbsp;&nbsp;&nbsp; return (2);&nbsp;&nbsp; &nbsp;&nbsp;
        &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; // Invalid command-line
        register.<br>
        &nbsp;<br>
        &nbsp; // Try for a connection.<br>
        &nbsp; ConnectionSocket = CallSocket (argv[1], atoi (argv[2]));<br>
        &nbsp; if (ConnectionSocket == -1)<br>
        &nbsp;&nbsp;&nbsp; return (3);&nbsp;&nbsp; &nbsp;&nbsp;
        &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; // Couldn't connect to
        server.<br>
        <br>
        &nbsp; // Create a packet containing a PCDU command.&nbsp; Note
        that we set the<br>
        &nbsp; // u bitfield to indicate a counter operation rather than
        an<br>
        &nbsp; // i/o operation.<br>
      </span> <span style="font-family: monospace;"><span
          style="font-family: monospace;">&nbsp; FormIoPacket (0x100 |
          CounterRegister, 1 /*PINC*/, Packet);</span><br>
      </span> <span style="font-family: monospace;"><br>
        &nbsp; // Loop forever.<br>
        &nbsp; time (&amp;t);<br>
        &nbsp; tNext = t + 1;<br>
        &nbsp; while (1)<br>
        &nbsp;&nbsp;&nbsp; {<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (time (&amp;t), t &lt;
        tNext);&nbsp;&nbsp; // Wait for time to rollover.<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tNext = t + 1;<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; send (ConnectionSocket, Packet,
        4, MSG_NOSIGNAL);<br>
        &nbsp;&nbsp;&nbsp; }<br>
        }<br>
      </span> </div>
    <h2><a name="CoreFormat" id="CoreFormat"></a>Format of a yaAGC
      Core-Rope Image File</h2>
    As used by the <span style="font-weight: bold;">yaAGC</span>, <span
      style="font-weight: bold;">yaYUL</span>, and <span
      style="font-weight: bold;">Oct2Bin</span> programs, the file used
    to store a core-rope binary image has a format which may be
    described as follows.<br>
    <ul>
      <li>Each 15-bit memory word is represented as a 16-bit value,
        left-aligned.&nbsp; In other words, the bit D0 is unused, and
        bits D1-D15 are used to hold the memory word.&nbsp; Bit D15 is
        the most-significant bit and bit D1 the least significant.&nbsp;
        Bit D0, which would have been used in the actual AGC to hold an
        odd-parity bit, is not defined; in practice, it is always 0
        since parity is not supported by <span style="font-weight:
          bold;">yaAGC</span>, <span style="font-weight: bold;">yaYUL</span>,
        and <span style="font-weight: bold;">Oct2Bin</span>.</li>
      <li>The 16-bit memory words are stored in big-endian format,
        meaning that the more-significant byte comes first and the
        less-significant byte comes second.&nbsp; (This is the opposite
        ordering from that used in an Intel 'x86 CPU.)<br>
      </li>
      <li>The file contains exactly 36 (44 octal) memory banks, and is
        therefore 36×1024 words or 36×2048=73728 bytes in size.</li>
      <li>The banks are ordered as follows:&nbsp; Bank 2, bank 3, bank
        0, bank 1, bank 4, bank 5, bank 6, .....&nbsp; (In other words,
        the banks are in the order you'd naively expect, except that
        banks 2,3 are swapped with banks 0,1.)&nbsp; This is the same
        ordering as in assembly listings produced by the original <span
          style="font-weight: bold;">YUL</span> program.&nbsp; It has
        presumably been done this way because banks 2 and 3—while
        addressable as banked memory—are <span style="font-style:
          italic;">also</span> addressable as unbanked ("fixed-fixed")
        memory.&nbsp; In some sense, therefore, banks 2 and 3 are a more
        fundamental type of memory than the other banks.&nbsp; They are
        the "prime real-estate".</li>
    </ul>
    For those with access to Julian Webb's AGC simulator—a very small
    number of people at this writing—I've provided a utility called <span
      style="font-weight: bold;">webb2burkey-rope</span> that can
    convert the <span style="font-weight: bold;">yaAGC</span> core-rope
    format to Julian's format, and vice-versa.<br>
    <br>
    It's also important if you intend to create your own binary-image
    files—and I don't suppose that you <span style="font-style:
      italic;">will</span>—to know that each memory bank is checked (as
    part of the built-in self test) for an appropriate checksum.&nbsp;
    The bank checksums are governed by the following rules:<br>
    <ul>
      <li>Since the checksums must be computed by the AGC (or <span
          style="font-weight: bold;">yaAGC</span>), all of the
        arithmetic used (in the rules below) for checksum manipulation
        follow the rules of the AGC's 15-bit 1's-complement signed
        arithmetic.&nbsp; For example, when we say that two values are
        added together, we mean that the two values are considered as
        15-bit 1's-complement signed integers, and that the sum so
        produced is a 15-bit 1's-complement signed integer.&nbsp; (In
        case it is not obvious, these rules do <span style="font-style:
          italic;">not</span> correspond to arithmetic performed by most
        modern CPU's—as of this writing, anyhow—and therefore require
        special coding to be handled properly.)<br>
      </li>
      <li>The checksum of any given memory bank is equal to the number
        of the memory bank, or to the negative of the memory bank
        number.&nbsp; For example, the checksum of bank 26 is equal
        either to 26 or to -26.&nbsp; (The reason for allowing the
        negative possibility is that the limitations of 1's complement
        signed arithmetic don't allow the positive checksum to be
        produced in all cases.)</li>
      <li>The checksum is simply the sum of all of the words in the
        bank, up to and including the last <span style="font-style:
          italic;">used</span> word (referred to as the "bugger
        word").&nbsp; Additionally, every time there is an overflow (the
        sum equals or exceeds 16384) it is reduced by 16383 (and yes, I
        do mean "16383" and not "16384").&nbsp; Every time there is an
        underflow (the sum is less than or equal to -16384), it is
        increased by 16383.&nbsp; (This has an effect similar to a
        circular shift: data overflowing bit 15 reappears in bit 1
        rather than being discarded.)</li>
      <li>The "bugger word" is a special word appearing after all of the
        code and constants in the bank, added for the sole purpose of
        making the checksum come out right—in other words, to the
        positive or negative of the bank number. For a bank that is
        completely full (contains 1023 words), the bugger word is simply
        placed in the last&nbsp; physical word of the bank.&nbsp;<br>
      </li>
      <li>For banks which are <span style="font-style: italic;">not</span>
        completely full, placement of the bugger word is slightly more
        complex.&nbsp; The bugger word still closely follows the used
        words of the bank, but is not at the physical end of the
        bank.&nbsp; Words after the bugger word are not included in the
        bank checksum, so special markers must be added in order to tell
        the build-in-self-test software when to stop computing the
        checksum—i.e., to tell it where the bugger word is.&nbsp; This
        is done by preceding the bugger word by two machine-code
        instructions (or only one if there is not room for two) that are
        basically "loop forever" codes.&nbsp; In assembly language,
        these instructions would be "TC <span style="font-style:
          italic;">self</span>"; numerically, such an instruction
        happens to assemble to the value of the memory address of the
        instruction—4000-5777 octal for bank 2, 6000-7777 octal for bank
        3, and 2000-3777 for all other banks.</li>
      <li>Words within a bank but after the bugger word are
        undefined.&nbsp; In practice, <span style="font-weight: bold;">yaYUL</span>
        or <span style="font-weight: bold;">Oct2Bin</span> will always
        force them to zero, so they actually could be included within
        bank checksums without any problem.<br>
      </li>
    </ul>
    <h2><a name="Format_of_a_yaAGS_Core_Image_File"
        id="Format_of_a_yaAGS_Core_Image_File"></a>Format of a yaAGS
      Core Image File</h2>
    The <span style="font-weight: bold;">yaAGS</span> core-image file
    simply contains 32-bits for each location from 0 to 07777, in
    little-endian format.&nbsp; Only the least-significant 18 bits are
    used, and the upper 14 bits of each value are zero. The format is
    chosen to be easy for lazy programmers on little-endian CPUs like
    the Intel Pentium.&nbsp; (If you are such a lazy programmer, and
    don't care to explicitly account for the endianness of the data, you
    will of course product non-portable code.)&nbsp; <span
      style="font-weight: bold;">yaAGS</span> itself and the assembler <span
      style="font-weight: bold;">yaLEMAP</span> work on big-endian CPUs
    as well, and are platform-independent.<br>
    <br>
    <hr style="width: 100%; height: 2px;">
    <center> <br>
      <span style="color: rgb(84, 89, 93); font-family: sans-serif;
        font-size: 11.05px; font-style: normal; font-variant: normal;
        font-weight: normal; letter-spacing: normal; line-height:
        16.575px; orphans: auto; text-align: center; text-indent: 0px;
        text-transform: none; white-space: normal; widows: 1;
        word-spacing: 0px; -webkit-text-stroke-width: 0px; display:
        inline !important; float: none; background-color: rgb(255, 255,
        255);"> This page is available under the <a
          href="https://creativecommons.org/publicdomain/zero/1.0/">Creative
Commons
          No Rights Reserved License</a></span><br>
      <i><font size="-1">Last modified by <a
            href="mailto:info@sandroid.org">Ronald Burkey</a> on
          2021-09-21.<br>
          <br>
          <a href="http://www.ibiblio.org"><img style="border: 0px solid
              ; width: 300px; height: 100px;" alt="Virtual AGC is hosted
              by ibiblio.org" src="hosted.png" width="300" height="100"></a><br>
        </font></i> </center>
    <br>
    <br>
  </body>
</html>
back to top