Insofar as the Space Shuttle is concerned, the Virtual AGC
Project's present goals — or if you'd prefer, my goals —
are the following:
In essence, we'd like to do the same kinds of things for the
Space Shuttle's onboard computers, and in particular the
computers' software, as we have done for Apollo's onboard computer
systems and software.
I don't pretend to be putting together an
"everything about the Space Shuttle" site. If you want to
know about the Space Shuttle's Main Engines (SSME) or Reaction
Control System (RCS), or hear marvelous facts such as the maximum
payload size being a 15×60 foot cylinder weighing 65,000 pounds,
then this is not the place to look. (But that's big,
isn't it? I never knew.)
Now, there are various nuances to the statements above, such as
whether access to source code must be restricted in some ways,
rather than being freely available. And by "the" source
code, do I mean all revisions? Do I mean for all
components of the system? And by "the" development tools, do
I mean the original ones, or do I mean partial work-alikes?
And by emulation, do I mean emulation of the entire stack of code,
or just for some restricted portion of it? And besides
which, how do I really know which documents may be relevant to
these matters and which may be completely irrelevant?
For example, although I explicitly said above that this isn't
the site to come to if you want to learn about engines (SSME), the
engines were in fact controlled by a dedicated controller
containing two redundant Honeywell
HDC-601 digital computers ... so shouldn't those computers
and their software be covered here?
Answers to those questions will become clear in the sections
below ... or at least, clearer than they are now. There are
a lot of gray areas. And I don't pretend to know all of the
answers yet, so we may need to await future events to have
a more-complete picture. But there aren't necessarily
unique, permanently-correct answers anyway. One thing I can
say unequivocally is that integration into space-flight simulation
systems is my hope rather than anything that I'll actively
pursue personally; integration is the prerogative of the developers of those
space-flight simulators, rather than mine, if they feel it's
worthwhile for them. But it's a bit premature to worry about that yet.
The upshot is that my explanation of the Shuttle's computer systems will by
necessity be rather limited. The system is simply too
complex, and there are too many resources already available on the
web for me to suppose that a presentation by a johnny-come-lately
like me would be worthwhile or even interesting about a topic this
big. Perhaps the best place to get a general introduction
would be Chapter
4, "Computers in the Space Shuttle Avionics System", of James
Tomayko's Computers in Spaceflight: The NASA Experience,
but there are numerous other documents in our Shuttle
Library to provide more detail.
With that said, here's a brief synopsis. As with any
engineering system of substantial complexity, prepare to descend
into acronym hell!
The portion of the Shuttle's full avionics system which primarily
concerns us is the Data Process System (DPS), which
includes the General Purpose Computers (GPC), the crew
interface (display and keyboards), the mass-memory units, and the
data-bus network interconnecting all of them. Here's a
diagram, swiped from the aforementioned Computers in
Spaceflight, that gives a very high-level view of the system
architecture:
Aside: In spite of this technical distinction between the acronyms PFS and PASS, I find in practice (and have been chided by veterans of the Shuttle project) that the term PASS was always used in preference to PFS. In other words, people speak of PASS vs BFS rather than PFS vs BFS, and stare at you blankly if you mention PFS to them. Since that is the common usage, I'm going to adopt it throughout the remainder of this article, and will not pedantically use the acronym PFS (even though it's technically correct) even where the distinction vs PASS is significant.Nominally, the behaviors of these four copies of FCOS were synchronized ... not on a CPU-cycle by CPU-cycle basis, but to the extent that inputs to the GPCs from the spacecraft, as well as commands output from the GPCs to the spacecraft, occurred at the same time. In particular, the fact that outputs from the GPCs were synchronized allowed detection if one of the GPCs was behaving abnormally. I say they did this "nominally", because this extreme level of redundancy was warranted only during critical flight phases ... in particular, during ascent and reentry. During the more-leisurely phases of the mission, if additional computing power was needed, the four principal GPCs did not necessarily need to run identical, redundant software.
The pre-2000 configuration was known collectively as the Multifunction
CRT Display System (MCDS), while the post-2000
configuration was known as the Multifunction Electronic
Display Subsystem (MEDS).
In the diagrams below, the pre-2000 configuration is shown on
the left, while the post-2000 configuration is shown on the
right. Notice that the LCD-based displays (on the right)
have 6 buttons along the bottom edges that the CRTs (on the
left) lack, as well as being taller relative to their
width. The LCDs continued to display 51×26 textual
characters, just as the CRTs had, but the text was scrunched
into the upper part of the screen, while a strip along the
bottom of the LCD could display additional stuff that the CRTs
hadn't been able to, such as menu options selectable by the
edge buttons. These differences were transparent to the
PASS / BFS flight software, because the additional stuff
displayed along the bottom was not controlled by the PASS /
BFS software. In contrast, keyboards were the same in
type and number throughout the duration of the Shuttle
program.
Older configuration: 4 CRT displays
(Multifunction CRT Display System, or MCDS) |
Newer configuration: 11 LCD displays (Multifunction Electronic Display Subsystem, or MEDS) |
"PASS software consists of two types of software: system software and application software. System software runs the GPC. It is responsible for tasks such as GPC–to–GPC communication, loading software from MMUs, and timekeeping activities. Application software is software that runs the orbiter. This includes software that calculates orbiter trajectories and maneuvers, monitors various orbiter systems (such as power, communications, and life support), and supports mission–specific payload operations. The application software is divided into broad functional areas called major functions; in turn, each major function consists of Operational Sequences (OPS), which are loaded into the GPCs for each major phase of flight.Schematically, schematically you can see how the application software was structures, at least in one version of the flight software. Over the decades in which the Shuttle's flight software was in use, there were certainly changes to this structure.
"Finally, each OPS has one or more Major Modes (MMs) that address individual events or subphases of the flight."
All documents I can find that I feel are relevant to discussion
of the Space Shuttle's onboard computer systems and their software
have been collected on our Space Shuttle Library page.
That should be your first stop in a documentation
pilgrimage! However, here are some websites that have
additional documents that you may find interesting, and which may
still contain relevant materials that I've overlooked:
I have become aware of private individuals with copies of what I
think may be the complete very-late revisions of the Shuttle's
flight software, both primary (PFS/PASS) and backup (BFS).
This is remarkable, given that a former developer of Shuttle
software has told me that:
"When NASA shut down the Space Shuttle project, they erased all of the backup storage media — since there WAS NO REQUIREMENT for saving source code! Most of the HAL/S compiler and related tools (like ... other support software were not saved), but all of the HAL/S-based flight code was preserved."
In fact, I filed a Freedom of Information Act (FOIA) request with
NASA's FOIA Office to get a copy of the flight software from NASA, but
after several months of looking around they asserted that they didn't
have a copy of it. So apparently NASA fully lived up to the lack
of a requirement for preserving it, in spite of the assertion of my
informant that the flight code had in fact been mysteriously saved
(somewhere) after all. My developer informant also told me that
the Shuttle flight-code was the most-expensive software-development
project of all time. Good job all around, U.S. Government
agencies, preserving tax-payer investment!
But I digress.
Unfortunately, identifying that the source code for the
Shuttle's flight software still exists is not the same thing as saying
that I've convinced anybody to give me much of it. Without being
too specific, I will simply say that I presently have some
PASS source-code files in hand, representing a small fraction
of the total, but that I am not at liberty to show them to you due to
issues which I hope can eventually be resolved. Indeed, I can't even necessarily tell you yet everything I have managed to acquire. It's an unpleasant situation that I hope and expect to improve over time.
On the other hand, here is some software source code we do have, and which you can see right now in our source tree:
To the extent that we can present the contemporary source code
for Shuttle-related software here, or to work with it using the tools
provided on this site, some alterations from the original source code
files have been needed. We hope that these changes are not
substantive, but a difference is a difference, and you're entitled to
know about it if you're interested.
For one thing, Virtual AGC header blocks, consisting of program
comments, are added at the top every contemporary file we receive, so
that you can understand the provenance of the files as much as
possible.
These comments are crafted in a way that lets you distinguish such
"modern" comments from the original contents of the files.
Flight software files, when they become available, are expected to be "anonymized"
or "depersonalized", so as to remove all personally-identifying
information related to the original development teams; thus, whenever
the name or initials of a programmer are discovered in the program
comments of Shuttle flight software, we have replaced them by a unique
but impersonal numerical codes. This is at the behest of
some holders of the original source materials, as a condition for
obtaining the software. Whether this is a temporary or permanent condition, I cannot say.
Most significant, I expect, is the fact that the character encoding
of all contemporary Shuttle source code has been completely
changed. This necessity arises directly or
indirectly from the fact, unfortunate from our point of view, that the
contemporary character-encoding system used was an IBM system called
EBCDIC
(Extended Binary Coded Decimal Interchange Code), while modern source
code (as far as I know) is universally encoded using 7-bit ASCII
(American Standard Code for Information Interchange) or extension of
it such as UTF-8. But EBCDIC and ASCII are essentially 100%
incompatible, with only rare, accidental overlaps. The recoding of
the source-code files from EBCDIC to ASCII has been done before we ever
received any of the files, and was performed by unknown people, at an
unknown time, using an unknown process. Nor was it always
perfectly done, and has required occasional corrections by us.
Moreover, the EBCDIC vs ASCII issue isn't quite as simple as the
preceding paragraph suggests, because not all of the EBCDIC characters
used originally actually have ASCII equivalents. There are special
considerations regarding how you need to work with HAL/S source code in
light of those characters not supported by ASCII.
Here are the general rules:
A longer explanation is that for some decades now, the most-common character encoding in the U.S. has been 7-bit ASCII, 128 characters in all, sometimes called "plain vanilla" ASCII or just "ASCII". But since the Space Shuttle's flight software was originally developed on IBM mainframe systems like System/360, rather than using ASCII used an 8-bit character-encoding scheme called EBCDIC. It's pretty difficult to find any two EBCDIC tables that agree on all 256 characters, because various IBM systems seemed to have used slightly-different versions of EBCDIC. But here are ASCII and EBCDIC tables I pulled from Wikipedia that give the basic idea:Aside: With that said, if your operating system supports UTF-8 character coding rather than simple 7-bit ASCII, you can continue to use "¬" and "¢" in HAL/S source code. The compiler transparently converts them to "~" and "`" during the compilation, and then converts them back to "¬" and "¢" in printouts or in messages it displays. In particular, this does work fine in Mac OS and Linux, though there may be special considerations trying to do this in Microsoft Windows, discussed later. In some of the source code we receive, ¬ has instead already been replaced by "^". Thus any software we provide also silently converts "^" to "~".
ASCII (1977/1986) | ||||||||||||||||
|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
0x | NUL | SOH | STX | ETX | EOT | ENQ | ACK | BEL | BS | HT | LF | VT | FF | CR | SO | SI |
1x | DLE | DC1 | DC2 | DC3 | DC4 | NAK | SYN | ETB | CAN | EM | SUB | ESC | FS | GS | RS | US |
2x | SP | ! | " | # | $ | % | & | ' | ( | ) | * | + | , | - | . | / |
3x | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; | < | = | > | ? |
4x | @ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O |
5x | P | Q | R | S | T | U | V | W | X | Y | Z | [ | \ | ] | ^ | _ |
6x | ` | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o |
7x | p | q | r | s | t | u | v | w | x | y | z | { | | | } | ~ | DEL |
EBCDIC | ||||||||||||||||
|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
0x | NUL | SOH | STX | ETX | SEL | HT | RNL | DEL | GE | SPS | RPT | VT | FF | CR | SO | SI |
1x | DLE | DC1 | DC2 | DC3 | RES/ ENP |
NL | BS | POC | CAN | EM | UBS | CU1 | IFS | IGS | IRS | IUS/ ITB |
2x | DS | SOS | FS | WUS | BYP/ INP |
LF | ETB | ESC | SA | SFE | SM/ SW |
CSP | MFA | ENQ | ACK | BEL |
3x |
|
|
SYN | IR | PP | TRN | NBS | EOT | SBS | IT | RFF | CU3 | DC4 | NAK |
|
SUB |
4x | SP |
|
|
|
|
|
|
|
|
|
¢ | . | < | ( | + | | |
5x | & |
|
|
|
|
|
|
|
|
|
! | $ | * | ) | ; | ¬ |
6x | - | / |
|
|
|
|
|
|
|
|
¦ | , | % | _ | > | ? |
7x |
|
|
|
|
|
|
|
|
|
` | : | # | @ | ' | = | " |
8x |
|
a | b | c | d | e | f | g | h | i |
|
|
|
|
|
± |
9x |
|
j | k | l | m | n | o | p | q | r |
|
|
|
|
|
|
Ax |
|
|
s | t | u | v | w | x | y | z |
|
|
|
|
|
|
Bx | ^ |
|
|
|
|
|
|
|
|
|
[ | ] |
|
|
|
|
Cx | { | A | B | C | D | E | F | G | H | I |
|
|
|
|
|
|
Dx | } | J | K | L | M | N | O | P | Q | R |
|
|
|
|
|
|
Ex | \ |
|
S | T | U | V | W | X | Y | Z |
|
|
|
|
|
|
Fx | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|
|
|
|
|
EO |
HAL/S? HAL/S was a high-level programming language in which
the PASS and BFS application software was written. Whereas
infrastructural software (like operating systems and run-time
libraries) was written in whatever assembly-languages were native
to the particular CPUs running that code, which for IBM computers was IBM's so-called Basic Assembly Language (BAL).
HAL/S was a compiled language, and the HAL/S flight-software
source code was compiled down to a machine-code executable before
it could be run. Compilers existed for it that could be used
on several different types of computers. Some of the
compilers produced code that could be run on an IBM System/360
mainframe; others could produce executable code for the Shuttle's
IBM AP-101S onboard computers; for all I know, others produced
executable code for other computers.
I'm sure you can't help but notice that "HAL" was the name of the
computer in the movie 2001: A Space Odyssey, which came
out in 1968, not too many years before the HAL/S language was
invented. In the movie, H.A.L. stood for "Heuristic
Algorithmic Logic", and many people have observed that H.A.L. was
just one letter away from I.B.M. (I.e., "H" is one letter
before "I" in the alphabet, "A" is one letter before "B", and "L"
is one letter before "M".) The writer of the movie, Arthur
C. Clarke, maintained that that was simply a coincidence.
Where the "HAL" in HAL/S comes from has likewise been explained in
several ways, none of them relating to 2001: A Space Odyssey.
The HAL/S language was invented (and the flight software was
written) by a company called Intermetrics, many of whose employees
were refugees from the same Draper Laboratories (MIT
Instrumentation Laboratory) at which the Apollo flight software
had been written. One of those refugees was Ed Copps, one of
Intermetrics's founders, who is said to have named the HAL/S
language in honor of Hal Laning, perhaps the most-prominent among
the designers of the Apollo Guidance Computer's hardware.
Others offer the explanation that HAL/S is an acronym for
"High-order Assembly Language / Shuttle". Still
others state that "the acronym 'HAL' was never formally
defined". I have even seen one report (NASA-CR-141758) that
refers to it as "Houston Aerospace Language". Well, who
knows? It's fun to make up your
own mind about which constellation of facts matches your own
preferences. Probably not Houston Aerospace Language! But all I can really say for sure is that there's
nothing "heuristic" about HAL/S, even if 2001 may secretly
have been somewhere in the back of somebody's mind.
But I digress. As I was saying, the HAL/S software for the
Shuttle's PASS and BFS still survives in private stashes, which is
much better than the alternative of it not existing
anywhere. But I have very little of it as of yet, and am enjoined
to keep that which I do have private. Whether or not I can get
any more of it — and the extent to which I'm required to keep it
private after I get it — depends very much on the kindness of strangers.
Assuming that we can eventually get access to it, working with
the application software's source code requires knowledge of the
HAL/S language. Fortunately, we have a fair amount of
documentation of that:
We actually have quite a few revisions of some of these documents in our library, spanning the mid-1970's to the
mid-2000's, though I've only chosen to link the latest versions of
those documents above, even though from time to time the latest revision isn't always the most complete one.
Here's a brief sample of HAL/S code from "Programming in HAL/S",
just to give you its flavor:
FACTORIAL:
PROGRAM;
DECLARE INTEGER,
RESULT, N_MAX, I;
READ(5) N_MAX;
RESULT = 1;
DO FOR I = 2 TO N_MAX BY 1;
RESULT = I RESULT;
END;
WRITE(6) 'FACTORIAL=', RESULT;
CLOSE FACTORIAL;
What this program does is to read a number (N_MAX),
compute its mathematical factorial, then output the result.
While I won't dissect this short program in detail, I can make a
couple of observations. For one, the language is strongly
typed, meaning that every variable has a type that's
declared at compile time, and that storage for it is fixed and
unalterable at run-time. Nor is there any dynamic memory
allocation (as well as no stack and no recursion), so RAM usage is
completely known at compile time. HAL/S programs never
unexpectedly abort because memory has filled up. The other
observation is that the READ(5) and WRITE(6)
statements are very familiar to FORTRAN users ... or at least to
FORTRAN users of (say we say?) a certain vintage. In
FORTRAN-speak, the 5 and 6 are "logical unit numbers" (LUN) whose
specific interpretation as keyboard and printer (or keyboard and
display, or even as files) are assigned externally by the
Job Control Language (JCL) used to run the job. This
reflects the fact that the first HAL compilers targeted IBM 360
computers rather than the Shuttle's computers. In the
Shuttle software, these READ and WRITE
constructs, I think, wouldn't have been used, and keyboard input or display
output would instead have been handled by calls to the run-time
library.
C Compute corners of a parallelogram.What this example program does is to allow input of parameters describing a parallelogram — namely, the lengths of a "short" side and a "long" side (which is assumed to be along the x-axis), and the angle between them in radians — and then to output the (x,y) coordinates of the four corners. The code also illustrates another of HAL/S's novel features, in that it can do arithmetic not just on scalar variables like integers or floats, but also do vector arithmetic or even matrix arithmetic. For example, vector/matrix addition or subtraction, vector dot products or cross products, matrix multiplication or inversion, etc. Functions like COS or SIN or VECTOR2 (which forms a 2-vector from two scalar inputs) were available in the run-time library or as compile-time arithmetic when appropriate.
CORNERS: PROGRAM;
DECLARE SCALAR,
LONG, SHORT, ALPHA;
DECLARE VECTOR(2),
AB, BC, CD, DA;
READ(5) LONG, SHORT, ALPHA;
E -
M AB = 0;
E -
M BC = VECTOR (LONG, 0);
S 2
E -
M DA = VECTOR (SHORT COS(ALPHA), SHORT SIN(ALPHA));
S 2
E - - -
M CD = BC + DA;
E - - - -
M WRITE(6) AB, BC, CD, DA;
CLOSE CORNERS;
But you'll notice that if you have a subscript in an E line or an exponent in an S line (as in DEX$J or M**2 above), you just have to live with those little bits remaining in single-line notation. (In fact, there's not even any real need to put an M in column 1 for a main line, since the M meant exactly the same thing to the original compilers as a blank in column 1. I'm told — thank heaven! — that nobody ever actually did omit the M's.)E DEX$J
E I I
M COEF ALPHA
S L
S M**2
CORNERS: PROGRAM;In the single-line format, The beginning of a subscript is indicated by the '$' character.
DECLARE SCALAR,
LONG, SHORT, ALPHA;
DECLARE VECTOR(2),
AB, BC, CD, DA;
READ(5) LONG, SHORT, ALPHA;
AB = 0;
BC = VECTOR$2(LONG, 0);
DA = VECTOR$2(SHORT COS(ALPHA), SHORT SIN(ALPHA));
CD = BC + DA;
WRITE(6) AB, BC, CD, DA;
CLOSE CORNERS;
DECLARE SCALAR, X, Y, Z;
DECLARE INTEGER, I, J, K;
X = Y Z ;
I = 2 J K ;
By the way, SCALAR is what HAL/S calls its
floating-point type; thus SCALAR contrasts with INTEGER
or BOOLEAN datatypes, but not with VECTOR or MATRIX.
In fact, all VECTOR and MATRIX objects consist
entirely of SCALAR values. You can't have (say) a
VECTOR of INTEGER values. On the other
hand, there is an ARRAY type, of arbitrary
dimensionality, which can hold values of any datatype you like,
including VECTOR and MATRIX. And as it
turns out, there actually is an operator '*', but it is
the vector cross-product operation, not a multiplication of two
numbers. Similarly, the '.' operator is a vector
dot product.
As I've described above, any given shuttle had a number of
computers, running a lot of different software components — more
than just the GPCs running PASS/BFS we're discussing here.
Each of these software components had their own unique
versioning. I couldn't begin to tell you what those all are;
I don't even have a list of all the different computers or their
software components, let alone details about their versions.
However, in all but the very earliest missions, the collection
of all of the software components at their various revision levels
was itself identified by what's called the Operational
Increment (OI). You thus see various Shuttle documents
specifying "OI-24" or "OI-33", and what this means is that those
documents are specialized to those particular overall software
versions. The versioning of individual software components
of the overall software version was apparently by Version
Increments (VI), such as "VI 1.23".
At this point, I have no authoritative single document that links
software versions to specific Shuttle missions. For what
information I do have, I'd refer you to the Space
Shuttle Missions Summary. In the following tabulation,
sorted by software version, notice that a higher STS mission
number sometimes has a lower software version number, presumably
partially because the mission numbering doesn't perfectly agree
with the chronological order in which the missions were
flown. For that matter, notice confusing duplicate numbers,
like the entire range STS-26 through STS-33 (skipping STS-29); not
my fault, blame NASA!
Mission |
Software Version |
---|---|
STS-1 |
R16/T9 |
STS-2, STS-3, STS-4 |
R18/T11 |
STS-5, STS-6, STS-7, STS-8 |
R19/T12 |
STS-9 (STS 41-A), STS-11 (STS
41-B), STS 41-C (STS-13) |
OI-2 |
STS 41-DR (STS-14), STS
41-G (STS-17), STS 51-A (STS-19), STS 51-C (STS-20), STS 51-E (STS-22), STS 51-B (STS-24) |
OI-4 |
STS 51-D (STS-23), STS-51-E
(STS-22) |
OI-5 |
STS 51-F (STS-26) |
OI5-24 |
STS 51-G (STS-25) |
OI-6 |
STS 51-I (STS-27) |
OI6-27 |
STS 51-J (STS-28) |
OI6-28 |
STS 61-A (STS-30) |
OI6-29 |
STS 61-B (STS-31) |
OI6-30 |
STS 51-L (STS-33) |
OI17-26 |
STS 61-C (STS-32) |
OI17-32 |
STS-26 (STS-26R), STS-27 (STS-27R),
STS-28 (STS-28R), STS-29 (STS-29R), STS-30 (STS-30R), STS-33 (STS-33R) |
OI-8B |
STS-31 (STS-31R), STS-32 (STS-32R),
STS-34 (STS-34R), STS-36 (STS-36R) |
OI-8C |
STS-35 (STS 61-E), STS-38,
STS-40, STS-41 |
OI-8D |
STS-37, STS-39 |
OI-8F |
STS-42, STS-43, STS-44,
STS-45, STS-48 |
OI-20 |
STS-46, STS-47, STS-49,
STS-50, STS-52, STS-53,
STS-54, STS-55, STS-56 |
OI-21 |
STS-51, STS-57, STS-58,
STS-59, STS-60, STS-61, STS-62, STS-68 |
OI-22 |
STS-63, STS-64, STS-65,
STS-66, STS-67 |
OI-23 |
STS-69, STS-70, STS-71,
STS-72, STS-73, STS-74, STS-75, STS-76, STS-77, STS-78 |
OI-24 |
STS-79, STS-80, STS-81,
STS-82, STS-83, STS-84, STS-94 (STS-83R) |
OI-25 |
STS-85, STS-86, STS-87,
STS-89 |
OI-26 |
STS-88 (ISS-2A), STS-90,
STS-91, STS-93, STS-95, STS-103 |
OI-26B |
STS-92 (ISS 3A), STS-96
(ISS-2A.1), STS-97 (ISS 4A), STS-99, STS-101 (ISS 2A.2a), STS-106 (ISS 2A.2b) |
OI-27 |
STS-98 (ISS 5A), STS-100
(ISS 6A), STS-102 (ISS 5A.1), STS-104 (ISS 7A), STS-105 (ISS 7A.1), STS-108 (ISS UF-1), STS-109 |
OI-28 |
STS-107, STS-110 (ISS 8A),
STS-111 (ISS UF-2), STS-112 (ISS 9A), STS-113 (ISS 11A) |
OI-29 |
STS-114 (LF-1), STS-115
(ISS 12A), STS-116 (ISS 12A.1), STS-117 (ISS 13A), STS-118 (ISS 13A.1), STS-121 (ULF1.1) |
OI-30 |
STS-120 (ISS 10A), STS-122
(ISS 1E), STS-123 (ISS 1JA), STS-124 (ISS 1J), STS-125 |
OI-32 |
STS-119 (ISS-15A), STS-126
(ISS-ULF2), STS-127 (ISS-2JA) |
OI-33 |
STS-128 (ISS 17A), STS-129
(ULF3), STS-130 (ISS 20A), STS-131 (ISS 19A), STS-132 (ULF4), STS-133 (ULF5), STS-134 (ULF6), STS-135 (ULF7) |
OI-34 |
For example, the presentation for the STS-121
Flight Readiness Review (FRR) tells us that the software
version was OI-30, in agreement with the table above, while just
the Integrated Display Processor (IDP) software component was
version VI 4.01 and the Multifunction Display Unit Function (MDUF)
was version VI 5.00.
As was mentioned earlier in the Introduction, the principal method by
which the General Purpose Computers (GPC) running the primary
flight software (PASS) and backup flight software (BFS) interact
with the crew includes keyboards and display screens. What's
unusual about the display screens is that what appears on them is
only partially controlled by the PASS or BFS
software. Instead, there was another processor sitting
between each of the displays and the GPCs, and it was this extra
processor that directly controlled what was displayed and how the
display was formatted. (For that matter, the keyboards also
were attached to one of these extra processors rather than to the
GPCs, so whatever keystrokes were seen by the PASS / BFS software
had already been pre-digested by these extra processors.)
In the case of the older, pre-2000
cockpit configuration (MCDS, 4 CRTs), this extra processor was
known as the Display Electronics Unit (DEU), and it
consisted of an IBM SP-0 CPU with 8K×16 bits of RAM. In the
case of the newer, post-2000 cockpit configuration (MEDS, 11
LCDs), the extra processor was known as the Integrated Display
Processor (IDP), an Intel 368DX microprocessor. The basic
schema is seen in the diagram to the right. While the
diagram is specific to the older (MCDS) configuration, the newer
(MEDS) configuration is conceptually quite similar. In the
case of the MEDS configuration, the software for the IDP that was
specifically tasked with formatting the display was called the Display
Application Software (DAS). But these kinds of details
are of little interest to us in the absence of the DAS or other
software that actually ran on the DEU/IDPs. So the only use
of these factoids I'll use in the context of the present
discussion is to refer from now on to what I've been calling the
"extra processor" instead as the "DEU/IDP".
What is of importance to us, however, is that in addition
to inputs from the GPCs via the MIL-STD-1553 databuses, the
DEU/IDP's RAM was used to store a set of templates that controlled
the formatting of the display screen. These templates were
loaded from mass memory into RAM at power-up. In other
words, the screen templates are independent of the PASS /
BFS source code.
PASS GNC SYS SUMM 1 screen, STS-96
|
BFS GNC SYS SUMM 1 screen, STS-96
|
As you can probably deduce from these images, some of the areas
are supposed to be updated with data from the GPC (or elsewhere in
the spacecraft), such as the HH, MM, and SS in the upper-right
corner or the X's and S's that are all over the place. Other
markings, like the "SURF", "POS", "MOM", and "DPS" are simply
features of the template, and don't change at the whim of the GPC
or more specifically, of PASS or BFS.
The screen templates don't quite fall under the
Operational Increment (OI) top-level software-versioning scheme
we've already discussed. They do, but they are also
controlled by Program Change Notices (PCN). The
examples above are for STS-96 which flew software version OI-27,
but that doesn't mean that all missions using OI-27 necessarily
had identical screen templates. In a practical sense, what
this means is that to know the screen templates and consequent
display-screen formats for any given Shuttle mission, we must have
not merely the screen templates for that generic OI, but also the
differences to those templates that were made due to specific PCNs
... and of course, actually have the associated documentation so
that we can consult it.
Several documents provide screen templates that can be related to
one or more missions or software versions. The
most-available seems to be JSC-48017, the "Data Processing
System Dictionary". We have several revisions of
JSC-48017 in our Shuttle Library, and in principle, if we
could collect all of the different revisions, then we'd
have all of the screen templates for all of the missions. The
GNC SYS SUMM 1 sample templates above came from one such DPS
Dictionary. There are also reference-card-like
summaries that are very helpful, such as this
one for OI-34.
On the other hand, the Functional Subsystem Software
Requirements (FSSR) documents also contain these
templates, and seem a lot more authoritative, as well as providing
a lot more information. In fact, the FSSR goes so far as to give
screen coordinates for each field, and to explain how every datum
received by the DEU/IDP via the databus relates specifically to
each X and S on the display screen! Unfortunately, the FSSRs
are also a lot more numerous and a lot harder to find than DPS
Dictionaries are, so the dream of obtaining a complete set of them
seems more whimsical than obtaining a complete set of DPS
Dictionaries. Nevertheless, on balance, it seems as though
the FSSRs should be regarded as the controlling documents for the
screen templates. We just need to collect all of them, or
failing that, fall back on DPS Dictionaries when available.
For example, here are the same GNC SYS SUMM 1 templates, but for
software version OI-34 (say, mission STS-128), taken from the
FSSR. They're different than the ones shown above for
STS-96, though only barely so. Personally, I see only 4
differences, some sensible, some nonsensical, and some (I suspect)
misprints; perhaps you can find more. Incidentally, STS-96
had the MCDS (pre-2000) cockpit configuration, while STS-128 had
the MEDS (post-2000) cockpit configuration, so perhaps that has
something to do with the differences.
PASS GNC SYS SUMM 1 screen, STS-128
|
BFS GNC SYS SUMM 1 screen, STS-128
|
Keyboard data was supplied to the General Purpose Computers
(GPC), and hence to the PASS/BFS software, by means of messages on
the MIL-STD-1553 databuses interconnecting the GPCs and
DEU/IDPs. Similarly, data was output by the GPCs for display
by passing messages on the databuses as well. Technical
details about this messaging can be found in the Data
Processing System Brief. I won't bother to summarize
that information here, since the document's presentation is at
least as readable as anything I might write up to supplement
it. While our only available revision of this document so
far is for the MCDS, recall that the change from the MCDS to MEDS
cockpit configurations was done in a way that was transparent to
the existing software. That implies, I hope, that the
messaging format would have been the same in either configuration.
TBD
This section concerns itself entirely with the 2nd of these, namely compilation of HAL/S.
This turns out to be a complicated topic, both because the HAL/S
language is very complex in comparison to assembly languages like those
of the Apollo AGC, AGS, or LVDC, but also because it's hard to make an
effective compiler entirely independently of consideration of how the
object code will eventually be executed. As a result, compiler
development has proceeded in fits and starts, with tremendous amounts of
work being done on one approach or another, only to be eventually
abandoned in an incomplete state. And yet, the abandoned work
remains useful in some ways, so I can't truly discard it in good
conscience. In the next subsection I'll discuss the current
approach to a HAL/S compiler, while the two subsections thereafter will
discuss those zombie approaches ... not quite dead, but not quite alive
either.
In my current thinking, the roadmap to a usable HAL/S compiler is this:
In point of fact, HAL/S-FC had a total of 7 passes,
each one of which was a standalone program that executed separately,
and each of these could in principle be compiled with HAL/S-FC.
Emulation, or alternatively generation of object-code for non-IBM-BAL
computers, is outside the scope of this section. But it would
presumably either proceed from the HALMAT output of PASS1, or else from
the BAL output of PASS2. At this point, my vote would be for a
BAL-to-C translation system. In fact, emulators already exist that could presumably
run IBM System/360 object code generated by PASS2 of the compiler,
though I don't think that would be of much help in using the code within
a spacecraft-simulation system.
SIMPLE: PROGRAM;HAL/S considers the PROGRAM to be the basic executable unit, and thus at runtime the expectation would be that some selection of PROGRAMs is running, and possibly intercommunicating, and receiving timeslices to do so according to the assigned execution-priorities. But with the interpreter, we can just bypass all of that infrastructure and compute any values we like, directly and immediately, without wrapping our code in a PROGRAM. For example, by inputting a couple of hopefully-self-explanatory lines of HAL/S code into the interpreter, I get the following
DECLARE PI CONSTANT (3.141592653589793);
DECLARE R SCALAR;
WRITE(6) 'Input values of R to compute PI R**2, or else -1 to quit.';
DO WHILE TRUE;
READ(5) R;
IF R < 0 THEN EXIT;
WRITE(6) 'R =', R, 'and PI R**2 =', PI R**2;
END;
CLOSE SIMPLE;
HAL/S > DECLARE PI CONSTANT (3.141592653589793);Which is pretty convenient! But if we liked, we could still go to the trouble (not much!) of inputting the entire SIMPLE program into the interpreter, and then running it and inputting a few numbers into it:
HAL/S > DO FOR TEMPORARY I=0 TO 10; WRITE(6) I, I PI**2; END;
0 0.0
1 9.86960440108936E+00
2 1.97392088021787E+01
3 2.96088132032681E+01
4 3.94784176043574E+01
5 4.93480220054468E+01
6 5.92176264065361E+01
7 6.90872308076255E+01
8 7.89568352087149E+01
9 8.88264396098042E+01
10 9.86960440108936E+01
HAL/S >
HAL/S > `spoolIn case you're wondering, user input that begins with a backtick (`) is a command to the interpreter itself rather than a statement in the HAL/S language. In this example, `spool and `unspool are present to keep the interpreter from trying to execute each statement in the definition of the SIMPLE program individually, and instead treating them as an entire unit to be processed together. Meanwhile, just defining the SIMPLE program doesn't cause the SIMPLE program to execute, and it's the actual execution that's triggered by `run SIMPLE. And of course, SIMPLE doesn't vanish after we've finished running it; the interpreter still recalls its definition, and we could run it again if we liked:
Now spooling input for later processing.
HAL/S > SIMPLE: PROGRAM;
... > DECLARE PI CONSTANT (3.141592653589793);
... > DECLARE R SCALAR;
... > WRITE(6) 'Input values of R to compute PI R**2, or else -1 to quit.';
... > DO WHILE TRUE;
... > READ(5) R;
... > IF R < 0 THEN EXIT;
... > WRITE(6) 'R =', R, 'and PI R**2 =', PI R**2;
... > END;
... > CLOSE SIMPLE;
... > `unspool
Halting spooling of input. Processing already-spooled input ...
HAL/S > `run SIMPLE
Running as the primary thread.
Input values of R to compute PI R**2, or else -1 to quit.
READ > 0 1 2 3 4 5
R = 0.0 and PI R**2 = 0.0
R = 1.00000000000000E+00 and PI R**2 = 3.14159266000000E+00
R = 2.00000000000000E+00 and PI R**2 = 1.25663706400000E+01
R = 3.00000000000000E+00 and PI R**2 = 2.82743339400000E+01
R = 4.00000000000000E+00 and PI R**2 = 5.02654825600000E+01
R = 5.00000000000000E+00 and PI R**2 = 7.85398165000000E+01
READ > 6
R = 6.00000000000000E+00 and PI R**2 = 1.13097335760000E+02
READ > 7
R = 7.00000000000000E+00 and PI R**2 = 1.53938040340000E+02
READ > 8
R = 8.00000000000000E+00 and PI R**2 = 2.01061930240000E+02
READ > -1
HAL/S >
HAL/S > `run SIMPLEWhile the interpreter is far from complete (or correct!) that's just a small sampling of what it can do. I won't elaborate on it any more here. If you'd like to experiment with it yourself, you should consult the dedicated HAL/S Interpreter page for a lot more info on how to go about it.
Running as the primary thread.
Input values of R to compute PI R**2, or else -1 to quit.
READ > 20 21 -1
R = 2.00000000000000E+01 and PI R**2 = 1.25663706143592E+03
R = 2.10000000000000E+01 and PI R**2 = 1.38544236023310E+03
HAL/S >
Aside: The reason this approach was halted was mainly that it had become to unwieldy to continue adding the still-unimplemented features of HAL/S to the compiler portion of it. Moreover, I felt that the emulator portion, written in Python, while adequate, was slower in execution than I desired and too difficult to integrate into spacecraft-simulation software. Development on it could still continue someday, if desired.
(This section describes a completed but now-abandoned approach towards HAL/S compilation remains useful as a tool for cross-checking other approaches towards HAL/S compilation.)
My second approach to the HAL/S compilation problem was to port the original compiler, HAL/S-FC, from XPL/I to Python. HAL/S-FC consisted of 7 passes:Note: It's unfortunate that the Shuttle's Primary Avionics Software Subsystem (i.e., the flight software) is also referred to as "PASS". But do not be confused: PASS1, PASS2, PASS3, and PASS4 refer to passes of the compiler, and not to the PASS flight software.
I had felt that only PASS1 of the compiler needed to be ported, and
that emulation or object-code generation could proceed directly from the
HALMAT intermediate code produced by PASS1. I eventually turned
out not to be entirely correct in my thinking. Nevertheless, the
port of PASS1 was completed, apparently successfully, though it wasn't necessarily thoroughly tested.
Installation of the PASS1 port goes as follows:
git clone --depth=1 https://github.com/virtualagc/virtualagc.git
This is lots more than you need just for the HAL/S compiler, but it's by far the simplest and fastest way. And easy to update later with the command "git pull". (GitHub provides a way to download just the folder you need, but it takes such an incredibly long time that I won't waste your time or mine by describing it. Google it if you want.)
HAL_S_FC.py --helpIf you do, you're ready to go!
Aside: This command-line interface to the HAL/S compiler is my own addition rather than a port from the original. The IBM System/360 style computers on which the original HAL/S compiler ran had no such thing as a command line, and therefore no such thing as command-line options. Rather, invocation of the compiler, including specification of all of its options, was performed by creating a Job Control Language (JCL) file containing all of the necessary setup instructions, and of course we don't have any modern support for JCL. However, the command-line interface supports most of the same options which the JCL did, except for some which I haven't figured out well enough yet, plus a few of my own devising.
But there are a lot of options, not all of which can be explained in just a few words, so the --help command mentioned in the preceding paragraph may turn out to be less informative than you may hope ... for example, it tells you that the option LFXI is available (vs NOLFXI), but do you want that option or not? Well, you won't find out by looking at the --help message. In fact, I don't believe there's surviving documentation that describes the complete set of compiler options available. If you're interested beyond my limited attempt to spoon-feed you this info, my suggestion is to peruse Section 5 ("User-Specified Options") of the 2005 revision of the "HAL/S-FC User's Manual". However, in the next section, I'll provide my own recommendations as to which compiler options should be used.
As far as using the port of the
compiler's PASS1 is concerned, everything you do with the HAL/S compiler
is from a command line, so
everything I talk about below is something you're going to do or see on a
command
line.
Let's suppose you have a folder that contains HAL/S source-code
files. For example, if you followed the installation instructions
given above, you'll have downloaded the folder "yaShuttle/Source
Code/Programming in HAL-S/", which contains ~100 such files. But
regardless, 'cd' to the folder containing whatever HAL/S source-code
files you're interested in.
Let's suppose, for the sake of argument, that you have a HAL/S
source-code file called HELLO.hal. In fact, there is such a file
in the folder yaShuttle/ported/, though naturally you don't have to use
it, but let's suppose you do indeed want to
use it, and that you have cd'd to the yaShuttle/ported/ folder to do
so. That particular HELLO.hal looks like this:
HELLO: PROGRAM;
DECLARE I INTEGER;
DECLARE INTEGER, J;
REPLACE PRINTER BY "6";
WRITE(PRINTER) 'THE BEGINNING';
DO FOR I = 1 TO 5;
WRITE(PRINTER) I, 'HELLO, WORLD!';
DO FOR J = 2 TO 8 BY 2;
WRITE(¢PRINTER¢) J, 'ISN''T THIS FUN?';
END;
END;
WRITE(6) 'THE END';
CLOSE HELLO;
How to compile this? Well admittedly, the only up-to-date operating system I'm using is Linux. The versions of Windows and Mac OS available to me are ancient (Windows 7 and Mac OS 10.7.5). With that said, I have tried the ported HAL/S compiler on the versions I do have, and it works the same on every platform. My suggestion is to invoke the HAL/S compiler as follows:
The meaning of the --hal=HELLO switch here is pretty obvious, I suppose, and it's only necessary to note that if you leave off the suffix ".hal" at the end of a source-file name, the compiler will assume it's supposed to be there and will add it back.HAL_S_FC.py SRN --hal=HELLO
The option SRN tells the compiler to expect that there are
punch-card sequence numbers in columns 73-80 of the source-code lines
... which in HELLO.hal of course, there are not! In fact, you could leave off
this option with no difficulty for this example, or optionally use the
option NOSRN (which is also the default) instead. When SRN is present, columns 1-72 are allowed to contain source code, whereas when NOSRN
is present, columns 1-80 contain source code. All of the sample
source-code files I provide do fit into 72 columns, and all of the
flight-software source-code files (which I can't presently provide) do
have card-sequence numbers in columns 73-80, so using the SRN
option works well with any HAL/S files I provide. If you're going to work with
HAL/S source code, you'd better get used to thinking in terms of a
limited width, and perhaps to a limited width of
72 rather than a limited width of 80!
Here's the output listing you can expect to see from the compilation:
To do anything more-significant with the compiler, you naturally need
to study the HAL/S language a bit, using the references I recommended
earlier. But there are a few details that the contemporary HAL/S documentation
glosses over somewhat, but which you
need to understand if you're going to work with anything other than a trivially-simple HAL/S program.
It seems to have been the custom usually to put a single PROCEDURE or a single FUNCTION or a single COMPOOL in any given compilation unit, but that won't always be the case.
The COMPOOL block needs a little explanation. A COMPOOL in HAL/S functions something like a COMMON
area in Fortran or an imported module in Python (except that it
contains just variables). COMPOOLs have names, and there can be many COMPOOLs present at once.
If you played with the "modern" compiler, you'll recall that it was easy to DECLARE
global variables willy-nilly but from the comments I just made above,
you'll perceive that there's no such thing as a global variable in
HAL/S. Rather, what you might like to think of as a global
variable is actually a variable residing in a COMPOOL.
Now, since each PROCEDURE and FUNCTION usually resides in a
separate (and separately-compiled) compilation unit, and since every
variable that's shared between compilation units usually reside in COMPOOLs in yet other separate
compilation units, to compile even a very simple program without errors you have to understand how all of these separate
compilation units manage to interface to each other.
The mechanism by which this interface is implemented at the compiler level is based on the
notion of the "template library". The template library functions
something like the mechanism of a "header file" in C or C++, in which
the header file provides prototyping information about functions
and variables. But rather than
there being innumerable header files, each specialized to a single
purpose, HAL/S has a single template library that provides the
template information for everything. The compiler will read
the template library whenever a HAL/S source-code file needs it to, but it can also optionally write back to the template library (or some
separate template library) the information it newly discovers about
objects it encounters. In that respect, the template library is a simple kind of database.
The compilation strategy is thus to make sure you compile any
particular compilation unit before you compile any other
compilation unit that needs it. (And yes, it's possible to
have a circular condition in which two different compilation units
depend on each other, which defeats this strategy. We'll just ignore that in this discussion.)
So let's take an example. Let's suppose we have a HAL/S PROGRAM called P, a HAL/S FUNCTION called F that P wants to use, and some "global" variables (A0, A1, and A2) used by both. Since there's no such thing as a global variable, these latter will have to go into a COMPOOL that we'll call C. Nominally that's 3 separate compilation units, comprising 3 separate HAL/S source-code files. Perhaps A0, A1, and A2 are the coefficients of a quadratic polynomial and F() computes the values of the polynomials. Here's what the source code for these three compilation units might look like:
C.hal |
F.hal |
P.hal |
---|---|---|
C: COMPOOL; |
D INCLUDE TEMPLATE C |
D INCLUDE TEMPLATE C |
The first time we process these files, we would have to compile these in left-to-right order, because COMPOOL C needs to be in the template library before F.hal is compiled, and FUNCTION F
must be in the template library before P.hal is compiled. (On
subsequent processing, as long as the prototyping information for COMPOOL C and FUNCTION F didn't change, the template library wouldn't change, and it wouldn't matter what order we compiled the 3 files.) The
suggested compiler command-line switches I gave earlier aren't quite
adequate now that we need to fix up the template library. We need
two additional switches: TEMPLATE, which causes "templates" to be generated for the compilation units encountered, and --templib,
which causes those new templates to be stored in the main template
library, as opposed to being stored by default in a separate, newly-created temporary template library. So here's what
the compilation is like:
HAL_S_FC.py SRN TEMPLATE --templib -hal=C
HAL_S_FC.py SRN TEMPLATE --templib -hal=F
HAL_S_FC.py SRN TEMPLATE --templib -hal=P
For whatever it's worth, the template library is a human-readable
file (in so-called JSON format), found in the same folder as HAL_S_FC.py
itself, namely virtualagc/yaShuttle/ported/TEMPLIB.json. (No, in case you're bothered by such things, JSON did
not exist when the original HAL/S compiler was written. But I use JSON
to implement something the IBM operating system called a Partitioned
Data Set, or PDS for short. The fact that it's JSON rather than
PDS is at the operating-system level and is transparent to the
HAL/S compiler proper.) So can you actually see what the generated templates
look
like just by looking at TEMPLIB.json:
Hopefully this emphasizes a point that may not have been entirely obvious before, which is that the template library merely contains meta-information about the compilation units it has processed, but does not contain the compiled object code for those units! The object code for each unit is separate, and must be combined into a single executable by a linker program ... which we do not have at present....
"@@C ": [
" C: EXTERNAL COMPOOL ; DECLARE A0 SCALAR INITIAL ( 1.7 ) , A1 SCALAR INITIAL ( 5",
" .9 ) , A2 SCALAR INITIAL ( - 3.3 ) ; ",
" CLOSE ; ",
"D VERSION 01"
],
"@@F ": [
" F: EXTERNAL FUNCTION ( X ) SCALAR ; DECLARE X SCALAR ; ",
" CLOSE ; ",
"D VERSION 01"
],
"@@P ": [
" P: EXTERNAL PROGRAM ; ",
" CLOSE ; ",
"D VERSION 01"
],
...
Warning: The side effect of this is that if you had, say, a FUNCTION called VELOCITY_OF_EARTH and another called VELOCITY_OF_SHIP, both of them would result in generation of a template called "@@VELOCI". But there can be only one. The template for whichever was compiled most-recently would overwrite the other's template in the template library, without any warning you'd be likely to notice, probably eventually causing a compile time error when some hapless compilation unit tried to use the now-overwritten function template. (If you recognized the "there can be only one" reference a couple of sentences back, you might say that this is high-handed behavior on the part of HAL/S-FC, or even than HAL/S-FC was a Highhander. Then again, you might not.) This behavior is related to the limitations of the IBM 360 file-system objects known as Partitioned Data Sets, rather than just being some random idiocy; it is analogous to the 8-character filenames (plus 3-character "extensions") that those of us old enough to experience Microsoft DOS (and Digital Research CP/M) had to endure. It didn't seem so bad at the time.
Aside: Why was this the port of PASS1 abandoned? It turned out that additional data concerning the flight software had become available in the meantime, about which I don't yet care to speak, and it became obvious PASS1 was not enough. To make full use of the additional data would require ports of at least the OPT, AUX, and PASS passes. But the effort and cost in time of porting just PASS1 had been so great that I couldn't really tolerate the thought of proceeding to port at least three additional passes. Almost as significant is the fact that the documentation for HALMAT had survived only in incomplete form. HALMAT itself is version-dependent to some degree, and the more-complete but early documentation we have of it is seldom relevant to the compiler source-code version available to us. As porting of the compiler's PASS1 progressed, I became increasingly-less optimistic that adequate HALMAT documentation could be recovered to use it as the basis for emulation or code generation. But since the port of PASS1 can (or should be able to) produce reports and HALMAT output identical to the original HAL/S-FC, it remains valuable as a cross-checking tool, even if abandoned for primary HAL/S development.