apollo guidance computer agc

607
Block I Apollo Guidance Computer (AGC) How to build one in your basement Part 1: Overview John Pultorak December, 2004

Upload: kevin-haworth

Post on 19-Nov-2014

119 views

Category:

Documents


5 download

DESCRIPTION

This is a compilation of nine sections which describe and document every detail on how to build and make fully functional an Apollo Guidance Computer. Not for the casual hobbyist. The author of this incredible work actually built one of these in his basement, took four years. Also, the types of integrated circuits used are not low power, collectively it draws quite a bit of DC current. If you think that take on a monumental challenge, try this - or at least read all about it...

TRANSCRIPT

Page 1: Apollo Guidance Computer AGC

Block IApollo Guidance Computer (AGC)

How to build one in your basement

Part 1: Overview

John Pultorak

December, 2004

Page 2: Apollo Guidance Computer AGC

Abstract

This report describes my successful project to build a working reproduction of the 1964

prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the

Apollo moon landings, and is the world’s first integrated circuit computer.

I built it in my basement. It took me 4 years.

If you like, you can build one too. It will take you less time, and yours will be better than

mine.

I documented my project in 9 separate .pdf files:

Part 1 Overview: Introduces the project.

Part 2 CTL Module: Design and construction of the control module.

Part 3 PROC Module: Design and construction of the processing (CPU) module.

Part 4 MEM Module: Design and construction of the memory module.

Part 5 IO Module: Design and construction of the display/keyboard (DSKY) module.

Part 6 Assembler: A cross-assembler for AGC software development.

Part 7 C++ Simulator: A low-level simulator that runs assembled AGC code.

Part 8 Flight Software: My translation of portions of the COLOSSUS 249 flight

software.

Part 9 Test & Checkout: A suite of test programs in AGC assembly language.

Page 3: Apollo Guidance Computer AGC

Why build an AGC?

Early computers are interesting. Because they’re simple, you can (if you like) actually

understand the entire computer, from hardware to software.

The AGC is the most interesting early computer because: a) it flew the first men to the

moon; and b) it’s the world’s first integrated circuit (IC, or microchip) computer. It also has

interesting architectural features.

Original AGC:Designed by M.I.T. in 1964

World's first microchip computer

Prototype computer for Apollo moon landing

Memory: 12K fixed (ROM), 1K eraseable (RAM)

Clock: 1.024 MHz

Computing: 11 instructions, 16 bit word

Logic: ~5000 ICs (3-input NOR gates, RTL logic)

My AGC:Built from original M.I.T. design documents

Started November 2000, completed October 2004

~15K hand-wrapped wire connections; ~3500 feet of wire

Cost (parts only): $2,980.

Labor: ~2500 hours

Logic: ~500 ICs (LSTTL logic)

Runs flight software (1969 program name: COLOSSUS 249)

How did I build it?I collected orig inal documents from libraries, technical services, and the internet. I had to

pay for some (~$350.) Mostly, they’re available for free now.

I wrote an AGC software simulation (in C++) and cross-assembler (to program it). Then, I

wrote test and checkout programs in AGC assembly language to check the simulator against

specifications in the original documents.

I downloaded a big chunk of original flight software from M.I.T. and got it running on my

simulator.

The simulator was my baseline for logic design. I put my logic design into a circuit design

tool (CircuitMaker) which “captures” schematics and (digitally) simulates circuits. Using

CircuitMaker, I “unit-tested” each AGC subsystem logic design (there are about 20).

Then, I assembled my subsystem logic simulations into one really huge dig ital circuit

simulation of the entire AGC and “integration-tested” this for about 6 months. I eventually

ran my entire suite of AGC test and checkout software on this circuit simulation. (The

simulation was extremely slow, running at about a 500,000 : 1 rate, but very detailed).

I bought parts, mostly from JAMECO, and wire-wrapped the entire computer on 15 circuit

boards in my basement. I built the “relay rack” out of 1x2 inch pine boards, rails for

shelving (can you spot them?), plexiglass, screws, and spray paint.

Page 4: Apollo Guidance Computer AGC

Three AGCs

To succeed, I had to build the AGC three times. Or rather, I had to bu ild three AGCs. Each

one is a fully functional computer. Each one is a step toward building the next. The last one

is the one I wanted.

Here’s the “faces” of my three AGCs:

AGC #1: my C++ AGC simulator.

It has every register and logic

signal in the original

documentation.

I use it to develop and debug

AGC assembly language code.

When I got this working, I knew I

understood the AGC. I knew I

could do the rest of the project.

AGC #2: my CircuitMaker digital circuit

simulator AGC. What you see here are front

panel logic indicators for signals and registers.

The remaining part: about 60 or so pages of

logic diagrams; the same schematics you’ll see

in the CTL, PROC, MEM, and IO .pdf files that

follow this overview.

This AGC literally runs about a half-million

times slower than the first! I used it to debug

my logic design.

When I got this working, I knew I still had a

year (14 months, actually) of tedious work

ahead.

Page 5: Apollo Guidance Computer AGC

AGC #3: This is

the final one.

My hardware AGC

is built into a

relay rack to give

it the same

prototyped

appearance as

the original. The

dimensions are

about 3 x 5 feet.

The upper left

module (CTL) is

the control logic.

The lower left

module (PROC) is

the CPU.

The lower right

module (MEM) is

the memory.

The upper left

module (IO) has

the inputs and

outputs. The

keyboard and

display (DSKY)

for user input are

on the upper-

middle-right.

The white KYNAR

wires look like

cobwebs to me.

This was

photographed in

my back yard.

Can you see the

blue sky and tree

branch reflections

in the upper

panels?

Page 6: Apollo Guidance Computer AGC

Here I am, plugging COLOSSUS 249 flight

software EPROMs into ZIF sockets.

We lugged the AGC out of the basement and

took it outdoors for these photographs. It’s in

the backyard, propped against the back of my

house.

A close-up of COLOSSUS EPROMs. I put red

tape over the quartz windows to keep them

from erasing themselves.

A bought the toggle switches a few years

ago from a surplus vendor. They were so

cheap, I bought a 100 of them. Aren’t they

great?

I really like flashing lights and control panels.

There’s no way to debug something this

complex without them.

I bought LEDs in bulk from the same place

that sold me the switches.

Page 7: Apollo Guidance Computer AGC

AGC Demonstration

Here’s a demonstration of my AGC. It’s running my version of the COLOSSUS 249 flight

software load:

At power-on, the AGC initializes to major mode 00

(POO).

Display CM clock:

<VERB> <0> <6> <NOUN> <3> <6> <ENTER>

The red buttons were from Radio Shack.

The AGC samples and displays the CM clock. 58

hours, 44 minutes, 34.27 seconds.

Page 8: Apollo Guidance Computer AGC

Test display lights:<VERB> <3> <5> <ENTER>

All DSKY lamps and display segments illuminate

for 5 sec. The Verb and Noun displays flash. After

5 sec, the DSKY lamps extinguish. The 88888

displays are left in the registers.

Page 9: Apollo Guidance Computer AGC

Load component 1 for dataset atoctal address 50 with octal 123:

<VERB> <2> <1> <NOUN> <0> <1>

<ENTER>

Verb/noun display flashes: waiting for address

<5> <0> <ENTER>

Verb/noun display flash continues: waiting for

data

<1> <2> <3> <ENTER>

Octal word from R1 is loaded into memory at

address 50.

Page 10: Apollo Guidance Computer AGC

Start a monitor program tocontinuously display elapsed timefrom the CM clock:

<VERB> <1> <6> <NOUN> <3> <6>

<ENTER>

The monitor program starts to continuously

display the CM clock, updating the display about

about 1 second intervals. The time shown is 58

hours, 47 minutes, and 23.67 seconds.

Page 11: Apollo Guidance Computer AGC

Display component 1 of dataset atoctal address 50:

<VERB> <0> <1>

The “key rel” light flashes because the CM clock

monitor program has been suspended.

<NOUN> <0> <1> <ENTER>

verb/noun display flashes: waiting for address

<5> <0> <ENTER>

The octal word from address 50 is displayed in

R1. In a previous operation, we had set the word

to 123.

Page 12: Apollo Guidance Computer AGC

Increment the address:

<NOUN> <1> <5> <ENTER>

The octal word in address 51 is displayed in R1,

incremented address in R3.

<ENTER>

The octal word in address 52 is displayed in R1,

incremented address in R3.

Page 13: Apollo Guidance Computer AGC

Resume the CM clock monitorprogram:

<KEY REL>

Verb 16, noun 36 reappears, along with the

clock display. The key release light goes out.

(I’m not sure why the photos suddenly turned

darker; I think someone must have turned off a

light in an adjoining room)

Terminate the CM clock monitorprogram:

<VERB> <3> <4> <ENTER>

Page 14: Apollo Guidance Computer AGC

Change major mode to P00:

<VERB> <3> <7> <ENTER>

Verb/noun display flashes: waiting for major

mode.

Enter major mode P00:

<0> <0> <ENTER>

AGC starts POO.

Page 15: Apollo Guidance Computer AGC

AGC Project Diary

October - November, 2000:

Thinking about building a computer. Decided to reproduce a minicomputer from the

1960's or ‘70's. Started gathering technical documentation on DEC PDP 8 and Data

General NOVA.

Found a book in the local library (Ceruzzi, “A history of Modern Computing”) with a

page on the AGC. Decided to build a NASA flight computer; Gemini or Apollo. Gemini

interests me more, because it’s the earlier. Downloaded Tomayko’s “Computers in

Spaceflight.”

December 2000:

My search for Gemini computer documentation on CASI and NTIS is fruitless. IBM

federal systems division is gone. Found some interesting AGC documentation. Asked

for, and received, E.C. Hall’s “History of the Apollo Guidance Computer” for

Christmas.

January - February 2001:

Decided to buld an AGC. Ordered about $300. of technical documents from CASI and

NTIS. Discovered you can’t judge a document by it’s title.

Sent e-mail to Goddard Space Flight Center; got a copy of the AGC Basic Training

Manual, a programmer’s manual for the Block II. Went to CompUSA and bought a

Microsoft C++ compiler. Starting to build a AGC Block II software simulation.

Sent an e-mail to Draper Labs (former MIT Instrumentation Lab where AGC was

designed) asking for R-393 (Block I “Logic Description”). This might be the key

document. Draper responds by sending R-393 (free!).

JACKPOT!

Abandoning Block II simulator. I am building a Block I AGC.

March - May 2001:

Rapid progress on the Block I simulation. Wrote an AGC cross-assembler in C++; it

produces object code readable by the AGC simulator. Generating test code to debug

AGC basic instructions.

Designed the simulator to map as closely as possib le to the R-393 hardware

registers, buses, microinstructions, and control signals. Broke the simulation into 20

subsystems that map to AGC hardware. I will eventually use the simulator code to

guide my hardware logic design.

Finished emulation of all 11 normal and extracode instructions. Wrote my first Block I

assembly language program! Starting to simulate the priority counters and

interrupts.

June - August 2001:

Finished v1.0 of the Block I simulator. Wrote a suite of AGC assembly language test

and checkout programs: TECO1 checks basic instructions; TECO2 checks extracode

instructions; TECO3 checks editing registers. Everything works, including interrupts

and counters.

Found MIT website with AGC history and interesting online documentation.

Page 16: Apollo Guidance Computer AGC

E-mailed Eldon Hall, designer of the AGC, telling him about my project. His reply was

gracious and encouraging. Wrote many emails to others asking for Block I source

code.

I order a 2.048 MHz crystal from DigiKey. My first hardware purchase.

September - October 2001:

Can’t find any original Block I source code, except tiny fragments in the documents.

Recoded my own EXEC, WAITLIST, and interrupt handlers using specifications from

R-393 and others. I’m starting to become a good AGC programmer. Now my

simulator can multitask!

Discovered Block II flight software (COLOSSUS 249) is now downloadable from MIT.

300+ pages of blurry assembler source code listing. Is that an eight, a six, number

zero with a slash through it, or the letter “O”, or maybe “G”? Printed a hardcopy. I

think I can make most of it out.

The second half of COLOSSUS is missing! The missing part has the INTERBANK

COMMUNICATION, EXEC, and WAITLIST. E-mailed MIT. Their reply: they don’t have

the missing portion.

November - December 2001:

Tried to reproduce DSKY code using flowcharts from Green’s “Keyboard and Display

System Program”. Green calls it PINBALL GAME. Very confusing. Started writing a

C++ simulation from Green’s flowcharts. Things are becoming clearer.

Located PINBALL in my COLOSSUS fragment. Abandoned effort to code my own. I

will use the real thing.

January - February 2002:

Retyped most of COLOSSUS PINBALL back into machine-readable form. 95% is

already Block I instructions; recoded the remaining 5% into Block I equivalent.

Finished all the octal display verbs (1-5) and decimal verb (6) and the load verbs

(21-25), but they’re only tested for octal loads so far. Noun tables are stubbed, but I

can manually set them for different scaling.

Integrated PINBALL into my EXEC and WAITLIST. Coded up a few missing pieces for

interbank communication. Also had to code a math library (yikes). But it works.

The AGC simulator is running at about 1/30 the speed of the original. I need to speed

it up.

March - May 2002:

Bought a new, faster PC. The simulator now runs at about 1/5 speed. Recoded some

simulator pieces. Now its 1:1.

Finished PINBALL. All regular verbs (0-39) work. Also, normal nouns 1, 2, 3, 9, 15,

26, and 36. Very cool. My favorites: verb 16, noun 36, a monitor routine to

continuously display the AGC clock, and verb 35 which does the lamp test.

Now that I have some proficiency, I am reluctant to leave AGC software, but it’s time

to start hardware logic design.

Page 17: Apollo Guidance Computer AGC

June - December 2002:

Decided to use 74LS logic family. Started designing AGC logic, subsystem-by-

subsystem, using the C++ simulator code as my guide. Began with MBF. Posted a

subsystem block diagram on the wall. I’m coloring in blocks as I finish each

subsystem design.

Entered logic designs into the CircuitMaker PC tool. Using CircuitMaker’s digital circuit

simulation to unit-test each subsystem.

Struggling with ALU and read/write bus design. The original AGC OR’ed everything

onto the bus, and the default bus state was logical zero: sometimes, they read the

bus without writing to clear registers. Other times, they wrote multip le registers

simultaneously to OR the data. These tricks won’t work with tri-state bus drivers. I

identify where tricks are used and add ALU logic to handle the cases. My ALU sort-of

feeds back on itself. Confusing, but it should work.

Logic design the old way: Karnaugh maps, excitation tables, and bubble-pushing.

Fun, sort of.

Logic design is now finished, except for the DSKY. Unit tests are done.

I start ordering parts from JAMECO. The first order is for more than 200 ICs.

January 2003:

DSKY logic design is now finished and unit tested in CircuitMaker. All blocks on my

diagram are colored in. Will the subsystems work together?

February - May 2003:

Using CircuitMaker to integrate subsystems. Diagrams for each subsystem are

hooked into CircuitMaker “macros”; rectangular components with all inputs and

outputs for that subsystem. “Wired” all subsystem macros together. Will it run? I call

it AGC2, to differentiate it from the C++ simulator, which I now call AGC1.

Now I have two AGCs! When I build the hardware, that will make three.

Started debugging a TC instruction, the simplest, in AGC2. Worked it through, step-

by-step, fixing logic and interface errors. Finally, it works. Debugging the remaining

8 basic instructions.

Massive snowstorm; snowed in, 3 days straight. Lots of time for AGC2 debugging and

testing.

I estimate my power budget and order a 15A 5V supply. More ICs and sockets are

ordered, too.

Sick of hand-assembling test code for AGC2. Wrote a version of the cross-assembler

that produces object code for AGC2. Broke TECO1 into 8 parts; one for each

instruction. One-by-one, I get all portions of TECO1 to run on AGC2.

Broke TECO2 and TECO3 into pieces and got them to run on AGC2 also.

INTEGRATION TESTING IS DONE!

How to build it? There are too many subsystems and interfaces.

Page 18: Apollo Guidance Computer AGC

June - August 2003

Grouped the 20 subsystems into 4 “assemblies” (soon to be called “modules”): I/O,

CTL, PROC, and MEM. This is more manageable.

Wrote C++ code that checks the netlists produced by CircuitMaker for fan-out.

Established a limit of 8 TTL loads, and added buffers where necessary. Added buffers

between the 4 modules to make the fan-in for each module/module interface 1 TTL

load.

Stuffed IC sockets into 13 circuit boards; each board is 13"x5". What connectors and

cables to use between boards? Between modules? Should I worry about bus

termination? What kind of chassis?

Decided to build each module as a small relay rack. Board-to-board connections

inside each module are wire-wrapped--no connectors. Between modules, 40-pin IDE

cables, mating to 30-pin wire-wrap connectors, are for module/module interfaces.

Too lazy to pull 500 IC sockets and redo the boards. I’ll work in connectors and

additional buffers where I can. Better buy the longest IDE cables (3 feet). More worry

about bus termination.

Module/Module interfaces are now defined: 6 IDE cables.

Built a rack for the I/O module out of 1x2 pine boards. Spray-painted gray; it looks

pretty good. Hired my engineering student son to wire-wrap some I/O module logic

during summer vacation. He wires most of the DSKY. It lights up and multiplexes,

but operation is erratic; set aside for now.

September - December 2003:

Built control panels for PROC, CTL, and MEM modules by mounting switches on a

wooden frame. Used thick styrene plastic for a faceplate, hand-lettered with indelible

marker. It doesn’t look too bad.

Built indicator light panels for PROC, CTL, and MEM by punching holes in styrene

plastic with a push-pin and then shoving LEDs through the plastic into the PCB.

Hundreds of LEDs; my thumb has a blister.

Built 3 more relay racks for the PROC, CTL, and MEM modules. Laid all the boards out

on the racks. Will the IDE cables reach? Yes, but in some cases, barely.

Bought an EPROM programmer. Learned Motorola S-format. Wrote yet another

version of the cross-assembler that outputs S-Record (s2f) format object code.

Burned EPROMs with TECO1, TECO2, TECO3, and the AGC flight software.

Modified the C++ simulator (AGC1) so it dumps its microinstructions (subsystem

CPM-A) in Motorola S-format. Burned EPROMS for CPM-A. Created a special version

of AGC1 that reads CPM-A S-format microinstructions to verify the tables and reads

AGC object code in S-format to verify the cross-assembler.

January - April 2004

Powered up, and started debugging the partly completed I/O module. Corrected a

design error and a few minor wiring errors; cleaned up some cold-solder joints. It

now works reliably. Finished wiring the I/O module. It’s difficult to test, but it seems

to work.

Page 19: Apollo Guidance Computer AGC

May - September 2004

Wired the power connections for all sockets on the CTL module; added a bypassing

capacitor for every 2 packages, and a 10uf tantalum capacitor for each row of ICs.

Wired the LED lamps and drivers, and then the logic for each subsystem. Plugged all

the CTL chips into the sockets.

Discovered all control signals from CPM-A were inverted: the EPROM tables were

generated from AGC1, which uses positive logic. The hardware AGC uses negative

logic, because TTL inputs float high; I wanted floating inputs to assume the inactive

state during assembly and test. Pried the EPROMs out of their sockets, bit-flipped the

tables, erased and reprogrammed the chips, and reinserted them. Now it works.

Completed wiring for the other modules. Now to hook them up.

September - October 2004

Built a large rack to hold the 4 modules. Screwed the 4 modules into the rack and

hooked up the IDE cables. Powered it on. Everything lights up. No smoke. Amazing!

It runs part of TECO1, getting through dozens of instructions including subroutine

calls, before bombing out.

Trying to debug the AGC by burning test EPROMs, single-stepping the clock, and

comparing the results to the AGC1 C++ simulator. It’s acting flaky. Could it be a

supply problem?

Tore out my flimsy power distribution; replaced it with heavy aluminum bus bars.

Supply lines look cleaner on the scope, but the operation is just as flaky as before.

Maybe worse. It’s bombing out in d ifferent places. Is there some common element?

Common element: the problem always involves read bus microinstructions. The ALU

sets a default state on the read bus if no other subsystem is using it. My bus

arbitration scheme stinks: if a read signal is asserted, the ALU disables its default

state, but propagation delays cause both drivers to enable simultaneously for a brief

period. Is this the problem?

I kludge-in logic to disable the read bus during CLK1. This gives the read bus logic

time to settle. I add propagation delay to the CLK1 input to TPG so the bus is

disabled before the TPG state transition occurs. Will this fix the problem?

No. It gets farther along, but still bombs out on read bus operations. It’s time to

download internet advice on bus termination. I add 220/330 ohm passive

termination to the read bus input in the ALU. IT WORKS!! TECO1 and TECO3 run

flawlessly.

TECO2 bombs out while testing the DV (divide) instruction. It produces different

results than the AGC1 simulator in the tests that involve division by zero. Do I care?

I decide I don’t.

I load the COLOSSUS EPROMs. The AGC flight software hangs at first; but I add

some passive termination to the “busy” bus driver (for the read bus, of course) and

then it works flawlessly too. The project is finished (except, I have to write up these

reports!)

Page 20: Apollo Guidance Computer AGC

AGC Block I Diagram

I constructed this diagram in the first months of my project. It shows the AGC subsystems

as boxes. I gave them three-letter names. My diagram is derived from a sim ilar block II

diagram I found in R-700.

I used this diagram to

organize my simulator and

logic designs. But, when it

became time to build the

AGC, I felt this diagram

had too many interfaces;

too much complexity.

To simplify things, I

grouped the subsystems

from this diagram into 4

modules.

The KBD, INP, OUT, and

DSP subsystems were

external interfaces, so I

grouped them into an IO

module. I’ll tell you about

it in part 5 of this report.

The ADR, MEM, MBF, and

PAR subsystems dealt with

memory, so they went into

a MEM module (described

in part 4).

The MON, CLK, SCL, TPG, SEQ, and CPM subsystems generated the timing and control

pulses that run all the other subsystems, so I gathered them into a CTL (control) module (in

part 2).

What remained? The ALU, CRG, INT, and CTR subsystems. I put them in a PROC

(processing) module (part 3).

Page 21: Apollo Guidance Computer AGC

How my AGC differs from the original

For my purposes, the original AGC is described in a M.I.T. document called R-393 (A.

Hopkins, R. Alonso, and H. Blair-Smith, "Logical Description for the Apollo Guidance

Computer (AGC4)", R-393, MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963).

Logic DesignThe original AGC4 was built almost entirely from 1964-era 3-input NOR gate ICs; about

5,000 of them. Original gate-level logic designs are not available.

Logic for my replica was recreated using specifications in R-393, and architecture

information/diagrams from R-700. Since R-393 defines (in detail) AGC registers, register

transfers, microinstructions, and most control pulses (logic signals), the architecture of my

replica closely mirrors the original to a low level.

The logic design for my replica uses late 1960's-early 1970's 74LS TTL logic, which affords

about a 10-to-1 reduction in package count. Flip-flop and register chips are used instead of

constructing each element from NOR gates.

The replica successfully runs those portions of the original COLOSSUS flight software that

have been loaded onto it.

ClockThe original AGC4 divided its 2.048 MHz clock down into 4-phase 1.024 MHz signals to drive

asynchronous, level-triggered, register logic.

My replica divides the 2.048 MHz clock into a 2 phased, non-overlapping 1.024 MHz clock to

drive synchronous, edge-triggered register logic. Phase 1 of the clock (CLK1) steps a

sequencer (TPG), which sets up the control signals. Those signals have time to propagate

(settle) between phase 1 and phase 2. Phase 2 (CLK2) clocks the registers using the control

signals established in phase 1. Data transfer occurs at phase 2.

Timing Pulses and Control StatesThe original AGC4 operation was controlled by 12 non-overlapping timing pulses (TP1 -

TP12) generated from a 4-bit gray code counter. Two SR FFs (called R1 and R2) were used

to generate 3 states to control standby operation (STANDBY, POWERON, RUN). R-393

identifies a start/stop logic subsystem which gates the time pulse generator to run and halt

AGC4 for ground test purposes but the internals were not defined.

My control states are integrated into one state machine with 16 states. The 12 timing pulses

(TP1 - TP12) are implemented as states along with 2 additional states for standby operation

(STBY, PWRON). The remaining 2 states (RLSE, WAIT) handle front panel switch inputs for

single stepping.

Interpolation of Gaps in Control LogicR-393 defines control pulses for TP1-TP11, but does not define control pulses for TP12.

Interfaces between interrupts, involuntary counters, and the main control logic are not well

defined. For this reason, logic in the gaps in R-393 had to be interpolated, based upon

functional requirements.

Number and Address of Involuntary CountersThe number of involuntary counters and their address range is ambiguously defined in R-

Page 22: Apollo Guidance Computer AGC

393. Table 1-1 in R-393 says AGC4 has 20 (base 10, I assume) counters. This is supported

by Figure 2-5 which numbers counters from 1-20. However, Table 3-1 which shows AGC

special registers assigns the counters to addresses 0030 through 0056 (base 8) which

translates to 23 (base 10) counters. And Table 5-1, section D gives the counter addresses

from 0034 for OVCTR through 0056 for TRKR R, which translates to 19 (base 10) counters.

So, its unclear whether AGC4 had 19, 20, or 23 counters and whether the counter addresses

start at 0030 or 0034.

To resolve the ambiguity, I set the starting address for the counters to 34 (octal), which is

the starting address used in the Block II AGC (COLOSSUS program listing). For convenience,

I only implemented counters that were used by the AGC EXEC and WAITLIST, the real-time

clock, and the overflow (5 in all). These are:

address counter

34 OVCTR

35 TIME2

36 TIME1

37 TIME3

40 TIME4

I also used the Block II ordering of TIME1 and TIME2, for compatibility with the COLOSSUS

flight software. In the AGC4, TIME1 is at the lower address.

Address of Interrupt Vectors and GOPROGIn the Block II AGC, GOPROG (the starting address for execution) is at the bottom of fixed

memory at address 4000, and the interrupt vectors follow at 4004, 4010, 4014, etc. By

extension, it would seem that the Block I AGC GOPROG would be at the bottom of fixed

memory at 2000, followed by interrupt vectors at 2004, 2010, 2014, etc. However, R-393

has the interrupt vectors starting at the bottom of fixed memory at 2000 (according to the

RUPT3 sequence on pages 3-67/3-68). R-393 doesn’t identify the address for the Block I

GOPROG.

For compatibility with the COLOSSUS source code (which I translated and cross-assembled

for Block I), I set GOPROG to 2000, with the interrupt vectors beginning at 2004.

Number of InterruptsThe original AGC had 5 vectored interrupts: UPRUPT, ERUPT, KEYRUPT, T3RUPT, and

DSRUPT. UPRUPT was used for uplinked commands; ERUPT was generated when hardware

errors were detected. Since I didn’t plan to use these interrupts, I eliminated the hardware

that supports them from my replica.

My replica implements the remaining 3 interrupts: KEYRUPT, T3RUPT, and DSRUPT

(T4RUPT).

Priority Counter sequencesThe original AGC4 implemented 3 sequences: PINC, MINC, and SHINC. PINC increments

counter locations in memory; MINC decrements them. SHINC implements a shift operation

used to shift telemetry bits into the AGC. After 16 bits were shifted into an AGC word, an

interrupt UPRUPT was triggered, so the AGC could pull the telemetry word out of the

counter.

Since I’m not receiving telemetry, I didn’t implement the SHINC subsequence or the UPRUPT

interrupt.

Page 23: Apollo Guidance Computer AGC

MemoryAGC memory is 16-bit words, organized into 1024 word banks. The lowest bank (bank 0) is

erasable memory, originally core, but implemented in my replica as static RAM. All banks

above bank 0 are fixed memory (originally implemented as rope core, but implemented in

my replica as EPROM). AGC4 initially had 12K words of fixed memory. My replica has 15K.

BusesThe original AGC OR’ed everything onto the bus, and the default bus state was logical zero:

Registers were sometimes cleared by reading the default state off the bus. Other times,

several registers were simultaneously read to OR the data. Because these tricks won’t work

well w ith tri-state bus drivers, I identified these instances and added logic to the ALU to

handle them.

Flight SoftwareThe original Block I flight software is not available (at least, to me). The Block II software

(COLOSSUS 249) is available. Block II is an extension of the Block I instruction set.

However, most of the Block II software was originally coded as Block I, so translating the

Block II code back to Block I only involves changing about 5% of the instructions back to

their Block I equivalents. This is what I did.

Back in 2002, only a portion of the COLOSSUS Block II code was available. Some key

portions, such as the EXEC and WAITLIST, were missing. I coded these parts in, using

information from the M.I.T. documents and the interfaces and functional requirements

implied by their use in the portions of COLOSSUS that were available.

Page 24: Apollo Guidance Computer AGC

Sources

Many of these sources are now (2004) available (free!) online at

http://hrst.mit.edu/hrs/apollo/public/

R. Alonso, J. H. Laning, Jr. and H. Blair-Smith, "Preliminary MOD 3C Programmer's Manual",

E-1077, MIT Instrumentation Laboratory, Cambridge, MA, Nov. 1961.

Useful information on AGC4's predecessor: AGC3. AGC3 had fewer instructions (8 vs.

11) and a shorter instruction cycle (8 vs 12 timing pulses). It is primarily helpful for

its presentation of AGC Block I programming techniques and examples.

A. I. Green and J. J. Rocchio, "Keyboard and Display System Program for AGC (Program

Sunrise)", E-1574, MIT Instrumentation Laboratory, Cambridge, MA, Aug. 1964.

Flowcharts for DSKY software; no source code. Gives input codes for the DSKY

keyboard and the output codes for display characters and registers.

E. C. Hall, "Journey to the Moon: The History of the Apollo Guidance Computer", AIAA,

Reston VA, 1996.

Nice information on the AGC development history with photos; R-700 (also by E.C.

Hall) is a better technical summary.

E. C. Hall, "MIT's Role in Project Apollo, Volume III, Computer Subsystem", R-700, MIT

Charles Stark Draper Laboratory, Cambridge, MA, Aug. 1972.

An excellent overview of the AGC; more technical than Hall's "Journey to the Moon"

book. It contains an excellent diagram of the Block II register architecture and a nice

diagram of a bit-slice of the register/bus logic. My copy from NTIS is somewhat poor

quality. There is also a useful discussion of the AGC test and checkout software.

A. Hopkins, "Guidance Computer Design, Part VI"

Extracted from some (unknown) larger document. An excellent overview of the Block

II AGC with emphasis on the I/O circuits. A very useful discussion of number

representation and overflow handling in the AGC, which is unconventional.

A. Hopkins, R. Alonso, and H. Blair-Smith, "Logical Description for the Apollo Guidance

Computer (AGC4)", R-393, MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963.

My primary source. It has a nearly complete specification of the AGC4 (Block I)

instruction set, register transfers, and control pulses. Information on the logic design

is largely absent, however. There are some internal inconsistencies and gaps in the

definition of the control logic: particularly at TP12, in the memory cycle, and at the

intersection of the control logic with the interrupts and involuntary counters.

Unfortunately, there are few diagrams; its mostly text and tables. There are also

some examples of double-precision math routines.

B. I. Savage and A. Drake, "AGC4 Basic Train ing Manual, Volume I", E-2052, MIT

Instrumentation Laboratory, Cambridge, MA, Jan. 1967.

The software manual for the Block II AGC. It has a fairly complete presentation of the

instruction set, but lacks example code.

Page 25: Apollo Guidance Computer AGC

Now, what?

There’s 8 more parts to this report. Download and read the parts you’re interested in.

Perhaps you want to build your own AGC. You can use my software and logic designs, or

develop your own. There’s lots of room for improvement in my work. You could use it as

your starting point.

If you like, you can contact me at: [email protected]

Page 26: Apollo Guidance Computer AGC

Block IApollo Guidance Computer (AGC)

How to build one in your basement

Part 2: Control (CTL) Module

John Pultorak

December, 2004

Page 27: Apollo Guidance Computer AGC

Abstract

This report describes my successful project to build a working reproduction of the 1964

prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the

Apollo moon landings, and is the world’s first integrated circuit computer.

I built it in my basement. It took me 4 years.

If you like, you can build one too. It will take you less time, and yours will be better than

mine.

I documented my project in 9 separate .pdf files:

Part 1 Overview: Introduces the project.

Part 2 CTL Module: Design and construction of the control module.

Part 3 PROC Module: Design and construction of the processing (CPU) module.

Part 4 MEM Module: Design and construction of the memory module.

Part 5 IO Module: Design and construction of the display/keyboard (DSKY) module.

Part 6 Assembler: A cross-assembler for AGC software development.

Part 7 C++ Simulator: A low-level simulator that runs assembled AGC code.

Part 8 Flight Software: My translation of portions of the COLOSSUS 249 flight

software.

Part 9 Test & Checkout: A suite of test programs in AGC assembly language.

Page 28: Apollo Guidance Computer AGC

Overview

The Control Module (CTL) has 9 subsystems: CMI, MON, CLK, SCL, TPG, SEQ, CPM-A,

CPM-B, CPM-C

CMI (Control Module external

Interface)

The CMI interfaces the other control

module subsystems (described below)

to external AGC modules. 40-pin IDE

connectors interface to the PROC,

MEM, and IO modules. Inputs from

those modules are buffered to 1 LSTTL

load.

MON (AGC Monitor)

The monitor subsystem has the

front-panel switches that control AGC

operation, and also implements the

power-up reset circuit.

CLK (Clock)

The AGC is controlled by a 2.048 MHz

crystal clock. The clock is divided to

produce a 2-phase, non-overlapping

1.024 MHz AGC system clock for

nominal operation. For test purposes,

a low-frequency RC clock can also be

selected, or the clock can be

single-stepped.

SCL (Scaler)

The 1.024 MHz AGC clock is divided by

two to produce a 512 kHz signal called

the MASTER FREQUENCY; this signal

is further divided through a SCALER,

first by five to produce a 102.4 kHz

signal. This is then divided by two

through 17 successive stages called F1

(51.2 kHz) through F17 (0.78125 Hz).

The F10 stage (100 Hz) is fed back into the AGC to increment the real-time clock and other

priority counters in the PROC module. The F17 stage is used to intermittently run the AGC

when it operates in the STANDBY mode.

TPG (Time Pulse Generator)

AGC instructions are implemented in groups of 12 steps, called timing pulses. The timing

pulses, named TP1 through TP12, are produced by the Time Pulse Generator (TPG). Each set

of 12 timing pulses is called an instruction subsequence. Simple instructions, such as TC,

execute in a single subsequence of 12 pulses. More complex instructions require several

subsequences.

SEQ (Sequence Generator)

The sequence generator has the SQ register, which holds the next op-code, and the CTR

Page 29: Apollo Guidance Computer AGC

register--a counter used to count instruction subsequences during multiplication. The

sequence generator also has the branch register (BR) which controls conditional processing

during instruction execution, and the STAGE registers (STA and STB) which select the

instruction subsequences for complex instructions that have more than one subsequence.

CPM-A (Control

Pulse Matrix A)

The CPM-A is the

combinational logic

matrix that

implements most

of the control logic.

It is driven by

inputs from the SQ

register (which

selects the

instruction), the

STB stage register

(which selects the

instruction

subsequence), and

the BR branch

register (which

selects conditional

steps in a

subsequence).

CPM-B (Control

Pulse Matrix B)

The CPM-B

decodes read and

write control

signals for special

memory location associated with input/output registers, central registers (A, Q, Z, and LP),

and the editing registers used for rotation and shifting.

CPM-C (Control Pulse Matrix C)

The CPM-C decodes control signals primarily associated with interrupts, the memory cycle,

and the selection of new instructions and instruction subsequences.

Page 30: Apollo Guidance Computer AGC

This is a functional diagram showing the interrelationships between the Time Pulse

Generator (TPG), the Control Pulse Matrix (CPM-A, B, and C), and the registers that are in

the Sequence

Generator (SEQ).

The diagram is

mine, but the style

is borrowed from

original AGC

documentation:

control signals are

represented by

diamonds. The

arrows show the

direction of data

flow. When a control

signal is asserted,

data is allowed to

flow through the

diamond. For

example, when WSQ

is asserted, the

opcode is written

from the Read/Write

bus into the SQ

register.

Registers (LOOPCTR, STA, STB, SQ, BR, and SNI) are represented by rectangles. The lower

bit of the 2-bit STA register is set by ST1. The upper bit is set by any one of the 3 control

signals flowing into it. The STA register is cleared by CLRSTA.

When WSTB is asserted, the STA register is copied to STB. STB and the SQ register select

the instruction subsequence.

The instruction subsequence, time pulse generator, BR register, and SNI all feed into the

Control Pulse Matrix to select the active control pulses.

The diagram was developed by analyzing the R-393 document. It was one of my first

diagrams; a sort-of conceptual breakthrough that became my gateway for understanding

the AGC control module.

Page 31: Apollo Guidance Computer AGC

The instruction

subsequences

executed by the

AGC are shown

in this diagram.

Each yellow

circle is a

subsequence; a

set of 12 steps,

with each step

generating 0-5

control pulses.

Eleven steps

(TP1-TP11) are

in the yellow

circle; the 12th

step, which

selects the next

subsequence

(TP12), is in the

orange circle.

This is discussed

in more detail in

the TPG, SEQ,

and CPM-A

subsystems.

Page 32: Apollo Guidance Computer AGC

A late addition to the CTL design fixed a problem with the read bus logic. Due to

propagation delays (and some poor design on my part), the tri-state buffers from multiple

registers were simultaneously enabled for brief periods causing some transients. I “kludged”

in a design change that suppressed output to the read bus during CLK1, thereby giving the

bus control logic time to settle.

Page 33: Apollo Guidance Computer AGC

CTL Internal Subsystem Interconnections

This diagram shows internal interconnections for the subsystems in the CTL module.

Page 34: Apollo Guidance Computer AGC
Page 35: Apollo Guidance Computer AGC

CTL Module External Interfaces

The CTL module interfaces to the PROC, MEM, and IO modules through 40-pin IDE ribbon

cables.

Page 36: Apollo Guidance Computer AGC

J100-CTL: CTL-to-PROC I/F

J100 is a 40-pin IDE ribbon cable that connects the CTL module to the PROC module.

OUTPUTS (from CTL):

PIN signal full name state definition

1 WA3 WRITE ADDR 3 (74) 0=Write reg at address 3 (LP)

2 WA2 WRITE ADDR 2 (73) 0=Write reg at address 2 (Z)

3 WA1 WRITE ADDR 1 (72) 0=Write reg at address 1 (Q)

4 WA0 WRITE ADDR 0 (71) 0=Write reg at address 0 (A)

5 RA3 READ ADDR 3 (60) 0=Read reg at address 3 (LP)

6 RA2 READ ADDR 2 (59) 0=Read reg at address 2 (Z)

7 RA1 READ ADDR 1 (58) 0=Read reg at address 1 (Q)

8 RA0 READ ADDR 0 (57) 0=Read reg at address 0 (A)

9 WZ WRITE Z (50) 0=Write Z

10 WYx WRITE Y NO RESET (49) 0=Write Y (do not reset)

11 WY WRITE Y (48) 0=Write Y

12 WX WRITE X (47) 0=Write X

13 WQ WRITE Q (45) 0=Write Q

14 WOVR WRITE OVF (41) 0=Write overflow

15 WOVI WRITE OVF RUPT INH (40) 0=Write overflow RUPT inh ibit

16 WOVC WRITE OVF CNTR (39) 0=Write overflow counter

17 WLP WRITE LP (38) 0=Write LP

18 WB WRITE B (36) 0=Write B

19 WALP WRITE A/LP (35) 0=Write A and LP

20 WA WRITE A (34) 0=Write A

21 F10X F10 SCALER ONESHOT 1=timed out (100.0 Hz)

23 R24 READ 24 (25) 0=Read 24

24 R22 READ 22 (24) 0=Read 22

25 R2 READ 2 (23) 0=Read 2

26 R1C READ 1 COMP (22) 0=Read 1 complimented

27 R1 READ 1 (21) 0=Read 1

28 RZ READ Z (20) 0=Read Z

29 RU READ U (19) 0=Read sum

30 RSCT READ CNTR ADDR (18) 0=Read selected counter address

31 RSB READ SIGN (17) 0=Read sign bit

32 RRPA READ RUPT ADDR (16) 0=Read RUPT address

33 RQ READ Q (15) 0=Read Q

34 RLP READ LP (13) 0=Read LP

35 RC READ C (11) 0=Read C

36 RB14 READ BIT 14 (10) 0=Read bit 14

37 RB READ B (9) 0=Read B

38 RA READ A (8) 0=Read A

39 KRPT KNOCK DOWN RUPT (6) 0=Knock down Rupt priority

40 CI SET CARRY IN (1) 0=Carry in

Page 37: Apollo Guidance Computer AGC

J101-CTL: CTL-to-PROC I/F

J101 is a 40-pin IDE ribbon cable that connects the CTL module to the PROC module.

INPUTS (to CTL):

PIN signal full name state definition

21 SB_01 SUB SEL 01 SB_01 is LSB; SB_02 is MSB

22 SB_02 SUB SEL 02 00=no counter; 01=PINC; 10=MINC

23 IRQ INT RQST 0=interrupt requested.

25 WB_01 WRITE BUS 01 (lsb)

26 WB_02 WRITE BUS 02

27 WB_03 WRITE BUS 03

28 WB_04 WRITE BUS 04

29 WB_05 WRITE BUS 05

30 WB_06 WRITE BUS 06

31 WB_07 WRITE BUS 07

32 WB_08 WRITE BUS 08

33 WB_09 WRITE BUS 09

34 WB_10 WRITE BUS 10

35 WB_11 WRITE BUS 11

36 WB_12 WRITE BUS 12

37 WB_13 WRITE BUS 13

38 WB_14 WRITE BUS 14

39 WB_15 WRITE BUS 15 US (overflow) bit

40 WB_16 WRITE BUS 16 SG (sign) bit

OUTPUTS (from CTL):

PIN signal full name state definition

1 R2000 READ 2000 (101) 0=Read 2000

2 WPCTR WRITE PCTR (98) 0=Write PCTR (latch priority counter

sequence)

3 RPT READ RUPT (94) 0=Read RUPT opcode

4 INH SET INHINT (93) 0=Set INHINT

5 CLRP CLEAR RPCELL (92) 0=Clear RPCELL

6 CLINH1 CLEAR INHINT1 (88) 0=Clear INHINT1

7 CLINH CLEAR INHINT (87) 0=Clear INHINT

8 GENRST GENERAL RESET (86) 0=General Reset

19 CLK1 CLOCK1 1.024 MHz AGC clock 1 (normally low)

20 CLK2 CLOCK2 1.024 MHz AGC clock 2 (normally low)

Page 38: Apollo Guidance Computer AGC

J102-CTL: CTL-to-MEM I/F

J102 is a 40-pin IDE ribbon cable that connects the CTL module to the MEM module.

INPUTS (to CTL):

PIN signal full name state definition

31 EQU_16 ADDRESS = 016 (1) 0=CADR in register S = 016

32 EQU_17 ADDRESS = 017 (2) 0=CADR in register S = 017

33 GTR_17 ADDRESS > 017 (3) 0=CADR in register S > 017

34 EQU_25 ADDRESS = 025 (4) 0=CADR in register S = 025

35 GTR_27 ADDRESS > 027 (5) 0=CADR in register S > 027

36 GTR_1777 ADDRESS > 01777 (6) 0=CADR in register S > 01777

37 AD_1 ADDRESS (1) where AD_4 is MSB, AD_1 is LSB:

38 AD_2 ADDRESS (2) (low-order bits of address)

38 AD_3 ADDRESS (3)

40 AD_4 ADDRESS (4)

OUTPUTS (from CTL):

PIN signal full name state definition

1 WE WRITE EMEM (97) 0=Write E-MEM from G

2 SBWG WRITE G (95) 0=Write G from memory

3 GENRST GENERAL RESET (86) 0=General Reset

4 W23 WRITE ADDR 23 (85) 0=Write into SL

5 W22 WRITE ADDR 22 (84) 0=Write into CYL

6 W21 WRITE ADDR 21 (83) 0=Write into SR

7 W20 WRITE ADDR 20 (82) 0=Write into CYR

8 WGn WRITE G NORMAL (81) 0=Write G (normal gates)

9 WBK WRITE BNK (80) 0=Write BNK reg

10 RBK READ BNK (70) 0=Read BNK reg

11 WS WRITE S (46) 0=Write S

12 WP2 WRITE P2 (44) 0=Write P2

13 WPx WRITE P NO RESET (43) 0=Write P (do not reset)

14 WP WRITE P (42) 0=Write P

15 WGx WRITE G NO RESET (37) 0=Write G (do not reset)

16 TP TEST PARITY (30) 0=Test parity

17 RP2 READ PARITY 2 (14) 0=Read parity 2

18 RG READ G (12) 0=Read G

19 GP GEN PARITY (5) 0=Generate Parity

20 CLG CLR G (2) 0=Clear G

21 CLK2 CLOCK2 1.024 MHz AGC clock 2 (normally low)

22 CLK1 CLOCK1 1.024 MHz AGC clock 1 (normally low)

23 NPURST POWER UP RESET 0=reset, 1=normal operation.

24 SWCLK DEBOUNCE CLOCK low freq clk for switch debounce

25 FCLK CLOCK MODE 1=free-running clk mode; 0=single clk

mode

Page 39: Apollo Guidance Computer AGC

J103-CTL: CTL-to-I/O I/F

J100 is a 40-pin IDE ribbon cable that connects the CTL module to the I/O module.

INPUTS (to CTL):

PIN signal full name state definition

40 OUT1_8 STANDBY ENABLED 1=standby enabled; works with STANDBY

ALLOWED switch

OUTPUTS (from CTL):

PIN signal full name state definition

1 CLK1 CLOCK1 1.024 MHz AGC clock 1 (normally low)

2 CLK2 CLOCK2 1.024 MHz AGC clock 2 (normally low)

3 NSA STANDBY ALLOWED 0=standby allowed

5 GENRST GENERAL RESET (86) 0=clear the DSKY, OUT1, and OUT2.

6 WA11 WRITE OUT1 (76) 0=write into OUT1 from write bus

7 WA10 WRITE OUT0 (75) 0=write into OUT0 (DSKY) from write bus

8 RA11 READ OUT1 (66) 0=output OUT1 register to read bus

9 RA4 READ IN0 (61) 0=output IN0 register to read bus

20 STBY STANDBY 0=AGC is in the standby state

Page 40: Apollo Guidance Computer AGC
Page 41: Apollo Guidance Computer AGC
Page 42: Apollo Guidance Computer AGC
Page 43: Apollo Guidance Computer AGC

MON (AGC Monitor)

MON INPUTS:

I/F signal full name state definition

SW-RUN RUN/STEP SELECT SW

NSW-RUN

SW-INS STEP MODE SW

NSW-INS

SW-FCL CLOCK MODE SW

NSW-FCL

SW-SA STANDBY ALLOWED SW

NSW-SA

SW-STP INST STEP SW

NSW-STP

SW-MCL CLOCK STEP SW

NSW-MCL

SW-RST MASTER RESET SW

MON OUTPUTS:

signal full name state definition

NRUN RUN/HALT 0=run, 1=step

INST INST STEP MODE 1=instruction step, 0=sequence step

NSTEP SINGLE STEP 0=step (momentary)

NSA STANDBY ALLOWED 0=standby allowed

MCLK CLOCK STEP 1=step (momentary); triggers a single

clock pulse. Ignored if FCLK is 1.

FCLK CLOCK MODE 1=continuous clock output at 1.024 MHz,

0=single clock

NPURST POWER UP RESET 0=reset, 1=normal operation.

SENAB SCALER ENABLE 1=enable counting; 0=hold

Page 44: Apollo Guidance Computer AGC

CTL CONTROL PANEL SWITCHES

Clock Control:

RATE Controls the slow clock rate when the 1MHZ/SLOW switch is in the SLOW

position.

1MHZ/SLOW Selects the free-running clock rate when the RUN/STEP switch is in the RUN

position. The 1MHZ position gates a 2MHz signal into the 2-phased clock

which produces a 1MHz 2-phased clock rate. The SLOW position gates a low

frequency clock; the frequency is controlled by RATE.

RUN/STEP Selects a free-running (RUN) or a single-stepped (STEP) clock. In the RUN

position, the rate is controlled by the 1MHZ/SLOW switch. In the STEP

position, the clock steps each time the STEP button is depressed.

STEP Manually steps the clock when the RUN/STEP switch is in the STEP position.

The clock is 2-phased, so each press steps an alternate phase.

Scaler:

ENAB/DISAB Enables or disables the SCALER.

F10 Manually triggers the F10 stage of the SCALER.

F13 Manually triggers the F13 stage of the SCALER.

F17 Manually triggers the F17 stage of the SCALER.

Page 45: Apollo Guidance Computer AGC

Execution Control:

RUN/STEP In the RUN position, the AGC free-runs at a rate determined by the clock

controls. In the STEP position, the AGC single-steps to the next instruction or

next sequence when the STEP button is depressed; the rate is determined by

the clock controls.

INST/SEQ Selects whether the AGC single-steps all the way to the next instruction

(INST) or just to the next sequence (SEQ). Some instructions, such as TC,

have a single sequence; on these instructions, the switch has the same effect

in either position.

STEP Single-steps the AGC when the RUN/STEP switch is in the STEP position.

RESET Reset the entire AGC. Puts the TPG into the standby state.

Standby:

ALLOW/DISA The ALLOWED position authorizes the AGC software to put the AGC in standby

mode. The AGC is released from standby mode by a signal from F17 in the

SCALER. If the scaler switch is in the DISAB position, the scaler is disabled,

and the AGC will remain in the standby state. When the standby switch is in

the DISAB position, the standby mode is inhibited.

Normal Operation:

Set the following switch positions for nominal operation:

switch position

1MHZ/SLOW 1MHZ

RUN/STEP RUN (clock control)

ENAB/DISAB ENAB (scaler)

RUN/STEP RUN (execution control)

ALLOW/DISA ALLOWED (standby)

Page 46: Apollo Guidance Computer AGC

CTL CONTROL SWITCH CONNECTIONS

PIN signal state definition

1 BUS#10, line 1 Execution control: RUN/STEP

2 BUS#10, line 2

3 BUS#10, line 3 Execution control: INST/SEQ

4 BUS#10, line 4

5 BUS#10, line 5 Clock control: RUN/STEP

6 BUS#10, line 6

7 BUS#10, line 7 STANDBY ALLOWED/DISABLED

8 BUS#10, line 8

9 BUS#10, line 9 Execution control: STEP

10 BUS#10, line 10

11 BUS#10, line 11 Clock control: STEP

12 BUS#10, line 12

13 BUS#10, line 13 RESET

14 BUS#10, line 14 SCALER DISAB

15 RATE (SLOW) CLOCK CONTROL RATE

16 1MHZ Clock control: 1MHZ/SLOW

17 SLOW

18 F10 MANUAL TRIGGER F10

19 F13 MANUAL TRIGGER F13

20 F17 MANUAL TRIGGER F17

Page 47: Apollo Guidance Computer AGC
Page 48: Apollo Guidance Computer AGC
Page 49: Apollo Guidance Computer AGC
Page 50: Apollo Guidance Computer AGC

CTL INDICATORS

The CTL module has a panel of indicator lamps (LEDs) to show the state of CTL registers and

critical logic signals.

These indicator

lamps show the

current state of all

registers and some

additional,

important logic

signals produced by

the CTL module.

The matrix of lamps

in the lower portion

show active

subsequences. Much

of the control logic

is negative (active

low) where an

illuminated lamp

means that the

signal is NOT

asserted. At the

time the photo was

taken the AGC was

running

the COLOSSUS 249

flight software load, executing Verb 16, Noun 36: a monitor verb which displays the AGC

real time clock.

Page 51: Apollo Guidance Computer AGC
Page 52: Apollo Guidance Computer AGC
Page 53: Apollo Guidance Computer AGC
Page 54: Apollo Guidance Computer AGC

CLK (Clock)

The original AGC used asynchronous logic driven by a 4-phase clock. This recreation uses

synchronous logic driven by a 2-phase non-

overlapping clock. The synchronous clock logic

was designed to produce the follow ing state

transitions:

FFA FFB

0 0 idle state

0 1 decoded for phase 1

1 1

1 0 decoded for phase 2

The outputs of FFA and FFB are decoded by

combinational logic to produce the non-

overlapping phase 1 and phase 2 clock signals.

The sequence is arranged so there is a single

logic level transition for each state transition to

prevent transients.

Page 55: Apollo Guidance Computer AGC

CLK INPUTS:

I/F signal full name state definition

MON:

MCLK CLOCK STEP 1=step (momentary); triggers a single

clock pulse. Ignored if FCLK is 1.

FCLK CLOCK MODE 1=continuous clock output at 1.024 MHz,

0=single clock whenever MCLK is 1.

NPURST POWER UP RESET 0=power up reset

OUTPUTS:

signal full name state definition

CLK1 CLOCK1 1.024 MHz AGC clock 1 (normally low)

CLK2 CLOCK2 1.024 MHz AGC clock 2 (normally low)

Page 56: Apollo Guidance Computer AGC
Page 57: Apollo Guidance Computer AGC
Page 58: Apollo Guidance Computer AGC

SCL (Scaler)

The 1.024 MHz AGC clock is

divided by two to produce a

512 kHz signal called the

MASTER FREQUENCY; this

signal is further divided

through a SCALER, first by

five to produce a 102.4 kHz

signal. This is then divided

by two through 17

successive stages called F1

(51.2 kHz) through F17

(0.78125 Hz). The F10 stage

(100 Hz) is fed back into the

AGC to increment the

real-time clock and other

priority counters in the PROC

module. The F17 stage is

used to intermittently run

the AGC when it operates in

the STANDBY mode.

The F10, F13, and F17

outputs of the SCALER feed

into a synchronous one-shot

that produces a short output

pulse on the rising edge of

the input.

Page 59: Apollo Guidance Computer AGC

SCALER (SCL) ONE-SHOT LOGIC DESIGN

Boolean operators:

* (AND), + (OR), ' (NOT)

Scaler Divide-by-10 Excitation Table:

The divide-by-10 state machine is implemented with a 74161 parallel counter. Control Mode

for 74161 Parallel Counter:

NPE CET

0 x LOAD

1 1 COUNT

1 0 HOLD

Current Next Par In

State D C B A D C B A NPE CET D C B A

0 0 0 0 0 0 0 0 1 1 1

1 0 0 0 1 0 0 1 0 1 1

2 0 0 1 0 0 0 1 1 1 1

3 0 0 1 1 0 1 0 0 1 1

4 0 1 0 0 0 1 0 1 1 1

5 0 1 0 1 0 1 1 0 1 1

6 0 1 1 0 0 1 1 1 1 1

7 0 1 1 1 1 0 0 0 1 1

8 1 0 0 0 1 0 0 1 1 1

9 1 0 0 1 0 0 0 0 0 x 0 0 0 0

NPE = (D * A)'

CET = 1

One-shot Excitation Table:

The one-shot state machine is implemented with two J-K FFs.

JK flip-flop excitation table:

J K

0 0 Qn-1 (no change)

0 1 0

1 0 1

1 1 Qn-1' (toggle)

FN is the one-shot trigger; Q(A) is the one-shot output.

Cur Inp Nxt ffB ffA

State B A FN B A J K J K

IDLE 0 0 0 0 0 0 x 0 x

0 0 1 0 1 0 x 1 x

Page 60: Apollo Guidance Computer AGC

HIGH 0 1 0 1 0 1 x x 1

0 1 1 1 0 1 x x 1

LOW 1 0 0 0 0 x 1 0 x

1 0 1 1 0 x 0 0 x

UNUSED 1 1 0 x x x x x x

1 1 1 x x x x x x

The excitation table and logic equations were derived from the CLK subsystem state

machine which also performs a one-shot function. The CLK subsystems's FCLK signal was

factored out by setting it to zero. The MCLK input is the one-shot trigger; it was renamed

FN.

ff(B) J = QA

ff(B) K = FN'

ff(A) J = QB' * FN

ff(A) K = QA

Page 61: Apollo Guidance Computer AGC

SCL INPUTS:

I/F signal full name state definition

CLK:

CLK1 CLOCK1 1.024 MHz AGC clock

MON:

SW-SEN SCALER ENABLE 1=enable counting;

0=hold

NPURST POWER UP RESET 0=power up reset

SCL OUTPUTS:signal full name state definition

F10X F10 SCALER ONESHOT 1=timed out (100.0 Hz)

F13X F13 SCALER ONESHOT 1=timed out ( 12.5 Hz)

F17X F17 SCALER ONESHOT 1=timed out ( 0.78125

Hz)

F1 SCALER OUT F1 51.2 KHz square wave

F2 SCALER OUT F2 25.6 KHz square wave

F3 SCALER OUT F3 12.8 KHz square wave

F4 SCALER OUT F4 6,4 KHz square wave

F5 SCALER OUT F5 3.2 KHz square wave

F6 SCALER OUT F6 1.6 KHz square wave

F7 SCALER OUT F7 0.8 KHz square wave

F8 SCALER OUT F8 0.4 KHz square wave

F9 SCALER OUT F9 0.2 KHz square wave

F10 SCALER OUT F10 0.1 KHz square wave (100 Hz)

F11 SCALER OUT F11 50.0 Hz square wave

F12 SCALER OUT F12 25.0 Hz square wave

F13 SCALER OUT F13 12.5 Hz square wave

F14 SCALER OUT F14 6.25 Hz square wave

F15 SCALER OUT F15 3.125 Hz square wave

F16 SCALER OUT F16 1.5625 Hz square wave

F17 SCALER OUT F17 0.78125 Hz square wave

Note: One shot outputs are active for one clock pulse.

State transitions occur on the rising edge of CLK1

Page 62: Apollo Guidance Computer AGC
Page 63: Apollo Guidance Computer AGC
Page 64: Apollo Guidance Computer AGC

TPG (Time Pulse Generator)

Page 65: Apollo Guidance Computer AGC

TIME PULSE GENERATOR (TPG) LOGIC DESIGN

Boolean operators:

* (AND), + (OR), ' (NOT)

TPG Internal Control Signals:

These are local to the TPG; if the signal is asserte

d, TPG makes a state transition. These decoded

signals are the inputs to the excitation table.

TPG_0 = PURST' * ( FCLK' + F17X )

TPG_1 = FCLK' + F13X

TPG_2 = RUN + (SNI' * INST)

TPG_3 = SNI * OUT1_8 * SA

TPG_4 = STEP'

TPG_5 = STEP + RUN

TPG Excitation Table:

Control Mode for 74161 Parallel Counter:

NPE CET

0 x LOAD

1 1 COUNT

1 0 HOLD

*denotes active low

Current *Current TPG_x Next Par In

State D C B A Decoder 0 1 2 3 4 5 D C B A *NPE CET D C B A

STBY 0 0 0 0 NSTBY 0 x x x x x 0 0 0 0 1 0

1 x x x x x 0 0 0 1 1 1

PWRON0 0 0 1 NPWRON x 0 x x x x 0 0 0 1 1 0

x 1 x x x x 0 0 1 0 1 1

TP1 0 0 1 0 NTP1 x x x x x x 0 0 1 1 1 1

TP2 0 0 1 1 NTP2 x x x x x x 0 1 0 0 1 1

TP3 0 1 0 0 NTP3 x x x x x x 0 1 0 1 1 1

TP4 0 1 0 1 NTP4 x x x x x x 0 1 1 0 1 1

TP5 0 1 1 0 NTP5 x x x x x x 0 1 1 1 1 1

TP6 0 1 1 1 NTP6 x x x x x x 1 0 0 0 1 1

TP7 1 0 0 0 NTP7 x x x x x x 1 0 0 1 1 1

TP8 1 0 0 1 NTP8 x x x x x x 1 0 1 0 1 1

TP9 1 0 1 0 NTP9 x x x x x x 1 0 1 1 1 1

TP10 1 0 1 1 NTP10 x x x x x x 1 1 0 0 1 1

TP11 1 1 0 0 NTP11 x x x x x x 1 1 0 1 1 1

Page 66: Apollo Guidance Computer AGC

TP12 1 1 0 1 NTP12 x x x 1 x x 0 0 0 0 0 x 0 0 0 0

x x 1 0 x x 0 0 1 0 0 x 0 0 1 0

x x 0 0 x x 1 1 1 0 1 1

SRLSE 1 1 1 0 NSRLSE x x x x 0 x 1 1 1 0 1 0

x x x x 1 x 1 1 1 1 1 1

WAIT 1 1 1 1 NWAIT x x x x x 1 0 0 1 0 0 x 0 0 1 0

x x x x x 0 1 1 1 1 1 0

Maxterms:

NPE = (NTP12 + TPG_3') * (NTP12 + TPG_2' + TPG_3) * (NWAIT + TPG_5')

CET = (NSTBY + TPG_0) * (NPWRON + TPG_1) * (NSRLSE + TPG_4) * (NWAIT + TPG_5)

Par In A,B,C = 0

Par In B = (NTP12' * TPG_3)'

Page 67: Apollo Guidance Computer AGC

TPG INPUTS:

I/F signal full name state definition

MON:

NRUN RUN/HALT 0=run, 1=step

INST INST STEP MODE 1=instruction step,

0=sequence step

NSTEP SINGLE STEP 0=step (momentary)

FCLK CLOCK MODE 1=continuous, 0=single

clock

NSA STANDBY ALLOWED 0=standby allowed

NPURST POWER UP RESET 0=power up reset

CLK:

CLK1 CLOCK1 1024 MHz AGC clock 1

SEQ:

SNI SELECT NEXT INST 1=select next instruction

SCL:

F17X F17 SCALER ONESHOT 1=timed out

F13X F13 SCALER ONESHOT 1=timed out

OUT:

OUT1_8 STANDBY ENABLED 1=standby enabled; works with STANDBY

ALLOWED switch

TPG OUTPUTS:

signal full name state definition

TPG_Q3 TPG STATE where Q0 is LSB, Q3 is MSB:

TPG_Q2 00 = STBY

TPG_Q1 01 = PWRON

TPG_Q0 02 = TP1

03 = TP2

04 = TP3

05 = TP4

06 = TP5

07 = TP6

08 = TP7

09 = TP8

10 = TP9

11 = TP10

12 = TP11

13 = TP12

14 = SRLSE

15 = WAIT

Page 68: Apollo Guidance Computer AGC
Page 69: Apollo Guidance Computer AGC

SEQ (Sequence Generator)

The sequence generator contains the stage registers and branch registers that (along with

the time pulse generator) control execution of the microinstruction sequence.

Some back-of-the-envelope design that went into the branch

register logic is shown in the next few charts. This is the

conceptual design for the branch register. It has 2 flip-flops

named BR2 and BR1. The flip-flops are set by the control signals

shown as diamonds in this diagram.

The J and K

inputs to the BR1

flip-flop are

developed in this

chart.

Page 70: Apollo Guidance Computer AGC

This chart shows

the J and K inputs

to the BR2 flip-flop.

Logic to sense a 1's

compliment minus

zero from the write

bus is also

developed.

Page 71: Apollo Guidance Computer AGC

Here are some charts showing the stage

register design. This is the conceptual

design. There are (2) 2-bit stage registers:

STA and STB.

This is my initial cut at STA and STB. My initial attempt at CLSTB is scratched out and then

developed into the correct solution on the later charts.

Page 72: Apollo Guidance Computer AGC

This is the J input to the STA2 flip-

flop. The initial design is at the

top. In the middle, I

“DeMorganize” it using some

bubble-pushing to get the final

implementation at the bottom.

Here’s the J and K inputs to

STB1 and STB2. This is the

logic that transfers the

contents of the STA flip-

flops to STB.

Page 73: Apollo Guidance Computer AGC

The J and K inputs to STB1 and STB2 move through a multi-step DeMorganizing process in

the next 2 charts to reach their final state:

Page 74: Apollo Guidance Computer AGC

SEQ INPUTS:

I/F signal full name state definition

CLK:

CLK2 CLOCK 2 data transfer occurs on falling edge

CPM-C:

GENRST GENERAL RESET 0=General Reset

WSQ WRITE SQ 0=Write SQ

CLISQ CLEAR SNI 0=Clear SNI

CLSTA CLEAR STA 0=Clear state counter A

(STA)

WSTB WRITE STB 0=Write stage counter B

(STB)

CLSTB CLEAR STB 0=Clear state counter B

(STB)

SETSTB SET ST1 0=Set the ST1 bit of STB

CPM-A:

TRSM TEST RESUME 0=Test for resume

TSGN TEST SIGN 0=Test sign

TSGN2 TEST SIGN 2 0=Test sign 2

ST1 SET STAGE 1 0=Stage 1

ST2 SET STAGE 2 0=Stage 2

CLCTR CLR LOOP CTR 0=Clear loop counter

CTR INCR LOOP CTR 0=Loop counter

TMZ TEST MINUS ZERO 0=Test for minus zero

TOV TEST OVF 0=Test for overflow

NISQ NEW INSTRUCT 0=New instruction to the

SQ reg

WBUS:

WB_01 WRITE BUS 01

... ...

WB_14 WRITE BUS 14

WB_15 WRITE BUS 15 US (overflow) bit for write bus

WB_16 WRITE BUS 16 SG (sign) bit for write bus

ADR:

EQU_25 ADDRESS = 025 0=CADR in register S evaluates to = 025

SEQ OUTPUTS:

I/F signal full name state definition

CPM-A:

BR1 BRANCH REG 1 where BR1 is MSB, BR2 is LSB

BR2 BRANCH REG 2 BR00 =0 BR1=0, BR2=0

BR01 =1 BR1=0, BR2=1

BR10 =2 BR1=1, BR2=0

BR11 =3 BR1=1, BR2=1

Page 75: Apollo Guidance Computer AGC

SQ_3 INST REG where SQ_3 is MSB, SQ_0 is LSB

SQ_2

SQ_1

SQ_0

STB_1 STAGE REG where STB_1 is MSB, STB_0 is LSB

STB_0

LOOP6 LOOPCNTR EQ 6 0=LOOPCNTR is holding the number 6.

SNI SELECT NEXT INST 1=select next instruction (SNI register)

Page 76: Apollo Guidance Computer AGC
Page 77: Apollo Guidance Computer AGC
Page 78: Apollo Guidance Computer AGC
Page 79: Apollo Guidance Computer AGC
Page 80: Apollo Guidance Computer AGC

CPM-A (Control Pulse Matrix A)

In this AGC replica, the CPM-A subsequences are implemented in EPROM (they were

implemented as a diode matrix in the original). The address into the EPROM is constructed

as follows (bit 1 is the LSB):

bit

13,14 CTR subsequence (2)

9-12: register SQ (4)

7,8: register STB (2)

3-6: register SG (4)

2: register BR1 (1)

1: register BR2 (1)

Bits 7-14 (STB, SQ, and CTR) select the instruction subsequence. Bits 1-6 select the control

pulses (control logic signals) that are asserted from that subsequence.

SELECTING THE INSTRUCTION SUBSEQUENCE

The 11 AGC instructions, priority counter operations, and interrupt operations are

implemented in 22 instruction subsequences. Some instructions (TC) have a single

subsequence; others have several subsequences.

The instruction subsequence is choosen by CTR, SQ, and STB. These form bits 7-14 of the

CPM-A EPROM address.

CTR (EPROM address bits 13-14)

The CTR signal has 2 lines: SB_02 is the MSB; SB_01 is the LSB. The signal comes from the

CTR subsystem in the PROC module. It indicates whether processing needs to be briefly

interrupted to insert a PINC or MINC subsequence to increment or decrement a priority

counter.

CTR00: SB_02=0, SB_01=0 no counter; do the next subsequence

CTR01: SB_02=0, SB_01=1 PINC

CTR10: SB_02=1, SB_01=0 MINC

CTR11: SB_02=1, SB_01=1 both; they cancel out, so do the next

subsequence

Register SQ (EPROM address bits 9-12)

The 4-bit SQ register holds the currently executing instruction. The code in the SQ register

is the same as the op code for these four instructions.

NMEM SQ REG OPCODE USAGE DESCRIPTION CYCLESTC 00 00 TC K Transfer Control 1 MCTCCS 01 01 CCS K Count, Compare, Skip 2 MCTINDEX 02 02 INDEX K Index 2 MCTXCH 03 03 XCH K Exchange 2 MCT

The SQ register code for these four instructions is the op code + 010 (octal). This happens

because all of these instructions have bit 15 set (the sign (SG) bit) while in memory. When

Page 81: Apollo Guidance Computer AGC

the instruction is copied from memory to the memory buffer register (G) to register B, the

SG bit moves from bit 15 to bit 16 and the sign is copied back into bit 15 (US). Therefore,

the CS op code (04) becomes (14), and so on.

NMEM SQ REG OPCODE USAGE DESCRIPTION CYCLESCS 014 04 CS K Clear and Subtract 2 MCTTS 015 05 TS K Transfer to Storage 2 MCTAD 016 06 AD K Add 2 or 3 MCTMASK 017 07 MASK K Bitwise AND 2 MCT

These are the three extended instructions. They are accessed by executing an INDEX 5777

before each instruction. By convention, address 5777 contains 47777. The INDEX instruction

adds 47777 to the extended instruction to form the SQ op code. For example, the INDEX

adds 4 to the 4 op code for MP to produce the 11 (octal; the addition generates an

end-around-carry). SQ register code (the 7777 part is a negative zero).

NMEM SQ REG OPCODE USAGE DESCRIPTION CYCLESMP 011 04 MP K Multiply 10 MCTDV 012 05 DV K Divide 18 MCTSU 013 06 SU K Subtract 4 or 5 MCT

STB (EPROM address bits 7-8)

The stage register B (STB) selects the subsequence for a given instruction. Some instructions

have multiple subsequences; others (TC) have only one.

The stage register has 2 bits: STB2 is the MSB; STB1 is the LSB. All instructions initiallly

begin with the stage register set to zero. If an instruction needs more than one subsequence,

the stage register is incremented to select the next subsequence.

STB00: STB2=0, STB1=0

STB01: STB2=0, STB1=1

STB10: STB2=1, STB1=0

STB11: STB2=1, STB1=1

INSTRUCTION SUBSEQUENCES

There are 22 instruction subsequences:

TC0 0

CCS0 1

CCS1 2

NDX0 3

NDX1 4

RSM3 5

XCH0 6

CS0 7

TS0 8

AD0 9

MASK0 10

MP0 11

MP1 12

Page 82: Apollo Guidance Computer AGC

MP3 13

DV0 14

DV1 15

SU0 16

RUPT1 17

RUPT3 18

STD2 19

PINC0 20

MINC0 21

If the CTR signals are 01 (SB_02=0, SB_01=1) the PINC subsequence is selected. If the CTR

signals are 10 (SB_02=1, SB_01=0) the MINC subsequence is selected. Otherwise,

subsequences for each instruction are selected using the 4-bit SQ register and the 2-bit stage

register (STB2, STB1, where STB2 is the MSB). Some instructions (TC) have only one

subsequence. At the start of each instruction, the stage counter is initially set to zero. The

interrupt call and resturn sequences are also stored at SQ=00.

SQ STB00 STB01 STB10 STB11

TC/RUPT 00: TC0 RUPT1 STD2 RUPT3

CCS 01: CCS0 CCS1 ---- ----

INDEX 02: NDX0 NDX1 ---- RSM3

XCH 03: XCH0 ---- STD2 ----

04: ---- ---- ---- ----

05: ---- ---- ---- ----

06: ---- ---- ---- ----

07: ---- ---- ---- ----

10: ---- ---- ---- ----

MP 11: MP0 MP1 ---- MP3

DV 12: DV0 DV1 STD2 ----

SU 13: SU0 ---- STD2 ----

CS 14: CS0 ---- STD2 ----

TS 15: TS0 ---- STD2 ----

AD 16: AD0 ---- STD2 ----

MASK 17: MASK0 ---- STD2 ----

SELECTING THE CONTROL PULSES

Each subsequence consists of 12 steps (TP1 - TP12), with each step asserting up to 5 control

pulses (control logic signals). Steps TP1-TP11 are unique to each subsequence; step TP12 is

common to all subsequences. Control pulses for TP12 are discussed in CPM-C.

For some steps, selection of the control pulses is also conditional on the state of the 2-bit

branch register (BR1 and BR2: BR1 is the MSB and BR2 is the LSB):

BR00 BR1=0, BR2=0

BR01 BR1=0, BR2=1

BR10 BR1=1, BR2=0

BR11 BR1=1, BR2=1

Bits 1-6 of the CPM-A EPROM address is formed as follows:

Page 83: Apollo Guidance Computer AGC

3-6: register SG (4)

2: register BR1 (1)

1: register BR2 (1)

The column on the far left is the step; columns to the right specify the control pulses that are

asserted for that step. Some steps have no control pulses.

subsequence TC0:

TP1 RB WY WS CI ----

TP2

TP3 WG ---- ---- ---- ----

TP4 RA WOVI ---- ---- ----

TP5

TP6

TP7 RG RSC WB WP ----

TP8 RZ WQ GP TP ----

TP9 RB WSC WG ---- ----

TP10 RU WZ ---- ---- ----

TP11 NISQ ---- ---- ---- ----

subsequence CCS0:

TP1 RB WS ---- ---- ----

TP2 RZ WY ---- ---- ----

TP3 WG ---- ---- ---- ----

TP4

TP5

TP6 RG RSC WB TSGN WP

TP7 BR00, RC TMZ ---- ---- ----

BR01, RC TMZ ---- ---- ----

BR10, RB TMZ ---- ---- ----

BR11, RB TMZ ---- ---- ----

TP8 BR00, GP TP ---- ---- ----

BR01, R1 WX GP TP ----

BR10, R2 WX GP TP ----

BR11, R1 R2 WX GP TP,

TP9 RB WSC WG ---- ----

TP10 BR00, RC WA ---- ---- ----

BR01, WA R1C ---- ---- ----

BR10, RB WA ---- ---- ----

BR11, WA R1C ---- ---- ----

TP11 RU ST1 WZ ---- ----

subsequence CCS1:

TP1 RZ WY WS CI ----

TP2

TP3 WG ---- ---- ---- ----

TP4 RU WZ ---- ---- ----

TP5 RA WY CI ---- ----

TP6

TP7 RG RSC WB WP ----

TP8 RU WB GP TP ----

Page 84: Apollo Guidance Computer AGC

TP9

TP10 RC WA WOVI ---- ----

TP11 RG RSC WB NISQ ----

subsequence NDX0:

TP1 RB WS ---- ---- ----

TP2

TP3 WG ---- ---- ---- ----

TP4 RA WOVI ---- ---- ----

TP5

TP6

TP7 RG RSC WB WP ----

TP8 GP TP ---- ---- ----

TP9 RB WSC WG ---- ----

TP10 TRSM ---- ---- ---- ----

TP11 ST1 ---- ---- ---- ----

subsequence NDX1:

TP1 RZ WY WS CI ----

TP2

TP3 WG ---- ---- ---- ----

TP4 RU WZ ---- ---- ----

TP5

TP6 RB WY ---- ---- ----

TP7 RG RSC WB WP ----

TP8 RB WX GP TP ----

TP9 RB WSC WG ---- ----

TP10

TP11 RU WB WOVI NISQ ----

subsequence RSM3:

TP1 R24 WS ---- ---- ----

TP2

TP3 WG ---- ---- ---- ----

TP4

TP5

TP6

TP7 RG WZ ---- ---- ----

TP8

TP9

TP10

TP11 NISQ ---- ---- ---- ----

subsequence XCH0:

TP1 RB WS ---- ---- ----

TP2 RA WP ---- ---- ----

TP3 WG ---- ---- ---- ----

TP4 WP2 ---- ---- ---- ----

TP5

TP6

Page 85: Apollo Guidance Computer AGC

TP7 RG RSC WB WP, ----

TP8 GP TP ---- ---- ----

TP9 RA WSC WG RP2 ----

TP10 RB WA WOVI ---- ----

TP11 ST2 ---- ---- ---- ----

subsequence CS0:

TP1 RB WS ---- ---- ----

TP2

TP3 WG ---- ---- ---- ----

TP4

TP5

TP6

TP7 RG RSC WB WP, ----

TP8 GP TP ---- ---- ----

TP9 RB WSC WG ---- ----

TP10 RC WA WOVI ---- ----

TP11 ST2 ---- ---- ---- ----

subsequence TS0:

TP1 RB WS ---- ---- ----

TP2 RA WB TOV WP ----

TP3 WG ---- ---- ---- ----

TP4 BR00, ---- ---- ---- ---- ----

BR01, RZ WY CI ---- ---- (overflow)

BR10, RZ WY CI ---- ---- (underflow)

BR11, ---- ---- ---- ---- ----

TP5 BR00, ---- ---- ---- ---- ----

BR01, R1 WA ---- ---- ----

BR10, WA R1C ---- ---- ----

BR11, ---- ---- ---- ---- ----

TP6

TP7 BR00, ---- ---- ---- ---- ----

BR01, RU WZ ---- ---- ----

BR10, RU WZ ---- ---- ----

BR11, ---- ---- ---- ---- ----

TP8 GP ---- ---- ---- ----

TP9 RB WSC WG ---- ----

TP10 RA WOVI ---- ---- ----

TP11 ST2 ---- ---- ---- ----

subsequence AD0:

TP1 RB WS ---- ---- ----

TP2 RA WY ---- ---- ----

TP3 WG ---- ---- ---- ----

TP4

TP5

TP6

TP7 RG RSC WB WP ----

TP8 RB WX GP TP ----

TP9 RB WSC WG ---- ----

TP10

Page 86: Apollo Guidance Computer AGC

TP11 RU WA WOVC ST2 WOVI

SUB_MASK0 performs a logical AND using DeMorgan's Theorem: the inputs are inverted, a

logical OR is performed, and the result is inverted. The implementation of the OR (at TP8) is

somewhat unorthodox: the inverted inputs are in registers U and C. The OR is achieved by

gating both registers onto the read/write bus simultaneously. (The bus only transfers logical

1's; register-to-register transfers are performed by clearing the destination register and then

transferring the 1's from the source register to the destination). When the 1's from both

registers are simultaneously gated onto the bus, the word on the bus is a logical OR of both

registers.

subsequence MASK0:

TP1 RB WS ---- ---- ----

TP2 RA WB ---- ---- ----

TP3 WG ---- ---- ---- ----

TP4 RC WY ---- ---- ----

TP5

TP6

TP7 RG RSC WB WP ----

TP8 RU RC WA GP TP

TP9

TP10 RA WB ---- ---- ----

TP11 RC WA ST2 WOVI ----

subsequence MP0:

TP1 RB WS ---- ---- ----

TP2 RA WB TSGN ---- ----

TP3 RSC WG ---- ---- ----

TP4 BR00, RB WLP ---- ---- ----

BR01, RB WLP ---- ---- ----

BR10, RC WLP ---- ---- ----

BR11, RC WLP ---- ---- ----

TP5 RLP WA ---- ---- ----

TP6

TP7 BR00, RG WY WP ---- ----

BR01, RG WY WP ---- ----

BR10, RG WB WP ---- ----

BR11, RG WB WP ---- ----

TP8 BR00, GP TP ---- ---- ----

BR01, GP TP ---- ---- ----

BR10, RC WY GP TP ----

BR11, RC WY GP TP ----

TP9 RU WB TSGN2 ---- ----

TP10 BR00, RA WLP TSGN ---- ----

BR01, RA RB14 WLP TSGN ----

BR10, RA WLP TSGN ---- ----

BR11, RA RB14 WLP TSGN ----

TP11 BR00, ST1 WALP ---- ---- ----

BR01, R1 ST1 WALP R1C ----

BR10, RU ST1 WALP ---- ----

BR11, RU ST1 WALP ---- ----

Page 87: Apollo Guidance Computer AGC

subsequence MP1:

TP1 RA WY ---- ---- ----

TP2 RLP WA TSGN ---- ----

TP3 BR00, ---- ---- ---- ---- ----

BR01, ---- ---- ---- ---- ----

BR10, RB WX ---- ---- ----

BR11, RB WX ---- ---- ----

TP4 RA WLP ---- ---- ----

TP5 RLP TSGN ---- ---- ----

TP6 RU WALP ---- ---- ----

TP7 RA WY ---- ---- ----

TP8 BR00, ---- ---- ---- ---- ----

BR01, ---- ---- ---- ---- ----

BR10, RB WX ---- ---- ----

BR11, RB WX ---- ---- ----

TP9 RLP WA ---- ---- ----

TP10 RA WLP CTR ---- ----

TP11 RU ST1 WALP ---- ----

subsequence MP3:

TP1 RZ WY WS CI ----

TP2 RLP TSGN ---- ---- ----

TP3 WG ---- ---- ---- ----

TP4 RU WZ ---- ---- ----

TP5 RA WY ---- ---- ----

TP6 BR00, ---- ---- ---- ---- ----

BR01, ---- ---- ---- ---- ----

BR10, RB WX ---- ---- ----

BR11, RB WX ---- ---- ----

TP7 RG RSC WB WP ----

TP8 RLP WA GP TP ----

TP9 RB WSC WG ---- ----

TP10 RA WLP ---- ---- ----

TP11 RU WALP NISQ ---- ----

subsequence DV0:

TP1 RB WS ---- ---- ----

TP2 RA WB TSGN ---- ----

TP3 RSC WG ---- ---- ----

TP4 BR00, RC WA ---- ---- ----

BR01, RC WA ---- ---- ----

BR10, ---- ---- ---- ---- ----

BR11, ---- ---- ---- ---- ----

TP5 BR00, R1 WLP ---- ---- ----

BR01, R1 WLP ---- ---- ----

BR10, R2 WLP ---- ---- ----

BR11, R2 WLP ---- ---- ----

TP6 RA WQ ---- ---- ----

TP7 RG WB TSGN WP ----

TP8 RB WA GP TP ----

TP9 BR00, RLP R2 WB ---- ----

Page 88: Apollo Guidance Computer AGC

BR01, RLP R2 WB ---- ----

BR10, ---- ---- ---- ---- ----

BR11, ---- ---- ---- ---- ----

TP10 BR00, RB WLP ---- ---- ----

BR01, RB WLP ---- ---- ----

BR10, RC WA ---- ---- ----

BR11, RC WA ---- ---- ----

TP11 R1 ST1 WB ---- ----

subsequence DV1:

TP1 R22 WS ---- ---- ----

TP2 RQ WG ---- ---- ----

TP3 RG WQ WY RSB ----

TP4 RA WX ---- ---- ----

TP5 RLP TSGN2 ---- ---- ----

TP6

TP7 RU TSGN ---- ---- ----

TP8 BR00, ---- ---- ---- ---- ----

BR01, ---- ---- ---- ---- ----

BR10, RU WQ ---- ---- ----

BR11, RU WQ ---- ---- ----

TP9 BR00, RB RSB WG ---- ----

BR01, RB RSB WG ---- ----

BR10, RB WG ---- ---- ----

BR11, RB WG ---- ---- ----

TP10 RG WB TSGN ---- ----

TP11 BR00, ST1 ---- ---- ---- ----

BR01, ST1 ---- ---- ---- ----

BR10, RC WA ST2 ---- ----

BR11, RB WA ST2 ---- ----

subsequence SU0:

TP1 RB WS ---- ---- ----

TP2 RA WY ---- ---- ----

TP3 WG ---- ---- ---- ----

TP4

TP5

TP6

TP7 RG RSC WB WP ----

TP8 RC WX GP TP ----

TP9 RB WSC WG ---- ----

TP10

TP11 RU WA WOVC ST2 WOVI

subsequence RUPT1:

TP1 R24 WY WS CI, ----

TP2

TP3 WG ---- ---- ---- ----

TP4

TP5

TP6

Page 89: Apollo Guidance Computer AGC

TP7

TP8

TP9 RZ WG ---- ---- ----

TP10 RU WZ ---- ---- ----

TP11 ST1 ST2 ---- ---- ----

subsequence RUPT3:

TP1 RZ WS ---- ---- ----

TP2 RRPA WZ ---- ---- ----

TP3 RZ KRPT WG ---- ----

TP4

TP5

TP6

TP7

TP8

TP9 RB WSC WG ---- ----

TP10

TP11 ST2 ---- ---- ---- ----

subsequence STD2:

TP1 RZ WY WS CI, ----

TP2

TP3 WG ---- ---- ---- ----

TP4 RU WZ ---- ---- ----

TP5

TP6

TP7 RG RSC WB WP ----

TP8 GP TP ---- ---- ----

TP9 RB WSC WG ---- ----

TP10

TP11 NISQ ---- ---- ---- ----

subsequence PINC:

TP1 WS RSCT ---- ---- ----

TP2

TP3 WG ---- ---- ---- ----

TP4 R1 WY ---- ---- ----

TP5

TP6 RG WX WP ---- ----

TP7 TP ---- ---- ---- ----

TP8 WP ---- ---- ---- ----

TP9 RU CLG WPx ---- ----

TP10 RU WGx WOVR ---- ----

TP11

subsequence MINC:

TP1 WS, RSCT ---- ---- ----

TP2

TP3 WG ---- ---- ---- ----

TP4 WY R1C ---- ---- ----

Page 90: Apollo Guidance Computer AGC

TP5

TP6 RG WX WP ---- ----

TP7 TP ---- ---- ---- ----

TP8 WP ---- ---- ---- ----

TP9 RU CLG WPx ---- ----

TP10 RU WGx WOVR ---- ----

TP11

Page 91: Apollo Guidance Computer AGC

Here’s some of the analysis used to develop the instruction sequence decoder. This decoder

takes in the STB and SQ inputs and decodes the instruction sequence for display to the

operator.

Page 92: Apollo Guidance Computer AGC

CONTROL SIGNAL DEFINITIONS

SIGNAL # DESCRIPTION

CI 1 Carry in

CLG 2 Clear G

CLCTR 3 Clear loop counter

CTR 4 Loop counter

GP 5 Generate Parity

KRPT 6 Knock down Rupt priority

NISQ 7 New instruction to the SQ register

RA 8 Read A

RB 9 Read B

RB14 10 Read bit 14

RC 11 Read C

RG 12 Read G

RLP 13 Read LP

RP2 14 Read parity 2

RQ 15 Read Q

RRPA 16 Read RUPT address

RSB 17 Read sign bit

RSCT 18 Read selected counter address

RU 19 Read sum

RZ 20 Read Z

R1 21 Read 1

R1C 22 Read 1 complimented

R2 23 Read 2

R22 24 Read 22

R24 25 Read 24

ST1 26 Stage 1

ST2 27 Stage 2

TMZ 28 Test for minus zero

TOV 29 Test for overflow

TP 30 Test parity

TRSM 31 Test for resume

TSGN 32 Test sign

TSGN2 33 Test sign 2

WA 34 Write A

WALP 35 Write A and LP

WB 36 Write B

Wgx 37 Write G (do not reset)

WLP 38 Write LP

WOVC 39 Write overflow counter

WOVI 40 Write overflow RUPT inh ibit

WOVR 41 Write overflow

WP 42 Write P

Wpx 43 Write P (do not reset)

WP2 44 Write P2

WQ 45 Write Q

WS 46 Write S

WX 47 Write X

WY 48 Write Y

Wyx 49 Write Y (do not reset)

Page 93: Apollo Guidance Computer AGC

WZ 50 Write Z

Control signal outputs from CPM-A used as inputs to CPM-B only (not used outside of CPM):

SIGNAL # DESCRIPTION

RSC 51 Read special and central (output to B only, not outside CPM)

WSC 52 Write special and central (output to B only, not outside CPM)

WG 53 Write G (output to B only, not outside CPM)

Control signal outputs from CPM-A used as inputs to CPM-C only (not used outside of CPM):

SIGNAL # DESCRIPTION

SDV1 54 Subsequence DV1 is currently active

SMP1 55 Subsequence MP1 is currently active

SRSM3 56 Subsequence RSM3 is currently active

Page 94: Apollo Guidance Computer AGC

CPM-A INPUTS:

I/F signal full name state definition

TPG:

TPG_Q3 TPG STATE where Q3 is MSB, Q0 is

LSB:

TPG_Q2 00 = STBY

TPG_Q1 01 = PWRON

TPG_Q0 02 = TP1

03 = TP2

04 = TP3

05 = TP4

06 = TP5

07 = TP6

08 = TP7

09 = TP8

10 = TP9

11 = TP10

12 = TP11

13 = TP12

14 = SRLSE

15 = WAIT

SEQ:

BR1 BRANCH REG 1 BR1 is MSB, BR2 is LSB

BR2 BRANCH REG 2 BR00=0:BR1=0, BR2=0

BR01=1:BR1=0, BR2=1

BR10=2:BR1=1, BR2=0

BR11=3:BR1=1, BR2=1

SQ_3 INST REG where SQ_3 is MSB,

SQ_0 is LSB

SQ_2

SQ_1

SQ_0

STB_1 STAGE REG where STB_1 is MSB,

STB_0 is LSB

STB_0

LOOP6 LOOPCNTR EQ 6 0=LOOPCNTR is holding

the number 6.

SNI SELECT NEXT INST 1=select next instruction (SNI register)

CTR:

SB_01 SUB SEL 01 SB_01 is LSB; SB_02 is MSB

SB_02 SUB SEL 02 00=no counter; 01=PINC; 10=MINC

INT:

Page 95: Apollo Guidance Computer AGC

IRQ INT RQST 0=interrupt requested.

MON:

NRUN RUN/HALT 0=run, 1=step

CPM-A OUTPUTS:

signal full name state definition

CI SET CARRY IN 0=Carry in

CLG CLR G 0=Clear G

CLCTR CLR LOOP CTR 0=Clear loop counter

CTR INCR LOOP CTR 0=Loop counter

GP GEN PARITY 0=Generate Parity

KRPT KNOCK DOWN RUPT 0=Knock down Rupt priority

NISQ NEW INSTRUCT 0=New instruction to the SQ reg

RA READ A 0=Read A

RB READ B 0=Read B

RB14 READ BIT 14 0=Read bit 14

RC READ C 0=Read C

RG READ G 0=Read G

RLP READ LP 0=Read LP

RP2 READ PARITY 2 0=Read parity 2

RQ READ Q 0=Read Q

RRPA READ RUPT ADDR 0=Read RUPT address

RSB READ SIGN 0=Read sign bit

RSCT READ CNTR ADDR 0=Read selected counter address

RU READ U 0=Read sum

RZ READ Z 0=Read Z

R1 READ 1 0=Read 1

R1C READ 1 COMP 0=Read 1 complimented

R2 READ 2 0=Read 2

R22 READ 22 0=Read 22

R24 READ 24 0=Read 24

ST1 SET STAGE 1 0=Stage 1

ST2 SET STAGE 2 0=Stage 2

TMZ TEST MINUS ZERO 0=Test for minus zero

TOV TEST OVF 0=Test for overflow

TP TEST PARITY 0=Test parity

TRSM TEST RESUME 0=Test for resume

TSGN TEST SIGN 0=Test sign

TSGN2 TEST SIGN 2 0=Test sign 2

WA WRITE A 0=Write A

WALP WRITE A/LP 0=Write A and LP

WB WRITE B 0=Write B

WGx WRITE G NO RESET 0=Write G (do not reset)

WLP WRITE LP 0=Write LP

WOVC WRITE OVF CNTR 0=Write overflow counter

WOVI WRITE OVF RUPT INH 0=Write overflow RUPT inh ibit

WOVR WRITE OVF 0=Write overflow

WP WRITE P 0=Write P

WPx WRITE P NO RESET 0=Write P (do not reset)

WP2 WRITE P2 0=Write P2

Page 96: Apollo Guidance Computer AGC

WQ WRITE Q 0=Write Q

WS WRITE S 0=Write S

WX WRITE X 0=Write X

WY WRITE Y 0=Write Y

WYx WRITE Y NO RESET 0=Write Y (do not reset)

WZ WRITE Z 0=Write Z

OUTPUTS TO CPM-B ONLY; NOT USED OUTSIDE CPM

RSC READ SPECIAL REG 0=Read special and central

WSC WRITE SPECIAL REG 0=Write special and central

WG WRITE G 0=Write G

OUTPUTS TO CPM-C ONLY; NOT USED OUTSIDE CPM

SDV1 SUBSEQ DV1 0=Subsequence DV1 is selected

SMP1 SUBSEQ MP1 0=Subsequence MP1 is selected

SRSM3 SUBSEQ RSM3 0=Subsequence RSM3 is selected

Page 97: Apollo Guidance Computer AGC
Page 98: Apollo Guidance Computer AGC
Page 99: Apollo Guidance Computer AGC

CPM-B (Control Pulse Matrix B)

Some AGC registers are mapped onto low memory addresses (00 - 17 octal), so reading or

writing to those addresses causes data to be read from, or written into, flip-flop registers

instead of memory. These addresses include the central registers (A, Q, Z, LP), the bank

register (BNK), and I/O registers.

Addresses 16 and 17 are used in conjunction with the INDEX instruction to inhibit or enable

interrupts; this is a trick used to extend the instruction set; to cram more instructions into a

3-bit op code.

The addresses from 20-23 are in eraseable memory, but any data written into those

addresses is rotated or shifted. This is implemented through the G register in the MEM

module.

Addresses 24-27 are reserved for saving the central register before servicing an interrupt.

Registers Z and B are automatically saved by the interrupt subsequence. Registers A and Q

must be saved by the interrupt service routine.

SPECIAL REGISTERS

These addresses called special registers. All numbers are in octal.

addr Flip-Flop registers

00 A register (accumulator)

01 Q register

02 Z register (program counter)

03 LP register

04 IN0 input register 0

05 IN1 input register 1

06 IN2 input register 2

07 IN3 input register 3

10 OUT0 output register 0

11 OUT1 output register 1

12 OUT2 output register 2

13 OUT3 output register 3

14 OUT4 output register 4

15 BANK bank register

16 RELINT

17 INHINT

Eraseable memory registers

20 CYR cycle right

21 SR shift right

22 CYL cycle left

23 SL shift left

24 ZRUPT save register Z

25 BRUPT save register B

26 ARUPT save register A

27 QRUPT save register Q

Page 100: Apollo Guidance Computer AGC

CPM-B translates the WG, RSC, and WSC signals generated by SUBSYSTEM A into signals

that read from or write to these registers. The logic is given below (all numbers are in octal):

if WG is asserted from CPM-A,

...and the address bus = 020: assert:W20

...and the address bus = 021: assert:W21

...and the address bus = 022: assert:W22

...and the address bus = 023: assert:W23

...otherwise, if the address bus > 17: assert:WGn (not a central register)

if RSC is asserted from CPM-A

...and the address bus = 00: assert:RA0

...and the address bus = 01: assert:RA1

...and the address bus = 02: assert:RA2

...and the address bus = 03: assert:RA3

...and the address bus = 04: assert:RA4

...and the address bus = 05: assert:RA5

...and the address bus = 06: assert:RA6

...and the address bus = 07: assert:RA7

...and the address bus = 010: assert:RA10

...and the address bus = 011: assert:RA11

...and the address bus = 012: assert:RA12

...and the address bus = 013: assert:RA13

...and the address bus = 014: assert:RA14

...and the address bus = 015: assert:RBK

...and the address bus = 016: do nothing

...and the address bus = 017: do nothing

if WSC is asserted from CPM-A,

...and the address bus = 00: assert:WA0

...and the address bus = 01: assert:WA1

...and the address bus = 02: assert:WA2

...and the address bus = 03: assert:WA3

...and the address bus = 010: assert:WA10

...and the address bus = 011: assert:WA11

...and the address bus = 012: assert:WA12

...and the address bus = 013: assert:WA13

...and the address bus = 014: assert:WA14

...and the address bus = 015: assert:WBK

...and the address bus = 016: do nothing

...and the address bus = 017: do nothing

Page 101: Apollo Guidance Computer AGC

Here’s a table I developed to work out the relationships between addresses and CPM-B logic

signals:

Page 102: Apollo Guidance Computer AGC

CPM-B CONTROL SIGNALS

SIGNAL # DESCRIPTION

RA0 57 Read register at address 0 (A)

RA1 58 Read register at address 1 (Q)

RA2 59 Read register at address 2 (Z)

RA3 60 Read register at address 3 (LP)

RA4 61 Read register at address 4

RA5 62 Read register at address 5

RA6 63 Read register at address 6

RA7 64 Read register at address 7

RA10 65 Read register at address 10 (octal)

RA11 66 Read register at address 11 (octal)

RA12 67 Read register at address 12 (octal)

RA13 68 Read register at address 13 (octal)

RA14 69 Read register at address 14 (octal)

RBK 70 Read BNK

WA0 71 Write register at address 0 (A)

WA1 72 Write register at address 1 (Q)

WA2 73 Write register at address 2 (Z)

WA3 74 Write register at address 3 (LP)

WA10 75 Write register at address 10 (octal)

WA11 76 Write register at address 11 (octal)

WA12 77 Write register at address 12 (octal)

WA13 78 Write register at address 13 (octal)

WA14 79 Write register at address 14 (octal)

WBK 80 Write BNK

WGn 81 Write G (normal gates)

W20 82 Write into CYR

W21 83 Write into SR

W22 84 Write into CYL

W23 85 Write into SL

Page 103: Apollo Guidance Computer AGC

CPM-B INPUTS:

I/F signal full name state definition

CPM-A

RSC READ SPECIAL REG 0=Read special and central

WSC WRITE SPECIAL REG 0=Write special and central

WG WRITE G 0=Write G

ADR:

AD_4 ADDRESS AD_4=MSB, AD_1=LSB:

AD_3 (low-order bits of 14-bit

address)

AD_2

AD_1

GTR_17 ADDRESS > 017 0=CADR in register S >

017

GTR_27 ADDRESS > 027 0=CADR in register S >

027

CPM-B OUTPUTS:

I/F signal full name state definition

RA0 READ ADDR 0 0=Read reg at address 0

(A)

RA1 READ ADDR 1 0=Read reg at address 1 (Q)

RA2 READ ADDR 2 0=Read reg at address 2 (Z)

RA3 READ ADDR 3 0=Read reg at address 3 (LP)

RA4 READ ADDR 4 0=Read reg at address 4

RA5 READ ADDR 5 0=Read reg at address 5

RA6 READ ADDR 6 0=Read reg at address 6

RA7 READ ADDR 7 0=Read reg at address 7

RA10 READ ADDR 10 0=Read reg at address 10 (octal)

RA11 READ ADDR 11 0=Read reg at address 11 (octal)

RA12 READ ADDR 12 0=Read reg at address 12 (octal)

RA13 READ ADDR 13 0=Read reg at address 13 (octal)

RA14 READ ADDR 14 0=Read reg at address 14 (octal)

RBK READ BNK 0=Read BNK reg

WA0 WRITE ADDR 0 0=Write reg at address 0 (A)

WA1 WRITE ADDR 1 0=Write reg at address 1 (Q)

WA2 WRITE ADDR 2 0=Write reg at address 2 (Z)

WA3 WRITE ADDR 3 0=Write reg at address 3 (LP)

WA10 WRITE ADDR 10 0=Write reg at address 10 (octal)

WA11 WRITE ADDR 11 0=Write reg at address 11 (octal)

WA12 WRITE ADDR 12 0=Write reg at address 12 (octal)

WA13 WRITE ADDR 13 0=Write reg at address 13 (octal)

WA14 WRITE ADDR 14 0=Write reg at address 14 (octal)

WBK WRITE BNK 0=Write BNK reg

Page 104: Apollo Guidance Computer AGC

WGn WRITE G NORMAL 0=Write G (normal gates)

W20 WRITE ADDR 20 0=Write into CYR

W21 WRITE ADDR 21 0=Write into SR

W22 WRITE ADDR 22 0=Write into CYL

W23 WRITE ADDR 23 0=Write into SL

Page 105: Apollo Guidance Computer AGC
Page 106: Apollo Guidance Computer AGC

CPM-C (Control Pulse Matrix C)

The CPM-C subsystem issues control signals for the memory cycle, selecting the next

instruction, and performing priority counter subsequences. These signals are issued at

specific points in the 12-step cycle of the time pulse generator (TPG).

STBY: assert:GENRST Resets various AGC registers.

PWRON: assert:R2000 Put the starting address on the read bus.

CPM-A asserts:WB, which copies the data

into register B, which is the prefetch

register for the next instruction. Since the

opcode for a branch is 0, the instruction in

B becomes TC 2000, which is the first

instruction always executed by the AGC.

TP1: assert:CLISQ SNI <- 0. Moved from TP12 to TP1 because

CLISQ was getting cleared in this hardware

AGC replica before TPG was clocked;

therefore TPG was not seeing the SNI

indication.

TP5: if: the address bus > 17 (not a central register)

and the address bus < 2000 (not fixed memory; must be erasable)

and SDV1 or SMP1 are not asserted (not a loop counter subsequence)

then: assert:SBWG read erasable memory into G by TP6

if: the address bus = 17

then: assert:INH INHINT instruction (INDEX 017)

if: the address bus = 16

then: assert:CLINH RELINT instruction (INDEX 016)

TP6: if: the address bus > 1777 (not eraseable memory)

and SDV1 or SMP1 are not asserted (not a loop counter subsequence)

then: assert:SBWG read fixed memory into G register by TP7

TP11: if: the address bus > 17 (not a central register)

and the address bus < 2000 (not fixed memory; must be erasable)

and SDV1 or SMP1 are not asserted (not a loop counter subsequence)

then: assert:WE G register written to memory beginning at

TP11; Memory updates are in G by TP10

for all normal and extracode instructions,

but the PINC and MINC sequences write to

G in TP10 because they need to update the

parity bit.

if: SRSM3 is asserted

then: assert:CLRP Additional interrupts are inhibited during

servicing of an interrupt; Remove the

inhibition when RESUME is executed

(INDEX 025)

Page 107: Apollo Guidance Computer AGC

TP12: assert:WPCTR Check the priority counters; service any

waiting inputs on the next memory cycle.

if: the SNI register = 1 (if SNI is set, get next instruction)

then:

if: IRQ is asserted (if interrupt requested (see CPM-A for

similar assertion))

then:

assert:RPT Read the interrupt vector.

assert:SETSTB STB <- 1. Will cause the RUPT1

subsequence to execute.

else: (not an interrupt; a normal instruction)

assert:CLSTB STB <- 0 . The CPM-A will assert RB here,

which, when accompanied by WSQ

(below), will read the next instruction from

register B onto the bus. WSQ will write it

into SQ.

endif

assert:WSQ Write the next instruction (on the write

bus) into the SQ register.

assert:CLSTA Clear STA register.

assert:CLINH1 Clear INHINT1. Removes inhibition of

interrupts (if they were) AFTER the next

instruction

else: (not a new instruction)

if: CTR00 or CTR11 if previous sequence was not a PINC or

MINC, get next subsequence for same

instruction. if the previous sequence was

PINC or MINC, we already have the

subsequence, but it was interrupted by the

counter.

then:

assert:WSTB Copy STB <- STA. Gets next sequence for

same instruction.

assert:CLSTA STA <- 0

Page 108: Apollo Guidance Computer AGC

This truth table shows the logic

needed at TP12 to produce the

RPT, SETSTB, CLSTB, CLSTA,

WSQ, WSTB, CLISQ, and CLINH1

signals, given the SNI, IRQ,

NRUN, and SB inputs.

This chart shows the logic for

some of the more simple

control pulses generated by

CMP-C. Some pulses reduce to

states from the TPG, such as

CLISQ, WPCTR, and CLINH1,

which reduce to TP12.

Page 109: Apollo Guidance Computer AGC

This is the logic for RPT and SETSTB.

The design for CLSTB is a

little more complex. The

truth table to the left is

reduced through the

Karnaugh map to the

Minterm equation below

the map. A little bubble

pushing DeMorganizes

the logic to the final

solution at the bottom

right.

Page 110: Apollo Guidance Computer AGC

This is the logic for

WE and SBWG, two

signals that control

memory access.

Page 111: Apollo Guidance Computer AGC

CPM-C CONTROL SIGNALS

SIGNAL # DESCRIPTION

GENRST 86 General Reset

CLINH 87 Clear INHINT

CLINH1 88 Clear INHINT1

CLSTA 89 Clear state counter A (STA)

CLSTB 90 Clear state counter B (STB)

CLISQ 91 Clear SNI

CLRP 92 Clear RPCELL

INH 93 Set INHINT

RPT 94 Read RUPT opcode

SBWG 95 Write G from memory

SETSTB 96 Set the ST1 bit of STB

WE 97 Write E-MEM from G

WPCTR 98 Write PCTR (latch priority counter sequence)

WSQ 99 Write SQ

WSTB 100 Write stage counter B (STB)

R2000 101 Read 2000

Page 112: Apollo Guidance Computer AGC

CPM INPUTS:

I/F signal full name state definition

TPG:

TPG_Q3 TPG STATE where Q3 is MSB, Q0 is

LSB:

TPG_Q2 00 = STBY

TPG_Q1 01 = PWRON

TPG_Q0 02 = TP1

03 = TP2

04 = TP3

05 = TP4

06 = TP5

07 = TP6

08 = TP7

09 = TP8

10 = TP9

11 = TP10

12 = TP11

13 = TP12

14 = SRLSE

15 = WAIT

ADR:

EQU_16 ADDRESS = 016 0=CADR in register S = 016

EQU_17 ADDRESS = 017 0=CADR in register S = 017

GTR_17 ADDRESS > 017 0=CADR in register S > 017

GTR_1777 ADDRESS > 01777 0=CADR in register S > 01777

CPM-A:

SDV1 SUBSEQ DV1 0=Subsequence DV1 is selected

SMP1 SUBSEQ MP1 0=Subsequence MP1 is selected

SRSM3 SUBSEQ RSM3 0=Subsequence RSM3 is selected

CTR:

SB_01 SUB SEL 01 SB_01 is LSB; SB_02 is MSB

SB_02 SUB SEL 02 00=no counter; 01=PINC; 10=MINC

SEQ:

SNI SELECT NEXT INST 1=select next instruction (SNI register)

INT:

IRQ INT RQST 0=interrupt requested.

MON:

NRUN RUN/HALT 0=run, 1=step

Page 113: Apollo Guidance Computer AGC

CPM OUTPUTS:

I/F signal full name state definition

GENRST GENERAL RESET 0=General Reset

CLINH CLEAR INHINT 0=Clear INHINT

CLINH1 CLEAR INHINT1 0=Clear INHINT1

CLSTA CLEAR STA 0=Clear state counter A (STA)

CLSTB CLEAR STB 0=Clear state counter B (STB)

CLISQ CLEAR SNI 0=Clear SNI

CLRP CLEAR RPCELL 0=Clear RPCELL

INH SET INHINT 0=Set INHINT

RPT READ RUPT 0=Read RUPT opcode

SBWG WRITE G 0=Write G from memory

SETSTB SET ST1 0=Set the ST1 bit of STB

WE WRITE EMEM 0=Write E-MEM from G

WPCTR WRITE PCTR 0=Write PCTR (latch priority counter

sequence)

WSQ WRITE SQ 0=Write SQ

WSTB WRITE STB 0=Write stage counter B (STB)

R2000 READ 2000 0=Read 2000

Page 114: Apollo Guidance Computer AGC
Page 115: Apollo Guidance Computer AGC

Fabrication

The CTL module is (3) 13"x5" circuit boards, and 1 control panel.

Module Rack

The module framework is designed to resemble a relay rack, but scaled to fit the circuit

board dimensions. It is constructed out of 1"x2" pine and spray-painted semi-gloss gray.

Circu it boards are mounted to the rack by 2 phillips screws at either end. Nylon spacers

(1/4") are used as standoffs to hold the board edges above the rack. The boards are

mounted so the chips are in the back and the pins are wiring are visible from the front.

Power is distributed by 2 heavy aluminum bus bars mounted vertically, one per side, on the

back of the module. Machine screws are mounted through the bus bars at evenly-spaced

intervals to provide connection points for the boards.

Solid copper wire (24 gauge) connects the boards to the bus bars. Ring terminals are used

on the bus bar side of the connection. On the circuit board size, the wires are soldered

directly to the supply rails.

Materials were purchased from Home Depot, ACE Hardware, and Radio Shack.

Circuit Boards

The circuit boards are 13"x5" general purpose prototyping boards, epoxy glass with double-

side plated through pads on 0.1" centers (JAMECO 21477CL).

ICs are mounted in level 3 machine tooled wire-wrap sockets: 8, 14, 16, 20, 24, and 28 pin

(JAMECO). Each socket has the pin-out labeled with a wire-wrap socket ID marker, which

slips onto the socket before wrapping (JAMECO). The part number is written onto the ID

marker.

Sockets are arranged in 4 horizontal rows on each board, with

about 10 sockets per row.

Power is distributed on the back-side of each board by bare 24-

gauge solid copper wire supply rails soldered at equal intervals

to Klipwrap terminals: 3-prong terminals with a square tail for

wire-wrapping (JAMECO 34163CL). A +5V rail runs above each

row of sockets and a ground rail runs below. Each rail connects

directly to the alum inum module power bus using a ring tail

connector.

On the pin side of the board, all connections are made with 30

AWG Kynar wire-wrap wire (JAMECO). Red wire is used for direct

connections to the +5V supply rail. Black w ire is used for direct connections to ground. White

wire is used for everything else.

Power connections from the supply rails to each ICs are double-wrapped. Bypassing

capacitors (.1 uf disc ) are soldered across the supply rails at the Klipwrap terminals; about 1

capacitor for every 2 IC packages.

Page 116: Apollo Guidance Computer AGC

All connections were stripped and hand-wrapped using a Radio Shack hand-wrap tool. As

each connection was made, the corresponding line on the schematic was marked with a

colored highlighter.

DIP resistor networks (JAMECO) plugged into 20-pin wire-wrap sockets were used as current

limiting resistors for the panel indicators.

Page 117: Apollo Guidance Computer AGC

CTL Printed Circuit Board (PCB) A

The A board contains the clock (CLK), the scaler (SCL), and the time pulse generator (TPG).

Page 118: Apollo Guidance Computer AGC

CTL Printed Circuit Board (PCB) B

The B board contains the display indicators, their current-limiting resistor networks, and the

open collector drivers. The display panel is a sheet of white styrene plastic. A push pin was

used to make holes through the plastic, and the LEDs were inserted in rows. The panel was

hand-lettered with an indelible marker. A few chips near the bottom right of the B board are

associated with subsystems on the C board.

Page 119: Apollo Guidance Computer AGC

CTL Printed Circuit Board (PCB) C

The C board contains the sequence generator (SEQ) and control pulse matrixes (CPM-A,

CPM-B, and CPM-C). The big ICs at the bottom are the EPROMs that hold the control pulse

matrix table for CPM-A. Each EPROM holds the tables for 8 control signals. The large ICs at

the top are decoders for the CPM-B and CPM-C logic.

Page 120: Apollo Guidance Computer AGC

Parts (ICs)

74LS00 (14) U74,U26,U27,U25,U79,U78,U55,U54,U53,U48,U13,U42,U34,U28

74LS02 (9) U4,U77,U9,U73,U45,U43,U3,U38,U32

74LS04 (15) U62,U29,U76,U69,U64,U57,U71,U59,U58,U56,U49,U41,U40,U39,U33

74LS06 (11) U22,U21,U20,U23,U14,U17,U18,U19,U16,U15,U1

74LS08 (2) U65,U10

74LS10 (4) U12,U70,U52,U51

74LS20 (8) U67,U68,U66,U63,U75,U61,U60,U6

74LS27 (3) U7,U44,U2

74LS32 (3) U72,U11,U5

74LS74 (1) U24

74LS112 (8) U8,U50,U47,U46,U35,U36,U37,U31

74LS138 (1) U99

74LS154 (7) U81,U82,U83,U98,U100,U101,U106

74LS161 (8) U104,U107,U108,U109,U110,U111,U112,U113

74LS244 (10) U80,U84,U85,U93,U94,U95,U96,U97,U102,U103

74LS273 (1) U105

27C128 (7) U86,U87,U88,U89,U90,U91,U92

4001 (1) U30

555 (1) U114

IC’s, sockets, PCB’s, resistors, capacitors, wire-wrap wire were purchased from JAMECO. The

2.048 MHz crystal and the IDE wire-wrap were from DigiKey. Wire ties, wire-wrap tools, and

copper wire were purchased from Radio Shack. IDE ribbon cables were purchased from an

online computer supplier.

Power Budget

qty mA (ea) mA (tot)

74LS00 14 2.4 33.6

74LS02 9 2.4 21.6

74LS04 15 3.6 54.0

74LS06 11 3.6 39.6

74LS08 2 4.4 8.8

74LS10 4 1.8 7.2

74LS20 8 1.2 9.6

74LS27 3 3.4 10.2

74LS32 3 4.9 14.7

74LS74 1 4.0 4.0

74LS112 8 4.0 32.0

74LS138 1 6.3 6.3

74LS154 7 6.2 43.4

74LS161 8 19.0 152.0

74LS244 10 32.0 320.0

74LS273 1 17.0 17.0

27C128 7 25.0 175.0

4001 1 0.4 0.4

555 1 3.0 3.0

LED 61 20.0 1220.0

Page 121: Apollo Guidance Computer AGC

-------

2.2 Amps total

1.0 Amps (excluding LEDs)

Page 122: Apollo Guidance Computer AGC

EPROM generator program

This C++ program generates all files needed to program the CPM-A EPROMs. The files are

generated in Motorola S-Record format.

/*

****************************************************************

*

* CPM-A EPROM GENERATOR

*

*9/14/01

*

*****************************************************************

Versions:

Derived from AGC C++ simulator 1.15.

Operation:

Generates all of the CPM-A EPROM files in Motorola s2f S-Record format

suitable for EPROM program mers.

*/

#include <str ing.h>

#include <stdlib.h>

#include <ctype.h>

#include <iostream.h>

#include <stdio.h>

#define MAXPULSES 15

#de fine M AX_IPULSES 5 // no m ore than 5 ins tru ct ion -gen erated pu lses act ive at any t ime

enum cpType { // **inferred; not defined in orignal R393 AGC 4 spec.

NO_PULSE=0,

// OUTPUTS FROM SUBSYSTEM A

CI =1, // C ar ry in

CLG =2, // Clear G

CLCTR =3, // Clear loop counter

CTR =4, // Loop counter

GP =5, // Gen erate Parity

KRPT =6, // Knock dow n Ru pt priority

NISQ =7, // New instruction to the SQ register

RA =8, // Read A

RB =9, // Read B

RB14 =10, // Read bit 14

RC =11, // Read C

RG =12, // Read G

RLP =13, // Read LP

RP2 =14, // Read parity 2

RQ =15, // Read Q

RRPA =16, // Read RU PT add ress

RSB =17, // R ead s ign bit

RSCT =18, // Read selected cou nter addre ss

RU =19, // Read sum

RZ =20, // Read Z

R1 =21, // Read 1

R1C =22, // Read 1 complimented

R2 =23, // Read 2

R22 =24, // Read 22

R24 =25, // Read 24

ST1 =26, // Stage 1

ST2 =27, // Stage 2

TMZ =28, // Test for minus zero

TOV =29, // Test for overflow

TP =30, // Test parity

TRSM =31, // Tes t fo r resume

TSGN =32, // Test sign

TSGN2 =33, // Test sign 2

WA =34, // Write A

Page 123: Apollo Guidance Computer AGC

WA LP =35, // Write A and LP

WB =36, // Write B

WGx =37, // Write G (do no t reset)

WLP =38, // Write LP

WOVC =39, // Write overf low counter

WOVI =40, // W rite over flow RU PT inh ibit

WOVR =41, // Write overflow

WP =42, // Write P

WPx =43, // Write P (do no t reset)

WP2 =44, // Write P2

WQ =45, // Write Q

WS =46, // Write S

WX =47, // Write X

WY =48, // Write Y

WYx =49, // Write Y (do no t reset)

WZ =50, // Write Z

// OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM B ONLY;

// NOT USED OUTS IDE CPM

RSC =51, // Read special and central (output to B only, not outside CPM)

WSC =52, // Write special and central (output to B only, not outside CPM)

WG =53, // Wr ite G (output to B only , not outs ide CPM)

// OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM C ONLY;

// NOT USED OUTS IDE CPM

SDV1 =54, // Subsequence D V1 is currently active

SMP1 =55, // Subsequence M P1 is currently active

SRSM3 =56, // Subsequence RS M3 is currently active

// EXTERNAL OUTPUTS FROM SUBSYSTEM B

//

RA0 =57, // Read register at address 0 (A)

RA1 =58, // Read reg is ter a t address 1 (Q)

RA2 =59, // Read register at address 2 (Z)

RA3 =60, // Read register at address 3 (LP)

RA4 =61, // Read reg ister at address 4

RA5 =62, // Read reg ister at address 5

RA6 =63, // Read reg ister at address 6

RA7 =64, // Read reg ister at address 7

RA10 =65, // R ead reg iste r a t add ress 10 (octal)

RA11 =66, // R ead reg iste r a t add ress 11 (octal)

RA12 =67, // R ead reg iste r a t add ress 12 (octal)

RA13 =68, // R ead reg iste r a t add ress 13 (octal)

RA14 =69, // R ead reg iste r a t add ress 14 (octal)

RBK =70, // Read BNK

WA0 =71, // Write register at address 0 (A)

WA1 =72, // Wr ite reg is ter a t address 1 (Q)

WA2 =73, // Write register at address 2 (Z)

WA3 =74, // Write register at address 3 (LP)

WA10 =75, // W rite regis ter a t add ress 10 (octal)

WA11 =76, // W rite regis ter a t add ress 11 (octal)

WA12 =77, // W rite regis ter a t add ress 12 (octal)

WA13 =78, // W rite regis ter a t add ress 13 (octal)

WA14 =79, // W rite regis ter a t add ress 14 (octal)

WBK =80, // Write BNK

WGn =81, // Write G (normal gates)**

W20 =82, // Write into CYR

W21 =83, // Write into SR

W22 =84, // Write into CYL

W23 =85, // Write into SL

// THESE ARE THE LEFTOVERS -- THEY 'RE PROBABLY USED IN SUBSYSTEM C

//

GENRST =86, // General Reset**

CLINH =87, // Clear INHINT**

CLINH1 =88, // Clear INHINT1**

CLSTA =89, // Clear state counter A (STA)**

CLSTB =90, // Clear state counter B (STB)**

CLISQ =91, // Clear SNI**

CLRP =92, // Clear RPCELL**

INH =93, // Set INHINT**

RPT =94, // Read RUPT opcode **

SBWG =95, // Write G from m emory

SETSTB =96, // Set the ST1 bit of STB

Page 124: Apollo Guidance Computer AGC

WE =97, // Wr ite E-MEM from G

WPCTR =98, // Write PCTR (latch priority counter sequence)**

WSQ =99, // Write SQ

WSTB =100, // Write stage counter B (STB)**

R2000 =101, // Read 2000 **

};

stat ic cpType glb l_cp[MAXPULSES]; // current set of asserted control pulses (MAXPULSES)

enum scType { // identif ies subsequence for a given instruction

SUB0=0, // ST2=0, ST1=0

SUB1=1, // ST2=0, ST1=1

SUB2=2, // ST2=1, ST1=0

SUB3=3 // ST2=1, ST1=1

};

enum brType {

BR00 =0, // BR1=0, BR2=0

BR01 =1, // BR1=0, BR2=1

BR10 =2, // BR1=1, BR2=0

BR11 =3, // BR1=1, BR2=1

NO_BR =4 // NO BRANCH

};

struct controlSubStep {

brType br; // normally no branch (NO_BR)

cpType pulse[MAX_IPULSES]; // contains 0 - MAXPULSES control pulses

};

struct controlStep {

controlSubStep substep[4]; // indexed by brType (BR00, BR01, BR10, BR11)

};

struct subsequence {

controlStep tp[11]; // indexed by tpType (TP1-TP11)

};

struct sequence {

subsequence* subseq[4]; // indexed by scType

};

#define STEP_INACTIVE \

NO_BR, {NO_ PULSE , NO _PU LSE , NO _PU LSE , NO _PU LSE , NO _PU LSE }, \

NO_BR, {NO_ PULSE , NO _PU LSE , NO _PU LSE , NO _PU LSE , NO _PU LSE }, \

NO_BR, {NO_ PULSE , NO _PU LSE , NO _PU LSE , NO _PU LSE , NO _PU LSE }, \

NO_BR, {NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE}

#de fine STE P(p1 , p2, p3 , p4, p5 ) \

NO_BR, { p1 , p2, p3, p4 , p5} , \

NO_BR, {NO_ PULSE , NO _PU LSE , NO _PU LSE , NO _PU LSE , NO _PU LSE }, \

NO_BR, {NO_ PULSE , NO _PU LSE , NO _PU LSE , NO _PU LSE , NO _PU LSE }, \

NO_BR, {NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE}

subsequence SUB_TC0 = {

STEP ( RB, WY, WS, CI, NO_PULSE ), // TP 1

STEP_INACTIVE, // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP ( RA, WOV I, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 4

STEP_INACTIVE, // TP 5

STEP_INACTIVE, // TP 6

STEP ( RG, RSC, WB, WP, NO_PULSE ), // TP 7

STEP ( RZ, WQ, GP, TP, NO_PULSE ), // TP 8

STEP ( RB, WSC, WG, NO_PULSE, NO_PULSE ), // TP 9

STEP ( RU, WZ, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 10

STEP ( NISQ, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 11

};

subsequence SUB_CCS0 = {

STEP ( RB, WS, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP ( RZ, WY, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP_INACTIVE, // TP 4

STEP_INACTIVE, // TP 5

STEP ( RG, RSC, WB, TSGN, WP ), // TP 6

BR00, RC, TMZ, NO_PULSE, NO_PULSE, NO_PULSE, // TP 7

BR01, RC, TMZ, NO_PULSE, NO_PULSE, NO_PULSE,

Page 125: Apollo Guidance Computer AGC

BR10, RB, TMZ, NO_PULSE, NO_PULSE, NO_PULSE,

BR11, RB, TMZ, NO_PULSE, NO_PULSE, NO_PULSE,

BR00, GP, TP, NO_PULSE, NO_PULSE, NO_PULSE, // TP 8

BR01, R1, WX, GP, TP, NO_PULSE,

BR10, R2, WX, GP, TP, NO_PULSE,

BR11, R1, R2, WX, GP, TP,

STEP ( RB, WSC, WG, NO_PULSE, NO_PULSE ), // TP 9

BR00, RC, WA, NO_PULSE, NO_PULSE, NO_PULSE, // TP 10

BR01, WA, R1C, NO_PULSE, NO_PULSE, NO_PULSE,

BR10, RB, WA, NO_PULSE, NO_PULSE, NO_PULSE,

BR11, WA, R1C, NO_PULSE, NO_PULSE, NO_PULSE,

STEP ( RU, ST1, WZ, NO_PULSE, NO_PULSE ) // TP 11

};

subsequence SUB_CCS1 = {

STEP ( RZ, WY, WS, CI, NO_PULSE ), // TP 1

STEP_INACTIVE, // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP ( RU, WZ, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 4

STEP ( RA, WY, CI, NO_PULSE, NO_PULSE ), // TP 5

STEP_INACTIVE, // TP 6

STEP ( RG, RSC, WB, WP, NO_PULSE ), // TP 7

STEP ( RU, WB, GP, TP, NO_PULSE ), // TP 8

STEP_INACTIVE, // TP 9

STEP ( RC, WA, WOV I, NO_PULSE, NO_PULSE ), // TP 10

STEP ( RG, RSC, WB, NISQ, NO_PULSE ) // TP 11

};

subsequence SUB_NDX0 = {

STEP ( RB, WS, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP_INACTIVE, // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP ( RA, WOV I, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 4

STEP_INACTIVE, // TP 5

STEP_INACTIVE, // TP 6

STEP ( RG, RSC, WB, WP, NO_PULSE ), // TP 7

STEP ( GP, TP, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 8

STEP ( RB, WSC, WG, NO_PULSE, NO_PULSE ), // TP 9

STEP ( TRSM, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 10

STEP ( ST1, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 11

};

subsequence SUB_NDX1 = {

STEP ( RZ, WY, WS, CI, NO_PULSE ), // TP 1

STEP_INACTIVE, // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP ( RU, WZ, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 4

STEP_INACTIVE, // TP 5

STEP ( RB, WY, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 6

STEP ( RG, RSC, WB, WP, NO_PULSE ), // TP 7

STEP ( RB, WX, GP, TP, NO_PULSE ), // TP 8

STEP ( RB, WSC, WG, NO_PULSE, NO_PULSE ), // TP 9

STEP_INACTIVE, // TP 10

STEP ( RU, WB, WOV I, NISQ, NO_PULSE ), // TP 11

};

subsequence SUB_RSM3 = {

STEP ( R24, WS, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP_INACTIVE, // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP_INACTIVE, // TP 4

STEP_INACTIVE, // TP 5

STEP_INACTIVE, // TP 6

STEP ( RG, WZ, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 7

STEP_INACTIVE, // TP 8

STEP_INACTIVE, // TP 9

STEP_INACTIVE, // TP 10

STEP ( NISQ, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 11

};

subsequence SUB_XCH0 = {

STEP ( RB, WS, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP ( RA, WP, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP ( WP2, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 4

STEP_INACTIVE, // TP 5

Page 126: Apollo Guidance Computer AGC

STEP_INACTIVE, // TP 6

STEP ( RG, RSC, WB, WP, NO_PULSE ), // TP 7

STEP ( GP, TP, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 8

STEP ( RA, WSC, WG, RP2, NO_PULSE ), // TP 9

STEP ( RB, WA, WOV I, NO_PULSE, NO_PULSE ), // TP 10

STEP ( ST2, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 11

};

subsequence SUB_CS0 = {

STEP ( RB, WS, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP_INACTIVE, // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP_INACTIVE, // TP 4

STEP_INACTIVE, // TP 5

STEP_INACTIVE, // TP 6

STEP ( RG, RSC, WB, WP, NO_PULSE ), // TP 7

STEP ( GP, TP, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 8

STEP ( RB, WSC, WG, NO_PULSE, NO_PULSE ), // TP 9

STEP ( RC, WA, WOV I, NO_PULSE, NO_PULSE ), // TP 10

STEP ( ST2, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 11

};

subsequence SUB_TS0 = {

STEP ( RB, WS, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP ( RA, WB, TOV, WP, NO_PULSE

), // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

BR00, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, // TP 4

BR01, RZ, WY, CI, NO_PULSE, NO_PULSE, //

overflow

BR10, RZ, WY, CI, NO_PULSE, NO_PULSE, //

underflow

BR11, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

BR00, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, // TP 5

BR01, R1, WA, NO_PULSE, NO_PULSE, NO_PULSE,

BR10, WA, R1C, NO_PULSE, NO_PULSE, NO_PULSE,

BR11, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

STEP_INACTIVE, // TP 6

BR00, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, // TP 7

BR01, RU, WZ, NO_PULSE, NO_PULSE, NO_PULSE,

BR10, RU, WZ, NO_PULSE, NO_PULSE, NO_PULSE,

BR11, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

STEP ( GP, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 8

STEP ( RB, WSC, WG, NO_PULSE, NO_PULSE

), // TP 9

STEP ( RA, WOV I, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 10

STEP ( ST2, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 11

};

subsequence SUB_AD0 = {

STEP ( RB, WS, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP ( RA, WY, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP_INACTIVE, // TP 4

STEP_INACTIVE, // TP 5

STEP_INACTIVE, // TP 6

STEP ( RG, RSC, WB, WP, NO_PULSE ), // TP 7

STEP ( RB, WX, GP, TP, NO_PULSE ), // TP 8

STEP ( RB, WSC, WG, NO_PULSE, NO_PULSE ), // TP 9

STEP_INACTIVE, // TP 10

STEP ( RU, WA, WOVC, ST2, WOVI ), // TP 11

};

// No te: AND is perfo rmed u sing D eM orga n's Theorem: the inpu ts are inver ted , a

// logical OR is performed, and the result is inverted. The implementation of the

// OR (at TP8 ) is somewh at unorthodox: the inverted inpu ts are in registers U

// and C. The OR is achieved by gating both registers onto the read/write bus

// simu ltaneously. (The bus on ly transfers logical 1's; register-to-register transfers

// are performed by clearing the destination register and then transferr ing the

// 1's from the source register to th e destination). When the 1 's from both

// registers are simultaneously gated onto the bus, the word on the bus is a logical

// OR of both reg isters.

subsequence SUB_MASK0 = {

STEP ( RB, WS, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP ( RA, WB, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

Page 127: Apollo Guidance Computer AGC

STEP ( RC, WY, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 4

STEP_INACTIVE, // TP 5

STEP_INACTIVE, // TP 6

STEP ( RG, RSC, WB, WP, NO_PULSE ), // TP 7

STEP ( RU, RC, WA, GP, TP ), // TP 8

(CHANGED)

STEP_INACTIVE, // TP 9

STEP ( RA, WB, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 10

(CHANGED)

STEP ( RC, WA, ST2, WOV I, NO_PULSE ), // TP 11

};

subsequence SUB_MP0 = {

STEP ( RB, WS, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP ( RA, WB, TSGN, NO_PULSE, NO_PULSE ), // TP 2

STEP ( RSC, WG, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

BR00, RB, WLP, NO_PULSE, NO_PULSE, NO_PULSE, // TP 4

BR01, RB, WLP, NO_PULSE, NO_PULSE, NO_PULSE,

BR10, RC, WLP, NO_PULSE, NO_PULSE, NO_PULSE,

BR11, RC, WLP, NO_PULSE, NO_PULSE, NO_PULSE,

STEP ( RLP, WA, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 5

STEP_INACTIVE, // TP 6

BR00, RG, WY, WP, NO_PULSE, NO_PULSE, // TP 7

BR01, RG, WY, WP, NO_PULSE, NO_PULSE,

BR10, RG, WB, WP, NO_PULSE, NO_PULSE,

BR11, RG, WB, WP, NO_PULSE, NO_PULSE,

BR00, GP, TP, NO_PULSE, NO_PULSE, NO_PULSE, // TP 8

BR01, GP, TP, NO_PULSE, NO_PULSE, NO_PULSE,

BR10, RC, WY, GP, TP, NO_PULSE,

BR11, RC, WY, GP, TP, NO_PULSE,

STEP ( RU, WB, TSGN2, NO_PULSE, NO_PULSE ), // TP 9

BR00, RA, WLP, TSGN, NO_PULSE, NO_PULSE, // TP 10

BR01, RA, RB14, WLP, TSGN, NO_PULSE,

BR10, RA, WLP, TSGN, NO_PULSE, NO_PULSE,

BR11, RA, RB14, WLP, TSGN, NO_PULSE,

BR00, ST1, WALP, NO_PULSE, NO_PULSE, NO_PULSE, // TP 11

BR01, R1, ST1, WALP, R1C, NO_PULSE,

BR10, RU, ST1, WALP, NO_PULSE, NO_PULSE,

BR11, RU, ST1, WALP, NO_PULSE, NO_PULSE,

};

subsequence SUB_MP1 = {

STEP ( RA, WY, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP ( RLP, WA, TSGN, NO_PULSE, NO_PULSE ), // TP 2

BR00, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, // TP 3

BR01, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

BR10, RB, WX, NO_PULSE, NO_PULSE, NO_PULSE,

BR11, RB, WX, NO_PULSE, NO_PULSE, NO_PULSE,

STEP ( RA, WLP, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 4

STEP ( RLP, TSGN, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 5

STEP ( RU, WALP, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 6

STEP ( RA, WY, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 7

BR00, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, // TP 8

BR01, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

BR10, RB, WX, NO_PULSE, NO_PULSE, NO_PULSE,

BR11, RB, WX, NO_PULSE, NO_PULSE, NO_PULSE,

STEP ( RLP, WA, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 9

STEP ( RA, WLP, CTR, NO_PULSE, NO_PULSE ), // TP 10

STEP ( RU, ST1, WALP, NO_PULSE, NO_PULSE ), // TP 11

};

subsequence SUB_MP3 = {

STEP ( RZ, WY, WS, CI, NO_PULSE ), // TP 1

STEP ( RLP, TSGN, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP ( RU, WZ, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 4

STEP ( RA, WY, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 5

BR00, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, // TP 6

BR01, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

BR10, RB, WX, NO_PULSE, NO_PULSE, NO_PULSE,

BR11, RB, WX, NO_PULSE, NO_PULSE, NO_PULSE,

STEP ( RG, RSC, WB, WP, NO_PULSE ), // TP 7

STEP ( RLP, WA, GP, TP, NO_PULSE ), // TP 8

STEP ( RB, WSC, WG, NO_PULSE, NO_PULSE ), // TP 9

STEP ( RA, WLP, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 10

STEP ( RU, WALP, NISQ, NO_PULSE, NO_PULSE ), // TP 11

Page 128: Apollo Guidance Computer AGC

};

subsequence SUB_DV0 = {

STEP ( RB, WS, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP ( RA, WB, TSGN, NO_PULSE, NO_PULSE ), // TP 2

STEP ( RSC, WG, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

BR00, RC, WA, NO_PULSE, NO_PULSE, NO_PULSE, // TP 4

BR01, RC, WA, NO_PULSE, NO_PULSE, NO_PULSE,

BR10, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

BR11, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

BR00, R1, WLP, NO_PULSE, NO_PULSE, NO_PULSE, // TP 5

BR01, R1, WLP, NO_PULSE, NO_PULSE, NO_PULSE,

BR10, R2, WLP, NO_PULSE, NO_PULSE, NO_PULSE,

BR11, R2, WLP, NO_PULSE, NO_PULSE, NO_PULSE,

STEP ( RA, WQ, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 6

STEP ( RG, WB, TSGN, WP, NO_PULSE ), // TP 7

STEP ( RB, WA, GP, TP, NO_PULSE ), // TP 8

BR00, RLP, R2, WB, NO_PULSE, NO_PULSE, // TP 9

BR01, RLP, R2, WB, NO_PULSE, NO_PULSE,

BR10, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

BR11, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

BR00, RB, WLP, NO_PULSE, NO_PULSE, NO_PULSE, // TP 10

BR01, RB, WLP, NO_PULSE, NO_PULSE, NO_PULSE,

BR10, RC, WA, NO_PULSE, NO_PULSE, NO_PULSE,

BR11, RC, WA, NO_PULSE, NO_PULSE, NO_PULSE,

STEP ( R1, ST1, WB, NO_PULSE, NO_PULSE ), // TP 11

};

subsequence SUB_DV1 = {

STEP ( R22, WS, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP ( RQ, WG, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 2

STEP ( RG, WQ, WY, RSB, NO_PULSE ), // TP 3

STEP ( RA, WX, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 4

STEP ( RLP, TSGN2, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 5

STEP_INACTIVE, // TP 6

STEP ( RU, TSGN, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 7

BR00, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, // TP 8

BR01, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

BR10, RU, WQ, NO_PULSE, NO_PULSE, NO_PULSE,

BR11, RU, WQ, NO_PULSE, NO_PULSE, NO_PULSE,

BR00, RB, RSB, WG, NO_PULSE, NO_PULSE, // TP 9

BR01, RB, RSB, WG, NO_PULSE, NO_PULSE,

BR10, RB, WG, NO_PULSE, NO_PULSE, NO_PULSE,

BR11, RB, WG, NO_PULSE, NO_PULSE, NO_PULSE,

STEP ( RG, WB, TSGN, NO_PULSE, NO_PULSE ), // TP 10

BR00, ST1, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, // TP 11

BR01, ST1, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

BR10, RC, WA, ST2, NO_PULSE, NO_PULSE,

BR11, RB, WA, ST2, NO_PULSE, NO_PULSE,

};

subsequence SUB_SU0 = {

STEP ( RB, WS, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP ( RA, WY, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP_INACTIVE, // TP 4

STEP_INACTIVE, // TP 5

STEP_INACTIVE, // TP 6

STEP ( RG, RSC, WB, WP, NO_PULSE ), // TP 7

STEP ( RC, WX, GP, TP, NO_PULSE ), // TP 8

STEP ( RB, WSC, WG, NO_PULSE, NO_PULSE ), // TP 9

STEP_INACTIVE, // TP 10

STEP ( RU, WA, WOVC, ST2, WOVI ), // TP 11

};

subsequence SUB_RUPT1 = {

STEP ( R24, WY, WS, CI, NO_PULSE ), // TP 1

STEP_INACTIVE, // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP_INACTIVE, // TP 4

STEP_INACTIVE, // TP 5

STEP_INACTIVE, // TP 6

STEP_INACTIVE, // TP 7

STEP_INACTIVE, // TP 8

STEP ( RZ, WG, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 9

STEP ( RU, WZ, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 10

Page 129: Apollo Guidance Computer AGC

STEP ( ST1, ST2, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 11

};

subsequence SUB_RUPT3 = {

STEP ( RZ, WS, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP ( RRPA, WZ, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 2

STEP ( RZ, KRPT, WG, NO_PULSE, NO_PULSE ), // TP 3

STEP_INACTIVE, // TP 4

STEP_INACTIVE, // TP 5

STEP_INACTIVE, // TP 6

STEP_INACTIVE, // TP 7

STEP_INACTIVE, // TP 8

STEP ( RB, WSC, WG, NO_PULSE, NO_PULSE ), // TP 9

STEP_INACTIVE, // TP 10

STEP ( ST2, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 11

};

subsequence SUB_STD2 = {

STEP ( RZ, WY, WS, CI, NO_PULSE ), // TP 1

STEP_INACTIVE, // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP ( RU, WZ, NO_PULSE, NO_PULSE, NO_PULSE ), // TP

STEP_INACTIVE, // TP 5

STEP_INACTIVE, // TP 6

STEP ( RG, RSC, WB, WP, NO_PULSE ), // TP 7

STEP ( GP, TP, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 8

STEP ( RB, WSC, WG, NO_PULSE, NO_PULSE ), // TP 9

STEP_INACTIVE, // TP 10

STEP ( NISQ, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 11

};

subsequence SUB_PINC = {

STEP ( WS, RSCT, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP_INACTIVE, // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP ( R1, WY, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 4

STEP_INACTIVE, // TP 5

STEP ( RG, WX, WP, NO_PULSE, NO_PULSE ), // TP 6

STEP ( TP, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 7

STEP ( WP, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 8

STEP ( RU, CLG, WPx, NO_PULSE, NO_PULSE ), // TP 9

STEP ( RU, WG x, WOVR, NO_PULSE, NO_PULSE ), // TP 10

STEP_INACTIVE, // TP 11

};

subsequence SUB_MINC = {

STEP ( WS, RSCT, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP_INACTIVE, // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP ( WY, R1C, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 4

STEP_INACTIVE, // TP 5

STEP ( RG, WX, WP, NO_PULSE, NO_PULSE ), // TP 6

STEP ( TP, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 7

STEP ( WP, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 8

STEP ( RU, CLG, WPx, NO_PULSE, NO_PULSE ), // TP 9

STEP ( RU, WG x, WOVR, NO_PULSE, NO_PULSE ), // TP 10

STEP_INACTIVE, // TP 11

};

subsequence SUB_SHINC = {

STEP ( WS, RSCT, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 1

STEP_INACTIVE, // TP 2

STEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 3

STEP ( WY, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 4

STEP_INACTIVE, // TP 5

STEP ( RG, WYx, WX, WP, NO_PULSE ), // TP 6

STEP ( TP, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 7

STEP ( WP, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE ), // TP 8

STEP ( RU, CLG, WPx, NO_PULSE, NO_PULSE ), // TP 9

STEP ( RU, WG x, WOVR, NO_PULSE, NO_PULSE ), // TP 10

STEP_INACTIVE, // TP 11

};

char* subse qString [] =

{

"TC0",

Page 130: Apollo Guidance Computer AGC

"CCS0 ",

"CCS1 ",

"NDX0 ",

"NDX1 ",

"RSM3 ",

"XCH0",

"CS0",

"TS0",

"AD0",

"MAS K0",

"MP0",

"MP1",

"MP3",

"DV0",

"DV1",

"SU0",

"RUPT1",

"RUPT3",

"STD2 ",

"PINC0",

"MINC0",

"SHINC0 ",

"NO_SEQ"

};

enum subseq {

TC0 =0,

CCS0 =1,

CCS1 =2,

NDX0 =3,

NDX1 =4,

RSM3 =5,

XCH0 =6,

CS0 =7,

TS0 =8,

AD0 =9,

MASK0 =10,

MP0 =11,

MP1 =12,

MP3 =13,

DV0 =14,

DV1 =15,

SU0 =16,

RUPT1 =17,

RUPT3 =18,

STD2 =19,

PINC0 =20,

MINC0 =21,

SHINC0 =22,

NO_SEQ =23

};

enum tpType {

STBY =0,

PWRON =1,

TP1 =2, // TIME PULSE 1: start of memory cycle t ime (MCT)

TP2 =3,

TP3 =4,

TP4 =5,

TP5 =6,

TP6 =7, // EMEM is available in G register by TP6

TP7 =8, // FMEM is available in G register by TP7

TP8 =9,

TP9 =10,

TP10 =11, // G register written to memory beginning at TP10

TP11 =12, // TIME PULSE 11: end of memory cycle t ime (MCT)

TP12 =13, // select new subsequence/select new instruction

SRLSE =14, // step switch release

WAIT =15

};

subseq instructionSubsequenceD ecoder(

int SB2_field, int SB1_field, int SQ_field, int STB_field)

Page 131: Apollo Guidance Computer AGC

{

// Com binationa l logic decodes instru ction and the stage coun t

// to get the instruction subsequence.

static subseq decode[16][4] = {

{ TC0, RUPT1, STD2, RUPT3 }, // 00

{ CCS0, CCS1, NO_SEQ, NO_SEQ }, // 01

{ NDX0, NDX1, NO_SEQ, RSM3 }, // 02

{ XCH0, NO_SEQ, STD2, NO_SEQ }, // 03

{ NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ }, // 04

{ NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ }, // 05

{ NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ }, // 06

{ NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ }, // 07

{ NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ }, // 10

{ MP0, MP1, NO_SEQ, MP3 }, // 11

{ DV0, DV1, STD2, NO_SEQ }, // 12

{ SU0, NO_SEQ, STD2, NO_SEQ }, // 13

{ CS0, NO_SEQ, STD2, NO_SEQ }, // 14

{ TS0, NO_SEQ, STD2, NO_SEQ }, // 15

{ AD0, NO_SEQ, STD2, NO_SEQ }, // 16

{ MASK0, NO_SEQ, STD2, NO_SEQ } // 17

};

if(SB2_field == 0 && SB1_field == 1)

return PINC0;

else if(SB2_field == 1 && SB1_field == 0)

return MINC0;

else

return decode[SQ_ field][STB_ field];

}

void clearControlPu lses()

{

for(unsigned i=0; i<MAXPULSES; i++)

glbl_cp[i] = NO_PULSE;

}

void assert(cpType* pulse)

{

int j=0;

for(unsigned i=0; i<MAXPULSES && j<MAX_IPULSES && pulse[j] != NO_PULSE; i++)

{

if(glbl_cp[i] == NO_PULSE)

{

glbl_cp[i] = pu lse[j];

j++;

}

}

}

void assert(cpType pulse)

{

for(unsigned i=0; i<MAXPULSES; i++)

{

if(glbl_cp[i] == NO_PULSE)

{

glbl_cp[i] = pulse;

break;

}

}

}

void get_CPM_A (int CPM_A _addre ss)

{

// EPROM address bits (bit 1 is LSB)

// 1: register BR2

// 2: register BR1

// 3-6: register SG (4)

// 7,8: register STB (2)

// 9-12: register SQ (4)

// 13: STB_01

// 14: STB_02

Page 132: Apollo Guidance Computer AGC

//***********************************************************

// EPROM emulator

int SB2_field = (CPM_A_address >> 13) & 0x1;

int SB1_field = (CPM_A_address >> 12) & 0x1;

int SQ_ field = (CPM _A_address >> 8 ) & 0 xf;

int STB_field = (CPM_A_address >> 6) & 0x3;

int SG_ field = (CPM _A_address >> 2 ) & 0 xf;

int BR1_field = (CPM_A_address >> 1) & 0x1;

int BR2_field = (CPM_A_address ) & 0x1;

// Decode the cu rrent instru ction subsequ ence (glbl_subse q).

subse q glbl_subseq = instructionSubse quenceD ecoder(SB 2_field, SB1_field, SQ _field, STB_field);

static subsequence* subsp[] =

{

&SUB_TC0, &SUB_CCS0, &SUB_CCS1, &SUB_NDX0, &SUB_NDX1, &SUB_RSM3,

&SUB_XCH0, &SUB_CS0, &SUB_TS0, &SUB_AD0, &SUB_MASK0, &SUB_MP0,

&SUB_MP1, &SUB_MP3, &SUB_DV0, &SUB_DV1, &SUB_SU0, &SUB_RUPT1,

&SUB_RUPT3, &SUB_STD2, &SUB_PINC, &SUB_MINC, &SUB_SHIN C,0

};

// Clear old control pulses.

clearControlPulses ();

// Get new control pulses for the current instruction subsequence.

if(glb l_subseq != NO_SEQ && // THIS TESTS OUT OK

SG_fie ld >= TP1 &&

SG_field <= TP11)

{

subse quence* subseqP = subsp [glbl_subse q];

if(subseqP)

{

// index t-2 because TP1= 2, but array is indexed from zero

contro lStep& csref = subse qP-> tp[SG _field-2];

brTyp e b = (brType) ((BR1_field << 1) | BR2_field);

contro lSubS tep& cssref = csref.substep[b ];

if(cssref.br == NO_BR)

cssref = csref.substep[0 ];

cpType* p = cssref.pulse;

asser t(p);

}

}

// Implement these h ere, becau se the instruction sequence de coder

// function is buried in the CPM-A ROM and so, identif ication of

// the se quences is no t availab le ou tside CPM-A. CPM-C needs info

// on these 3 sequences.

switch(glbl_subseq)

{

case DV1: assert(SDV1); break;

case MP1: assert(SMP1); break;

case RSM3: assert(SRSM3); break;

}

//***********************************************************

}

char* cpTypeStr ing[] =

{

"NO_PU LSE",

/ / OUTPUTS FROM SUBSYSTEM A

"CI" , "CLG" , "CLCTR", "C TR", "GP", "K RPT ", "NISQ ", "RA ", "RB ",

"RB 14", "RC ", "RG ", "RLP", "R P2" , "RQ ", "RR PA", "RS B", "RSCT ",

"RU ", "RZ ", "R1 ", "R1 C", "R2", "R2 2", "R 24", "ST1", "ST2", "TM Z",

"TO V", "TP" , "TRSM ", "TS GN ", "TS GN 2", "W A", "WALP ", "W B", "WGx",

"WLP", "WOV C", "WOV I", "W OV R", "W P", "W Px" , "WP2" , "WQ", "WS",

"WX", "WY", "WYx", "WZ",

// OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM B ONLY;

// NOT USED OUTS IDE CPM

Page 133: Apollo Guidance Computer AGC

//

"RSC", "WS C", "WG",

// OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM C ONLY;

// NOT USED OUTS IDE CPM

//

"SDV1 ", "SMP1", "SRSM 3",

/ / EXTERNAL OUTPUTS FROM SUBSYSTEM B

//

"RA 0", "R A1", "RA 2", "R A3", "RA 4", "R A5", "RA 6", "R A7", "RA 10", "RA 11",

"RA 12", "RA 13", "RA 14", "RB K", "W A0", "W A1", "W A2", "W A3", "W A10",

"WA1 1", "WA12", "WA 13", "WA14 ", "WBK", "WG n", "W20", "W21 ", "W22", "W23",

/ / THESE ARE THE LEFTOVERS -- THEY 'RE PROBABLY USED IN SUBSYSTEM C

//

"GENRST", "C LINH ", "CLINH 1", "C LST A", "CLSTB", "CLISQ ", "CLRP ", "INH" ,

"RPT", "SBWG", "SETSTB", "WE", "WPCTR", "WSQ", "WSTB", "R2000"

};

// for debug purposes only

char* printControlPulses ()

{

static char buf[MA XPU LSES*6 ];

strcpy(buf,"");

for(unsigned i=0; i<MAXPULSES && g lb l_cp[ i] != NO_PULSE; i++)

{

strcat(bu f, cpTypeString[g lbl_cp[i]]);

strcat(bu f," ");

}

//if(strcmp(bu f,"") == 0) strcat(buf,"NO NE" );

return bu f;

}

// return the EPROM word corresponding to the pulses

// in glbl_cp.

unsigned w riteEPROM (int lowBit)

{

un signe d EPROMword = 0x00 ; // no pu lses; de fault

for(unsigned i=0; i<MAXPULSES && g lb l_cp[ i] != NO_PULSE; i++)

{

int pulse = glbl_cp[i] - lowBit;

if(pulse < 0 || pulse > 7)

continue; // pulse is not in this EPROM

EPROMword |= 0x01 << pulse;

}

// printf("%02X \n",EPROMw ord);

//return EPROMword;

// The CPM -A con trol signals are nega tive logic, so we n eed to

// b it-f lip the word. No signa l is a 1, and an a sser ted s ignal is

// a 0:

return ((~EP ROMw ord) & 0xff);

}

const unsigned agcMem Size = 0x3fff+1; // # of cells in a 16-bit address range

void writeEPRO M(FILE * fpObj, int lowBit)

{

// Write an EPROM file using M otorola's S -Reco rd form at (s2f).

// Some parameters that control f ile format. You can change maxBytes

// without affecting anything else. 'addressBytes' is determined by

// the choosen S-R ecord forma t.

const int m axBytes = 20; // se t limit on record length

const int addressBytes = 3; // 24-bit address range

const int sumCheckBytes = 1;

const int maxdata = m axBytes - ad dressByte s - sumC heckBytes;

int i=0; // current E PROM address

int sumCheck = 0;

while ( i < agcMemSize)

{

Page 134: Apollo Guidance Computer AGC

// get dataByteCount; the number of bytes of EPROM data per record.

int dataByteCount = maxdata;

if(i + dataByteCount >= agcMemSize)

{

da taByteC ount = agcM em Size - i;

}

// write record header (*** 3 byte address assumed ***)

int totalByteCount = dataByteCoun t + addre ssBytes + sumCheckBytes;

fprintf(fpObj, "S2% 02X %06X ", totalByteCou nt, i);

sumCh eck = tota lByteCount & 0x ff;

sumCheck = (sumCheck + ((i & 0xff0000) >> 16)) % 256;

sumCheck = (sumCheck + ((i & 0x00ff00) >> 8)) % 256;

sumCheck = (sumCheck + ((i & 0x0000ff) )) % 256;

// write data bytes into record

for(int j=0; j<dataByteCount; j++)

{

get_CPM_A( i+j); // get CPM-A pulses for address i+j

int data = writeEPROM(lowBit); // comvert pulses to EPROM format

fprintf(fpObj, "% 02X ", data);

sumCheck = (sumCheck + data) % 256;

}

// terminate record by adding the checksum and a newline.

fprintf(fpObj, "% 02X \n", (~sum Check) & 0xff);

i += da taBy teCount;

}

// write an end-of-file record here

i = 0; // use address ze ro for last record

sumCheck = 0x04; // byte count

sumCheck = (sumCheck + ((i & 0xff0000) >> 16)) % 256;

sumCheck = (sumCheck + ((i & 0x00ff00) >> 8)) % 256;

sumCheck = (sumCheck + ((i & 0x0000ff) )) % 256;

fprintf(fpObj, "S804%06X %02X ", i, (~sumCheck) & 0xff);

}

void main(int argc, ch ar* a rgv[])

{

FILE* fpObj = 0;

fpOb j = fopen("CPM1_8 .hex" , "w");

if(!fpOb j)

{

perro r("fopen failed for object file");

exit(-1);

}

writeEPROM(fpO bj, 1); // pulses 1 -8

fclose(fpOb j);

fpOb j = fopen("CPM9_16.hex", "w" );

if(!fpOb j)

{

perro r("fopen failed for object file");

exit(-1);

}

writeEPROM(fpObj, 9); // pulses 9-16

fclose(fpOb j);

fpOb j = fopen("CPM17_24.hex", "w ");

if(!fpOb j)

{

perro r("fopen failed for object file");

exit(-1);

}

writeEPROM(fpObj, 17); // pulses 17-24

fclose(fpOb j);

fpOb j = fopen("CPM25_32.hex", "w ");

Page 135: Apollo Guidance Computer AGC

if(!fpOb j)

{

perro r("fopen failed for object file");

exit(-1);

}

writeEPROM(fpObj, 25); // pulses 25-32

fclose(fpOb j);

fpOb j = fopen("CPM33_40.hex", "w ");

if(!fpOb j)

{

perro r("fopen failed for object file");

exit(-1);

}

writeEPROM(fpObj, 33); // pulses 33-40

fclose(fpOb j);

fpOb j = fopen("CPM41_48.hex", "w ");

if(!fpOb j)

{

perro r("fopen failed for object file");

exit(-1);

}

writeEPROM(fpObj, 41); // pulses 41-48

fclose(fpOb j);

fpOb j = fopen("CPM49_56.hex", "w ");

if(!fpOb j)

{

perro r("fopen failed for object file");

exit(-1);

}

writeEPROM(fpObj, 49); // pulses 49-56

fclose(fpOb j);

}

Page 136: Apollo Guidance Computer AGC

Block IApollo Guidance Computer (AGC)

How to build one in your basement

Part 3: Processing (PROC) Module

John Pultorak

December, 2004

Page 137: Apollo Guidance Computer AGC

Abstract

This report describes my successful project to build a working reproduction of the 1964

prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the

Apollo moon landings, and is the world’s first integrated circuit computer.

I built it in my basement. It took me 4 years.

If you like, you can build one too. It will take you less time, and yours will be better than

mine.

I documented my project in 9 separate .pdf files:

Part 1 Overview: Introduces the project.

Part 2 CTL Module: Design and construction of the control module.

Part 3 PROC Module: Design and construction of the processing (CPU) module.

Part 4 MEM Module: Design and construction of the memory module.

Part 5 IO Module: Design and construction of the display/keyboard (DSKY) module.

Part 6 Assembler: A cross-assembler for AGC software development.

Part 7 C++ Simulator: A low-level simulator that runs assembled AGC code.

Part 8 Flight Software: My translation of portions of the COLOSSUS 249 flight

software.

Part 9 Test & Checkout: A suite of test programs in AGC assembly language.

Page 138: Apollo Guidance Computer AGC

Overview

The Processing Module (PROC) has 5 subsystems: PMI, ALU, CRG, INT, CTR

PMI (Processing Module

external Interface)

The PMI interfaces other

processing module subsystems

to external AGC modules.

40-pin IDE connectors interface

to the other CTL, MEM, and IO

modules. Inputs from those

modules are buffered to 1

LSTTL load.

ALU (Arithmetic Logic Unit)

The ALU contains the 16-bit

ADDER to perform 1's

complement arithmetic and

increment the program counter

(Z register). The ALU also

contains the B and C registers,

and logic to inclusive OR the

contents of the them with the

ADDER. The inclusive OR occurs

when the control module (CTL)

issues signals to READ the

contents of both registers onto

the READ bus simultaneously.

The ALU transfers data from the

READ bus to the WRITE bus for

register-to-register transfers

and can force the data lines of

the WRITE bus to specific states

to gate various constants into

the AGC registers

CRG (Central Register)

The AGC has four 16-bit

“central registers” for general

computational use. These are

the accumulator (A) for general

computation; the program counter (Z) which contains the address of the next instruction;

the Q register holding the remainder in the DV instruction, and the return address after TC

instructions; and the LP register used to hold the lower product after MP instructions.

INT (Interrupt Priority)

The original AGC had five vectored interrupts. This recreation implements three of them:

RUPT1, also called T3RUPT which is used as general-purpose timer by the AGC WAITLIST

software; RUPT3, also called T4RUPT or DSRUPT, which is used to update the DSKY display

at regular intervals; and RUPT4, also called KERUPT, which is triggered by a key press from

the user's keyboard. The AGC responds to each interrupt by temporarily suspending the

current program, executing a short interrupt service routine, and then resuming the

Page 139: Apollo Guidance Computer AGC

interrupted program.

CTR (Priority Counter)

Twenty memory locations in the original AGC functioned as up/down counters. The counters

would increment (PINC) or decrement (MINC) in response to external inputs. Increment or

decrement was handled by one 12-step subsequence of microinstructions inserted between

any two regular instructions. This replica implements 5 of the counters: OVCTR, an overflow

counter incremented or decremented by arithmetic overflow during certain instructions;

TIME2 and TIME1, the AGC real-time clock; TIME3, a general purpose timer incremented by

a 100Hz signal from the SCALER (SCL); and TIME4, a timer used to update the DSKY

display.

Page 140: Apollo Guidance Computer AGC

The ALU has a 16-bit

parallel adder. The

addend and augend

are supplied by the

X and Y registers.

The sum, called the

U register although

it is not really a

register at all, is

gated to the read

bus through the RU

(read U) control

signal. The WX and

WY control signals

copy the contents of

the write bus into

the X and Y

registers.

The B register is

loaded from the

write bus with the

WB (write B) signal.

The contents of B

are output to the

read bus with the RB

(read B) signal. The

inverted output of B

can be gated to the

read bus with the RC

(read C) signal.

Page 141: Apollo Guidance Computer AGC

The AGC has four user-accessible central registers. The A register is the accumulator; Z is

the program counter; Q stores the return address for jumps (TC instruction), and LP stores

the lower product (MP

instruction).

Central register contents

can be output to the read

bus by asserting the

appropriate read control

pulse (RA, RQ, RZ, or

RLP). Each register is

also mapped to a

memory location, with

register A mapped to

address 0, Q to address

1, Z to 2, and LP to 3.

The R0, R1, R2, and R3

control pulses output

those registers to the

read bus.

The write bus contents

can be loaded into a

central register with a

write control pulse. WA

and WALP load the A

register; WQ, the Q

register; WZ the Z

register; and WLP and

WALP the LP register.

The W0, W1, W2, and

W3 control pulses

mapped to memory

addresses 0,1,2, and 3

also load those registers.

Page 142: Apollo Guidance Computer AGC

The interrupt priority

subsystem manages

vectored interrupts. Five

interrupts (0-4) are

implemented. Each

interrupt is latched by its

own “RP cell” flip-flop.

Signals from all RP cells

feed into a priority

encoder; a combinational

logic array that outputs

the code of the highest

priority interrupt in the

RP cells. When RPT is

asserted, the priority

code is latched into

RPCELL. This is decoded

into an address which is

the interrupt vector; the

address is written to the

read bus when RRPA is

asserted.

After the interrupt code

has been loaded into

RPCELL, asserting KRPT

(knock-down RPT) causes

the RP cell for that

interrupt to be reset. This

causes the next highest

priority interrupt to be

decoded by the priority

encoder.

The INHINT and INHINT1

flip-flops inhibit

interrupts.

Page 143: Apollo Guidance Computer AGC

The priority counter

logic design is similar

to the interrupt

subsystem. Up (+)

and down (-) count

input signals feed into

20 PCELLs, one PCELL

for each counter. The

PCELLs feed into the

priority encoder which

outputs the code of

the highest priority

PCELL having a up or

down input set. The

PCELL code is written

to the PCELL register

when WPCTR is

asserted.

The PCELL memory

address, derived from

PCELL, is written to

read bus when RSCT

is asserted. After the

code is latched into

the PCELL register,

the corresponding

PCELL is reset by

asserting WOVR.

The up or down code

for the selected PCELL is written to PSEQ when WPCTR is asserted. This code feeds to the

control logic on the CTL module which selects the PINC (increment) or MINC (decrement)

instruction subsequence to bump the priority counter up or down.

The PINC and MINC subsequences are inserted between normal instruction subsequences. A

SHINC subsequence implements a bit-shift which is used to load telemetry bits into the AGC

and assemble them into words. SHINC is not implemented in this AGC replica.

Page 144: Apollo Guidance Computer AGC

PROC Internal Subsystem Interconnections

This diagram shows internal interconnections for the subsystems in the PROC module.

Page 145: Apollo Guidance Computer AGC

PROC Module External Interfaces

The PROC module interfaces to the CTL, MEM, and IO modules through 40-pin IDE ribbon

cables.

Page 146: Apollo Guidance Computer AGC

J100-PROC: PROC-to-CTL I/F

J100 is a 40-pin IDE cable that connects the PROC module to the CTL module.

INPUTS (to PROC):

PIN signal full name state definition

1 WA3 WRITE ADDR 3 (74) 0=Write reg at address 3 (LP)

2 WA2 WRITE ADDR 2 (73) 0=Write reg at address 2 (Z)

3 WA1 WRITE ADDR 1 (72) 0=Write reg at address 1 (Q)

4 WA0 WRITE ADDR 0 (71) 0=Write reg at address 0 (A)

5 RA3 READ ADDR 3 (60) 0=Read reg at address 3 (LP)

6 RA2 READ ADDR 2 (59) 0=Read reg at address 2 (Z)

7 RA1 READ ADDR 1 (58) 0=Read reg at address 1 (Q)

8 RA0 READ ADDR 0 (57) 0=Read reg at address 0 (A)

9 WZ WRITE Z (50) 0=Write Z

10 WYx WRITE Y NO RESET (49) 0=Write Y (do not reset)

11 WY WRITE Y (48) 0=Write Y

12 WX WRITE X (47) 0=Write X

13 WQ WRITE Q (45) 0=Write Q

14 WOVR WRITE OVF (41) 0=Write overflow

15 WOVI WRITE OVF RUPT INH (40) 0=Write overflow RUPT inh ibit

16 WOVC WRITE OVF CNTR (39) 0=Write overflow counter

17 WLP WRITE LP (38) 0=Write LP

18 WB WRITE B (36) 0=Write B

19 WALP WRITE A/LP (35) 0=Write A and LP

20 WA WRITE A (34) 0=Write A

21 F10X F10 SCALER ONESHOT 1=timed out (100.0 Hz)

23 R24 READ 24 (25) 0=Read 24

24 R22 READ 22 (24) 0=Read 22

25 R2 READ 2 (23) 0=Read 2

26 R1C READ 1 COMP (22) 0=Read 1 complimented

27 R1 READ 1 (21) 0=Read 1

28 RZ READ Z (20) 0=Read Z

29 RU READ U (19) 0=Read sum

30 RSCT READ CNTR ADDR (18) 0=Read selected counter address

31 RSB READ SIGN (17) 0=Read sign bit

32 RRPA READ RUPT ADDR (16) 0=Read RUPT address

33 RQ READ Q (15) 0=Read Q

34 RLP READ LP (13) 0=Read LP

35 RC READ C (11) 0=Read C

36 RB14 READ BIT 14 (10) 0=Read bit 14

37 RB READ B (9) 0=Read B

38 RA READ A (8) 0=Read A

39 KRPT KNOCK DOWN RUPT (6) 0=Knock down Rupt priority

40 CI SET CARRY IN (1) 0=Carry in

Page 147: Apollo Guidance Computer AGC
Page 148: Apollo Guidance Computer AGC

J101-PROC: PROC-to-CTL I/F

J101 is a 40-pin IDE cable that connects the PROC module to the CTL module.

INPUTS (to PROC):

PIN signal full name state definition

1 R2000 READ 2000 (101) 0=Read 2000

2 WPCTR WRITE PCTR (98) 0=Write PCTR (latch priority counter seq)

3 RPT READ RUPT (94) 0=Read RUPT opcode

4 INH SET INHINT (93) 0=Set INHINT

5 CLRP CLEAR RPCELL (92) 0=Clear RPCELL

6 CLINH1 CLEAR INHINT1 (88) 0=Clear INHINT1

7 CLINH CLEAR INHINT (87) 0=Clear INHINT

8 GENRST GENERAL RESET (86) 0=General Reset

19 CLK1 CLOCK1 1.024 MHz AGC clock 1 (normally low)

20 CLK2 CLOCK2 1.024 MHz AGC clock 2 (normally low)

OUTPUTS (from PROC):

PIN signal full name state definition

21 SB_01 SUB SEL 01 SB_01 is LSB; SB_02 is MSB

22 SB_02 SUB SEL 02 00=no counter; 01=PINC; 10=MINC

23 IRQ INT RQST 0=interrupt requested.

25 WB_01 WRITE BUS 01 (lsb)

26 WB_02 WRITE BUS 02

27 WB_03 WRITE BUS 03

28 WB_04 WRITE BUS 04

29 WB_05 WRITE BUS 05

30 WB_06 WRITE BUS 06

31 WB_07 WRITE BUS 07

32 WB_08 WRITE BUS 08

33 WB_09 WRITE BUS 09

34 WB_10 WRITE BUS 10

35 WB_11 WRITE BUS 11

36 WB_12 WRITE BUS 12

37 WB_13 WRITE BUS 13

38 WB_14 WRITE BUS 14

39 WB_15 WRITE BUS 15 US (overflow) bit

40 WB_16 WRITE BUS 16 SG (sign) bit

Page 149: Apollo Guidance Computer AGC
Page 150: Apollo Guidance Computer AGC

J104-PROC: PROC-to-IO I/F

J104 is a 40-pin IDE cable that connects the PROC module to the IO module.

INPUTS (to PROC):

PIN signal full name state definition

40 RB_01 READ BUS 01 (lsb)

39 RB_02 READ BUS 02

38 RB_03 READ BUS 03

37 RB_04 READ BUS 04

36 RB_05 READ BUS 05

35 RB_06 READ BUS 06

34 RB_07 READ BUS 07

33 RB_08 READ BUS 08

32 RB_09 READ BUS 09

31 RB_10 READ BUS 10

30 RB_11 READ BUS 11

29 RB_12 READ BUS 12

28 RB_13 READ BUS 13

27 RB_14 READ BUS 14

26 RB_15 READ BUS 15 US (overflow) bit

25 RB_16 READ BUS 16 SG (sign) bit

22 BUSY2 READ BUS BUSY 0=OUT register output to read bus

21 BUSY1 READ BUS BUSY 0=INP register output to read bus

20 KB_STR KEY STROBE 1=key pressed strobe; to KEYRUPT. Key

data is valid on the negative edge of

KB_STR. Data is latched until the next

keypress.

OUTPUTS (from PROC):

PIN signal full name state definition

1 WB_01 WRITE BUS 01 (lsb)

2 WB_02 WRITE BUS 02

3 WB_03 WRITE BUS 03

4 WB_04 WRITE BUS 04

5 WB_05 WRITE BUS 05

6 WB_06 WRITE BUS 06

7 WB_07 WRITE BUS 07

8 WB_08 WRITE BUS 08

9 WB_09 WRITE BUS 09

10 WB_10 WRITE BUS 10

11 WB_11 WRITE BUS 11

12 WB_12 WRITE BUS 12

13 WB_13 WRITE BUS 13

14 WB_14 WRITE BUS 14

15 WB_15 WRITE BUS 15 US (overflow) bit

16 WB_16 WRITE BUS 16 SG (sign) bit

Page 151: Apollo Guidance Computer AGC

J105-PROC: PROC-to-MEM I/F

J105 is a 40-pin IDE cable that connects the PROC module to the MEM module.

INPUTS (to PROC):

PIN signal full name state definition

40 RB_01 READ BUS 01 (lsb)

39 RB_02 READ BUS 02

38 RB_03 READ BUS 03

37 RB_04 READ BUS 04

36 RB_05 READ BUS 05

35 RB_06 READ BUS 06

34 RB_07 READ BUS 07

33 RB_08 READ BUS 08

32 RB_09 READ BUS 09

31 RB_10 READ BUS 10

30 RB_11 READ BUS 11

29 RB_12 READ BUS 12

28 RB_13 READ BUS 13

27 RB_14 READ BUS 14

26 RB_15 READ BUS 15 US (overflow) bit

25 RB_16 READ BUS 16 SG (sign) bit

22 BUSY7 READ BUS BUSY 0=BNK register output enabled to read

bus

21 BUSY5 READ BUS BUSY 0=G register output enabled to read bus

OUTPUTS (from PROC):

PIN signal full name state definition

1 WB_01 WRITE BUS 01 (lsb)

2 WB_02 WRITE BUS 02

3 WB_03 WRITE BUS 03

4 WB_04 WRITE BUS 04

5 WB_05 WRITE BUS 05

6 WB_06 WRITE BUS 06

7 WB_07 WRITE BUS 07

8 WB_08 WRITE BUS 08

9 WB_09 WRITE BUS 09

10 WB_10 WRITE BUS 10

11 WB_11 WRITE BUS 11

12 WB_12 WRITE BUS 12

13 WB_13 WRITE BUS 13

14 WB_14 WRITE BUS 14

15 WB_15 WRITE BUS 15 US (overflow) bit

16 WB_16 WRITE BUS 16 SG (sign) bit

Page 152: Apollo Guidance Computer AGC
Page 153: Apollo Guidance Computer AGC

PROC CONTROL PANEL PUSHBUTTONS

RUPT1 Set the RUPT1 flip-flop (FF). Simulates a TIME3 overflow. Triggers a T3RUPT.

RUPT3 Set the RUPT3 flip-flop (FF). Simulates a TIME4 overflow. Triggers a T4RUPT

(DSRUPT).

RUPT4 Set the RUPT4 flip-flop (FF). Simulates a DSKY keypress. Triggers a KEYRUPT.

TIME1 Set the TIME1 flip-flop (FF). Increments the low-order word of the AGC

real-time clock.

TIME2 Set the TIME2 flip-flop (FF). Increments the high-order word of the AGC

real-time-clock.

TIME3 Set the TIME3 flip-flop (FF). Increments the general purpose timer.

TIME4 Set the TIME4 flip-flop (FF). Increments the display update timer.

Page 154: Apollo Guidance Computer AGC

PROC CONTROL PANEL CONNECTIONS

PIN signal state definition

1 RUPT1 GND=set RUPT1 FF

2 RUPT3 GND=set RUPT3 FF

3 RUPT4 GND=set RUPT4 FF

4 TIME1 GND=set TIME1 FF

5 TIME2 GND=set TIME2 FF

6 TIME3 GND=set TIME3 FF

7 TIME4 GND=set TIME4 FF

8 GND

Page 155: Apollo Guidance Computer AGC

PROC INDICATORS

The PROC module has a panel of indicator lamps (LEDs) to show the state of PROC registers

and critical logic signals.

These indicator lamps

show the current state of

all registers and some

additional, important

logic signals produced by

the PROC module. AGC

numbers are represented

in octal, so all register

lamps are in groups of

three. At the time the

photo was taken the

AGC was running

the COLOSSUS 249

flight software load,

executing Verb 16, Noun

36: a monitor verb

which displays the AGC

real time clock.

Page 156: Apollo Guidance Computer AGC
Page 157: Apollo Guidance Computer AGC
Page 158: Apollo Guidance Computer AGC
Page 159: Apollo Guidance Computer AGC
Page 160: Apollo Guidance Computer AGC

ALU (Arithmetic Logic Unit)

My earliest architectural representation of the ALU logic is shown below:

The ALU contains the 16-bit ADDER (colored orange in the diagram) which performs 1's

complement arithmetic, and increments the program counter (Z register). Each orange box is

a 4-bit parallel adder; collectively, they add 16 bits. The ADDER uses the X, Y, and U

registers:

X: the 16-bit extension register (2 8-bit registers in yellow) that holds one of two inputs

to the ADDER.

Y: the 16-bit extension register (also in yellow) that holds the other input to the ADDER.

U: the ADDER output (the 1's complement sum of the contents of registers X and Y).

Outputs to the bus labeled “B” on the diagram.

Page 161: Apollo Guidance Computer AGC

The ALU also contains the B and C registers:

B: a general-purpose buffer register (shown as 2 8-bit registers in yellow), also used to

pre-fetch the next instruction. At the start of the next instruction sequence, the upper

bits of B (containing the next op code) are copied to the SQ register (in CTL), and the

lower bits (the address) are copied to the S register in (MEM). Output to the bus

labeled “A” on the diagram.

C: not a separate register, but the 1's complement of B.

The ALU contains logic (using

74LS181 ALU chips, shown in

green) to do any of the following:

select the B register; select the

complement of the B register (the

“C” register); select the U register;

select the C register OR’ed with U,

or select logical zero. Those logic

functions, needed for AGC

operation, are shown in the upper

right corner of the diagram. The

outputs of the 74LS181 selector are

gated through a buffer to the read

bus.

The original AGC could inclusive OR

the outputs of any combination of

registers onto the bus, but the

control module only used this

feature for the B/C and U registers.

One of the uses involved the MASK

instruction, which is a logical AND:

DeMorgan's theorem was used to

implement the equivalent of a

logical AND by inverting operands

through the C register, performing a

logical OR through the bus, and

then inverting the result.

The 74LS181 logic functions are

gated to the read bus through the

data selector logic, shown in the adjacent diagram.

Page 162: Apollo Guidance Computer AGC

The ALU also transfers data from the

READ bus to the WRITE bus for

register-to-register data moves: Data

is output from the source register

onto the READ bus, then transferred

from the READ bus to the WRITE bus

through the ALU, and finally loaded

from the WRITE bus into the

destination register.

The logic that translates the READ

bus to the WRITE bus can also force

the data lines of the WRITE bus to

specific states to gate various

arithmetic constants onto the bus.

The accompanying diagram shows

the the control signal on the left

(RB14, R1, etc) and to the right is

the bit pattern that’s OR’ed onto the

bus when the signal is asserted. The

default state of the read bus is

logical zero, so if no other read signal

is asserted, the number that appears

on the bus is the constant;

otherwise, it’s the constant inclusive

OR’ed with the contents of the READ

bus.

The ALU contains READ bus control

logic. Registers in the MEM module,

the central registers in the PROC

module, and the ALU all interface to

the READ bus through tri-state

buffers. These buffers are normally in

the high-impedance state, but the

control module (CTL) issues READ

control signals to output the contents

of specific registers to the READ bus

at certain times. Only one register

should be gated onto the READ bus

at any given time.

When no READ control signals are asserted, the ALU gates its output onto the READ bus by

default. When the control module gates a register onto the READ bus, a BUSY signal is sent

to the ALU module, which causes the ALU to inhibit its output. Because of propagation

delays, the ALU might continue to output to the READ bus for a brief time while another

register is also gated to the bus. To prevent this, all output to the read bus is inhibited during

CLK1. This gives the control signals, which transition on the leading edge of CLK1, enough

setup time to resolve the conflict.

Page 163: Apollo Guidance Computer AGC

ALU INPUTS:

I/F signal full name state definition

CLK:

CLK1 CLOCK 1 1=read bus setup; inhibit read bus out

CLK2 CLOCK 2 data transfer occurs on falling edge

CPM:

RB READ B 0=output B register to write bus

RC READ C 0=output comp of reg B (C) to write bus

RU READ G 0=output U register to write bus

R1 READ OCTAL 1 0=incl OR 000001 w/write bus

R1C READ OCTAL -1 0=incl OR 177776 w/write bus

R2 READ OCTAL 2 0=incl OR 000002 w/write bus

R22 READ OCTAL 22 0=incl OR 000022 w/write bus

R24 READ OCTAL 24 0=incl OR 000024 w/write bus

R2000 READ OCTAL 2000 0=incl OR 002000 w/write bus

RB14 READ BIT14 0=incl OR 020000 w/write bus

RSB READ SIGN BIT 0=incl OR 100000 w/write bus

WB WRITE B 0=write into B from write

bus

CI WRITE CI 0=set carry register to 1

WY WRITE Y 0=write Y

WX WRITE X 0=write into X from write

bus

WYX WRITE Y 0=write into Y from write

bus

RBUS:

RB_01 READ BUS 01

...

RB_14 READ BUS 14

RB_15 READ BUS 15 US (overflow) bit for read

bus

RB_16 READ BUS 16 SG (sign) bit for read bus

INP: BUSY1 READ BUS BUSY 0=valid data from INP on

read bus

OUT: BUSY2 READ BUS BUSY 0=valid data from OUT on

read bus

CTR: BUSY3 READ BUS BUSY 0=valid data from CTR on

read bus

INT: BUSY4 READ BUS BUSY 0=valid data from INT on read bus

MBF: BUSY5 READ BUS BUSY 0=valid data from MBF on read bus

CRG: BUSY6 READ BUS BUSY 0=valid data from CRG on read bus

ADR: BUSY7 READ BUS BUSY 0=valid data from ADR on read bus

MBF OUTPUTS:

I/F signal full name state definition

Page 164: Apollo Guidance Computer AGC

WBUS:

WB_01 WRITE BUS 01

...

WB_14 WRITE BUS 14

WB_15 WRITE BUS 15 US (overflow) bit for write bus

WB_16 WRITE BUS 16 SG (sign) bit for write bus

Page 165: Apollo Guidance Computer AGC
Page 166: Apollo Guidance Computer AGC
Page 167: Apollo Guidance Computer AGC
Page 168: Apollo Guidance Computer AGC
Page 169: Apollo Guidance Computer AGC
Page 170: Apollo Guidance Computer AGC

CRG (Central Register)

The AGC has four 16-bit registers for general computational use. These are called the

"central registers":

A: the 16-bit accumulator, used

for general computation.

Z: the 16-bit program counter,

which contains the address of

the next instruction to be

executed.

Q: the 16-bit register used to

hold the remainder in the DV

instruction, and to hold the

return address after TC

instructions.

LP: the 16-bit register used to

hold the lower product after

MP instructions.

Register A and LP shifters

In addition to “normal” control pulses that write each line of the write bus into the

corresponding bit of the registers, the A and LP registers have special write control pulses

that shift bits:

The WALP control pulse bit-shifts into the A and LP register. The table below shows how the

shifter works. The row of 16 comma-separated entries represent bits in the register. The

leftmost position is the register MSB, rightmost position is the LSB. The entry shows the bit

of the WRITE bus that’s mapped onto that register bit by the shifter.

For the WALP pulse, bit 1 of the WRITE bus (B1) is written into bit 14 of the LP register. “BX”

means leave that bit of the register alone (don’t change it).

The same WALP pulse causes bit 2 of the WRITE bus (B2) to be written into the lowest bit of

the A register, bit 3 of the WRITE bus (B3) to be written into the next bit, and so forth. “US”

(uncorrected sign) is the overflow bit (bit 15) of the WRITE bus. “SG” is the 1's complement

sign (bit 16) from the WRITE bus.

WALP for register LP:

BX, BX, B1, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX

WALP for register A:

SG, SG, US, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2

Page 171: Apollo Guidance Computer AGC

Similarly, the WLP control pulse bit-shifts the WRITE bus into the LP register as follows (D0

on bit 14 of the LP register means force the bit to zero):

WLP

B1, B1, D0, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2

The logic design for handling bit 14 of the LP

register, which takes control inputs from

WALP, WLP, and WA3 is shown here. WA3 is

identical to WLP.

Depending upon the WALP, WLP, or WA3

inputs, bit 14 of LP will either be set to B1 of

the WRITE bus, or forced to zero.

Page 172: Apollo Guidance Computer AGC

CRG INPUTS:

I/F signal full name state definition

CLK:

CLK1 CLOCK 1 1=read bus setup; inhibit read bus output

CLK2 CLOCK 2 data transfer occurs on falling edge

CPM:

RA READ A 0=output A to read bus

RA0 READ A 0=output A to read bus

RQ READ Q 0=output Q to read bus

RA1 READ Q 0=output Q to read bus

RZ READ Z 0=output Z to read bus

RA2 READ Z 0=output Zto read bus

RLP READ LP 0=output LPto read bus

RA3 READ LP 0=output LP to read bus

WA WRITE A 0=load A from write bus

WA0 WRITE A 0=load A from write bus

WQ WRITE Q 0=load Q from write bus

WA1 WRITE Q 0=load Q from write bus

WZ WRITE Z 0=load Z from write bus

WA2 WRITE Z 0=load Z from write bus

WALP WRITE A,LP 0=load A,LP from write

bus

WLP WRITE LP 0=load LP from write bus

GENRST GENERAL RESET 0=General Reset

WBUS:

WB_01 WRITE BUS 01

...

WB_14 WRITE BUS 14

WB_15 WRITE BUS 15 US (overflow) bit for write bus

WB_16 WRITE BUS 16 SG (sign) bit for write bus

MBF OUTPUTS:

I/F signal full name state definition

RBUS:

RB_01 READ BUS 01

...

RB_14 READ BUS 14

RB_15 READ BUS 15 US (overflow) bit for read/write bus

RB_16 READ BUS 16 SG (sign) bit for read/write bus

BUSY READ BUS BUSY 0=output enabled to read bus

Page 173: Apollo Guidance Computer AGC
Page 174: Apollo Guidance Computer AGC
Page 175: Apollo Guidance Computer AGC
Page 176: Apollo Guidance Computer AGC
Page 177: Apollo Guidance Computer AGC

INT (Interrupt Priority)

The original AGC had five vectored interrupts. This recreation implements the following 3:

RUPT1 Also called T3RUPT because it's triggered by overflow of the TIME3 priority

counter.

RUPT3 Also called T4RUPT because it's triggered by overflow of the TIME4 priority

counter. Because the interrupt is used by software to update the DSKY display

at regular intervals, it's sometimes called DSRUPT.

RUPT4 Triggered by a key press from the user's keyboard. Also called KEYRUPT.

The AGC software responds to each interrupt by temporarily suspending the current program,

executing a short interrupt service routine, and then resuming the interrupted program.

Page 178: Apollo Guidance Computer AGC

INT INPUTS:

I/F signal full name state definition

CLK:

CLK1 CLOCK 1 1=read bus setup; inhibit read bus out

CLK2 CLOCK 2 data transfer occurs on falling edge

CPM:

GENRST GENERAL RESET 0=reset INT registers

RRPA READ RUPT ADDRESS 0=output RPCELL address

(2004,2010,2014,2020,2024) to read bus

RPT READ RUPT OPCODE 0=load RUPT opcode into RPCELL register

KRPT KNOCK DOWN RUPT PRIO 0=reset RUPT latch currently selected by

RPCELL register

CLRP CLEAR RPCELL 0=clear RPCELL register

WOVI WRITE OVF RUPT INH 0=test overflow; if

overflow, inhibit interrupt

(set INHINT1)

CLINH1 CLEAR INHINT1 0=clear INHINT1 register

INH SET INHINT 0=set INHINT register

CLINH CLEAR INHINT 0=clear INHINT register

WBUS:

WB_15 WRITE BUS 15 US (overflow) bit for write

bus

WB_16 WRITE BUS 16 SG (sign) bit for write bus

CTR/KBD:

RUPT1 INTERRUPT 1 0=trigger interrupt 1 (2004 octal; TIME3

overflow)

RUPT3 INTERRUPT 3 0=trigger interrupt 3 (2014 octal; TIME4

overflow)

RUPT4 INTERRUPT 4 0=trigger interrupt 4 (negative edge)

(2020 octal; keyboard activity)

Note: interrupt cells above RUPT4 not implemented.

INT OUTPUTS:

I/F signal full name state definition

SEQ:

IRQ INT RQST 0=interrupt requested. Active if allof the

following are true:

a) one or more RUPT FF's are set

b) interrupt is not currently being serviced

Page 179: Apollo Guidance Computer AGC

c) interrupts are not inhibited

RBUS:

RB_01 READ BUS 01

...

RB_14 READ BUS 14

RB_15 READ BUS 15 US (overflow) bit for read/write bus

RB_16 READ BUS 16 SG (sign) bit for read/write bus

BUSY READ BUS BUSY 0=output enabled to read bus

Page 180: Apollo Guidance Computer AGC
Page 181: Apollo Guidance Computer AGC
Page 182: Apollo Guidance Computer AGC

CTR (Priority Counter)

The Block I AGC had 20 memory locations dedicated as up/down counters (involuntary

counters). The counters would increment or decrement in response to external plus or minus

logic signals. Increment (PINC) or decrement (MINC) was handled by one subsequence of

microinstructions inserted between any two regular instruction subsequences when counter

inputs occurred.

This replica implements 5 counters used by the AGC operating system and user interface:

Counter Addr Description

OVCTR 34 An overflow counter incremented (PINC) or decremented (MINC) when

overflow conditions occur during certain instructions.

TIME2 35 The high-order bits of the AGC clock; incremented (PINC) by overflow

of TIME1.

TIME1 36 The low-order bits of the AGC clock; incremented (PINC) by a 100Hz

signal from the SCALER (SCL) in the control module (CTL).

TIME3 37 A general purpose timer incremented by a 100Hz signal from the

SCALER (SCL) in the control module (CTL).

TIME4 40 A special purpose timer used for software update of the DSKY display.

Incremented by a 100Hz signal from the SCALER (SCL) in the control

module (CTL).

INT/CTR interface

This chart shows how counter

overflows are handled. F10 (from

the scaler) increments TIME1,

TIME3, and TIME4.

A positive overflow of TIME1

causes an increment of TIME2.

Positive overflow of TIME3

triggers a T3RUPT interrupt.

Positive overflow of TIME4

triggers a DSRUPT (T4RUPT)

interrupt.

The addresses of TIME1 and

TIME2 are reversed for Block II.

This chart shows the Block I

order, but my replica used the

Block II order for compatibility

with the COLOSSUS flight

software.

Page 183: Apollo Guidance Computer AGC

CTR Design Problem

During unit testing, I uncovered a bug in my implementation of CTR: The plus inputs set the

P-cell which eventually triggers a PINC subsequence and increments the counter. Minus

inputs set the M-cell, which triggers a MINC subsequence and decrements the counter.

Near-simultaneous plus and m inus inputs should cancel out, producing no change in count.

As a consequence, the counter logic was designed so that, if the P- and M-cells are both set,

no counter sequence (PINC or MINC) is selected. The problem is, the P- and M-cells are reset

by WOVR, which only occurs in PINC or MINC. So, if both cells are set--and therefore, no

subsequence is selected--WOVR is never issued, the cells never reset, and all counting

activity is disabled for that counter.

Here are the options I developed fixing the design:

a) Create a new subsequence similar to PINC or MINC that issues WOVR, but does not

change the counter. Select this new subsequence when the P- and M-cells are simultaneously

set.

b) Allow the P- and M-cells to trigger PINC and MINC sequences, resulting in a net change of

zero to the counter.

c) Leave the design as-is, because the M-cell is only used for OVCTR in my implementation,

and therefore, the problem can never occur.

I choose option C to avoid redesign and re-unit-testing of CTR.

Page 184: Apollo Guidance Computer AGC

CTR INPUTS:

I/F signal full name state definition

CLK:

CLK1 CLOCK 1 1=read bus setup; inhibit read bus out

CLK2 CLOCK 2 data transfer occurs on falling edge

CPM:

GENRST GENERAL RESET 0=reset CTR registers

WPCTR WRITE PSEQ 0=write sequence into

PSEQ

RSCT READ PCELL ADDRESS 0=output PCELL address

(034-043) to read bus

WOVC WRITE OVRFLOW CNTR 0=test overflow and

inc/dec OVCTR

WOVR WRITE OVERFLOW 0=clear selected PCELL

and handle

counter overflow (if any)

WBUS:

WB_15 WRITE BUS 15 US (overflow) bit for

write bus

WB_16 WRITE BUS 16 SG (sign) bit for write

bus

EXTERNAL:

P3P P3 CELL + COUNT 0=count up P3 counter

(036 octal; TIME1)

P4P P4 CELL + COUNT 0=count up P4 counter

(037 octal; TIME3)

P5P P5 CELL + COUNT 0=count up P5 counter

(040 octal, TIME4)

Note: priority cells 6-20 not implemented.

CTR OUTPUTS:

I/F signal full name state definition

COUNTER OVERFLOW:

CPO_04 P4 + OVERFLOW 0=P4 cell pos ovf (during WOVR)

note: TIME3 + overflow; connect

to INT subsystem to trigger T3RUPT

interrupt.

CPO_05 P5 + OVERFLOW 0=P5 cell pos ovf (during WOVR)

Page 185: Apollo Guidance Computer AGC

note: TIME4 + overflow; connect

to INT subsystem to trigger T4RUPT

(DSRUPT) interrupt.

SEQ:

SB_01 SUB SEL 01 SB_01 is LSB; SB_02 is MSB

SB_02 SUB SEL 02 00=no counter; 01=PINC; 10=MINC

RBUS:

RB_01 READ BUS 01

...

RB_14 READ BUS 14

RB_15 READ BUS 15 US (overflow) bit for read/write bus

RB_16 READ BUS 16 SG (sign) bit for read/write bus

BUSY READ BUS BUSY 0=output enabled to read bus

Page 186: Apollo Guidance Computer AGC
Page 187: Apollo Guidance Computer AGC
Page 188: Apollo Guidance Computer AGC
Page 189: Apollo Guidance Computer AGC
Page 190: Apollo Guidance Computer AGC

Fabrication

The PROC module is (4) 13"x5" circuit boards, and 1 control panel.

Module Rack

The module framework is designed

to resemble a relay rack, but scaled

to fit the circuit board dimensions.

It is constructed out of 1"x2" pine

and spray-painted semi-gloss gray.

Circuit boards are mounted to the

rack by 2 phillips screws at either

end. Nylon spacers (1/4") are used

as standoffs to hold the board

edges above the rack. The boards

are mounted so the chips are in the

back and the pins are wiring are

visible from the front.

Power is distributed by 2 heavy

aluminum bus bars mounted

vertically, one per side, on the back

of the module. Machine screws are

mounted through the bus bars at

evenly-spaced intervals to provide

connection points for the boards.

Solid copper wire (24 gauge) connects the boards to the bus bars. Ring terminals are used

on the bus bar side of the connection. On the circuit board size, the wires are soldered

directly to the supply rails.

Materials were purchased from Home Depot, ACE Hardware, and Radio Shack.

Circuit Boards

The circuit boards are 13"x5" general purpose prototyping boards, epoxy glass with double-

side plated through pads on 0.1" centers (JAMECO 21477CL).

ICs are mounted in level 3 machine tooled wire-wrap sockets: 8, 14,

16, 20, 24, and 28 pin (JAMECO). Each socket has the pin-out labeled

with a w ire-wrap socket ID marker, which slips onto the socket before

wrapping (JAMECO). The part number is written onto the ID marker.

Sockets are arranged in 4 horizontal rows on each board, with about

10 sockets per row.

Power is distributed on the back-side of each board by bare 24-gauge

solid copper wire supply rails soldered at equal intervals to Klipwrap terminals: 3-prong

terminals with a square tail for wire-wrapping (JAMECO 34163CL). A +5V rail runs above

each row of sockets and a ground rail runs below. Each rail connects directly to the aluminum

module power bus using a ring tail connector.

Page 191: Apollo Guidance Computer AGC

On the pin side of the board, all connections are made with 30 AWG Kynar wire-wrap wire

(JAMECO). Red wire is used for direct connections to the +5V supply rail. Black wire is used

for direct connections to ground. White wire is used for everything else.

Power connections from the supply rails to each ICs are double-wrapped. Bypassing

capacitors (.1 uf disc ) are soldered across the supply rails at the Klipwrap terminals; about 1

capacitor for every 2 IC packages.

All connections were stripped and hand-wrapped using a Radio Shack hand-wrap tool. As

each connection was made, the corresponding line on the schematic was marked with a

colored highlighter.

DIP resistor networks (JAMECO) plugged into 20-pin wire-wrap sockets were used as current

limiting resistors for the panel indicators.

Page 192: Apollo Guidance Computer AGC

PROC Printed Circuit Board (PCB) A

The A board contains display drivers for the B board (left side), buffers for the interfaces to

external modules (bottom right), and priority counter logic (upper right). Sockets for 3 IDE

interface cables to external modules are visible at the bottom.

Page 193: Apollo Guidance Computer AGC

PROC Printed Circuit Board (PCB) B

The B board contains the display indicators, their current limiting resistor networks, and the

open collector drivers. The display panel is a sheet of white styrene plastic. A push pin was

used to make holes through the plastic and the LEDs were inserted in rows. The panel was

hand-lettered with an indelible marker.

Page 194: Apollo Guidance Computer AGC

PROC Printed Circuit Board (PCB) C

The C board contains the the logic for the interrupt (INT) subsystem (upper half of the

board), and the central registers (CRG; lower half of the board).

Page 195: Apollo Guidance Computer AGC

PROC Printed Circuit Board (PCB) D

The D board contains the ALU logic. The large 74181 ALU chips are at the bottom right. The

four chips that form the ADDER are in the bottom half of the board, slightly to the right of

the middle.

Page 196: Apollo Guidance Computer AGC

Parts (ICs)

IC’s, sockets, PCB’s, resistors, capacitors, wire-wrap wire were purchased from JAMECO. IDE

wire-wrap sockets were from DigiKey. Wire ties, wire-wrap tools, and copper wire were from

Radio Shack. IDE ribbon cables were purchased from an online computer supplier.

74LS00 (9) U60,U66,U57,U53,U51,U44,U46,U47,U42

74LS02 (4) U70,U6,U49,U2

74LS04 (11) U54,U45,U37,U68,U7,U36,U69,U71,U59,U48,U72

74LS06 (26) U28,U29,U30,U31,U27,U26,U23,U24,U25,U22,U21,U20,U18,U19,U17,U

16,U15,U12,U13,U14,U11,U10,U35,U34,U33,U32

74LS08 (4) U63,U61,U56,U52

74LS10 (2) U50,U43

74LS20 (2) U67,U73

74LS21 (1) U1

74LS27 (1) U9

74LS32 (5) U4,U41,U40,U39,U38

74LS83 (4) U134,U135,U136,U137

74LS86 (1) U5

74LS112 (7) U65,U64,U62,U58,U55,U8,U3

74LS138 (4) U84,U85,U86,U94

74LS148 (2) U93,U97

74LS151 (2) U87,U88

74LS181 (4) U130,U131,U132,U133

74LS244 (33) U74,U75,U76,U77,U78,U79,U80,U81,U82,U83,U89,U90,U95,U96,U101,

U102,U104,U105,U108,U111,U112,U115,U116,U117,U118,U119,U120,

U121,U122,U124,U125,U128,U129

74LS273 (19) U91,U92,U98,U99,U100,U103,U106,U107,U109,U110,U113,U114,U123

,U126,U127,U138,U139,U140,U141

Power Budget

qty mA (ea) mA (tot)

74LS00 9 2.4 21.6

74LS02 4 2.4 9.6

74LS04 11 3.6 39.6

74LS06 26 3.6 93.6

74LS08 4 4.4 17.6

74LS10 2 1.8 3.6

74LS20 2 1.2 2.4

74LS21 1 2.2 2.2

74LS27 1 3.4 3.4

74LS32 5 4.9 24.5

74LS83 4 22.0 88.0

74LS86 1 6.1 6.1

74LS112 7 4.0 28.0

74LS138 4 6.3 25.2

74LS148 2 12.0 24.0

74LS151 2 6.0 12.0

74LS181 4 21.0 84.0

74LS244 33 32.0 1056.0

Page 197: Apollo Guidance Computer AGC

74LS273 19 17.0 323.0

LED 153 20.0 3060.0

-----

4.9 Amps total

1.9 Amps (excluding LEDs)

Page 198: Apollo Guidance Computer AGC

Block IApollo Guidance Computer (AGC)

How to build one in your basement

Part 4: Memory (MEM) Module

John Pultorak

December, 2004

Page 199: Apollo Guidance Computer AGC

Abstract

This report describes my successful project to build a working reproduction of the 1964

prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the

Apollo moon landings, and is the world’s first integrated circuit computer.

I built it in my basement. It took me 4 years.

If you like, you can build one too. It will take you less time, and yours will be better than

mine.

I documented my project in 9 separate .pdf files:

Part 1 Overview: Introduces the project.

Part 2 CTL Module: Design and construction of the control module.

Part 3 PROC Module: Design and construction of the processing (CPU) module.

Part 4 MEM Module: Design and construction of the memory module.

Part 5 IO Module: Design and construction of the display/keyboard (DSKY) module.

Part 6 Assembler: A cross-assembler for AGC software development.

Part 7 C++ Simulator: A low-level simulator that runs assembled AGC code.

Part 8 Flight Software: My translation of portions of the COLOSSUS 249 flight

software.

Part 9 Test & Checkout: A suite of test programs in AGC assembly language.

Page 200: Apollo Guidance Computer AGC

Overview

The Memory Module (MEM) has 5 subsystems: MMI, ADR, EMM/FMM, MBF, and PAR

MMI (Memory Module external

Interface)

The MMI interfaces other memory

module subsystems (ADR, EMM/FMM,

MBF, and PAR; described below) to

external AGC modules. 40-pin IDE

connectors interface to the PROC and

CTL modules. Inputs from those

modules are buffered to 1 LSTTL load.

A 1-pin connector interfaces to the IO

module.

EMM/FMM (Eraseable/Fixed

Memory)

The EMM/FMM is the AGC memory.

AGC memory is 16-bit words,

organized into 1024 word banks. The

lowest bank (bank 0) is erasable

memory (EMM), originally implemented

as core, but implemented here as RAM.

All banks above bank 0 are fixed

memory (originally implemented as

rope core, but implemented here as

EPROM). The Block I AGC initially had

12K words of fixed memory. This

implementation has 15K.

The MSB (bit 16) in memory is an odd

parity bit. The lower 15 bits hold

instructions or data.

MBF (Memory Buffer Register)

The MBF has the 16-bit memory buffer

register which holds 16-bit data words moving to and from memory. This is also called the G

register.

The AGC transfers data to and from memory through the G register during the "memory

cycle." The memory cycle takes 12 timing pulses (11.72 microseconds). During AGC

operation, data words cycle continuously from memory to the G register and then back

again to memory.

There are four locations in eraseable memory, at addresses 20-23 (octal), dubbed "editing

locations" because whatever was stored there would emerge shifted or rotated by one bit

position. This shifting is performed in the MBF.

PAR (Parity Generate and Test)

The PAR generates and tests the memory parity bit. The lower 15 bits of each memory word

Page 201: Apollo Guidance Computer AGC

hold AGC instructions or data. Each word is protected by a 16th "odd parity" bit. This bit is

set to 1 or 0 by a parity generator circuit so a count of the 1's in each memory word always

produces an odd number. A parity checking circuit tests the parity bit during each memory

cycle; if the bit doesn't match the expected value, the memory word is assumed to be

corrupted and a PARITY ALARM panel light illuminates on the IO module.

ADR (Memory Address)

The ADR constructs the AGC memory address. The address is formed from the S register

which holds the lower 12-bits that directly address the lowest 4K of memory, and the BANK

register, which selects higher memory banks when addressing is in the fixed-switchable

mode.

Page 202: Apollo Guidance Computer AGC

The AGC transfers data to and from memory through the G register in a process called the

"memory cycle." The memory cycle takes 12 timing pulses (11.72 microseconds). The cycle

begins at tim ing pulse 1 (TP1) when the AGC loads the memory address to be fetched into

the S register in ADR. Memory hardware retrieves the data word from memory at the

address specified by the S register. Words from erasable memory are deposited into the G

register by timing pulse 6 (TP6); words from fixed memory are deposited by timing pulse 7.

The retrieved

memory word is

then available in the

G register for AGC

access during timing

pulses 7 through 10.

After timing pulse

10, data in the G

register is written

back to memory.

The memory address

is formed from the

12-bit S register and

the 4-bit BANK

register. Memory in

the lowest 4 1K

banks is directly

addressed by the S

register. The higher

1K banks (5-12) are

address through the

bank register as

described in the ADR

subsystem section of

this document.

The high-order bit in

memory (bit 15) is an

odd parity bit. If the

memory word is a

data word, the 14th bit

is the sign, and bits

13 through 1 hold the

magnitude. The

number

representation is 1's

complement.

The first half of the

memory cycle copies

data from memory to

the G register, The

sign bit in memory

(bit 14) is copied to bits 15 and 14 of the G register. Bits 13 through 1 in memory are

Page 203: Apollo Guidance Computer AGC

copied to bits 13 through 1 in G. This is performed in the MBF and EMM/FMM subsystems.

The parity bit (bit 16 in memory) is read by the PAR subsystem and tested against parity

generated on the memory word copied into G. If the parity bits fail to match, a parity alarm

is generated.

The 14th bit in the G register (and the central registers in the AGC) is called the Uncorrected

Sign (US). This extra sign bit is used as an overflow indication in multi-word operations.

Normally, the Sign and Uncorrected sign should agree. When overflow or underflow

conditions occur, both signs will disagree, and are reconciled by software in an operation at

the end of a long string of multi-word computations.

At the end of the memory cycle, the G register is copied back to memory. The sign bit in G

(bit 15) is written to the sign bit (bit 14) in memory. Bits 13 through 1 in G are written to

bits 13 through 1 in memory. A new odd parity bit is computed in the PAR subsystem and

written to the 16th bit in memory.

Page 204: Apollo Guidance Computer AGC

These diagrams

show the timing

of the memory

cycle. The top

chart is a little

more

conceptual; the

bottom chart

shows the clock

cycles and

control pulses

directly

associated with

reading

eraseable

memory

(SBEWG) or

fixed memory

(SBFWG) to the

G register (the

‘WG’ part

means ‘write to

G’). The WE

pulse writes G

back to memory.

CLK1 steps the

sequencer in the

CTL module that

enables the

control signals.

The signals have

time to settle

between CLK1

and CLK2. Data

transfer occurs

on CLK2.

Page 205: Apollo Guidance Computer AGC

This is a functional

diagram of the ADR,

EMM/FMM, and MBF

subsystems in the

MEM module.

The diagram is mine,

but the style is

borrowed from

original AGC

documentation:

control signals are

represented by

diamonds. The

arrows show the

direction of data

flow. When a control

signal is asserted,

data is allowed to

flow through the

diamond.

For example, when

WE is asserted, the

contents of the G

register are written

into eraseable

memory (bank 0).

Note the different

formats for data and

instruction word in

memory, shown at

the bottom of the

diagram.

Page 206: Apollo Guidance Computer AGC

This is a functional

diagram of the

PAR subsystem in

the MEM module.

The diagram was

developed during

the early stages of

my AGC

architecture

analysis in 2001.

Page 207: Apollo Guidance Computer AGC

MEM Internal Subsystem InterconnectionsThis diagram shows internal interconnections for subsystems in the MEM module.

Page 208: Apollo Guidance Computer AGC

MEM Module External Interfaces

The MEM module interfaces to the PROC and CTL modules through 40-pin IDE ribbon cables.

Page 209: Apollo Guidance Computer AGC

J102-CTL: CTL-to-MEM I/F

J102 is a 40-pin IDE cable that connects the MEM module to the CTL module.

INPUTS (to CTL):

PIN signal full name state definition

1 WE WRITE EMEM (97) 0=Write E-MEM from G

2 SBWG WRITE G (95) 0=Write G from memory

3 GENRST GENERAL RESET (86) 0=General Reset

4 W23 WRITE ADDR 23 (85) 0=Write into SL

5 W22 WRITE ADDR 22 (84) 0=Write into CYL

6 W21 WRITE ADDR 21 (83) 0=Write into SR

7 W20 WRITE ADDR 20 (82) 0=Write into CYR

8 WGn WRITE G NORMAL (81) 0=Write G (normal gates)

9 WBK WRITE BNK (80) 0=Write BNK reg

10 RBK READ BNK (70) 0=Read BNK reg

11 WS WRITE S (46) 0=Write S

12 WP2 WRITE P2 (44) 0=Write P2

13 WPx WRITE P NO RESET (43) 0=Write P (do not reset)

14 WP WRITE P (42) 0=Write P

15 WGx WRITE G NO RESET (37) 0=Write G (do not reset)

16 TP TEST PARITY (30) 0=Test parity

17 RP2 READ PARITY 2 (14) 0=Read parity 2

18 RG READ G (12) 0=Read G

19 GP GEN PARITY (5) 0=Generate Parity

20 CLG CLR G (2) 0=Clear G

21 CLK2 CLOCK2 1.024 MHz AGC clock phase 2 (normally

low)

22 CLK1 CLOCK1 1.024 MHz AGC clock phase 2 (normally

low)

23 NPURST POWER UP RESET 0=reset, 1=normal operation.

24 SWCLK DEBOUNCE CLOCK low freq clk for switch debounce (not

used)

25 FCLK CLOCK MODE 1=free-running clk mode; 0=single clk

mode

OUTPUTS (from CTL):

PIN signal full name state definition

31 EQU_16 ADDRESS = 016 (1) 0=CADR in register S = 016

32 EQU_17 ADDRESS = 017 (2) 0=CADR in register S= 017

33 GTR_17 ADDRESS > 017 (3) 0=CADR in register S > 017

34 EQU_25 ADDRESS = 025 (4) 0=CADR in register S = 025

35 GTR_27 ADDRESS > 027 (5) 0=CADR in register S > 027

36 GTR_1777 ADDRESS > 01777 (6) 0=CADR in register S > 01777

37 AD_1 ADDRESS (1) where AD_4 is MSB, AD_1 is LSB

38 AD_2 ADDRESS (2)

39 AD_3 ADDRESS (3)

40 AD_4 ADDRESS (4)

Page 210: Apollo Guidance Computer AGC

J105-MEM: MEM-to-PROC I/F

J102 is a 40-pin IDE cable that connects the MEM module to the PROC module.

INPUTS (to MEM):

PIN signal full name state definition

1 WB_01 WRITE BUS 01 (lsb)

2 WB_02 WRITE BUS 02

3 WB_03 WRITE BUS 03

4 WB_04 WRITE BUS 04

5 WB_05 WRITE BUS 05

6 WB_06 WRITE BUS 06

7 WB_07 WRITE BUS 07

8 WB_08 WRITE BUS 08

9 WB_09 WRITE BUS 09

10 WB_10 WRITE BUS 10

11 WB_11 WRITE BUS 11

12 WB_12 WRITE BUS 12

13 WB_13 WRITE BUS 13

14 WB_14 WRITE BUS 14

15 WB_15 WRITE BUS 15 US (overflow) bit

16 WB_16 WRITE BUS 16 SG (sign) bit

OUTPUTS (from MEM):

PIN signal full name state definition

40 RB_01 READ BUS 01 (lsb)

39 RB_02 READ BUS 02

38 RB_03 READ BUS 03

37 RB_04 READ BUS 04

36 RB_05 READ BUS 05

35 RB_06 READ BUS 06

34 RB_07 READ BUS 07

33 RB_08 READ BUS 08

32 RB_09 READ BUS 09

31 RB_10 READ BUS 10

30 RB_11 READ BUS 11

29 RB_12 READ BUS 12

28 RB_13 READ BUS 13

27 RB_14 READ BUS 14

26 RB_15 READ BUS 15 US (overflow) bit

25 RB_16 READ BUS 16 SG (sign) bit

22 BUSY7 READ BUS BUSY 0=BNK register output to read bus

21 BUSY5 READ BUS BUSY 0=G register output to read bus

Page 211: Apollo Guidance Computer AGC
Page 212: Apollo Guidance Computer AGC
Page 213: Apollo Guidance Computer AGC

MEM CONTROL PANEL SWITCHES

AGC/MANUAL Permits memory to be examined and loaded when the switch is in the

MANUAL position and the AGC is halted.

EXAM Loads the address counter with the contents of the switch register. To

work, the following switches must also be set: AGC/MANUAL -->

MANUAL

NEXT Steps the address to the next location. To work, the following switches

must also be set: AGC/MANUAL --> MANUAL

READ/WRITE Displays memory contents in the READ position; displays switch

register contents in the WRITE position.

LOAD Load memory with data manually entered into the switch register. To

work, the following switches must also be set prior to LOAD: CLOCK

CONTROL (on CTL module) --> STEP; AGC/MANUAL --> MANUAL;

READ/WRITE --> WRITE

CLEAR PARITY Clears a parity alarm indication by resetting the parity alarm (PALM)

register. The parity alarm indicator is on the IO module.

Page 214: Apollo Guidance Computer AGC

MEM CONTROL SWITCH CONNECTIONS

PIN signal state definition

1 READ/WRITE GND=read

2 AGC/MANUAL GND=manual

3 EXAM GND=examine

4 NEXT GND=examine next

5 CLEAR PARITY GND=clear

6 LOAD LOAD switch contact

7 LOAD LOAD switch contact

PIN signal full name state definition

1 D1 DATA1 LSB on switch bus 101

2 D2 DATA2

3 D3 DATA3

4 D4 DATA4

5 D5 DATA5

6 D6 DATA6

7 D7 DATA7

8 D8 DATA8

9 D9 DATA9

10 D10 DATA10

11 D11 DATA11

12 D12 DATA12

13 D13 DATA13

14 D14 DATA14

15 D15 DATA15

16 D16 DATA16 LSB on switch bus 101

17 GND GND

Page 215: Apollo Guidance Computer AGC

MEM INDICATORS

These indicator lamps show the

current state of all registers and

some additional, important logic

signals produced by the MEM

module. AGC numbers are

represented in octal, so all

register lamps are in groups of

three. At the time the photo was

taken the AGC was running

the COLOSSUS 249 flight

software load, executing Verb

16, Noun 36: a monitor verb

which disp lays the AGC real time

clock.

Page 216: Apollo Guidance Computer AGC
Page 217: Apollo Guidance Computer AGC
Page 218: Apollo Guidance Computer AGC
Page 219: Apollo Guidance Computer AGC

ADR (Memory Address)

The AGC has a 14-bit address range. Memory address is selected by the 12-bit S register

and the 4-b it BANK register.

S: the 12-bit memory address register, which holds the lower portion of

the memory address.

BANK: the 4-bit memory bank register, which selects the memory bank when

addressing is in the fixed-switchable mode.

Each AGC instruction has a 12-bit address field. The lower bits (1-10) address memory

inside each bank. Bits 11 and 12 select the bank:

00: selects the erasable memory bank; the BANK register is ignored.

01: selects the lowest bank (bank 1) of fixed memory; the BANK register is

ignored.

10: selects the next bank (bank 2) of fixed memory; the BANK register is

ignored.

11: selects the BANK register, which is used to address any bank above 2.

If the BANK register contains 0, 1, or 2, the BANK register is

overridden and bank 3 is selected.

Banks 1 and 2 are called "fixed-fixed" memory, because they are always available,

regardless of the contents of the BANK register. Banks 3 and above are called

"fixed-switchable" because the selected bank is determined by the BANK register.

Type:

E Eraseable Memory

FF Fixed-Fixed Memory

FS Fixed-Switchable Memory

S Register:

14-bit BANK bits 12-bit

address bank type Reg. 12,11 address

00000 - 01777 0 (E) ignored 00 0000 - 1777

02000 - 03777 1 (FF) ignored 01 2000 - 3777

04000 - 05777 2 (FF) ignored 10 4000 - 5777

06000 - 07777 3 (FS) 0000 - 0011 11 6000 - 7777

10000 - 11777 4 (FS) 0100 11 6000 - 7777

12000 - 13777 5 (FS) 0101 11 6000 - 7777

14000 - 15777 6 (FS) 0110 11 6000 - 7777

16000 - 17777 7 (FS) 0111 11 6000 - 7777

20000 - 21777 8 (FS) 1000 11 6000 - 7777

22000 - 23777 9 (FS) 1001 11 6000 - 7777

24000 - 25777 10 (FS) 1010 11 6000 - 7777

26000 - 27777 11 (FS) 1011 11 6000 - 7777

30000 - 31777 12 (FS) 1100 11 6000 - 7777

BANK register (B) + S register (S) Decodes to address:

B4 B3 B2 B1 S12 S11 A14 A13 A12 A11

X X X X 0 0 0 0 0 0

X X X X 0 1 0 0 0 1

Page 220: Apollo Guidance Computer AGC

X X X X 1 0 0 0 1 0

0 0 0 0 1 1 0 0 1 1

0 0 0 1 1 1 0 0 1 1

0 0 1 0 1 1 0 0 1 1

0 0 1 1 1 1 0 0 1 1

0 1 0 0 1 1 0 1 0 0

0 1 0 1 1 1 0 1 0 1

0 1 1 0 1 1 0 1 1 0

0 1 1 1 1 1 0 1 1 1

1 0 0 0 1 1 1 0 0 0

1 0 0 1 1 1 1 0 0 1

1 0 1 0 1 1 1 0 1 0

1 0 1 1 1 1 1 0 1 1

1 1 0 0 1 1 1 1 0 0

1 1 0 1 1 1 1 1 0 1

1 1 1 0 1 1 1 1 1 0

1 1 1 1 1 1 1 1 1 1

X=don’t care

This is an early conceptual diagram of

ADR architecture. The WRITE bus loads

the BNK register or S register. Outputs

from both registers feed into the bank

decoder to generate the bank address.

Page 221: Apollo Guidance Computer AGC

The ADR generates some logic

signals to test the address.

These are internally used in

MEM and also made available

to the external modules. The

GTR signals test whether the

generated address is greater

than 1777, 27, or 17 (all octal).

The EQU logic tests whether the

generated address is equal to a specific

value: 14, 16, 17, or 25.

Page 222: Apollo Guidance Computer AGC

The bank select logic chooses

between the S register or a

combination of the S register

and the bank register to

generate address bits 14-11. It

uses S register bits 11 and 12

to make the decision. The

selection signal enables tri-

state buffer A or B to produce

the correct bank address.

Page 223: Apollo Guidance Computer AGC

ADR INPUTS:

I/F signal full name state definition

CLK:

CLK1 CLOCK 1 1=read bus setup; inhibit read bus output

CLK2 CLOCK 2 data transfer occurs on falling edge

CPM:

GENRST GENERAL RESET 0=reset ADR registers

RBK READ BANK 0=output BNK register to read bus

WBK WRITE BANK 0=write into BNK register

from write bus

WS WRITE S 0=write into S register

from write bus

WBUS:

WB_01 WRITE BUS 01

...

WB_14 WRITE BUS 14

ADR OUTPUTS:

I/F signal full name state definition

MEM:

AD_11 ADDRESS BUS 11 bank select bits

...

AD_14 ADDRESS BUS 14

AD_1 ADDRESS BUS 1 low order address

...

AD_10 ADDRESS BUS 10

various:

EQU_16 ADDRESS = 016 0=CADR in reg S = 016

EQU_17 ADDRESS = 017 0=CADR in reg S = 017

GTR_17 ADDRESS > 017 0=CADR in reg S > 017

EQU_25 ADDRESS = 025 0=CADR in reg S = 025

GTR_27 ADDRESS > 027 0=CADR in reg S > 027

GTR_1777 ADDRESS > 01777 0=CADR in reg S > 01777

RBUS:

RB_01 READ BUS 01

...

RB_16 READ BUS 16

BUSY READ BUS BUSY 0=output to read bus

Page 224: Apollo Guidance Computer AGC
Page 225: Apollo Guidance Computer AGC
Page 226: Apollo Guidance Computer AGC
Page 227: Apollo Guidance Computer AGC
Page 228: Apollo Guidance Computer AGC

EMM/FMM (Eraseable/Fixed Memory)

MEM INPUTS:

I/F signal full name state definition

CLK:

CLK2 CLOCK 2 data transfer occurs on CLK2

CPM:

WE WRITE ERASEABLE 0=write memory bus to

eraseable memory

SBWG WRITE G (MEM) 0=read eraseable or fixed

memory onto memory bus

ADR: GTR_1777 ADDRESS > 01777 0=CADR in reg S > 01777

AD_01 ADDRESS BUS 01

...

AD_10 ADDRESS BUS 10

AD_11 ADDRESS BUS 11 bank select portion of

address bus

...

AD_14 ADDRESS BUS 14 bank select portion of

address bus

BIDIRECTIONAL (IN/OUT):

I/F signal full name state definition

EMM/FMM:

MEM_01 MEMORY_BUS 01 Memory word formats:

... inst: 15-13:op code; 12-1:address

MEM_15 MEMORY_BUS 15 data: 15:SG; 14-1 data

MEM_16 MEMORY_BUS 16 parity (odd) bit for memory bus

Page 229: Apollo Guidance Computer AGC
Page 230: Apollo Guidance Computer AGC
Page 231: Apollo Guidance Computer AGC

MBF (Memory Buffer Register)

The AGC has a 16-

bit G register for

transferring data to

and from memory.

WRITE bus data can

be written directly

into the G register,

or can be bit-shifted

before writing. Data

from the G register

can be copied to the

READ bus, or to the

memory bus.

The following

section shows how

bits are shifted in

bus-to-register-to-

memory transfers.

The row of 16

comma-separated

entries represent bit

locations at the

destination; the leftmost entry is the MSB, and the rightmost is the LSB. The designation in

each location identifies source bit location. This will become clearer shortly.

In memory, the 16th bit is the odd parity bit, and the 15th bit is the sign. In the G register,

the bits are flipped: the 16th bit is the sign, and the 15th bit is the parity. The WE pulse,

which writes from the G register to memory, causes the sign bit (SG; bit 16 in G) to be

written to bit 15 in memory. Parity is written to memory from the parity generator (PAR),

not from the parity bit in G. (The G parity bit holds the parity read from memory.)

WE:

BX, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1

Data is written from memory to G by the SBWG control pulse. The sign in memory (SG; bit

15) is written to bit 16 in G. The parity bit (bit 16 in memory) is written to bit 15 in G by the

PAR subsystem.

SBWG:

SG, BX, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1

Data is written into G from the WRITE bus using WG (no shift), or one of the following

control pulses that produce the following shifts:

W20:

B1, BX, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2

Page 232: Apollo Guidance Computer AGC

W21:

SG, BX, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2

W22:

B14, BX, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1, SG

W23:

SG, BX, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1, SG

Data is read from G to the READ bus as follows. The parity bit (bit 15 in G) is not transferred

to the read bus; instead, the sign bit is copied onto bits 15 and 16 of the READ bus.

RG:

SG, SG, B14, B13,

B12, B11, B10, B9, B8,

B7, B6, B5, B4, B3, B2, B1

Some of the design that

went into the

combinational logic that

sets bit 16 in the G

register from the READ

bus is shown here. The

MB_B16 output controls

the 16th bit for the W20

and W21 control pulses.

Page 233: Apollo Guidance Computer AGC

The MB_C16 output controls the

16th bit for the W22 and W23

control pulses.

Page 234: Apollo Guidance Computer AGC

MBF INPUTS:

I/F signal full name state definition

CLK:

CLK1 CLOCK 1 1=read bus setup; inhibit read bus output

CLK2 CLOCK 2 data transfer occurs on falling edge

CPM:

RG READ G 0=output G register to read/write bus

WE WRITE ERASEABLE 0=output G register to memory bus

GTR_17 ADDRESS > 017 0=CADR in register S > 017

SBWG WRITE G (MEM) 0=write G from memory bus

WGN WRITE G 0=write G from read/write

bus (no shift)

WGX WRITE G 0=write G from read/write

bus (no shift)

W20 WRITE G (SHIFT) 0=write G

W21 WRITE G (SHIFT) 0=write G

W22 WRITE G (SHIFT) 0=write G

W23 WRITE G (SHIFT) 0=write G

GENRST GENERAL RESET 0=General Reset

WBUS:

WB_01 WRITE BUS 01

...

WB_14 WRITE BUS 14

WB_15 WRITE BUS 15 US (overflow) bit for write

bus

WB_16 WRITE BUS 16 SG (sign) bit for write bus

MBF OUTPUTS:

I/F signal full name state definition

RBUS:

RB_01 READ BUS 01

...

RB_14 READ BUS 14

RB_15 READ BUS 15 US (overflow) bit for read/write bus

RB_16 READ BUS 16 SG (sign) bit for read/write bus

BUSY READ BUS BUSY 0=output enabled to read bus

Page 235: Apollo Guidance Computer AGC

BIDIRECTIONAL (IN/OUT):

I/F signal full name state definition

EMM/FMM:

MEM_01 MEMORY_BUS 01 Memory word formats:

... inst: 15-13:op code; 12-1:address

MEM_15 MEMORY_BUS 15 data: 15:SG; 14-1 data

MEM_16 MEMORY_BUS 16 parity (odd) bit for memory bus

Page 236: Apollo Guidance Computer AGC
Page 237: Apollo Guidance Computer AGC
Page 238: Apollo Guidance Computer AGC

PAR (Parity Generation and Test)

The PAR subsystem checks

the memory parity bit

during each memory cycle

and generates an alarm if

the parity bit in memory

does not match the

expected odd parity. The

PAR subsystem also

generates parity from the

contents of G and writes

this parity back to memory.

Page 239: Apollo Guidance Computer AGC

This block diagram of the PAR

subsystem emerges from the

previous diagram.

This is the combinational

logic used to generate

the input to the G15

register. This is the 1-bit

register that holds bit 15

(the parity bit) for the G

register. The remainder

of the G register (bits 1-

14 and bit 16) is in the

MBF subsystem.

The minterms are written

out on top. DeMorgan’s

Theorem and a little

bubble-pushing changes

the OR gate into a NAND.

Page 240: Apollo Guidance Computer AGC

PAR INPUTS:

I/F signal full name state definition

CLK:

CLK2 CLOCK 2 data transfer occurs on

falling edge

CPM:

RG READ G15 0=write G15 into P

RP2 READ P2 0=write P2 into G15

WP WRITE P 0=write P (same as WPX)

WPX WRITE P 0=write P (same as WP)

WP2 WRITE P2 0=write P2 from 1-15

generator

SBWG WRITE G15 (MEM) 0=write G15 from memory

parity bit

GP WRITE G15 0=write G15 from 1-15

generator (same as WGX)

WGX WRITE G15 0=write G15 from 1-15

generator (same as GP)

CLG CLEAR G15 0=clear G15

TP TEST PARITY 0=test parity from P-15

ADR:

GTR_27 ADDRESS > 027 0=CADR in Register S evaluates to > 027

WBUS:

WB_01 WRITE BUS 01

...

WB_14 WRITE BUS 14

WB_15 WRITE BUS 15 US (overflow) bit for write bus

WB_16 WRITE BUS 16 SG (sign) bit for write bus

MON:

CLRPLM CLEAR PARITY ALM 0=clear parity alarm

PAR OUTPUTS:

I/F signal full name state definition

MON

PARALM PARITY ALARM 1=parity alarm

Page 241: Apollo Guidance Computer AGC

BIDIRECTIONAL (IN/OUT):

I/F signal full name state definition

EMM/FMM:

MEM_16 MEMORY_BUS 16 parity (odd) bit for memory bus

Page 242: Apollo Guidance Computer AGC
Page 243: Apollo Guidance Computer AGC
Page 244: Apollo Guidance Computer AGC

Fabrication

The MEM module is (3) 13"x5" circuit boards, and 1 control panel.

Module Rack

The module framework is designed

to resemble a relay rack, but

scaled to fit the circuit board

dimensions. It is constructed out

of 1"x2" pine and spray-painted

semi-gloss gray.

Circuit boards are mounted to the

rack by 2 phillips screws at either

end. Nylon spacers (1/4") are

used as standoffs to hold the

board edges above the rack. The

boards are mounted so the chips

are in the back and the pins are

wiring are visib le from the front.

Power is distributed by 2 heavy

aluminum bus bars mounted

vertically, one per side, on the

back of the module. Machine

screws are mounted through the bus bars at evenly-spaced intervals to provide connection

points for the boards.

Solid copper wire (24 gauge) connects the boards to the bus bars. Ring terminals are used

on the bus bar side of the connection. On the circuit board size, the wires are soldered

directly to the supply rails.

Materials were purchased from Home Depot, ACE Hardware, and Radio Shack.

Circuit Boards

The circuit boards are 13"x5" general purpose prototyping boards,

epoxy glass with double-side plated through pads on 0.1" centers

(JAMECO 21477CL).

ICs are mounted in level 3 machine tooled wire-wrap sockets: 8, 14,

16, 20, 24, and 28 pin (JAMECO). Each socket has the pin-out labeled

with a w ire-wrap socket ID marker, which slips onto the socket before

wrapping (JAMECO). The part number is written onto the ID marker.

Sockets are arranged in 4 horizontal rows on each board, with about

10 sockets per row.

Power is distributed on the back-side of each board by bare 24-gauge solid copper wire

supply rails soldered at equal intervals to Klipwrap terminals: 3-prong terminals with a

square tail for wire-wrapping (JAMECO 34163CL). A +5V rail runs above each row of sockets

Page 245: Apollo Guidance Computer AGC

and a ground rail runs below. Each rail connects directly to the aluminum module power bus

using a ring tail connector.

On the pin side of the board, all connections are made with 30 AWG Kynar wire-wrap wire

(JAMECO). Red wire is used for direct connections to the +5V supply rail. Black wire is used

for direct connections to ground. White wire is used for everything else.

Power connections from the supply rails to each ICs are double-wrapped. Bypassing

capacitors (.1 uf disc ) are soldered across the supply rails at the Klipwrap terminals; about

1 capacitor for every 2 IC packages.

All connections were stripped and hand-wrapped using a Radio Shack hand-wrap tool. As

each connection was made, the corresponding line on the schematic was marked with a

colored highlighter.

DIP resistor networks (JAMECO) plugged into 20-pin wire-wrap sockets were used as current

limiting resistors for the panel indicators.

Page 246: Apollo Guidance Computer AGC

MEM Printed Circuit Board (PCB) A

The A board contains the zero-insertion force (ZIF) sockets for the fixed memory EPROMs,

and the 2 40-pin IDE connectors that interface to the other modules. The eraseable

memories (U101, U102) are also clearly visible next to the EPROMs. The Memory Address

(ADR) and Eraseable/Fixed Memory (EMM/FMM) subsystems are primarily located on this

board.

Page 247: Apollo Guidance Computer AGC

MEM Printed Circuit Board (PCB) B

The B board contains the display indicators, their current-limiting resistor networks, and the

open collector drivers. The display panel is a sheet of white styrene plastic. A push pin was

used to make holes through the plastic and the LEDs were inserted in rows. The panel was

hand-lettered with an indelible marker.

Page 248: Apollo Guidance Computer AGC

MEM Printed Circuit Board (PCB) C

The C board primarily contains the Memory Buffer (MBF) and Parity Generation and Test

(PAR) subsystems.

Page 249: Apollo Guidance Computer AGC

Parts (ICs)

74LS00 (11) U50,U25,U26,U27,U40,U32,U33,U34,U43,U44,U53

74LS02 (3) U52,U31,U55

74LS04 (12) U39,U28,U51,U56,U48,U46,U45,U41,U30,U35,U36,U54

74LS06 (21) U20,U19,U18,U15,U16,U17,U14,U13,U12,U10,U11,U9,U6,U7,U8,U5,U

4,U21,U22,U23,U24

74LS10 (3) U49,U37,U42

74LS20 (2) U47,U29

74LS27 (2) U2,U38

74LS74 (1) U1

74LS86 (1) U3

74LS154 (1) U72

74LS193 (4) U63,U64,U65,U66

74LS244 (31) U57,U58,U59,U60,U61,U62,U67,U68,U69,U70,U71,U73,U83,U84,U85,

U86,U87,U88,U89,U90,U91,U92,U93,U94,U95,U96,U97,U98,U103,U10

4,U105

74LS273 (10) U74,U75,U76,U79,U80,U81,U82,U106,U107,U108

74S280 (2) U77,U78

27C128 (2) U99,U100

2016 (2) U101,U102

Power Budget

qty mA (ea) mA (tot)

74LS00 11 2.4 26.4

74LS02 3 2.4 7.2

74LS04 12 3.6 43.2

74LS06 21 3.6 75.6

74LS10 3 1.8 5.4

74LS20 2 1.2 2.4

74LS27 2 3.4 6.8

74LS74 1 4.0 4.0

74LS86 1 6.1 6.1

74LS154 1 6.2 6.2

74LS193 4 19.0 76.0

74LS244 31 32.0 992.0

74LS273 10 17.0 170.0

74LS280 2 16.0 32.0

27C128 2 25.0 50.0

2016 2 25.0 50.0

LED 124 20.0 2480.0

-------

4.0 Amps total

1.6 Amps (excluding LEDs)

Page 250: Apollo Guidance Computer AGC

Block IApollo Guidance Computer (AGC)

How to build one in your basement

Part 5: Input/Output (IO) Module

John Pultorak

December, 2004

Page 251: Apollo Guidance Computer AGC

Abstract

This report describes my successful project to build a working reproduction of the 1964

prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the

Apollo moon landings, and is the world’s first integrated circuit computer.

I built it in my basement. It took me 4 years.

If you like, you can build one too. It will take you less time, and yours will be better than

mine.

I documented my project in 9 separate .pdf files:

Part 1 Overview: Introduces the project.

Part 2 CTL Module: Design and construction of the control module.

Part 3 PROC Module: Design and construction of the processing (CPU) module.

Part 4 MEM Module: Design and construction of the memory module.

Part 5 IO Module: Design and construction of the display/keyboard (DSKY) module.

Part 6 Assembler: A cross-assembler for AGC software development.

Part 7 C++ Simulator: A low-level simulator that runs assembled AGC code.

Part 8 Flight Software: My translation of portions of the COLOSSUS 249 flight

software.

Part 9 Test & Checkout: A suite of test programs in AGC assembly language.

Page 252: Apollo Guidance Computer AGC

Overview

The I/O Module (IO) has 5 subsystems: IMI, KBD, INP, OUT, DSP

IMI (I/O Module

external Interface)

The IMI interfaces the

I/O module to other

AGC modules. 40-pin

IDE connectors

interface to the PROC

and CTL modules. A 1-

pin connector interfaces

to the MEM module.

Inputs taken those

modules are buffered to

1 LSTTL load.

KBD (Keyboard)

An 18-button keyboard;

the AGC’s flight

software user input

interface. The

keyboard/display unit is

called the DSKY.

INP (Input

Registers)

The AGC has 4 16-bit

input registers that

receive data from the

keyboard and discrete

logic signals. IN0 reads

from the keyboard and

the STANDBY ALLOWED

discrete signal. IN1-IN3

are not implemented in

this replica.

OUT (Output

Registers)

The AGC has 5 16-bit

output registers that

drive the DSKY display

and other spacecraft

subsystems. OUT0

writes to the DSKY

display; OUT1 drives

the 6 discrete indicator

lamps on the AGC DSKY

display; OUT2-OUT4

are not implemented in this replica.

Page 253: Apollo Guidance Computer AGC

DSP (Display)

A matrix of green 7-segment displays; the output side of the AGC’s flight software user

interface. There are (3) 5-digit displays with +/- signs which can display decimal or octal

data, and (3) 2-digit displays to show the current program (PROG), verb, and noun.

An additional panel of 6 indicator lamps shows AGC status and alarm states.

Page 254: Apollo Guidance Computer AGC

AGC input registers and

control signals that read

them onto the bus are

shown in the diagram to

the right. The 5-bit

keyboard code and

STANDBY ALLOWED switch

are read from “register 0"

(IN0) when the R4 (RA4)

control pulse is asserted.

The signal is R4 because

the register is mapped to

memory address 4. The

registers are actually

buffers, not latches.

Keyboard codes are latched

internally in the keyboard

subsystem.

The IN1, IN2, and IN3

registers are not

implemented in this

replica.

AGC output registers are shown in the next

figure. OUT0 drives the 7-segment DSKY

displays. W10 (WA10) loads data from the

write bus into the DSKY display; the “10" is

because it is mapped onto memory location 10

(octal). Each 16-bit word controls 2 digits on

the display. The digit pair is selected by a 4-bit

code at the top of the word.

OUT1 drives discrete indicator lamps on a

panel adjacent to the 7-segment display. W11

(WA11) writes to the register, and R11 (RA11)

reads from it.

The OUT2, OUT3, and OUT4 registers are not

implemented in this replica.

Page 255: Apollo Guidance Computer AGC

IO Internal Subsystem Interconnections

This diagram shows internal interconnections for the subsystems in the IO module.

Page 256: Apollo Guidance Computer AGC

IO Module External Interfaces

The IO module interfaces to the CTL and PROC modules through 40-pin IDE ribbon cables.

Page 257: Apollo Guidance Computer AGC

J103-IO: CTL-to-I/O I/F

INPUTS (to IO):

PIN signal full name state definition

1 CLK1 CLOCK1 1.024 MHz AGC clock phase 2 (normally

low)

2 CLK2 CLOCK2 1.024 MHz AGC clock phase 2 (normally

low)

3 NSA STANDBY ALLOWED 0=standby allowed

5 GENRST GENERAL RESET (86) 0=clear the DSKY, OUT1, and OUT2.

6 WA11 WRITE OUT1 (76) 0=write into OUT1 from write bus

7 WA10 WRITE OUT0 (75) 0=write into OUT0 (DSKY) from write bus

8 RA11 READ OUT1 (66) 0=output OUT1 register to read bus

9 RA4 READ IN0 (61) 0=output IN0 register to read bus

20 STBY STANDBY 0=AGC is in the standby state

OUTPUTS (from IO):

PIN signal full name state definition

40 OUT1_8 STANDBY ENABLED 1=standby enabled; works with STANDBY

ALLOWED switch

Page 258: Apollo Guidance Computer AGC

J104-IO: PROC-to-IO I/F

INPUTS (to IO):

PIN signal full name state definition

1 WB_01 WRITE BUS 01 (lsb)

2 WB_02 WRITE BUS 02

3 WB_03 WRITE BUS 03

4 WB_04 WRITE BUS 04

5 WB_05 WRITE BUS 05

6 WB_06 WRITE BUS 06

7 WB_07 WRITE BUS 07

8 WB_08 WRITE BUS 08

9 WB_09 WRITE BUS 09

10 WB_10 WRITE BUS 10

11 WB_11 WRITE BUS 11

12 WB_12 WRITE BUS 12

13 WB_13 WRITE BUS 13

14 WB_14 WRITE BUS 14

15 WB_15 WRITE BUS 15 US (overflow) bit

16 WB_16 WRITE BUS 16 SG (sign) bit

OUTPUTS (from IO):

PIN signal full name state definition

40 RB_01 READ BUS 01 (lsb)

39 RB_02 READ BUS 02

38 RB_03 READ BUS 03

37 RB_04 READ BUS 04

36 RB_05 READ BUS 05

35 RB_06 READ BUS 06

34 RB_07 READ BUS 07

33 RB_08 READ BUS 08

32 RB_09 READ BUS 09

31 RB_10 READ BUS 10

30 RB_11 READ BUS 11

29 RB_12 READ BUS 12

28 RB_13 READ BUS 13

27 RB_14 READ BUS 14

26 RB_15 READ BUS 15 US (overflow) bit

25 RB_16 READ BUS 16 SG (sign) bit

22 BUSY2 READ BUS BUSY 0=OUT registers output to read bus

21 BUSY1 READ BUS BUSY 0=INP registers output to read bus

20 KB_STR KEY STROBE 1=key pressed strobe; to KEYRUPT. Key

data is valid on the negative edge of

KB_STR. Data is latched until the next

keypress.

Page 259: Apollo Guidance Computer AGC
Page 260: Apollo Guidance Computer AGC
Page 261: Apollo Guidance Computer AGC

IO DISPLAY/KEYBOARD (DSKY)

The keyboard/display portion of the IO module contains a keyboard, a bank of 7-segment

displays, a panel of discrete indicator lamps, and a board of display drivers.

Page 262: Apollo Guidance Computer AGC

DSKY KEYBOARD

The DSKY has an 18-button keyboard:

0-9 Decimal (or octal) digits.

+ Plus sign for decimal entries.

- Minus sign for decimal entries.

VERB Tells the AGC the next 2 digits

entered will be a VERB.

NOUN Tells the AGC the next 2 digits

entered will be a NOUN.

ENTER Tells the AGC the data entry is

finished.

CLEAR Clears an error in entry.

ERR RST Resets the OPR ERR alarm lamp.

KEY REL Tells the AGC it can have control of

the display. If the AGC wants

control of the display, the KEL REL

lamp will be flashing.

Page 263: Apollo Guidance Computer AGC

DSKY 7-SEGMENT DISPLAY

COMP ACTY A green indicator lamp that

illuminates when the AGC is not

idle. The lamp is controlled by the

“dummy job”, the lowest priority

job in the AGC EXEC software’s

non-preemptive multitasking.

When the dummy job is running,

the lamp is extinguished because

the AGC is idle. When the dummy

job exits because there is a higher

priority job running, the lamp

illuminates. The light is driven by

bit 1 of OUT1.

PROG The 2-digit code for the current

AGC program. Driven by OUT0.

VERB The 2-digit code for the selected

VERB. Verbs are actions;

directives for the AGC to do

something, such as loading or

displaying memory data. Driven

by OUT0.

NOUN The 2-digit code for the selected

NOUN. The noun is the thing

acted upon by the verb. Nouns usually refer to memory locations, which are

mapped to some AGC function. Driven by OUT0.

R1 Register 1. The uppermost of the three 5-digit displays. Registers R1, R2, and

R3 can display data in octal or decimal. Octal data is displayed without a sign.

Decimal data is indicated by the presence of a + or - sign in front of the data.

The displays I used in my replica cannot display a + sign, so I modified the

logic slightly: decimal data is represented by a leftmost decimal point.

Negative decimal numbers have a - sign and the decimal point; positive

numbers just have the decimal point. Driven by OUT0.

R2 Register 2. The middle of the three 5-digit displays. Driven by OUT0.

R3 Register 3. The bottommost of the three 5-digit displays. Driven by OUT0.

Page 264: Apollo Guidance Computer AGC

IO DISCRETE INDICATORS

The DSKY has a panel of discrete indicator lamps (LEDs) to show status or caution and

warning signals. Four of the lamps are driven by bits in output register 1 (OUT1). The parity

alarm is driven by a signal from the MEM module. The standby lamp is driven by the

standby state of the time pulse generator (TPG) in the CTL module.

UPLINK ACTY Uplink activity. Illuminates when data is uplinked to the AGC. Driven

by bit 3 (UPTL) of OUT1.

OPR ERR Operator Error (also called CHECK FAIL). Illuminates when the AGC

detects a data entry error. Driven by bit 7 of OUT1.

KEY REL Key Release. Illuminated by the AGC when it needs to use the display,

but the operator has taken control of it. The AGC causes this lamp to

flash to signal the operator to release control of the display by hitting

the KEY REL button. Driven by bit 5 (KEY RELS) of OUT1.

PROG Program Alarm. Illuminates when the AGC encounters an error

condition. Driven by bit 8 of OUT1.

STBY Standby. Illuminates when the AGC is in the STANDBY mode.

PARITY ALARM Illuminates when a parity error is detected during the memory cycle in

the MEM module.

Page 265: Apollo Guidance Computer AGC

KBD (Keyboard)

The keyboard is an 18-pushbutton unit that

generates and latches a 5-bit code. The code is

given in “Keyboard and Display System Program

for AGC (Program Sunrise)”, A. I. Green and J.

J. Rocchio, E-1574, MIT Instrumentation

Laboratory, Cambridge, MA, 1964.

The keyboard codes and logic for generating the

5-bit signal is reproduced to the right. The “Key

Name” column identifies the name of the

keyboard key; “A” through “E” are the 5 logic

signals for the 5-bit code, where “A” is the MSB.

Page 266: Apollo Guidance Computer AGC

The 18 switches in the

keyboard feed into the

combinational logic encoder

which generates the 5-bit

signal. The output of the

encoder feeds into a 5-bit

latch.

The keys are debounced by

generating a “keypress”

signal whenever a key is

pushed. The keypress signal

feeds through a “D” flip-flop

clocked at around 100Hz.

This samples the keypress

signal every 10 mSec and

latches the sample. The 10

mSec interval exceeds the

contact bounce time of the

keyboard switches.

To give the combinational logic time to settle before the keycode is latched, the output of the

keypress D flip-flop is fed into an RC monstable. Latching occurs on the trailing edge of the

one-shot pulse.

The keyboard codes are fed into “input register” IN0, which is really just a buffer that gates

the codes onto the read bus when the proper read signal is asserted. The original design also

maps the keypress strobe which generates the keyboard interrupt (KEYRUPT) onto bit 6 of

the register, but I skipped this since there doesn’t seem to be any practical reason for doing

it and the COLOSSUS flight software doesn’t seem to look at the field.

The STANDBY ALLOWED switch (CTL module) maps to be 14.

Page 267: Apollo Guidance Computer AGC

KBD INPUTS:

I/F signal full name state definition

CLK:

CLK2 CLOCK 2 data transfer occurs on falling edge

CPM:

GENRST GENERAL RESET 0=reset KBD register

KBD OUTPUTS:

I/F signal full name state definition

KBD:

KB_01 KEYBOARD BUS 01 Keyboard codes

...

KB_05 KEYBOARD BUS 05

INT:

KB_STR KEY STROBE 1=key pressed strobe; to KEYRUPT. Key

data is valid on the negative edge of

KB_STR. Data is latched until the next

keypress.

Page 268: Apollo Guidance Computer AGC
Page 269: Apollo Guidance Computer AGC
Page 270: Apollo Guidance Computer AGC

INP (Input Registers)

INP INPUTS:

I/F signal full name state definition

CPM:

RA4 READ IN0 0=output IN0 register to read bus

RA5 READ IN1 0=output IN1 register to read bus

RA6 READ IN2 0=output IN2 register to read bus

RA7 READ IN3 0=output IN3 register to read bus

KBD:

KB_01 KEYBOARD BUS 01

...

KB_05 KEYBOARD BUS 05

NSA STANDBY ALLOWED 0=standby allowed

INP OUTPUTS:

I/F signal full name state definition

RBUS:

RB_01 READ BUS 01

...

RB_14 READ BUS 14

RB_15 READ BUS 15 US (overflow) bit for read/write bus

RB_16 READ BUS 16 SG (sign) bit for read/write bus

BUSY READ BUS BUSY 0=output enabled to read bus

Page 271: Apollo Guidance Computer AGC
Page 272: Apollo Guidance Computer AGC

OUT (Output Registers)

OUT INPUTS:

I/F signal full name state definition

CLK:

CLK2 CLOCK 2 data transfer occurs on falling edge

CPM:

RA11 READ OUT1 0=OUT1 to read bus

RA12 READ OUT2 0=OUT2 to read bus

RA13 READ OUT3 0=OUT3 to read bus

RA14 READ OUT4 0=OUT4 to read bus

WA11 WRITE OUT1 0=load OUT1 from

write bus

WA12 WRITE OUT2 0=load OUT2 from

write bus

WA13 WRITE OUT3 0=load OUT3 from

write bus

WA14 WRITE OUT4 0=load OUT4 from

write bus

GENRST GENERAL RESET 0=clear DSKY, OUT1,

and OUT2.

WBUS:

WB_01 WRITE BUS 01

...

WB_14 WRITE BUS 14

WB_15 WRITE BUS 15 US (overflow) bit for

write bus

WB_16 WRITE BUS 16 SG (sign) bit for write

bus

OUT OUTPUTS:

I/F signal full name state definition

DSP:

OT0_01 OUT0 REG 01 OUT0 register output to

DSKY

...

OT0_16 OUT0 REG 16

OT1_01 OUT1 REG 01 COMP panel indicator; 1=on

OT1_03 OUT1 REG 03 UPTL panel indicator; 1=on

OT1_05 OUT1 REG 05 KEY RELS panel indicator; 1=on

OT1_07 OUT1 REG 07 CHECK FAIL panel indicator 1=on

OT1_08 OUT1 REG 08 STBY panel indicator 1=on

OT1_09 OUT1 REG 09 PROG ALM panel indicator 1=on

Page 273: Apollo Guidance Computer AGC

RBUS:

RB_01 READ BUS 01

...

RB_14 READ BUS 14

RB_15 READ BUS 15 US (overflow) bit for read/write bus

RB_16 READ BUS 16 SG (sign) bit for read/write bus

BUSY READ BUS BUSY 0=output enabled to read bus

Page 274: Apollo Guidance Computer AGC
Page 275: Apollo Guidance Computer AGC

DSP (Display)

The 7-segment DSKY display is driven by output register 0 (OUT0). Each 16-bit write to

OUT0 writes data to a pair of 7-segment digits.

Four fields in OUT0 are involved: The relay word (RLYWD; bits 12-15) field selects the pair of

digits; the DSPH field (bits 6-10) contains the 5-bit numerical code for the left digit in the

pair, and DPSL (bits 1-5) has the code for the right digit. The 1-bit DPSC (bit 11) field

controls verb/noun flash (enables 1 Hz blinking of the VERB and NOUN digits) and the plus

and minus signs to the left of the three 5-digit “registers” on the DSKY display.

Bits 15-12 Bit 11 Bits 10-6 Bits 5-1

RLYWD DSPC DSPH DSPL

1011 MD1 MD2

1010 FLASH VD1 VD2

1001 ND1 ND2

1000 UPACT R1D1

0111 +R1S R1D2 R1D3

0110 -R1S R1D4 R1D5

0101 +R2S R2D1 R2D2

0100 -R2S R2D3 R2D4

0011 R2D5 R3D1

0010 +R3S R3D2 R3D3

0001 -R3S R3D4 R3D5

Each 7-segment digit on the display has a name (VD1, VD2, etc). The

digits are physically arranged like this:

MD1 MD2 : major mode (PROG)

VD1 VD2 : VERB ND1 ND2 : NOUN

R1S R1D1 R1D2 R1D3 R1D4 R1D5 : register 1

R2S R2D1 R2D2 R2D3 R2D4 R2D5 : register 2

R3S R3D1 R3D2 R3D3 R3D4 R3D5 : register 3

In my assembled unit, the displays were in groups of 3, so some digits

were not needed and left unwired.

The 5-bit codes that illuminate each digit in the display are given below; these are the codes

sent to the DPSH and DPSL fields in OUT0.

In my implementation, I translate them into 4-bit binary-coded decimal representation (BCD)

and feed them into a 74LS47 7-segment decoder. The mapping of the AGC digit to my

Page 276: Apollo Guidance Computer AGC

74LS47 decoder code is also given. The AGC digit codes are very peculiar; I suspect they

were chosen for easy decoding into the 7-segment displays.

Digit AGC 74LS47

Blank 00000 1111

0 10101 0000

1 00011 0001

2 11001 0010

3 11011 0011

4 01111 0100

5 11110 0101

6 11100 0110

7 10011 0111

8 11101 1000

9 11111 1001

My initial block diagram for the DSP logic is shown here. Two combinational logic code

converters changes the 5-bit AGC code (DSPH, DPSL) into 4-bit BCD. The converted codes

are latched into 4-bit registers by write pulses decoded by the relay word (RLYWD) decoder.

Single bit latches hold the flash and sign bit codes transmitted by DSPC (bit 11 of OUT0).

Although I show separate decoders for each digit, I actually multiplexed the display to

minimize the hardware. In this way, I only needed a pair of 74LS47 decoders; one for DSPH

and the other for DSPL.

Page 277: Apollo Guidance Computer AGC

Some back-of-the-envelope bits and

pieces of the logic design are also

shown here. One “diagram” shows the

verb/noun flash logic. Note the simple

Karnaugh map (a graphical method for

reducing boolean expressions), and a

bit of bubble-pushing (a graphical

technique for applying DeMorgan’s

Theorem to transform logic functions

between AND and OR).

The other “diagram” shows the logic for

the +/- signs on registers 1, 2, and 3. The

displays I used in my replica cannot

display a + sign, so I modified the AGC

logic slightly: decimal data is represented

by a leftmost decimal point. Negative

decimal numbers have a - sign and

decimal point; positive decimal numbers

just have the decimal point.

Page 278: Apollo Guidance Computer AGC

The digit display portion of the DSKY uses green common-anode LED displays grouped in

three’s. Like most components, these were purchased from JAMECO. Here’s the pinouts:

Page 279: Apollo Guidance Computer AGC

A panel of discrete indicator LEDs are mapped against bits in output register 1 (OUT1).

Page 280: Apollo Guidance Computer AGC

DSP INPUTS:

I/F signal full name state definition

CLK:

CLK2 CLOCK 2 data transfer occurs on falling edge

PAR:

PARALM PARITY ALARM 1=parity alarm

INP:

OT0_01 OUT0 REG 01 OUT0 register output to DSKY

...

OT0_15 OUT0 REG 15

OT1_01 OUT1 REG 01 COMP panel indicator; 1=on

OT1_03 OUT1 REG 03 UPTL panel indicator;

1=on

OT1_05 OUT1 REG 05 KEY RELS panel

indicator; 1=on

OT1_07 OUT1 REG 07 CHECK FAIL panel

indicator 1=on

OT1_08 OUT1 REG 08 STBY panel indicator

1=on

OT1_09 OUT1 REG 09 PROG ALM panel

indicator 1=on

CPM:

WA10 WRITE OUT0 0=write into OUT0

(DSKY) from write bus

GENRST GENERAL RESET 0=clear the DSKY.

DSP OUTPUTS:

I/F signal full name state definition

none.

Page 281: Apollo Guidance Computer AGC
Page 282: Apollo Guidance Computer AGC
Page 283: Apollo Guidance Computer AGC
Page 284: Apollo Guidance Computer AGC
Page 285: Apollo Guidance Computer AGC
Page 286: Apollo Guidance Computer AGC
Page 287: Apollo Guidance Computer AGC
Page 288: Apollo Guidance Computer AGC
Page 289: Apollo Guidance Computer AGC
Page 290: Apollo Guidance Computer AGC
Page 291: Apollo Guidance Computer AGC
Page 292: Apollo Guidance Computer AGC
Page 293: Apollo Guidance Computer AGC

Fabrication

The IO module is (2) 13"x5" circuit boards, and 1 DSKY panel containing a display driver

board, a 7-segment display board, a discrete LED indicator board, and a keyboard.

Module Rack

The module framework is designed to

resemble a relay rack, but scaled to fit the

circuit board dimensions. It is constructed

out of 1"x2" pine and spray-painted semi-

gloss gray.

Circuit boards are mounted to the rack by 2

phillips screws at either end. Nylon spacers

(1/4") are used as standoffs to hold the

board edges above the rack. The boards are

mounted so the chips are in the back and

the pins are wiring are visible from the

front.

Power is distributed by 2 heavy aluminum

bus bars mounted vertically, one per side,

on the back of the module. Machine screws

are mounted through the bus bars at

evenly-spaced intervals to provide

connection points for the boards.

Solid copper wire (24 gauge) connects the

boards to the bus bars. Ring terminals are

used on the bus bar side of the connection. On the circuit board size, the wires are soldered

directly to the supply rails.

Materials were purchased from Home Depot, ACE Hardware, and Radio Shack.

Circuit Boards

The circuit boards are 13"x5" general purpose prototyping boards, epoxy glass with double-

side plated through pads on 0.1" centers (JAMECO 21477CL).

ICs are mounted in level 3 machine tooled wire-wrap sockets: 8, 14,

16, 20, 24, and 28 pin (JAMECO). Each socket has the pin-out labeled

with a w ire-wrap socket ID marker, which slips onto the socket before

wrapping (JAMECO). The part number is written onto the ID marker.

Sockets are arranged in 4 horizontal rows on each board, with about

10 sockets per row.

Power is distributed on the back-side of each board by bare 24-gauge

solid copper wire supply rails soldered at equal intervals to Klipwrap terminals: 3-prong

terminals with a square tail for wire-wrapping (JAMECO 34163CL). A +5V rail runs above

each row of sockets and a ground rail runs below. Each rail connects directly to the aluminum

module power bus using a ring tail connector.

Page 294: Apollo Guidance Computer AGC

On the pin side of the board, all connections are made with 30 AWG Kynar wire-wrap wire

(JAMECO). Red wire is used for direct connections to the +5V supply rail. Black wire is used

for direct connections to ground. White wire is used for everything else.

Power connections from the supply rails to each ICs are double-wrapped. Bypassing

capacitors (.1 uf disc ) are soldered across the supply rails at the Klipwrap terminals; about 1

capacitor for every 2 IC packages.

All connections were stripped and hand-wrapped using a Radio Shack hand-wrap tool. As

each connection was made, the corresponding line on the schematic was marked with a

colored highlighter.

DIP resistor networks (JAMECO) plugged into 20-pin wire-wrap sockets were used as current

limiting resistors for the panel indicators.

Page 295: Apollo Guidance Computer AGC

IO Circuit Board A

The A board contains the module interface buffers, input and output registers, and the

latches that hold the BCD codes for the 7-segment displays.

Page 296: Apollo Guidance Computer AGC

IO Circuit Board B

The B board contains keyboard and display logic. The 40-pin IDE connectors that interface to

the other modules are visible at the bottom. The 5 red LEDs show the keyboard code latched

into the KBD output register.

Page 297: Apollo Guidance Computer AGC

IO Device Driver Board C

The C board contains driver transistors and their associated resistors. The transistors are

plastic medium-power complementary si licon: NPN transistors are TIP102, PNP transistors

are TIP107. Viewed from the front of the TO-220 case, the base (1) is to the left, collector

(2) in the middle, and emitter (3) to the right. The metal tab (4) is the collector.

Page 298: Apollo Guidance Computer AGC

An empty space at the top of the IO module rack was filled with a plexiglass panel listing

verb and noun codes:

Page 299: Apollo Guidance Computer AGC

Parts (ICs)

IC’s, sockets, PCB’s, resistors, capacitors, wire-wrap wire were purchased from JAMECO. IDE

wire-wrap sockets were from DigiKey. Wire ties, wire-wrap tools, and copper wire were from

Radio Shack. IDE ribbon cables were purchased from an online computer supplier.

74LS00 (13) U27, U27B, U27C, U15C, U15B, U15, U14C, U14B, U14, U29D, U29C,

U29B, U34B

74LS02 (3) U25,U25,U33C

74LS04 (27) U40E, U40D, U38D, U38C, U40F, U40C, U39E, U39D, U39C, U39B,

U41D, U40B, U37F, U39F, U12, U12B, U12C, U12D, U12E, U11F, U11E,

U11D, U11C, U11B, U11, U39A, U37

74LS06 (41) U26F, U26E, U26D, U26C, U26B, U26, U20, U18D, U18C, U18B, U18,

U20C, U17E, U17D, U20B, U16F, U16E, U9, U9B, U9C, U9D, U9E, U9F,

U10, U10B, U10C, U10D, U7, U7B, U7C, U7D, U7E, U7F, U8, U20,

U19F, U19E, U19D, U19C, U19B, U19

74LS08 (1) U28

74LS10 (1) U4

74LS20 (5) U2, U3, U5, U31, U32

74LS27 (2) U35C, U36

74LS47 (4) U46, U47, U48, U45

74LS74 (1) U1

74LS86 (1) U24C

74LS112 (5) U6A, U23B, U22B, U21B, U30

74LS138 (9) U50, U67, U68, U69, U70, U73, U74, U75, U76

74LS148 (4) U65, U66, U71, U72

74LS154 (1) U51

74LS161A (1) U49

74LS244 (10) U101, U100, U52, U53, U77, U78, U81, U82, U83, U84

74LS273 (3) U79, U80, U44

74LS374 (11) U54, U55, U56, U57, U58, U59, U60, U61, U62, U63, U64

GREENCA (21) DISP1, DISP2, DISP3, DISP4,DISP5, DISP6, DISP7, DISP8, DISP9,

DISP10, DISP11, DISP12, DISP13, DISP14, DISP15, DISP16, DISP17,

DISP18, DISP19, DISP20, DISP21

555 (3) U85, U42, U43

NPN3 (35) Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q15, Q16, Q17, Q18, Q19, Q20, Q21,

Q32, Q33, Q34, Q35, Q36, Q37, Q38, Q39, Q40, Q41, Q42, Q43, Q44,

Q45, Q8, Q9, Q10, Q11, Q12, Q13, Q14

PNP3 (22) Q22, Q23, Q24, Q25, Q26, Q27, Q28, Q29, Q30, Q31, Q46, Q47, Q48,

Q49, Q50, Q51, Q52, Q53, Q54, Q55, Q56, Q57

Power Budget

qty mA (ea) mA (tot)

74LS00 13 2.4 31.2

74LS02 3 2.4 7.2

74LS04 27 3.6 97.2

74LS06 41 3.6 147.6

74LS08 1 4.4 4.4

74LS10 1 1.8 1.8

74LS20 5 1.2 6.0

Page 300: Apollo Guidance Computer AGC

74LS27 2 3.4 6.8

74LS47 4 7.0 28.0

74LS74 1 4.0 4.0

74LS86 1 6.1 6.1

74LS112 5 4.0 20.0

74LS138 9 6.3 56.7

74LS148 4 12.0 48.0

74LS154 1 6.2 6.2

74LS161 1 19.0 19.0

74LS244 10 32.0 320.0

74LS273 3 17.0 51.0

74LS374 11 27.0 297.0

555 3 3.0 9.0

GREENCA 21 140.0 2940.0

LED 25 20.0 500.0

----

4.6 Amps total

4.1 Amps (excluding single LEDs)

Page 301: Apollo Guidance Computer AGC

Block IApollo Guidance Computer (AGC)

How to build one in your basement

Part 6: Assembler

John Pultorak

December, 2004

Page 302: Apollo Guidance Computer AGC

Abstract

This report describes my successful project to build a working reproduction of the 1964

prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the

Apollo moon landings, and is the world’s first integrated circuit computer.

I built it in my basement. It took me 4 years.

If you like, you can build one too. It will take you less time, and yours will be better than

mine.

I documented my project in 9 separate .pdf files:

Part 1 Overview: Introduces the project.

Part 2 CTL Module: Design and construction of the control module.

Part 3 PROC Module: Design and construction of the processing (CPU) module.

Part 4 MEM Module: Design and construction of the memory module.

Part 5 IO Module: Design and construction of the display/keyboard (DSKY) module.

Part 6 Assembler: A cross-assembler for AGC software development.

Part 7 C++ Simulator: A low-level simulator that runs assembled AGC code.

Part 8 Flight Software: My translation of portions of the COLOSSUS 249 flight

software.

Part 9 Test & Checkout: A suite of test programs in AGC assembly language.

Page 303: Apollo Guidance Computer AGC

Overview

This AGC cross-assembler, coded in C++, produces AGC object code in Motorola S-format.

The code can be burned into EPROM for use by the hardware AGC, or executed by the C++

AGC simulator.

OperationThe assembler reads an AGC source code text file (having a .asm extension). It generates

an assembly listing text file (.lst extension) and an two object code text files (_H.hex and

_L.hex suffixes). The object code files are readable by the AGC simulator or an EPROM

programmer.

SyntaxSource code files are text files containing multiple lines of source code. Each line is

terminated by a newline character. Source code files can be produced by any editor, as long

as it doesn't insert any hidden characters or formatting information.

Each line of source code consists of one of the following:

a) A blank line.

b) A comment (comments must begin with a semicolon (;)).

c) A line of assembler code.

The assembler ignores blank lines and anything that occurs after a semicolon on any given

line.

A line of assembler code consists of the following components:

1) A label (this is optional).

2) An op code or assembler directive.

3) An operand (also optional).

4) A comment (optional; comments must start with a semicolon).

The components, if present, must appear in the order given. Each component is separated

from the next by one or more white spaces or tabs. The only constraint is that the label, if

present, must start in the 1st column of the line. If no label is present, the op code or

assembler directive must not start in the 1st column, but may appear in any subsequent

column.

The operand may consist of one of the following:

a) An asterisk (the assembler substitutes in the current value of the location

counter.

b) A symbolic name (the assemble substitutes in the value during the second

pass of the assembly.

c) A numeric constant. Octal contants must be preceeded by a '%'; hexadecimal

constants are preceeded by a '$'; anything else is treated as a decimal.

d) An expression consisting of one or more of the above, separated by the

operators: +, -, @ (for multiplication), or / (for division). Unary plus or minus

is also allowed.

Examples:

*+2 Location counter plus 2.

LABEL+%10/2 LABEL plus octal number 10 divided by decimal number 2.

-5 Negative decimal 5.

Page 304: Apollo Guidance Computer AGC

Assembler DirectivesThe following directives are supported:

ORG Set the location counter to the operand following ORG.

EQU Set the label to the operand value.

DS Define a word of storage; set the value to the operand value.

CADR Define a word of storage; set the value to the operand value (assumed

to be a 14-bit address; this is an alias for CADR).

ADRES Define a word of storage; set the value to the operand value (operand

is treated as a 12-bit address).

INCL Inline include a file; the operand contains the filename.

AddressingThe location counter and symbol table always contain the full 14-bit address. AGC

instructions require a 12-bit address as an operand. Addressing is implemented in 1K banks

(bits 10 through 1). Bits 12 and 11 select banks 0 (erasable memory), 1 (fixed-fixed), or 2

(fixed-fixed). These banks are directly addressable in 12-bits. Banks above 2 are called

'fixed-switchable' and are addressed using the BANK register: bits 12 and 11 of the operand

are set to '1' and the bank register provides the high-order 4 bits (bits 14 through 11) of the

address. The lower 10 bits of the operand provide the address within the bank.

Errataa) The assembler ignores the last line of the source (.asm) file. If the last line of your

source file contains code, you must add an additional blank line to the end of your

source file to ensure that your last line of code is assembled.

b) The symbol table could be sorted before the second pass. The linear search through

the symbol table could be replaced by a more efficient method. (But, assembly is so

fast, it doesn’t matter).

c) The assembler directives and syntax don't match those of the original block I AGC.

d) A macro definition capability might be handy.

e) Generates empty .lst and .obj files if the source code file does not exist.

f) Incorrectly assigns a zero value to labels that equate to a forward referenced label.

i.e.:

LABEL1 EQU LABEL2 ; assembler incorrectly sets LABEL1 to zero

LABEL2 EQU *

Page 305: Apollo Guidance Computer AGC

Assembler listing

The assembler produces a list file (.lst) that shows the assembled source code. The format

of the file was designed to mimic (somewhat) the format of the original assembler. You will

find a fragment of the original assembler listing reproduced in part 8.

List files from my assembler have this format:

Page 306: Apollo Guidance Computer AGC

Object code

The object code is output to text files in Motorola S-Record format (S2F) suitable for

immediate use by EPROM programmers, and also readable by the C++ simulator.

There’s lots of documentation on S-Record formats on the internet.

The files are pretty big. If you open one up, you’ll discover they contain many short records

that look like these:

This is a fragment of the source code for the lower 8 bits of the TECO1 test and checkout

program (described in part 9).

The assembler contains C++ code for generating these files; the C++ simulator has code for

reading them.

Page 307: Apollo Guidance Computer AGC

Assembler v1.6

/* **************************************************************** * * Cross Assembler for Block I Apollo Guidance Computer (AGC4) * THIS VERSION IS MODIFIED TO OUTPUT IN S-RECORD FORMAT SUITABLE FOR * LOADING IN EPROM (s2f format). * Author: John Pultorak * 6/1/2002 * *****************************************************************

Versions:1.0 - First version of the AGC assembler.1.1 - Added ability to handle simple arithmetic expressions for the operand.1.2 - Changed label fields to 14 char. Printed symbol table in 3 columns.

Corrected wrong implementation of OVSK.1.3 - Added support for bank addressing.1.4 - Added capability to inline code with nested includes.1.5 - Added CADR, ADRES assembler directives. Swapped addresses for

TIME1 and TIME2 for compatibility with Block II PINBALL routines.1.6 - Fixed the parser so it doesn't mangle comments anymore. Added

FCADR and ECADR to the assembler directives. Added a check forassembled code that overwrites already used locations.

1.6 - EPROM Assembler outputs to low and high EPROM files.

Operation:The assembler reads an AGC source code file (having a .asm extension).It generates an assembly listing text file (.lst extension) and anobject code text file (.obj extension). The object code file is readableby the AGC simulator.

Syntax:Source code files are text files containing multiple lines of source code.Each line is terminated by a newline character. Source code files can beproduced by any editor, as long as it doesn't insert any hidden charactersor formatting information.

Each line of assembly code consists of one of the following:a) a blank line;b) a comment (comments must begin with a semicolon (;));c) or a line of assembler code.

The assembler ignores blank lines and anything that occurs after a semicolonon any given line.

A line of assembler code consists of the following components:1) a label (this is optional);2) an op code or assembler directive;3) an operand (also optional);4) a comment (optional; comments must start with a semicolon)

The components, if present, must appear in the order given. Each component isseparated from the next by one or more white spaces or tabs. The only constraintis that the label, if present, must start in the 1st column of the line. If nolabel is present, the op code or assembler directive must not start in the 1stcolumn, but may appear in any subsequent column.

The operand may consist of one of the following:a) an asterisk (the assembler substitutes in the current value of the

location counter;b) a symbolic name (the assemble substitutes in the value during the

second pass of the assembly;c) a numeric constant. Octal contants must be preceeded by a '%';

hexadecimal constants are preceeded by a '$'; anything elseis treated as a decimal.

d) an expression consisting of one or more of the above, separated by the operators: +, -, @ (for multiplication), or / (for division).

Unary plus or minus is also allowed.examples:

*+2 means location counter plus 2LABEL+%10/2-5

Page 308: Apollo Guidance Computer AGC

Assembler Directives:The following directives are supported:ORG - set the location counter to the operand following ORG.EQU - set the label to the operand value.DS - define a word of storage; set the value to the operand value.CADR - define a word of storage; set the value to the operand value (assumed to be a 14-bit address; this is an alias for CADR).ADRES - define a word of storage; set the value to the operand value (operand is treated as a 12-bit address).INCL - inline include a file; the operand contains the filename.

Addressing:The location counter and symbol table always contain the full 14-bit address.AGC instructions require a 12-bit address as an operand. Addressing is implementedin 1K banks (bits 10 through 1). Bits 12 and 11 select banks 0 (erasable memory),1 (fixed-fixed), or 2 (fixed-fixed). These banks are directly addressable in12-bits. Banks above 2 are called 'fixed-switchable' and are addressed usingthe BANK register: bits 12 and 11 of the operand are set to '1' and the bank register provides the high-order 4 bits (bits 14 through 11) of the address. The lower 10 bits of the operand provide the address within the bank.

Errata:The assembler ignores the last line of the source (.asm) file. If the lastline of your source file contains code, you must add an additional blankline to the end of your source file to ensure that your last line of codeis assembled.

The symbol table should be sorted before the second pass. The linearsearch through the symbol table should be replaced by a more efficientmethod.

The assembler directives and syntax don't match those of the original block I AGC.

A macro definition capability would be handy.

Generates empty .lst and .obj files if the source code file does not exist.

Incorrectly assigns a zero value to labels that equate to a forward referencedlabel. i.e.:

LABEL1 EQU LABEL2 ; assembler incorrectly sets LABEL1to zero

LABEL2 EQU *

The assembler generates object code for eraseable memory addresses.*/

#include <string.h>#include <stdlib.h>#include <ctype.h>#include <iostream.h>#include <stdio.h>

// Create a flag for each memory location in a 14-bit address space// These are initialized to false, and then set as the code is assembled.// An attempt to assemble code on top of a previously used location is// flagged as an error.

const unsigned agcMemSize = 037777+1; // # of cells in a 14-bit address rangebool memoryUsed [agcMemSize];

//***********************************************************************// MODIFIED FROM THE ORIGINAL ASSEMBLER HERE.// This array represents the fixed memory PROM (14-bit address) int EPROM_H [agcMemSize];int EPROM_L [agcMemSize];//***********************************************************************

unsigned pass = 0;unsigned locCntr = 0; // address in 14-bit formatunsigned errorCount = 0;

FILE* fpList = 0; // output (assembly listing)

Page 309: Apollo Guidance Computer AGC

//***********************************************************************// MODIFIED FROM THE ORIGINAL ASSEMBLER HERE.FILE* fpObj_H = 0; // output MSB's (object code in S-RECORD format)FILE* fpObj_L = 0; // output LSB's (object code in S-RECORD format)//***********************************************************************

struct ocode{

char* name;unsigned code;bool isOpCode; // true=it is an op codebool addrOpnd; // true=convert operand to 12-bit address formatunsigned len; // words

};

ocode allcodes[] = {

// Block I op codes.{ "TC", 0000000, true, true, 1 }, { "CCS", 0010000, true, true, 1 }, { "INDEX", 0020000, true, true, 1 }, { "XCH", 0030000, true, true, 1 }, { "CS", 0040000, true, true, 1 }, { "TS", 0050000, true, true, 1 }, { "AD", 0060000, true, true, 1 }, { "MASK", 0070000, true, true, 1 }, { "MP", 0040000, true, true, 1 }, { "DV", 0050000, true, true, 1 }, { "SU", 0060000, true, true, 1 },

// Implied address codes (R393: 3-12){ "RESUME", 0020025, true, false, 1 }, // INDEX 25{ "EXTEND", 0025777, true, false, 1 }, // INDEX 5777{ "INHINT", 0020017, true, false, 1 }, // INDEX 17{ "RELINT", 0020016, true, false, 1 }, // INDEX 16{ "XAQ", 0000000, true, false, 1 }, // TC A{ "RETURN", 0000001, true, false, 1 }, // TC Q{ "NOOP", 0030000, true, false, 1 }, // XCH A{ "COM", 0040000, true, false, 1 }, // CS A{ "TCAA", 0050002, true, false, 1 }, // TS Z{ "OVSK", 0050000, true, false, 1 }, // TS A{ "DOUBLE", 0060000, true, false, 1 }, // AD A{ "SQUARE", 0040000, true, false, 1 }, // MP A

// For "clarity" (R393: 3-12){ "TCR", 0000000, true, true, 1 }, // same as TC; subroutine call with return{ "CAF", 0030000, true, true, 1 }, // same as XCH; address to fixed acts like

Clear and Add{ "OVIND", 0050000, true, true, 1 }, // same as TS

// Assembler directives{ "DS", 0, false, false, 1 }, // define storage; reserves 1 word of memory{ "CADR", 0, false, false, 1 }, // define 14-bit addr; reserves 1 word of memory{ "FCADR", 0, false, false, 1 }, // define 14-bit addr; reserves 1 word of memory{ "ECADR", 0, false, false, 1 }, // define 14-bit addr; reserves 1 word of memory{ "ADRES", 0, false, true, 1 }, // define 12-bit addr; reserves 1 word of memory{ "ORG", 0, false, false, 0 }, // origin; sets location counter to operand value{ "EQU", 0, false, false, 0 }, // equate; assigns a value to a label{ "INCL", 0, false, false, 0 }, // include; inline include source code{ "", 0, false, false, 99 } // end-of-list flag

};

void parse(char* buf, char* labl, char* opcd, char* opnd, char* cmnt){

// strip off newline char.buf[strlen(buf) - 1] = '\0';

// replace any horizontal tabs with spacesfor(unsigned i=0; i<strlen(buf); i++) {

if(buf[i] == ';') break; // don't edit commentsif(buf[i] == '\t') buf[i] = ' ';

}

strcpy(labl,"");

Page 310: Apollo Guidance Computer AGC

strcpy(opcd,""); strcpy(opnd,""); strcpy(cmnt,"");

char* sp = buf;char* s = 0;

enum {_labl=0, _opcd, _opnd, _cmnt } mode = _labl;

if(buf[0] == ' ') mode = _opcd;do{

s = strtok(sp, " "); sp = 0;if(s){

if(s[0] == ';'){

// Copy the remainder of the comment verbatim.strcat(cmnt, s); strcat(cmnt, " "); s += strlen(s) + 1; strcat(cmnt, s);return;

}switch(mode){case _labl: strcat(labl, s); mode = _opcd; break;case _opcd: strcat(opcd, s); mode = _opnd; break;case _opnd: strcat(opnd, s); mode = _cmnt; break;}

}} while(s);

}

struct symbl{

char name[20];unsigned val;

};

symbl symTab[5000];unsigned nSym = 0;

// Pre-defined symbols corresponding to architectural// conventions in the block I AGC4.

symbl constSymTab[] = {

{ "A", 00 },{ "Q", 01 },{ "Z", 02 },{ "LP", 03 },{ "IN0", 04 },{ "IN1", 05 },{ "IN2", 06 },{ "IN3", 07 },{ "OUT0", 010 },{ "OUT1", 011 },{ "OUT2", 012 },{ "OUT3", 013 },{ "OUT4", 014 },{ "BANK", 015 },{ "CYR", 020 },{ "SR", 021 },{ "CYL", 022 },{ "SL", 023 },{ "ZRUPT", 024 },{ "BRUPT", 025 },{ "ARUPT", 026 },{ "QRUPT", 027 },{ "OVCTR", 034 },{ "TIME2", 035 },{ "TIME1", 036 },{ "TIME3", 037 },{ "TIME4", 040 },{ "GOPROG", 02000 },

Page 311: Apollo Guidance Computer AGC

{ "T3RUPT", 02004 },{ "ERRUPT", 02010 },{ "DSRUPT", 02014 },{ "KEYRUPT", 02020 },{ "UPRUPT", 02024 },{ "EXTENDER", 05777 },{ "BANK0", 000057 }, // erasable memory, just above the counter assignments{ "BANK1", 002000 }, // fixed-fixed{ "BANK2", 004000 }, // fixed-fixed{ "BANK3", 006000 }, // start of fixed-switchable{ "BANK4", 010000 },{ "BANK5", 012000 },{ "BANK6", 014000 },{ "BANK7", 016000 },{ "BANK10", 020000 },{ "BANK11", 022000 },{ "BANK12", 024000 },{ "BANK13", 026000 },{ "BANK14", 030000 },{ "", 0 }

};

void add(char* labl, unsigned value){

// Check whether symbol is already defined.unsigned i;for(i=0; i<nSym; i++){

if(strcmp(symTab[i].name, labl)==0){

fprintf(fpList,"*** ERROR: %s redefined.\n", symTab[i].name);errorCount++;return;

}}

// Add new symbol to symbol tablestrcpy(symTab[nSym].name, labl);symTab[nSym].val = value;nSym++;

}

// Return the int value of the operand string. The string is// assumed to be a simple value (not an expression)int _getopnd(char* opnd){

if(strlen(opnd)==0)return 0;

else if(opnd[0] == '$') // hex numberreturn strtol(opnd+1, 0, 16);

else if(opnd[0] == '%') // octal numberreturn strtol(opnd+1, 0, 8);

else if(isdigit(opnd[0])) // decimal numberreturn strtol(opnd, 0, 10);

else if(opnd[0] == '*')return locCntr;

else // must be label; look up value{

unsigned i;for(i=0; i<nSym; i++){

if(strcmp(symTab[i].name, opnd)==0)return symTab[i].val;

}

// Not there, so check whether symbol is an// assembler-defined constant. If so, copy it to// the user-defined symbols.for(i=0; strcmp(constSymTab[i].name,"") != 0; i++){

if(strcmp(constSymTab[i].name, opnd)==0){

strcpy(symTab[nSym].name, opnd);symTab[nSym].val = constSymTab[i].val;nSym++;

Page 312: Apollo Guidance Computer AGC

return constSymTab[i].val;}

}

if(pass == 1){

fprintf(fpList,"*** ERROR: %s undefined.\n", opnd);errorCount++;

}}return 0;

}

// returns pointer to new position in istrchar* getToken(char* istr, char* ostr){

*ostr = '\0';

// bump past any whitespacewhile(*istr == ' ') istr++;

if(*istr == '\0') return istr;

bool keepGoing = true;do{

*ostr = *istr;if(*ostr == '+' || *ostr == '-' || *ostr == '@' || *ostr == '/')

keepGoing = false;ostr++; istr++;

}while(keepGoing && *istr != '\0' && *istr != '+' && *istr != '-'

&& *istr != '@' && *istr != '/');

*ostr = '\0';return istr;

}

int _eval(char* sp, int tot){

if(*sp == '\0') return tot;

char op[20];sp = getToken(sp, op);

char vstr[20];int val = 0;sp = getToken(sp,vstr);if(*vstr =='-') // unary minus{

sp = getToken(sp, vstr);val = -(_getopnd(vstr));

}else

val = _getopnd(vstr);

switch(*op){case '+': tot += val; break;case '-': tot -= val; break;case '@': tot *= val; break;case '/': tot /= val; break;}

return _eval(sp,tot);}

int eval(char* sp){

char op[20];getToken(sp, op);char sp1[80];if(*op != '+' && *op != '-')

strcpy(sp1,"+");else

strcpy(sp1,"");

Page 313: Apollo Guidance Computer AGC

strcat(sp1, sp);return _eval(sp1, 0);

}

// Return the value of the operand string. The string may// be a simple token or an expression consisting of multiple// tokens and operators. Evaluation occurs from left to right;// no parenthesis allowed. Unary minus is allowed and correctly// evaluated. Valid operators are +, -, @, and /. The @ operator// is multiplication (the traditional * operator already is used// to refer to the location counter.unsigned getopnd(char* opnd){

//return _getopnd(opnd); // the old call did not allow for expressions

unsigned retval = 0;if(strcmp(opnd,"-0") == 0 || strcmp(opnd,"-%0") == 0 || strcmp(opnd,"-$0") == 0)

retval = 077777; // -0else{ // return the int value of the operand

int opndVal = eval(opnd);

// now, convert the number into 16-bit signed AGC formatif(opndVal < 0){

// convert negative values into AGC 16-bit 1's C form.opndVal = 077777 + opndVal;if(opndVal < 0){

fprintf(fpList,"*** ERROR: %s underflowed.\n", opnd);errorCount++;opndVal = 0;

}}else if(opndVal > 077777){

fprintf(fpList,"*** ERROR: %s overflowed.\n", opnd);errorCount++;opndVal = 0;

}retval = (unsigned) opndVal;

}return retval;

}

bool isDefined(char* opcd){

for(int j=0; allcodes[j].len != 99; j++){

if(strcmp(allcodes[j].name, opcd) == 0){

return true;}

}return false;

}

unsigned getopcode(char* opcd){

for(int j=0; allcodes[j].len != 99; j++){

if(strcmp(allcodes[j].name, opcd) == 0){

return allcodes[j].code;}

}fprintf(fpList,"*** ERROR: %s undefined.\n", opcd);errorCount++;

return 0;}

bool has12bitAddr(char* opcd){

for(int j=0; allcodes[j].len != 99; j++)

Page 314: Apollo Guidance Computer AGC

{if(strcmp(allcodes[j].name, opcd) == 0){

return allcodes[j].addrOpnd;}

}return false;

}

bool isOpCode(char* opcd){

for(int j=0; allcodes[j].len != 99; j++){

if(strcmp(allcodes[j].name, opcd) == 0){

return allcodes[j].isOpCode;}

}return false;

}

unsigned getoplen(char* opcd){

for(int j=0; allcodes[j].len != 99; j++){

if(strcmp(allcodes[j].name, opcd) == 0){

return allcodes[j].len;}

}return 0;

}

void updateLocCntr(char* opcd, char* opnd){

unsigned size = 0;for(int i=0; allcodes[i].len != 99; i++){

if(strcmp(allcodes[i].name, opcd) == 0){

size = allcodes[i].len; break;}

}locCntr += size;

if(strcmp(opcd,"ORG") == 0){

locCntr = getopnd(opnd);}

}

unsigned genOddParity(unsigned r){

//check the lower 15 bits of 'r' and return the odd parityunsigned evenParity =

(1&(r>>0)) ^ (1&(r>>1)) ^ (1&(r>>2)) ^ (1&(r>>3)) ^(1&(r>>4)) ^ (1&(r>>5)) ^ (1&(r>>6)) ^ (1&(r>>7)) ^(1&(r>>8)) ^ (1&(r>>9)) ^ (1&(r>>10)) ^ (1&(r>>11)) ^(1&(r>>12)) ^ (1&(r>>13)) ^ (1&(r>>14));

return ~evenParity & 1; // odd parity}

// Read the source file and build the symbol table.void readSourceForPass1(char* fn){

char buf[256];char labl[100]; // labelchar opcd[100]; // op codechar opnd[100]; // operandchar cmnt[100]; // comment

// Open the source code file.FILE* fp = fopen(fn, "r");if(!fp){

Page 315: Apollo Guidance Computer AGC

perror("fopen failed for source file");return;

}

while(fgets(buf, 256, fp)){

parse(buf, labl, opcd, opnd, cmnt);

if(strcmp(opcd,"INCL")==0)readSourceForPass1(opnd);

if(strlen(labl)>0){

if(strcmp(opcd,"EQU")==0)add(labl, getopnd(opnd));

elseadd(labl, locCntr);

}updateLocCntr(opcd, opnd);

}fclose(fp);

}

// Read the source file and symbol table and build// the object code

void readSourceForPass2(char* fn){

char buf[256];char labl[100]; // labelchar opcd[100]; // op codechar opnd[100]; // operandchar cmnt[100]; // comment

// Open the source code file.FILE* fp = fopen(fn, "r");if(!fp){

perror("fopen failed for source file");return;

}

while(fgets(buf,256,fp)){

parse(buf, labl, opcd, opnd, cmnt);

if(strcmp(opcd,"INCL")==0){

// Include directive (INCL).fprintf(fpList, " %-14s %-8s %-14s %s\n",

labl, opcd, opnd, cmnt);readSourceForPass2(opnd);

}else if(strcmp(opcd,"")==0){

// Comment.fprintf(fpList, " %s\n", cmnt);

}else if(getoplen(opcd) == 0){

// Must be ORG or EQU assembler directive.fprintf(fpList, " %-14s %-8s %-14s %s\n",

labl, opcd, opnd, cmnt);

if(!isDefined(opcd)){

fprintf(fpList,"*** ERROR: %s undefined.\n", opcd);errorCount++;

}}else{

// Since we got this far, we know the assembly line contains a// valid 'opcd' that reserves some storage space. It must be an// instruction or a DS.

// Location counter (locCntr) contains 14-bit address; symbol table

Page 316: Apollo Guidance Computer AGC

// also stores 14-bit addresses. If the operand is an address above// bank 3 (05777), it is not directly addressable and needs to be// converted into a 12-bit bank address. In bank addressing, bits// 12,11 are set and bits 10-1 contain the address inside the bank.// (The programmer must set the bank register to select the correct// bank.)

// Generate a string containing the address (for the list file).// If the address is erasable, or fixed-fixed, show the 12-bit// address. // If the address is fixed-switchable, show the bank number,// followed by the 10-bit bank address.

unsigned locCntrBank = (036000 & locCntr) >> 10;char locCntrString[20];if(locCntrBank <= 3) sprintf(locCntrString, " %04o", locCntr);else

sprintf(locCntrString, "%2o,%04o", locCntrBank, 01777 & locCntr);

// Generate the data to be stored at that address. Convert to// 12-bit address format, if necessary.

unsigned operValue = getopnd(opnd);unsigned operBank = (036000 & operValue) >> 10;if(has12bitAddr(opcd)){

// Convert operand from a 14-bit address to a 12-bit// address.// First, find bank (bits 14-11). If the bank is <= 03, no// conversion is necessary.

if(operBank > 03){

// Bank is not directly addressable, so get 10 bit// bank address and set fixed-switchable flag bits// 12 and 11.

operValue = (01777 & operValue) | 06000;}

}unsigned data = getopcode(opcd) + operValue;data |= genOddParity(data) << 15;

// Generate a string containing the data info for the list file.char dataString[20];if(isOpCode(opcd))

sprintf(dataString, "%01o %2o,%04o %1o", (getopcode(opcd) & 070000) >> 12, operBank, operValue,

genOddParity(data));else

sprintf(dataString, " %05o %1o", operValue, genOddParity(data));

if(memoryUsed[locCntr]){

fprintf(fpList,"*** ERROR: %06o address already in use.\n",locCntr);

errorCount++;}memoryUsed[locCntr] = true;

fprintf(fpList, "%05o %7s %11s %-14s %-8s %-14s %s\n",locCntr, locCntrString, dataString, labl, opcd, opnd, cmnt);

//***********************************************************************// MODIFIED FROM THE ORIGINAL ASSEMBLER HERE.// Insert the assembled code into an array, indexed by the address.// This has the effect of sorting the data by address, so we can walk// through the addresses and output the code to EPROM later.unsigned dataLow = 0x00ff & data;unsigned dataHigh = (0xff00 & data) >> 8;

if(locCntr >=1024) // FIXED MEMORY only; not ERASEABLE{

// fixed memoryEPROM_H [locCntr] = dataHigh;EPROM_L [locCntr] = dataLow;

Page 317: Apollo Guidance Computer AGC

}//***********************************************************************

}

updateLocCntr(opcd, opnd);}fclose(fp);

}

//***********************************************************************// MODIFIED FROM THE ORIGINAL ASSEMBLER HERE.

void writeEPROM(FILE* fpObj, int EPROM[]){

// Write an EPROM file using Motorola's S-Record format (s2f).

// Some parameters that control file format. You can change maxBytes// without affecting anything else. 'addressBytes' is determined by// the choosen S-Record format.

const int maxBytes = 20; // set limit on record lengthconst int addressBytes = 3; // 16-bit address rangeconst int sumCheckBytes = 1;

const int maxdata = maxBytes - addressBytes - sumCheckBytes;

int i=0; // current EPROM addressint sumCheck = 0;while (i < agcMemSize){

// get dataByteCount; the number of bytes of EPROM data per record.int dataByteCount = maxdata;if(i + dataByteCount >= agcMemSize){

dataByteCount = agcMemSize - i;}

// write record header (*** 2 byte address assumed ***)int totalByteCount = dataByteCount + addressBytes + sumCheckBytes;fprintf(fpObj, "S2%02X%06X", totalByteCount, i);sumCheck = totalByteCount & 0xff;sumCheck = (sumCheck + ((i & 0xff0000) >> 16)) % 256;sumCheck = (sumCheck + ((i & 0x00ff00) >> 8)) % 256;sumCheck = (sumCheck + ((i & 0x0000ff) )) % 256;

// write data bytes into recordfor(int j=0; j<dataByteCount; j++){

fprintf(fpObj, "%02X", EPROM [i+j]);sumCheck = (sumCheck + EPROM [i+j]) % 256;

}// terminate record by adding the checksum and a newline.

fprintf(fpObj, "%02X\n", (~sumCheck) & 0xff);

i += dataByteCount;}

// write an end-of-file record herei=0; // set address zero for last recordsumCheck = 0x04; // byte countsumCheck = (sumCheck + ((i & 0xff0000) >> 16)) % 256;sumCheck = (sumCheck + ((i & 0x00ff00) >> 8)) % 256;sumCheck = (sumCheck + ((i & 0x0000ff) )) % 256;fprintf(fpObj, "S804%06X%02X", i, (~sumCheck) & 0xff);

}

//***********************************************************************

void main(int argc, char* argv[]){

cout << "AGC Block I assembler" << endl;

// The assembler reads an assembly source code file// with a .asm extension; i.e.: myProg.asm// It writes an assembly listing text file with// a .lst extension (myProg.lst) and an object code

Page 318: Apollo Guidance Computer AGC

// text file with a .obj extension (myProg.obj)#ifdef NOTDEF

// use this to enter the source file using command lineif(argc != 2){

cout << "*** ERROR: source file name not specified." << endl;exit(-1);

}

fp = fopen(argv[1], "r");#endif

char sourcefile[80];cout << "Enter source file: ";cin >> sourcefile;

// Valid source files have a .asm extension; strip the// extension off so we can use the prefix for the list// and object files.

char prefix[80];strcpy(prefix, sourcefile);

char* p = prefix;while(*p != '\0') { p++; if(*p == '.') break; }if(strcmp(p,".asm") != 0){

cerr << "*** ERROR: Source file not *.asm" << endl;exit(-1);

}*p = '\0';

// Open a text file for the assembly listing. The filename// will have a .lst extension.

char listfile[80];sprintf(listfile, "%s.lst", prefix);fpList = fopen(listfile, "w");if(!fpList){

perror("fopen failed for assembly list file");exit(-1);

}

//***********************************************************************// MODIFIED FROM THE ORIGINAL ASSEMBLER HERE.

// Open a two text files for the object code. The filenames// will have a .hex extension

char objfile[80];

sprintf(objfile, "%s_H.hex", prefix);fpObj_H = fopen(objfile, "w");if(!fpObj_H){

perror("fopen failed for object file");exit(-1);

}

sprintf(objfile, "%s_L.hex", prefix);fpObj_L = fopen(objfile, "w");if(!fpObj_L){

perror("fopen failed for object file");exit(-1);

}

fprintf(fpList,"Block I Apollo Guidance Computer (AGC4) assembler version 1.6 forEPROM\n\n");

// INITIALIZE EPROMfor(int k=0; k< agcMemSize; k++){

EPROM_H [k] = 0;EPROM_L [k] = 0;

}//***********************************************************************

fprintf(fpList,"First pass: generate symbol table.\n");

Page 319: Apollo Guidance Computer AGC

readSourceForPass1(sourcefile);

locCntr = 0;pass++;

// Clear the memory use flags; these are used to catch// any overwriting of already assembled code.

memset(memoryUsed, false, sizeof(bool) * agcMemSize);

fprintf(fpList,"Second pass: generate object code.\n\n");readSourceForPass2(sourcefile);

//***********************************************************************// MODIFIED FROM THE ORIGINAL ASSEMBLER HERE.

// Write the EPROM data to filewriteEPROM(fpObj_H, EPROM_H);writeEPROM(fpObj_L, EPROM_L);

fclose(fpObj_H);fclose(fpObj_L);//***********************************************************************

fprintf(fpList,"\nAssembly complete. Errors = %d\n", errorCount);

fprintf(fpList,"\nSymbol table:\n");

unsigned j=0;for(unsigned i=0; i<nSym; i++){

fprintf(fpList,"%-14s %06o ", symTab[i].name, symTab[i].val);j = (j+1) % 3;if(j==0) fprintf(fpList,"\n");

}fclose(fpList);

}

Page 320: Apollo Guidance Computer AGC
Page 321: Apollo Guidance Computer AGC

Block IApollo Guidance Computer (AGC)

How to build one in your basement

Part 7: C++ Simulator

John Pultorak

December, 2004

Page 322: Apollo Guidance Computer AGC

Abstract

This report describes my successful project to build a working reproduction of the 1964

prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the

Apollo moon landings, and is the world’s first integrated circuit computer.

I built it in my basement. It took me 4 years.

If you like, you can build one too. It will take you less time, and yours will be better than

mine.

I documented my project in 9 separate .pdf files:

Part 1 Overview: Introduces the project.

Part 2 CTL Module: Design and construction of the control module.

Part 3 PROC Module: Design and construction of the processing (CPU) module.

Part 4 MEM Module: Design and construction of the memory module.

Part 5 IO Module: Design and construction of the display/keyboard (DSKY) module.

Part 6 Assembler: A cross-assembler for AGC software development.

Part 7 C++ Simulator: A low-level simulator that runs assembled AGC code.

Part 8 Flight Software: My translation of portions of the COLOSSUS 249 flight

software.

Part 9 Test & Checkout: A suite of test programs in AGC assembly language.

Page 323: Apollo Guidance Computer AGC

Overview

This document describes my AGC Block I C++ simulator. I developed it almost entirely from

detailed information in this document:

A. Hopkins, R. Alonso, and H. Blair-Smith, "Logical Description for the Apollo Guidance

Computer (AGC4)", R-393, MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963.

My simulator reproduces not only the AGC instruction set and user-accessible registers, but

all of the registers, all microinstructions, time-pulse generator states, read, write and

memory busses, and control pulses (logic signals) for all AGC subsystems.

The simulator is a tool I used to capture AGC design from the R-393 document. When I got

it working well enough to run my test and checkout software suite (described in part 9) and

flight software (described in part 8), I knew I understood the AGC well enough to build one.

The simulator header and source code files became requirements that guided my AGC logic

design (described in parts 2-5).

Running the simulator

The simulator is run by keyboard commands. The output is a scrolling, formatted text

display; the compiler obligingly provides a little DOS window for viewing the output. It looks

like this (most of

the numbers are

in octal):

The top line is

the revision

number of the

simulator. I

went through

lots of versions.

The second line

shows the Time

Pulse Generator

state (TP11) and

some of the

important scaler

outputs.

The next line shows the current state of some small registers in the SEQ subsystem, which

is part of the AGC control module. STA and STB stage registers which select instruction

subsequences. BR1 and 2 are the branch registers. SNI is “select next instruction”, a 1-bit

register that does exactly that. CI is the “carry-in” bit for the ALU. The loop counter is used

for iterating through arithmetic instructions.

The next line, starting with RPCELL, shows important registers associated with interrupts

and the priority counters. The tail-end of the line shows the current instruction (in the SQ

register), which is an INDEX instruction. The subsequence is NDX0.

Page 324: Apollo Guidance Computer AGC

The next line (CP) shows currently asserted control pulses (logic signals). ST1 and WE are

being asserted.

The left side of the next 4 lines shows the state of registers associated with memory (S, G,

P, P2, and CADR), the ALU (B, X, Y, U), and the read bus (RBU) and write bus (WBU).

The right side of those 4 lines shows control inputs for running, stepping, and clocking the

simulator.

The bottom part of the display shows AGC memory. The 2-digit numbers on the left show

memory addresses from 00-56. Each memory location has a name; it’s shown to the right of

the address. Immediately to the right of that is the contents of that location.

Addresses 00-17 are mapped to AGC registers, and are not really part of the AGC eraseable

memory. Addresses 00-03 are the AGC central registers, followed by input and output

registers.

Addresses 16 and 17 are not storage locations, but a means for enabling and disabling

interrupts.

The eraseable memory starts at address 20. Addresses 20-23 are the editing registers.

Writing to these causes the data in the registers to be shifted or rotated.

Addresses 24-27 are used for saving the central registers (00-03) when an interrupt occurs.

Addresses 34-56 are priority counter locations. The AGC will increment or decrement these

based on + pr - logic signals to the priority counter cells.

The lower right of the simulator is the DSKY: the display/keyboard user interface for the

astronauts. The simulator is running the COLOSSUS 249 flight software load, and is

currently executing major mode 0 (P00), verb 16, noun 36, which is a monitor program to

continuously display the command module elapsed time clock. The clock, displayed in R1,

R2, and R3, shows 0 hours, 1 minute, and 54.23 seconds. It updates about once a second

but, of course, you can’t see that here.

Compiler

The simulator was compiled with Microsoft Visual C++ 6.0 Standard Edition.

Page 325: Apollo Guidance Computer AGC

Commands

Here’s the complete list of commands the simulator knows. The keyboard key you hit is:

{Q}, and the name of the command is: <QUIT>.

Simulator commands{q} <QUIT> Exits the simulator.

{l} <LOAD> The command is a lower case “L”, not a “1". Load fixed

memory with object code produced by the assembler.

The object code files are in Motorola S-Record format

(compatible with EPROM programmers). The command

will ask for a filename.

{m} <MENU> Intended to be a useful menu of simulator command,

but I never got around to it.

Hardware reset commands{p} <POWER UP RESET> Asserts the PURST control signal. This is a power-up

reset signal that is supposed to be automatically

generated when the AGC initially powers on.

{h} <RESET> Asserts the GENRST control signal.

Clock controls{F1} <CLK> Single-step the AGC clock. Only works when MCLK <F2>

has been selected.

{F2} <MCLK> Asserts the MCLK control signal. Disables the free-

running 1MHz clock. When MCLK is selected, you can

single-step the clock by by pressing <F1>.

{F4} <FCLK> Asserts the FCLK control signal. Causes the simulator

clock to free-run at 1MHz. This is the normal operational

mode.

Page 326: Apollo Guidance Computer AGC

Time pulse generator (TPG) controls{r} <RUN> Toggles between the “run” (1) and “step” (0) modes.

“Run” makes the AGC free-run (the normal mode).

“Step” single-steps the AGC, either by instruction or by

instruction subsequence.

{s} <STEP> Steps the AGC to the next instruction or instruction

sequence when <R> is toggled to the step mode.

{n} <INST> Toggles whether the AGC steps by instruction (1) or

instruction subsequence (0). Each instruction contains

one or more subsequences. Each subsequence is 12

steps or timing pulses long.

Debugger commands{e} <EXAMINE> Examines the contents of memory. The command asks

for a starting address and then displays the memory

data at that address and following locations.

{y} <WATCH> Halts the AGC when any instruction changes a watched

memory location. The command asks for a memory

address (CADR) to watch.

{b} <BREAKPOINT> Toggles a breakpoint on/off. When the breakpoint is on,

it halts the AGC when instruction execution hits that

address.

{d} <DISPLAY> Displays or refreshes the standard AGC register display.

{f} <DEBUG> Displays the currently executing AGC source code. You

can single step with this display and watch the AGC

move through the source code. Very useful for

debugging. A “>” arrow shows the next instruction to be

executed in the listing.

Scaler controls{z} <F17> Manually generates the <F17> scaler pulse. Useful for

testing when the scaler has been toggled to off <C>, or

when you’re single-stepping the AGC.

{x} <F13> Manually generates the <F13> scaler pulse. Useful for

testing when the scaler has been toggled to off <C>, or

when you’re single-stepping the AGC.

{c} <TOGGLE SCALER> Toggle the scaler on/off. When the scaler is off, the F13

and F17 signals are not automatically generated.

Priority counter controls{[} <-CNTR> Manually assert a m inus input to a prority counter cell.

The command will ask for the cell number.

{]} <+CNTR> Manually assert a p lus input to a priority counter cell.

The command will ask for the cell number.

Page 327: Apollo Guidance Computer AGC

Interrupt controls{i} <INTERRUPT> Generates an AGC interrupt. The command will ask you

for an interrupt number (1-5).

Other AGC controls{a} <STANDBY ALLOWED> The standby allowed switch lets the AGC software put

the AGC in a standby mode.

{;} <CLEAR PARITY ALARM> Clears the parity alarm. The alarm is generated when an

error occurs (odd parity) in memory.

DSKY controls{/} <VERB> The VERB key on the DSKY display.

{*} <NOUN> The NOUN key on the DSKY display.

{-} <MINUS> The MINUS key on the DSKY display.

{+} <PLUS> The PLUS key on the DSKY display.

{.} <CLEAR> The CLEAR key on the DSKY display.

{j} <ENTER> The ENTER key on the DSKY display.

{g} <KEY REL> The KEY RELEASE key on the DSKY display.

Page 328: Apollo Guidance Computer AGC

Simulator demonstration

Here’s the simulator, demonstrating some COLOSSUS 249 flight software functions. This is

the same scenario I ran in Part 1 using my hardware AGC.

Initialization

At startup, the simulator loads the microinstructions from the EPROM tables. These are the

same tables I eventually used to program the hardware AGC EPROMs.

Reading EPROM: CPM1_8.hex

Reading EPROM: CPM9_16.hex

Reading EPROM: CPM17_24.hex

Reading EPROM: CPM25_32.hex

Reading EPROM: CPM33_40.hex

Reading EPROM: CPM41_48.hex

Reading EPROM: CPM49_56.hex

The simulator is now initialized

and ready for commands.

<LOAD>

The simulator asks, and I enter the name of object files containing the COLOSSUS flight

software.

<POWER UP RESET> <RUN>

<FCLK>

I tell the simulator to start

running, and enable the free-

running clock. The AGC starts

running in real-time with the 1MHz

clock. The DSKY shows major

mode 00 (P00).

Page 329: Apollo Guidance Computer AGC

Display elapsed time fromthe CM clock

<VERB> <0> <6> <NOUN> <3>

<6> <ENTER>

Test display lights

<VERB> <3> <5> <ENTER>

All DSKY lamps and display

segments illuminate for 5 sec;

after 5 sec, the DSKY lamps

extinguish.

Load component 1 fordataset at octal address50 with octal 123

<VERB> <2> <1> <NOUN> <0>

<1> <ENTER>

Verb/noun display flashes: waiting

for address. Flashing is indicated

by the asterisk to the right of the

NOUN display.

Page 330: Apollo Guidance Computer AGC

<5> <0> <ENTER>

Verb/noun display flash continues:

waiting for data.

<1> <2> <3> <ENTER>

Octal word from R1 is loaded at

address 50.

Start a monitor programto continuously displayelapsed time from the CMclock

<VERB> <1> <6> <NOUN> <3>

<6> <ENTER>

Page 331: Apollo Guidance Computer AGC

Display component 1 ofdataset at octal address50

<VERB> <0> <1>

The key rel light flashes because

the CM clock monitor program has

been suspended. This is indicated

by an asterisk in the KR display

above the DSKY.

<NOUN> <0> <1> <ENTER>

Verb/noun display flashes: waiting

for address.

<5> <0> <ENTER>

Octal word from address 50 is

displayed in R1.

Page 332: Apollo Guidance Computer AGC

Increment the address

<NOUN> <1> <5> <ENTER>

Octal word from address 51 is

displayed in R1, address in R3.

<ENTER>

Octal word from address 52 is

displayed in R1, address in R3.

Resume the CM clockmonitor program

<KEY REL>

Verb 16, noun 36 reappears, along

with the clock display. Notice that

the KR light (asterisk) goes out.

Page 333: Apollo Guidance Computer AGC

Terminate the CM clockmonitor program

<VERB> <3> <4> <ENTER>

Change major mode toP00

<VERB> <3> <7> <ENTER>

Verb/noun display flashes:

waiting for major mode.

<0> <0> <ENTER>

Page 334: Apollo Guidance Computer AGC

The 20-or-so

subsystems in the AGC

are represented by C++

classes. There are some

additional classes for

registers and other

things.

I wanted a simulator

architecture I could

develop quickly that

would easily and directly

map to a hardware logic

design. I went through

16 versions of the

simulator; they’re

discussed at the top of

the AGCMain.cpp file

which contains,

unsurprisingly, the

main().

If you want to run the

simulator, you can

compile it from the

source code given here. To run it, you’ll also need the assembler (discussed in part 6), some

AGC software (parts 8 and 9), and the EPROM tables in Motorola S-Record format. The C++

code to generate these tables is given at the end of part 2.

Here it is, warts and all...

Page 335: Apollo Guidance Computer AGC

Main (AGCMain.cpp)

/**************************************************************************** * AGC4 (Apollo Guidance Computer) BLOCK I Simulator * * AUTHOR: John Pultorak * DATE: 07/29/02 * FILE: AGCmain.cpp * * VERSIONS: * 1.0 - initial version. * 1.1 - fixed minor bugs; passed automated test and checkout programs: * teco1.asm, teco2.asm, and teco3.asm to test basic instructions, * extended instructions, and editing registers. * 1.2 - decomposed architecture into subsystems; fixed minor bug in DSKY * keyboard logic (not tested in current teco*.asm suite). * Implemented scaler pulses F17, F13, F10. Tied scaler output to * involuntary counters and interrupts. Implemented counter overflow * logic and tied it to interrupts and other counters. Added simple * set/clear breakpoint. Fixed a bug in bank addressing. * 1.3 - fixed bugs in the DSKY. Added 14-bit effective address (CADR) to the * simulator display output. Inhibited interrupts when the operator * single-steps the AGC. * 1.4 - performance enhancements. Recoded the control pulse execution code * for better simulator performance. Also changed the main loop so it * polls the keyboard and system clock less often for better performance. * 1.5 - reversed the addresses of TIME1 and TIME2 so TIME2 occurs first. * This is the way its done in Block II so that a common routine (READLO) * can be used to read the double word for AGC time. * 1.6 - added indicators for 'CHECK FAIL' and 'KEY RELS'. Mapped them to OUT1, * bits 5 and 7. Added a function to display the current location in * the source code list file using the current CADR. * 1.7 - increased length of 'examine' function display. Any changes in DSKY now * force the simulator to update the display immediately. Added a 'watch' * function that looks for changes in a memory location and halts the * AGC. Added the 'UPTL', 'COMP', and "PROG ALM" lights to the DSKY. * 1.8 - started reorganizing the simulator in preparation for H/W logic design. * Eliminated slow (1Hz) clock capability. Removed BUS REQUEST feature. * Eliminated SWRST switch. * 1.9 - eliminated the inclusive 'OR' of the output for all registers onto the * R/W bus. The real AGC OR'ed all register output onto the bus; normally * only one register was enabled at a time, but for some functions several * were simultaneously enabled to take advantage of the 'OR' function (i.e.: * for the MASK instruction). The updated logic will use tristate outputs * to the bus except for the few places where the 'OR' function is actually * needed. Moved the parity bit out of the G register into a 1-bit G15 * register. This was done for convenience because the parity bit in G * is set independently from the rest of the register. * 1.10 - moved the G15 parity register from MBF to the PAR subsystem. Merged SBFWG * and SBEWG pulses into a single SBWG pulse. Deleted the CLG pulse for MBF * (not needed). Separated the ALU read pulses from all others so they can * be executed last to implement the ALU inclusive OR functions. Implemented * separate read and write busses, linked through the ALU. Implemented test * parity (TP) signal in PAR; added parity alarm (PALM) FF to latch PARITY * ALARM indicator in PAR. * 1.11 - consolidated address testing signals and moved them to ADR. Moved memory * read/write functions from MBF to MEM. Merged EMM and FMM subsystems into * MEM. Fixed a bad logic bug in writeMemory() that was causing the load of * the fixed memory to overwrite array boundaries and clobber the CPM table. * Added a memory bus (MEM_DATA_BUS, MEM_PARITY_BUS). * 1.12 - reduced the number of involuntary counters (CTR) from 20 to 8. Eliminated * the SHINC subsequence. Changed the (CTR) sequence and priority registers into * a single synchronization register clocked by WPCTR. Eliminated the fifth * interrupt (UPRUPT; INT). Eliminated (OUT) the signal to read from output * register 0 (the DSKY register), since it was not used and did not provide * any useful function, anyway. Deleted register OUT0 (OUT) which shadowed * the addressed DSKY register and did not provide any useful function. * Eliminated the unused logic that sets the parity bit in OUT2 for downlink * telemetry. * 1.13 - reorganized the CPM control pulses into CPM-A, CPM-B, and CPM-C groups. * Added the SDV1, SMP1, and SRSM3 control pulses to CPM-A to indicate when * those subsequences are active; these signals are input to CPM-C. Moved the * ISD function into CPM-A. Fixed a minor bug causing subsequence RSM3 to be * displayed as RSM0. Added GENRST to clear most registers during STBY. * 1.14 - Moved CLISQ to TP1 to fix a problem in the hardware AGC. CLISQ was clearing

Page 336: Apollo Guidance Computer AGC

* SNI on CLK2 at TP12, but the TPG was advancing on CLK1 which occurs after * CLK2, so the TPG state machine was not seeing SNI and was not moving to * the correct state. In this software simulation, everything advances on * the same pulse, so it wasn't a problem to clear SNI on TP12. Added a * switch to enable/disable the scaler. * 1.15 - Reenabled interrupts during stepping (by removing MON::RUN) signals from * CPM-A and CPM-C logic). Interrupts can be prevented by disabling the scaler. * Fixed a problem with INHINT1; it is supposed to prevent an interrupt * between instructions if there's an overflow. It was supposed to be cleared * on TP12 after SNI (after a new instruction), but was being cleared on TP12 * after every subsequence. * 1.16 - Changed CPM-A to load and use EPROM tables for the control pulse matrix. The * EPROM tables are negative logic (0=asserted), but this simulator expects * positive logic, so each word is bit-flipped when the EPROM tables load * during simulator initialization. * SOURCES: * Mostly based on information from "Logical Description for the Apollo Guidance * Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh Blair-Smith, R-393, * MIT Instrumentation Laboratory, 1963. * * PORTABILITY: * Compiled with Microsoft Visual C++ 6.0 standard edition. Should be fairly * portable, except for some Microsoft-specific I/O and timer calls in this file. * * NOTE: set tabs to 4 spaces to keep columns formatted correctly. * ***************************************************************************** */

#include <conio.h>

#include <iostream.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <conio.h>#include <stdio.h>#include <time.h>#include <ctype.h>

#include "reg.h"

#include "TPG.h"#include "MON.h"#include "SCL.h"#include "SEQ.h"#include "INP.h"#include "OUT.h"#include "BUS.h"#include "DSP.h"#include "ADR.h"#include "PAR.h"#include "MBF.h"#include "MEM.h"#include "CTR.h"#include "INT.h"#include "KBD.h"#include "CRG.h"#include "ALU.h"#include "CPM.h"#include "ISD.h"#include "CLK.h"

extern bool dskyChanged;

//-----------------------------------------------------------------------// CONTROL LOGIC

void genAGCStates(){

// 1) Decode the current instruction subsequence (glbl_subseq).// SEQ::glbl_subseq = CPM::instructionSubsequenceDecoder();

// 2) Build a list of control pulses for this state.CPM::controlPulseMatrix();

Page 337: Apollo Guidance Computer AGC

// 3) Execute the control pulses for this state. In the real AGC, these occur// simultaneously. Since we can't achieve that here, we break it down into the// following steps:// Most operations involve data transfers--usually reading data from// a register onto a bus and then writing that data into another register. To// approximate this, we first iterate through all registers to perform// the 'read' operation--this transfers data from register to bus.// Then we again iterate through the registers to do 'write' operations,// which move data from the bus back into the register.

BUS::glbl_READ_BUS = 0; // clear bus; necessary because words are logical // OR'ed onto the bus.

MEM::MEM_DATA_BUS = 0; // clear data lines: memory bits 15-1MEM::MEM_PARITY_BUS = 0; // parity line: memory bit 16

// Now start executing the pulses:

// First, read register outputs onto the bus or anywhere else.int i;for(i=0; i<MAXPULSES && SEQ::glbl_cp[i] != NO_PULSE; i++){

CLK::doexecR(SEQ::glbl_cp[i]);}

// Next, execute ALU read pulses. See comments in ALU .C fileALU::glbl_BUS = 0;for(i=0; i<MAXPULSES && SEQ::glbl_cp[i] != NO_PULSE; i++){

CLK::doexecR_ALU(SEQ::glbl_cp[i]);}BUS::glbl_WRITE_BUS = BUS::glbl_READ_BUS; // in case nothing is logically OR'ed below;for(i=0; i<MAXPULSES && SEQ::glbl_cp[i] != NO_PULSE; i++){

CLK::doexecR_ALU_OR(SEQ::glbl_cp[i]);}

// Now, write the bus and any other signals into the register inputs.

for(i=0; i<MAXPULSES && SEQ::glbl_cp[i] != NO_PULSE; i++){

CLK::doexecW(SEQ::glbl_cp[i]);}

// Always execute these pulses.SCL::doexecWP_SCL();SCL::doexecWP_F17();SCL::doexecWP_F13();SCL::doexecWP_F10();TPG::doexecWP_TPG();

}

//-----------------------------------------------------------------------// SIMULATION LOGIC

// contains prefix for source filename; i.e.: the portion// of the filename before .obj or .lst

char filename[80];

char* getCommand(char* prompt){

static char s[80];char* sp = s;

cout << prompt; cout.flush();

char key;while((key = _getch()) != 13){

if(isprint(key)){

cout << key; cout.flush();*sp = key; sp++;

}

Page 338: Apollo Guidance Computer AGC

else if(key == 8 && sp != s){

cout << key << " " << key; cout.flush();sp--;

}}*sp = '\0';return s;

}

bool breakpointEnab = false;unsigned breakpoint = 0;void toggleBreakpoint(){

if(!breakpointEnab){

char b[80];strcpy(b, getCommand("Set breakpoint: -- enter 14-bit CADR (octal): "));cout << endl;

breakpoint = strtol(b,0,8);breakpointEnab = true;

}else{

cout << "Clearing breakpoint." << endl;breakpointEnab = false;

}}

bool watchEnab = false;unsigned watchAddr = 0;unsigned oldWatchValue = 0;void toggleWatch(){

if(!watchEnab){

char b[80];strcpy(b, getCommand("Set watch: -- enter 14-bit CADR (octal): "));cout << endl;

watchAddr = strtol(b,0,8);watchEnab = true;oldWatchValue = MEM::readMemory(watchAddr);

char buf[100];sprintf(buf, "%06o: %06o", watchAddr, oldWatchValue);cout << buf << endl;

}else{

cout << "Clearing watch." << endl;watchEnab = false;

}}

void incrCntr(){

char cntrname[80];strcpy(cntrname, getCommand("Increment counter: -- enter pcell (0-19): "));cout << endl;

int pc = atoi(cntrname);CTR::pcUp[pc] = 1;

}

void decrCntr(){

char cntrname[80];strcpy(cntrname, getCommand("Decrement counter: -- enter pcell (0-19): "));cout << endl;

int pc = atoi(cntrname);CTR::pcDn[pc] = 1;

}

Page 339: Apollo Guidance Computer AGC

void interrupt(){

char iname[80];strcpy(iname, getCommand("Interrupt: -- enter priority (1-5): "));cout << endl;

int i = atoi(iname) - 1;INT::rupt[i] = 1;

}

#ifdef NOTDEF// Load AGC memory from the specified file object file

void loadMemory(){

strcpy(filename, getCommand("Load Memory -- enter filename: "));cout << endl;

// Add the .obj extension.char fname[80];strcpy(fname, filename);strcat(fname, ".obj");

FILE* fp = fopen(fname, "r");if(!fp){

perror("fopen failed:");cout << "*** ERROR: Can't load memory for file: " << fname << endl;return;

}unsigned addr;unsigned data;while(fscanf(fp, "%o %o", &addr, &data) != EOF){

MEM::writeMemory(addr, data);}fclose(fp);cout << "Memory loaded." << endl;

}#endif

static int loadBuf[0xffff+1]; // tempory buffer for assembling H,L memory data

void loadEPROM(char* fileName, bool highBytes){

cout << "Reading EPROM: " << fileName << endl;

// Open the EPROM file.FILE* ifp = fopen(fileName, "r");if(!ifp){

perror("fopen failed for source file");exit(-1);

}

const int addressBytes = 3; // 24-bit address rangeconst int sumCheckBytes = 1;

char buf[4096]; // buffer holds a single S-Recordwhile(fgets(buf,4096,ifp)){

// process a recordif(buf[0] != 'S'){

cout << "Error reading start of EPROM record for: " << fileName << endl;exit(-1);

}

char tmp[256];

strncpy(tmp, &buf[2], 2); tmp[2] = '\0';int totalByteCount = strtol(tmp, 0, 16);int mySumCheck = totalByteCount & 0xff;

Page 340: Apollo Guidance Computer AGC

strncpy(tmp, &buf[4], 6); tmp[addressBytes*2] = '\0';int address = strtol(tmp, 0, 16);mySumCheck = (mySumCheck + ((address & 0xff0000) >> 16)) % 256;mySumCheck = (mySumCheck + ((address & 0x00ff00) >> 8)) % 256;mySumCheck = (mySumCheck + ((address & 0x0000ff) )) % 256;

//cout << hex << totalByteCount << ", " << address << dec << endl;

int dataBytes = totalByteCount - addressBytes - sumCheckBytes;

int i = (addressBytes+2)*2; // index to 1st databyte char.for(int j=0; j<dataBytes; j++){

// get a data bytestrncpy(tmp, &buf[i], 2); tmp[2] = '\0';int data = strtol(tmp, 0, 16);//cout << hex << data << dec << endl;mySumCheck = (mySumCheck + data) % 256;

if(highBytes){

loadBuf[address] = loadBuf[address] | ((data << 8) & 0xff00);}else{

loadBuf[address] = loadBuf[address] | (data & 0xff);}address++;

i+=2; // bump to next databyte char}strncpy(tmp, &buf[i], 2); tmp[2] = '\0';int sumCheck = strtol(tmp, 0, 16);

if(sumCheck != ((~mySumCheck) & 0xff)){

cout << "sumCheck failed; file: " << fileName << ", address: " << hex << address << ", sumCheck: " << sumCheck << ", mySumCheck: " << mySumCheck << dec << endl;

exit(-1);}

}fclose(ifp);cout << "Memory loaded." << endl;

}

// Load AGC memory from the specified EPROM filesvoid loadMemory(){

strcpy(filename, getCommand("Load Memory -- enter filename: "));cout << endl;

char fname[80];

// Add the _H.hex extension.strcpy(fname, filename);strcat(fname, "_H.hex");

loadEPROM(fname, true);

// Add the _L.hex extension.strcpy(fname, filename);strcat(fname, "_L.hex");

loadEPROM(fname, false);

//*******************************************************************// EPROM is now in loadBuf; move it to AGC memory.// AGC fixed memory only uses NUMFBANK banks.

for(int address=1024; address < 1024*(NUMFBANK+1); address++){

// Don't load address region 0-1023; that region is allocated

Page 341: Apollo Guidance Computer AGC

// to eraseable memory.//cout << "loading CADR=" << hex << address << endl;MEM::writeMemory(address, loadBuf[address]);

}//*******************************************************************

}

// Write the entire contents of fixed and// eraseable memory to the specified file.// Does not write the registers

void saveMemory(char* filename){

FILE* fp = fopen(filename, "w");if(!fp){

perror("*** ERROR: fopen failed:");exit(-1);

}char buf[100];for(unsigned addr=020; addr<=031777; addr++){

sprintf(buf, "%06o %06o\n", addr, MEM::readMemory(addr));fputs(buf, fp);

}fclose(fp);

}

void examineMemory(){

char theAddress[20];strcpy(theAddress, getCommand("Examine Memory -- enter address (octal): "));cout << endl;

unsigned address = strtol(theAddress, 0, 8);

char buf[100];for(unsigned i=address; i<address+23; i++){

sprintf(buf, "%06o: %06o", i, MEM::readMemory(i));cout << buf << endl;

}}

// Returns true if time (s) elapsed since last time it returned true; does not block// search for "Time Management"

bool checkElapsedTime(time_t s){

if(!s) return true;

static clock_t start = clock();clock_t finish = clock();

double duration = (double)(finish - start) / CLOCKS_PER_SEC;if(duration >= s){ start = finish;

return true;}return false;

}

// Blocks until time (s) has elapsed.void delay(time_t s){

if(!s) return;

clock_t start = clock();clock_t finish = 0;double duration = 0;

do{

finish = clock();}while((duration = (double)(finish - start) / CLOCKS_PER_SEC) < s);

Page 342: Apollo Guidance Computer AGC

}

void updateAGCDisplay(){

static bool displayTimeout = false;static int clockCounter = 0;

if(checkElapsedTime(2)) displayTimeout = true;if(MON::FCLK){

if(MON::RUN){

// update every 2 seconds at the start of a new instructionif(displayTimeout || dskyChanged){

clockCounter++;if(

(TPG::register_SG.read() == TP12 && SEQ::register_SNI.read() == 1) ||

(TPG::register_SG.read() == STBY) ||clockCounter > 500 ||dskyChanged)

{MON::displayAGC();displayTimeout = false;clockCounter = 0;dskyChanged = false;

}}

}else{

static bool displayOnce = false;if(TPG::register_SG.read() == WAIT){

if(displayOnce == false){

MON::displayAGC();displayOnce = true;clockCounter = 0;

}}else{

displayOnce = false;}

}}else

MON::displayAGC(); // When the clock is manual or slow, always update.}

void showMenu(){

cout << "AGC4 EMULATOR MENU:" << endl;cout << " 'r' = RUN: toggle RUN/HALT switch upward to the RUN position." << endl;

}

const int startCol = 0; // columns are numbered 0-nconst int colLen = 5; // number of chars in column

const int maxLines = 23; // # of total lines to displayconst int noffset = 10; // # of lines prior to, and including, selected line

const int maxLineLen = 79;

void showSourceCode(){

// Add the .lst extension.char fname[80];strcpy(fname, filename);strcat(fname, ".lst");

// Open the file containing the source code listing.FILE* fp = fopen(fname, "r");if(!fp)

Page 343: Apollo Guidance Computer AGC

{perror("fopen failed:");cout << "*** ERROR: Can't load source list file: " << fname << endl;return;

}cout << endl;

// Get the address of the source code line to display.// The address we want is the current effective address is the// S and bank registers.

char CADR[colLen+1];sprintf(CADR, "%05o", ADR::getEffectiveAddress());

int op = 0; // offset indexlong foffset[noffset];for(int i=0; i<noffset; i++) foffset[i]=0;

bool foundit = false;int lineCount = 0;

char s[256];char valString[20];char out[256];

while(!feof(fp)){

if(!foundit){

foffset[op] = ftell(fp);op = (op + 1) % noffset;

}

// Read a line of the source code list file.if(fgets(s, 256, fp)){

// Get the address (CADR) from the line.strncpy(valString, s+startCol, colLen);valString[colLen]='\0';

// 'foundit' is true after we have found the desired line.if(foundit){

if(strcmp(valString,CADR) == 0)cout << ">";

elsecout << " ";

// truncate line so it fits in 80 col displaystrncpy(out, s, maxLineLen);out[maxLineLen] = '\0';cout << out;

lineCount++;if(lineCount >= maxLines)

break;}else{

if(strcmp(valString, CADR) == 0){

// Reposition the file pointer back several lines so// we can see the code that preceeds the desired// line, too.

foundit = true;fseek(fp, foffset[op], 0);

}}

}}fclose(fp);

}

void main(int argc, char* argv[]){

Page 344: Apollo Guidance Computer AGC

CPM::readEPROM( "CPM1_8.hex", CPM::EPROM1_8);CPM::readEPROM( "CPM9_16.hex", CPM::EPROM9_16);CPM::readEPROM("CPM17_24.hex", CPM::EPROM17_24);CPM::readEPROM("CPM25_32.hex", CPM::EPROM25_32);CPM::readEPROM("CPM33_40.hex", CPM::EPROM33_40);CPM::readEPROM("CPM41_48.hex", CPM::EPROM41_48);CPM::readEPROM("CPM49_56.hex", CPM::EPROM49_56);

bool singleClock = false;

genAGCStates();MON::displayAGC();

while(1){

// NOTE: assumes that the display is always pointing to the start of// a new line at the top of this loop!

// Clock the AGC, but between clocks, poll the keyboard// for front-panel input by the user. This uses a Microsoft function;// substitute some other non-blocking function to access the keyboard// if you're porting this to a different platform.cout << "> "; cout.flush(); // display prompt

while( !_kbhit() ){

if(MON::FCLK || singleClock){

// This is a performance enhancement. If the AGC is running,// don't check the keyboard or simulator display every// simulation cycle, because that slows the simulator // down too much.

int genStateCntr = 100;do { CLK::clkAGC();

singleClock = false;

genAGCStates(); genStateCntr--;

// Needs more work. It doesn't always stop at the// right location and sometimes stops at the// instruction afterwards, too.

if(breakpointEnab && breakpoint == ADR::getEffectiveAddress())

{MON::RUN = 0;

}

// Halt right after instr that changes a watched// memory location.

if(watchEnab){

unsigned newWatchValue = MEM::readMemory(watchAddr);if(newWatchValue != oldWatchValue){

MON::RUN = 0;}oldWatchValue = newWatchValue;

}

} while (MON::FCLK && MON::RUN && genStateCntr > 0);

updateAGCDisplay();

}// for convenience, clear the single step switch on TP1; in the// hardware AGC, this happens when the switch is releasedif(MON::STEP && TPG::register_SG.read() == TP1) MON::STEP = 0;

}char key = _getch();

// Keyboard controls for front-panel:switch(key)

Page 345: Apollo Guidance Computer AGC

{// AGC controls// simulator controls

case 'q': cout << "QUIT..." << endl; exit(0);case 'm': showMenu(); break;

case 'd': genAGCStates(); MON::displayAGC(); break; // update display

case 'l': loadMemory(); break;case 'e': examineMemory(); break;

case 'f':showSourceCode();break;

case ']': incrCntr(); //genAGCStates();//displayAGC(EVERY_CYCLE);break;

case '[': decrCntr(); //genAGCStates();//displayAGC(EVERY_CYCLE);break;

case 'i': interrupt(); //genAGCStates();//displayAGC(EVERY_CYCLE);break;

case 'z'://SCL::F17 = (SCL::F17 + 1) % 2; genAGCStates();MON::displayAGC();break;

case 'x'://SCL::F13 = (SCL::F13 + 1) % 2; genAGCStates();MON::displayAGC();break;

case 'c': MON::SCL_ENAB = (MON::SCL_ENAB + 1) % 2;genAGCStates();MON::displayAGC();break;

case 'r': MON::RUN = (MON::RUN + 1) % 2; genAGCStates();if(!MON::FCLK) MON::displayAGC();break;

case 's': MON::STEP = (MON::STEP + 1) % 2; genAGCStates();if(!MON::FCLK) MON::displayAGC();break;

case 'a': MON::SA = (MON::SA + 1) % 2; genAGCStates();MON::displayAGC();break;

case 'n': MON::INST = (MON::INST + 1) % 2; genAGCStates();

Page 346: Apollo Guidance Computer AGC

MON::displayAGC();break;

case 'p': MON::PURST = (MON::PURST + 1) % 2;genAGCStates();MON::displayAGC();break;

case 'b':toggleBreakpoint();break;

case 'y':toggleWatch();break;

case ';': // Clear ALARM indicators

PAR::CLR_PALM(); // Asynchronously clear PARITY FAILMON::displayAGC();break;

// DSKY:case '0': KBD::keypress(KEYIN_0); break;case '1': KBD::keypress(KEYIN_1); break;case '2': KBD::keypress(KEYIN_2); break;case '3': KBD::keypress(KEYIN_3); break;case '4': KBD::keypress(KEYIN_4); break;case '5': KBD::keypress(KEYIN_5); break;case '6': KBD::keypress(KEYIN_6); break;case '7': KBD::keypress(KEYIN_7); break;case '8': KBD::keypress(KEYIN_8); break;case '9': KBD::keypress(KEYIN_9); break;case '+': KBD::keypress(KEYIN_PLUS); break;case '-': KBD::keypress(KEYIN_MINUS); break;case '.': KBD::keypress(KEYIN_CLEAR); break;case '/': KBD::keypress(KEYIN_VERB); break;case '*': KBD::keypress(KEYIN_NOUN); break;case 'g': KBD::keypress(KEYIN_KEY_RELEASE); break;case 'h': KBD::keypress(KEYIN_ERROR_RESET); break;case 'j': KBD::keypress(KEYIN_ENTER); break;

case '\0': // must be a function keykey = _getch();switch(key){case 0x3b: // F1: single clock pulse (when system clock off)

singleClock = true; break; case 0x3c: // F2: manual clock (FCLK=0)

MON::FCLK = 0; genAGCStates(); MON::displayAGC(); break; case 0x3e: // F4: fast clock (FCLK=1)

MON::FCLK = 1; genAGCStates(); MON::displayAGC(); break;default: cout << "function key: " << key << "="

<< hex << (int) key << dec << endl;}break;

//default: cout << "??" << endl;default: cout << key << "=" << hex << (int) key << dec << endl;}

}}

Page 347: Apollo Guidance Computer AGC

ADR (ADR.h)

/**************************************************************************** * ADR - MEMORY ADDRESS subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: ADR.h * * VERSIONS: * * DESCRIPTION: * Memory address for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef ADR_H#define ADR_H

enum specialRegister { // octal addresses of special registers// Flip-Flop registers

A_ADDR =00,Q_ADDR =01,Z_ADDR =02,LP_ADDR =03,IN0_ADDR =04,IN1_ADDR =05,IN2_ADDR =06,IN3_ADDR =07,OUT0_ADDR =010,OUT1_ADDR =011,OUT2_ADDR =012,OUT3_ADDR =013,OUT4_ADDR =014,BANK_ADDR =015,

// No bits in these registersRELINT_ADDR =016,INHINT_ADDR =017,

// In eraseable memoryCYR_ADDR =020,SR_ADDR =021,CYL_ADDR =022,SL_ADDR =023,ZRUPT_ADDR =024,BRUPT_ADDR =025,ARUPT_ADDR =026,QRUPT_ADDR =027,

};

class regS : public reg { public:

regS() : reg(12, "%04o") { }};

class regBNK : public reg { public:

regBNK() : reg(4, "%02o") { }};

class ADR

Page 348: Apollo Guidance Computer AGC

{friend class MON;

friend class MEM;

friend class CLK;friend class CPM;

public:static void execWP_WS();static void execRP_RBK();

static void execWP_WBK();

static bool GTR_17(); // for MBF, CPM static bool GTR_27(); // for PAR static bool EQU_16(); // for CPM static bool EQU_17(); // for CPM static bool EQU_25(); // for SEQ static bool GTR_1777(); // for CPM

static unsigned getEffectiveAddress();

private:static regS register_S; // address registerstatic regBNK register_BNK; // bank register

static unsigned bankDecoder();

static unsigned conv_WBK[];};

#endif

Page 349: Apollo Guidance Computer AGC

ADR (ADR.cpp)

/**************************************************************************** * ADR - MEMORY ADDRESS subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: ADR.cpp * * NOTES: see header file. * ***************************************************************************** */#include "reg.h"#include "ADR.h"#include "SEQ.h"#include "BUS.h"

regS ADR::register_S; // address registerregBNK ADR::register_BNK; // bank register

// transfer bits 14-11 from the bus into the 4-bit bank registerunsigned ADR::conv_WBK[] ={ BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, B14, B13, B12, B11 };

void ADR::execWP_WS(){

register_S.write(BUS::glbl_WRITE_BUS);}

void ADR::execRP_RBK(){

BUS::glbl_READ_BUS = register_BNK.read() << 10;}

void ADR::execWP_WBK(){

register_BNK.writeShift(BUS::glbl_WRITE_BUS, ADR::conv_WBK);}

bool ADR::GTR_27(){

return (register_S.read() > 027); }

bool ADR::GTR_17(){

// check: address is not a central registerreturn (register_S.read() > 017);

}

bool ADR::EQU_25(){

return (register_S.read() == 025); }

bool ADR::EQU_17(){

// check: instruction is INHINT (INDEX 017)return (register_S.read() == 017);

}

bool ADR::EQU_16(){

// check: instruction is RELINT (INDEX 016))return (register_S.read() == 016);

}

bool ADR::GTR_1777(){

// check: address is fixed memory

Page 350: Apollo Guidance Computer AGC

return (register_S.read() > 01777); }

unsigned ADR::bankDecoder(){

// Memory is organized into 13 banks of 1K words each. The banks are numbered// 0-12. Bank 0 is erasable memory; banks 1-12 are fixed (rope) memory. The 10// lower bits in the S register address memory inside a bank. The 2 upper bits// in the S register select the bank. If the 2 upper bits are both 1, the 4-bit// bank register is used to select the bank.// 12 11 Bank// 0 0 0 erasable memory// 0 1 1 fixed-fixed 1 memory// 1 0 2 fixed-fixed 2 memory// 1 1 3-12 fixed-switchable memory (bank register selects bank)unsigned bank = ADR::register_S.readField(12,11);if(bank == 3){

// fixed-switchableif(register_BNK.read() <= 03) // defaults to 6000 - 7777

return 03;else

return register_BNK.read(); // 10000 - 31777}else

return bank; // erasable or fixed-fixed}

unsigned ADR::getEffectiveAddress(){

// Return the 14-bit address selected by lower 10 bits of the S register (1K)// and the bank decoder (which selects the 1K bank)

unsigned lowAddress = ADR::register_S.readField(10,1);

if(ADR::bankDecoder() == 0)return lowAddress;

unsigned highAddress = ADR::bankDecoder() << 10;return highAddress | lowAddress;

}

Page 351: Apollo Guidance Computer AGC

ALU (ALU.h)

/**************************************************************************** * ALU - ARITHMETIC UNIT subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: ALU.h * * VERSIONS: * * DESCRIPTION: * Arithmetic Unit for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef ALU_H#define ALU_H

#include "reg.h"

class regB : public reg { public:

regB() : reg(16, "%06o") { }};

class regCI : public reg { public:

regCI() : reg(1, "%01o") { }};

class regX : public reg { public:

regX() : reg(16, "%06o") { }};

class regY : public reg { public:

regY() : reg(16, "%06o") { }};

class regU : public reg { public:

regU() : reg(16, "%06o") { }virtual unsigned read();

};

class ALU{public:

static unsigned glbl_BUS; // mixes the RC and RU together for MASK

// In the hardware AGC, all read pulses are enabled simultaneously// by CLK1. This simulator has to do the pulses one-at-a-time, so// they are executed in the following sequence to mimic the hardware://// 1) all read pulses involving subsystems other than ALU are executed,// These read pulses output to the glbl_READ_BUS. Only 0 or 1// of these pulses should be active at any time (never 2 or more),//// 2) next, the read pulses for the ALU are executed. The ALU is treated// differently because it is the only subsystem where several read

Page 352: Apollo Guidance Computer AGC

// pulses can be active simultaneously. In the original AGC, these// pulses 'inclusive OR' their output to the glbl_READ_BUS, so the// simulator has be implemented to execute all read pulses other than// the ALU reads first, so the ALU will have the bus data it needs// in order to do the inclusive OR.// In the recreated AGC hardware design, the ALU is also the subsystem// that links the glbl_READ_BUS to the glbl_WRITE_BUS.//// The recreated ALU hardware design checks whether anything is being// written to the glbl_READ_BUS by the other subsystems. If not, it// outputs zeroes to the glbl_READ_BUS for input to the inclusive OR// operation.// It then transfers data on the glbl_READ_BUS to the glbl_WRITE_BUS// using an inclusive OR with data generated by other ALU read pulses.// The AGC sequencer uses this operation to set certain data lines.//// 3) finally, all write pulses are executed.

static void execRP_ALU_RB();static void execRP_ALU_RC();static void execRP_ALU_RU();

static void execRP_ALU_OR_RB14();static void execRP_ALU_OR_R1();static void execRP_ALU_OR_R1C();static void execRP_ALU_OR_R2();static void execRP_ALU_OR_R22();static void execRP_ALU_OR_R24();static void execRP_ALU_OR_R2000();static void execRP_ALU_OR_RSB();

static void execWP_GENRST();static void execWP_WB();

static void execWP_CI();static void execWP_WY();

static void execWP_WX();static void execWP_WYx();

static regB register_B; // next instructionstatic regCI register_CI; // ALU carry-in flip flopstatic regX register_X; // ALU X registerstatic regY register_Y; // ALU Y registerstatic regU register_U; // ALU sum

};

#endif

Page 353: Apollo Guidance Computer AGC

ALU (ALU.cpp)

/**************************************************************************** * ALU - ARITHMETIC UNIT subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: ALU.cpp * * NOTES: see header file. * ***************************************************************************** */#include "ALU.h"#include "SEQ.h"#include "BUS.h"

regB ALU::register_B; // next instructionregCI ALU::register_CI; // ALU carry-in flip flopregX ALU::register_X; // ALU X registerregY ALU::register_Y; // ALU Y registerregU ALU::register_U; // ALU sum

unsigned ALU::glbl_BUS = 0;

//************************************************************

void ALU::execRP_ALU_RB(){

BUS::glbl_READ_BUS = register_B.read();}

// Performs an inclusive OR or register U and register C; // in the MASK instruction, the RC and RU control pulses// are activated simultaneously. This causes both to be// gated onto the AGC bus which performs the logical OR.

void ALU::execRP_ALU_RC(){

ALU::glbl_BUS |= register_B.outmask() & (~register_B.read());BUS::glbl_READ_BUS = ALU::glbl_BUS;

}

// Performs an inclusive OR or register U and register C; // in the MASK instruction, the RC and RU control pulses// are activated simultaneously. This causes both to be// gated onto the AGC bus which performs the logical OR.

void ALU::execRP_ALU_RU(){

ALU::glbl_BUS |= register_U.read();BUS::glbl_READ_BUS = ALU::glbl_BUS;

}

//************************************************************

//************************************************************// This is the interface between the read and write busses

void ALU::execRP_ALU_OR_RB14(){

BUS::glbl_WRITE_BUS |= 0020000 | BUS::glbl_READ_BUS;}

void ALU::execRP_ALU_OR_R1(){

Page 354: Apollo Guidance Computer AGC

BUS::glbl_WRITE_BUS |= 0000001 | BUS::glbl_READ_BUS;}

void ALU::execRP_ALU_OR_R1C(){

BUS::glbl_WRITE_BUS |= 0177776 | BUS::glbl_READ_BUS;}

void ALU::execRP_ALU_OR_R2(){

BUS::glbl_WRITE_BUS |= 0000002 | BUS::glbl_READ_BUS;}

void ALU::execRP_ALU_OR_RSB(){

BUS::glbl_WRITE_BUS |= 0100000 | BUS::glbl_READ_BUS;}

void ALU::execRP_ALU_OR_R22(){

BUS::glbl_WRITE_BUS |= 0000022 | BUS::glbl_READ_BUS;}

void ALU::execRP_ALU_OR_R24(){

BUS::glbl_WRITE_BUS |= 0000024 | BUS::glbl_READ_BUS;}

void ALU::execRP_ALU_OR_R2000(){

BUS::glbl_WRITE_BUS |= 0002000 | BUS::glbl_READ_BUS; // TC GOPROG instruction}

//************************************************************

void ALU::execWP_GENRST(){}

void ALU::execWP_CI(){

register_CI.writeField(1,1,1);}

void ALU::execWP_WX(){

register_X.write(BUS::glbl_WRITE_BUS);}

void ALU::execWP_WB(){

register_B.write(BUS::glbl_WRITE_BUS);}

void ALU::execWP_WYx(){

register_Y.write(BUS::glbl_WRITE_BUS);}

void ALU::execWP_WY(){

if(!SEQ::isAsserted(CI)) register_CI.writeField(1,1,0);register_X.write(0);register_Y.write(BUS::glbl_WRITE_BUS);

}

Page 355: Apollo Guidance Computer AGC

unsigned regU::read(){

unsigned carry = (outmask()+1) & (ALU::register_X.read() + ALU::register_Y.read()); // end-around

carryif(carry || ALU::register_CI.read())

carry = 1; else

carry = 0; return outmask() & (ALU::register_X.read() + ALU::register_Y.read() + carry);}

Page 356: Apollo Guidance Computer AGC

BUS (BUS.h)

/**************************************************************************** * BUS - READ/WRITE BUS subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: BUS.h * * VERSIONS: * * DESCRIPTION: * RW Bus for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef BUS_H#define BUS_H

// BUS LINE DESIGNATIONS// Specify the assignment of bus lines to the inputs of a register (for a 'write'// operation into a register). Each 'conv_' array specifies the inputs into a// single register. The index into the array corresponds to the bit position in// the register, where the first parameter (index=0) is bit 16 of the register (msb)// and the last parameter (index=15) is register bit 1 (lsb). The value of// the parameter identifies the bus line assigned to that register bit. 'BX'// means 'don't care'; i.e.: leave that register bit alone.

enum { D0=17, // force bit to zeroSGM=15, // sign bit in memorySG=16, // sign (S2; one's compliment)US=15, // uncorrected sign (S1; overflow), except in register GB14=14, B13=13, B12=12, B11=11, B10=10, B9=9, B8=8, B7=7, B6=6, B5=5, B4=4, B3=3, B2=2, B1=1, BX=0 // ignore

};

enum ovfState { NO_OVF, POS_OVF, NEG_OVF };

class BUS{public:

static unsigned glbl_READ_BUS; // read/write bus for xfer between central regsstatic unsigned glbl_WRITE_BUS; // read/write bus for xfer between central regs

friend class INT;friend class CTR;

private:static ovfState testOverflow(unsigned bus);

};

#endif

Page 357: Apollo Guidance Computer AGC

BUS (BUS.cpp)

/**************************************************************************** * BUS - READ/WRITE BUS subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: BUS.cpp * * NOTES: see header file. * ***************************************************************************** */#include "BUS.h"

unsigned BUS::glbl_READ_BUS = 0;unsigned BUS::glbl_WRITE_BUS = 0;

ovfState BUS::testOverflow(unsigned bus){

if((bus & 0100000) && !(bus & 0040000))return NEG_OVF; // negative overflow

else if(!(bus & 0100000) && (bus & 0040000))return POS_OVF; // positive overflow

elsereturn NO_OVF;

}

Page 358: Apollo Guidance Computer AGC

CLK (CLK.h)

/**************************************************************************** * CLK - CLOCK subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: CLK.h * * VERSIONS: * * DESCRIPTION: * Clock for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef CLK_H#define CLK_H

#include "reg.h"

// define pointer-to-function typetypedef void (*EXECTYPE)();

class CLK{public:

static void doexecR(int pulse);static void doexecR_ALU(int pulse);static void doexecR_ALU_OR(int pulse);static void doexecW(int pulse);

static void clkAGC();

static reg* registerList[];

};

#endif

Page 359: Apollo Guidance Computer AGC

CLK (CLK.cpp)

/**************************************************************************** * CLK - CLOCK subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: CLK.cpp * * NOTES: see header file. * ***************************************************************************** */#include "CLK.h"#include "INP.h"#include "OUT.h"#include "MBF.h"#include "ADR.h"#include "SEQ.h"#include "ALU.h"#include "CRG.h"#include "CTR.h"#include "INT.h"#include "PAR.h"#include "TPG.h"#include "SCL.h"#include "MEM.h"

// A container for all registers. This is kept so we can iterate through// all registers to execute the control pulses. For simulation purposes// only; this has no counterpart in the hardware AGC.

reg* CLK::registerList[] = // registers are in no particular sequence{

&INP::register_IN0, &INP::register_IN1, &INP::register_IN2, &INP::register_IN3,&OUT::register_OUT1, &OUT::register_OUT2, &OUT::register_OUT3, &OUT::register_OUT4,&MBF::register_G, &PAR::register_G15, &ADR::register_S, &ADR::register_BNK,

&SEQ::register_SQ, &ALU::register_B,&CRG::register_Q, &CRG::register_Z, &CRG::register_LP, &CRG::register_A, &ALU::register_X,&ALU::register_Y, &ALU::register_U, &SEQ::register_STA, &SEQ::register_STB, &SEQ::register_SNI,&SEQ::register_LOOPCTR, &ALU::register_CI, &SEQ::register_BR1, &SEQ::register_BR2, &CTR::register_UpCELL, &CTR::register_DnCELL,&INT::register_RPCELL, &INT::register_INHINT1, &INT::register_INHINT,&PAR::register_P, &PAR::register_P2, &PAR::register_PALM,&TPG::register_SG,&SCL::register_SCL,&SCL::register_F17, &SCL::register_F13, &SCL::register_F10,0 // zero is end-of-list flag

};

void CLK::clkAGC(){

// Now that all the inputs are set up, clock the registers so the outputs// can change state in accordance with the inputs.

for(int i=0; registerList[i]; i++){

registerList[i]->clk();}

}

void execR_NOPULSE() { }void execR_RA0() { CRG::execRP_RA0(); }void execR_RA1() { CRG::execRP_RA1(); }void execR_RA2() { CRG::execRP_RA2(); }void execR_RA3() { CRG::execRP_RA3(); }void execR_RA4() { INP::execRP_RA4(); }void execR_RA5() { INP::execRP_RA5(); }void execR_RA6() { INP::execRP_RA6(); }

Page 360: Apollo Guidance Computer AGC

void execR_RA7() { INP::execRP_RA7(); }void execR_RA11() { OUT::execRP_RA11(); }void execR_RA12() { OUT::execRP_RA12(); }void execR_RA13() { OUT::execRP_RA13(); }void execR_RA14() { OUT::execRP_RA14(); }void execR_RA() { CRG::execRP_RA(); }void execR_RBK() { ADR::execRP_RBK(); }void execR_RG() { MBF::execRP_RG(); }void execR_RLP() { CRG::execRP_RLP(); }void execR_RQ() { CRG::execRP_RQ(); }void execR_RRPA() { INT::execRP_RRPA(); }void execR_RSCT() { CTR::execRP_RSCT(); }void execR_RZ() { CRG::execRP_RZ(); }void execR_SBWG() { MEM::execRP_SBWG(); }void execR_WE() { MBF::execRP_WE(); PAR::execRP_WE(); }

void execR_ALU_RB() { ALU::execRP_ALU_RB(); }void execR_ALU_RC() { ALU::execRP_ALU_RC(); }void execR_ALU_RU() { ALU::execRP_ALU_RU(); }

void execR_ALU_OR_RSB() { ALU::execRP_ALU_OR_RSB(); }void execR_ALU_OR_R1() { ALU::execRP_ALU_OR_R1(); }void execR_ALU_OR_R1C() { ALU::execRP_ALU_OR_R1C(); }void execR_ALU_OR_R2() { ALU::execRP_ALU_OR_R2(); }void execR_ALU_OR_R22() { ALU::execRP_ALU_OR_R22(); }void execR_ALU_OR_R24() { ALU::execRP_ALU_OR_R24(); }void execR_ALU_OR_R2000() { ALU::execRP_ALU_OR_R2000(); }void execR_ALU_OR_RB14() { ALU::execRP_ALU_OR_RB14(); }

EXECTYPE execR[] ={

execR_NOPULSE, // NO_PULSE,execR_NOPULSE, // CI, // Carry inexecR_NOPULSE, // CLG, // Clear GexecR_NOPULSE, // CLCTR, // Clear loop counter**execR_NOPULSE, // CTR, // Loop counterexecR_NOPULSE, // GP, // Generate ParityexecR_NOPULSE, // KRPT, // Knock down Rupt priorityexecR_NOPULSE, // NISQ, // New instruction to the SQ registerexecR_RA, // RA, // Read AexecR_NOPULSE, // RB, // Read BexecR_NOPULSE, // RB14, // Read bit 14execR_NOPULSE, // RC, // Read CexecR_RG, // RG, // Read GexecR_RLP, // RLP, // Read LPexecR_NOPULSE, // RP2, // Read parity 2execR_RQ, // RQ, // Read QexecR_RRPA, // RRPA, // Read RUPT addressexecR_NOPULSE, // RSB, // Read sign bitexecR_RSCT, // RSCT, // Read selected counter addressexecR_NOPULSE, // RU, // Read sumexecR_RZ, // RZ, // Read ZexecR_NOPULSE, // R1, // Read 1execR_NOPULSE, // R1C, // Read 1 complimentedexecR_NOPULSE, // R2, // Read 2execR_NOPULSE, // R22, // Read 22execR_NOPULSE, // R24, // Read 24execR_NOPULSE, // ST1, // Stage 1execR_NOPULSE, // ST2, // Stage 2execR_NOPULSE, // TMZ, // Test for minus zeroexecR_NOPULSE, // TOV, // Test for overflowexecR_NOPULSE, // TP, // Test parityexecR_NOPULSE, // TRSM, // Test for resumeexecR_NOPULSE, // TSGN, // Test signexecR_NOPULSE, // TSGN2, // Test sign 2execR_NOPULSE, // WA, // Write AexecR_NOPULSE, // WALP, // Write A and LPexecR_NOPULSE, // WB, // Write BexecR_NOPULSE, // WGx, // Write G (do not reset)execR_NOPULSE, // WLP, // Write LPexecR_NOPULSE, // WOVC, // Write overflow counterexecR_NOPULSE, // WOVI, // Write overflow RUPT inhibitexecR_NOPULSE, // WOVR, // Write overflowexecR_NOPULSE, // WP, // Write P

Page 361: Apollo Guidance Computer AGC

execR_NOPULSE, // WPx, // Write P (do not reset)execR_NOPULSE, // WP2, // Write P2execR_NOPULSE, // WQ, // Write QexecR_NOPULSE, // WS, // Write SexecR_NOPULSE, // WX, // Write XexecR_NOPULSE, // WY, // Write YexecR_NOPULSE, // WYx, // Write Y (do not reset)execR_NOPULSE, // WZ, // Write Z

execR_NOPULSE, // RSC, // Read special and centralexecR_NOPULSE, // WSC, // Write special and centralexecR_NOPULSE, // WG, // Write G

execR_NOPULSE, // SDV1, // Subsequence DV1 is activeexecR_NOPULSE, // SMP1, // Subsequence MP1 is activeexecR_NOPULSE, // SRSM3, // Subsequence RSM3 is active

execR_RA0, // RA0, // Read register at address 0 (A)execR_RA1, // RA1, // Read register at address 1 (Q)execR_RA2, // RA2, // Read register at address 2 (Z)execR_RA3, // RA3, // Read register at address 3 (LP)execR_RA4, // RA4, // Read register at address 4execR_RA5, // RA5, // Read register at address 5execR_RA6, // RA6, // Read register at address 6execR_RA7, // RA7, // Read register at address 7execR_NOPULSE, // RA10, // Read register at address 10 (octal)execR_RA11, // RA11, // Read register at address 11 (octal)execR_RA12, // RA12, // Read register at address 12 (octal)execR_RA13, // RA13, // Read register at address 13 (octal)execR_RA14, // RA14, // Read register at address 14 (octal)execR_RBK, // RBK, // Read BNKexecR_NOPULSE, // WA0, // Write register at address 0 (A)execR_NOPULSE, // WA1, // Write register at address 1 (Q)execR_NOPULSE, // WA2, // Write register at address 2 (Z)execR_NOPULSE, // WA3, // Write register at address 3 (LP)execR_NOPULSE, // WA10, // Write register at address 10 (octal)execR_NOPULSE, // WA11, // Write register at address 11 (octal)execR_NOPULSE, // WA12, // Write register at address 12 (octal)execR_NOPULSE, // WA13, // Write register at address 13 (octal)execR_NOPULSE, // WA14, // Write register at address 14 (octal)execR_NOPULSE, // WBK, // Write BNKexecR_NOPULSE, // WGn, // Write G (normal gates)**execR_NOPULSE, // W20, // Write into CYRexecR_NOPULSE, // W21, // Write into SRexecR_NOPULSE, // W22, // Write into CYLexecR_NOPULSE, // W23 // Write into SL

execR_NOPULSE, // GENRST,// General Reset**execR_NOPULSE, // CLINH, // Clear INHINT**execR_NOPULSE, // CLINH1,// Clear INHINT1**execR_NOPULSE, // CLSTA, // Clear state counter A (STA)**execR_NOPULSE, // CLSTB, // Clear state counter B (STB)**execR_NOPULSE, // CLISQ, // Clear SNI**execR_NOPULSE, // CLRP, // Clear RPCELL**execR_NOPULSE, // INH, // Set INHINT**execR_NOPULSE, // RPT, // Read RUPT opcode **execR_SBWG, // SBWG, // Write G from memoryexecR_NOPULSE, // SETSTB,// Set the ST1 bit of STBexecR_WE, // WE, // Write E-MEM from GexecR_NOPULSE, // WPCTR, // Write PCTR (latch priority counter sequence)**execR_NOPULSE, // WSQ, // Write SQexecR_NOPULSE, // WSTB, // Write stage counter B (STB)**execR_NOPULSE, // R2000, // Read 2000 **

}; // 99

void CLK::doexecR(int pulse) { execR[pulse](); }

EXECTYPE execR_ALU[] ={

execR_NOPULSE, // NO_PULSE,execR_NOPULSE, // CI, // Carry inexecR_NOPULSE, // CLG, // Clear G

Page 362: Apollo Guidance Computer AGC

execR_NOPULSE, // CLCTR, // Clear loop counter**execR_NOPULSE, // CTR, // Loop counterexecR_NOPULSE, // GP, // Generate ParityexecR_NOPULSE, // KRPT, // Knock down Rupt priorityexecR_NOPULSE, // NISQ, // New instruction to the SQ registerexecR_NOPULSE, // RA, // Read AexecR_ALU_RB, // RB, // Read BexecR_NOPULSE, // RB14, // Read bit 14execR_ALU_RC, // RC, // Read CexecR_NOPULSE, // RG, // Read GexecR_NOPULSE, // RLP, // Read LPexecR_NOPULSE, // RP2, // Read parity 2execR_NOPULSE, // RQ, // Read QexecR_NOPULSE, // RRPA, // Read RUPT addressexecR_NOPULSE, // RSB, // Read sign bitexecR_NOPULSE, // RSCT, // Read selected counter addressexecR_ALU_RU, // RU, // Read sumexecR_NOPULSE, // RZ, // Read ZexecR_NOPULSE, // R1, // Read 1execR_NOPULSE, // R1C, // Read 1 complimentedexecR_NOPULSE, // R2, // Read 2execR_NOPULSE, // R22, // Read 22execR_NOPULSE, // R24, // Read 24execR_NOPULSE, // ST1, // Stage 1execR_NOPULSE, // ST2, // Stage 2execR_NOPULSE, // TMZ, // Test for minus zeroexecR_NOPULSE, // TOV, // Test for overflowexecR_NOPULSE, // TP, // Test parityexecR_NOPULSE, // TRSM, // Test for resumeexecR_NOPULSE, // TSGN, // Test signexecR_NOPULSE, // TSGN2, // Test sign 2execR_NOPULSE, // WA, // Write AexecR_NOPULSE, // WALP, // Write A and LPexecR_NOPULSE, // WB, // Write BexecR_NOPULSE, // WGx, // Write G (do not reset)execR_NOPULSE, // WLP, // Write LPexecR_NOPULSE, // WOVC, // Write overflow counterexecR_NOPULSE, // WOVI, // Write overflow RUPT inhibitexecR_NOPULSE, // WOVR, // Write overflowexecR_NOPULSE, // WP, // Write PexecR_NOPULSE, // WPx, // Write P (do not reset)execR_NOPULSE, // WP2, // Write P2execR_NOPULSE, // WQ, // Write QexecR_NOPULSE, // WS, // Write SexecR_NOPULSE, // WX, // Write XexecR_NOPULSE, // WY, // Write YexecR_NOPULSE, // WYx, // Write Y (do not reset)execR_NOPULSE, // WZ, // Write Z

execR_NOPULSE, // RSC, // Read special and centralexecR_NOPULSE, // WSC, // Write special and centralexecR_NOPULSE, // WG, // Write G

execR_NOPULSE, // SDV1, // Subsequence DV1 is activeexecR_NOPULSE, // SMP1, // Subsequence MP1 is activeexecR_NOPULSE, // SRSM3, // Subsequence RSM3 is active

execR_NOPULSE, // RA0, // Read register at address 0 (A)execR_NOPULSE, // RA1, // Read register at address 1 (Q)execR_NOPULSE, // RA2, // Read register at address 2 (Z)execR_NOPULSE, // RA3, // Read register at address 3 (LP)execR_NOPULSE, // RA4, // Read register at address 4execR_NOPULSE, // RA5, // Read register at address 5execR_NOPULSE, // RA6, // Read register at address 6execR_NOPULSE, // RA7, // Read register at address 7execR_NOPULSE, // RA10, // Read register at address 10 (octal)execR_NOPULSE, // RA11, // Read register at address 11 (octal)execR_NOPULSE, // RA12, // Read register at address 12 (octal)execR_NOPULSE, // RA13, // Read register at address 13 (octal)execR_NOPULSE, // RA14, // Read register at address 14 (octal)execR_NOPULSE, // RBK, // Read BNKexecR_NOPULSE, // WA0, // Write register at address 0 (A)execR_NOPULSE, // WA1, // Write register at address 1 (Q)execR_NOPULSE, // WA2, // Write register at address 2 (Z)execR_NOPULSE, // WA3, // Write register at address 3 (LP)execR_NOPULSE, // WA10, // Write register at address 10 (octal)

Page 363: Apollo Guidance Computer AGC

execR_NOPULSE, // WA11, // Write register at address 11 (octal)execR_NOPULSE, // WA12, // Write register at address 12 (octal)execR_NOPULSE, // WA13, // Write register at address 13 (octal)execR_NOPULSE, // WA14, // Write register at address 14 (octal)execR_NOPULSE, // WBK, // Write BNKexecR_NOPULSE, // WGn, // Write G (normal gates)**execR_NOPULSE, // W20, // Write into CYRexecR_NOPULSE, // W21, // Write into SRexecR_NOPULSE, // W22, // Write into CYLexecR_NOPULSE, // W23 // Write into SL

execR_NOPULSE, // GENRST,// General Reset**execR_NOPULSE, // CLINH, // Clear INHINT**execR_NOPULSE, // CLINH1,// Clear INHINT1**execR_NOPULSE, // CLSTA, // Clear state counter A (STA)**execR_NOPULSE, // CLSTB, // Clear state counter B (STB)**execR_NOPULSE, // CLISQ, // Clear SNI**execR_NOPULSE, // CLRP, // Clear RPCELL**execR_NOPULSE, // INH, // Set INHINT**execR_NOPULSE, // RPT, // Read RUPT opcode **execR_NOPULSE, // SBWG, // Write G from memoryexecR_NOPULSE, // SETSTB,// Set the ST1 bit of STBexecR_NOPULSE, // WE, // Write E-MEM from GexecR_NOPULSE, // WPCTR, // Write PCTR (latch priority counter sequence)**execR_NOPULSE, // WSQ, // Write SQexecR_NOPULSE, // WSTB, // Write stage counter B (STB)**execR_NOPULSE, // R2000, // Read 2000 **

};

void CLK::doexecR_ALU(int pulse) { execR_ALU[pulse](); }

EXECTYPE execR_ALU_OR[] ={

execR_NOPULSE, // NO_PULSE,execR_NOPULSE, // CI, // Carry inexecR_NOPULSE, // CLG, // Clear GexecR_NOPULSE, // CLCTR, // Clear loop counter**execR_NOPULSE, // CTR, // Loop counterexecR_NOPULSE, // GP, // Generate ParityexecR_NOPULSE, // KRPT, // Knock down Rupt priorityexecR_NOPULSE, // NISQ, // New instruction to the SQ registerexecR_NOPULSE, // RA, // Read AexecR_NOPULSE, // RB, // Read BexecR_ALU_OR_RB14, // RB14, // Read bit 14execR_NOPULSE, // RC, // Read CexecR_NOPULSE, // RG, // Read GexecR_NOPULSE, // RLP, // Read LPexecR_NOPULSE, // RP2, // Read parity 2execR_NOPULSE, // RQ, // Read QexecR_NOPULSE, // RRPA, // Read RUPT addressexecR_ALU_OR_RSB, // RSB, // Read sign bitexecR_NOPULSE, // RSCT, // Read selected counter addressexecR_NOPULSE, // RU, // Read sumexecR_NOPULSE, // RZ, // Read ZexecR_ALU_OR_R1, // R1, // Read 1execR_ALU_OR_R1C, // R1C, // Read 1 complimentedexecR_ALU_OR_R2, // R2, // Read 2execR_ALU_OR_R22, // R22, // Read 22execR_ALU_OR_R24, // R24, // Read 24execR_NOPULSE, // ST1, // Stage 1execR_NOPULSE, // ST2, // Stage 2execR_NOPULSE, // TMZ, // Test for minus zeroexecR_NOPULSE, // TOV, // Test for overflowexecR_NOPULSE, // TP, // Test parityexecR_NOPULSE, // TRSM, // Test for resumeexecR_NOPULSE, // TSGN, // Test signexecR_NOPULSE, // TSGN2, // Test sign 2execR_NOPULSE, // WA, // Write AexecR_NOPULSE, // WALP, // Write A and LPexecR_NOPULSE, // WB, // Write BexecR_NOPULSE, // WGx, // Write G (do not reset)execR_NOPULSE, // WLP, // Write LP

Page 364: Apollo Guidance Computer AGC

execR_NOPULSE, // WOVC, // Write overflow counterexecR_NOPULSE, // WOVI, // Write overflow RUPT inhibitexecR_NOPULSE, // WOVR, // Write overflowexecR_NOPULSE, // WP, // Write PexecR_NOPULSE, // WPx, // Write P (do not reset)execR_NOPULSE, // WP2, // Write P2execR_NOPULSE, // WQ, // Write QexecR_NOPULSE, // WS, // Write SexecR_NOPULSE, // WX, // Write XexecR_NOPULSE, // WY, // Write YexecR_NOPULSE, // WYx, // Write Y (do not reset)execR_NOPULSE, // WZ, // Write Z

execR_NOPULSE, // RSC, // Read special and centralexecR_NOPULSE, // WSC, // Write special and centralexecR_NOPULSE, // WG, // Write G

execR_NOPULSE, // SDV1, // Subsequence DV1 is activeexecR_NOPULSE, // SMP1, // Subsequence MP1 is activeexecR_NOPULSE, // SRSM3, // Subsequence RSM3 is active

execR_NOPULSE, // RA0, // Read register at address 0 (A)execR_NOPULSE, // RA1, // Read register at address 1 (Q)execR_NOPULSE, // RA2, // Read register at address 2 (Z)execR_NOPULSE, // RA3, // Read register at address 3 (LP)execR_NOPULSE, // RA4, // Read register at address 4execR_NOPULSE, // RA5, // Read register at address 5execR_NOPULSE, // RA6, // Read register at address 6execR_NOPULSE, // RA7, // Read register at address 7execR_NOPULSE, // RA10, // Read register at address 10 (octal)execR_NOPULSE, // RA11, // Read register at address 11 (octal)execR_NOPULSE, // RA12, // Read register at address 12 (octal)execR_NOPULSE, // RA13, // Read register at address 13 (octal)execR_NOPULSE, // RA14, // Read register at address 14 (octal)execR_NOPULSE, // RBK, // Read BNKexecR_NOPULSE, // WA0, // Write register at address 0 (A)execR_NOPULSE, // WA1, // Write register at address 1 (Q)execR_NOPULSE, // WA2, // Write register at address 2 (Z)execR_NOPULSE, // WA3, // Write register at address 3 (LP)execR_NOPULSE, // WA10, // Write register at address 10 (octal)execR_NOPULSE, // WA11, // Write register at address 11 (octal)execR_NOPULSE, // WA12, // Write register at address 12 (octal)execR_NOPULSE, // WA13, // Write register at address 13 (octal)execR_NOPULSE, // WA14, // Write register at address 14 (octal)execR_NOPULSE, // WBK, // Write BNKexecR_NOPULSE, // WGn, // Write G (normal gates)**execR_NOPULSE, // W20, // Write into CYRexecR_NOPULSE, // W21, // Write into SRexecR_NOPULSE, // W22, // Write into CYLexecR_NOPULSE, // W23 // Write into SL

execR_NOPULSE, // GENRST,// General Reset**execR_NOPULSE, // CLINH, // Clear INHINT**execR_NOPULSE, // CLINH1,// Clear INHINT1**execR_NOPULSE, // CLSTA, // Clear state counter A (STA)**execR_NOPULSE, // CLSTB, // Clear state counter B (STB)**execR_NOPULSE, // CLISQ, // Clear SNI**execR_NOPULSE, // CLRP, // Clear RPCELL**execR_NOPULSE, // INH, // Set INHINT**execR_NOPULSE, // RPT, // Read RUPT opcode **execR_NOPULSE, // SBWG, // Write G from memoryexecR_NOPULSE, // SETSTB,// Set the ST1 bit of STBexecR_NOPULSE, // WE, // Write E-MEM from GexecR_NOPULSE, // WPCTR, // Write PCTR (latch priority counter sequence)**execR_NOPULSE, // WSQ, // Write SQexecR_NOPULSE, // WSTB, // Write stage counter B (STB)**execR_ALU_OR_R2000, // R2000, // Read 2000 **

};

void CLK::doexecR_ALU_OR(int pulse) { execR_ALU_OR[pulse](); }

Page 365: Apollo Guidance Computer AGC

void execW_NOPULSE() { }void execW_CI() { ALU::execWP_CI(); }void execW_CLG() { PAR::execWP_CLG(); }void execW_CLINH() { INT::execWP_CLINH(); }void execW_CLINH1() { INT::execWP_CLINH1(); }void execW_CLISQ() { SEQ::execWP_CLISQ(); }void execW_CLCTR() { SEQ::execWP_CLCTR(); }void execW_CLRP() { INT::execWP_CLRP(); }void execW_CLSTA() { SEQ::execWP_CLSTA(); }void execW_CLSTB() { SEQ::execWP_CLSTB(); }void execW_CTR() { SEQ::execWP_CTR(); }

void execW_GENRST() { SEQ::execWP_GENRST(); MBF::execWP_GENRST(); CRG::execWP_GENRST(); PAR::execWP_GENRST(); ALU::execWP_GENRST(); CTR::execWP_GENRST(); INT::execWP_GENRST(); OUT::execWP_GENRST(); }

void execW_GP() { PAR::execWP_GP(); }void execW_INH() { INT::execWP_INH(); }void execW_KRPT() { INT::execWP_KRPT(); }void execW_NISQ() { SEQ::execWP_NISQ(); }void execW_RPT() { INT::execWP_RPT(); }void execW_RP2() { PAR::execWP_RP2(); }void execW_SBWG() { MBF::execWP_SBWG(); PAR::execWP_SBWG(); }void execW_SETSTB() { SEQ::execWP_SETSTB(); }void execW_ST1() { SEQ::execWP_ST1(); }void execW_ST2() { SEQ::execWP_ST2(); }void execW_TMZ() { SEQ::execWP_TMZ(); }void execW_TOV() { SEQ::execWP_TOV(); }void execW_TP() { PAR::execWP_TP(); }void execW_TRSM() { SEQ::execWP_TRSM(); }void execW_TSGN() { SEQ::execWP_TSGN(); }void execW_TSGN2() { SEQ::execWP_TSGN2(); }void execW_WA0() { CRG::execWP_WA0(); }void execW_WA1() { CRG::execWP_WA1(); }void execW_WA2() { CRG::execWP_WA2(); }void execW_WA3() { CRG::execWP_WA3(); }void execW_WA10() { OUT::execWP_WA10(); }void execW_WA11() { OUT::execWP_WA11(); }void execW_WA12() { OUT::execWP_WA12(); }void execW_WA13() { OUT::execWP_WA13(); }void execW_WA14() { OUT::execWP_WA14(); }void execW_WA() { CRG::execWP_WA(); }void execW_WALP() { CRG::execWP_WALP(); }void execW_WB() { ALU::execWP_WB(); }void execW_WBK() { ADR::execWP_WBK(); }void execW_WE() { MEM::execWP_WE(); }void execW_WGn() { MBF::execWP_WGn(); }void execW_WGx() { MBF::execWP_WGx(); PAR::execWP_WGx(); }void execW_WLP() { CRG::execWP_WLP(); }void execW_WOVC() { CTR::execWP_WOVC(); }void execW_WOVI() { INT::execWP_WOVI(); }void execW_WOVR() { CTR::execWP_WOVR(); }void execW_WP() { PAR::execWP_WP(); }void execW_WPx() { PAR::execWP_WPx(); }void execW_WP2() { PAR::execWP_WP2(); }void execW_WPCTR() { CTR::execWP_WPCTR(); }void execW_WQ() { CRG::execWP_WQ(); }void execW_WS() { ADR::execWP_WS(); }void execW_WSQ() { SEQ::execWP_WSQ(); }void execW_WSTB() { SEQ::execWP_WSTB(); }void execW_WX() { ALU::execWP_WX(); }void execW_WY() { ALU::execWP_WY(); }void execW_WYx() { ALU::execWP_WYx(); }void execW_WZ() { CRG::execWP_WZ(); }void execW_W20() { MBF::execWP_W20(); }void execW_W21() { MBF::execWP_W21(); }void execW_W22() { MBF::execWP_W22(); }void execW_W23() { MBF::execWP_W23(); }

Page 366: Apollo Guidance Computer AGC

EXECTYPE execW[] ={

execW_NOPULSE, // NO_PULSE,execW_CI, // CI, // Carry inexecW_CLG, // CLG, // Clear GexecW_CLCTR, // CLCTR, // Clear loop counter**execW_CTR, // CTR, // Loop counterexecW_GP, // GP, // Generate ParityexecW_KRPT, // KRPT, // Knock down Rupt priorityexecW_NISQ, // NISQ, // New instruction to the SQ registerexecW_NOPULSE, // RA, // Read AexecW_NOPULSE, // RB, // Read BexecW_NOPULSE, // RB14, // Read bit 14execW_NOPULSE, // RC, // Read CexecW_NOPULSE, // RG, // Read GexecW_NOPULSE, // RLP, // Read LPexecW_RP2, // RP2, // Read parity 2execW_NOPULSE, // RQ, // Read QexecW_NOPULSE, // RRPA, // Read RUPT addressexecW_NOPULSE, // RSB, // Read sign bitexecW_NOPULSE, // RSCT, // Read selected counter addressexecW_NOPULSE, // RU, // Read sumexecW_NOPULSE, // RZ, // Read ZexecW_NOPULSE, // R1, // Read 1execW_NOPULSE, // R1C, // Read 1 complimentedexecW_NOPULSE, // R2, // Read 2execW_NOPULSE, // R22, // Read 22execW_NOPULSE, // R24, // Read 24execW_ST1, // ST1, // Stage 1execW_ST2, // ST2, // Stage 2execW_TMZ, // TMZ, // Test for minus zeroexecW_TOV, // TOV, // Test for overflowexecW_TP, // TP, // Test parityexecW_TRSM, // TRSM, // Test for resumeexecW_TSGN, // TSGN, // Test signexecW_TSGN2, // TSGN2, // Test sign 2execW_WA, // WA, // Write AexecW_WALP, // WALP, // Write A and LPexecW_WB, // WB, // Write BexecW_WGx, // WGx, // Write G (do not reset)execW_WLP, // WLP, // Write LPexecW_WOVC, // WOVC, // Write overflow counterexecW_WOVI, // WOVI, // Write overflow RUPT inhibitexecW_WOVR, // WOVR, // Write overflowexecW_WP, // WP, // Write PexecW_WPx, // WPx, // Write P (do not reset)execW_WP2, // WP2, // Write P2execW_WQ, // WQ, // Write QexecW_WS, // WS, // Write SexecW_WX, // WX, // Write XexecW_WY, // WY, // Write YexecW_WYx, // WYx, // Write Y (do not reset)execW_WZ, // WZ, // Write Z

execW_NOPULSE, // RSC, // Read special and centralexecW_NOPULSE, // WSC, // Write special and centralexecW_NOPULSE, // WG, // Write G

execR_NOPULSE, // SDV1, // Subsequence DV1 is activeexecR_NOPULSE, // SMP1, // Subsequence MP1 is activeexecR_NOPULSE, // SRSM3, // Subsequence RSM3 is active

execW_NOPULSE, // RA0, // Read register at address 0 (A)execW_NOPULSE, // RA1, // Read register at address 1 (Q)execW_NOPULSE, // RA2, // Read register at address 2 (Z)execW_NOPULSE, // RA3, // Read register at address 3 (LP)execW_NOPULSE, // RA4, // Read register at address 4execW_NOPULSE, // RA5, // Read register at address 5execW_NOPULSE, // RA6, // Read register at address 6execW_NOPULSE, // RA7, // Read register at address 7execW_NOPULSE, // RA10, // Read register at address 10 (octal)execW_NOPULSE, // RA11, // Read register at address 11 (octal)execW_NOPULSE, // RA12, // Read register at address 12 (octal)execW_NOPULSE, // RA13, // Read register at address 13 (octal)execW_NOPULSE, // RA14, // Read register at address 14 (octal)execW_NOPULSE, // RBK, // Read BNK

Page 367: Apollo Guidance Computer AGC

execW_WA0, // WA0, // Write register at address 0 (A)execW_WA1, // WA1, // Write register at address 1 (Q)execW_WA2, // WA2, // Write register at address 2 (Z)execW_WA3, // WA3, // Write register at address 3 (LP)execW_WA10, // WA10, // Write register at address 10 (octal)execW_WA11, // WA11, // Write register at address 11 (octal)execW_WA12, // WA12, // Write register at address 12 (octal)execW_WA13, // WA13, // Write register at address 13 (octal)execW_WA14, // WA14, // Write register at address 14 (octal)execW_WBK, // WBK, // Write BNKexecW_WGn, // WGn, // Write G (normal gates)**execW_W20, // W20, // Write into CYRexecW_W21, // W21, // Write into SRexecW_W22, // W22, // Write into CYLexecW_W23, // W23 // Write into SL

execW_GENRST, // GENRST,// General Reset**execW_CLINH, // CLINH, // Clear INHINT**execW_CLINH1, // CLINH1,// Clear INHINT1**execW_CLSTA, // CLSTA, // Clear state counter A (STA)**execW_CLSTB, // CLSTB, // Clear state counter B (STB)**execW_CLISQ, // CLISQ, // Clear SNI**execW_CLRP, // CLRP, // Clear RPCELL**execW_INH, // INH, // Set INHINT**execW_RPT, // RPT, // Read RUPT opcode **execW_SBWG, // SBWG, // Write G from memoryexecW_SETSTB, // SETSTB,// Set the ST1 bit of STBexecW_WE, // WE, // Write E-MEM from GexecW_WPCTR, // WPCTR, // Write PCTR (latch priority counter sequence)**execW_WSQ, // WSQ, // Write SQexecW_WSTB, // WSTB, // Write stage counter B (STB)**execW_NOPULSE, // R2000, // Read 2000 **

}; // 99

void CLK::doexecW(int pulse) { execW[pulse](); }

Page 368: Apollo Guidance Computer AGC

CPM (CPM.h)

/**************************************************************************** * CPM - CONTROL PULSE MATRIX subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: CPM.h * * VERSIONS: * * DESCRIPTION: * Control Pulse Matrix for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef CPM_H#define CPM_H

#include "TPG.h"#include "SEQ.h"

class CPM{public:

static subseq instructionSubsequenceDecoder(int counter_subseq, int SQ_field, int STB_field);

static char* subseqString[];

static void controlPulseMatrix();

static void readEPROM(char* fileName, int* eprom);

static int EPROM1_8 [0x3fff+1];static int EPROM9_16 [0x3fff+1];static int EPROM17_24[0x3fff+1];static int EPROM25_32[0x3fff+1];static int EPROM33_40[0x3fff+1];static int EPROM41_48[0x3fff+1];static int EPROM49_56[0x3fff+1];

private:// Clear the list of currently asserted control pulses.

static void clearControlPulses();

// Assert the set of control pulses by adding them to the list of currently// active control signals.static void assert(cpType* pulse);

// Assert a control pulse by adding it to the list of currently asserted// control pulses.static void assert(cpType pulse);

static void get_CPM_A(int CPM_A_address);

static void getControlPulses_EPROM(int address);

static void checkEPROM(int inval, int lowbit);};

#endif

Page 369: Apollo Guidance Computer AGC

CPM (CPM.cpp)

/**************************************************************************** * CPM - CONTROL PULSE MATRIX subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: CPM.cpp * * NOTES: see header file. * ***************************************************************************** */#include "CPM.h"#include "SEQ.h"#include "MON.h"#include "CTR.h"#include "INT.h"#include "ADR.h"

#include <stdlib.h>

char* CPM::subseqString[] ={

"TC0","CCS0","CCS1","NDX0","NDX1","RSM3","XCH0","CS0","TS0","AD0","MASK0","MP0","MP1","MP3","DV0","DV1","SU0","RUPT1","RUPT3","STD2","PINC0","MINC0","SHINC0","NO_SEQ"

};

subseq CPM::instructionSubsequenceDecoder(int counter_subseq, int SQ_field, int STB_field)

{// Combinational logic decodes instruction and the stage count // to get the instruction subsequence.

static subseq decode[16][4] = {{ TC0, RUPT1, STD2, RUPT3 }, // 00{ CCS0, CCS1, NO_SEQ, NO_SEQ }, // 01{ NDX0, NDX1, NO_SEQ, RSM3 }, // 02{ XCH0, NO_SEQ, STD2, NO_SEQ }, // 03

{ NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ }, // 04{ NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ }, // 05{ NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ }, // 06{ NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ }, // 07{ NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ }, // 10

{ MP0, MP1, NO_SEQ, MP3 }, // 11{ DV0, DV1, STD2, NO_SEQ }, // 12{ SU0, NO_SEQ, STD2, NO_SEQ }, // 13

{ CS0, NO_SEQ, STD2, NO_SEQ }, // 14{ TS0, NO_SEQ, STD2, NO_SEQ }, // 15{ AD0, NO_SEQ, STD2, NO_SEQ }, // 16

Page 370: Apollo Guidance Computer AGC

{ MASK0, NO_SEQ, STD2, NO_SEQ } // 17

};

if(counter_subseq == PINCSEL)return PINC0;

else if(counter_subseq == MINCSEL)return MINC0;

elsereturn decode[SQ_field][STB_field];

}

void CPM::clearControlPulses(){

for(unsigned i=0; i<MAXPULSES; i++)SEQ::glbl_cp[i] = NO_PULSE;

}

void CPM::assert(cpType* pulse){

int j=0;for(unsigned i=0; i<MAXPULSES && j<MAX_IPULSES && pulse[j] != NO_PULSE; i++){

if(SEQ::glbl_cp[i] == NO_PULSE){

SEQ::glbl_cp[i] = pulse[j];j++;

}}

}

void CPM::assert(cpType pulse){

for(unsigned i=0; i<MAXPULSES; i++){

if(SEQ::glbl_cp[i] == NO_PULSE){

SEQ::glbl_cp[i] = pulse;break;

}}

}

int CPM::EPROM1_8 [];int CPM::EPROM9_16 [];int CPM::EPROM17_24[];int CPM::EPROM25_32[];int CPM::EPROM33_40[];int CPM::EPROM41_48[];int CPM::EPROM49_56[];

void CPM::readEPROM(char* fileName, int* eprom){

cout << "Reading EPROM: " << fileName << endl;

// Open the EPROM file.FILE* ifp = fopen(fileName, "r");if(!ifp){

perror("fopen failed for source file");exit(-1);

}

const int addressBytes = 3; // 24-bit address rangeconst int sumCheckBytes = 1;

char buf[4096];while(fgets(buf,4096,ifp)){

// process a recordif(buf[0] != 'S'){

cout << "Error reading start of EPROM record for: " << fileName << endl;exit(-1);

Page 371: Apollo Guidance Computer AGC

}

char tmp[256];

strncpy(tmp, &buf[2], 2); tmp[2] = '\0';int totalByteCount = strtol(tmp, 0, 16);int mySumCheck = totalByteCount & 0xff;

strncpy(tmp, &buf[4], 6); tmp[addressBytes*2] = '\0';int address = strtol(tmp, 0, 16);mySumCheck = (mySumCheck + ((address & 0xff0000) >> 16)) % 256;mySumCheck = (mySumCheck + ((address & 0x00ff00) >> 8)) % 256;mySumCheck = (mySumCheck + ((address & 0x0000ff) )) % 256;

//cout << hex << totalByteCount << ", " << address << dec << endl;

int dataBytes = totalByteCount - addressBytes - sumCheckBytes;int i = (addressBytes+2)*2; // index to 1st databyte char.for(int j=0; j<dataBytes; j++){

// get a data bytestrncpy(tmp, &buf[i], 2); tmp[2] = '\0';int data = strtol(tmp, 0, 16);//cout << hex << data << dec << endl;mySumCheck = (mySumCheck + data) % 256;

// The H/W AGC needs negative logic in the EPROMS (0=asserted)// but this simulator needs positive logic, so we bit flip the word.//eprom[address] = data;eprom[address] = ((~data) & 0xff);address++;

i+=2; // bump to next databyte char}strncpy(tmp, &buf[i], 2); tmp[2] = '\0';int sumCheck = strtol(tmp, 0, 16);

if(sumCheck != ((~mySumCheck) & 0xff)){

cout << "sumCheck failed; file: " << fileName << ", address: " << hex <<address

<< ", sumCheck: " << sumCheck << ", mySumCheck: " << mySumCheck <<dec << endl;

exit(-1);}

}fclose(ifp);

}

void CPM::checkEPROM(int inval, int lowbit){

for(int mask=0x1; inval && mask !=0x100; mask=mask<<1){

if(inval & mask)assert((cpType) lowbit);

lowbit++;}

}

// perform the CPM-A EPROM function using the EPROM filesvoid CPM::getControlPulses_EPROM(int address){

checkEPROM(EPROM1_8 [address], 1);checkEPROM(EPROM9_16 [address], 9);checkEPROM(EPROM17_24[address], 17);checkEPROM(EPROM25_32[address], 25);checkEPROM(EPROM33_40[address], 33);checkEPROM(EPROM41_48[address], 41);checkEPROM(EPROM49_56[address], 49);

}

void CPM::get_CPM_A(int address)

Page 372: Apollo Guidance Computer AGC

{// Use the EPROM tables to get the CPM-A control pulses documented// in R-393.

getControlPulses_EPROM(address);

// Now add some additional control pulses implied, but not documented// in R-393.if(SEQ::register_LOOPCTR.read() == 6){

assert(ST2); // STA <- 2assert(CLCTR); // CTR <- 0

}

//*****************************************************************// Now that the EPROM tables are used for CPM-A, this function is only // used to display the instruction subsequence in MON.

SEQ::glbl_subseq = CPM::instructionSubsequenceDecoder(CTR::getSubseq(), SEQ::register_SQ.read(), SEQ::register_STB.read());//*****************************************************************

// These were in CPM-C, where the rest of the control signal assertions// related to their use still are, but were moved here because WB and RB// are part of the R-393 sequence tables. Check CPM-C to see how these// assertions fit in (the former use is commented out there).

switch(TPG::register_SG.read()){

case PWRON:assert(WB); // TC GOPROG copied to B (see CPM-C for related assertions)break;

case TP12:if(SEQ::register_SNI.read() == 1){

if(!INT::IRQ()){

// Normal instructionassert(RB); // SQ <- B (see CPM-C for related assertions)

}}break;

default: ;}

}

void CPM::controlPulseMatrix(){

// Combination logic decodes time pulse, subsequence, branch register, and// "select next instruction" latch to get control pulses associated with // those states.

// Get rid of any old control pulses.clearControlPulses();

//*******************************************************************************// SUBSYSTEM A

int SB2_field = 0;int SB1_field = 0;

switch(CTR::getSubseq()){case PINCSEL:

SB2_field = 0;SB1_field = 1;break;

case MINCSEL:SB2_field = 1;SB1_field = 0;break;

default:

Page 373: Apollo Guidance Computer AGC

SB2_field = 0;SB1_field = 0;

};

int CPM_A_address = 0;CPM_A_address =

(SB2_field << 13) | (SB1_field << 12) |(SEQ::register_SQ.read() << 8) | (SEQ::register_STB.read() << 6) | (TPG::register_SG.read() << 2) | (SEQ::register_BR1.read() << 1) | SEQ::register_BR2.read();

// Construct address into CPM-A control pulse ROM:// Address bits (bit 1 is LSB)// 1: register BR2// 2: register BR1// 3-6: register SG (4)// 7,8: register STB (2)// 9-12: register SQ (4)// 13: STB_01 (from CTR: selects PINC, MINC, or none)// 14: STB_02 (from CTR: selects PINC, MINC, or none)

get_CPM_A(CPM_A_address);

//*******************************************************************************

//*******************************************************************************// SUBSYSTEM B

// NOTE: WG, RSC, WSC are generated by SUBSYSTEM A. Those 3 signals are only used// by SUBSYSTEM B; not anywhere else.

// CONSIDER MOVING TO ADR **********************8

if(SEQ::isAsserted(WG)){

switch(ADR::register_S.read()){case 020: assert(W20); break;case 021: assert(W21); break;case 022: assert(W22); break;case 023: assert(W23); break;default: if(ADR::GTR_17()) assert(WGn); // not a central register}

}if(SEQ::isAsserted(RSC)){

switch(ADR::register_S.read()){case 00: assert(RA0); break;case 01: assert(RA1); break;case 02: assert(RA2); break;case 03: assert(RA3); break;case 04: assert(RA4); break;case 05: assert(RA5); break;case 06: assert(RA6); break;case 07: assert(RA7); break;case 010: assert(RA10); break;case 011: assert(RA11); break;case 012: assert(RA12); break;case 013: assert(RA13); break;case 014: assert(RA14); break;case 015: assert(RBK); break;default: break; // 016, 017}

}if(SEQ::isAsserted(WSC))

switch(ADR::register_S.read()){case 00: assert(WA0); break;

Page 374: Apollo Guidance Computer AGC

case 01: assert(WA1); break;case 02: assert(WA2); break;case 03: assert(WA3); break;case 010: assert(WA10); break;case 011: assert(WA11); break;case 012: assert(WA12); break;case 013: assert(WA13); break;case 014: assert(WA14); break;case 015: assert(WBK); break;default: break; // 016, 017}

//*******************************************************************************

//*******************************************************************************// SUBSYSTEM C

switch(TPG::register_SG.read()){

case STBY:assert(GENRST);// inhibit all alarms// init "SQ" complex// clear branch registers// stage registers are not cleared; should they be?

// zeroes are already gated onto bus when no read pulses are asserted.// to zero synchronous-clocked registers, assert write pulses here.// Level-triggered registers are zeroed by GENRST anded with CLK2.break;

case PWRON:assert(R2000);//assert(WB); // TC GOPROG copied to B (implemented in CPM-A)break;

case TP1:// Moved this from TP12 to TP1 because CLISQ was getting cleared in the// hardware AGC before TPG was clocked; therefore TPG was not seeing the// SNI indication.

assert(CLISQ); // SNI <- 0

case TP5:// EMEM must be available in G register by TP6if( ADR::GTR_17() && // not a central register

!ADR::GTR_1777() && // not fixed memory!SEQ::isAsserted(SDV1) && // not a loop counter subseq!SEQ::isAsserted(SMP1))

{assert(SBWG);

}if( ADR::EQU_17() ) assert (INH); // INHINT (INDEX 017)if( ADR::EQU_16() ) assert (CLINH); // RELINT (INDEX 016)break;

case TP6:// FMEM must be available in G register by TP7if( ADR::GTR_1777() && // not eraseable

memory!SEQ::isAsserted(SDV1) && // not a loop counter subseq!SEQ::isAsserted(SMP1))

{assert(SBWG);

}break;

case TP11:// G register written to memory beginning at TP11; Memory updates are in// G by TP10 for all normal and extracode instructions, but the PINC, MINC,

Page 375: Apollo Guidance Computer AGC

// and SHINC sequences write to G in TP10 because they need to update the// parity bit.if( ADR::GTR_17() && // not a central register

!ADR::GTR_1777() && // not fixed memory!SEQ::isAsserted(SDV1) && // not a loop counter subseq!SEQ::isAsserted(SMP1))

{assert(WE);

}// Additional interrupts are inhibited during servicing of an interrupt;// Remove the inhibition when RESUME is executed (INDEX 025)if(SEQ::isAsserted(SRSM3)) assert(CLRP);break;

case TP12:// DISABLE INPUT CHANGE TO PRIORITY COUNTER (reenable after TP1)// Check the priority counters; service any waiting inputs on the next// memory cycle.assert(WPCTR);if(SEQ::register_SNI.read() == 1) // if SNI is set, get next instruction{

if(INT::IRQ()) // if interrupt requested (see CPM-A for similar assertion){

// Interrupt: SQ <- 0 (the default RW bus state)assert(RPT); // latch interrupt vectorassert(SETSTB); // STB <- 1

}else{

// Normal instruction//assert(RB); // SQ <- B (implemented in CPM-A)assert(CLSTB); // STB <- 0

}assert(WSQ);assert(CLSTA); // STA <- 0

// Remove inhibition of interrupts (if they were) AFTER the nextinstruction

assert(CLINH1); // INHINT1 <- 0}else if(CTR::getSubseq() == NOPSEL) // if previous sequence was not a counter{

// get next sequence for same instruction.assert(WSTB); // STB <- STAassert(CLSTA); // STA <- 0

}//assert(CLISQ); // SNI <- 0 (moved to TP1)

break;

default: ;}//*******************************************************************************

}

Page 376: Apollo Guidance Computer AGC

CRG (CRG.h)

/**************************************************************************** * CRG - ADDRESSABLE CENTRAL REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: CRG.h * * VERSIONS: * * DESCRIPTION: * Addressable Central Registers for the Block 1 Apollo Guidance Computer * prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef CRG_H#define CRG_H

#include "reg.h"

class regQ : public reg { public:

regQ() : reg(16, "%06o") { }};

class regZ : public reg { public:

regZ() : reg(16, "%06o") { }};

class regLP : public reg { public:

regLP() : reg(16, "%06o") { }};

class regA : public reg { public:

regA() : reg(16, "%06o") { }};

class CRG{public:

static void execWP_GENRST();

static void execRP_RQ();static void execRP_RA1();static void execWP_WQ();static void execWP_WA1();static void execRP_RZ();static void execRP_RA2();static void execWP_WZ();static void execWP_WA2();static void execRP_RLP();static void execRP_RA3();static void execRP_RA();static void execRP_RA0();static void execWP_WA();static void execWP_WA0();static void execWP_WALP();

Page 377: Apollo Guidance Computer AGC

static void execWP_WLP();static void execWP_WA3();

static regQ register_Q; // return addressstatic regZ register_Z; // program counterstatic regLP register_LP; // lower accumulatorstatic regA register_A; // accumulator

static unsigned conv_WALP_LP[];static unsigned conv_WALP_A[];static unsigned conv_WLP[];

};

#endif

Page 378: Apollo Guidance Computer AGC

CRG (CRG.cpp)

/**************************************************************************** * CRG - ADDRESSABLE CENTRAL REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: CRG.cpp * * NOTES: see header file. * ***************************************************************************** */#include "CRG.h"#include "SEQ.h"#include "BUS.h"

regQ CRG::register_Q; // return addressregZ CRG::register_Z; // program counterregLP CRG::register_LP; // lower accumulatorregA CRG::register_A; // accumulator

// BUS LINE ASSIGNMENTS// Specify the assignment of bus lines to the inputs of a register (for a 'write'// operation into a register). Each 'conv_' array specifies the inputs into a// single register. The index into the array corresponds to the bit position in// the register, where the first parameter (index=0) is bit 16 of the register (msb)// and the last parameter (index=15) is register bit 1 (lsb). The value of// the parameter identifies the bus line assigned to that register bit. 'BX'// means 'don't care'; i.e.: leave that register bit alone.

unsigned CRG::conv_WALP_LP[] ={ BX, BX, B1, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX };

unsigned CRG::conv_WALP_A[] ={ SG, SG, US, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2 };

unsigned CRG::conv_WLP[] ={ B1, B1, D0, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2 };

void CRG::execWP_GENRST(){

register_Q.write(0);register_Z.write(0);register_LP.write(0);register_A.write(0);

}

void CRG::execRP_RQ(){

BUS::glbl_READ_BUS = register_Q.read();}void CRG::execRP_RA1(){

BUS::glbl_READ_BUS = register_Q.read();}

void CRG::execWP_WQ(){

register_Q.write(BUS::glbl_WRITE_BUS);}

void CRG::execWP_WA1(){

register_Q.write(BUS::glbl_WRITE_BUS);

Page 379: Apollo Guidance Computer AGC

}

void CRG::execRP_RZ(){

BUS::glbl_READ_BUS = register_Z.read();}

void CRG::execRP_RA2(){

BUS::glbl_READ_BUS = register_Z.read();}

void CRG::execWP_WZ(){

register_Z.write(BUS::glbl_WRITE_BUS);}

void CRG::execWP_WA2(){

register_Z.write(BUS::glbl_WRITE_BUS);}

void CRG::execRP_RLP(){

BUS::glbl_READ_BUS = register_LP.read();}

void CRG::execRP_RA3(){

BUS::glbl_READ_BUS = register_LP.read();}

void CRG::execWP_WALP(){

register_LP.writeShift(BUS::glbl_WRITE_BUS, CRG::conv_WALP_LP);register_A.writeShift(BUS::glbl_WRITE_BUS, CRG::conv_WALP_A);

}void CRG::execWP_WLP(){

register_LP.writeShift(BUS::glbl_WRITE_BUS, CRG::conv_WLP);}

void CRG::execWP_WA3(){

register_LP.writeShift(BUS::glbl_WRITE_BUS, CRG::conv_WLP);}

void CRG::execRP_RA(){

BUS::glbl_READ_BUS = register_A.read();}

void CRG::execRP_RA0(){

BUS::glbl_READ_BUS = register_A.read();}

void CRG::execWP_WA(){

register_A.write(BUS::glbl_WRITE_BUS);}

void CRG::execWP_WA0(){

register_A.write(BUS::glbl_WRITE_BUS);

Page 380: Apollo Guidance Computer AGC

}

Page 381: Apollo Guidance Computer AGC

CTR (CTR.h)

/**************************************************************************** * CTR - INVOLUNTARY PRIORITY COUNTER subsystem * * AUTHOR: John Pultorak * DATE: 10/25/02 * FILE: CTR.h * * VERSIONS: * * DESCRIPTION: * Involuntary Counters for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef CTR_H#define CTR_H

#include "reg.h"

enum ctrNumber { // indexes for priority cellsOVCTR =0,

TIME2 =1, // Block II puts TIME2 firstTIME1 =2,TIME3 =3,TIME4 =4,

};

enum ctrAddr { // octal addresses of counters// Note: In Block 1, TIME1 preceeds TIME2. In Block II,// this is reversed: TIME2 preceeds TIME1. This reversal// was done so that the most significant time word occurs// at the lower address in the 2 word AGC clock. Therefore,// a common AGC software routine can be used to read the// time.

OVCTR_ADDR =0034,

TIME2_ADDR =0035, // Block II puts TIME2 firstTIME1_ADDR =0036,TIME3_ADDR =0037,TIME4_ADDR =0040,

SPARE1_ADDR =0041,

SPARE2_ADDR =0042,SPARE3_ADDR =0043

};

enum pCntrType {NOPSEL =0, // NO COUNTERPINCSEL =1, // PINCMINCSEL =2 // MINC

};

class regUpCELL : public reg { public:

// Bit synchronize the counter inputs.regUpCELL() : reg(8, "%03o") { }

};

class regDnCELL : public reg { public:

Page 382: Apollo Guidance Computer AGC

// Bit synchronize the counter inputs.regDnCELL() : reg(8, "%03o") { }

};

class CTR{public:

static void execWP_GENRST();static void execWP_WPCTR();static void execRP_RSCT();static void execWP_WOVR();static void execWP_WOVC();

static unsigned getSubseq();

static unsigned pcUp[];static unsigned pcDn[];

static regUpCELL register_UpCELL; // latches the selected priority counter cell (0-7)static regDnCELL register_DnCELL; // latches the selected priority counter cell (0-7)

private:static void resetAllpc();

};

#endif

Page 383: Apollo Guidance Computer AGC

CTR (CTR.cpp)

/**************************************************************************** * CTR - INVOLUNTARY PRIORITY COUNTER subsystem * * AUTHOR: John Pultorak * DATE: 10/25/02 * FILE: CTR.cpp * * NOTES: see header file. * ***************************************************************************** */#include "CTR.h"#include "INT.h"#include "BUS.h"#include "SEQ.h"

regUpCELL CTR::register_UpCELL; // latches the selected priority counter cell (0-7 (decimal))regDnCELL CTR::register_DnCELL; // latches the selected priority counter cell (0-7 (decimal))

unsigned CTR::pcUp[8];unsigned CTR::pcDn[8];

// PRIORITY COUNTERS

// ****************************************************// The interrupt priorities are stored in RPCELL as 1-5, but// the priority counter priorities are stored as 0-7; this// inconsistency should be fixed, probably. Also, the method// of address determination for the priority counters needs work

void CTR::resetAllpc(){

for(int i=0; i<8; i++) { pcUp[i]=0; pcDn[i]=0; }}

// priority encoder; outputs 0-7; 0=highest priority (OVCTR), 1=TIME2, 2=TIME1, etcstatic bool newPriority = true; // a simulator performance optimization; not in the hardware AGCunsigned getPriority(){

// simulator optimization; don't recompute priority if the priority inputs haven'tchanged

static unsigned priority = 7; // default (lowest priority)if(!newPriority) return priority;

priority = 7; // default (lowest priority)for(int i=0; i<8; i++) {

if(CTR::register_UpCELL.readField(i+1,i+1) |CTR::register_DnCELL.readField(i+1,i+1))

{priority = i;break;

}}newPriority = false;return priority;

}

unsigned CTR::getSubseq(){

unsigned pc = getPriority();

unsigned upCell = CTR::register_UpCELL.readField(pc+1,pc+1);unsigned dnCell = CTR::register_DnCELL.readField(pc+1,pc+1);

Page 384: Apollo Guidance Computer AGC

if(upCell == 1 && dnCell == 0)return PINCSEL;

else if(upCell == 0 && dnCell == 1) return MINCSEL;

else return NOPSEL;

}

void CTR::execWP_GENRST(){

register_UpCELL.write(0);register_DnCELL.write(0);

resetAllpc();}

void CTR::execWP_WPCTR(){

// transfer cell data into up and down synch registers

for(int i=0; i<8; i++) {

register_UpCELL.writeField(i+1,i+1,pcUp[i]);register_DnCELL.writeField(i+1,i+1,pcDn[i]);

}newPriority=true; // a simulator performance optimization; not in hardware AGC

}

// Selected counter address is requested at TP1.// Counter address is latched at TP12

void CTR::execRP_RSCT(){

BUS::glbl_READ_BUS = 034 + getPriority();}

void CTR::execWP_WOVR(){

unsigned pc = getPriority();if(register_UpCELL.readField(pc+1,pc+1)){

pcUp[pc]=0;}if(register_DnCELL.readField(pc+1,pc+1)){

pcDn[pc]=0;}

// generate various actions in response to counter overflows:switch(BUS::testOverflow(BUS::glbl_WRITE_BUS)){

case POS_OVF: // positive overflowswitch(getPriority()) // get the counter{case TIME1: CTR::pcUp[TIME2]=1; break; // overflow from TIME1 increments

TIME2case TIME3: INT::rupt[T3RUPT]=1; break; // overflow from TIME3 triggers

T3RUPTcase TIME4: INT::rupt[DSRUPT]=1; break; // overflow from TIME4 triggers

DSRUPT}break;

case NEG_OVF: break; // no actions for negative counter overflow}

}

void CTR::execWP_WOVC(){

Page 385: Apollo Guidance Computer AGC

switch(BUS::testOverflow(BUS::glbl_WRITE_BUS)){

case POS_OVF: CTR::pcUp[OVCTR]=1; break; // incr OVCTR (034)case NEG_OVF: CTR::pcDn[OVCTR]=1; break; // decr OVCTR (034)

}

}

// register_PCELL: Overflow from the selected counter appears// on the bus when WOVR or WOVC is asserted;// it could be used to trigger an interrupt// or routed to increment another counter

Page 386: Apollo Guidance Computer AGC

DSP (DSP.h)

/**************************************************************************** * DSP - DSKY DISPLAY subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: DSP.h * * VERSIONS: * * DESCRIPTION: * DSKY Display for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef DSP_H#define DSP_H

class DSP{public:

// DSKY display

// major mode displaystatic char MD1;static char MD2;

// verb displaystatic char VD1;static char VD2;

// noun displaystatic char ND1;static char ND2;

// R1static char R1S;static char R1D1;static char R1D2;static char R1D3;static char R1D4;static char R1D5;

// R2static char R2S;static char R2D1;static char R2D2;static char R2D3;static char R2D4;static char R2D5;

// R3static char R3S;static char R3D1;static char R3D2;static char R3D3;static char R3D4;static char R3D5;

// These flags control the sign; if both bits are 0 or 1, there is no sign.// Otherwise, the sign is set by the selected bit.

static unsigned R1SP;static unsigned R1SM;static unsigned R2SP;static unsigned R2SM;static unsigned R3SP;static unsigned R3SM;

Page 387: Apollo Guidance Computer AGC

// verb/noun flashstatic unsigned flash;

static void clearOut0();

static char signConv(unsigned p, unsigned m);

static char outConv(unsigned in);

static void decodeRelayWord(unsigned in);};

#endif

Page 388: Apollo Guidance Computer AGC

DSP (DSP.cpp)

/**************************************************************************** * DSP - DSKY DISPLAY subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: DSP.cpp * * NOTES: see header file. * ***************************************************************************** */#include "DSP.h"#include <string.h>#include <iostream.h>#include <stdio.h>

bool dskyChanged = false; // true when DSKY display changes

// major mode displaychar DSP::MD1=0;char DSP::MD2=0;

// verb displaychar DSP::VD1=0;char DSP::VD2=0;

// noun displaychar DSP::ND1=0;char DSP::ND2=0;

// R1char DSP::R1S=0;char DSP::R1D1=0;char DSP::R1D2=0;char DSP::R1D3=0;char DSP::R1D4=0;char DSP::R1D5=0;

// R2char DSP::R2S=0;char DSP::R2D1=0;char DSP::R2D2=0;char DSP::R2D3=0;char DSP::R2D4=0;char DSP::R2D5=0;

// R3char DSP::R3S=0;char DSP::R3D1=0;char DSP::R3D2=0;char DSP::R3D3=0;char DSP::R3D4=0;char DSP::R3D5=0;

// These flags control the sign; if both bits are 0 or 1, there is no sign.// Otherwise, the sign is set by the selected bit.

unsigned DSP::R1SP=0;unsigned DSP::R1SM=0;unsigned DSP::R2SP=0;unsigned DSP::R2SM=0;unsigned DSP::R3SP=0;unsigned DSP::R3SM=0;

// flag controls 1 Hz flash of verb and noun displayunsigned DSP::flash = 0; // 0=flash off, 1=flash on

void DSP::clearOut0(){

MD1 = MD2 = ' '; // major mode displayVD1 = VD2 = ' '; // verb display

Page 389: Apollo Guidance Computer AGC

ND1 = ND2 = ' '; // noun displayR1S = R1D1 = R1D2 = R1D3 = R1D4 = R1D5 = ' '; // R1R2S = R2D1 = R2D2 = R2D3 = R2D4 = R2D5 = ' '; // R2R3S = R3D1 = R3D2 = R3D3 = R3D4 = R3D5 = ' '; // R3

R1SP = R1SM = 0;R2SP = R2SM = 0;R3SP = R3SM = 0;

}

char DSP::signConv(unsigned p, unsigned m){

if(p && !m)return '+';

else if(m && !p)return '-';

elsereturn ' ';

}

char DSP::outConv(unsigned in){

switch(in){case 000: return ' ';case 025: return '0';case 003: return '1';case 031: return '2';case 033: return '3';case 017: return '4';case 036: return '5';case 034: return '6';case 023: return '7';case 035: return '8';case 037: return '9';}return ' '; // error

}

void DSP::decodeRelayWord(unsigned in){

unsigned charSelect = (in & 074000) >> 11; // get bits 15-12unsigned b11 = (in & 02000) >> 10; // get bit 11unsigned bHigh = (in & 01740) >> 5; // get bits 10-6unsigned bLow = in & 037;

//******************************#ifdef NOTDEF

char buf[80]; sprintf(buf, "bits15-12: %02o, Bit11: %01o, bits10-6: %02o, bits5-1: %02o",

charSelect, b11, bHigh, bLow);cout << buf << endl;

#endifdskyChanged = true;//******************************

switch(charSelect){case 013: MD1 = outConv(bHigh); MD2 = outConv(bLow); break;case 012: VD1 = outConv(bHigh); VD2 = outConv(bLow); flash = b11; break;case 011: ND1 = outConv(bHigh); ND2 = outConv(bLow); break;case 010: R1D1 = outConv(bLow); break;// UPACT not implemented

case 007: R1SP = b11; R1S = signConv(R1SP, R1SM);R1D2 = outConv(bHigh);R1D3 = outConv(bLow); break;

case 006: R1SM = b11; R1S = signConv(R1SP, R1SM);R1D4 = outConv(bHigh);R1D5 = outConv(bLow); break;

case 005: R2SP = b11; R2S = signConv(R2SP, R2SM);R2D1 = outConv(bHigh);R2D2 = outConv(bLow); break;

Page 390: Apollo Guidance Computer AGC

case 004: R2SM = b11; R2S = signConv(R2SP, R2SM);R2D3 = outConv(bHigh);R2D4 = outConv(bLow); break;

case 003: R2D5 = outConv(bHigh);R3D1 = outConv(bLow); break;

case 002: R3SP = b11; R3S = signConv(R3SP, R3SM);R3D2 = outConv(bHigh);R3D3 = outConv(bLow); break;

case 001: R3SM = b11; R3S = signConv(R3SP, R3SM);R3D4 = outConv(bHigh);R3D5 = outConv(bLow); break;

}}

Page 391: Apollo Guidance Computer AGC

INP (INP.h)

/**************************************************************************** * INP - INPUT REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: INP.h * * VERSIONS: * * DESCRIPTION: * Input Registers for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef INP_H#define INP_H

#include "reg.h"

class regIn0 : public reg { public:

regIn0() : reg(16, "%06o") { }};

class regIn1 : public reg { public:

regIn1() : reg(16, "%06o") { }};

class regIn2 : public reg { public:

regIn2() : reg(16, "%06o") { }};

class regIn3 : public reg { public:

regIn3() : reg(16, "%06o") { }};

class INP{public:

static void execRP_RA4();static void execRP_RA5();static void execRP_RA6();static void execRP_RA7();static regIn0 register_IN0; // input register 0static regIn1 register_IN1; // input register 1static regIn2 register_IN2; // input register 2static regIn3 register_IN3; // input register 3

};

#endif

Page 392: Apollo Guidance Computer AGC

INP (INP.cpp)

/**************************************************************************** * INP - INPUT REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: INP.cpp * * NOTES: see header file. * ***************************************************************************** */#include "INP.h"#include "SEQ.h"#include "KBD.h"#include "MON.h"#include "BUS.h"

regIn0 INP::register_IN0; // input register 0regIn1 INP::register_IN1; // input register 1regIn2 INP::register_IN2; // input register 2regIn3 INP::register_IN3; // input register 3

void INP::execRP_RA4(){

// Sample the state of the inputs at the moment the// read pulse is asserted. In the H/W implementation,// register 0 is a buffer, not a latch.

register_IN0.writeField(5,1,KBD::kbd);register_IN0.writeField(6,6,0); // actually should be keypressed stroberegister_IN0.writeField(14,14,MON::SA);register_IN0.clk();BUS::glbl_READ_BUS = register_IN0.read();

}

void INP::execRP_RA5(){

BUS::glbl_READ_BUS = register_IN1.read();}

void INP::execRP_RA6(){

BUS::glbl_READ_BUS = register_IN2.read();}

void INP::execRP_RA7(){

BUS::glbl_READ_BUS = register_IN3.read();}

Page 393: Apollo Guidance Computer AGC

INT (INT.h)

/**************************************************************************** * INT - PRIORITY INTERRUPT subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: INT.h * * VERSIONS: * * DESCRIPTION: * Priority Interrupts for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef INT_H#define INT_H

#include "reg.h"

enum ruptAddress {// Addresses for service routines of vectored interrupts

T3RUPT_ADDR =02004, // option 1: overflow of TIME 3ERRUPT_ADDR =02010, // option 2: error signalDSRUPT_ADDR =02014, // option 3: telemetry end pulse or TIME 4 overflowKEYRUPT_ADDR =02020, // option 4: activity from MARK, keyboard, or tape reader

};

enum ruptNumber {// Option number (selects rupt priority cell)// NOTE: the priority cells (rupt[]) are indexed 0-4, but stored in the // RPCELL register as 1-5; (0 in RPCELL means no interrupt)

T3RUPT =0, // option 1: overflow of TIME 3ERRUPT =1, // option 2: error signalDSRUPT =2, // option 3: telemetry end pulse or TIME 4 overflowKEYRUPT =3, // option 4: activity from MARK, keyboard, or tape reader

};

class regRPCELL : public reg { public:

regRPCELL() : reg(5, "%02o") { }};// also inhibits additional interrupts while an interrupt is being processed

class regINHINT1 : public reg { public:

regINHINT1() : reg(1, "%01o") { }};

class regINHINT : public reg { public:

regINHINT() : reg(1, "%01o") { }};

class INT{public:

friend class CLK;friend class MON;

static void execRP_RRPA();

Page 394: Apollo Guidance Computer AGC

static void execWP_GENRST();static void execWP_RPT();static void execWP_KRPT();static void execWP_CLRP();static void execWP_WOVI();static void execWP_CLINH1();static void execWP_INH();static void execWP_CLINH();

static bool IRQ(); // returns true if an interrupt is requested

static unsigned rupt[];

private:static void resetAllRupt();static unsigned getPriorityRupt();

static regRPCELL register_RPCELL; // latches the selected priority interrupt vector (1-5)static regINHINT1 register_INHINT1; // inhibits interrupts for 1 instruction (on WOVI)static regINHINT register_INHINT; // inhibits interrupts on INHINT, reenables on RELINT

};

#endif

Page 395: Apollo Guidance Computer AGC

INT (INT.cpp)

/**************************************************************************** * INT - PRIORITY INTERRUPT subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: INT.cpp * * NOTES: see header file. * ***************************************************************************** */#include "INT.h"#include "SEQ.h"#include "BUS.h"

regRPCELL INT::register_RPCELL; // latches the selected priority interrupt vector (1-5)regINHINT1 INT::register_INHINT1; // inhibits interrupts for 1 instruction (on WOVI)regINHINT INT::register_INHINT; // inhibits interrupts on INHINT, reenables on RELINT

// NOTE: the priority cells (rupt[]) are indexed 0-4, but stored in the // RPCELL register as 1-5; (0 in RPCELL means no interrupt)unsigned INT::rupt[5];

bool INT::IRQ(){

if( INT::getPriorityRupt() // if interruptrequested

&& INT::register_RPCELL.read() == 0 // and interrupt not currently beingserviced

&& INT::register_INHINT1.read() == 0 // and interrupt not inhibited for 1instruction

&& INT::register_INHINT.read() == 0) // and interrupts enabled (RELINT){

return true;}return false;

}

void INT::resetAllRupt(){

for(int i=0; i<5; i++) { rupt[i]=0; }}

// interrupt vector; outputs 1-5 (decimal) == vector; 0 == no interruptunsigned INT::getPriorityRupt(){

for(int i=0; i<5; i++) { if(rupt[i]) return i+1; }return 0;

}

void INT::execRP_RRPA(){

BUS::glbl_READ_BUS = 02000 + (register_RPCELL.read() << 2);}

// latches the selected priority interrupt vector (1-5)// also inhibits additional interrupts while an interrupt is being processed

void INT::execWP_GENRST(){

register_RPCELL.write(0);register_INHINT.write(1);resetAllRupt();

}

void INT::execWP_RPT(){

Page 396: Apollo Guidance Computer AGC

register_RPCELL.write(INT::getPriorityRupt());}

void INT::execWP_KRPT(){

INT::rupt[register_RPCELL.read()-1] = 0;}

void INT::execWP_CLRP(){

register_RPCELL.write(0);}

// INHINT1: inhibits interrupts for 1 instruction (on WOVI)

void INT::execWP_WOVI(){

if(BUS::testOverflow(BUS::glbl_WRITE_BUS) != NO_OVF) register_INHINT1.write(1);

}

void INT::execWP_CLINH1(){

register_INHINT1.write(0);}

// INHINT: inhibits interrupts on INHINT, reenables on RELINT

void INT::execWP_INH(){

register_INHINT.write(1);}

void INT::execWP_CLINH(){

register_INHINT.write(0);}

Page 397: Apollo Guidance Computer AGC

ISD (ISD.h)

/**************************************************************************** * ISD - INSTRUCTION SUBSEQUENCE DECODER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: ISD.h * * VERSIONS: * * DESCRIPTION: * Instruction Subsequence Decoder for the Block 1 Apollo Guidance Computer * prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef ISD_H#define ISD_H

#include "SEQ.h"#include "CTR.h"

// INSTRUCTION SUBSEQUENCE DECODER

#ifdef NOTDEFclass ISD{public:

static subseq instructionSubsequenceDecoder();

static char* ISD::subseqString[];};#endif

#endif

Page 398: Apollo Guidance Computer AGC

ISD (ISD.cpp)

/**************************************************************************** * ISD - INSTRUCTION SUBSEQUENCE DECODER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: ISD.cpp * * NOTES: see header file. * ***************************************************************************** */#include "ISD.h"

#ifdef NOTDEFchar* ISD::subseqString[] ={

"TC0","CCS0","CCS1","NDX0","NDX1","RSM3","XCH0","CS0","TS0","AD0","MASK0","MP0","MP1","MP3","DV0","DV1","SU0","RUPT1","RUPT3","STD2","PINC0","MINC0","SHINC0","NO_SEQ"

};

subseq ISD::instructionSubsequenceDecoder(){

// Combinational logic decodes instruction and the stage count // to get the instruction subsequence.

static subseq decode[16][4] = {{ TC0, RUPT1, STD2, RUPT3 }, // 00{ CCS0, CCS1, NO_SEQ, NO_SEQ }, // 01{ NDX0, NDX1, NO_SEQ, RSM3 }, // 02{ XCH0, NO_SEQ, STD2, NO_SEQ }, // 03

{ NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ }, // 04{ NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ }, // 05{ NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ }, // 06{ NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ }, // 07{ NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ }, // 10

{ MP0, MP1, NO_SEQ, MP3 }, // 11{ DV0, DV1, STD2, NO_SEQ }, // 12{ SU0, NO_SEQ, STD2, NO_SEQ }, // 13

{ CS0, NO_SEQ, STD2, NO_SEQ }, // 14{ TS0, NO_SEQ, STD2, NO_SEQ }, // 15{ AD0, NO_SEQ, STD2, NO_SEQ }, // 16{ MASK0, NO_SEQ, STD2, NO_SEQ } // 17

};

switch(CTR::getSubseq()){case PINCSEL: return PINC0;

Page 399: Apollo Guidance Computer AGC

case MINCSEL: return MINC0;default: return decode[SEQ::register_SQ.read()][SEQ::register_STB.read()];}

}

#endif

Page 400: Apollo Guidance Computer AGC

KBD (KBD.h)

/**************************************************************************** * KBD - DSKY KEYBOARD subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: KBD.h * * VERSIONS: * * DESCRIPTION: * DSKY Keyboard for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef KBD_H#define KBD_H

enum keyInType {// DSKY keyboard input codes: Taken from E-1574, Appendix 1// These codes enter the computer through bits 1-5 of IN0.// The MSB is in bit 5; LSB in bit 1. Key entry generates KEYRUPT.KEYIN_NONE =0, // no key depressed**KEYIN_0 =020,KEYIN_1 =001,KEYIN_2 =002,KEYIN_3 =003,KEYIN_4 =004,KEYIN_5 =005,KEYIN_6 =006,KEYIN_7 =007,KEYIN_8 =010,KEYIN_9 =011,KEYIN_VERB =021,KEYIN_ERROR_RESET =022,KEYIN_KEY_RELEASE =031,KEYIN_PLUS =032,KEYIN_MINUS =033,KEYIN_ENTER =034,KEYIN_CLEAR =036,KEYIN_NOUN =037,

};

class KBD{public:

static keyInType kbd; // latches the last key entry from the DSKYstatic void keypress(keyInType c);

};

#endif

Page 401: Apollo Guidance Computer AGC

KBD (KBD.cpp)

/**************************************************************************** * KBD - DSKY KEYBOARD subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: KBD.cpp * * NOTES: see header file. * ***************************************************************************** */#include "KBD.h"#include "INT.h"

// DSKY keyboardkeyInType KBD::kbd=KEYIN_NONE; // latches the last key entry from the DSKY

void KBD::keypress(keyInType c){

// latch the keycodekbd = c;

// generate KEYRUPT interruptINT::rupt[KEYRUPT] = 1;

}

Page 402: Apollo Guidance Computer AGC

MBF (MBF.h)

/**************************************************************************** * MBF - MEMORY BUFFER REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: MBF.h * * VERSIONS: * * DESCRIPTION: * Memory Buffer Register for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef MBF_H#define MBF_H

#include "reg.h"

class regG : public reg { public:

// all memory bits except bit 15 (parity)// bit 15 is not used, so ignore it.

regG() : reg(16, "%06o") { }};

class MBF{public:

static void execWP_GENRST();

static void execRP_RG();static void execRP_WE();

static void execWP_WGn();static void execWP_WGx();static void execWP_W20();static void execWP_W21();static void execWP_W22();static void execWP_W23();static void execWP_SBWG();

// Bit 15 (parity) is kept in a separate register in PAR// because it is independently loaded.

static regG register_G; // memory buffer register (except for bit 15)

static unsigned conv_RG[];static unsigned conv_WGn[];static unsigned conv_W20[];static unsigned conv_W21[];static unsigned conv_W22[];static unsigned conv_W23[];static unsigned conv_SBWG[];static unsigned conv_WE[];

};

#endif

Page 403: Apollo Guidance Computer AGC

MBF (MBF.cpp)

/**************************************************************************** * MBF - MEMORY BUFFER REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: MBF.cpp * * NOTES: see header file. * ***************************************************************************** */#include "MBF.h"#include "SEQ.h"#include "ADR.h"#include "BUS.h"#include "PAR.h"#include "MEM.h"

// The actual bit 15 of register_G is not used.regG MBF::register_G; // memory buffer register (except bit 15: parity)

unsigned MBF::conv_RG[] ={ SG, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1 };

unsigned MBF::conv_SBWG[] ={ SGM, BX, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1 };

unsigned MBF::conv_WE[] ={ BX, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1 };

unsigned MBF::conv_W20[] ={ B1, BX, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2 };

unsigned MBF::conv_W21[] ={ SG, BX, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2 };

unsigned MBF::conv_W22[] ={ B14, BX, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1, SG };

unsigned MBF::conv_W23[] ={ SG, BX, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1, SG };

void MBF::execWP_GENRST(){

register_G.write(0);}

void MBF::execRP_RG(){

if(ADR::GTR_17()){

BUS::glbl_READ_BUS = register_G.shiftData(0, register_G.read(), MBF::conv_RG); }

}

void MBF::execRP_WE(){

// Write G into memory; shift the sign to bit 15; parity is written from the // PAR subsystem

MEM::MEM_DATA_BUS = (register_G.shiftData(0, MBF::register_G.read(), MBF::conv_WE));}

Page 404: Apollo Guidance Computer AGC

void MBF::execWP_WGn(){

register_G.write(BUS::glbl_WRITE_BUS);}

void MBF::execWP_WGx(){

// This is only used in PINC, MINC, and SHINC. Does not clear G// register; writes (ORs) into G from RWBus and writes into parity// from 1-15 generator. The sequence calls CLG in a previous TP to// reset G to zero, so the OR operation can be safely eliminated// from my implementation of the design.

register_G.write(BUS::glbl_WRITE_BUS);}

void MBF::execWP_W20(){

register_G.writeShift(BUS::glbl_WRITE_BUS, MBF::conv_W20);}

void MBF::execWP_W21(){

register_G.writeShift(BUS::glbl_WRITE_BUS, MBF::conv_W21);}

void MBF::execWP_W22(){

register_G.writeShift(BUS::glbl_WRITE_BUS, MBF::conv_W22);}

void MBF::execWP_W23(){

register_G.writeShift(BUS::glbl_WRITE_BUS, MBF::conv_W23);}

void MBF::execWP_SBWG(){

register_G.writeShift(MEM::MEM_DATA_BUS, MBF::conv_SBWG);

}

Page 405: Apollo Guidance Computer AGC

MEM (MEM.h)

/**************************************************************************** * MEM - ERASEABLE/FIXED MEMORY subsystem * * AUTHOR: John Pultorak * DATE: 9/26/02 * FILE: MEM.h * * VERSIONS: * * DESCRIPTION: * Eraseable & Fixed Memory for the Block 1 Apollo Guidance Computer * prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef MEM_H#define MEM_H

#include "reg.h"

#define NUMFBANK 12 // number of 1024 word fixed memory banks

class regEMEM : public reg { public:

regEMEM() : reg(16, "%06o") { }regEMEM& operator= (const unsigned& r) { write(r); return *this; }

};

class regFMEM : public reg { public:

regFMEM() : reg(16, "%06o") { }regFMEM& operator= (const unsigned& r) { write(r); return *this; }

};

class MEM{public:

static void execWP_WE();static void execRP_SBWG();

static regEMEM register_EMEM[]; // erasable memorystatic regFMEM register_FMEM[]; // fixed memory

static unsigned MEM_DATA_BUS; // data lines: memory bits 15-1static unsigned MEM_PARITY_BUS; // parity line: memory bit 16

static unsigned readMemory();static void writeMemory(unsigned data);

// The following functions are used in the simulator,// but are implemented in the AGC design.

static unsigned readMemory(unsigned address);static void writeMemory(unsigned address, unsigned data);

};

#endif

Page 406: Apollo Guidance Computer AGC

MEM (MEM.cpp)

/**************************************************************************** * MEM - ERASEABLE/FIXED MEMORY subsystem * * AUTHOR: John Pultorak * DATE: 9/26/02 * FILE: MEM.cpp * * NOTES: see header file. * ***************************************************************************** */#include "MEM.h"#include "ADR.h"#include "stdlib.h"

regEMEM MEM::register_EMEM[1024]; // erasable memoryregFMEM MEM::register_FMEM[1024*(NUMFBANK+1)]; // fixed memory (lowest 1024 words ignored)

unsigned MEM::MEM_DATA_BUS = 0; // data lines: memory bits 15-1unsigned MEM::MEM_PARITY_BUS = 0; // parity line: memory bit 16

void MEM::execWP_WE(){

// Write into memory; parity bit in bit 16writeMemory( (MEM_PARITY_BUS << 15) | MEM_DATA_BUS );

}

void MEM::execRP_SBWG(){

MEM_DATA_BUS = readMemory() & 0077777; // everything except parityMEM_PARITY_BUS = (readMemory() & 0100000) >> 15; // parity bit only

}

unsigned MEM::readMemory(){

// Return memory value addressed by lower 10 bits of the S register (1K) and the// bank decoder (which selects the 1K bank)

unsigned lowAddress = ADR::register_S.readField(10,1);

if(ADR::bankDecoder() == 0)return MEM::register_EMEM[lowAddress].read();

unsigned highAddress = ADR::bankDecoder() << 10;return MEM::register_FMEM[highAddress | lowAddress].read();

}

void MEM::writeMemory(unsigned data){

// Write into erasable memory addressed by lower 10 bits of the S register (1K) // and the bank decoder (which selects the 1K bank)

unsigned lowAddress = ADR::register_S.readField(10,1);if(ADR::bankDecoder() == 0){

MEM::register_EMEM[lowAddress].write(data);MEM::register_EMEM[lowAddress].clk(); // not a synchronous FF, so execute

immediately *************}

}

unsigned MEM::readMemory(unsigned address){

// Address is 14 bits. This function is used by the simulator for examining// memory; it is not part of the AGC design.

unsigned lowAddress = address & 01777;unsigned bank = (address & 036000) >> 10;

if(bank == 0)return MEM::register_EMEM[lowAddress].read();

Page 407: Apollo Guidance Computer AGC

unsigned highAddress = bank << 10;return MEM::register_FMEM[highAddress | lowAddress].read();

}

void MEM::writeMemory(unsigned address, unsigned data){

// Address is 14 bits. This function is used by the simulator for depositing into// memory; it is not part of the AGC design. This function is also used to// initialize fixed memory.

//************************************************************// This function could also write the parity into memory//************************************************************unsigned lowAddress = address & 01777;unsigned bank = (address & 036000) >> 10;

if(bank == 0){

if(lowAddress > 1024) {

cout << "Error: Eraseable address=" << lowAddress << endl; exit(0);

}MEM::register_EMEM[lowAddress].write(data);MEM::register_EMEM[lowAddress].clk(); // execute immediately

}else{

unsigned highAddress = bank << 10;if((highAddress | lowAddress) >= 1024*(NUMFBANK+1)) {

cout << "Error: Fixed address=" << (highAddress | lowAddress) << endl; exit(0);

}

MEM::register_FMEM[highAddress | lowAddress].write(data);MEM::register_FMEM[highAddress | lowAddress].clk(); // execute immediately

}}

Page 408: Apollo Guidance Computer AGC

MON (MON.h)

/**************************************************************************** * MON - AGC MONITOR subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: MON.h * * VERSIONS: * * DESCRIPTION: * AGC Monitor for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef MON_H#define MON_H

class MON{public:

static void displayAGC();

static char* MON::clkTypestring[];

static unsigned PURST; // power up resetstatic unsigned RUN; // run/halt switchstatic unsigned STEP; // single step switchstatic unsigned INST; // instruction/sequence step select switchstatic unsigned FCLK; // clock mode (0=single (manual) clock, 1=continuous clock)

static unsigned SA; // "standby allowed" SW; // 0=NO (full power), 1=YES (low power)

static unsigned SCL_ENAB; // "scaler enabled" SW; 0=NO (scaler halted), 1=YES(scaler running)

};

#endif

Page 409: Apollo Guidance Computer AGC

MON (MON.cpp)

/**************************************************************************** * MON - AGC MONITOR subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: MON.cpp * * NOTES: see header file. * ***************************************************************************** */#include "MON.h"

#include "TPG.h"#include "MON.h"#include "SCL.h"#include "SEQ.h"#include "INP.h"#include "OUT.h"#include "BUS.h"#include "DSP.h"#include "ADR.h"#include "PAR.h"#include "MBF.h"#include "MEM.h"#include "CTR.h"#include "INT.h"#include "KBD.h"#include "CRG.h"#include "ALU.h"#include "CPM.h"#include "ISD.h"#include "CLK.h"

unsigned MON::PURST=1; // power up reset; initially high at startupunsigned MON::RUN=0; // run/halt switchunsigned MON::STEP=0; // single step switchunsigned MON::INST=1; // instruction/sequence step select switchunsigned MON::FCLK=0; // clock mode

unsigned MON::SA=0; // "standby allowed" SW; 0=NO (full power), 1=YES (low power)

unsigned MON::SCL_ENAB=1; // "scaler enabled" SW; 0=NO (scaler halted), 1=YES (scalerrunning)

void MON::displayAGC(){

char buf[100];cout << "AGC4 SIMULATOR 1.16 -------------------------------" << endl;sprintf(buf," TP: %-5s F17:%1d F13:%1d F10:%1d SCL:%06o",

TPG::tpTypestring[TPG::register_SG.read()], SCL::register_F17.read(), SCL::register_F13.read(), SCL::register_F10.read(),SCL::register_SCL.read());

cout << buf << endl;

sprintf(buf, " STA:%01o STB:%01o BR1:%01o BR2:%01o SNI:%01o CI:%01o LOOPCTR:%01o",

SEQ::register_STA.read(), SEQ::register_STB.read(), SEQ::register_BR1.read(), SEQ::register_BR2.read(),SEQ::register_SNI.read(), ALU::register_CI.read(), SEQ::register_LOOPCTR.read());

cout << buf << endl;

sprintf(buf, " RPCELL:%05o INH1:%01o INH:%01o UpCELL:%03o DnCELL:%03o SQ:%02o %-6s %-6s",

INT::register_RPCELL.read(), INT::register_INHINT1.read(),INT::register_INHINT.read(),

CTR::register_UpCELL.read(), CTR::register_DnCELL.read(),SEQ::register_SQ.read(), SEQ::instructionString[SEQ::register_SQ.read()], CPM::subseqString[SEQ::glbl_subseq]);

cout << buf << endl;

sprintf(buf, " CP:%s", SEQ::getControlPulses());cout << buf << endl;

Page 410: Apollo Guidance Computer AGC

// For the G register, bit 15 comes from register G15; the other bits (16, 14-1)come

// from register G.sprintf(buf, " S: %04o G:%06o P:%06o (r)RUN :%1d (p)PURST:%1d

(F2,F4)FCLK:%1d", ADR::register_S.read(), (MBF::register_G.read() & 0137777) | (PAR::register_G15.read() << 14), PAR::register_P.read(),MON::RUN, MON::PURST, MON::FCLK);

cout << buf << endl;

sprintf(buf, " RBU:%06o WBU:%06o P2:%01o (s)STEP:%1d", BUS::glbl_READ_BUS & 0177777, BUS::glbl_WRITE_BUS & 0177777,

PAR::register_P2.read(), MON::STEP);cout << buf << endl;

char parityAlm = ' ';if(PAR::register_PALM.read()) parityAlm = '*';

sprintf(buf, " B:%06o CADR:%06o (n)INST:%1d PALM:[%c]", ALU::register_B.read(), ADR::getEffectiveAddress(), MON::INST, parityAlm);

cout << buf << endl;

sprintf(buf, " X:%06o Y:%06o U:%06o (a)SA :%1d", ALU::register_X.read(), ALU::register_Y.read(), ALU::register_U.read(), MON::SA);

cout << buf << endl;

cout << endl;sprintf(buf, "00 A:%06o 15 BANK:%02o 36 TIME1:%06o 53 OPT Y:%06o",

CRG::register_A.read(), ADR::register_BNK.read(), MEM::readMemory(036),MEM::readMemory(053));

cout << buf << endl;sprintf(buf, "01 Q:%06o 16 RELINT:%6s 37 TIME3:%06o 54 TRKR X:%06o",

CRG::register_Q.read(),"", MEM::readMemory(037), MEM::readMemory(054));cout << buf << endl;sprintf(buf, "02 Z:%06o 17 INHINT:%6s 40 TIME4:%06o 55 TRKR Y:%06o",

CRG::register_Z.read(),"", MEM::readMemory(040), MEM::readMemory(055));cout << buf << endl;sprintf(buf, "03 LP:%06o 20 CYR:%06o 41 UPLINK:%06o 56 TRKR Z:%06o",

CRG::register_LP.read(), MEM::readMemory(020), MEM::readMemory(041),MEM::readMemory(056));

cout << buf << endl;

sprintf(buf, "04 IN0:%06o 21 SR:%06o 42 OUTCR1:%06o", INP::register_IN0.read(), MEM::readMemory(021), MEM::readMemory(042));

cout << buf << endl;

char progAlm = ' ';if(OUT::register_OUT1.read() & 0400) progAlm = '*';

char compFail = ' '; // also called 'check fail' and 'oper err'if(OUT::register_OUT1.read() & 0100) compFail = '*';

char keyRels = ' ';if(OUT::register_OUT1.read() & 020) keyRels = '*';

char upTl = ' ';if(OUT::register_OUT1.read() & 004) upTl = '*';

char comp = ' '; // also called comp actyif(OUT::register_OUT1.read() & 001) comp = '*';

sprintf(buf, "05 IN1:%06o 22 CYL:%06o 43 OUTCR2:%06o CF:[%c%c]:KR [%c]:PA", INP::register_IN1.read(), MEM::readMemory(022), MEM::readMemory(043),compFail, keyRels, progAlm);

cout << buf << endl;

sprintf(buf, "06 IN2:%06o 23 SL:%06o 44 PIPA X:%06o", INP::register_IN2.read(), MEM::readMemory(023), MEM::readMemory(044));

cout << buf << endl;

sprintf(buf, "07 IN3:%06o 24 ZRUPT:%06o 45 PIPA Y:%06o A:[%c%c] M:[%c%c]", INP::register_IN3.read(), MEM::readMemory(024), MEM::readMemory(045),

Page 411: Apollo Guidance Computer AGC

upTl, comp, DSP::MD1, DSP::MD2);

cout << buf << endl;char fc = ' '; if(DSP::flash) fc = '*';sprintf(buf, "10 OUT0: 25 BRUPT:%06o 46 PIPA Z:%06o V:[%c%c] N:[%c%c] %c",

MEM::readMemory(025), MEM::readMemory(046),DSP::VD1, DSP::VD2, DSP::ND1, DSP::ND2, fc);

cout << buf << endl;sprintf(buf, "11 OUT1:%06o 26 ARUPT:%06o 47 CDU X:%06o R1:[ %c%c%c%c%c%c ]",

OUT::register_OUT1.read(), MEM::readMemory(026), MEM::readMemory(047),DSP::R1S, DSP::R1D1, DSP::R1D2, DSP::R1D3, DSP::R1D4, DSP::R1D5);

cout << buf << endl;sprintf(buf, "12 OUT2:%06o 27 QRUPT:%06o 50 CDU Y:%06o R2:[ %c%c%c%c%c%c ]",

OUT::register_OUT2.read(), MEM::readMemory(027), MEM::readMemory(050),DSP::R2S, DSP::R2D1, DSP::R2D2, DSP::R2D3, DSP::R2D4, DSP::R2D5);

cout << buf << endl;sprintf(buf, "13 OUT3:%06o 34 OVCTR:%06o 51 CDU Z:%06o R3:[ %c%c%c%c%c%c ]",

OUT::register_OUT3.read(), MEM::readMemory(034), MEM::readMemory(051),DSP::R3S, DSP::R3D1, DSP::R3D2, DSP::R3D3, DSP::R3D4, DSP::R3D5);

cout << buf << endl;sprintf(buf, "14 OUT4:%06o 35 TIME2:%06o 52 OPT X:%06o",

OUT::register_OUT4.read(), MEM::readMemory(035), MEM::readMemory(052));cout << buf << endl;

}

Page 412: Apollo Guidance Computer AGC

OUT (OUT.h)

/**************************************************************************** * OUT - OUTPUT REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: OUT.h * * VERSIONS: * * DESCRIPTION: * Output Registers for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef OUT_H#define OUT_H

#include "reg.h"

class regOut1 : public reg { public: regOut1() : reg(16, "%06o") { }};

class regOut2 : public reg { public: regOut2() : reg(16, "%06o") { }

};

class regOut3 : public reg { public: regOut3() : reg(16, "%06o") { }};

class regOut4 : public reg { public: regOut4() : reg(16, "%06o") { }};

class OUT{public:

static void execWP_GENRST();static void execWP_WA10();static void execRP_RA11();static void execWP_WA11();static void execRP_RA12();static void execWP_WA12();static void execRP_RA13();static void execWP_WA13();static void execRP_RA14();static void execWP_WA14();

static regOut1 register_OUT1; // output register 1static regOut2 register_OUT2; // output register 2static regOut3 register_OUT3; // output register 3static regOut4 register_OUT4; // output register 4

};

#endif

Page 413: Apollo Guidance Computer AGC

OUT (OUT.cpp)

/**************************************************************************** * OUT - OUTPUT REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: OUT.cpp * * NOTES: see header file. * ***************************************************************************** */#include "OUT.h"#include "SEQ.h"#include "BUS.h"#include "DSP.h"#include "ADR.h"#include "PAR.h"#include <stdlib.h>

regOut1 OUT::register_OUT1; // output register 1regOut2 OUT::register_OUT2; // output register 2regOut3 OUT::register_OUT3; // output register 3regOut4 OUT::register_OUT4; // output register 4

// Writing to OUT0 loads the selected DSKY display register.

void OUT::execWP_GENRST(){

DSP::clearOut0();

register_OUT1.write(0);register_OUT2.write(0);

}

void OUT::execWP_WA10(){

DSP::decodeRelayWord(BUS::glbl_WRITE_BUS); }

void OUT::execRP_RA11(){

BUS::glbl_READ_BUS = register_OUT1.read();}

void OUT::execWP_WA11(){

register_OUT1.write(BUS::glbl_WRITE_BUS);}

void OUT::execRP_RA12(){

BUS::glbl_READ_BUS = register_OUT2.read();}

void OUT::execWP_WA12(){

register_OUT2.write(BUS::glbl_WRITE_BUS);}

Page 414: Apollo Guidance Computer AGC

void OUT::execRP_RA13(){

BUS::glbl_READ_BUS = register_OUT3.read();}

void OUT::execWP_WA13(){

register_OUT3.write(BUS::glbl_WRITE_BUS);}

void OUT::execRP_RA14(){

BUS::glbl_READ_BUS = register_OUT4.read();}

void OUT::execWP_WA14(){

register_OUT4.write(BUS::glbl_WRITE_BUS);}

Page 415: Apollo Guidance Computer AGC

PAR (PAR.h)

/**************************************************************************** * PAR - PARITY GENERATION AND TEST subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: PAR.h * * VERSIONS: * * DESCRIPTION: * Parity Generation and Test for the Block 1 Apollo Guidance Computer * prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef PAR_H#define PAR_H

#include "reg.h"

class regG15 : public reg { public:

// memory buffer register bit 15 (parity) onlyregG15() : reg(1, "%01o") { }

};

class regP : public reg { public: regP() : reg(16, "%06o") { }};

class regP2 : public reg { public:

regP2() : reg(1, "%01o") { }};

class regPALM : public reg { public:

// parity alarm FF (set on TP)regPALM() : reg(1, "%01o") { }

};

class PAR{public:

static void execRP_WE();

static void execWP_WP();static void execWP_WPx();static void execWP_WP2();static void execWP_RP2();static void execWP_GP();static void execWP_SBWG();static void execWP_WGx();static void execWP_CLG();

static void execWP_GENRST();

Page 416: Apollo Guidance Computer AGC

static void execWP_TP();

static void CLR_PALM(); // asynchronous clear for PARITY ALARM

// memory buffer register bit 15; the rest of the// memory buffer register is defined in MBF

static regG15 register_G15;

static regP2 register_P2;static regP register_P;

static regPALM register_PALM;

static unsigned gen1_15Parity(unsigned r);static unsigned genP_15Parity(unsigned r);

static unsigned conv_WP[];};

#endif

Page 417: Apollo Guidance Computer AGC

PAR (PAR.cpp)

/**************************************************************************** * PAR - PARITY GENERATION AND TEST subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: PAR.cpp * * NOTES: see header file. * ***************************************************************************** */#include "PAR.h"#include "SEQ.h"#include "BUS.h"#include "MBF.h"#include "ADR.h"#include "MEM.h"

regP PAR::register_P;regP2 PAR::register_P2;regG15 PAR::register_G15; // memory buffer register bit 15regPALM PAR::register_PALM; // PARITY ALARM FF

unsigned PAR::conv_WP[] ={

BX, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1 };

void PAR::execRP_WE(){

// Write parity into memory.MEM::MEM_PARITY_BUS = PAR::register_G15.read();

}

// IMPLEMENTATION NOTE: It has been empirically determined that the following// control signals are mutually exclusive (there is never more than one of these// generated at any time):// GP, WGX, RP2, SBWG, CLG

// NOTE: WP clears register_P before writing into it. Strictly speaking, WPx isn't// supposed to clear the register (should OR into the register), but in the counter// sequences where WPx is used, register_P is always cleared in the previous TP by// asserting WP with default zeroes on the write bus.

void PAR::execWP_WP(){

// set all bits except parity bitregister_P.writeShift(BUS::glbl_WRITE_BUS, PAR::conv_WP);

// now set parity bit; in the actual AGC, this is// a single operation.

if(SEQ::isAsserted(RG))register_P.writeField(16, 16, register_G15.read());

elseregister_P.writeField(16, 16, 0); // clear parity bit

}

void PAR::execWP_WPx(){

// set all bits except parity bitregister_P.writeShift(BUS::glbl_WRITE_BUS, PAR::conv_WP);

// now set parity bit; in the actual AGC, this is// a single operation.

if(SEQ::isAsserted(RG))register_P.writeField(16, 16, register_G15.read());

else

Page 418: Apollo Guidance Computer AGC

register_P.writeField(16, 16, 0); // clear parity bit}

void PAR::execWP_WP2(){

register_P2.write(gen1_15Parity(register_P.read()));}

void PAR::execWP_RP2(){

register_G15.write(register_P2.read());}

void PAR::execWP_GP(){

register_G15.write(gen1_15Parity(register_P.read()));}

void PAR::execWP_SBWG(){

register_G15.write(MEM::MEM_PARITY_BUS); // load memory bit 16 (parity) into G15}

void PAR::execWP_WGx(){

// This is only used in PINC, MINC, and SHINC. Does not clear G// register; writes (ORs) into G from RWBus and writes into parity// from 1-15 generator. All done in one operation, although I show// it in two steps here. The sequence calls CLG in a previous TP.

register_G15.write(PAR::gen1_15Parity(register_P.read()));}

void PAR::execWP_CLG(){

register_G15.write(0);}

void PAR::execWP_GENRST(){

register_PALM.write(0);}

void PAR::execWP_TP(){

if(ADR::GTR_27() && genP_15Parity(register_P.read())) register_PALM.write(genP_15Parity(register_P.read()));}

void PAR::CLR_PALM(){

// asynchronous clear for PARITY ALARM (from MON)register_PALM.clear();

}

unsigned PAR::gen1_15Parity(unsigned r){

//check the lower 15 bits of 'r' and return the odd parity;//bit 16 is ignored.unsigned evenParity =

(1&(r>>0)) ^ (1&(r>>1)) ^ (1&(r>>2)) ^ (1&(r>>3)) ^(1&(r>>4)) ^ (1&(r>>5)) ^ (1&(r>>6)) ^ (1&(r>>7)) ^(1&(r>>8)) ^ (1&(r>>9)) ^ (1&(r>>10)) ^ (1&(r>>11)) ^(1&(r>>12)) ^ (1&(r>>13)) ^ (1&(r>>14));

return ~evenParity & 1; // odd parity}

unsigned PAR::genP_15Parity(unsigned r){

//check all 16 bits of 'r' and return the odd parityunsigned evenParity =

(1&(r>>0)) ^ (1&(r>>1)) ^ (1&(r>>2)) ^ (1&(r>>3)) ^(1&(r>>4)) ^ (1&(r>>5)) ^ (1&(r>>6)) ^ (1&(r>>7)) ^(1&(r>>8)) ^ (1&(r>>9)) ^ (1&(r>>10)) ^ (1&(r>>11)) ^

Page 419: Apollo Guidance Computer AGC

(1&(r>>12)) ^ (1&(r>>13)) ^ (1&(r>>14)) ^ (1&(r>>15));return ~evenParity & 1; // odd parity

}

Page 420: Apollo Guidance Computer AGC

Registers (reg.h)

#ifndef reg_H#define reg_H

#include <iostream.h>#include <string.h>#include <stdio.h>

class reg{public:

virtual unsigned read() { return mask & slaveVal; }virtual void write(unsigned v) { load = true; masterVal = mask & v; }

// asynchronous clearvoid clear() { slaveVal = 0; }

// load is set when a register is written into.void clk() { if(load) slaveVal = masterVal; load = false; }

unsigned readField(unsigned msb, unsigned lsb); // bitfield numbered n - 1void writeField(unsigned msb, unsigned lsb, unsigned v); // bitfield numbered n - 1

// Write a 16-bit word (in) into the register. Transpose the bits according to// the specification (ib).void writeShift(unsigned in, unsigned* ib);

// Return a shifted 16-bit word. Transpose the 'in' bits according to// the specification 'ib'. 'Or' the result to out and return the value.unsigned shiftData(unsigned out, unsigned in, unsigned* ib);

unsigned outmask() { return mask; }

protected:reg(unsigned s, char* fs)

: size(s), mask(0), masterVal(0), slaveVal(0), fmtString(fs), load(false){ mask = buildMask(size);}

static unsigned buildMask(unsigned s);

friend ostream& operator << (ostream& os, const reg& r){ char buf[32]; sprintf(buf, r.fmtString, r.slaveVal); os << buf; return os; }

private:unsigned size; // bitsunsigned masterVal;unsigned slaveVal;unsigned mask;char* fmtString;bool load;

reg(); // prevent instantiation of default constructor};

#endif

Page 421: Apollo Guidance Computer AGC

Registers (reg.cpp)

#include "reg.h"#include <math.h>#include "BUS.h"

unsigned reg::buildMask(unsigned s){

unsigned msk = 0;for(unsigned i=0; i<s; i++){

msk = (msk << 1) | 1;}return msk;

}

unsigned reg::readField(unsigned msb, unsigned lsb){

return (slaveVal >> (lsb-1)) & buildMask((msb-lsb)+1);}

void reg::writeField(unsigned msb, unsigned lsb, unsigned v){

load = true;unsigned fmask = buildMask((msb-lsb)+1) << (lsb-1);v = (v << (lsb-1)) & fmask;masterVal = (masterVal &(~fmask)) | v;

}

void reg::writeShift(unsigned in, unsigned* ib){

load = true;unsigned out = masterVal;

// iterate through each bit of the output word, copying in bits from the input// word and transposing bit position according to the specification (ib)

for(unsigned i=0; i<16; i++){

if(ib[i] == BX) continue; // BX is 'don't care', so leave it alone

// zero the output bit at 'ob', where ob specifies a bit// position (numbered 16-1, where 1 is lsb)

unsigned ob = 16-i;unsigned obmask = 1 << (ob - 1); // create mask for output bitout &= ~obmask;

if(ib[i] == D0) continue; // D0 is 'force the bit to zero'

// copy input bit ib[i] to output bit 'ob', where ib and ob// specify bit positions (numbered 16-1, where 1 is lsb)

unsigned ibmask = 1 << (ib[i] - 1); // create mask for input bitunsigned inbit = in & ibmask;

int shift = ib[i]-ob;if(shift<0)

inbit = inbit << abs(shift);else if(shift > 0)

inbit = inbit >> shift;out |= inbit;

}masterVal = out;

}

unsigned reg::shiftData(unsigned out, unsigned in, unsigned* ib){

// iterate through each bit of the output word, copying in bits from the input// word and transposing bit position according to the specification (ib)

for(unsigned i=0; i<16; i++){

if(ib[i] == BX) continue; // BX is 'don't care', so leave it alone

// zero the output bit at 'ob', where ob specifies a bit// position (numbered 16-1, where 1 is lsb)

unsigned ob = 16-i;

Page 422: Apollo Guidance Computer AGC

unsigned obmask = 1 << (ob - 1); // create mask for output bitout &= ~obmask;

if(ib[i] == D0) continue; // D0 is 'force the bit to zero'

// copy input bit ib[i] to output bit 'ob', where ib and ob// specify bit positions (numbered 16-1, where 1 is lsb)

unsigned ibmask = 1 << (ib[i] - 1); // create mask for input bitunsigned inbit = in & ibmask;

int shift = ib[i]-ob;if(shift<0)

inbit = inbit << abs(shift);else if(shift > 0)

inbit = inbit >> shift;out |= inbit;

}return out;

}

Page 423: Apollo Guidance Computer AGC

SCL (SCL.h)

/**************************************************************************** * SCL - SCALER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: SCL.h * * VERSIONS: * * DESCRIPTION: * Scaler for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef SCL_H#define SCL_H

#include "reg.h"

class regF17 : public reg { public:

regF17() : reg(2, "%01o") { }};

class regF13 : public reg { public:

regF13() : reg(2, "%01o") { }};

class regF10 : public reg { public:

regF10() : reg(2, "%01o") { }};

class regSCL : public reg { public:

regSCL() : reg(17, "%06o") { }};

class SCL{public:

static void doexecWP_SCL();static void doexecWP_F17();static void doexecWP_F13();static void doexecWP_F10();

static regSCL register_SCL;

// Normally outputs '0'; outputs '1' for one// clock pulse at the indicated frequency.

static unsigned F17x(); // 0.78125 Hz scaler outputstatic unsigned F13x(); // 12.5 Hz scaler outputstatic unsigned F10x(); // 100 Hz scaler output

static regF17 register_F17;static regF13 register_F13;static regF10 register_F10;

};

Page 424: Apollo Guidance Computer AGC

#endif

Page 425: Apollo Guidance Computer AGC

SCL (SCL.cpp)

/**************************************************************************** * SCL - SCALER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: SCL.cpp * * NOTES: see header file. * ***************************************************************************** */#include "SCL.h"#include "CTR.h"#include "MON.h"

regSCL SCL::register_SCL;regF17 SCL::register_F17;regF13 SCL::register_F13;regF10 SCL::register_F10;

enum oneShotType { // **inferred; not defined in orignal R393 AGC4 spec.WAIT_FOR_TRIGGER=0,OUTPUT_PULSE=1, // LSB (bit 1) is the output bit for the one-shotWAIT_FOR_RESET=2

};

void SCL::doexecWP_F17(){

int bit = SCL::register_SCL.readField(17,17);switch(register_F17.read()){case WAIT_FOR_TRIGGER: if(bit==1) register_F17.write(OUTPUT_PULSE); break;case OUTPUT_PULSE: register_F17.write(WAIT_FOR_RESET); break;case WAIT_FOR_RESET: if(bit==0) register_F17.write(WAIT_FOR_TRIGGER); break;default: ;}

}

void SCL::doexecWP_F13(){

int bit = SCL::register_SCL.readField(13,13);switch(register_F13.read()){case WAIT_FOR_TRIGGER: if(bit==1) register_F13.write(OUTPUT_PULSE); break;case OUTPUT_PULSE: register_F13.write(WAIT_FOR_RESET); break;case WAIT_FOR_RESET: if(bit==0) register_F13.write(WAIT_FOR_TRIGGER); break;default: ;}

}

void SCL::doexecWP_F10(){

int bit = SCL::register_SCL.readField(10,10);switch(register_F10.read()){case WAIT_FOR_TRIGGER: if(bit==1) register_F10.write(OUTPUT_PULSE); break;case OUTPUT_PULSE: register_F10.write(WAIT_FOR_RESET);

CTR::pcUp[TIME1] = 1;CTR::pcUp[TIME3] = 1;CTR::pcUp[TIME4] = 1;break;

case WAIT_FOR_RESET: if(bit==0) register_F10.write(WAIT_FOR_TRIGGER); break;default: ;}

}

unsigned SCL::F17x(){

return register_F17.readField(1,1);

Page 426: Apollo Guidance Computer AGC

}

unsigned SCL::F13x(){

return register_F13.readField(1,1);}

unsigned SCL::F10x(){

return register_F10.readField(1,1);}

void SCL::doexecWP_SCL(){

if(MON::SCL_ENAB) // if the scaler is enabled{

//write((read() + 1) % outmask());register_SCL.write((register_SCL.read() + 1));

}}

Page 427: Apollo Guidance Computer AGC

SEQ (SEQ.h)

/**************************************************************************** * SEQ - SEQUENCE GENERATOR subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: SEQ.h * * VERSIONS: * * DESCRIPTION: * Sequence Generator for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef SEQ_H#define SEQ_H

#include "reg.h"

#define MAXPULSES 15#define MAX_IPULSES 5 // no more than 5 instruction-generated pulses active at any time

enum cpType { // **inferred; not defined in orignal R393 AGC4 spec.NO_PULSE=0,

// OUTPUTS FROM SUBSYSTEM ACI =1, // Carry inCLG =2, // Clear GCLCTR =3, // Clear loop counterCTR =4, // Loop counterGP =5, // Generate ParityKRPT =6, // Knock down Rupt priorityNISQ =7, // New instruction to the SQ registerRA =8, // Read ARB =9, // Read BRB14 =10, // Read bit 14RC =11, // Read CRG =12, // Read GRLP =13, // Read LPRP2 =14, // Read parity 2RQ =15, // Read QRRPA =16, // Read RUPT addressRSB =17, // Read sign bitRSCT =18, // Read selected counter addressRU =19, // Read sumRZ =20, // Read ZR1 =21, // Read 1R1C =22, // Read 1 complimentedR2 =23, // Read 2R22 =24, // Read 22R24 =25, // Read 24ST1 =26, // Stage 1ST2 =27, // Stage 2TMZ =28, // Test for minus zeroTOV =29, // Test for overflowTP =30, // Test parityTRSM =31, // Test for resumeTSGN =32, // Test signTSGN2 =33, // Test sign 2WA =34, // Write AWALP =35, // Write A and LPWB =36, // Write BWGx =37, // Write G (do not reset)

Page 428: Apollo Guidance Computer AGC

WLP =38, // Write LPWOVC =39, // Write overflow counterWOVI =40, // Write overflow RUPT inhibitWOVR =41, // Write overflowWP =42, // Write PWPx =43, // Write P (do not reset)WP2 =44, // Write P2WQ =45, // Write QWS =46, // Write SWX =47, // Write XWY =48, // Write YWYx =49, // Write Y (do not reset)WZ =50, // Write Z

// OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM B ONLY;// NOT USED OUTSIDE CPMRSC =51, // Read special and central (output to B only, not outside CPM)WSC =52, // Write special and central (output to B only, not outside CPM)WG =53, // Write G (output to B only, not outside CPM)

// OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM C ONLY;// NOT USED OUTSIDE CPMSDV1 =54, // Subsequence DV1 is currently activeSMP1 =55, // Subsequence MP1 is currently activeSRSM3 =56, // Subsequence RSM3 is currently active

// EXTERNAL OUTPUTS FROM SUBSYSTEM B//RA0 =57, // Read register at address 0 (A)RA1 =58, // Read register at address 1 (Q)RA2 =59, // Read register at address 2 (Z)RA3 =60, // Read register at address 3 (LP)RA4 =61, // Read register at address 4RA5 =62, // Read register at address 5RA6 =63, // Read register at address 6RA7 =64, // Read register at address 7RA10 =65, // Read register at address 10 (octal)RA11 =66, // Read register at address 11 (octal)RA12 =67, // Read register at address 12 (octal)RA13 =68, // Read register at address 13 (octal)RA14 =69, // Read register at address 14 (octal)RBK =70, // Read BNKWA0 =71, // Write register at address 0 (A)WA1 =72, // Write register at address 1 (Q)WA2 =73, // Write register at address 2 (Z)WA3 =74, // Write register at address 3 (LP)WA10 =75, // Write register at address 10 (octal)WA11 =76, // Write register at address 11 (octal)WA12 =77, // Write register at address 12 (octal)WA13 =78, // Write register at address 13 (octal)WA14 =79, // Write register at address 14 (octal)WBK =80, // Write BNKWGn =81, // Write G (normal gates)**W20 =82, // Write into CYRW21 =83, // Write into SRW22 =84, // Write into CYLW23 =85, // Write into SL

// THESE ARE THE LEFTOVERS -- THEY'RE PROBABLY USED IN SUBSYSTEM C//GENRST =86, // General Reset**CLINH =87, // Clear INHINT**CLINH1 =88, // Clear INHINT1**CLSTA =89, // Clear state counter A (STA)**CLSTB =90, // Clear state counter B (STB)**CLISQ =91, // Clear SNI**CLRP =92, // Clear RPCELL**INH =93, // Set INHINT**RPT =94, // Read RUPT opcode **SBWG =95, // Write G from memorySETSTB =96, // Set the ST1 bit of STBWE =97, // Write E-MEM from GWPCTR =98, // Write PCTR (latch priority counter sequence)**WSQ =99, // Write SQ

Page 429: Apollo Guidance Computer AGC

WSTB =100, // Write stage counter B (STB)**R2000 =101, // Read 2000 **

};

// INSTRUCTIONS

// Op Codes, as they appear in the SQ register.enum instruction {

// The code in the SQ register is the same as the op code for these// four instructions.TC =00, // 00 TC K Transfer Control 1 MCTCCS =01, // 01 CCS K Count, Compare, and Skip 2 MCTINDEX =02, // 02 INDEX K 2 MCTXCH =03, // 03 XCH K Exchange 2 MCT

// The SQ register code is the op code + 010 (octal). This happens because all// of these instructions have bit 15 set (the sign (SG) bit) while in memory. When the// instruction is copied from memory to the memory buffer register (G) to register// B, the SG bit moves from bit 15 to bit 16 and the sign is copied back into bit// 15 (US). Therefore, the CS op code (04) becomes (14), and so on.CS =014, // 04 CS K Clear and Subtract 2 MCTTS =015, // 05 TS K Transfer to Storage 2 MCTAD =016, // 06 AD K Add 2 or 3 MCTMASK =017, // 07 MASK K Bitwise AND 2 MCT

// These are extended instructions. They are accessed by executing an INDEX 5777// before each instruction. By convention, address 5777 contains 47777. The INDEX// instruction adds 47777 to the extended instruction to form the SQ op code. For// example, the INDEX adds 4 to the 4 op code for MP to produce the 11 (octal; the// addition generates an end-around-carry). SQ register code (the 7777 part is a // negative zero).MP =011, // 04 MP K Multiply 10 MCTDV =012, // 05 DV K Divide 18 MCTSU =013, // 06 SU K Subtract 4 or 5 MCT

};

enum subseq {TC0 =0,CCS0 =1,CCS1 =2,NDX0 =3,NDX1 =4,RSM3 =5,XCH0 =6,CS0 =7,TS0 =8,AD0 =9,MASK0 =10,MP0 =11,MP1 =12,MP3 =13,DV0 =14,DV1 =15,SU0 =16,RUPT1 =17,RUPT3 =18,STD2 =19,PINC0 =20,MINC0 =21,SHINC0 =22,NO_SEQ =23

};

enum scType { // identifies subsequence for a given instructionSUB0=0, // ST2=0, ST1=0SUB1=1, // ST2=0, ST1=1SUB2=2, // ST2=1, ST1=0SUB3=3 // ST2=1, ST1=1

};

enum brType {BR00 =0, // BR1=0, BR2=0BR01 =1, // BR1=0, BR2=1

Page 430: Apollo Guidance Computer AGC

BR10 =2, // BR1=1, BR2=0BR11 =3, // BR1=1, BR2=1NO_BR =4 // NO BRANCH

};

const int GOPROG =02000; // bottom address of fixed memory

class regSQ : public reg { public:

regSQ() : reg(4, "%02o") { }};

class regSTA : public reg { public:

regSTA() : reg(2, "%01o") { }};

class regSTB : public reg { public:

regSTB() : reg(2, "%01o") { }};

class regBR1 : public reg { public:

regBR1() : reg(1, "%01o") { }};

class regBR2 : public reg { public:

regBR2() : reg(1, "%01o") { }};

class regCTR : public reg { public:

regCTR() : reg(3, "%01o") { }};

class regSNI : public reg { public: regSNI() : reg(1, "%01o") { }};

class SEQ{public:

static void execWP_GENRST();static void execWP_WSQ(); static void execWP_NISQ();static void execWP_CLISQ();static void execWP_ST1();static void execWP_ST2();static void execWP_TRSM();static void execWP_CLSTA();static void execWP_WSTB();static void execWP_CLSTB();static void execWP_SETSTB();static void execWP_TSGN();static void execWP_TOV();static void execWP_TMZ();static void execWP_TSGN2();static void execWP_CTR();static void execWP_CLCTR();

static regSNI register_SNI; // select next intruction flagstatic cpType glbl_cp[MAXPULSES]; // current set of asserted control pulses

(MAXPULSES)

static char* cpTypeString[];

Page 431: Apollo Guidance Computer AGC

// Test the currently asserted control pulses; return true if the specified// control pulse is active.static bool isAsserted(cpType pulse);

// Return a string containing the names of all asserted control pulses.static char* getControlPulses();

static subseq glbl_subseq; // currently decoded instruction subsequence

static regSQ register_SQ; // instruction registerstatic regSTA register_STA; // stage counter Astatic regSTB register_STB; // stage counter Bstatic regBR1 register_BR1; // branch register1static regBR2 register_BR2; // branch register2static regCTR register_LOOPCTR; // loop counter

static char* instructionString[];};

#endif

Page 432: Apollo Guidance Computer AGC

SEQ (SEQ.cpp)

/**************************************************************************** * SEQ - SEQUENCE GENERATOR subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: SEQ.cpp * * NOTES: see header file. * ***************************************************************************** */#include "SEQ.h"#include "ADR.h"#include "BUS.h"

regSNI SEQ::register_SNI; // select next intruction flagcpType SEQ::glbl_cp[]; // current set of asserted control pulses (MAXPULSES)

regSQ SEQ::register_SQ; // instruction registerregSTA SEQ::register_STA; // stage counter AregSTB SEQ::register_STB; // stage counter BregBR1 SEQ::register_BR1; // branch register1regBR2 SEQ::register_BR2; // branch register2regCTR SEQ::register_LOOPCTR; // loop countersubseq SEQ::glbl_subseq; // currently decoded instruction subsequence

char* SEQ::instructionString[] ={

"TC","CCS","INDEX","XCH","***","***","***","***","***","MP","DV","SU","CS","TS","AD","MASK"

};

char* SEQ::cpTypeString[] = {

"NO_PULSE",

// OUTPUTS FROM SUBSYSTEM A"CI", "CLG", "CLCTR", "CTR", "GP", "KRPT", "NISQ", "RA", "RB", "RB14", "RC", "RG", "RLP", "RP2", "RQ", "RRPA", "RSB", "RSCT", "RU", "RZ", "R1", "R1C", "R2", "R22", "R24", "ST1", "ST2", "TMZ", "TOV", "TP", "TRSM", "TSGN", "TSGN2", "WA", "WALP", "WB", "WGx", "WLP", "WOVC", "WOVI", "WOVR", "WP", "WPx", "WP2", "WQ", "WS", "WX", "WY", "WYx", "WZ",

// OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM B ONLY;// NOT USED OUTSIDE CPM//"RSC", "WSC", "WG",

// OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM C ONLY;// NOT USED OUTSIDE CPM//"SDV1", "SMP1", "SRSM3",

// EXTERNAL OUTPUTS FROM SUBSYSTEM B

Page 433: Apollo Guidance Computer AGC

//"RA0", "RA1", "RA2", "RA3", "RA4", "RA5", "RA6", "RA7", "RA10", "RA11", "RA12", "RA13", "RA14", "RBK", "WA0", "WA1", "WA2", "WA3", "WA10", "WA11", "WA12", "WA13", "WA14", "WBK", "WGn", "W20", "W21", "W22", "W23",

// THESE ARE THE LEFTOVERS -- THEY'RE PROBABLY USED IN SUBSYSTEM C//"GENRST", "CLINH", "CLINH1", "CLSTA", "CLSTB", "CLISQ", "CLRP", "INH", "RPT", "SBWG", "SETSTB", "WE", "WPCTR", "WSQ", "WSTB", "R2000"

};

void SEQ::execWP_GENRST(){

register_SQ.write(0);register_BR1.write(0);register_BR2.write(0);register_SNI.write(0);register_LOOPCTR.write(0);register_STA.write(0);register_STB.write(0);

}

void SEQ::execWP_WSQ(){

register_SQ.write(BUS::glbl_WRITE_BUS >> 12);}

void SEQ::execWP_NISQ(){

register_SNI.writeField(1,1,1); // change to write(1)??}

void SEQ::execWP_CLISQ(){

register_SNI.writeField(1,1,0); // change to write(0)??}

bool SEQ::isAsserted(cpType pulse){

for(unsigned i=0; i<MAXPULSES; i++)if(glbl_cp[i] == pulse) return true;

return false;}

char* SEQ::getControlPulses(){

static char buf[MAXPULSES*6];strcpy(buf,"");

for(unsigned i=0; i<MAXPULSES && glbl_cp[i] != NO_PULSE; i++){

strcat(buf, cpTypeString[glbl_cp[i]]);strcat(buf," ");

}//if(strcmp(buf,"") == 0) strcat(buf,"NONE");return buf;

}

void SEQ::execWP_ST1(){

register_STA.writeField(1,1,1);}

Page 434: Apollo Guidance Computer AGC

void SEQ::execWP_ST2(){

register_STA.writeField(2,2,1);}

void SEQ::execWP_TRSM(){

if(ADR::EQU_25()) register_STA.writeField(2,2,1);

}

void SEQ::execWP_CLSTA(){

register_STA.writeField(2,1,0);}

void SEQ::execWP_WSTB(){

register_STB.write(SEQ::register_STA.read()); }

void SEQ::execWP_CLSTB(){

register_STB.writeField(2,1,0);}

void SEQ::execWP_SETSTB(){

register_STB.writeField(2,1,1);}

void SEQ::execWP_TSGN(){

// Set Branch 1 FF// if sign bit is '1' (negative sign)

if(BUS::glbl_WRITE_BUS & 0100000) register_BR1.write(1);

else register_BR1.write(0);

}

void SEQ::execWP_TOV(){

// Set Branch 1 FF// if negative overflow (sign==1; overflow==0)

if((BUS::glbl_WRITE_BUS & 0140000) == 0100000) register_BR1.write(1);

else register_BR1.write(0);

// Set Branch 2 FF// if positive overflow (sign==0; oveflow==1)

if((BUS::glbl_WRITE_BUS & 0140000) == 0040000) register_BR2.write(1);

else register_BR2.write(0);

}

void SEQ::execWP_TSGN2(){

// Set Branch 2 FF// if sign bit is '1' (negative sign)

Page 435: Apollo Guidance Computer AGC

if(BUS::glbl_WRITE_BUS & 0100000) register_BR2.write(1);

else register_BR2.write(0);

}

void SEQ::execWP_TMZ(){

// Set Branch 2 FF// if minus zero

if(BUS::glbl_WRITE_BUS == 0177777) register_BR2.write(1);

else register_BR2.write(0);

}

void SEQ::execWP_CTR(){

register_LOOPCTR.write(register_LOOPCTR.read()+1);}

void SEQ::execWP_CLCTR(){

register_LOOPCTR.write(0);}

Page 436: Apollo Guidance Computer AGC

TPG (TPG.h)

/**************************************************************************** * TPG - TIME PULSE GENERATOR subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: TPG.h * * VERSIONS: * * DESCRIPTION: * Time Pulse Generator and Start/Stop Logic for the Block 1 Apollo Guidance * Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */#ifndef TPG_H#define TPG_H

#include "reg.h"

// Start/Stop Logic and Time Pulse Generator Subsystem

enum tpType {STBY =0,PWRON =1,

TP1 =2, // TIME PULSE 1: start of memory cycle time (MCT)TP2 =3,TP3 =4,TP4 =5,TP5 =6,TP6 =7, // EMEM is available in G register by TP6TP7 =8, // FMEM is available in G register by TP7TP8 =9,TP9 =10,TP10 =11, // G register written to memory beginning at TP10TP11 =12, // TIME PULSE 11: end of memory cycle time (MCT)TP12 =13, // select new subsequence/select new instruction

SRLSE =14, // step switch releaseWAIT =15

};

class regSG : public reg { public: regSG() : reg(4, "%02o") { }

};

class TPG{public:

static void doexecWP_TPG();

static regSG register_SG;

static char* tpTypestring[];};

#endif

Page 437: Apollo Guidance Computer AGC

TPG (TPG.cpp)

/**************************************************************************** * TPG - TIME PULSE GENERATOR subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: TPG.cpp * * NOTES: see header file. * ***************************************************************************** */#include "TPG.h"#include "MON.h"#include "SCL.h"#include "SEQ.h"#include "OUT.h"

char* TPG::tpTypestring[] = // must correspond to tpType enumerated type{

"STBY", "PWRON", "TP1", "TP2", "TP3", "TP4", "TP5", "TP6", "TP7", "TP8","TP9", "TP10", "TP11", "TP12", "SRLSE", "WAIT"

};

regSG TPG::register_SG; // static member

void TPG::doexecWP_TPG() {

unsigned mystate = register_SG.read();if(MON::PURST)

mystate = STBY;elseswitch(mystate){case STBY: if(!MON::PURST && ((!MON::FCLK) || SCL::F17x())) mystate = PWRON; break;case PWRON: if(((!MON::FCLK) || SCL::F13x())) mystate = TP1; break;

case TP1: mystate = TP2; break;case TP2: mystate = TP3; break;case TP3: mystate = TP4; break;case TP4: mystate = TP5; break;case TP5: mystate = TP6; break;case TP6: mystate = TP7; break;case TP7: mystate = TP8; break;case TP8: mystate = TP9; break;case TP9: mystate = TP10; break;case TP10: mystate = TP11; break;case TP11: mystate = TP12; break;case TP12:

if(SEQ::register_SNI.read() && OUT::register_OUT1.readField(8,8) && MON::SA)mystate = STBY;// the next transition to TP1 is incompletely decoded; it works because// the transition to STBY has already been tested.

else if((MON::RUN) || (!SEQ::register_SNI.read() && MON::INST))mystate = TP1;

elsemystate = SRLSE;

break;case SRLSE: if(!MON::STEP) mystate = WAIT; break;case WAIT:

if(MON::STEP || MON::RUN) mystate = TP1;

break;default: break;}register_SG.write(mystate);

}

Page 438: Apollo Guidance Computer AGC

Block IApollo Guidance Computer (AGC)

How to build one in your basement

Part 8: Flight Software

John Pultorak

December, 2004

Page 439: Apollo Guidance Computer AGC

Abstract

This report describes my successful project to build a working reproduction of the 1964

prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the

Apollo moon landings, and is the world’s first integrated circuit computer.

I built it in my basement. It took me 4 years.

If you like, you can build one too. It will take you less time, and yours will be better than

mine.

I documented my project in 9 separate .pdf files:

Part 1 Overview: Introduces the project.

Part 2 CTL Module: Design and construction of the control module.

Part 3 PROC Module: Design and construction of the processing (CPU) module.

Part 4 MEM Module: Design and construction of the memory module.

Part 5 IO Module: Design and construction of the display/keyboard (DSKY) module.

Part 6 Assembler: A cross-assembler for AGC software development.

Part 7 C++ Simulator: A low-level simulator that runs assembled AGC code.

Part 8 Flight Software: My translation of portions of the COLOSSUS 249 flight

software.

Part 9 Test & Checkout: A suite of test programs in AGC assembly language.

Page 440: Apollo Guidance Computer AGC

Overview

I wanted genuine Block I flight software for my AGC, but couldn’t find any. I eventually

wound up recreating Block I software from Block II code listings that were available. Major

portions of Block II were originally coded as Block I anyway, so the conversion back was not

too difficult. About 95% of the instructions were already Block I, so I just had to translate

the remaining 5% into their Block I equivalents.

I downloaded a partial listing of the COLOSSUS 249 flight software for the Block II Apollo

Command Module AGC from a M.I.T website in late 2001. The listing (at that time)

comprised first half

of the flight

software load. The

second half was

missing.

The part that was

present contained

eraseable memory

declarations, and

PINBALL, the AGC

user interface. The

missing portion

contained (among

other things) the

EXEC and

WAITLIST pieces of

the operating

system, bank

register calling

routines, and math

libraries.

The downloaded

document was a .pdf file containing 300 or so fuzzy dig ital images of assembler listing. I

printed it, and then retyped the erasable memory and PINBALL portions into a text file,

marking off each reentered line in the original listing with a highlighter.

I coded my own versions of the EXEC, WAITLIST, BANKCALL, and other missing routines

used by PINBALL. The R-393 document from M.I.T. provided some guidance.

Over a 6 month period, I was able to get all regular verbs and generic normal nouns

working. These are listed near the top of my assembler listing.

I added additional comments to portions of code taken from COLOSSUS. The page numbers

in my comments refer to pages in the COLOSSUS 249 assembler listing.

Page 441: Apollo Guidance Computer AGC

Original COLOSSUS 249 Assembler Code

For comparison purposes, here’s a page of the original AGC assembly code, downloaded

from the M.I.T. website. This is a tiny portion of the PINBALL code. I marked each line with

a yellow highlighter as I reentered it into a text file.

Page 442: Apollo Guidance Computer AGC

My COLOSSUS Assembler Code

Here’s the exact same portion of code, assembled for my Block I AGC. If you compare the

two listings, you’ll see that I defined some different assembler directives for allocating

storage (DS % instead of OCT) and that my code is sitting in a different bank (5 vs. 40) at a

different offset than the original Block II code.

Page 443: Apollo Guidance Computer AGC

Scenarios

Here’s how some AGC verbs and nouns are used to do commonplace operations. The

overview (part 1) and simulator (part 7) documents contain actual examples of some of

these operations in the simulated and hardware AGCs.

Display elapsed time from the AGC clock:

<VERB> <0> <6> <NOUN> <3> <6> <ENTER>

Start a monitor program to continuously display the AGC clock:

<VERB> <1> <6> <NOUN> <3> <6> <ENTER>

Terminate a monitor program:

<VERB> <3> <4> <ENTER>

Test DSJT display lights:

<VERB> <3> <5> <ENTER>

All DSKY lamps and display segments illuminate for 5 sec. after 5 sec, the DSKY

lamps extinguish.

Load component 1 for dataset at octal address 50 with octal 123:

<VERB> <2> <1> <NOUN> <0> <1> <ENTER>

Verb/noun display flashes: waiting for address.

<5> <0> <ENTER>

Verb/noun display flash continues: waiting for data.

<1> <2> <3> <ENTER>

Octal word from R1 is loaded at address 50.

Display component 1 of dataset at octal address 50:

<VERB> <0> <1> <NOUN> <0> <1> <ENTER>

Verb/noun display flashes: waiting for address.

<5> <0> <ENTER>

Octal word from address 50 is displayed in R1.

Display component 1 of dataset incrementing from 50:

<VERB> <0> <1> <NOUN> <0> <1> <ENTER>

Verb/noun display flashes: waiting for address.

<5> <0> <ENTER>

Octal word from address 50 is displayed in R1.

<NOUN> <1> <5> <ENTER>

Octal word from address 51 is displayed in R1, address in R3.

<ENTER>

Octal word from address 52 is displayed in R1, address in R3.

Load 3 component dataset at octal address 50 with octal values: 123, 456, 701:

<VERB> <2> <5> <NOUN> <0> <1> <ENTER>

Verb/noun display flashes: waiting for address.

<5> <0> <ENTER>

Verb/noun display flash continues: waiting for data.

<1> <2> <3> <ENTER>

<4> <5> <6> <ENTER>

<7> <0> <1> <ENTER>

Page 444: Apollo Guidance Computer AGC

Octal word from R1 is loaded at address 50; Octal word from R2 is loaded at address

51, Octal word from R3 is loaded at address 52.

Display 3 component dataset beginning at address 50:

<VERB> <0> <5> <NOUN> <0> <1> <ENTER>

Verb/noun display flashes: waiting for address.

<5> <0> <ENTER>

Octal word from address 50 is displayed in R1; Octal word from address 51 is

displayed in R2; Octal word from address 52 is displayed in R3.

Change major mode to P00:

<VERB> <3> <7> <ENTER>

Verb/noun display flashes: waiting for major mode

<0> <0> <ENTER>

Page 445: Apollo Guidance Computer AGC

VERBS and NOUNS

COLOSSUS REGULAR VERBS (00-39 decimal)

This is adapted from the Apollo 204 accident report posted on multiple

web sites by Richard F. Drushel. The information has been changed as

necessary to be consistent with usage in COLOSSUS 249.

Verb | |Code | Description | Remarks | |01 | Display octal comp 1 in R1 | Performs octal display of data on | | REGISTER 1. | |02 | Display octal comp 2 in R2 | Performs octal display of data on | | REGISTER 1. | |03 | Display octal comp 3 in R3 | Performs octal display of data on | | REGISTER 1. | |04 | Display octal comp 1,2 | Performs octal display of data on | in R1,R2 | REGISTER 1 and REGISTER 2 | |05 | Display octal comp 1,2,3 | Performs octal display of data on | in R1,R2,R3 | REGISTER 1, REGISTER 2, and REGISTER 3. | |06 | Display decimal in R1 or | Performs decimal display of data on | R1,R2 or R1,R2,R3 | appropriate registers. The scale | | factors, types of scale factor | | routines, and component information | | are stored within the machine for each | | noun which it is required to display | | in decimal. | |07 | Display DP decimal in R1,R2 | Performs a double precision decimal | | display of data on REGISTER 1 and | | REGISTER 2. It does no scale | | factoring. It merely performs a 10- | | character, fractional decimal | | conversion of two consecutive, erasable | | registers, using REGISTER 1 and | | REGISTER 2. The sign is placed in the | | REGISTER 1 sign position with the | | REGISTER 2 sign position remaining | | blank. It cannot be used with mixed | | nouns. Its intended use is primarily | | with "machine address to be specified" | | nouns. | |08 | (Spare) | | |09 | (Spare) | | |10 | (Spare) | | |11 | Monitor octal comp 1 in R1 | Performs octal display of updated data | | every 1/2 second on REGISTER 1. | |12 | Monitor octal comp 2 in R2 | Performs octal display of updated data | | every 1/2 second on REGISTER 1. | |13 | Monitor octal comp 3 in R3 | Performs octal display of updated data | | every 1/2 second on REGISTER 1. | |14 | Monitor octal comp 1,2 | Performs octal display of updated data | in R1,R2 | every 1/2 second on REGISTER 1 and | | REGISTER 2. | |15 | Monitor octal comp 1,2,3 | Performs octal display of updated data | in R1,R2,R3 | every 1/2 second on REGISTER 1, | | REGISTER 2, and REGISTER 3. | |

Page 446: Apollo Guidance Computer AGC

16 | Monitor decimal in R1 or | Performs decimal display of updated | R1,R2, or R1,R2,R3 | data every 1/2 second on appropriate | | registers. | |17 | Monitor DP decimal in R1,R2 | Performs double precision display of | | decimal data on REGISTER 1 and | | REGISTER 2. No scale factoring is | | performed. Provides 10-character, | | fractional decimal conversion of two | | consecutive erasable registers. The | | sign is placed in the sign-bit | | position of REGISTER 1. REGISTER 2 | | sign bit is blank. | |18 | (Spare) | | |19 | (Spare) | | |20 | (Spare) | | |21 | Load component 1 into R1 | Performs data loading. Octal | | quantities are unsigned. Decimal | | quantities are preceded by + or - | | sign. Data is displayed on REGISTER | | 1. | |22 | Load component 2 into R2 | Performs data loading. Octal | | quantities are unsigned. Decimal | | quantities are preceded by + or - | | sign. Data is displayed on REGISTER | | 2. | |23 | Load component 3 into R3 | Performs data loading. Octal | | quantities are unsigned. Decimal | | quantities are preceded by + or - | | sign. Data is displayed on REGISTER | | 3. | |24 | Load component 1,2 into | Performs data loading. Octal | R1,R2 | quantities are unsigned. Decimal | | quantities are preceded by + or - | | sign. Data is displayed on REGISTER | | 1 and REGISTER 2. | |25 | Load component 1,2,3 into | Performs data loading. Octal | R1,R2,R3 | quantities are unsigned. Decimal | | quantities are preceded by + or - | | sign. Data is displayed on REGISTER | | 1, REGISTER 2, and REGISTER 3. | |26 | (Spare) | | |27 | Display fixed memory | This verb is included to permit | | displaying the contents of fixed | | memory in any bank. Its intended use | | is for checking program ropes and the | | BANK positions of program ropes. | |28 | (Spare) | | |29 | (Spare) | | |30 | Request EXECUTIVE | Enters request to executive routine | (Used only during ground | for any machine address with priority | checkout.) | involved. This verb assumes that the | | desired priority has been loaded into | | bits 10-14 of the prio/delay register | | (noun 26). This verb is used with the | | noun, "machine address to be | | specified". The complete address of | | the desired location is then keyed in. | | (Refer to "Machine address to be | | specified" in paragraph on Verb/Noun | | Formats.) | |31 | Request WAITLIST | Enters request to "waitlist routine"

Page 447: Apollo Guidance Computer AGC

| (Used only during ground | for any machine address with delay | checkout.) | involved. This verb assumes that the | | desired number of 10-millisecond units | | of delay has been loaded into the low | | order bits of the prio/delay register | | (noun 26). This verb is used with the | | "machine address to be specified" noun. | | The complete address of the desired | | location is then keyed in. (Refer to | | "Machine address to be specified" in | | paragraph on Verb/Noun Formats.) | |32 | Recycle | | |33 | Proceed (without data) | Informs routine requesting data that | | the operator chooses not to load | | fresh data, but wishes the routine to | | continue as best it can with old data. | | Final decision for what action should | | be taken is left to the requesting | | routine. | |34 | Terminate | Informs routine requesting data to be | | loaded that the operator chooses not | | to load fresh data and wishes the | | routine to terminate. Final decision | | for what action should be taken is | | left to the requesting routine. If | | monitor is on, it is turned off. | |35 | Test lights | | |36 | Request fresh start | Initializes the program control | | software and the keyboard and display | | system program. | |37 | Change program (major mode) | Change to new major mode. (Refer to | | "Change major mode" in paragraph on | | Verb/Noun Formats.) | |;--------------------------------------------------------------------------

COLOSSUS EXTENDED VERBS (40-99 decimal)

Not implemented. Use of these verbs triggers the 'check fail ' indicator.

COLOSSUS NORMAL NOUNS (00-39 decimal)

This is adapted from the Apollo 204 accident report posted on multiple

web sites by Richard F. Drushel. The information has been changed as

necessary to be consistent with usage in COLOSSUS 249.

Noun | |Code | Description | Scale/Units | |01 | Specify machine address (frac) | .XXXXX FRAC | | .XXXXX FRAC | | .XXXXX FRAC | | 02 | Specify machine address (whole) | XXXXX INTEGER | | XXXXX INTEGER | | XXXXX INTEGER | | 03 | Specify machine address (degree) | XXX.XX DEG | | XXX.XX DEG | | XXX.XX DEG

Page 448: Apollo Guidance Computer AGC

| | 04 | (Spare) | | |05 | (Spare) | | |06 | (Spare) | | |07 | (Spare) | | |08 | (Spare) | | |09 | Alarm codes | OCT | | OCT | | OCT | |10 | (Spare) | | |11 | (Spare) | | |12 | (Spare) | | |13 | (Spare) | | |14 | (Spare) | | |15 | Increment address | OCT | | | |16 | (Spare) | | |17 | (Spare) | | |18 | (Spare) | | |19 | (Spare) | | |20 | (Spare) | | |21 | (Spare) | | |22 | (Spare) | | |23 | (Spare) | | |24 | (Spare) | | |25 | (Spare) | | |26 | Prio/delay, address | OCT (prio/delay) | | OCT (14-bit CADR) | | (not used) | |27 | (Spare) | | |28 | (Spare) | | |29 | (Spare) | | |30 | (Spare) | | |31 | (Spare) | | |32 | (Spare) | | |33 | (Spare) | | |34 | (Spare) | | |35 | (Spare) | | |36 | Time of CMC clock: | | REGISTER 1 | 00XXX. hours | REGISTER 2 | 000XX. minutes | REGISTER 3 | 0XX.XX seconds | |37 | (Spare) |

Page 449: Apollo Guidance Computer AGC

| |38 | (Spare) | | |39 | (Spare) | | |;--------------------------------------------------------------------------

COLOSSUS MIXED NOUNS (40-99 decimal)

Not implemented.

Page 450: Apollo Guidance Computer AGC

Flight software assembler listing

Block I Apollo Guidance Computer (AGC4) assembler version 1.6 for EPROM

First pass: generate symbol table.Second pass: generate object code.

;========================================================================== ; AGC (file:agc.asm) ; ; Version: 1.0 ; Author: John Pultorak ; Date: 6/7/2002 ; ; PURPOSE: ; AGC Block I demonstration. Includes most of the AGC operating system: ; WAITLIST, EXEC, PINBALL (DSKY routines), NOUN tables, VERB tables, ; bank intercommunication routines, the KEY, T3, and T4 interrupt handlers, ; and some dual precision (DP) math routines. ; ; The interpreter is not currently implemented. ; ; Where available, the source is from the Apollo 8 command module computer (CMC) ; load (called COLOSSUS). In cases where COLOSSUS source is not available, ; functionally equivalent code was constructed using COLOSSUS calling and return ; parameters and according to specifications in the technical reports given below. ; ; OPERATION: ; TBD. ; ; ERRATA: ; - Adapted for the AGC4R assembler. The assembler directives and syntax ; differ somewhat from the original AGC assembler. ; - some of the original source was missing from the COLOSSUS listing and ; had to be reverse engineered. Those portions probably differ somewhat ; from the original code in implementation, but should be functionally ; identical. ; - because the COLOSSUS source is for a block II AGC, but the AGC ; implemented here is block I, about 5% of COLOSSUS had to be translated ; to equivalent block I code. ; ; SOURCES: ; Information on the Block I architecture: instruction set, instruction ; sequences, registers, register transfers, control pulses, memory and ; memory addressing, I/O assignments, interrupts, and involuntary counters ; was obtained from: ; ; A. Hopkins, R. Alonso, and H. Blair-Smith, "Logical Description ; for the Apollo Guidance Computer (AGC4)", R-393, ; MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963. ; ; Supplementary AGC hardware information was obtained from: ; ; R. Alonso, J. H. Laning, Jr. and H. Blair-Smith, "Preliminary ; MOD 3C Programmer's Manual", E-1077, MIT Instrumentation ; Laboratory, Cambridge, MA, Nov. 1961. ; ; B. I. Savage and A. Drake, "AGC4 Basic Training Manual, Volume I", ; E-2052, MIT Instrumentation Laboratory, Cambridge, ; MA, Jan. 1967. ; ; E. C. Hall, "MIT's Role in Project Apollo, Volume III, Computer ; Subsystem", R-700, MIT Charles Stark Draper Laboratory, ; Cambridge, MA, Aug. 1972. ; ; A. Hopkins, "Guidance Computer Design, Part VI", source unknown. ; ; E, C. Hall, "Journey to the Moon: The History of the Apollo ; Guidance Computer", AIAA, Reston VA, 1996. ; ; AGC software information was obtained from: ; ; AGC Block II COLOSSUS rev 249 assembly listing, Oct 28, 1968. (A ; listing of the 1st 50% of the build. It encludes the entire ; eraseable memory, restart initialization, T4RUPT, and the ; entire set of DSKY routines. About 5% of instructions ; had to be converted from Block II to Block I). ; ; A. I. Green and J. J. Rocchio, "Keyboard and Display System Program ; for AGC (Program Sunrise)", E-1574, MIT Instrumentation ; Laboratory, Cambridge, MA, Aug. 1964. Contains detailed ; flowcharts and design materials for the DSKY software. ; ; A. Hopkins, R. Alonso, and H. Blair-Smith, "Logical Description ; for the Apollo Guidance Computer (AGC4)", R-393,

Page 451: Apollo Guidance Computer AGC

; MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963. ; Contains the software interfaces for EXEC and WAITLIST, and ; portions of the dual precision (DP) math library. ; ;========================================================================== INCL doc.asm ;========================================================================== ; AGC documentation (file:doc.asm) ; ; Version: 1.0 ; Author: John Pultorak ; Date: 06/01/2002 ; ; PURPOSE: ; Documents AGC ops source code. ;========================================================================== ;-------------------------------------------------------------------------- ; DSKY OPERATION (examples) ; ; verb/noun (V/N) flash: When the verb and noun indicators flash ; at 1Hz, the DSKY is waiting for keyboard input. ; ; ; Display elapsed time from the AGC clock: ; <VERB> <0> <6> <NOUN> <3> <6> <ENTER> ; ; Test display lights ; a) <VERB> <3> <5> <ENTER> ; b) all DSKY lamps and display segments illuminate for 5 sec. ; c) after 5 sec, the DSKY lamps extinguish ; ; Load component 1 for dataset at octal address 50 with octal 123 ; a) <VERB> <2> <1> <NOUN> <0> <1> <ENTER> ; b) verb/noun display flashes; waiting for address ; c) <5> <0> <ENTER> ; d) verb/noun display flash continues; waiting for data ; e) <1> <2> <3> <ENTER> ; f) octal word from R1 is loaded at address 50, ; ; Display component 1 of dataset at octal address 50: ; a) <VERB> <0> <1> <NOUN> <0> <1> <ENTER> ; b) verb/noun display flashes; waiting for address ; c) <5> <0> <ENTER> ; d) octal word from address 50 is displayed in R1 ; ; Load 3 component dataset at octal address 50 with octal values ; 123,456,701 ; a) <VERB> <2> <5> <NOUN> <0> <1> <ENTER> ; b) verb/noun display flashes; waiting for address ; c) <5> <0> <ENTER> ; d) verb/noun display flash continues; waiting for data ; e) <1> <2> <3> <ENTER> ; f) <4> <5> <6> <ENTER> ; g) <7> <0> <1> <ENTER> ; h) octal word from R1 is loaded at address 50, ; octal word from R2 is loaded at address 51, ; octal word from R3 is loaded at address 52 ; ; Display 3 component dataset beginning at address 50: ; a) <VERB> <0> <5> <NOUN> <0> <1> <ENTER> ; b) verb/noun display flashes; waiting for address ; c) <5> <0> <ENTER> ; d) octal word from address 50 is displayed in R1, ; octal word from address 51 is displayed in R2, ; octal word from address 52 is displayed in R3 ; ;-------------------------------------------------------------------------- ;-------------------------------------------------------------------------- ; COLOSSUS REGULAR VERBS (00-39 decimal) ; ; This is adapted from the Apollo 204 accident report posted on multiple ; web sites by Richard F. Drushel. The information has been changed as ; necessary to be consistent with usage in COLOSSUS. ; ; ; Verb | | ; Code | Description | Remarks ; | | ; 01 | Display octal comp 1 in R1 | Performs octal display of data on ; | | REGISTER 1. ; | | ; 02 | Display octal comp 2 in R2 | Performs octal display of data on

Page 452: Apollo Guidance Computer AGC

; | | REGISTER 1. ; | | ; 03 | Display octal comp 3 in R3 | Performs octal display of data on ; | | REGISTER 1. ; | | ; 04 | Display octal comp 1,2 | Performs octal display of data on ; | in R1,R2 | REGISTER 1 and REGISTER 2 ; | | ; 05 | Display octal comp 1,2,3 | Performs octal display of data on ; | in R1,R2,R3 | REGISTER 1, REGISTER 2, and REGISTER 3. ; | | ; 06 | Display decimal in R1 or | Performs decimal display of data on ; | R1,R2 or R1,R2,R3 | appropriate registers. The scale ; | | factors, types of scale factor ; | | routines, and component information ; | | are stored within the machine for each ; | | noun which it is required to display ; | | in decimal. ; | | ; 07 | Display DP decimal in R1,R2 | Performs a double precision decimal ; | | display of data on REGISTER 1 and ; | | REGISTER 2. It does no scale ; | | factoring. It merely performs a 10- ; | | character, fractional decimal ; | | conversion of two consecutive, erasable ; | | registers, using REGISTER 1 and ; | | REGISTER 2. The sign is placed in the ; | | REGISTER 1 sign position with the ; | | REGISTER 2 sign position remaining ; | | blank. It cannot be used with mixed ; | | nouns. Its intended use is primarily ; | | with "machine address to be specified" ; | | nouns. ; | | ; 08 | (Spare) | ; | | ; 09 | (Spare) | ; | | ; 10 | (Spare) | ; | | ; 11 | Monitor octal comp 1 in R1 | Performs octal display of updated data ; | | every 1/2 second on REGISTER 1. ; | | ; 12 | Monitor octal comp 2 in R2 | Performs octal display of updated data ; | | every 1/2 second on REGISTER 1. ; | | ; 13 | Monitor octal comp 3 in R3 | Performs octal display of updated data ; | | every 1/2 second on REGISTER 1. ; | | ; 14 | Monitor octal comp 1,2 | Performs octal display of updated data ; | in R1,R2 | every 1/2 second on REGISTER 1 and ; | | REGISTER 2. ; | | ; 15 | Monitor octal comp 1,2,3 | Performs octal display of updated data ; | in R1,R2,R3 | every 1/2 second on REGISTER 1, ; | | REGISTER 2, and REGISTER 3. ; | | ; 16 | Monitor decimal in R1 or | Performs decimal display of updated ; | R1,R2, or R1,R2,R3 | data every 1/2 second on appropriate ; | | registers. ; | | ; 17 | Monitor DP decimal in R1,R2 | Performs double precision display of ; | | decimal data on REGISTER 1 and ; | | REGISTER 2. No scale factoring is ; | | performed. Provides 10-character, ; | | fractional decimal conversion of two ; | | consecutive erasable registers. The ; | | sign is placed in the sign-bit ; | | position of REGISTER 1. REGISTER 2 ; | | sign bit is blank. ; | | ; 18 | (Spare) | ; | | ; 19 | (Spare) | ; | | ; 20 | (Spare) | ; | | ; 21 | Load component 1 into R1 | Performs data loading. Octal ; | | quantities are unsigned. Decimal ; | | quantities are preceded by + or - ; | | sign. Data is displayed on REGISTER ; | | 1. ; | | ; 22 | Load component 2 into R2 | Performs data loading. Octal ; | | quantities are unsigned. Decimal ; | | quantities are preceded by + or - ; | | sign. Data is displayed on REGISTER

Page 453: Apollo Guidance Computer AGC

; | | 2. ; | | ; 23 | Load component 3 into R3 | Performs data loading. Octal ; | | quantities are unsigned. Decimal ; | | quantities are preceded by + or - ; | | sign. Data is displayed on REGISTER ; | | 3. ; | | ; 24 | Load component 1,2 into | Performs data loading. Octal ; | R1,R2 | quantities are unsigned. Decimal ; | | quantities are preceded by + or - ; | | sign. Data is displayed on REGISTER ; | | 1 and REGISTER 2. ; | | ; 25 | Load component 1,2,3 into | Performs data loading. Octal ; | R1,R2,R3 | quantities are unsigned. Decimal ; | | quantities are preceded by + or - ; | | sign. Data is displayed on REGISTER ; | | 1, REGISTER 2, and REGISTER 3. ; | | ; 26 | (Spare) | ; | | ; 27 | Display fixed memory | This verb is included to permit ; | | displaying the contents of fixed ; | | memory in any bank. Its intended use ; | | is for checking program ropes and the ; | | BANK positions of program ropes. ; | | ; 28 | (Spare) | ; | | ; 29 | (Spare) | ; | | ; 30 | Request EXECUTIVE | Enters request to executive routine ; | (Used only during ground | for any machine address with priority ; | checkout.) | involved. This verb assumes that the ; | | desired priority has been loaded into ; | | bits 10-14 of the prio/delay register ; | | (noun 26). This verb is used with the ; | | noun, "machine address to be ; | | specified". The complete address of ; | | the desired location is then keyed in. ; | | (Refer to "Machine address to be ; | | specified" in paragraph on Verb/Noun ; | | Formats.) ; | | ; 31 | Request WAITLIST | Enters request to "waitlist routine" ; | (Used only during ground | for any machine address with delay ; | checkout.) | involved. This verb assumes that the ; | | desired number of 10-millisecond units ; | | of delay has been loaded into the low ; | | order bits of the prio/delay register ; | | (noun 26). This verb is used with the ; | | "machine address to be specified" noun. ; | | The complete address of the desired ; | | location is then keyed in. (Refer to ; | | "Machine address to be specified" in ; | | paragraph on Verb/Noun Formats.) ; | | ; 32 | Recycle | ; | | ; 33 | Proceed (without data) | Informs routine requesting data that ; | | the operator chooses not to load ; | | fresh data, but wishes the routine to ; | | continue as best it can with old data. ; | | Final decision for what action should ; | | be taken is left to the requesting ; | | routine. ; | | ; 34 | Terminate | Informs routine requesting data to be ; | | loaded that the operator chooses not ; | | to load fresh data and wishes the ; | | routine to terminate. Final decision ; | | for what action should be taken is ; | | left to the requesting routine. If ; | | monitor is on, it is turned off. ; | | ; 35 | Test lights | ; | | ; 36 | Request fresh start | Initializes the program control ; | | software and the keyboard and display ; | | system program. ; | | ; 37 | Change program (major mode) | Change to new major mode. (Refer to ; | | "Change major mode" in paragraph on ; | | Verb/Noun Formats.) ; | | ;--------------------------------------------------------------------------

Page 454: Apollo Guidance Computer AGC

;-------------------------------------------------------------------------- ; COLOSSUS EXTENDED VERBS (40-99 decimal) ; ; Not implemented. Use of these verbs triggers the 'check fail' indicator. ;-------------------------------------------------------------------------- ;-------------------------------------------------------------------------- ; COLOSSUS NORMAL NOUNS (00-39 decimal) ; ; This is adapted from the Apollo 204 accident report posted on multiple ; web sites by Richard F. Drushel. The information has been changed as ; necessary to be consistent with usage in COLOSSUS. ; ; ; Noun | | ; Code | Description | Scale/Units ; | | ; 01 | Specify machine address (frac) | .XXXXX FRAC ; | | .XXXXX FRAC ; | | .XXXXX FRAC ; | | ; 02 | Specify machine address (whole) | XXXXX INTEGER ; | | XXXXX INTEGER ; | | XXXXX INTEGER ; | | ; 03 | Specify machine address (degree) | XXX.XX DEG ; | | XXX.XX DEG ; | | XXX.XX DEG ; | | ; 04 | (Spare) | ; | | ; 05 | (Spare) | ; | | ; 06 | (Spare) | ; | | ; 07 | (Spare) | ; | | ; 08 | (Spare) | ; | | ; 09 | Alarm codes | OCT ; | | OCT ; | | OCT ; | | ; 10 | (Spare) | ; | | ; 11 | (Spare) | ; | | ; 12 | (Spare) | ; | | ; 13 | (Spare) | ; | | ; 14 | (Spare) | ; | | ; 15 | Increment address | OCT ; | | ; | | ; 16 | (Spare) | ; | | ; 17 | (Spare) | ; | | ; 18 | (Spare) | ; | | ; 19 | (Spare) | ; | | ; 20 | (Spare) | ; | | ; 21 | (Spare) | ; | | ; 22 | (Spare) | ; | | ; 23 | (Spare) | ; | | ; 24 | (Spare) | ; | | ; 25 | (Spare) | ; | | ; 26 | Prio/delay, address | OCT (prio/delay) ; | | OCT (14-bit CADR) ; | | (not used) ; | | ; 27 | (Spare) | ; | |

Page 455: Apollo Guidance Computer AGC

; 28 | (Spare) | ; | | ; 29 | (Spare) | ; | | ; 30 | (Spare) | ; | | ; 31 | (Spare) | ; | | ; 32 | (Spare) | ; | | ; 33 | (Spare) | ; | | ; 34 | (Spare) | ; | | ; 35 | (Spare) | ; | | ; 36 | Time of CMC clock: | ; | REGISTER 1 | 00XXX. hours ; | REGISTER 2 | 000XX. minutes ; | REGISTER 3 | 0XX.XX seconds ; | | ; 37 | (Spare) | ; | | ; 38 | (Spare) | ; | | ; 39 | (Spare) | ; | | ;-------------------------------------------------------------------------- ;-------------------------------------------------------------------------- ; COLOSSUS MIXED NOUNS (40-99 decimal) ; ; Not implemented. ;-------------------------------------------------------------------------- ;-------------------------------------------------------------------------- ; AGC ADDRESS ASSIGNMENTS ; ; Central Registers ; ; 000000 A accumulator ; 000001 Q subroutine return address ; 000002 Z program counter ; 000003 LP lower product register ; ; Input Registers ; ; 000004 IN0 ; 000005 IN1 ; 000006 IN2 ; 000007 IN3 ; ; Output Registers ; ; 000010 OUT0 ; 000011 OUT1 ; 000012 OUT2 ; 000013 OUT3 ; 000014 OUT4 ; ; Memory Bank Select ; ; 000015 BANK ; ; Interrupt Control ; ; 000016 RELINT re-enable interrupts ; 000017 INHINT inhibit interrupts ; ; Editing Registers ; ; 000020 CYR cycle right ; 000021 SR shift rRight ; 000022 CYL cycle left ; 000023 SL shift left ; ; Interrupt Storage Area ; ; 000024 ZRUPT save program counter (Z) ; 000025 BRUPT save B register ; 000026 ARUPT save accumulator (A) ; 000027 QRUPT save Q register ;

Page 456: Apollo Guidance Computer AGC

; 000030 - 000033 NOT USED ; ; Involuntary Counters ; ; 000034 OVCTR arithmetic overflow counter ; 000035 TIME2 AGC clock (high) ; 000036 TIME1 AGC clock (low) ; 000037 TIME3 WAITLIST (T3) timer ; 000040 TIME4 DISPLAY (T4) timer ; ; Involuntary Counters -- currently unused ; ; 000041 - 000056 NOT USED ; ; Eraseable Memory ; ; 000057 - 001777 ; ; Start of fixed memory ; ; 002000 GOPROG AGC (re)start vector ; ; 002004 T3RUPT interrupt vector for TIME3 (T3RUPT) ; 020010 ERRUPT interrupt vector ; 020014 DSRUPT interrupt vector for DSRUPT (T4RUPT) ; 020020 KEYRUPT interrupt vector for keyboard ; 020024 UPRUPT interrupt vector for uplink ;-------------------------------------------------------------------------- ;-------------------------------------------------------------------------- ; AGC TABLES (name, file, description) ; ; Keyboard/display ; CHARIN2 bank40_1.asm keyboard character table ; INRELTAB bank40_1.asm DSKY register/display table map ; DSPTAB dsky_e.asm display table for DSKY ; ; Verbs: ; VERBTAB bank41_1.asm regular verb routines (00-39) ; ; Nouns: ; NNADTAB bank42_3.asm noun address table (00-99) ; NNTYPTAB bank42_3.asm noun type table (00-99) ; SFINTAB bank42_3.asm noun input scale factor select ; SFOUTAB bank42_3.asm nout output scale factor select ; IDADDTAB bank42_3.asm mixed noun address table (40-99) ; RUTMXTAB bank42_3.asm mixed noun scale factor routine (40-99) ; ; Noun scale factor routines: ; SFOUTABR bank41_1.asm scale factor output routines ; SFINTABR bank41_2.asm scale factor input routines ; ; Major Modes: ; FCADRMM bank04_1.asm entry points for MM jobs ; EPREMM1 bank04_1,asm priorities for MM jobs ;-------------------------------------------------------------------------- ; ERASEABLE MEMORY DECLARATIONS ORG BANK0 ; immediately following counters INCL waitlist_e.asm ; WAITLIST variables ;========================================================================== ; WAITLIST (file:waitlist_e.asm) ; ; Version: 1.0 ; Author: John Pultorak ; Date: 11/15/2001 ; ; PURPOSE: ; Eraseable memory variables and structures for the WAITLIST. See the ; WAITLIST source code file for more information. ;========================================================================== MAXTASK EQU 7 ; max number of tasks MAXVAL EQU %037777 ; largest pos 15-bit int (+16383 dec) MAXDELAY EQU 12000 ; 120 seconds (in .01 sec ticks) MAXTIMEOUT EQU MAXVAL-MAXDELAY+1 ; TIME3 setting for MAXDELAY ; task delta t: number of 10 mSec ticks until timeout. ; i.e.: 0=timeout, 1=10mS until timeout, 2=20mS until timeout... ; maximum time delay is 120 (decimal) seconds. ;

Page 457: Apollo Guidance Computer AGC

; If a task record is empty (unused), the address is always set to ; zero and the time is set to MAXDELAY. ; task record structure TSKTIME EQU 0 ; offset to task delta time TSKADDR EQU 1 ; offset to 14-bit task address TRECSZ EQU 2 ; size of task record (words) ; Array of all task records WL_taskList EQU * 00057 0057 00000 1 DS 0 ; record 000060 0060 00000 1 DS 0 00061 0061 00000 1 DS 0 ; record 100062 0062 00000 1 DS 0 00063 0063 00000 1 DS 0 ; record 200064 0064 00000 1 DS 0 00065 0065 00000 1 DS 0 ; record 300066 0066 00000 1 DS 0 00067 0067 00000 1 DS 0 ; record 400070 0070 00000 1 DS 0 00071 0071 00000 1 DS 0 ; record 500072 0072 00000 1 DS 0 00073 0073 00000 1 DS 0 ; record 600074 0074 00000 1 DS 0 00075 0075 00000 1 WL_IN_saveQ DS 0 ; return address00076 0076 00000 1 WL_IN_taskPtr DS 0 ; points to task rec in list00077 0077 00000 1 WL_IN_loopCnt DS 0 ; loop counter 00100 0100 00000 1 WL_AT_saveQ DS 0 ; return address00101 0101 00000 1 WL_AT_taskPtr DS 0 ; points to task rec in list00102 0102 00000 1 WL_AT_newTime DS 0 ; time to be inserted00103 0103 00000 1 WL_AT_timeLeft DS 0 ; time remaining until timeout00104 0104 00000 1 WL_AT_loopCnt DS 0 ; loop counter 00105 0105 00000 1 WL_T3_saveQ DS 0 ; return address00106 0106 00000 1 WL_T3_oldBank DS 0 ; current bank 00107 0107 00000 1 WL_ST_saveQ DS 0 ; return address00110 0110 00000 1 WL_ST_taskPtr DS 0 ; points to task rec in list00111 0111 00000 1 WL_ST_newTime DS 0 ; time-out time00112 0112 00000 1 WL_ST_loopCnt DS 0 ; loop counter 00113 0113 00000 1 WL_RT_saveQ DS 0 ; return address00114 0114 00000 1 WL_RT_runAddr DS 0 ; address of task to run 00115 0115 00000 1 WL_RM_saveQ DS 0 ; return address00116 0116 00000 1 WL_RM_taskPtr DS 0 ; points to task rec in list00117 0117 00000 1 WL_RM_taskPtr2 DS 0 ; points to task rec behind taskPtr00120 0120 00000 1 WL_RM_loopCnt DS 0 ; loop counter00121 0121 00000 1 WL_RM_retval DS 0 ; tmp store for return value 00122 0122 00000 1 WL_IS_newTime DS 0 ; INPUT: time to be inserted00123 0123 00000 1 WL_IS_newAddr DS 0 ; INPUT: address to be inserted00124 0124 00000 1 WL_IS_saveQ DS 0 ; return address00125 0125 00000 1 WL_IS_taskPtr DS 0 ; points to task rec in list00126 0126 00000 1 WL_IS_taskPtr2 DS 0 ; points to task rec ahead of taskPtr00127 0127 00000 1 WL_IS_loopCnt DS 0 ; loop counter INCL exec_e.asm ; EXEC variables ;========================================================================== ; EXEC (file:exec_e.asm) ; ; Version: 1.0 ; Author: John Pultorak ; Date: 04/26/2002 ; ; PURPOSE: ; Eraseable memory variables and structures for the EXEX. See the EXEC ; source code file for more information. ; ; The COLOSSUS version of this is on p. 70. ; ; ERRATA: The current version of the EXEC does not set the BANKSET parameter. ; Instead, it stores the 14-bit CADR in LOC. Also, the JOBPRIOBASE field ; has been added. ;==========================================================================

Page 458: Apollo Guidance Computer AGC

MAXJOBS EQU 7 ; max number jobs (not incl current job) JRECSZ EQU 13 ; size of job record (words) ; (COLOSSUS, p. 70) ; dynamically allocated core sets for EXEC jobs (8 sets) ; record for current (running) job ; Job priority: 0=no job, 1=lowest priority job, 2=... EX_currentJob EQU * MPAC EQU * ; multi-purpose accumulator00130 0130 00000 1 DS 0 00131 0131 00000 1 DS 0 00132 0132 00000 1 DS 0 00133 0133 00000 1 DS 0 00134 0134 00000 1 DS 0 00135 0135 00000 1 DS 0 00136 0136 00000 1 DS 0 00137 0137 00000 1 MODE DS 0 ; +1 for TP, +0 for DP, or -1 for vector00140 0140 00000 1 LOC DS 0 ; location associated with job00141 0141 00000 1 BANKSET DS 0 ; usually contains bank setting00142 0142 00000 1 PUSHLOC DS 0 ; word of packed interpretive parameters00143 0143 00000 1 PRIORITY DS 0 ; priority of present job and work area00144 0144 00000 1 JOBPRIOBASE DS 0 ; nominal job priority ; records for additional jobs waiting to run JREC0 EQU * ORG JREC0+JRECSZ JREC1 EQU * ORG JREC1+JRECSZ JREC2 EQU * ORG JREC2+JRECSZ JREC3 EQU * ORG JREC3+JRECSZ JREC4 EQU * ORG JREC4+JRECSZ JREC5 EQU * ORG JREC5+JRECSZ JREC6 EQU * ORG JREC6+JRECSZ ; sorted list of jobs to run. The list is sorted by job priority ; with the highest priority job at the top of the list. Each ; entry on the list is a word index to a job record; the indexes are ; relative to 'EX_currentJob', but the current job is not on the ; list. EX_jobList EQU * ORG EX_jobList+MAXJOBS LOCCTR EQU EX_jobList ; index to next job record CHGJOB EQU 1 ; change jobs at next opportunity KEEPJOB EQU 0 ; keep the same job00307 0307 00000 1 newJob DS 0 ; change flag (set to CHGJOB or KEEPJOB) 00310 0310 00000 1 EX_JW_saveQ DS 0 ; return address00311 0311 00000 1 EX_JW_loopCnt DS 0 ; loop counter00312 0312 00000 1 EX_JW_CADR DS 0 ; address of job to wake00313 0313 00000 1 EX_JW_foundit DS 0 ; 0=job not found, 1=found00314 0314 00000 1 EX_JW_jobPtr DS 0 ; points to job rec in list00315 0315 00000 1 EX_JW_jobPtr2 DS 0 ; points to job rec ahead of jobPtr00316 0316 00000 1 EX_JW_fndIndx DS 0 ; index to awoken record 00317 0317 00000 1 EX_AJ_saveQ DS 0 ; return address00320 0320 00000 1 EX_AJ_loopCnt DS 0 ; loop counter00321 0321 00000 1 EX_AJ_jobPrio DS 0 ; priority of new job00322 0322 00000 1 EX_AJ_jobPtr DS 0 ; initialized to EX_jobList at startup00323 0323 00000 1 EX_AJ_field DS 0 ; index to field from start of record00324 0324 00000 1 EX_AJ_findx DS 0 ; total index to field

Page 459: Apollo Guidance Computer AGC

00325 0325 00000 1 EX_IN_saveQ DS 0 ; return address00326 0326 00000 1 EX_IN_loopCnt DS 0 ; loop counter00327 0327 00000 1 EX_IN_jobPtr DS 0 ; points to job rec in list00330 0330 00000 1 EX_IN_recIndex DS 0 ; record index init counter00331 0331 00000 1 EX_IN_field DS 0 ; index to field from start of record00332 0332 00000 1 EX_IN_findx DS 0 ; total index to field 00333 0333 00000 1 EX_MN_runAddr DS 0 ; address of job to run00334 0334 00000 1 EX_MN_field DS 0 ; index to field from start of record00335 0335 00000 1 EX_MN_findx DS 0 ; total index to field 00336 0336 00000 1 EX_RM_saveQ DS 0 ; return address00337 0337 00000 1 EX_RM_jobPtr DS 0 ; points to job rec in list00340 0340 00000 1 EX_RM_jobPtr2 DS 0 ; points to job rec behind jobPtr00341 0341 00000 1 EX_RM_savePtr DS 0 ; tmp store for index taken off list00342 0342 00000 1 EX_RM_loopCnt DS 0 ; loop counter00343 0343 00000 1 EX_RM_retval DS 0 ; tmp store for return value00344 0344 00000 1 EX_RM_field DS 0 ; index to field from start of record00345 0345 00000 1 EX_RM_findx DS 0 ; total index to field 00346 0346 00000 1 EX_IS_newPrio DS 0 ; INPUT: priority to be inserted00347 0347 00000 1 EX_IS_newPrioB DS 0 ; INPUT: nominal priority to be inserted00350 0350 00000 1 EX_IS_newLoc DS 0 ; INPUT: address to be inserted00351 0351 00000 1 EX_IS_saveQ DS 0 ; return address00352 0352 00000 1 EX_IS_jobPtr DS 0 ; points to job rec in list00353 0353 00000 1 EX_IS_jobPtr2 DS 0 ; points to job rec ahead of jobPtr00354 0354 00000 1 EX_IS_loopCnt DS 0 ; loop counter INCL dsky_e.asm ; DSKY variables ;========================================================================== ; DSKY (file:dsky_e.asm) ; ; Version: 1.0 ; Author: John Pultorak ; Date: 12/14/2001 ; ; PURPOSE: ; Eraseable memory variables and structures for the DSKY. See the EXEC ; source code file for more information. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968. ;========================================================================== 00355 0355 00000 1 FLAGWRD5 DS 0 ; GENERAL ERASABLE ASSIGNMENTS ; (COLOSSUS, p. 66) ; interrupt temporary storage pool ; (ITEMP1 through RUPTREG4) 00356 0356 00000 1 ITEMP1 DS 0 WAITEXIT EQU ITEMP1 EXECTEM1 EQU ITEMP1 00357 0357 00000 1 ITEMP2 DS 0 WAITBANK EQU ITEMP2 EXECTEM2 EQU ITEMP2 00360 0360 00000 1 ITEMP3 DS 0 RUPTSTOR EQU ITEMP3 WAITADR EQU ITEMP3 NEWPRIO EQU ITEMP3 00361 0361 00000 1 ITEMP4 DS 0 ;LOCCTR EQU ITEMP4 ; moved to EXEC WAITTEMP EQU ITEMP4 00362 0362 00000 1 ITEMP5 DS 0 NEWLOC EQU ITEMP5 00363 0363 00000 1 ITEMP6 DS 0 NEWLOCP1 EQU ITEMP6 ; DP address 00364 0364 00000 1 NEWJOB DS 0 ; COLOSSUS: must be at loc 68 due to wiring00365 0365 00000 1 RUPTREG1 DS 0 00366 0366 00000 1 RUPTREG2 DS 0 00367 0367 00000 1 RUPTREG3 DS 0 00370 0370 00000 1 RUPTREG4 DS 0 KEYTEMP1 EQU RUPTREG4 DSRUPTEM EQU RUPTREG4 ; FLAGWORD reservations

Page 460: Apollo Guidance Computer AGC

STATE EQU * ; 12 words00371 0371 00000 1 DS 0 00372 0372 00000 1 DS 0 00373 0373 00000 1 DS 0 00374 0374 00000 1 DS 0 00375 0375 00000 1 DS 0 00376 0376 00000 1 DS 0 00377 0377 00000 1 DS 0 00400 0400 00000 1 DS 0 00401 0401 00000 1 DS 0 00402 0402 00000 1 DS 0 00403 0403 00000 1 DS 0 00404 0404 00000 1 DS 0 FLAGFILL EQU * ; space for future flags00405 0405 00000 1 DS 0 00406 0406 00000 1 DS 0 00407 0407 00000 1 DS 0 00410 0410 00000 1 DS 0 ; pad load for DAPs ; (COLOSSUS, p. 67) EMDOT EQU FLAGFILL ; exit for VB3 STATEXIT EQU FLAGFILL+2 ; EXEC temporaries which may be used between CCS NEWJOBS. ; (INTB15P through RUPTMXM) 00411 0411 00000 1 INTB15P DS 0 ; reflects 15th bit of indexable addresses DSEXIT EQU INTB15P ; return for DSPIN EXITEM EQU INTB15P ; return for scale factor routine select BLANKRET EQU INTB15P ; return for 2BLANK 00412 0412 00000 1 INTBIT15 DS 0 ; similar to above WRDRET EQU INTBIT15 ; return for 5BLANK WDRET EQU INTBIT15 ; return for DSPWD DECRET EQU INTBIT15 ; return for PUTCOM (dec load) _2122REG EQU INTBIT15 ; temp for CHARIN ; The registers between ADDRWD and PRIORITY must stay in the following order ; for interpretive trace. 00413 0413 00000 1 ADDRWD DS 0 ; 12 bit interpretive operand subaddress00414 0414 00000 1 POLISH DS 0 ; holds CADR made from POLISH address UPDATRET EQU POLISH ; return for UPDATNN, UPDATVB CHAR EQU POLISH ; temp for CHARIN ERCNT EQU POLISH ; counter for error light reset DECOUNT EQU POLISH ; counter for scaling and display (dec) 00415 0415 00000 1 FIXLOC DS 0 ; work area address00416 0416 00000 1 OVFIND DS 0 ; set non-zero on overflow VBUF EQU * ; temporary storage used for vectors00417 0417 00000 1 DS 0 00420 0420 00000 1 DS 0 00421 0421 00000 1 DS 0 00422 0422 00000 1 DS 0 00423 0423 00000 1 DS 0 00424 0424 00000 1 DS 0 SGNON EQU VBUF ; temp for +,- on NOUNTEM EQU VBUF ; counter for MIXNOUN fetch DISTEM EQU VBUF ; counter for octal display verbs DECTEM EQU VBUF ; counter for fetch (dec display verbs) SGNOFF EQU VBUF+1 ; temp for +,- off NVTEMP EQU VBUF+1 ; temp for NVSUB SFTEMP1 EQU VBUF+1 ; storage for SF const hi part(=SFTEMP2-1) HITEMIN EQU VBUF+1 ; temp for load of hrs, min, sec ; must = LOWTEMIN-1 CODE EQU VBUF+2 ; for DSPIN SFTEMP2 EQU VBUF+2 ; storage for SF const low part(=SFTEMP1+1) LOWTEMIN EQU VBUF+2 ; temp for load of hrs, min, sec ; must = HITEMIN+1 ; (COLOSSUS, p. 68) MIXTEMP EQU VBUF+3 ; for MIXNOUN data SIGNRET EQU VBUF+3 ; return for +,- on ; Also, MIXTEMP+1 = VBUF+4, MIXTEMP+2 = VBUF+5 BUF EQU * ; temporary scalar storage

Page 461: Apollo Guidance Computer AGC

00425 0425 00000 1 DS 0 00426 0426 00000 1 DS 0 00427 0427 00000 1 DS 0 00430 0430 00000 1 BUF2 DS 0 00431 0431 00000 1 DS 0 INDEXLOC EQU BUF ; contains address of specified index SWWORD EQU BUF ; address of switch word SWBIT EQU BUF+1 ; switch bit within switch word00432 0432 00000 1 MPTEMP DS 0 ; temporary used in multiply and shift DMPNTEMP EQU MPTEMP ; DMPSUB temporary00433 0433 00000 1 DOTINC DS 0 ; component increment for DOT subroutine DVSIGN EQU DOTINC ; determines sign of DDV result ESCAPE EQU DOTINC ; used in arcsin/arccos ENTRET EQU DOTINC ; exit from enter 00434 0434 00000 1 DOTRET DS 0 ; return from DOT subroutine DVNORMCT EQU DOTRET ; dividend normalization count in DDV ESCAPE2 EQU DOTRET ; alternate arcsin/arccos switch WDCNT EQU DOTRET ; char counter for DSPWD INREL EQU DOTRET ; input buffer selector (X,Y,Z REG) 00435 0435 00000 1 MATINC DS 0 ; vector increment in MXV and VXM MAXDVSW EQU MATINC ; +0 if DP quotient is near one - else -1 POLYCNT EQU MATINC ; polynomial loop counter DSPMMTEM EQU MATINC ; DSPCOUNT save for DSPMM MIXBR EQU MATINC ; indicator for mixed or normal noun 00436 0436 00000 1 TEM1 DS 0 ; EXEC temp POLYRET EQU TEM1 DSREL EQU TEM1 ; rel address for DSPIN 00437 0437 00000 1 TEM2 DS 0 ; EXEC temp DSMAG EQU TEM2 ; magnitude store for DSPIN IDADDTEM EQU TEM2 ; mixnoun indirect address store 00440 0440 00000 1 TEM3 DS 0 ; EXEC temp COUNT EQU TEM3 ; for DSPIN 00441 0441 00000 1 TEM4 DS 0 ; EXEC temp LSTPTR EQU TEM4 ; list pointer for GRABUSY RELRET EQU TEM4 ; return for RELDSP FREERET EQU TEM4 ; return for FREEDSP DSPWDRET EQU TEM4 ; return for DSPSIGN SEPSCRET EQU TEM4 ; return for SEPSEC SEPMNRET EQU TEM4 ; return for SEPMIN 00442 0442 00000 1 TEM5 DS 0 ; EXEC temp NOUNADD EQU TEM5 ; temp storage for noun address ; (COLOSSUS, p. 69) 00443 0443 00000 1 NNADTEM DS 0 ; temp for noun address table entry00444 0444 00000 1 NNTYPTEM DS 0 ; temp for noun type table entry00445 0445 00000 1 IDAD1TEM DS 0 ; temp for indir address table entry (MIXNN) ; must - IDAD2TEM-1, = IDAD3TEM-200446 0446 00000 1 IDAD2TEM DS 0 ; temp for indir address table entry (MIXNN) ; must - IDAD2TEM+1, = IDAD3TEM-100447 0447 00000 1 IDAD3TEM DS 0 ; temp for indir address table entry (MIXNN) ; must - IDAD1TEM+2, = IDAD2TEM+100450 0450 00000 1 RUTMXTEM DS 0 ; temp for SF rout table entry (MIXNN only) ; AX*SR*T storage DEXDEX EQU TEM2 ; B(1) tmp DEX1 EQU TEM3 ; B(1) tmp DEX2 EQU TEM4 ; B(1) tmp RTNSAVER EQU TEM5 ; B(1) tmp TERM1TMP EQU BUF2 ; B(2) tmp ; (COLOSSUS, p. 70) Note: the eraseable memory for the EXEC. ; Moved to the EXEC area ; (COLOSSUS, p. 72) ; unswitched for display interface routines 00451 0451 00000 1 RESTREG DS 0 ; B(1) prm for display starts00452 0452 00000 1 NVWORD DS 0 00453 0453 00000 1 MARXNV DS 0 00454 0454 00000 1 NVSAVE DS 0 ; (retain the order of CADRFLSH to FAILREG+2 for downlink purposes)00455 0455 00000 1 CADRFLSH DS 0 ; B(1) tmp00456 0456 00000 1 CADRMARK DS 0 ; B(1) tmp

Page 462: Apollo Guidance Computer AGC

00457 0457 00000 1 TEMPFLSH DS 0 ; B(1) tmp 00460 0460 00000 1 FAILREG DS 0 ; B(3) prm 3 alarm-abort user=S 2CADR00461 0461 00000 1 DS 0 00462 0462 00000 1 DS 0 ; (COLOSSUS, p. 73) ; verb 37 storage 00463 0463 00000 1 MINDEX DS 0 ; B(1) tmp index for major mode00464 0464 00000 1 MMNUMBER DS 0 ; B(1) tmp major mode requested via V37 ; pinball interrupt storage 00465 0465 00000 1 DSPCNT DS 0 ; B(1) prm DSPOUT counter ; pinball executive action 00466 0466 00000 1 DSPCOUNT DS 0 ; display position indicator00467 0467 00000 1 DECBRNCH DS 0 ; Bits2,1: octal=0, +dec=1, -dec=2 ; Bit5=R1 (dec), Bit4=R2 (dec), Bit3=R3 (dec)00470 0470 00000 1 VERBREG DS 0 ; verb code00471 0471 00000 1 NOUNREG DS 0 ; noun code00472 0472 00000 1 XREG DS 0 ; R1 input buffer00473 0473 00000 1 YREG DS 0 ; R2 input buffer00474 0474 00000 1 ZREG DS 0 ; R3 input buffer00475 0475 00000 1 XREGLP DS 0 ; low part of XREG (for ded conv only)00476 0476 00000 1 YREGLP DS 0 ; low part of YREG (for ded conv only) HITEMOUT EQU YREGLP ; temp for display of HRS, MIN, SEC ; must equal LOTEMOUT-100477 0477 00000 1 ZREGLP DS 0 ; low part of ZREG (for ded conv only) LOTEMOUT EQU ZREGLP ; temp for display of HRS, MIN, SEC ; must equal HITEMOUT+1 ; (COLOSSUS, p. 74) 00500 0500 00000 1 MODREG DS 0 ; mode code00501 0501 00000 1 DSPLOCK DS 0 ; keyboard/subroutine call interlock00502 0502 00000 1 REQRET DS 0 ; return register for load00503 0503 00000 1 LOADSTAT DS 0 ; status indicator for LOADTST00504 0504 00000 1 CLPASS DS 0 ; pass indicator clear00505 0505 00000 1 NOUT DS 0 ; activity counter for DSPTAB00506 0506 00000 1 NOUNCADR DS 0 ; machine CADR for noun00507 0507 00000 1 MONSAVE DS 0 ; N/V code for monitor (= MONSAVE1 - 1)00510 0510 00000 1 MONSAVE1 DS 0 ; NOUNCADR for monitor (MATBS) = MONSAVE + 100511 0511 00000 1 MONSAVE2 DS 0 ; NVMONOPT options ; The 11 register table for the display panel (COLOSSUS, p.74, p.306) ; comment key = RELADD: RELAYWD BIT11 BITS10-6 BITS5-1 DSPTAB EQU * 00512 0512 00000 1 DS 0 ; 0: 0001 -R3 R3D4( 1) R3D5( 0)00513 0513 00000 1 DS 0 ; 1: 0010 +R3 R3D2( 3) R3D3( 2)00514 0514 00000 1 DS 0 ; 2: 0011 --- R2D5( 5) R3D1( 4)00515 0515 00000 1 DS 0 ; 3: 0100 -R2 R2D3( 7) R2D4( 6)00516 0516 00000 1 DS 0 ; 4: 0101 +R2 R2D1(11) R2D2(10)00517 0517 00000 1 DS 0 ; 5: 0110 -R1 R1D4(13) R1D5(12)00520 0520 00000 1 DS 0 ; 6: 0111 +R1 R1D2(15) R1D3(14)00521 0521 00000 1 DS 0 ; 7: 1000 --- -------- R1D1(16)00522 0522 00000 1 DS 0 ; 8: 1001 --- ND1 (21) ND2 (20)00523 0523 00000 1 DS 0 ; 9: 1010 --- VD1 (23) VD2 (22)00524 0524 00000 1 DS 0 ; 10:1011 --- MD1 (25) MD1 (24)00525 0525 00000 1 DS 0 ; 11: C/S lights 00526 0526 00000 1 NVQTEM DS 0 ; NVSUB storage for calling address ; must = NVBNKTEM-100527 0527 00000 1 NVBNKTEM DS 0 ; NVSUB storage for calling bank ; must = NVQTEM+100530 0530 00000 1 VERBSAVE DS 0 ; needed for recycle00531 0531 00000 1 CADRSTOR DS 0 ; ENDIDLE storage00532 0532 00000 1 DSPLIST DS 0 ; waiting reg for DSP syst internal use00533 0533 00000 1 EXTVRACT DS 0 ; extended verb activity interlock 00534 0534 00000 1 DSPTEM1 DS 0 ; buffer storage area 1 (mostly for time)00535 0535 00000 1 DS 0 00536 0536 00000 1 DS 0 00537 0537 00000 1 DSPTEM2 DS 0 ; buffer storage area 2 (mostly for deg)00540 0540 00000 1 DS 0 00541 0541 00000 1 DS 0 DSPTEMX EQU DSPTEM2 ; B(2) S-S display buffer for external verbs NORMTEM1 EQU DSPTEM1 ; B(3) DSP normal display registers ; display for extended verbs OPTIONX EQU DSPTEMX ; B(2) extended verb option code N12(VB2)

Page 463: Apollo Guidance Computer AGC

; temp store for major mode change 00542 0542 00000 1 MMTEMP DS 0 ; T4RUPT Erasable 00543 0543 00000 1 DSRUPTSW DS 0 ; (COLOSSUS, p. 78)00544 0544 00000 1 T4RET DS 0 ; added, not part of COLOSSUS00545 0545 00000 1 DSPOUTRET DS 0 ; added, not part of COLOSSUS00546 0546 00000 1 DK_IN_saveQ DS 0 ; return for T4RUPT init ; Replacement for Block II LXCH instruction (not part of COLOSSUS) 00547 0547 00000 1 LXCH_LPRET DS 0 ; LP return address00550 0550 00000 1 LXCH_A DS 0 ; save A ; vars for KEYPROG 00551 0551 00000 1 KP_MPAC DS 0 ; Vars for DPTEST (not part of COLOSSUS) 00552 0552 00000 1 DPTEST_A DS 0 00553 0553 00000 1 DPTEST_Q DS 0 ; Vars for REQDATX, REQDATY, REQDATZ (not part of COLOSSUS) 00554 0554 00000 1 REQ_Q DS 0 ; Vars for SETNCADR (not part of COLOSSUS) 00555 0555 00000 1 SETNCADR_Q DS 0 ; Vars for ALLDC_OC (not part of COLOSSUS) 00556 0556 00000 1 ALLDC_OC_Q DS 0 ; Vars for SFRUTMIX (not part of COLOSSUS) 00557 0557 00000 1 SFRUTMIX_L DS 0 ; Vars for SFCONUM (not part of COLOSSUS) 00560 0560 00000 1 SFCONUM_L DS 0 ; vars for BLANKSUB (not part of COLOSSUS) 00561 0561 00000 1 BLANKSUB_Q DS 0 ; Vars for GTSFOUT, GTSFIN (not part of COLOSSUS) 00562 0562 00000 1 GTSF_RET DS 0 ; Vars for FIXRANGE (not part of COLOSSUS) 00563 0563 00000 1 FR_RETQ DS 0 ; Vars for NVSUB (not part of COLOSSUS) 00564 0564 00000 1 NVSUB_L DS 0 00565 0565 00000 1 NVSUB_A DS 0 ; Vars for ENDIDLE (not part of COLOSSUS) 00566 0566 00000 1 ENDIDLE_L DS 0 ; Vars for NVSUBUSY (not part of COLOSSUS) 00567 0567 00000 1 NBSUBSY1_L DS 0 ; Vars for FLASHON/FLASHOFF (not part of COLOSSUS) 00570 0570 00000 1 FLASHRET DS 0 ; vars for PASTEVB (not part of COLOSSUS) 00571 0571 00000 1 PASTE_TMP DS 0

Page 464: Apollo Guidance Computer AGC

; vars for NEWMODEA (not part of COLOSSUS) 00572 0572 00000 1 NEWMODEA_Q DS 0 ; Vars for MATH LIB (not part of COLOSSUS) 00573 0573 00000 1 SHORTMP_A DS 0 00574 0574 00000 1 SHORTMP_OVFL DS 0 00575 0575 00000 1 SHORTMP_OVFH DS 0 00576 0576 00000 1 ADDRWD1 DS 0 00577 0577 00000 1 MATH_Q DS 0 00600 0600 00000 1 PRSHRTMP_Q DS 0 ; KEYRUPT Eraseable 00601 0601 00000 1 KEYRET DS 0 ; added, not part of COLOSSUS 00602 0602 00000 1 SAVEQ DS 0 ; temp for return addr ; Bank intercommunication 00603 0603 00000 1 BJBANK DS 0 00604 0604 00000 1 BJRET DS 0 00605 0605 00000 1 PJBANK DS 0 00606 0606 00000 1 PJRET DS 0 00607 0607 00000 1 PJA DS 0 00610 0610 00000 1 BCBANK DS 0 00611 0611 00000 1 BCRET DS 0 00612 0612 00000 1 BCA DS 0 00613 0613 00000 1 MBCBANK DS 0 00614 0614 00000 1 MBCRET DS 0 00615 0615 00000 1 MBCA DS 0 00616 0616 00000 1 DCBANK DS 0 00617 0617 00000 1 DCRET DS 0 ; FIXED MEMORY DECLARATIONS ORG EXTENDER 05777 5777 47777 0 DS %47777 ; needed for EXTEND ;-------------------------------------------------------------------------- ; RESTART/INTERRUPT ENTRY POINTS ;-------------------------------------------------------------------------- ; Program (re)start ORG GOPROG 02000 2000 0 1,2126 0 TC goMAIN ; AGC (re)start begins here! ; Interrupt vectors ORG T3RUPT 02004 2004 5 0,0026 0 TS ARUPT ; TIME3 interrupt vector02005 2005 3 0,0001 0 XCH Q 02006 2006 5 0,0027 1 TS QRUPT 02007 2007 0 1,2034 1 TC goT3 ORG ERRUPT 02010 2010 5 0,0026 0 TS ARUPT 02011 2011 3 0,0001 0 XCH Q 02012 2012 5 0,0027 1 TS QRUPT 02013 2013 0 1,2036 0 TC goER ORG DSRUPT ; T4RUPT for DSKY display02014 2014 5 0,0026 0 TS ARUPT 02015 2015 3 0,0001 0 XCH Q 02016 2016 5 0,0027 1 TS QRUPT 02017 2017 0 1,2037 1 TC goDS ORG KEYRUPT ; DSKY keyboard interrupt vector02020 2020 5 0,0026 0 TS ARUPT 02021 2021 3 0,0001 0 XCH Q 02022 2022 5 0,0027 1 TS QRUPT 02023 2023 0 1,2041 0 TC goKEY ORG UPRUPT 02024 2024 5 0,0026 0 TS ARUPT 02025 2025 3 0,0001 0 XCH Q 02026 2026 5 0,0027 1 TS QRUPT 02027 2027 0 1,2043 1 TC goUP

Page 465: Apollo Guidance Computer AGC

; restore Q and A registers and resume endRUPT EQU * 02030 2030 3 0,0027 1 XCH QRUPT ; restore Q02031 2031 5 0,0001 0 TS Q 02032 2032 3 0,0026 0 XCH ARUPT ; restore A02033 2033 2 0,0000 1 RESUME ; resume normal program execution ;-------------------------------------------------------------------------- ; RUPT (INTERRUPT) SERVICE ROUTINES ; ; Upon entry, registers will contain these values: ; - ZRUPT: Prior contents of program counter (Z register). ; - BRUPT: Prior contents of B register. ; - ARUPT: Prior contents of accumulator (A register). ; - QRUPT: Prior contents of Q register. ; ; When the service routine is finished, jump to endRUPT to restore the A ; and Q registers. Call RESUME to restore Z and B, which causes a return ; to normal (non-interrupt) execution. Interrupts are disabled upon entry ; to the service routine; they are reenabled following RESUME. ;-------------------------------------------------------------------------- goT3 EQU * 02034 2034 0 1,2347 0 TCR WL_TIME3task ; handle T3RUPT for WAITLIST02035 2035 0 1,2030 0 TC endRUPT goER EQU * 02036 2036 0 1,2030 0 TC endRUPT goDS EQU * 02037 2037 0 2,4047 0 TCR T4PROG ; handle T4RUPT for DSKY display02040 2040 0 1,2030 0 TC endRUPT goKEY EQU * 02041 2041 0 2,4132 0 TCR KEYPROG ; handle keyrupt for keyboard entry02042 2042 0 1,2030 0 TC endRUPT goUP EQU * 02043 2043 0 1,2030 0 TC endRUPT ;-------------------------------------------------------------------------- ; FIXED MEMORY CONSTANTS ;-------------------------------------------------------------------------- 02044 2044 00200 0 ofbit DS %200 ; OUT1, bit 8 initiates standby 02045 2045 77777 0 NEG0 DS -0 02046 2046 77776 1 NEG1 DS -1 02047 2047 77775 1 NEG2 DS -2 02050 2050 00000 1 ZERO DS 0 02051 2051 00001 0 ONE DS 1 02052 2052 00002 0 TWO DS 2 02053 2053 00003 1 THREE DS 3 02054 2054 00004 0 FOUR DS 4 02055 2055 00005 1 FIVE DS 5 02056 2056 00006 1 SIX DS 6 02057 2057 00007 0 SEVEN DS 7 02060 2060 00012 1 TEN DS 10 02061 2061 00013 0 ELEVEN DS 11 ; must be in reverse order. Pinball treats this as a table ; and indexes thru it. 02062 2062 40000 0 BIT15 DS %40000 02063 2063 20000 0 BIT14 DS %20000 02064 2064 10000 0 BIT13 DS %10000 02065 2065 04000 0 BIT12 DS %04000 02066 2066 02000 0 BIT11 DS %02000 02067 2067 01000 0 BIT10 DS %01000 02070 2070 00400 0 BIT9 DS %00400 02071 2071 00200 0 BIT8 DS %00200 02072 2072 00100 0 BIT7 DS %00100 02073 2073 00040 0 BIT6 DS %00040 02074 2074 00020 0 BIT5 DS %00020 02075 2075 00010 0 BIT4 DS %00010 02076 2076 00004 0 BIT3 DS %00004 02077 2077 00002 0 BIT2 DS %00002 02100 2100 00001 0 BIT1 DS %00001 02101 2101 00177 0 LOW7 DS %00177 02102 2102 06000 1 bankAddr DS %6000 ; fixed-switchable addr range starts here02103 2103 01777 1 lowAddr DS %1777 ; mask for 10-bit address02104 2104 01400 1 OCT1400 DS %1400

Page 466: Apollo Guidance Computer AGC

02105 2105 00013 0 NOUTCON DS 11 02106 2106 37777 1 POSMAX DS %37777 ;------------------------------------------------------------------------- ; CLRMEM - INITIALIZE ERASEABLE MEMORY ; ; Uses QRUPT and ARUPT as scratchpad. This is OK, because interrupts ; are disabled anyway. All eraseable memory above the AGC clock (TIME1, ; TIME2) is cleared. The AGC clock is not cleared because this might ; be a restart or a startup from standby mode. ;------------------------------------------------------------------------- CLRMEM EQU * 02107 2107 3 0,0001 0 XCH Q 02110 2110 5 0,0027 1 TS QRUPT ; save return address 02111 2111 3 1,2123 0 XCH CLRMEM_WC ; init count of words to clear02112 2112 5 0,0026 0 TS ARUPT CLRMEM_CHK EQU * 02113 2113 1 0,0026 1 CCS ARUPT 02114 2114 0 1,2116 0 TC CLRMEM_WORD 02115 2115 0 0,0027 1 TC QRUPT ; return CLRMEM_WORD EQU * 02116 2116 5 0,0026 0 TS ARUPT 02117 2117 3 1,2050 0 CAF CLRMEM_VAL 02120 2120 2 0,0026 1 INDEX ARUPT 02121 2121 5 0,0037 0 TS CLRMEM_BADDR ; clear a word02122 2122 0 1,2113 0 TC CLRMEM_CHK ; done? CLRMEM_VAL EQU ZERO ; set memory to this value CLRMEM_BADDR EQU TIME3 ; base address to clear02123 2123 01741 1 CLRMEM_WC DS %1777-TIME3+1 ; clear everything >= TIME3 ;------------------------------------------------------------------------- ; FRESH START ; ; AGC starts executing here, following power-up, or restart. ;------------------------------------------------------------------------- 02124 2124 10000 0 V37BANK DS %10000 ; BANK (4) containg PREMM1, FCADRMM102125 2125 37600 0 SAMASK DS %37600 ; mask to zero lower 7 bits goMAIN EQU * SLAP1 EQU goMAIN ; entry for V36 (fresh start request) 02126 2126 2 0,0000 0 INHINT ; First, check for standby operation. Loosely based on the standby ; algorithm in R-393. Probably should flash the 'computer activity' ; light as well. 02127 2127 3 1,2071 0 CAF BIT8 ; add 2 to 7th power to AGC clock02130 2130 6 0,0036 1 AD TIME1 02131 2131 5 0,0036 1 TS TIME1 02132 2132 3 1,2050 0 CAF ZERO ; skipped on ovf and C(A) set to 102133 2133 6 0,0035 1 AD TIME2 ; bump TIME2 with overflow, if any02134 2134 5 0,0035 1 TS TIME2 02135 2135 3 1,2125 0 CAF SAMASK ; zero the LSBs of TIME102136 2136 7 0,0036 0 MASK TIME1 02137 2137 5 0,0036 1 TS TIME1 02140 2140 3 1,2044 0 XCH ofbit ; enable standby operation02141 2141 5 0,0011 1 TS OUT1 02142 2142 0 1,2107 0 TC CLRMEM ; clear everything but the AGC clock ; set fresh start major mode to P00 (AGC CMC idle) 02143 2143 3 1,2124 1 CAF V37BANK 02144 2144 5 0,0015 0 TS BANK ; bank for major mode tables 02145 2145 3 4,6046 0 CAF NOV37MM ; assumes BANK is set (above)02146 2146 5 0,0463 0 TS MINDEX ; index to P00 goMMchange EQU * 02147 2147 2 0,0000 0 INHINT ; inhibit interrupts ; Initialize WAITLIST and EXEC eraseable memory. Initialize DSKY eraseable

Page 467: Apollo Guidance Computer AGC

; memory (but don't initialize BANK or MINDEX; they are used to start the ; main job for this major mode. 02150 2150 0 1,3252 1 TCR EX_initEX ; initialize EXEC02151 2151 0 1,2204 0 TCR WL_initWL ; initialize WAITLIST02152 2152 0 2,4007 1 TCR DK_initDK ; initialize DSKY ; Start the major mode job. This is modified from COLOSSUS because block I ; doesn't have E-bank and my SPVAC interface is a little different from the ; original. The references to PREMM1 and FCADRMM1 assume that the BANK is ; set to the one containing those tables. V37XEQ EQU * 02153 2153 2 0,0000 0 INHINT 02154 2154 2 0,0463 1 INDEX MINDEX 02155 2155 3 4,6037 0 CAF PREMM1 02156 2156 5 0,0542 1 TS MMTEMP 02157 2157 7 2,4666 1 MASK HI5 ; obtain priority bits 15-1102160 2160 0 2,4640 1 TC RIGHT5 02161 2161 0 2,4640 1 TC RIGHT5 ; shift right to bits 5-102162 2162 5 0,0360 1 TS NEWPRIO ; store PRIO for SPVAC 02163 2163 2 0,0463 1 INDEX MINDEX 02164 2164 3 4,6030 1 CAF FCADRMM1 02165 2165 0 1,3075 0 TC SPVAC ; job CADR in C(A), job prio in NEWPRIO V37XEQC EQU * 02166 2166 3 1,2050 0 CAF ZERO ; was CA MMTEMP in Block II02167 2167 6 0,0542 1 AD MMTEMP ; upon return from FINDVAC, place the02170 2170 7 1,2101 1 MASK LOW7 ; new MM in MODREG (the low 7 bits of02171 2171 0 2,5036 1 TC NEWMODEA ; PHSERDT1) 02172 2172 0 2,5003 1 TC RELDSP ; release display ; Start the EXEC. 02173 2173 0 1,2656 0 TC EX_exec ; never returns ;------------------------------------------------------------------------- ; AGC LIBRARIES ; ; System services in fixed-fixed memory. ;------------------------------------------------------------------------- INCL waitlist_f.asm ; WAITLIST, incl. T3RUPT handler ;========================================================================== ; WAITLIST (file:waitlist_f.asm) ; ; Version: 1.0 ; Author: John Pultorak ; Date: 11/15/2001 ; ; PURPOSE: ; Constants and source code for WAITLIST. ; ; Non-preemptive interrupt timer routines, originally implemented by J. H. ; Laning, Jr. for AGC3 and later adapted for AGC4. Briefly discussed in ; R-393, which gives some of the software interfaces into the WAITLIST. ; This is my own recreation, and the internals may differ from the original. ; ; A task is scheduled for execution by calling 'WAITLIST' and ; furnishing the time-out time and starting address. ; L XCH TASK_TIMEOUT ; in 10 mSec ticks ; L+1 TC WAITLIST ; L+2 DS TASK_ADDRESS ; 14-bit address ; L+3 ... execution resumes here ; ; TASK_TIMEOUT = a positive integer from 1 - MAXDELAY that specifies the delay ; in 10 mSec ticks. Maximum delay is 12000 (2 minutes). ; TASK_ADDRESS = starting address of the task (14-bit address) ; ; WAITLIST can be called from from an interrupt, or from normal execution. ; It is the only public function of the waitlist. ; ; **** WARNING **** If WAITLIST is not called from an interrupt, be sure to ; inhibit interrupts before calling it to protect the integrity of the list. ; ; Tasks execute when TIME3 overflows and generates an interrupt (T3RUPT). ; The task executes during the interrupt. Tasks terminate themselves by ; jumping to TASKOVER. ; TC TASKOVER ; ; Because tasks execute during an interrupt, they should be fairly short. ; Tasks can initiate longer operations by scheduling a 'job' using EXEC.

Page 468: Apollo Guidance Computer AGC

;========================================================================== 02174 2174 00002 0 WL_taskRecSize DS TRECSZ ; size of a task record (words)02175 2175 00057 0 WL_tskLstStart DS WL_taskList ; starting address for task list02176 2176 00073 0 WL_tskLstEnd DS MAXTASK-1@TRECSZ+WL_taskList 02177 2177 00006 1 WL_numTasks DS MAXTASK-1 ; init loop counter for all tasks02200 2200 00005 1 WL_numTasks1 DS MAXTASK-2 ; init loop counter for all tasks - 1 02201 2201 37777 1 WL_maxVal DS MAXVAL 02202 2202 27340 0 WL_maxDelay DS MAXDELAY 02203 2203 10440 0 WL_maxTimeOut DS MAXTIMEOUT ;-------------------------------------------------------------------------- ; WL_initWL - INITIALIZE WAITLIST ; ; Subroutine initializes the eraseable memory segment for WAITLIST. ; Necessary in case the AGC is restarted. ; ; Note: the valid range for TIME3 is 10440 to 37777 (which spans ; 12000 (base 10) ticks, which corresponds to 120 seconds) ; positive overflow occurs at 40000, which triggers T3RUPT. ; TIME3 values of 0 to 10437 are illegal; these values occur ; after timeout when the counter overflows. TIME3 values in this ; range indicate that timeout has occurred and that T3RUPT is ; presently occuring, or is pending. ;-------------------------------------------------------------------------- WL_initWL EQU * 02204 2204 3 0,0001 0 XCH Q 02205 2205 5 0,0075 0 TS WL_IN_saveQ ; save return address 02206 2206 3 1,2203 1 CAF WL_maxTimeOut 02207 2207 5 0,0037 0 TS TIME3 ; Iterate through task list and initialize all records to NIL 02210 2210 3 1,2175 0 CAF WL_tskLstStart ; init pointer to start of list02211 2211 5 0,0076 0 TS WL_IN_taskPtr 02212 2212 3 1,2177 1 CAF WL_numTasks ; loop for number of tasks WL_IN_loop EQU * 02213 2213 5 0,0077 1 TS WL_IN_loopCnt 02214 2214 3 1,2202 0 CAF WL_maxDelay 02215 2215 2 0,0076 1 INDEX WL_IN_taskPtr 02216 2216 5 0,0000 1 TS TSKTIME 02217 2217 3 1,2050 0 CAF ZERO 02220 2220 2 0,0076 1 INDEX WL_IN_taskPtr 02221 2221 5 0,0001 0 TS TSKADDR 02222 2222 3 0,0076 0 XCH WL_IN_taskPtr ; bump task pointer back 1 record02223 2223 6 1,2174 1 AD WL_taskRecSize 02224 2224 5 0,0076 0 TS WL_IN_taskPtr 02225 2225 1 0,0077 0 CCS WL_IN_loopCnt ; done checking task list?02226 2226 0 1,2213 0 TC WL_IN_loop ; not yet 02227 2227 3 0,0075 0 XCH WL_IN_saveQ 02230 2230 5 0,0001 0 TS Q ; restore return address02231 2231 0 0,0000 0 RETURN ;-------------------------------------------------------------------------- ; WAITLIST - ADD TASK TO WAITLIST ; ; Subroutine adds a task to WL_taskList. The following conditions are ; true upon entry. ; 1) The task list is sorted so the next task scheduled for execution ; is at the front of the list. ; 2) If no tasks are currently scheduled, the task record at the front ; of the list will be NIL. ; 3) Unused (NIL) records in the task list have their time fields set to ; MAXDELAY and their address fields set to zero. ; 4) If any tasks are on the waitlist, the time field in that task's ; record will contain the remaining time AFTER the next timeout. The ; task scheduled for execution at timeout will have a time remaining ; of zero. ; Any other tasks that will execute at that time will also have a time of ; zero. Tasks that will execute some time in the future AFTER timeout ; will have nonzero times; these times indicate the additional time ; needed after the next timeout. ; ; This is the only 'public' function. It can be called from a job or from ; a task or other interrupt. It disables interrupts to maintain the integrity ; of the taskList.

Page 469: Apollo Guidance Computer AGC

;-------------------------------------------------------------------------- WAITLIST EQU * 02232 2232 5 0,0102 1 TS WL_AT_newTime ; save task time02233 2233 3 0,0001 0 XCH Q 02234 2234 5 0,0100 0 TS WL_AT_saveQ ; save return address-1 02235 2235 3 1,2050 0 CAF ZERO 02236 2236 2 1,2176 1 INDEX WL_tskLstEnd 02237 2237 6 0,0001 0 AD TSKADDR 02240 2240 1 0,0000 0 CCS A ; list full?02241 2241 0 1,2343 1 TC WL_AT_done ; >0 yes, so give up ; Calculate time remaining until currently scheduled time-out. 02242 2242 3 1,2050 0 CAF ZERO 02243 2243 6 0,0037 0 AD TIME3 ; get time02244 2244 5 0,0103 0 TS WL_AT_timeLeft ; save it, temporarily ; Did TIME3 recently overflow? If so, we are inside T3RUPT, or T3RUPT ; is pending. TIME3 values from 0 - 10437 are not legal, so they ; indicate that an overflow has occurred. 02245 2245 4 1,2203 0 CS WL_maxTimeOut 02246 2246 6 0,0103 0 AD WL_AT_timeLeft 02247 2247 1 0,0000 0 CCS A ; TIME3 recently overflowed?02250 2250 0 1,2264 0 TC WL_AT_noOvf ; >0 no02251 2251 0 1,2264 0 TC WL_AT_noOvf ; +0 no02252 2252 0 1,2254 0 TC *+2 ; <0 yes02253 2253 0 1,2264 0 TC WL_AT_noOvf ; -0 no ; TIME3 already timed-out, so we must be inside T3RUPT, or T3RUPT ; is pending. Just add the new task to the list. No time correction ; is necessary; the epoch is NOW. 02254 2254 3 1,2050 0 CAF ZERO 02255 2255 6 0,0102 1 AD WL_AT_newTime 02256 2256 5 0,0122 0 TS WL_IS_newTime ; set time field in new task record 02257 2257 2 0,0100 1 INDEX WL_AT_saveQ ; indirectly address WL_AT_saveQ02260 2260 3 0,0000 1 CAF 0 02261 2261 5 0,0123 1 TS WL_IS_newAddr ; set addr field in new task record 02262 2262 0 1,2473 0 TCR WL_insert ; add new task to task list02263 2263 0 1,2343 1 TC WL_AT_done ; TIME3 has not timed out yet. Calculate time remaining until timeout ; (timeout occurs when TIME3 overflows) WL_AT_noOvf EQU * 02264 2264 4 0,0103 1 CS WL_AT_timeLeft ; get -TIME302265 2265 6 1,2201 0 AD WL_maxVal 02266 2266 6 1,2051 1 AD ONE 02267 2267 5 0,0103 0 TS WL_AT_timeLeft ; time left = -TIME3 + %37777 + 1 ; Compare that time against the timeout for the new task. WL_AT_chkOrder EQU * 02270 2270 4 0,0102 0 CS WL_AT_newTime 02271 2271 6 0,0103 0 AD WL_AT_timeLeft 02272 2272 1 0,0000 0 CCS A ; compare new task to current02273 2273 0 1,2306 0 TC WL_AT_mkFirst ; >0 (make new task 1st)02274 2274 0 1,2276 0 TC *+2 ; +002275 2275 0 1,2276 0 TC *+1 ; <0 ; The new task does not need to run before the current time-out, so ; just add it to the list. Subtract the remaining time interval from the ; new task's time, so the new task will have the same epoch as the other ; tasks on the list. 02276 2276 4 0,0103 1 CS WL_AT_timeLeft 02277 2277 6 0,0102 1 AD WL_AT_newTime ; make epoch correction02300 2300 5 0,0122 0 TS WL_IS_newTime ; set time field in new task record 02301 2301 2 0,0100 1 INDEX WL_AT_saveQ ; indirectly address WL_AT_saveQ02302 2302 3 0,0000 1 CAF 0 02303 2303 5 0,0123 1 TS WL_IS_newAddr ; set addr field in new task record 02304 2304 0 1,2473 0 TCR WL_insert ; add new task to task list02305 2305 0 1,2343 1 TC WL_AT_done ; The new task needs to run prior to the current time-out. Add the time ; remaining to all tasks currently on the list to change their epoch ; to NOW. WL_AT_mkFirst EQU * 02306 2306 3 1,2175 0 CAF WL_tskLstStart ; set pointer to front of list

Page 470: Apollo Guidance Computer AGC

02307 2307 5 0,0101 1 TS WL_AT_taskPtr 02310 2310 3 1,2177 1 CAF WL_numTasks ; loop for number of tasks WL_AT_loop EQU * 02311 2311 5 0,0104 1 TS WL_AT_loopCnt 02312 2312 3 1,2050 0 CAF ZERO 02313 2313 2 0,0101 0 INDEX WL_AT_taskPtr 02314 2314 6 0,0001 0 AD TSKADDR 02315 2315 1 0,0000 0 CCS A ; end of list?02316 2316 0 1,2320 1 TC *+2 ; >0 no, so keep going02317 2317 0 1,2333 0 TC WL_AT_schTsk ; +0 yes, add the new task 02320 2320 3 1,2050 0 CAF ZERO 02321 2321 2 0,0101 0 INDEX WL_AT_taskPtr 02322 2322 6 0,0000 1 AD TSKTIME 02323 2323 6 0,0103 0 AD WL_AT_timeLeft ; time-out = time-out + timeLeft02324 2324 2 0,0101 0 INDEX WL_AT_taskPtr 02325 2325 5 0,0000 1 TS TSKTIME 02326 2326 3 0,0101 1 XCH WL_AT_taskPtr ; bump task pointer back 1 record02327 2327 6 1,2174 1 AD WL_taskRecSize 02330 2330 5 0,0101 1 TS WL_AT_taskPtr 02331 2331 1 0,0104 0 CCS WL_AT_loopCnt ; done fixing the times?02332 2332 0 1,2311 0 TC WL_AT_loop ; not yet ; Now that the tasks all share the same epoch, add the new task to the ; list and call the scheduler to schedule the next task. WL_AT_schTsk EQU * 02333 2333 3 1,2050 0 CAF ZERO 02334 2334 6 0,0102 1 AD WL_AT_newTime 02335 2335 5 0,0122 0 TS WL_IS_newTime ; set time field in new task record 02336 2336 2 0,0100 1 INDEX WL_AT_saveQ ; indirectly address WL_AT_saveQ02337 2337 3 0,0000 1 CAF 0 02340 2340 5 0,0123 1 TS WL_IS_newAddr ; set addr field in new task record 02341 2341 0 1,2473 0 TCR WL_insert ; add new task to task list 02342 2342 0 1,2417 1 TCR WL_schedTask ; schedule the next task WL_AT_done EQU * 02343 2343 3 0,0100 0 XCH WL_AT_saveQ 02344 2344 6 1,2051 1 AD ONE 02345 2345 5 0,0001 0 TS Q ; restore return address02346 2346 0 0,0000 0 RETURN ;-------------------------------------------------------------------------- ; WL_TIME3task - T3 TIMEOUT ; ; Perform WAITLIST activities when TIME3 times-out. Called by the ; T3 interrupt handler. ;-------------------------------------------------------------------------- WL_TIME3task EQU * 02347 2347 3 0,0001 0 XCH Q 02350 2350 5 0,0105 0 TS WL_T3_saveQ ; save return address02351 2351 3 0,0015 0 XCH BANK 02352 2352 5 0,0106 0 TS WL_T3_oldBank ; save current bank ; Execute all timed-out tasks. 02353 2353 0 1,2362 1 TCR WL_runTasks ; Set up TIME3 to overflow at the next task's time-out. ; Adjust the time-outs for all remaining tasks. 02354 2354 0 1,2417 1 TCR WL_schedTask 02355 2355 3 0,0106 0 XCH WL_T3_oldBank 02356 2356 5 0,0015 0 TS BANK ; restore previous bank02357 2357 3 0,0105 0 XCH WL_T3_saveQ 02360 2360 5 0,0001 0 TS Q ; restore return address02361 2361 0 0,0000 0 RETURN ;-------------------------------------------------------------------------- ; WL_runTasks - RUN TIMED-OUT TASK(S) ; ; Runs all tasks timed-out on WL_taskList. Tasks are removed ; from the list before they are run. ;-------------------------------------------------------------------------- WL_runTasks EQU * 02362 2362 3 0,0001 0 XCH Q 02363 2363 5 0,0113 1 TS WL_RT_saveQ ; save return address

Page 471: Apollo Guidance Computer AGC

; loop, checking the task on the front of the list. If it is ; timed out, remove it from the list and run it. WL_RT_loop EQU * 02364 2364 3 1,2050 0 CAF ZERO 02365 2365 2 1,2175 1 INDEX WL_tskLstStart 02366 2366 6 0,0000 1 AD TSKTIME 02367 2367 1 0,0000 0 CCS A ; task timed out?02370 2370 0 1,2414 1 TC WL_RT_done ; >0 no, so we are done02371 2371 0 1,2373 1 TC *+2 ; +002372 2372 0 1,2373 1 TC *+1 ; <0 ; This task has timed out, so run it. 02373 2373 0 1,2565 0 TCR WL_remove ; remove task from list02374 2374 5 0,0114 0 TS WL_RT_runAddr ; save 14-bit address of task to run ; The task address is always 14-bit, so check whether the address falls ; within erasable or fixed-fixed memory. If so, use it as-is; otherwise, ; set the bank register and change the address to 12-bit. 02375 2375 4 0,0000 0 COM ; -(14bitAddr)+%600002376 2376 6 1,2102 0 AD bankAddr 02377 2377 1 0,0000 0 CCS A ; task is bank addressed?02400 2400 0 1,2411 1 TC WL_RT_runIt ; >0 no, just run it, as is02401 2401 0 1,2403 1 TC *+2 ; +0 yes02402 2402 0 1,2403 1 TC *+1 ; <0 yes 02403 2403 3 1,2050 0 CAF ZERO 02404 2404 6 0,0114 0 AD WL_RT_runAddr 02405 2405 5 0,0015 0 TS BANK ; set the bank 02406 2406 7 1,2103 0 MASK lowAddr ; get lowest 10-bits of address02407 2407 6 1,2102 0 AD bankAddr ; set bits 11,12 for fixed-switchable02410 2410 5 0,0114 0 TS WL_RT_runAddr WL_RT_runIt EQU * 02411 2411 2 0,0114 1 INDEX WL_RT_runAddr ; apply indirect address to next instr.02412 2412 0 0,0000 1 TC 0 ; run the task TASKOVER EQU * ; task returns here02413 2413 0 1,2364 1 TC WL_RT_loop ; check next task on list WL_RT_done EQU * 02414 2414 3 0,0113 1 XCH WL_RT_saveQ 02415 2415 5 0,0001 0 TS Q ; restore return address02416 2416 0 0,0000 0 RETURN ;-------------------------------------------------------------------------- ; WL_schedTask - SCHEDULE NEXT TASK ; ; Schedule task on the front of list for the next time-out. Adjust the ; time-out for all other tasks on the list, so they contain the remaining ; time after the next timeout. ;-------------------------------------------------------------------------- WL_schedTask EQU * 02417 2417 3 0,0001 0 XCH Q 02420 2420 5 0,0107 1 TS WL_ST_saveQ ; save return address 02421 2421 3 1,2050 0 CAF ZERO 02422 2422 2 1,2175 1 INDEX WL_tskLstStart 02423 2423 6 0,0001 0 AD TSKADDR 02424 2424 1 0,0000 0 CCS A ; task scheduled?02425 2425 0 1,2427 1 TC *+2 ; >0 yes02426 2426 0 1,2466 1 TC WL_ST_noTask ; +0 no, so we are done 02427 2427 3 1,2050 0 CAF ZERO 02430 2430 2 1,2175 1 INDEX WL_tskLstStart 02431 2431 6 0,0000 1 AD TSKTIME 02432 2432 5 0,0111 0 TS WL_ST_newTime ; save the new task's time-out ; Iterate through all tasks on the list. Subtract the time-out time ; from each task. (The 1st task on the list will now have a time-out ; of zero) 02433 2433 3 1,2175 0 CAF WL_tskLstStart ; set pointer to front of list02434 2434 5 0,0110 1 TS WL_ST_taskPtr 02435 2435 3 1,2177 1 CAF WL_numTasks ; loop for number of tasks WL_ST_loop EQU * 02436 2436 5 0,0112 0 TS WL_ST_loopCnt 02437 2437 3 1,2050 0 CAF ZERO 02440 2440 2 0,0110 0 INDEX WL_ST_taskPtr 02441 2441 6 0,0001 0 AD TSKADDR

Page 472: Apollo Guidance Computer AGC

02442 2442 1 0,0000 0 CCS A ; end of list?02443 2443 0 1,2445 0 TC *+2 ; >0 no, so keep going02444 2444 0 1,2461 0 TC WL_ST_setT3 ; +0 yes, set TIME3 02445 2445 3 1,2050 0 CAF ZERO 02446 2446 2 0,0110 0 INDEX WL_ST_taskPtr 02447 2447 6 0,0000 1 AD TSKTIME 02450 2450 2 0,0000 1 EXTEND 02451 2451 6 0,0111 0 SU WL_ST_newTime ; time-out = time-out - newtime02452 2452 2 0,0110 0 INDEX WL_ST_taskPtr 02453 2453 5 0,0000 1 TS TSKTIME 02454 2454 3 0,0110 1 XCH WL_ST_taskPtr ; bump task pointer back 1 record02455 2455 6 1,2174 1 AD WL_taskRecSize 02456 2456 5 0,0110 1 TS WL_ST_taskPtr 02457 2457 1 0,0112 1 CCS WL_ST_loopCnt ; done fixing the times?02460 2460 0 1,2436 1 TC WL_ST_loop ; not yet ; Set TIME3 to overflow at the time-out of the task on the front ; of the list: TIME3 = %37777 - WL_ST_newTime + 1 WL_ST_setT3 EQU * 02461 2461 4 0,0111 1 CS WL_ST_newTime 02462 2462 6 1,2201 0 AD WL_maxVal 02463 2463 6 1,2051 1 AD ONE 02464 2464 5 0,0037 0 TS TIME3 ; overflow at new time-out time02465 2465 0 1,2470 0 TC WL_ST_done WL_ST_noTask EQU * 02466 2466 3 1,2203 1 CAF WL_maxTimeOut 02467 2467 5 0,0037 0 TS TIME3 ; nothing scheduled, reset the clock WL_ST_done EQU * 02470 2470 3 0,0107 1 XCH WL_ST_saveQ 02471 2471 5 0,0001 0 TS Q ; restore return address02472 2472 0 0,0000 0 RETURN ;-------------------------------------------------------------------------- ; WL_insert - INSERT TASK INTO SORTED LIST ; ; Insert a task record into the sorted list. Use 'WL_IS_newTime' and ; 'WL_IS_newAddr' to set the fields of record to be inserted. ; Performs an insertion sort, with the records sorted by time. ; Lowest times are at the front of the list. If several records ; have the same time, the records inserted first will appear first ; in the list. NIL records have a time of NOTASK and a address ; of positive zero. ;-------------------------------------------------------------------------- WL_insert EQU * 02473 2473 3 0,0001 0 XCH Q 02474 2474 5 0,0124 0 TS WL_IS_saveQ ; save return address 02475 2475 3 1,2176 0 CAF WL_tskLstEnd ; set pointer to back of list02476 2476 5 0,0125 1 TS WL_IS_taskPtr 02477 2477 2 0,0000 1 EXTEND 02500 2500 6 1,2174 1 SU WL_taskRecSize ; set pointer to rec in front of it02501 2501 5 0,0126 1 TS WL_IS_taskPtr2 02502 2502 3 1,2050 0 CAF ZERO 02503 2503 2 0,0125 0 INDEX WL_IS_taskPtr 02504 2504 6 0,0001 0 AD TSKADDR 02505 2505 1 0,0000 0 CCS A ; list full?02506 2506 0 1,2562 1 TC WL_IS_done ; >0 yes ; Work from the back of the list to the front, pushing each record ; to the back until the insertion point is found. 02507 2507 3 1,2200 1 CAF WL_numTasks1 ; loop for number of tasks minus 1 WL_IS_loop EQU * 02510 2510 5 0,0127 0 TS WL_IS_loopCnt 02511 2511 3 1,2050 0 CAF ZERO 02512 2512 2 0,0126 0 INDEX WL_IS_taskPtr2 02513 2513 6 0,0001 0 AD TSKADDR 02514 2514 1 0,0000 0 CCS A ; previous record is NIL?02515 2515 0 1,2517 0 TC *+2 ; no, so check it02516 2516 0 1,2541 0 TC WL_IS_bumpPtr ; yes, so skip to next record ; Is this the insertion point? 02517 2517 4 0,0122 1 CS WL_IS_newTime 02520 2520 2 0,0126 0 INDEX WL_IS_taskPtr2 02521 2521 6 0,0000 1 AD TSKTIME

Page 473: Apollo Guidance Computer AGC

02522 2522 1 0,0000 0 CCS A ; found insertion point?02523 2523 0 1,2527 0 TC *+4 ; >0 no, keep checking02524 2524 0 1,2552 1 TC WL_IS_insRec ; +0 yes02525 2525 0 1,2552 1 TC WL_IS_insRec ; <0 yes02526 2526 0 1,2552 1 TC WL_IS_insRec ; -0 yes ; No, bump the record toward the back of the list. 02527 2527 3 1,2050 0 CAF ZERO 02530 2530 2 0,0126 0 INDEX WL_IS_taskPtr2 02531 2531 6 0,0000 1 AD TSKTIME 02532 2532 2 0,0125 0 INDEX WL_IS_taskPtr 02533 2533 5 0,0000 1 TS TSKTIME ; copy time field 02534 2534 3 1,2050 0 CAF ZERO 02535 2535 2 0,0126 0 INDEX WL_IS_taskPtr2 02536 2536 6 0,0001 0 AD TSKADDR 02537 2537 2 0,0125 0 INDEX WL_IS_taskPtr 02540 2540 5 0,0001 0 TS TSKADDR ; copy address field WL_IS_bumpPtr EQU * 02541 2541 3 0,0125 1 XCH WL_IS_taskPtr ; bump task pointer forward 1 record02542 2542 2 0,0000 1 EXTEND 02543 2543 6 1,2174 1 SU WL_taskRecSize 02544 2544 5 0,0125 1 TS WL_IS_taskPtr 02545 2545 2 0,0000 1 EXTEND 02546 2546 6 1,2174 1 SU WL_taskRecSize ; set pointer to record in front of it02547 2547 5 0,0126 1 TS WL_IS_taskPtr2 02550 2550 1 0,0127 1 CCS WL_IS_loopCnt ; done bumping tasks backward?02551 2551 0 1,2510 1 TC WL_IS_loop ; not yet ; Insert new record. WL_IS_insRec EQU * 02552 2552 3 1,2050 0 CAF ZERO 02553 2553 6 0,0122 0 AD WL_IS_newTime 02554 2554 2 0,0125 0 INDEX WL_IS_taskPtr 02555 2555 5 0,0000 1 TS TSKTIME ; set time field 02556 2556 3 1,2050 0 CAF ZERO 02557 2557 6 0,0123 1 AD WL_IS_newAddr 02560 2560 2 0,0125 0 INDEX WL_IS_taskPtr 02561 2561 5 0,0001 0 TS TSKADDR ; set address field WL_IS_done EQU * 02562 2562 3 0,0124 0 XCH WL_IS_saveQ 02563 2563 5 0,0001 0 TS Q ; restore return address02564 2564 0 0,0000 0 RETURN ;-------------------------------------------------------------------------- ; WL_remove - REMOVE TASK FROM FRONT OF LIST ; ; Returns the address of the task in register A. If the list is ; empty, it returns zero in A. If a task is removed from the list, ; the remaining tasks are moved up to the front. ;-------------------------------------------------------------------------- WL_remove EQU * 02565 2565 3 0,0001 0 XCH Q 02566 2566 5 0,0115 1 TS WL_RM_saveQ ; save return address 02567 2567 3 1,2175 0 CAF WL_tskLstStart ; set pointer to front of list02570 2570 5 0,0116 1 TS WL_RM_taskPtr 02571 2571 6 1,2174 1 AD WL_taskRecSize ; set pointer to next rec behind it02572 2572 5 0,0117 0 TS WL_RM_taskPtr2 ; Save the address of record at the front of the list. 02573 2573 3 1,2050 0 CAF ZERO 02574 2574 2 0,0116 0 INDEX WL_RM_taskPtr 02575 2575 6 0,0001 0 AD TSKADDR 02576 2576 5 0,0121 0 TS WL_RM_retval ; get address of 1st task 02577 2577 1 0,0000 0 CCS A ; list empty?02600 2600 0 1,2602 1 TC *+2 ; >0, no02601 2601 0 1,2636 0 TC WL_RM_done ; +0, yes, so exit ; Loop through the remaining records in the task list and ; bubble them up to the front. 02602 2602 3 1,2200 1 CAF WL_numTasks1 ; loop for number of tasks minus 1 WL_RM_loop EQU * 02603 2603 5 0,0120 1 TS WL_RM_loopCnt

Page 474: Apollo Guidance Computer AGC

02604 2604 3 1,2050 0 CAF ZERO 02605 2605 2 0,0117 1 INDEX WL_RM_taskPtr2 02606 2606 6 0,0000 1 AD TSKTIME 02607 2607 2 0,0116 0 INDEX WL_RM_taskPtr 02610 2610 5 0,0000 1 TS TSKTIME ; copy time field 02611 2611 3 1,2050 0 CAF ZERO 02612 2612 2 0,0117 1 INDEX WL_RM_taskPtr2 02613 2613 6 0,0001 0 AD TSKADDR 02614 2614 2 0,0116 0 INDEX WL_RM_taskPtr 02615 2615 5 0,0001 0 TS TSKADDR ; copy address field 02616 2616 1 0,0000 0 CCS A ; remainder of list empty?02617 2617 0 1,2621 0 TC *+2 ; >0, no02620 2620 0 1,2636 0 TC WL_RM_done ; +0, yes, so exit 02621 2621 3 0,0116 1 XCH WL_RM_taskPtr ; bump task pointer back 1 record02622 2622 6 1,2174 1 AD WL_taskRecSize 02623 2623 5 0,0116 1 TS WL_RM_taskPtr 02624 2624 6 1,2174 1 AD WL_taskRecSize ; set pointer to record behind it02625 2625 5 0,0117 0 TS WL_RM_taskPtr2 02626 2626 1 0,0120 0 CCS WL_RM_loopCnt ; done bumping tasks upward?02627 2627 0 1,2603 0 TC WL_RM_loop ; not yet ; Since we removed a record, the last record on the list ; should be NIL. 02630 2630 3 1,2202 0 CAF WL_maxDelay 02631 2631 2 0,0116 0 INDEX WL_RM_taskPtr 02632 2632 5 0,0000 1 TS TSKTIME ; set time field to NIL 02633 2633 3 1,2050 0 CAF ZERO 02634 2634 2 0,0116 0 INDEX WL_RM_taskPtr 02635 2635 5 0,0001 0 TS TSKADDR ; set address field to NIL WL_RM_done EQU * 02636 2636 3 0,0115 1 XCH WL_RM_saveQ 02637 2637 5 0,0001 0 TS Q ; restore return address02640 2640 3 0,0121 0 XCH WL_RM_retval ; return task address in A02641 2641 0 0,0000 0 RETURN INCL exec_f.asm ; EXEC ;========================================================================== ; EXEC (file:exec_f.asm) ; ; Version: 1.0 ; Author: John Pultorak ; Date: 04/26/2002 ; ; PURPOSE: ; Constants and source code for EXEC. ; ; Non-preemptive multitasking routines, originally implemented by J. H. ; Laning, Jr. for AGC3 and later adapted for AGC4. Briefly discussed in ; R-393, which gives some of the software interfaces into the ; multitasking. This is my own recreation, and it only includes the job ; scheduling. The original EXEC also includes memory management for the ; eraseable memory; this is not reproduced here. ; ; Overview: scheduled elements are called 'jobs'. Up to 7 jobs can be ; concurrently scheduled. An 8th 'dummy' job is always scheduled. Each ; job has an assigned priority (1-n, where 1 is the lowest priority). ; The highest priority job always executes. When that job terminates, ; the next highest priority job is selected for execution. If several ; jobs have the same priority, they are executed round-robin. ; ; A job is scheduled for execution by calling 'NOVAC' and ; furnishing the job priority and starting address. ; L XCH JOB_PRIORITY ; L+1 TC NOVAC ; L+2 DS JOB_ADDRESS ; L+3 ... execution resumes here ; ; JOB_PRIORITY = a positive integer from %3 - %37776 where a higher number ; indicates higher priority. Priorities below 3 are reserved for ; internal EXEC use: 0=no job, 1=sleeping job, 2=dummy job. ; Priority %37777 is also reserved for woken jobs. ; JOB_ADDRESS = starting address of the job. ; ; **** WARNING **** If NOVAC is not being called from an interrupt, be sure to ; inhibit interrupts before calling it to protect the integrity of the list. ; ; When a new job is added, the new job's record (core set) is ; initialized with a copy of the current job's record (MPAC and other ; parameters), except for the new job priority and address, which are ; set by the 'add job' routine. Therefore, data can be stored into

Page 475: Apollo Guidance Computer AGC

; MPAC prior to starting a new job as a method of passing data into ; the new job. ; ; Jobs terminate themselves by jumping to ENDOFJOB. This removes them ; from the EXEC scheduler: ; TC ENDOFJOB ; ; Jobs can suspend themselves (yield to a higher priority job) by ; executing the following sequence. If there is no other job of ; higher priority, executing of the yielded job resumes at L+2 ; L CCS newJob ; L+1 TC CHANG1 ; L+2 ... execution resumes here ; ; If there is no other job of equal or higher priority, the branch is ; not taken. ; ; Jobs can put themselves to sleep by calling JOBSLEEP. The address ; where execution of the sleeping job should resume must be in register ; A before calling JOBSLEEP. The job will remain sleeping until JOBWAKE ; is called: ; ; L CAF WAKECADR ; L+1 TC JOBSLEEP ; (does not return from JOBSLEEP) ; ; Sleeping jobs are awakened by calling JOBWAKE. The address where ; execution of the sleeping job should resume must be in register A. ; JOBWAKE returns to the address after the call and execution continues ; for the calling job. The job that was sleeping will now be the next ; job to execute. ; ; L CAF WAKECADR ; L+1 TC JOBWAKE ; L+2 ... execution continues here ; ;========================================================================== 02642 2642 37777 1 EX_WAKE_PRIO DS %37777 ; waking job priority (highest)02643 2643 00002 0 EX_DUMMY_PRIO DS %00002 ; dummy job priority (lowest runnable)02644 2644 00001 0 EX_SLEEP_PRIO DS %00001 ; sleeping job; must be < dummy 02645 2645 00130 0 EX_jobCurStart DS EX_currentJob ; starting address for current job 02646 2646 00015 0 EX_jobRecSize DS JRECSZ ; size of a job record (words)02647 2647 00300 1 EX_jobLstStart DS EX_jobList ; starting address for jobList02650 2650 00307 0 EX_jobLstEnd DS MAXJOBS+EX_jobList 02651 2651 00306 1 EX_jobLstEnd1 DS MAXJOBS-1+EX_jobList 02652 2652 00006 1 EX_numJobs DS MAXJOBS-1 ; init loop counter for all jobs02653 2653 00005 1 EX_numJobs1 DS MAXJOBS-2 ; init loop counter for all jobs - 1 ; enumerated types for setting change flag:02654 2654 00001 0 EX_changeJob DS CHGJOB ; change job02655 2655 00000 1 EX_keepJob DS KEEPJOB ; keep job ;-------------------------------------------------------------------------- ; EX_exec -- EXEC SCHEDULER ; ; Executes the highest priority job. Enables interrupts while the job is ; running. Once called, this function never returns. ;-------------------------------------------------------------------------- EX_exec EQU * ; entry point ; Add a dummy job (lowest priority) that never terminates. 02656 2656 3 1,2643 1 CAF EX_DUMMY_PRIO ; job priority02657 2657 0 1,3162 1 TC NOVAC 02660 2660 03510 0 DS dumJob ; 14 bit job address02661 2661 2 0,0000 0 INHINT ; inhibit RUPTs enab by addJob ; Get the next job to run. EX_MN_findJob EQU * 02662 2662 0 1,3410 1 TCR EX_remove ; compare priority of current job to priority of next waiting job. ; If next job has same priority as current job, set the newJob ; flag so they will be scheduled round-robin. 02663 2663 4 0,0143 0 CS PRIORITY ; get priority of current job 02664 2664 2 1,2647 1 INDEX EX_jobLstStart 02665 2665 2 0,0000 0 INDEX 0 02666 2666 6 0,0143 1 AD PRIORITY ; compare with priority of next job

Page 476: Apollo Guidance Computer AGC

02667 2667 1 0,0000 0 CCS A ; next job has equal priority?02670 2670 0 1,2677 0 TC EX_MN_setFlg ; >0 (error!)02671 2671 0 1,2677 0 TC EX_MN_setFlg ; +0 yes, set flag 02672 2672 0 1,2674 0 TC *+2 ; <0 no, clear flag02673 2673 0 1,2677 0 TC EX_MN_setFlg ; -0 yes, set flag 02674 2674 3 1,2655 0 CAF EX_keepJob ; clear change flag02675 2675 5 0,0307 0 TS newJob 02676 2676 0 1,2701 0 TC EX_MN_runJob EX_MN_setFlg EQU * 02677 2677 3 1,2654 1 CAF EX_changeJob ; set change flag02700 2700 5 0,0307 0 TS newJob ; Start the job. Interrupts are reenabled before 'EX_curJobPtr' is ; referenced, but the interrupts can only call 'NOVAC' which does ; not change 'EX_curJobPtr'. ; The job address is always 14-bit, so check whether the address falls ; within erasable or fixed-fixed memory. If so, use it as-is; otherwise, ; set the bank register and change the address to 12-bit. EX_MN_runJob EQU * 02701 2701 3 1,2050 0 CAF ZERO 02702 2702 6 0,0140 1 AD LOC 02703 2703 5 0,0333 1 TS EX_MN_runAddr ; save job's 14 bit address 02704 2704 4 0,0000 0 COM 02705 2705 6 1,2102 0 AD bankAddr ; -(14bitAddr)+%600002706 2706 1 0,0000 0 CCS A ; job is bank addressed?02707 2707 0 1,2720 0 TC EX_MN_runIt ; >0 no, just run it, as is02710 2710 0 1,2712 1 TC *+2 ; +0 yes02711 2711 0 1,2712 1 TC *+1 ; <0 yes 02712 2712 3 1,2050 0 CAF ZERO 02713 2713 6 0,0333 1 AD EX_MN_runAddr 02714 2714 5 0,0015 0 TS BANK ; set the bank 02715 2715 7 1,2103 0 MASK lowAddr ; get lowest 10-bits of address02716 2716 6 1,2102 0 AD bankAddr ; set bits 11,12 for fixed-switchable02717 2717 5 0,0333 1 TS EX_MN_runAddr EX_MN_runIt EQU * 02720 2720 2 0,0000 1 RELINT ; enable interrupts02721 2721 2 0,0333 0 INDEX EX_MN_runAddr ; apply indirect address to next instr.02722 2722 0 0,0000 1 TC 0 ; run the job ; Job is terminated. Delete the job record. ENDOFJOB EQU * 02723 2723 2 0,0000 0 INHINT ; inhibit interrupts02724 2724 0 1,2662 1 TC EX_MN_findJob ; get next job ; job is sleeping. Keep the job record, but drop the priority so it ; is below the priority of the dummy job. This will keep the job ; from running until JOBWAKE is called. The address where it should ; resume running when awoken is in register A. JOBSLEEP EQU * 02725 2725 2 0,0000 0 INHINT ; inhibit interrupts02726 2726 5 0,0140 1 TS LOC ; save restart address 02727 2727 3 1,2644 0 CAF EX_SLEEP_PRIO 02730 2730 5 0,0143 1 TS PRIORITY ; set sleeping priority02731 2731 5 0,0346 0 TS EX_IS_newPrio 02732 2732 0 1,2757 0 TC EX_MN_mvRec ; finish up ; Job is suspended. Keep the job record, but update the address, so ; execution will resume at the point after suspension. CHANG1 EQU * 02733 2733 2 0,0000 0 INHINT ; inhibit interrupts02734 2734 3 0,0001 0 XCH Q 02735 2735 5 0,0333 1 TS EX_MN_runAddr ; save job's 12 bit restart address 02736 2736 4 0,0000 0 COM 02737 2737 6 1,2102 0 AD bankAddr ; -(12bitAddr)+%600002740 2740 1 0,0000 0 CCS A ; job is bank addressed?02741 2741 0 1,2750 1 TC EX_MN_notBank ; >0 no, just save it, as is02742 2742 0 1,2744 1 TC *+2 ; +0 yes02743 2743 0 1,2744 1 TC *+1 ; <0 yes 02744 2744 4 1,2102 1 CS bankAddr ; 12bitAddr - %600002745 2745 6 0,0333 1 AD EX_MN_runAddr

Page 477: Apollo Guidance Computer AGC

02746 2746 6 0,0015 0 AD BANK ; make it a 14-bit address02747 2747 0 1,2752 0 TC EX_MN_saveIt EX_MN_notBank EQU * 02750 2750 3 1,2050 0 CAF ZERO 02751 2751 6 0,0333 1 AD EX_MN_runAddr ; get restart address EX_MN_saveIt EQU * 02752 2752 5 0,0140 1 TS LOC ; save job's new starting address 02753 2753 3 1,2050 0 CAF ZERO 02754 2754 6 0,0144 0 AD JOBPRIOBASE 02755 2755 5 0,0143 1 TS PRIORITY 02756 2756 5 0,0346 0 TS EX_IS_newPrio ; restore job priority to nominal value ; given the priority, find the insertion point in the list. Copy ; the current job into the list at the correct insertion point. EX_MN_mvRec EQU * 02757 2757 0 1,3332 0 TCR EX_findIns 02760 2760 5 0,0352 0 TS EX_IS_jobPtr ; save address of insertion point ; copy all fields in current record to list 02761 2761 3 1,2646 1 XCH EX_jobRecSize 02762 2762 5 0,0334 0 TS EX_MN_field EX_MN_loop3 EQU * 02763 2763 1 0,0334 1 CCS EX_MN_field ; done?02764 2764 0 1,2766 1 TC *+2 ; not yet02765 2765 0 1,3002 0 TC EX_MN_done3 ; yes02766 2766 5 0,0334 0 TS EX_MN_field ; copy this field to list 02767 2767 3 1,2050 0 CAF ZERO 02770 2770 2 0,0352 1 INDEX EX_IS_jobPtr 02771 2771 6 0,0000 1 AD 0 ; get index to record in list02772 2772 6 0,0334 0 AD EX_MN_field ; add field displacement02773 2773 5 0,0335 1 TS EX_MN_findx ; save index to field in list 02774 2774 3 1,2050 0 CAF ZERO 02775 2775 2 0,0334 1 INDEX EX_MN_field 02776 2776 6 0,0130 0 AD EX_currentJob ; get field from current job02777 2777 2 0,0335 0 INDEX EX_MN_findx 03000 3000 5 0,0130 0 TS EX_currentJob ; copy field to list 03001 3001 0 1,2763 1 TC EX_MN_loop3 EX_MN_done3 EQU * 03002 3002 0 1,2662 1 TC EX_MN_findJob ; get next job ;-------------------------------------------------------------------------- ; JOBWAKE - wake up the job identified by address in register A ; ; Search jobList for a job with address matching the address in A. ; If found, bump the priority up to the highest level, so the job ; will be the next to run. ; ; This is a 'public' function. It assumes that interrupts are already ; disabled before it is called. Disabling interrupts during JOBWAKE ; is necessary to preserve the integrity of the joblist. ;-------------------------------------------------------------------------- JOBWAKE EQU * 03003 3003 5 0,0312 1 TS EX_JW_CADR ; save job address03004 3004 3 0,0001 0 XCH Q 03005 3005 5 0,0310 0 TS EX_JW_saveQ ; save return address ; Search the joblist for the job to wake (job address matches ; EX_JW_CADR). 03006 3006 3 1,2050 0 CAF ZERO 03007 3007 5 0,0313 0 TS EX_JW_foundit ; clear 'found it' flag 03010 3010 3 1,2651 1 CAF EX_jobLstEnd1 ; set pointer to back of list03011 3011 5 0,0314 1 TS EX_JW_jobPtr 03012 3012 6 1,2046 1 AD NEG1 ; set pointer to rec in front of it03013 3013 5 0,0315 0 TS EX_JW_jobPtr2 03014 3014 3 1,2653 0 CAF EX_numJobs1 ; loop for number of jobs minus 1 EX_JW_loop EQU * 03015 3015 5 0,0311 1 TS EX_JW_loopCnt ; if foundit=0, job has not been found yet. Keep searching toward

Page 478: Apollo Guidance Computer AGC

; the front of the list. ; if foundit=1, the job has been found and removed from the list. ; push all jobs in front of the removed job one step to the back ; to fill in the gap and to make room at the front of the list ; for the awoken job. 03016 3016 1 0,0313 1 CCS EX_JW_foundit ; already found job to wake?03017 3017 0 1,3035 1 TC EX_JW_moveRec ; >0, yes ; Is this the job? 03020 3020 4 0,0312 0 CS EX_JW_CADR 03021 3021 2 0,0314 0 INDEX EX_JW_jobPtr 03022 3022 2 0,0000 0 INDEX 0 03023 3023 6 0,0140 1 AD LOC 03024 3024 1 0,0000 0 CCS A ; found job to wake?03025 3025 0 1,3041 1 TC EX_JW_bumpPtr ; >0, no03026 3026 0 1,3030 1 TC *+2 ; +0, yes03027 3027 0 1,3041 1 TC EX_JW_bumpPtr ; <0, no ; found the job to wake. 03030 3030 3 1,2051 1 CAF ONE 03031 3031 5 0,0313 0 TS EX_JW_foundit ; set 'found it' flag ; save record index for awoken job 03032 3032 2 0,0314 0 INDEX EX_JW_jobPtr 03033 3033 3 0,0000 1 XCH 0 03034 3034 5 0,0316 0 TS EX_JW_fndIndx ; index for awoken job ; bump prior record back EX_JW_moveRec EQU * 03035 3035 2 0,0315 1 INDEX EX_JW_jobPtr2 03036 3036 3 0,0000 1 XCH 0 03037 3037 2 0,0314 0 INDEX EX_JW_jobPtr 03040 3040 3 0,0000 1 XCH 0 EX_JW_bumpPtr EQU * 03041 3041 3 0,0314 1 XCH EX_JW_jobPtr ; bump job pointer forward 1 record03042 3042 6 1,2046 1 AD NEG1 03043 3043 5 0,0314 1 TS EX_JW_jobPtr 03044 3044 6 1,2046 1 AD NEG1 ; set pointer to record in front of it03045 3045 5 0,0315 0 TS EX_JW_jobPtr2 03046 3046 1 0,0311 0 CCS EX_JW_loopCnt ; done bumping jobs backward?03047 3047 0 1,3015 0 TC EX_JW_loop ; not yet 03050 3050 1 0,0313 1 CCS EX_JW_foundit ; found job to wake?03051 3051 0 1,3053 1 TC *+2 ; >0, yes03052 3052 0 1,3056 1 TC EX_JW_done ; no 03053 3053 3 0,0316 0 XCH EX_JW_fndIndx ; put awoken job on front of list03054 3054 2 1,2647 1 INDEX EX_jobLstStart 03055 3055 5 0,0000 1 TS 0 EX_JW_done EQU * ; Is the awoken job at the front of the list? ; (If it was already there before we started searching, 'foundIt' ; will be false (0) so we need to make this test). 03056 3056 4 0,0312 0 CS EX_JW_CADR 03057 3057 2 1,2647 1 INDEX EX_jobLstStart 03060 3060 2 0,0000 0 INDEX 0 03061 3061 6 0,0140 1 AD LOC 03062 3062 1 0,0000 0 CCS A ; woken job at front of list?03063 3063 0 1,3074 1 TC EX_JW_return ; >0, no03064 3064 0 1,3066 1 TC *+2 ; +0, yes03065 3065 0 1,3074 1 TC EX_JW_return ; <0, no ; set awoken priority and change job flag 03066 3066 3 1,2642 0 CAF EX_WAKE_PRIO 03067 3067 2 1,2647 1 INDEX EX_jobLstStart 03070 3070 2 0,0000 0 INDEX 0 03071 3071 5 0,0143 1 TS PRIORITY ; set waking priority 03072 3072 3 1,2654 1 CAF EX_changeJob ; set the change flag03073 3073 5 0,0307 0 TS newJob EX_JW_return EQU * 03074 3074 0 0,0310 0 TC EX_JW_saveQ ; return

Page 479: Apollo Guidance Computer AGC

;-------------------------------------------------------------------------- ; SPVAC - ADD A JOB TO THE JOBLIST ; ; Similar to NOVAC, but used by VERB 37. The job CADR is in register A. ; The job priority is in NEWPRIO. Return to the address in Q. ; ; NOVAC differs from SPVAC, because NOVAC has the job CADR at the address ; in Q, and returns to Q+1. Also, in NOVAC the job priority is in A. ; ; This is a 'public' function. It can be called from a job ; or from an interrupt. ;-------------------------------------------------------------------------- SPVAC EQU * 03075 3075 5 0,0350 1 TS EX_IS_newLoc ; store new job address03076 3076 3 0,0001 0 XCH Q 03077 3077 5 0,0317 1 TS EX_AJ_saveQ ; save return address ; add new job to end of list 03100 3100 3 1,2050 0 CAF ZERO 03101 3101 6 0,0360 1 AD NEWPRIO 03102 3102 5 0,0346 0 TS EX_IS_newPrio 03103 3103 5 0,0347 1 TS EX_IS_newPrioB ; store new job priority 03104 3104 0 1,3332 0 TCR EX_findIns ; find insertion point in list03105 3105 5 0,0352 0 TS EX_IS_jobPtr ; save address of insertion point ; Initialize relevant fields in new job. The remaining fields ; should already be zeroed. ; Initialize fields for new job record. New job inherits copy of ; MPAC from current job, so copy all fields in current job to new ; job in list 03106 3106 3 1,2646 1 XCH EX_jobRecSize 03107 3107 5 0,0323 0 TS EX_AJ_field EX_SP_loop1 EQU * 03110 3110 1 0,0323 1 CCS EX_AJ_field ; done?03111 3111 0 1,3113 1 TC *+2 ; not yet03112 3112 0 1,3127 0 TC EX_SP_done1 ; yes03113 3113 5 0,0323 0 TS EX_AJ_field ; copy this field to list 03114 3114 3 1,2050 0 CAF ZERO 03115 3115 2 0,0352 1 INDEX EX_IS_jobPtr 03116 3116 6 0,0000 1 AD 0 ; get index to record in list03117 3117 6 0,0323 0 AD EX_AJ_field ; add field displacement03120 3120 5 0,0324 1 TS EX_AJ_findx ; save index to field in list 03121 3121 3 1,2050 0 CAF ZERO 03122 3122 2 0,0323 1 INDEX EX_AJ_field 03123 3123 6 0,0130 0 AD EX_currentJob ; get field from current job03124 3124 2 0,0324 0 INDEX EX_AJ_findx 03125 3125 5 0,0130 0 TS EX_currentJob ; copy field to list 03126 3126 0 1,3110 1 TC EX_SP_loop1 ; now, overwrite fields in the record with the priority ; and location unique to this job. EX_SP_done1 EQU * 03127 3127 3 1,2050 0 CAF ZERO 03130 3130 6 0,0346 0 AD EX_IS_newPrio 03131 3131 2 0,0352 1 INDEX EX_IS_jobPtr 03132 3132 2 0,0000 0 INDEX 0 03133 3133 5 0,0143 1 TS PRIORITY ; set priority field 03134 3134 3 1,2050 0 CAF ZERO 03135 3135 6 0,0347 1 AD EX_IS_newPrioB 03136 3136 2 0,0352 1 INDEX EX_IS_jobPtr 03137 3137 2 0,0000 0 INDEX 0 03140 3140 5 0,0144 0 TS JOBPRIOBASE ; set nominal priority field 03141 3141 3 1,2050 0 CAF ZERO 03142 3142 6 0,0350 1 AD EX_IS_newLoc 03143 3143 2 0,0352 1 INDEX EX_IS_jobPtr 03144 3144 2 0,0000 0 INDEX 0 03145 3145 5 0,0140 1 TS LOC ; set address field ; Set changeflag if priority of new job >= priority of current job

Page 480: Apollo Guidance Computer AGC

EX_SP_testFlg EQU * 03146 3146 4 0,0143 0 CS PRIORITY ; get -priority of current job 03147 3147 6 0,0321 1 AD EX_AJ_jobPrio ; add positive priority of new job03150 3150 1 0,0000 0 CCS A ; new job is highest priority?03151 3151 0 1,3154 1 TC *+3 ; >0, yes03152 3152 0 1,3154 1 TC *+2 ; +0, yes03153 3153 0 1,3156 0 TC EX_SP_done2 ; <0, no, current job is higher priority 03154 3154 3 1,2654 1 CAF EX_changeJob ; set the change flag03155 3155 5 0,0307 0 TS newJob EX_SP_done2 EQU * 03156 3156 3 0,0317 1 XCH EX_AJ_saveQ 03157 3157 5 0,0001 0 TS Q 03160 3160 0 0,0000 0 RETURN ;-------------------------------------------------------------------------- ; FINDVAC - not implemented ; ;-------------------------------------------------------------------------- 03161 3161 0 0,0001 0 FINDVAC TC Q ; just return ;-------------------------------------------------------------------------- ; NOVAC - ADD A JOB TO THE JOBLIST ; ; Search jobList for an empty slot. If found, put the new job in the ; empty slot. If the new job has the same, or higher, priority than the ; current job, set the change flag to 'CHGJOB' (change jobs at the next ; opportunity). ; ; This is a 'public' function. It can be called from a job ; or from an interrupt. ;-------------------------------------------------------------------------- NOVAC EQU * 03162 3162 5 0,0321 1 TS EX_AJ_jobPrio ; save job priority03163 3163 3 0,0001 0 XCH Q 03164 3164 5 0,0317 1 TS EX_AJ_saveQ ; save return address-1 ; add new job to end of list 03165 3165 3 1,2050 0 CAF ZERO 03166 3166 6 0,0321 1 AD EX_AJ_jobPrio 03167 3167 5 0,0346 0 TS EX_IS_newPrio 03170 3170 5 0,0347 1 TS EX_IS_newPrioB ; store new job priority 03171 3171 2 0,0317 0 INDEX EX_AJ_saveQ ; indirectly address addJobQ03172 3172 3 0,0000 1 CAF 0 03173 3173 5 0,0350 1 TS EX_IS_newLoc ; store new job address 03174 3174 0 1,3332 0 TCR EX_findIns ; find insertion point in list03175 3175 5 0,0352 0 TS EX_IS_jobPtr ; save address of insertion point ; Initialize relevant fields in new job. The remaining fields ; should already be zeroed. ; Initialize fields for new job record. New job inherits copy of ; MPAC from current job, so copy all fields in current job to new ; job in list 03176 3176 3 1,2646 1 XCH EX_jobRecSize 03177 3177 5 0,0323 0 TS EX_AJ_field EX_AJ_loop1 EQU * 03200 3200 1 0,0323 1 CCS EX_AJ_field ; done?03201 3201 0 1,3203 0 TC *+2 ; not yet03202 3202 0 1,3217 0 TC EX_AJ_done1 ; yes03203 3203 5 0,0323 0 TS EX_AJ_field ; copy this field to list 03204 3204 3 1,2050 0 CAF ZERO 03205 3205 2 0,0352 1 INDEX EX_IS_jobPtr 03206 3206 6 0,0000 1 AD 0 ; get index to record in list03207 3207 6 0,0323 0 AD EX_AJ_field ; add field displacement03210 3210 5 0,0324 1 TS EX_AJ_findx ; save index to field in list 03211 3211 3 1,2050 0 CAF ZERO 03212 3212 2 0,0323 1 INDEX EX_AJ_field 03213 3213 6 0,0130 0 AD EX_currentJob ; get field from current job03214 3214 2 0,0324 0 INDEX EX_AJ_findx

Page 481: Apollo Guidance Computer AGC

03215 3215 5 0,0130 0 TS EX_currentJob ; copy field to list 03216 3216 0 1,3200 0 TC EX_AJ_loop1 ; now, overwrite fields in the record with the priority ; and location unique to this job. EX_AJ_done1 EQU * 03217 3217 3 1,2050 0 CAF ZERO 03220 3220 6 0,0346 0 AD EX_IS_newPrio 03221 3221 2 0,0352 1 INDEX EX_IS_jobPtr 03222 3222 2 0,0000 0 INDEX 0 03223 3223 5 0,0143 1 TS PRIORITY ; set priority field 03224 3224 3 1,2050 0 CAF ZERO 03225 3225 6 0,0347 1 AD EX_IS_newPrioB 03226 3226 2 0,0352 1 INDEX EX_IS_jobPtr 03227 3227 2 0,0000 0 INDEX 0 03230 3230 5 0,0144 0 TS JOBPRIOBASE ; set nominal priority field 03231 3231 3 1,2050 0 CAF ZERO 03232 3232 6 0,0350 1 AD EX_IS_newLoc 03233 3233 2 0,0352 1 INDEX EX_IS_jobPtr 03234 3234 2 0,0000 0 INDEX 0 03235 3235 5 0,0140 1 TS LOC ; set address field ; Set changeflag if priority of new job >= priority of current job EX_AJ_testFlg EQU * 03236 3236 4 0,0143 0 CS PRIORITY ; get -priority of current job 03237 3237 6 0,0321 1 AD EX_AJ_jobPrio ; add positive priority of new job03240 3240 1 0,0000 0 CCS A ; new job is highest priority?03241 3241 0 1,3244 0 TC *+3 ; >0, yes03242 3242 0 1,3244 0 TC *+2 ; +0, yes03243 3243 0 1,3246 1 TC EX_AJ_done2 ; <0, no, current job is higher priority 03244 3244 3 1,2654 1 CAF EX_changeJob ; set the change flag03245 3245 5 0,0307 0 TS newJob EX_AJ_done2 EQU * 03246 3246 3 0,0317 1 XCH EX_AJ_saveQ 03247 3247 6 1,2051 1 AD ONE 03250 3250 5 0,0001 0 TS Q 03251 3251 0 0,0000 0 RETURN ;-------------------------------------------------------------------------- ; EX_initEX - INITIALIZE EXEC ; ; Initialize the eraseable memory segment for EXEC. Necessary in ; case the AGC is restarted. ;-------------------------------------------------------------------------- EX_initEX EQU * 03252 3252 3 0,0001 0 XCH Q 03253 3253 5 0,0325 0 TS EX_IN_saveQ ; save return address 03254 3254 3 1,2655 0 CAF EX_keepJob ; clear change flag03255 3255 5 0,0307 0 TS newJob 03256 3256 3 1,2050 0 CAF ZERO 03257 3257 5 0,0143 1 TS PRIORITY ; set current job record to NIL ; Iterate through jobList, initialize each element on the list so it ; points to its own job record. 03260 3260 3 1,2647 0 CAF EX_jobLstStart ; init pointer to start of list03261 3261 5 0,0327 1 TS EX_IN_jobPtr 03262 3262 3 1,2050 0 CAF ZERO 03263 3263 6 1,2646 1 AD EX_jobRecSize 03264 3264 5 0,0330 1 TS EX_IN_recIndex 03265 3265 3 1,2652 1 CAF EX_numJobs ; loop for number of jobs EX_IN_loop1 EQU * 03266 3266 5 0,0326 0 TS EX_IN_loopCnt 03267 3267 3 0,0330 1 XCH EX_IN_recIndex 03270 3270 2 0,0327 0 INDEX EX_IN_jobPtr 03271 3271 5 0,0000 1 TS 0 ; initialize record index03272 3272 6 1,2646 1 AD EX_jobRecSize 03273 3273 5 0,0330 1 TS EX_IN_recIndex ; bump index to next record 03274 3274 3 0,0327 1 XCH EX_IN_jobPtr ; bump job pointer back 1 record03275 3275 6 1,2051 1 AD ONE

Page 482: Apollo Guidance Computer AGC

03276 3276 5 0,0327 1 TS EX_IN_jobPtr 03277 3277 1 0,0326 1 CCS EX_IN_loopCnt ; done clearing jobList?03300 3300 0 1,3266 0 TC EX_IN_loop1 ; not yet ; Iterate through job records, initialize each field to zero. 03301 3301 3 1,2647 0 CAF EX_jobLstStart ; init pointer to start of list03302 3302 5 0,0327 1 TS EX_IN_jobPtr 03303 3303 3 1,2652 1 CAF EX_numJobs ; loop for number of jobs EX_IN_loop2 EQU * 03304 3304 5 0,0326 0 TS EX_IN_loopCnt ; loop for number of fields in each record 03305 3305 3 1,2646 1 XCH EX_jobRecSize 03306 3306 5 0,0331 0 TS EX_IN_field EX_IN_loop3 EQU * 03307 3307 1 0,0331 1 CCS EX_IN_field ; done?03310 3310 0 1,3312 1 TC *+2 ; not yet03311 3311 0 1,3324 1 TC EX_IN_done ; yes03312 3312 5 0,0331 0 TS EX_IN_field ; set the field to zero 03313 3313 3 1,2050 0 CAF ZERO 03314 3314 2 0,0327 0 INDEX EX_IN_jobPtr 03315 3315 6 0,0000 1 AD 0 ; get index to record03316 3316 6 0,0331 0 AD EX_IN_field ; add field displacement03317 3317 5 0,0332 0 TS EX_IN_findx ; save index to field03320 3320 3 1,2050 0 CAF ZERO 03321 3321 2 0,0332 1 INDEX EX_IN_findx 03322 3322 5 0,0130 0 TS EX_currentJob ; clear field 03323 3323 0 1,3307 0 TC EX_IN_loop3 ; done clearing all fields in record, so do next record EX_IN_done EQU * 03324 3324 3 0,0327 1 XCH EX_IN_jobPtr ; bump job pointer back 1 record03325 3325 6 1,2051 1 AD ONE 03326 3326 5 0,0327 1 TS EX_IN_jobPtr 03327 3327 1 0,0326 1 CCS EX_IN_loopCnt ; done clearing jobList?03330 3330 0 1,3304 0 TC EX_IN_loop2 ; not yet 03331 3331 0 0,0325 0 TC EX_IN_saveQ ; return ;-------------------------------------------------------------------------- ; EX_findIns - FIND INSERTION POINT INTO SORTED LIST ; ; Insert a job record into the sorted list. Use 'EX_IS_newPrio', ; EX_IS_newPrioB and 'EX_IS_newLoc' to set the fields of record to ; be inserted. ; Performs an insertion sort, with the records sorted by priority. ; Highest priority is at the front of the list. If several records ; have the same priority, the records inserted first will appear first ; in the list. NIL records have a priority of zero. ;-------------------------------------------------------------------------- EX_findIns EQU * 03332 3332 3 0,0001 0 XCH Q 03333 3333 5 0,0351 0 TS EX_IS_saveQ ; save return address 03334 3334 3 1,2651 1 CAF EX_jobLstEnd1 ; set pointer to back of list03335 3335 5 0,0352 0 TS EX_IS_jobPtr 03336 3336 6 1,2046 1 AD NEG1 ; set pointer to rec in front of it03337 3337 5 0,0353 1 TS EX_IS_jobPtr2 03340 3340 3 1,2050 0 CAF ZERO 03341 3341 2 0,0352 1 INDEX EX_IS_jobPtr 03342 3342 2 0,0000 0 INDEX 0 03343 3343 6 0,0143 1 AD PRIORITY ; check last record on list 03344 3344 1 0,0000 0 CCS A ; list full?03345 3345 0 1,3405 0 TC EX_FI_done ; >0 yes ; Work from the back of the list to the front, pushing each record ; to the back until the insertion point is found. 03346 3346 3 1,2653 0 CAF EX_numJobs1 ; loop for number of jobs minus 1 EX_FI_loop EQU *

Page 483: Apollo Guidance Computer AGC

03347 3347 5 0,0354 0 TS EX_IS_loopCnt 03350 3350 3 1,2050 0 CAF ZERO 03351 3351 2 0,0353 0 INDEX EX_IS_jobPtr2 03352 3352 2 0,0000 0 INDEX 0 03353 3353 6 0,0143 1 AD PRIORITY 03354 3354 1 0,0000 0 CCS A ; previous record is NIL?03355 3355 0 1,3357 0 TC *+2 ; no, so check it03356 3356 0 1,3376 0 TC EX_FI_bumpPtr ; yes, so skip to next record ; Is this the insertion point? 03357 3357 4 0,0346 1 CS EX_IS_newPrio 03360 3360 2 0,0353 0 INDEX EX_IS_jobPtr2 03361 3361 2 0,0000 0 INDEX 0 03362 3362 6 0,0143 1 AD PRIORITY 03363 3363 1 0,0000 0 CCS A ; found insertion point?03364 3364 0 1,3405 0 TC EX_FI_insRec ; >0 yes03365 3365 0 1,3405 0 TC EX_FI_insRec ; +0 yes03366 3366 0 1,3370 0 TC *+2 ; <0 no, keep checking03367 3367 0 1,3405 0 TC EX_FI_insRec ; -0 yes ; No, bump the record toward the back of the list. 03370 3370 2 0,0353 0 INDEX EX_IS_jobPtr2 03371 3371 3 0,0000 1 XCH 0 03372 3372 2 0,0352 1 INDEX EX_IS_jobPtr 03373 3373 3 0,0000 1 XCH 0 03374 3374 2 0,0353 0 INDEX EX_IS_jobPtr2 03375 3375 3 0,0000 1 XCH 0 EX_FI_bumpPtr EQU * 03376 3376 3 0,0352 0 XCH EX_IS_jobPtr ; bump job pointer forward 1 record03377 3377 6 1,2046 1 AD NEG1 03400 3400 5 0,0352 0 TS EX_IS_jobPtr 03401 3401 6 1,2046 1 AD NEG1 ; set pointer to record in front of it03402 3402 5 0,0353 1 TS EX_IS_jobPtr2 03403 3403 1 0,0354 1 CCS EX_IS_loopCnt ; done bumping jobs backward?03404 3404 0 1,3347 1 TC EX_FI_loop ; not yet ; New record should be inserted at EX_IS_jobPtr. EX_FI_insRec EQU * EX_FI_done EQU * 03405 3405 3 1,2050 0 CAF ZERO 03406 3406 6 0,0352 0 AD EX_IS_jobPtr ; get insertion spot in list03407 3407 0 0,0351 0 TC EX_IS_saveQ ; return ;-------------------------------------------------------------------------- ; EX_remove - REMOVE JOB FROM FRONT OF LIST ; ; Remove job from front of list and copy it to the current job. Bubble ; any remaining jobs toward the front of the list. ;-------------------------------------------------------------------------- EX_remove EQU * 03410 3410 3 0,0001 0 XCH Q 03411 3411 5 0,0336 1 TS EX_RM_saveQ ; save return address 03412 3412 3 1,2647 0 CAF EX_jobLstStart ; set pointer to front of list03413 3413 5 0,0337 0 TS EX_RM_jobPtr 03414 3414 6 1,2051 1 AD ONE ; set pointer to next rec behind it03415 3415 5 0,0340 0 TS EX_RM_jobPtr2 ; Dequeue the record at the top of the list (the next job to run). ; Make it the current job by copying it to the current job record. 03416 3416 3 1,2646 1 XCH EX_jobRecSize 03417 3417 5 0,0344 1 TS EX_RM_field EX_RM_loop1 EQU * 03420 3420 1 0,0344 0 CCS EX_RM_field ; done?03421 3421 0 1,3423 1 TC *+2 ; not yet03422 3422 0 1,3437 1 TC EX_RM_done1 ; yes03423 3423 5 0,0344 1 TS EX_RM_field ; copy field from list to current job 03424 3424 3 1,2050 0 CAF ZERO 03425 3425 2 0,0337 1 INDEX EX_RM_jobPtr 03426 3426 6 0,0000 1 AD 0 ; get index to record

Page 484: Apollo Guidance Computer AGC

03427 3427 6 0,0344 1 AD EX_RM_field ; add field displacement03430 3430 5 0,0345 0 TS EX_RM_findx ; save index to field03431 3431 3 1,2050 0 CAF ZERO 03432 3432 2 0,0345 1 INDEX EX_RM_findx 03433 3433 6 0,0130 0 AD EX_currentJob ; get field03434 3434 2 0,0344 0 INDEX EX_RM_field 03435 3435 5 0,0130 0 TS EX_currentJob ; move to current job 03436 3436 0 1,3420 1 TC EX_RM_loop1 ; done copying record for current job. Restore the current job to ; its default priority, in case it was previously elevated. EX_RM_done1 EQU * 03437 3437 3 1,2050 0 CAF ZERO 03440 3440 6 0,0144 0 AD JOBPRIOBASE 03441 3441 5 0,0143 1 TS PRIORITY 03442 3442 2 0,0337 1 INDEX EX_RM_jobPtr 03443 3443 3 0,0000 1 XCH 0 03444 3444 5 0,0341 1 TS EX_RM_savePtr ; so we can move it to the end later ; Loop through the remaining records in the job list and ; bubble them up to the front. 03445 3445 3 1,2653 0 CAF EX_numJobs1 ; loop for number of jobs minus 1 EX_RM_loop2 EQU * 03446 3446 5 0,0342 1 TS EX_RM_loopCnt 03447 3447 2 0,0340 1 INDEX EX_RM_jobPtr2 03450 3450 3 0,0000 1 XCH 0 03451 3451 2 0,0337 1 INDEX EX_RM_jobPtr 03452 3452 5 0,0000 1 TS 0 03453 3453 1 0,0000 0 CCS A ; remainder of list empty?03454 3454 0 1,3456 0 TC *+2 ; >0, no03455 3455 0 1,3465 0 TC EX_RM_done2 ; +0, yes, so exit 03456 3456 3 0,0337 0 XCH EX_RM_jobPtr ; bump job pointer back 1 record03457 3457 6 1,2051 1 AD ONE 03460 3460 5 0,0337 0 TS EX_RM_jobPtr 03461 3461 6 1,2051 1 AD ONE ; set pointer to record behind it03462 3462 5 0,0340 0 TS EX_RM_jobPtr2 03463 3463 1 0,0342 0 CCS EX_RM_loopCnt ; done bumping jobs upward?03464 3464 0 1,3446 1 TC EX_RM_loop2 ; not yet ; Since we removed a record, the last record on the list ; should be NIL. EX_RM_done2 EQU * 03465 3465 3 0,0341 1 XCH EX_RM_savePtr 03466 3466 2 0,0337 1 INDEX EX_RM_jobPtr ; move the index for the top record03467 3467 5 0,0000 1 TS 0 ; to the bottom of the list ; set all fields in NIL record to zero 03470 3470 3 1,2646 1 XCH EX_jobRecSize 03471 3471 5 0,0344 1 TS EX_RM_field EX_RM_loop3 EQU * 03472 3472 1 0,0344 0 CCS EX_RM_field ; done?03473 3473 0 1,3475 1 TC *+2 ; not yet03474 3474 0 1,3507 0 TC EX_RM_done3 ; yes03475 3475 5 0,0344 1 TS EX_RM_field ; set this field to zero 03476 3476 3 1,2050 0 CAF ZERO 03477 3477 2 0,0337 1 INDEX EX_RM_jobPtr 03500 3500 6 0,0000 1 AD 0 ; get index to record03501 3501 6 0,0344 1 AD EX_RM_field ; add field displacement03502 3502 5 0,0345 0 TS EX_RM_findx ; save index to field03503 3503 3 1,2050 0 CAF ZERO 03504 3504 2 0,0345 1 INDEX EX_RM_findx 03505 3505 5 0,0130 0 TS EX_currentJob ; clear field 03506 3506 0 1,3472 0 TC EX_RM_loop3 EX_RM_done3 EQU * 03507 3507 0 0,0336 1 TC EX_RM_saveQ ; return ;--------------------------------------------------------------------------

Page 485: Apollo Guidance Computer AGC

; DUMMY JOB - runs at the lowest priority and never terminates. Ensures ; that there is always at least one job executing. Sleeping jobs are ; given a lower priority than the dummy job. ; ; The dummy job controls the computer activity light on the DSKY. When ; the dummy job is running, the light is off. When the dummy job is ; preempted by a higher priority job, the light is on. ; ; I couldn't find good information on the computer activity light ; in COLOSSUS, so this is my best guess concerning its operation. It ; seems consistent witht the MPEG video of the Apollo 11 DSKY. ;-------------------------------------------------------------------------- ; entering dummy job -- turn off computer activity light dumJob EQU * 03510 3510 3 1,2050 0 CAF ZERO 03511 3511 6 0,0011 1 AD DSALMOUT 03512 3512 7 1,3525 1 MASK NOTACTLT 03513 3513 5 0,0011 1 TS DSALMOUT ; turn bit1 off ; runtime loop for dummy job dumJob1 EQU * 03514 3514 1 0,0307 1 CCS newJob ; check for context switch03515 3515 0 1,3517 1 TC dumJob2 ; yes03516 3516 0 1,3514 1 TC dumJob1 ; no ; exiting dummy job -- turn on computer activity light dumJob2 EQU * 03517 3517 4 0,0011 0 CS DSALMOUT ; inclusive OR bit 1 with 1 using03520 3520 7 1,3525 1 MASK NOTACTLT ; Demorgan's theorem03521 3521 4 0,0000 0 COM 03522 3522 5 0,0011 1 TS DSALMOUT 03523 3523 0 1,2733 1 TC CHANG1 ; exit to run higher priority job03524 3524 0 1,3510 0 TC dumJob ; job done, return here, light off again 03525 3525 77776 1 NOTACTLT DS %77776 ; 1's compliment of bit1 (comp activity light) INCL bank_f.asm ; bank intercommunication routines ;========================================================================== ; BANK INTERCOMMUNICATION (file:bank_f.asm) ; ; Version: 1.0 ; Author: John Pultorak ; Date: 01/19/2002 ; ; PURPOSE: ; Contains bank intercommunication routines. ; The source is missing from my (incomplete) listing of COLOSSUS. The ; implementation here is inferred from the usage in the COLOSSUS pinball ; routines. Some of these routines could probably be combined or optimized ; away if I understood the pinball software architecture a little better. ;========================================================================== ;-------------------------------------------------------------------------- ; DXCHJUMP ; Do a bank jump to the CADR in register A. After the bank jump, the return ; CADR is in register A. Contents of register Q are destroyed. ; This is my attempt to implement the block I equivalent for ; DCA MY2CADR ; DXCH Z ;... which is used in some places in COLOSSUS to implement bank jumps. In that ; implementation, MY2CADR has the lower portion of the address in MYCADR and ; the bank portion in MY2CADR+1. DCA loads the lower address into A and the ; bank address into L. DXCH loads the lower address into Z and the bank portion ; into BB (both bank register), thereby doing a bank call. After the call, ; the lower return address is in A and the return bank is in L. ;-------------------------------------------------------------------------- DXCHJUMP EQU * 03526 3526 5 0,0576 0 TS ADDRWD1 ; save 14-bit destination address 03527 3527 3 0,0001 0 XCH Q 03530 3530 5 0,0617 1 TS DCRET ; save old return address 03531 3531 3 0,0015 0 XCH BANK 03532 3532 5 0,0616 0 TS DCBANK ; save old bank ; put the 12-bit destination address in ADDRWD1 03533 3533 4 0,0576 1 CS ADDRWD1 ; -(14bitAddr)+%600003534 3534 6 1,2102 0 AD bankAddr 03535 3535 1 0,0000 0 CCS A ; CADR is bank addressed?03536 3536 0 1,3547 1 TC DODXCHCALL ; >0 no, just run it, as is

Page 486: Apollo Guidance Computer AGC

03537 3537 0 1,3541 1 TC *+2 ; +0 yes03540 3540 0 1,3541 1 TC *+1 ; <0 yes 03541 3541 3 1,2050 0 CAF ZERO 03542 3542 6 0,0576 0 AD ADDRWD1 03543 3543 5 0,0015 0 TS BANK ; set the bank 03544 3544 7 1,2103 0 MASK lowAddr ; get lowest 10-bits of address03545 3545 6 1,2102 0 AD bankAddr ; set bits 11,12 for fixed-switchable03546 3546 5 0,0576 0 TS ADDRWD1 ; save 12-bit destination address ; put the 14-bit return CADR into A. DODXCHCALL EQU * 03547 3547 4 0,0617 0 CS DCRET ; get 12-bit return address03550 3550 6 1,2102 0 AD bankAddr ; -(12bitAddr)+%600003551 3551 1 0,0000 0 CCS A ; return address is bank addressed?03552 3552 0 1,3561 0 TC DC_NOTBANK ; >0 no, just use it, as is03553 3553 0 1,3555 1 TC *+2 ; +0 yes03554 3554 0 1,3555 1 TC *+1 ; <0 yes 03555 3555 4 1,2102 1 CS bankAddr ; 12bitAddr - %600003556 3556 6 0,0617 1 AD DCRET 03557 3557 6 0,0616 0 AD DCBANK ; put return CADR in A03560 3560 0 1,3563 1 TC *+3 DC_NOTBANK EQU * 03561 3561 3 1,2050 0 CAF ZERO 03562 3562 6 0,0617 1 AD DCRET ; put return CADR in A 03563 3563 2 0,0576 1 INDEX ADDRWD1 ; apply indirect address to next instr.03564 3564 0 0,0000 1 TC 0 ; make the jump ;-------------------------------------------------------------------------- ; BANKCALL ; Do a bank jump to the location referenced by the 14-bit address referenced ; in Q. Does not affect register A (but assumes A does not contain an ; overflow). Functionally identical to POSTJUMP. ; Usage: ; TC BANKCALL ; bank jump to CADR ; DS MYCADR ; the 14-bit address ; returns here if MYCADR calls TC Q. ; ; Inferred from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968. ;-------------------------------------------------------------------------- BANKCALL EQU * 03565 3565 5 0,0612 1 TS BCA ; save A 03566 3566 2 0,0001 1 INDEX Q ; load the CADR into A03567 3567 3 0,0000 1 CAF 0 03570 3570 5 0,0576 0 TS ADDRWD1 ; save 14-bit destination address 03571 3571 3 0,0001 0 XCH Q 03572 3572 5 0,0611 1 TS BCRET ; save old return address-1 03573 3573 3 0,0015 0 XCH BANK 03574 3574 5 0,0610 0 TS BCBANK ; save old bank 03575 3575 4 0,0576 1 CS ADDRWD1 ; -(14bitAddr)+%600003576 3576 6 1,2102 0 AD bankAddr 03577 3577 1 0,0000 0 CCS A ; CADR is bank addressed?03600 3600 0 1,3611 1 TC DOBANKCALL ; >0 no, just run it, as is03601 3601 0 1,3603 1 TC *+2 ; +0 yes03602 3602 0 1,3603 1 TC *+1 ; <0 yes 03603 3603 3 1,2050 0 CAF ZERO 03604 3604 6 0,0576 0 AD ADDRWD1 03605 3605 5 0,0015 0 TS BANK ; set the bank 03606 3606 7 1,2103 0 MASK lowAddr ; get lowest 10-bits of address03607 3607 6 1,2102 0 AD bankAddr ; set bits 11,12 for fixed-switchable03610 3610 5 0,0576 0 TS ADDRWD1 DOBANKCALL EQU * 03611 3611 3 0,0612 1 XCH BCA ; restore A03612 3612 2 0,0576 1 INDEX ADDRWD1 ; apply indirect address to next instr.03613 3613 0 0,0000 1 TC 0 ; make the jump ; Jump returns here; restore the old bank and return 03614 3614 5 0,0612 1 TS BCA ; save A03615 3615 3 0,0610 0 XCH BCBANK 03616 3616 5 0,0015 0 TS BANK

Page 487: Apollo Guidance Computer AGC

03617 3617 3 0,0611 1 XCH BCRET 03620 3620 6 1,2051 1 AD ONE ; skip CADR03621 3621 5 0,0001 0 TS Q 03622 3622 3 0,0612 1 XCH BCA ; restore A03623 3623 0 0,0000 0 RETURN ;-------------------------------------------------------------------------- ; MYBANKCALL ; Functionally identical to BANKCALL. Used for converting the FLASHON/FLASHOFF ; COLOSSUS block II code to block I. In Block II, the V/N flash is controlled by ; setting a bit in an I/O channel. In Block I, a bit in the display table must ; be set using _11DSPIN. Because _11DSPIN is in fixed/switchable memory, but is ; called from fixed/fixed, a bank call function is needed. The original BANKCALL ; could not be used because it is not reentrant and I dont understand its usage ; in COLOSSUS well enough to be certain that FLASHON/FLASHOFF isn't already ; being called somewhere through BANKCALL. ;-------------------------------------------------------------------------- MYBANKCALL EQU * 03624 3624 5 0,0615 0 TS MBCA ; save A 03625 3625 2 0,0001 1 INDEX Q ; load the CADR into A03626 3626 3 0,0000 1 CAF 0 03627 3627 5 0,0576 0 TS ADDRWD1 ; save 14-bit destination address 03630 3630 3 0,0001 0 XCH Q 03631 3631 6 1,2051 1 AD ONE ; skip CADR03632 3632 5 0,0614 1 TS MBCRET ; save old return address 03633 3633 3 0,0015 0 XCH BANK 03634 3634 5 0,0613 0 TS MBCBANK ; save old bank 03635 3635 3 1,2050 0 CAF ZERO 03636 3636 6 0,0576 0 AD ADDRWD1 03637 3637 5 0,0015 0 TS BANK ; set the bank 03640 3640 7 1,2103 0 MASK lowAddr ; get lowest 10-bits of address03641 3641 6 1,2102 0 AD bankAddr ; set bits 11,12 for fixed-switchable03642 3642 5 0,0576 0 TS ADDRWD1 03643 3643 3 0,0615 0 XCH MBCA ; restore A03644 3644 2 0,0576 1 INDEX ADDRWD1 ; apply indirect address to next instr.03645 3645 0 0,0000 1 TC 0 ; make the jump ; Jump returns here; restore the old bank and return 03646 3646 5 0,0615 0 TS MBCA ; save A03647 3647 3 0,0613 0 XCH MBCBANK 03650 3650 5 0,0015 0 TS BANK 03651 3651 3 0,0615 0 XCH MBCA ; restore A03652 3652 0 0,0614 1 TC MBCRET ;-------------------------------------------------------------------------- ; POSTJUMP ; Do a bank jump to the location referenced by the 14-bit address referenced ; in Q. Does not affect register A (but assumes A does not contain an ; overflow). Functionally identical to BANKCALL ; Usage: ; TC POSTJUMP ; bank jump to CADR ; DS MYCADR ; the 14-bit address ; returns here if MYCADR calls TC Q. ; ; Inferred from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968. ;-------------------------------------------------------------------------- POSTJUMP EQU * 03653 3653 5 0,0607 0 TS PJA ; save A 03654 3654 2 0,0001 1 INDEX Q ; load the CADR into A03655 3655 3 0,0000 1 CAF 0 03656 3656 5 0,0576 0 TS ADDRWD1 ; save 14-bit destination address 03657 3657 3 0,0001 0 XCH Q 03660 3660 5 0,0606 1 TS PJRET ; save old return address-1 03661 3661 3 0,0015 0 XCH BANK 03662 3662 5 0,0605 1 TS PJBANK ; save old bank 03663 3663 4 0,0576 1 CS ADDRWD1 ; -(14bitAddr)+%600003664 3664 6 1,2102 0 AD bankAddr 03665 3665 1 0,0000 0 CCS A ; CADR is bank addressed?03666 3666 0 1,3677 1 TC DOPOSTJUMP ; >0 no, just run it, as is

Page 488: Apollo Guidance Computer AGC

03667 3667 0 1,3671 1 TC *+2 ; +0 yes03670 3670 0 1,3671 1 TC *+1 ; <0 yes 03671 3671 3 1,2050 0 CAF ZERO 03672 3672 6 0,0576 0 AD ADDRWD1 03673 3673 5 0,0015 0 TS BANK ; set the bank 03674 3674 7 1,2103 0 MASK lowAddr ; get lowest 10-bits of address03675 3675 6 1,2102 0 AD bankAddr ; set bits 11,12 for fixed-switchable03676 3676 5 0,0576 0 TS ADDRWD1 DOPOSTJUMP EQU * 03677 3677 3 0,0607 0 XCH PJA ; restore A03700 3700 2 0,0576 1 INDEX ADDRWD1 ; apply indirect address to next instr.03701 3701 0 0,0000 1 TC 0 ; make the jump ; Jump returns here; restore the old bank and return 03702 3702 5 0,0607 0 TS PJA ; save A 03703 3703 3 0,0605 1 XCH PJBANK 03704 3704 5 0,0015 0 TS BANK 03705 3705 3 0,0606 1 XCH PJRET 03706 3706 6 1,2051 1 AD ONE ; skip CADR03707 3707 5 0,0001 0 TS Q 03710 3710 3 0,0607 0 XCH PJA ; restore A03711 3711 0 0,0000 0 RETURN ;-------------------------------------------------------------------------- ; BANKJUMP ; Do a bank jump to the location referenced by the 14-bit address in A. ; Usage: ; CADRSTOR DS MYCADR ; ; CAF CADRSTOR ; load the 14-bit address ; TC BANKJUMP ; bank jump to CADR ; returns here if MYCADR calls TC Q ; ; Inferred from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968. ;-------------------------------------------------------------------------- BANKJUMP EQU * 03712 3712 5 0,0576 0 TS ADDRWD1 ; save 14-bit destination address 03713 3713 3 0,0001 0 XCH Q 03714 3714 5 0,0604 0 TS BJRET ; save old return address 03715 3715 3 0,0015 0 XCH BANK 03716 3716 5 0,0603 1 TS BJBANK ; save old bank 03717 3717 4 0,0576 1 CS ADDRWD1 ; -(14bitAddr)+%600003720 3720 6 1,2102 0 AD bankAddr 03721 3721 1 0,0000 0 CCS A ; CADR is bank addressed?03722 3722 0 1,3733 0 TC DOBANKJUMP ; >0 no, just run it, as is03723 3723 0 1,3725 1 TC *+2 ; +0 yes03724 3724 0 1,3725 1 TC *+1 ; <0 yes 03725 3725 3 1,2050 0 CAF ZERO 03726 3726 6 0,0576 0 AD ADDRWD1 03727 3727 5 0,0015 0 TS BANK ; set the bank 03730 3730 7 1,2103 0 MASK lowAddr ; get lowest 10-bits of address03731 3731 6 1,2102 0 AD bankAddr ; set bits 11,12 for fixed-switchable03732 3732 5 0,0576 0 TS ADDRWD1 DOBANKJUMP EQU * 03733 3733 2 0,0576 1 INDEX ADDRWD1 ; apply indirect address to next instr.03734 3734 0 0,0000 1 TC 0 ; make the jump ; Jump returns here; restore the old bank and return 03735 3735 3 0,0603 1 XCH BJBANK 03736 3736 5 0,0015 0 TS BANK 03737 3737 3 0,0604 0 XCH BJRET 03740 3740 5 0,0001 0 TS Q 03741 3741 0 0,0000 0 RETURN ;-------------------------------------------------------------------------- ; DATACALL ; Retrieve memory contents at location referenced by the 14-bit address in A. ; Usage:

Page 489: Apollo Guidance Computer AGC

; CADRSTOR DS MYCADR ; ; CAF CADRSTOR ; load the 14-bit address ; TC DATACALL ; return data in A ; ; Inferred from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968. ;-------------------------------------------------------------------------- DATACALL EQU * 03742 3742 5 0,0576 0 TS ADDRWD1 ; save 14-bit address 03743 3743 3 0,0001 0 XCH Q 03744 3744 5 0,0604 0 TS BJRET ; save old return address 03745 3745 3 0,0015 0 XCH BANK 03746 3746 5 0,0603 1 TS BJBANK ; save old bank 03747 3747 4 0,0576 1 CS ADDRWD1 ; -(14bitAddr)+%600003750 3750 6 1,2102 0 AD bankAddr 03751 3751 1 0,0000 0 CCS A ; CADR is bank addressed?03752 3752 0 1,3763 0 TC DODATACALL ; >0 no, just use it, as is03753 3753 0 1,3755 0 TC *+2 ; +0 yes03754 3754 0 1,3755 0 TC *+1 ; <0 yes 03755 3755 3 1,2050 0 CAF ZERO 03756 3756 6 0,0576 0 AD ADDRWD1 03757 3757 5 0,0015 0 TS BANK ; set the bank 03760 3760 7 1,2103 0 MASK lowAddr ; get lowest 10-bits of address03761 3761 6 1,2102 0 AD bankAddr ; set bits 11,12 for fixed-switchable03762 3762 5 0,0576 0 TS ADDRWD1 DODATACALL EQU * 03763 3763 3 1,2050 0 CAF ZERO 03764 3764 2 0,0576 1 INDEX ADDRWD1 ; apply indirect address to next instr.03765 3765 6 0,0000 1 AD 0 ; load the word 03766 3766 3 0,0603 1 XCH BJBANK ; restore the old bank03767 3767 5 0,0015 0 TS BANK 03770 3770 3 0,0603 1 XCH BJBANK ; get the word03771 3771 0 0,0604 0 TC BJRET ; return INCL T4rupt_f.asm ; T4RUPT handler ;========================================================================== ; T4RUPT (file:T4rupt_f.asm) ; ; Version: 1.0 ; Author: John Pultorak ; Date: 01/09/2002 ; ; PURPOSE: ; Contains T4RUPT handler and DSPOUT subroutine to update DSKY. ;========================================================================== ; RELTAB is a packed table. RELAYWORD code in upper 4 bits, RELAY code ; in lower 5 bits. In COLOSSUS, p. 129. RELTAB EQU * 03772 3772 04025 1 DS %04025 03773 3773 10003 0 DS %10003 03774 3774 14031 0 DS %14031 03775 3775 20033 0 DS %20033 03776 3776 24017 1 DS %24017 03777 3777 30036 1 DS %30036 04000 4000 34034 1 DS %34034 04001 4001 40023 1 DS %40023 04002 4002 44035 1 DS %44035 04003 4003 50037 0 DS %50037 04004 4004 54000 0 DS %54000 04005 4005 60000 1 RELTAB11 DS %60000 ;-------------------------------------------------------------------------- ; DK_initDK - INITIALIZE DSKY ; ; Subroutine initializes the eraseable memory segment for DSKY displays. ; Blank DSKY registers program, verb, noun, R1, R2, R3. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, Fresh Start and Restart, p.187. ;-------------------------------------------------------------------------- 04006 4006 05265 0 DKTESTINIT DS %5265 ; init DSKY to all zeroes (TEST ONLY)

Page 490: Apollo Guidance Computer AGC

DK_initDK EQU * 04007 4007 3 0,0001 0 XCH Q 04010 4010 5 0,0546 0 TS DK_IN_saveQ ; save return address 04011 4011 3 1,2060 0 CAF TEN ; blank DSKY registers04012 4012 5 0,0130 0 DSPOFF TS MPAC 04013 4013 4 1,2065 1 CS BIT12 ; CS DKTESTINIT ; set display to '0' 04014 4014 2 0,0130 1 INDEX MPAC 04015 4015 5 0,0512 1 TS DSPTAB 04016 4016 1 0,0130 1 CCS MPAC 04017 4017 0 2,4012 0 TC DSPOFF ; followed by additional DSKY initialization p 187, 188) 04020 4020 3 1,2050 0 CAF ZERO 04021 4021 5 0,0465 0 TS DSPCNT 04022 4022 5 0,0531 0 TS CADRSTOR 04023 4023 5 0,0502 0 TS REQRET 04024 4024 5 0,0504 0 TS CLPASS 04025 4025 5 0,0501 0 TS DSPLOCK 04026 4026 5 0,0507 0 TS MONSAVE ; kill monitor04027 4027 5 0,0510 0 TS MONSAVE1 04030 4030 5 0,0470 1 TS VERBREG 04031 4031 5 0,0471 0 TS NOUNREG 04032 4032 5 0,0532 0 TS DSPLIST 04033 4033 3 1,2105 1 CAF NOUTCON 04034 4034 5 0,0505 1 TS NOUT ; set DSKY display bit (sign bit). Word must be negative, but ; not minus zero (find out where they do this in COLOSSUS) 04035 4035 4 1,2051 0 CS ONE 04036 4036 5 0,0355 1 TS FLAGWRD5 ; initialize DSPCNT (index into DSPTAB). 04037 4037 3 1,2050 0 CAF ZERO 04040 4040 6 2,4072 0 AD TABLNTH 04041 4041 5 0,0465 0 TS DSPCNT ; schedule 1st T4RUPT 04042 4042 3 2,4074 0 CAF _120MRUPT ; reschedule interrupt for 120 mSec04043 4043 5 0,0040 0 TS TIME4 04044 4044 3 0,0546 0 XCH DK_IN_saveQ 04045 4045 5 0,0001 0 TS Q ; restore return address04046 4046 0 0,0000 0 RETURN ;-------------------------------------------------------------------------- ; T4PROG -- T4RUPT PROGRAM ; ; Performs T4RUPT (DSRUPT) functions. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.129. ;-------------------------------------------------------------------------- T4PROG EQU * 04047 4047 3 0,0001 0 XCH Q 04050 4050 5 0,0544 1 TS T4RET ; save return address 04051 4051 0 2,4116 0 TC DSPOUT ; update DSKY display 04052 4052 3 2,4074 0 CAF _120MRUPT ; reschedule interrupt for 120 mSec04053 4053 5 0,0040 0 TS TIME4 04054 4054 3 0,0544 1 XCH T4RET 04055 4055 5 0,0001 0 TS Q ; restore return address04056 4056 0 0,0000 0 RETURN ;-------------------------------------------------------------------------- ; DSPOUT -- PUTS OUT DISPLAYS ; ; Writes changes in the software display buffer to the AGC DSKY hardware ; display. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.131. ;-------------------------------------------------------------------------- DSPOUTSR EQU *

Page 491: Apollo Guidance Computer AGC

04057 4057 5 0,0505 1 TS NOUT ; decrement NOUT 04060 4060 4 1,2050 1 CS ZERO 04061 4061 5 0,0370 0 TS DSRUPTEM ; set to -0 for 1st pass thru DSPTAB 04062 4062 3 0,0465 0 XCH DSPCNT 04063 4063 6 1,2045 1 AD NEG0 ; to prevent +004064 4064 5 0,0465 0 TS DSPCNT DSPSCAN EQU * 04065 4065 2 0,0465 1 INDEX DSPCNT 04066 4066 1 0,0512 0 CCS DSPTAB ; test sign of DSPTAB + DSPCNT 04067 4067 1 0,0465 1 CCS DSPCNT ; >0, already displayed, test DSPCNT04070 4070 0 2,4063 0 TC DSPSCAN-2 ; if DSPCNT +, again04071 4071 0 2,4103 1 TC DSPLAY ; <0, not yet displayed 04072 4072 00012 1 TABLNTH DS %12 ; dec 10, length of DSPTAB04073 4073 1 0,0370 1 CCS DSRUPTEM ; if DSRUPTEM=+0, 2nd pass thru DSPTAB 04074 4074 37764 0 _120MRUPT DS 16372 ; (DSPCNT=0), +0 into NOUT 04075 4075 5 0,0505 1 TS NOUT ; DSRUPTEM=+0, every table entry was checked04076 4076 0 2,4126 0 TC DSPOUTEXIT ; return 04077 4077 5 0,0370 0 TS DSRUPTEM ; DSRUPTEM=-0, 1st pass thru DSPTAB04100 4100 3 2,4072 0 CAF TABLNTH ; (DSPCNT=0), +0 into DSRUPTEM, pass again04101 4101 0 2,4064 1 TC DSPSCAN-1 04102 4102 0 2,4126 0 TC DSPOUTEXIT ; return DSPLAY EQU * 04103 4103 6 1,2051 1 AD ONE 04104 4104 2 0,0465 1 INDEX DSPCNT 04105 4105 5 0,0512 1 TS DSPTAB ; replace positively04106 4106 7 2,4672 1 MASK LOW11 ; remove bits 12 to 1504107 4107 5 0,0370 0 TS DSRUPTEM 04110 4110 3 2,4666 0 CAF HI5 04111 4111 2 0,0465 1 INDEX DSPCNT 04112 4112 7 1,3772 1 MASK RELTAB ; pick up bits 12 to 15 of RELTAB entry04113 4113 6 0,0370 0 AD DSRUPTEM 04114 4114 5 0,0010 0 TS OUT0 ; was EXTEND/WRITE OUT0 in block II 04115 4115 0 2,4126 0 TC DSPOUTEXIT ; return DSPOUT EQU * 04116 4116 3 0,0001 0 XCH Q 04117 4117 5 0,0545 0 TS DSPOUTRET ; save return address 04120 4120 1 0,0355 0 CCS FLAGWRD5 ; no display unless DSKY flag (sign bit) on04121 4121 3 1,2050 0 CAF ZERO ; >0, DSKY disabled04122 4122 0 2,4126 0 TC NODSPOUT ; +0, DSKY disabled04123 4123 1 0,0505 0 CCS NOUT ; <0, DSKY enabled, so test NOUT04124 4124 0 2,4057 1 TC DSPOUTSR ; >0, handle display requests04125 4125 0 2,4126 0 TC NODSPOUT ; +0, no display requests NODSPOUT EQU * DSPOUTEXIT EQU * 04126 4126 3 0,0545 0 XCH DSPOUTRET ; return to calling routine04127 4127 5 0,0001 0 TS Q 04130 4130 0 0,0000 0 RETURN INCL keyrupt_f.asm ; KEYRUPT handler ;========================================================================== ; KEYRUPT (file:keyrupt_f.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 77. ;========================================================================== ;-------------------------------------------------------------------------- ; KEYRUPT -- KEYBOARD INTERRUPT HANDLER ; ; Performs keyRUPT functions. Triggered by a keyboard key entry. N-key ; rollover, implemented as follows: When an interrupt occurs, the current ; job record is saved and then restored when the job resumes after the ; interrupt. The job record includes MPAC, a set of general purpose ; registers assigned to the job. When the keyboard interrupt occurs, the ; interrupt handler stores the keyboard character in MPAC. A job is then ; started to process the character. The new job copies its MPAC fields from ; the current job, so the character is copied to storage owned by the job. ; When additional keyboard interrupts occur, they start their own jobs. ; Up to 7 jobs can be waiting in a queue for execution, so as many as ; 7 keyboard characters can be enqueued for processing. Since all keyboard ; jobs have the same priority, they are enqueued in the order received.

Page 492: Apollo Guidance Computer AGC

; Its OK for the keyboard handler to modify the MPAC of the interrupted job ; because the interrupted job's record is restored at the end of the ; interrupt service routine. ; ; Not included in my partial AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, so I had to improvise it from the original flow charts in ; E-1574, p.77. ;-------------------------------------------------------------------------- 04131 4131 37776 0 CHRPRIO DS %37776 ; priority of CHARIN job (highest) KEYPROG EQU * 04132 4132 3 0,0001 0 XCH Q 04133 4133 5 0,0601 0 TS KEYRET ; save return address ; prepare to EXEC a job to handle the keystroke. 04134 4134 3 0,0004 0 XCH IN0 04135 4135 7 2,4664 0 MASK LOW5 04136 4136 3 0,0130 0 XCH MPAC ; save keyboard code04137 4137 3 0,0551 0 XCH KP_MPAC ; save previous MPAC ; create the job. It terminates when it finishes processing the key. 04140 4140 3 2,4131 0 CAF CHRPRIO ; CHARIN job priority04141 4141 0 1,3162 1 TC NOVAC 04142 4142 12000 1 CADR CHARIN ; 14 bit CHARIN job address 04143 4143 3 0,0551 0 XCH KP_MPAC 04144 4144 3 0,0130 0 XCH MPAC ; restore previous MPAC 04145 4145 3 0,0601 0 XCH KEYRET 04146 4146 5 0,0001 0 TS Q ; restore return address04147 4147 0 0,0000 0 RETURN INCL math_f.asm ; DP math routines ;========================================================================== ; MATH LIBRARY (file:math_f.asm) ; ; Version: 1.0 ; Author: John Pultorak ; Date: 03/01/2002 ; ; PURPOSE: ; Contains double precision math routines. ;========================================================================== ;-------------------------------------------------------------------------- ; TPAGREE ; Force the signs in a triple precision (TP) word to agree. The word is ; in MPAC, MPAC+1, MPAC+2 ; ; The sign of the corrected number is always the sign of the most-significant ; non-zero word. ; ; This isn't included in my partial COLOSSUS listing, so I had to invent ; my own version. ;-------------------------------------------------------------------------- TPAGREE EQU * 04150 4150 3 0,0001 0 XCH Q 04151 4151 5 0,0577 1 TS MATH_Q ; return address ; Find the sign to convert to. It will be the sign ; of the most significant non-zero word. TPA_SGN0 EQU * 04152 4152 1 0,0130 1 CCS MPAC 04153 4153 0 2,4157 0 TC TPA_P0 ; >0, sign will be +04154 4154 0 2,4241 1 TC TPA_SGN1 ; +0, still don't know sign, check MPAC+104155 4155 0 2,4210 0 TC TPA_M0 ; <0, sign will be -04156 4156 0 2,4241 1 TC TPA_SGN1 ; -0, still don't know sign, check MPAC+1 ; MPAC is non-zero positive, so reconcile signs to a positive number. TPA_P0 EQU * 04157 4157 1 0,0131 0 CCS MPAC+1 04160 4160 0 2,4250 1 TC TPA_P1+2 ; >0, MPAC+1 is OK, check MPAC+204161 4161 0 2,4167 0 TC TPA_PZ0 ; +0, 04162 4162 0 2,4164 0 TC *+2 ; <0, fix MPAC+104163 4163 0 2,4167 0 TC TPA_PZ0 ; -0, 04164 4164 3 2,4317 0 CAF TPA_MPAC0 ; borrow from MPAC to correct MPAC+1

Page 493: Apollo Guidance Computer AGC

04165 4165 0 2,4337 1 TC TPA_FIXP 04166 4166 0 2,4250 1 TC TPA_P1+2 ; MPAC+1 is now non-zero positive; checkMPAC+2 ; MPAC is non-zero positive, MPAC+1 is zero TPA_PZ0 EQU * 04167 4167 1 0,0132 0 CCS MPAC+2 04170 4170 0 2,4175 0 TC *+5 ; >0, zero MPAC+1, MPAC+2 is OK04171 4171 0 2,4173 0 TC *+2 ; +0, MPAC+1, +2 both zero04172 4172 0 2,4200 1 TC TPA_PZ0FIX ; <0, 04173 4173 3 1,2050 0 CAF ZERO ; make sure they're both +004174 4174 5 0,0132 1 TS MPAC+2 04175 4175 3 1,2050 0 CAF ZERO 04176 4176 5 0,0131 1 TS MPAC+1 04177 4177 0 0,0577 1 TC MATH_Q ; MPAC is non-zero positive, MPAC+1 is zero, MPAC+2 is non-zero negative. ; Solution: borrow from MPAC, transfer borrowed value to MPAC+1, but also ; borrow from MPAC+1, use borrowed value to correct MPAC+2. TPA_PZ0FIX EQU * 04200 4200 3 0,0132 1 XCH MPAC+2 ; move MPAC+2 to MPAC+1 so we can use04201 4201 5 0,0131 1 TS MPAC+1 ; our standard correction function 04202 4202 3 2,4317 0 CAF TPA_MPAC0 ; borrow from MPAC to correct MPAC+104203 4203 0 2,4337 1 TC TPA_FIXP 04204 4204 3 2,4315 1 CAF MAXPOS ; move corrected value from MPAC+1 back04205 4205 3 0,0131 1 XCH MPAC+1 ; to MPAC+2. Set MPAC+1 to correct value04206 4206 5 0,0132 1 TS MPAC+2 ; borrowed from MPAC.04207 4207 0 0,0577 1 TC MATH_Q ; The MPAC is non-zero negative, so reconcile signs to a negative number. TPA_M0 EQU * 04210 4210 1 0,0131 0 CCS MPAC+1 04211 4211 0 2,4215 0 TC *+4 ; >0, fix MPAC+104212 4212 0 2,4220 0 TC TPA_MZ0 ; +0, 04213 4213 0 2,4264 0 TC TPA_M1+2 ; <0, MPAC+1 is OK, check MPAC+204214 4214 0 2,4220 0 TC TPA_MZ0 ; -0, 04215 4215 3 2,4317 0 CAF TPA_MPAC0 ; borrow from MPAC to correct MPAC+104216 4216 0 2,4321 0 TC TPA_FIXM 04217 4217 0 2,4264 0 TC TPA_M1+2 ; MPAC is non-zero negative, MPAC+1 is zero TPA_MZ0 EQU * 04220 4220 1 0,0132 0 CCS MPAC+2 04221 4221 0 2,4231 0 TC TPA_MZ0FIX ; >0, 04222 4222 0 2,4224 1 TC *+2 ; +0, MPAC+1, +2 both zero04223 4223 0 2,4226 0 TC *+3 ; <0, zero MPAC+1, MPAC+2 is OK 04224 4224 3 1,2045 1 CAF NEG0 ; make sure they're both -004225 4225 5 0,0132 1 TS MPAC+2 04226 4226 3 1,2045 1 CAF NEG0 04227 4227 5 0,0131 1 TS MPAC+1 04230 4230 0 0,0577 1 TC MATH_Q ; MPAC is non-zero negative, MPAC+1 is zero, MPAC+2 is non-zero positive ; Solution: borrow from MPAC, transfer borrowed value to MPAC+1, but also ; borrow from MPAC+1, use borrowed value to correct MPAC+2. TPA_MZ0FIX EQU * 04231 4231 3 0,0132 1 XCH MPAC+2 ; move MPAC+2 to MPAC+1 so we can use04232 4232 5 0,0131 1 TS MPAC+1 ; our standard correction function 04233 4233 3 2,4317 0 CAF TPA_MPAC0 ; borrow from MPAC to correct MPAC+104234 4234 0 2,4321 0 TC TPA_FIXM 04235 4235 3 2,4316 1 CAF MAXNEG ; move corrected value from MPAC+1 back04236 4236 3 0,0131 1 XCH MPAC+1 ; to MPAC+2. Set MPAC+1 to correct value04237 4237 5 0,0132 1 TS MPAC+2 ; borrowed from MPAC.04240 4240 0 0,0577 1 TC MATH_Q ; MPAC was zero, so we still don't know the sign. Check MPAC+1. TPA_SGN1 EQU * 04241 4241 1 0,0131 0 CCS MPAC+1 04242 4242 0 2,4246 0 TC TPA_P1 ; >0, sign will be +04243 4243 0 2,4277 1 TC TPA_SGN2 ; +0, still don't know sign, check MPAC+204244 4244 0 2,4262 0 TC TPA_M1 ; <0, sign will be -04245 4245 0 2,4277 1 TC TPA_SGN2 ; -0, still don't know sign, check MPAC+2

Page 494: Apollo Guidance Computer AGC

; MPAC+1 is non-zero positive, so reconcile signs to a positive number. TPA_P1 EQU * 04246 4246 3 1,2050 0 CAF ZERO 04247 4247 5 0,0130 0 TS MPAC ; set MPAC to +0 04250 4250 1 0,0132 0 CCS MPAC+2 04251 4251 0 0,0577 1 TC MATH_Q ; >0, all words are positive04252 4252 0 0,0577 1 TC MATH_Q ; +0, all words are positive04253 4253 0 2,4257 0 TC *+4 ; <0, MPAC+2 is nonzero -04254 4254 3 1,2050 0 CAF ZERO ; -0, change to +0 and we're done04255 4255 5 0,0132 1 TS MPAC+2 04256 4256 0 0,0577 1 TC MATH_Q 04257 4257 3 2,4320 1 CAF TPA_MPAC1 ; borrow from MPAC+1 to correct MPAC+204260 4260 0 2,4337 1 TC TPA_FIXP 04261 4261 0 0,0577 1 TC MATH_Q ; MPAC+1 is non-zero negative, so reconcile signs to a negative number. TPA_M1 EQU * 04262 4262 3 1,2045 1 CAF NEG0 04263 4263 5 0,0130 0 TS MPAC ; set MPAC to -0 04264 4264 1 0,0132 0 CCS MPAC+2 04265 4265 0 2,4274 1 TC *+7 ; >0, MPAC+2 is nonzero +04266 4266 0 2,4271 1 TC *+3 ; +0, change to -0 and we're done04267 4267 0 0,0577 1 TC MATH_Q ; <0, all words are negative04270 4270 0 0,0577 1 TC MATH_Q ; -0, all words are negative 04271 4271 3 1,2045 1 CAF NEG0 ; +0, change to -0 and we're done04272 4272 5 0,0132 1 TS MPAC+2 04273 4273 0 0,0577 1 TC MATH_Q 04274 4274 3 2,4320 1 CAF TPA_MPAC1 ; borrow from MPAC+1 to correct MPAC+204275 4275 0 2,4321 0 TC TPA_FIXM 04276 4276 0 0,0577 1 TC MATH_Q ; MPAC and MPAC+1 were both zero, so we still don't know the sign. ; Check MPAC+2. TPA_SGN2 EQU * 04277 4277 1 0,0132 0 CCS MPAC+2 04300 4300 0 2,4304 1 TC TPA_P2 ; >0, sign is +04301 4301 0 2,4310 1 TC TPA_P3 ; +0, number is all zeros04302 4302 0 2,4306 0 TC TPA_M2 ; <0, sign is -04303 4303 0 2,4310 1 TC TPA_P3 ; -0, number is all zeros 04304 4304 3 1,2050 0 TPA_P2 CAF ZERO 04305 4305 0 2,4312 0 TC *+5 ; set MPAC, MPAC+1 to +0 04306 4306 3 1,2045 1 TPA_M2 CAF NEG0 ; set MPAC, MPAC+1 to -004307 4307 0 2,4312 0 TC *+3 04310 4310 3 1,2050 0 TPA_P3 CAF ZERO 04311 4311 5 0,0132 1 TS MPAC+2 ; set MPAC, MPAC+1, MPAC+2 to +0 04312 4312 5 0,0131 1 TS MPAC+1 04313 4313 5 0,0130 0 TS MPAC 04314 4314 0 0,0577 1 TC MATH_Q 04315 4315 37777 1 MAXPOS DS %37777 ; largest non-overflow pos number04316 4316 40000 0 MAXNEG DS %40000 ; largest non-overflow neg number 04317 4317 00130 0 TPA_MPAC0 DS MPAC 04320 4320 00131 1 TPA_MPAC1 DS MPAC+1 ;-------------------------------------------------------------------------- ; TPA_FIXM ; Reconcile the signs in a double precision word. The most significant word ; is in C(A), the lesser word in C(A+1). Reconcilliation occurs by borrowing ; from C(A) and adding the borrowed amount to C(A+1). C(A) is assumed to be ; negative non-zero number and C(A+1) positive non-zero. The reconciliation ; makes both numbers negative. ; ; This is part of my implementation of TPAGREE. ;-------------------------------------------------------------------------- TPA_FIXM EQU * 04321 4321 5 0,0576 0 TS ADDRWD1 04322 4322 2 0,0576 1 INDEX ADDRWD1 04323 4323 4 0,0000 0 CS 0 ; borrow from 1st word

Page 495: Apollo Guidance Computer AGC

04324 4324 1 0,0000 0 CCS A 04325 4325 4 0,0000 0 COM 04326 4326 2 0,0576 1 INDEX ADDRWD1 04327 4327 5 0,0000 1 TS 0 04330 4330 3 2,4316 1 CAF MAXNEG 04331 4331 6 1,2046 1 AD NEG1 ; create negative overflow04332 4332 2 0,0576 1 INDEX ADDRWD1 04333 4333 6 0,0001 0 AD 1 ; correct 2nd word, changes sign04334 4334 2 0,0576 1 INDEX ADDRWD1 04335 4335 5 0,0001 0 TS 1 04336 4336 0 0,0001 0 TC Q ;-------------------------------------------------------------------------- ; TPA_FIXP ; Reconcile the signs in a double precision word. The most significant word ; is in C(A), the lesser word in C(A+1). Reconcilliation occurs by borrowing ; from C(A) and adding the borrowed amount to C(A+1). C(A) is assumed to be ; positive non-zero number and C(A+1) negative non-zero. The reconciliation ; makes both numbers positive. ; ; This is part of my implementation of TPAGREE. ;-------------------------------------------------------------------------- TPA_FIXP EQU * 04337 4337 5 0,0576 0 TS ADDRWD1 04340 4340 2 0,0576 1 INDEX ADDRWD1 04341 4341 1 0,0000 0 CCS 0 ; borrow from 1st word04342 4342 2 0,0576 1 INDEX ADDRWD1 04343 4343 5 0,0000 1 TS 0 04344 4344 3 2,4315 1 CAF MAXPOS 04345 4345 6 1,2051 1 AD ONE ; create positive overflow04346 4346 2 0,0576 1 INDEX ADDRWD1 04347 4347 6 0,0001 0 AD 1 ; correct 2nd word, changes sign04350 4350 2 0,0576 1 INDEX ADDRWD1 04351 4351 5 0,0001 0 TS 1 04352 4352 0 0,0001 0 TC Q ;-------------------------------------------------------------------------- ; SHORTMP -- MULTIPLY DOUBLE WORD BY A SINGLE WORD ; Multiply C(MPAC, MPAC+1) by the contents of A. Put the product in MPAC, ; MPAC+1, MPAC+2. ;; ; These aren't included in my partial COLOSSUS listing, so I had to invent ; my own version. ;-------------------------------------------------------------------------- SHORTMP EQU * 04353 4353 5 0,0573 0 TS SHORTMP_A ; MPAC+2 = MPAC+1 * A 04354 4354 2 0,0000 1 EXTEND 04355 4355 4 0,0131 0 MP MPAC+1 04356 4356 5 0,0574 1 TS SHORTMP_OVFL 04357 4357 3 0,0003 1 XCH LP 04360 4360 5 0,0132 1 TS MPAC+2 ; MPAC+1 = (MPAC * A) + overflow 04361 4361 3 0,0573 0 XCH SHORTMP_A 04362 4362 2 0,0000 1 EXTEND 04363 4363 4 0,0130 1 MP MPAC 04364 4364 5 0,0575 0 TS SHORTMP_OVFH 04365 4365 3 0,0003 1 XCH LP 04366 4366 6 0,0574 1 AD SHORTMP_OVFL 04367 4367 5 0,0131 1 TS MPAC+1 ; skip on overflow04370 4370 3 1,2050 0 CAF ZERO ; otherwise, make interword carry=0 ; MPAC = overflow 04371 4371 6 0,0575 0 AD SHORTMP_OVFH 04372 4372 5 0,0130 0 TS MPAC 04373 4373 0 0,0001 0 TC Q ; return ;-------------------------------------------------------------------------- ; DMP -- DOUBLE PRECISION MULTIPLY ; Multiply val, val+1 with C(MPAC, MPAC+1). 'ADDRWD1' contains the ; address of 'val'. The product appears in MPAC, MPAC+1, MPAC+2 ; ; This isn't included in my partial COLOSSUS listing, but is taken from

Page 496: Apollo Guidance Computer AGC

; the double precision math examples in R-393. ;-------------------------------------------------------------------------- DMP EQU * 04374 4374 2 0,0001 1 INDEX Q 04375 4375 3 0,0000 1 CAF 0 04376 4376 6 2,5777 0 AD EXTENDER 04377 4377 5 0,0576 0 TS ADDRWD1 04400 4400 3 0,0131 1 XCH MPAC+1 04401 4401 5 0,0034 0 TS OVCTR 04402 4402 2 0,0576 1 INDEX ADDRWD1 04403 4403 4 0,0001 1 MP 1 04404 4404 3 0,0034 0 XCH OVCTR 04405 4405 2 0,0576 1 INDEX ADDRWD1 04406 4406 4 0,0000 0 MP 0 04407 4407 3 0,0034 0 XCH OVCTR 04410 4410 6 0,0003 1 AD LP 04411 4411 3 0,0130 0 XCH MPAC 04412 4412 5 0,0132 1 TS MPAC+2 04413 4413 2 0,0576 1 INDEX ADDRWD1 04414 4414 4 0,0001 1 MP 1 04415 4415 3 0,0034 0 XCH OVCTR 04416 4416 3 0,0130 0 XCH MPAC 04417 4417 6 0,0003 1 AD LP 04420 4420 3 0,0132 1 XCH MPAC+2 04421 4421 2 0,0576 1 INDEX ADDRWD1 04422 4422 4 0,0000 0 MP 0 04423 4423 3 0,0034 0 XCH OVCTR 04424 4424 6 0,0130 0 AD MPAC 04425 4425 6 0,0003 1 AD LP 04426 4426 3 0,0131 1 XCH MPAC+1 04427 4427 3 0,0034 0 XCH OVCTR 04430 4430 5 0,0130 0 TS MPAC 04431 4431 3 0,0001 0 XCH Q ; skip next word on return04432 4432 6 1,2051 1 AD ONE 04433 4433 5 0,0001 0 TS Q 04434 4434 0 0,0001 0 TC Q BANKFF_1 EQU * ;------------------------------------------------------------------------- ; PINBALL ; ; Now, do the "pinball game" (DSKY) routines. ; ; Mimic the bank assignments in COLOSSUS. Since this is a block I AGC that ; has fewer banks, different bank numbers are used, but the sequence and ; relative allocation of routines to various banks is preserved. ;------------------------------------------------------------------------- ; don't change BANK04_1 without also changing V37BANK BANK04_1 EQU BANK4 ; was BANK 04 in COLOSSUS BANK40_1 EQU BANK5 ; was BANK 40 in COLOSSUS BANK41_1 EQU BANK6 ; was BANK 41 in COLOSSUS BANK42_1 EQU BANK7 ; was BANK 42 in COLOSSUS BANK43_1 EQU BANK10 ; was BANK 43 in COLOSSUS ; start of COLOSSUS routines ORG BANK04_1 ; COLOSSUS pp. 192-204 INCL bank04_1.asm ;========================================================================== ; MAJOR MODE CHANGE (file:bank04_1.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 192-204. ;========================================================================== ;-------------------------------------------------------------------------- ; VERB 37 ; ; In COLOSSUS, a successful V37 apparently also restarts the AGC. Here, ; we implement a subset of COLOSSUS to kick off a job associated with the ; verb. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.192-204. ;--------------------------------------------------------------------------

Page 497: Apollo Guidance Computer AGC

V37 EQU * ; verb 3710000 4,0000 5 0,0464 1 TS MMNUMBER ; save major mode ; ** skipped quite a bit of guidance system-related code ** 10001 4,0001 0 4,6005 1 TC CHECKTAB ; ** skipped more guidance system-related code ** V37BAD EQU * 10002 4,0002 0 2,5003 1 TC RELDSP ; releases display from astronaut10003 4,0003 0 1,3653 1 TC POSTJUMP ; bring back last normal display if there10004 4,0004 05067 0 CADR PINBRNCH ; was one, OY ; Search table for entry matching major mode number. Table entries ; are sorted by major mode number, so the search occurs in order from ; lowest number to highest. CHECKTAB EQU * 10005 4,0005 3 1,2050 0 CAF ZERO ; was CA NOV37MM in Block II10006 4,0006 6 4,6046 0 AD NOV37MM ; the no. of MM in table (minus 1) 10007 4,0007 5 0,0131 1 AGAINMM TS MPAC+1 10010 4,0010 3 1,2050 0 CAF ZERO ; was CA PREMM1 in Block II10011 4,0011 2 0,0131 0 INDEX MPAC+1 10012 4,0012 6 4,6037 0 AD PREMM1 ; obtain which MM this is for10013 4,0013 7 1,2101 1 MASK LOW7 10014 4,0014 4 0,0000 0 COM 10015 4,0015 6 0,0464 1 AD MMNUMBER 10016 4,0016 1 0,0000 0 CCS A ; MMNUMBER - current table MM number 10017 4,0017 1 0,0131 0 CCS MPAC+1 ; if GR, see if anymore in list10020 4,0020 0 4,6007 0 TC AGAINMM ; yes, get next one (was TCF)10021 4,0021 0 4,6026 0 TC V37NONO ; last time or passed MM (was TCF) ; Found the index into the major mode table for entry matching the ; major mode number input by the user. 10022 4,0022 3 1,2050 0 CAF ZERO ; was CA MPAC+1 in Block II10023 4,0023 6 0,0131 1 AD MPAC+1 10024 4,0024 5 0,0463 0 TS MINDEX ; save index for later 10025 4,0025 0 1,2147 1 TC goMMchange ; in Block II, jumped to restart AGC ; Requested MM doesn't exist V37NONO EQU * 10026 4,0026 0 2,4701 0 TC FALTON ; come here if MM requested doesn't exist10027 4,0027 0 4,6002 0 TC V37BAD ;-------------------------------------------------------------------------- ; FCADRMM ; ; For verb 37, two tables are maintained. Each table has an entry for each ; major mode that can be started from the keyboard. The entries are put ; into the table with the entry for the highest major mode coming first, ; to the lowest major mode which is the last entry in the table. ; ; The FCADRMM table contains the FCADR of the starting job of the major mode. ; ; The entries in this table must match the entries in PREMM1 below. ;-------------------------------------------------------------------------- FCADRMM1 EQU * 10030 4,0030 22147 0 CADR P79 10031 4,0031 22142 0 CADR P78 10032 4,0032 22127 0 CADR P04 10033 4,0033 22066 1 CADR P03 10034 4,0034 22036 1 CADR P02 10035 4,0035 22022 1 CADR P01 10036 4,0036 22000 1 CADR P00 ; etc ********* ;-------------------------------------------------------------------------- ; PREMM1 ; ; The PREMM1 table contains the E-bank, major mode, and priority information. ; It is in the following form: ; ; PPP PPE EEM MMM MMM ; ; Where, ; the 7 'M' bits contain the major mode number

Page 498: Apollo Guidance Computer AGC

; the 3 'E' bits contain the E-bank number (ignored in Block I) ; the 5 'P' bits contain the priority at which the job is to be started ; ; The entries in this table must match the entries in FCADRMM1 above. ;-------------------------------------------------------------------------- PREMM1 EQU * 10037 4,0037 26117 1 DS %26117 ; MM 79, PRIO 1310040 4,0040 26116 0 DS %26116 ; MM 78, PRIO 1310041 4,0041 26004 1 DS %26004 ; MM 04, PRIO 1310042 4,0042 26003 0 DS %26003 ; MM 03, PRIO 1310043 4,0043 26002 1 DS %26002 ; MM 02, PRIO 1310044 4,0044 26001 1 DS %26001 ; MM 01, PRIO 1310045 4,0045 26000 0 DS %26000 ; MM 00, PRIO 13 ; etc ********* EPREMM1 EQU * 10046 4,0046 00006 1 NOV37MM DS EPREMM1-PREMM1-1 ; number of entries in table (minus 1) BANK04_2 EQU * ORG BANK40_1 ; COLOSSUS pp. 310-317 INCL bank40_1.asm ;========================================================================== ; PINBALL GAME (file:bank40_1.asm) ; ; AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.310-317. ;========================================================================== ;-------------------------------------------------------------------------- ; CHARIN -- PROCESS KEYBOARD CHARACTER FROM KEYRUPT ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.310. ;-------------------------------------------------------------------------- CHARIN EQU * 12000 5,0000 3 1,2051 1 CAF ONE ; block display syst12001 5,0001 3 0,0501 0 XCH DSPLOCK ; make dsp syst busy, but save old12002 5,0002 5 0,0412 0 TS _2122REG ; C(DSPLOCK) for error light reset12003 5,0003 1 0,0531 1 CCS CADRSTOR ; all keys except ER turn on KR lite if12004 5,0004 0 5,6006 1 TC *+2 ; CADRSTOR is full. This reminds operator12005 5,0005 0 5,6016 0 TC CHARIN2 ; to re-establish a flashing display12006 5,0006 4 5,6062 1 CS ELRCODE1 ; which he has obscured with displays of12007 5,0007 6 0,0130 0 AD MPAC ; his own (see remarks preceding routine ; VBRELDSP). 12010 5,0010 1 0,0000 0 CCS A ; was BZF CHARIN2 in Block II12011 5,0011 0 5,6015 0 TC *+4 ; >012012 5,0012 0 5,6014 1 TC *+2 ; +012013 5,0013 0 5,6015 0 TC *+2 ; <012014 5,0014 0 5,6016 0 TC CHARIN2 ; -0 12015 5,0015 0 2,4713 0 TC RELDSPON CHARIN2 EQU * 12016 5,0016 3 0,0130 0 XCH MPAC 12017 5,0017 5 0,0414 0 TS CHAR 12020 5,0020 2 0,0000 0 INDEX A 12021 5,0021 0 5,6022 1 TC *+1 ; input_code function12022 5,0022 0 5,7307 1 TC CHARALRM ; 012023 5,0023 0 5,6101 1 TC NUM ; 112024 5,0024 0 5,6101 1 TC NUM ; 212025 5,0025 0 5,6101 1 TC NUM ; 312026 5,0026 0 5,6101 1 TC NUM ; 412027 5,0027 0 5,6101 1 TC NUM ; 512030 5,0030 0 5,6101 1 TC NUM ; 612031 5,0031 0 5,6101 1 TC NUM ; 712032 5,0032 0 5,6065 1 TC _89TEST 12033 5,0033 0 5,6065 1 TC _89TEST ; 11 912034 5,0034 0 5,7307 1 TC CHARALRM ; 1212035 5,0035 0 5,7307 1 TC CHARALRM ; 1312036 5,0036 0 5,7307 1 TC CHARALRM ; 1412037 5,0037 0 5,7307 1 TC CHARALRM ; 1512040 5,0040 0 5,7307 1 TC CHARALRM ; 1612041 5,0041 0 5,7307 1 TC CHARALRM ; 1712042 5,0042 0 5,6077 1 TC NUM-2 ; 20 012043 5,0043 0 5,6272 0 TC VERB ; 21 VERB12044 5,0044 0 5,7462 0 TC ERROR ; 22 ERROR LIGHT RESET12045 5,0045 0 5,7307 1 TC CHARALRM ; 2312046 5,0046 0 5,7307 1 TC CHARALRM ; 2412047 5,0047 0 5,7307 1 TC CHARALRM ; 2512050 5,0050 0 5,7307 1 TC CHARALRM ; 2612051 5,0051 0 5,7307 1 TC CHARALRM ; 2712052 5,0052 0 5,7307 1 TC CHARALRM ; 3012053 5,0053 0 5,7327 0 TC VBRELDSP ; 31 KEY RELEASE

Page 499: Apollo Guidance Computer AGC

12054 5,0054 0 5,6326 0 TC POSGN ; 32 +12055 5,0055 0 5,6312 1 TC NEGSGN ; 33 -12056 5,0056 0 5,6063 1 TC ENTERJMP ; 34 ENTER12057 5,0057 0 5,7307 1 TC CHARALRM ; 3512060 5,0060 0 5,6412 0 TC CLEAR ; 36 CLEAR12061 5,0061 0 5,6306 1 TC NOUN ; 37 NOUN 12062 5,0062 00022 1 ELRCODE1 DS %22 12063 5,0063 0 1,3653 1 ENTERJMP TC POSTJUMP 12064 5,0064 14002 0 DS ENTER _89TEST EQU * 12065 5,0065 1 0,0466 1 CCS DSPCOUNT 12066 5,0066 0 5,6072 1 TC *+4 ; >012067 5,0067 0 5,6072 1 TC *+3 ; +012070 5,0070 0 1,2723 0 TC ENDOFJOB ; <0, block data in if DSPCOUNT is <0 or -012071 5,0071 0 1,2723 0 TC ENDOFJOB ; -0 12072 5,0072 3 1,2053 0 CAF THREE 12073 5,0073 7 0,0467 0 MASK DECBRNCH 12074 5,0074 1 0,0000 0 CCS A 12075 5,0075 0 5,6101 1 TC NUM ; if DECBRNCH is +, 8 or 9 OK12076 5,0076 0 5,7307 1 TC CHARALRM ; if DECBRNCH is +0, reject 8 or 9 ;-------------------------------------------------------------------------- ; NUM -- PROCESS NUMERICAL KEYBOARD CHARACTER ; Assembles octal, 3 bits at a time. For decimal, it converts incoming word ; as a fraction, keeping results to DP (double precision). ; Octal results are left in XREG, YREG, or ZREG. High part of DEC in XREG, ; YREG, ZREG; the low parts in XREGLP, YREGLP, or ZREGLP). ; DECBRNCH is left at +0 for octal, +1 for +DEC, +2 for -DEC. ; If DSPCOUNT was left -, no more data is accepted. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.311. ;-------------------------------------------------------------------------- 12077 5,0077 3 1,2050 0 CAF ZERO 12100 5,0100 5 0,0414 0 TS CHAR NUM EQU * 12101 5,0101 1 0,0466 1 CCS DSPCOUNT 12102 5,0102 0 5,6106 0 TC *+4 ; >012103 5,0103 0 5,6106 0 TC *+3 ; +012104 5,0104 0 5,6105 0 TC *+1 ; <0, block datain if DSPCOUNT is <0 or -012105 5,0105 0 1,2723 0 TC ENDOFJOB ; -012106 5,0106 0 5,6241 0 TC GETINREL 12107 5,0107 1 0,0504 1 CCS CLPASS ; if CLPASS is >0 or +0, make it +012110 5,0110 3 1,2050 0 CAF ZERO 12111 5,0111 5 0,0504 0 TS CLPASS 12112 5,0112 0 5,6113 1 TC *+1 12113 5,0113 2 0,0414 1 INDEX CHAR 12114 5,0114 3 1,3772 0 CAF RELTAB 12115 5,0115 7 2,4664 0 MASK LOW5 12116 5,0116 5 0,0421 0 TS CODE 12117 5,0117 3 1,2050 0 CAF ZERO ; was CA DSPCOUNT in Block II12120 5,0120 6 0,0466 0 AD DSPCOUNT 12121 5,0121 5 0,0440 1 TS COUNT 12122 5,0122 0 5,7161 0 TC DSPIN 12123 5,0123 3 1,2053 0 CAF THREE 12124 5,0124 7 0,0467 0 MASK DECBRNCH 12125 5,0125 1 0,0000 0 CCS A ; +0=octal, +1=+dec, +2=-dec12126 5,0126 0 5,6137 1 TC DECTOBIN ; >012127 5,0127 2 0,0434 0 INDEX INREL ; +0 (octal)12130 5,0130 3 0,0470 1 XCH VERBREG 12131 5,0131 5 0,0022 1 TS CYL 12132 5,0132 4 0,0022 0 CS CYL 12133 5,0133 4 0,0022 0 CS CYL 12134 5,0134 3 0,0022 1 XCH CYL 12135 5,0135 6 0,0414 0 AD CHAR 12136 5,0136 0 5,6155 0 TC ENDNMTST DECTOBIN EQU * 12137 5,0137 2 0,0434 0 INDEX INREL 12140 5,0140 3 0,0470 1 XCH VERBREG 12141 5,0141 5 0,0130 0 TS MPAC ; sum x 2EXP-14 in MPAC12142 5,0142 3 1,2050 0 CAF ZERO 12143 5,0143 5 0,0131 1 TS MPAC+1 12144 5,0144 3 1,2060 0 CAF TEN ; 10 x 3EXP-1412145 5,0145 0 2,4353 0 TC SHORTMP ; 10SUM x 2EXP-28 in MPAC, MPAC+1 12146 5,0146 3 0,0131 1 XCH MPAC+1 12147 5,0147 6 0,0414 0 AD CHAR 12150 5,0150 5 0,0131 1 TS MPAC+1 12151 5,0151 0 5,6155 0 TC ENDNMTST ; no overflow 12152 5,0152 6 0,0130 0 AD MPAC ; overflow, must be 5th character

Page 500: Apollo Guidance Computer AGC

12153 5,0153 5 0,0130 0 TS MPAC 12154 5,0154 0 5,6176 1 TC DECEND ENDNMTST EQU * 12155 5,0155 2 0,0434 0 INDEX INREL 12156 5,0156 5 0,0470 1 TS VERBREG 12157 5,0157 4 0,0466 1 CS DSPCOUNT 12160 5,0160 2 0,0434 0 INDEX INREL 12161 5,0161 6 5,6232 1 AD CRITCON 12162 5,0162 1 0,0000 0 CCS A ; was BZF ENDNUM in Block II12163 5,0163 0 5,6167 1 TC *+4 ; >012164 5,0164 0 5,6166 0 TC *+2 ; +0, DSPCOUNT = CRITCON12165 5,0165 0 5,6167 1 TC *+2 ; <012166 5,0166 0 5,6170 1 TC ENDNUM ; -0 12167 5,0167 0 5,6227 0 TC MORNUM ; - , DSPCOUNT G/ CRITCON ENDNUM EQU * 12170 5,0170 3 1,2053 0 CAF THREE 12171 5,0171 7 0,0467 0 MASK DECBRNCH 12172 5,0172 1 0,0000 0 CCS A 12173 5,0173 0 5,6176 1 TC DECEND ENDALL EQU * 12174 5,0174 4 0,0466 1 CS DSPCOUNT ; block NUMIN by placing DSPCOUNT12175 5,0175 0 5,6230 0 TC MORNUM+1 ; negatively DECEND EQU * 12176 5,0176 4 1,2051 0 CS ONE 12177 5,0177 6 0,0434 1 AD INREL 12200 5,0200 1 0,0000 0 CCS A ; was BZMF ENDALL in Block II12201 5,0201 0 5,6205 0 TC *+4 ; >012202 5,0202 0 5,6204 1 TC *+2 ; +0, INREL=0,1(VBREG,NNREG), leave whole12203 5,0203 0 5,6204 1 TC *+1 ; <0, INREL=0,1(VBREG,NNREG), leave whole12204 5,0204 0 5,6174 0 TC ENDALL ; -0, INREL=0,1(VBREG,NNREG), leave whole 12205 5,0205 0 2,4374 0 TC DMP ; if INREL=2,3,4(R1,R2,R3), convert to frac ; mult sum x2EXP-28 in MPAC, MPAC+1 by12206 5,0206 06237 1 ADRES DECON ; 2EXP14/10EPX5. Gives(sum/10EXP5)x2EXP-14 ; in MPAC, +1, +212207 5,0207 3 1,2053 0 CAF THREE 12210 5,0210 7 0,0467 0 MASK DECBRNCH 12211 5,0211 2 0,0000 0 INDEX A 12212 5,0212 0 5,6212 0 TC *+0 12213 5,0213 0 5,6220 1 TC PDECSGN 12214 5,0214 4 0,0131 0 CS MPAC+1 ; - case (was DCS, DXCH in Block II)12215 5,0215 5 0,0131 1 TS MPAC+1 12216 5,0216 4 0,0132 0 CS MPAC+2 12217 5,0217 5 0,0132 1 TS MPAC+2 PDECSGN EQU * 12220 5,0220 3 0,0132 1 XCH MPAC+2 12221 5,0221 2 0,0434 0 INDEX INREL 12222 5,0222 5 0,0473 1 TS XREGLP-2 12223 5,0223 3 0,0131 1 XCH MPAC+1 12224 5,0224 2 0,0434 0 INDEX INREL 12225 5,0225 5 0,0470 1 TS VERBREG 12226 5,0226 0 5,6174 0 TC ENDALL MORNUM EQU * 12227 5,0227 1 0,0466 1 CCS DSPCOUNT ; decrement DSPCOUNT12230 5,0230 5 0,0466 0 TS DSPCOUNT 12231 5,0231 0 1,2723 0 TC ENDOFJOB CRITCON EQU * 12232 5,0232 00022 1 DS %22 ; dec 1812233 5,0233 00020 0 DS %20 ; dec 1612234 5,0234 00012 1 DS %12 ; dec 1012235 5,0235 00005 1 DS %5 12236 5,0236 00000 1 DS %0 DECON EQU * 12237 5,0237 05174 0 DS %05174 ; 2EXP14/10EXP5 = .16384 DEC12240 5,0240 13261 0 DS %13261 ;-------------------------------------------------------------------------- ; GETINREL ; Gets proper data register relative address for current C(DSPCOUNT) and ; puts into INREL: +0 VERBREG, 1 NOUNREG, 2 XREG, 3 YREG, 4 ZREG ;

Page 501: Apollo Guidance Computer AGC

; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.313. ;-------------------------------------------------------------------------- GETINREL EQU * 12241 5,0241 2 0,0466 1 INDEX DSPCOUNT 12242 5,0242 3 5,6245 1 CAF INRELTAB 12243 5,0243 5 0,0434 1 TS INREL ; (A TEMP, REG)12244 5,0244 0 0,0001 0 TC Q INRELTAB EQU * 12245 5,0245 00004 0 DS %4 ; R3D5, 0 = DSPCOUNT12246 5,0246 00004 0 DS %4 ; R3D4, 112247 5,0247 00004 0 DS %4 ; R3D3, 212250 5,0250 00004 0 DS %4 ; R3D2, 312251 5,0251 00004 0 DS %4 ; R3D1, 412252 5,0252 00003 1 DS %3 ; R2D5, 512253 5,0253 00003 1 DS %3 ; R2D4, 612254 5,0254 00003 1 DS %3 ; R2D3, 712255 5,0255 00003 1 DS %3 ; R2D2, 8D12256 5,0256 00003 1 DS %3 ; R2D1, 9D12257 5,0257 00002 0 DS %2 ; R1D5, 10D12260 5,0260 00002 0 DS %2 ; R1D4, 11D12261 5,0261 00002 0 DS %2 ; R1D3, 12D12262 5,0262 00002 0 DS %2 ; R1D2, 13D12263 5,0263 00002 0 DS %2 ; R1D1, 14D12264 5,0264 0 5,6271 0 TC CCSHOLE ; no DSPCOUNT numbers12265 5,0265 00001 0 DS %1 ; ND2, 16D12266 5,0266 00001 0 DS %1 ; ND1, 17D12267 5,0267 00000 1 DS %0 ; VD2, 18D12270 5,0270 00000 1 DS %0 ; VD1, 19D 12271 5,0271 0 1,2723 0 CCSHOLE TC ENDOFJOB ; can't find this anywhere; best guess ;-------------------------------------------------------------------------- ; VERB ; Verb key was pressed; prepare to enter a 2 decimal digit verb. ; Blank the verb display and call ENDOFJOB. ; ; NOUN ; Noun key was pressed; prepare to enter a 2 decimal digit noun. ; Blank the noun display and call ENDOFJOB. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.314. ;-------------------------------------------------------------------------- VERB EQU * 12272 5,0272 3 1,2050 0 CAF ZERO 12273 5,0273 5 0,0470 1 TS VERBREG 12274 5,0274 3 2,4675 1 CAF VD1 NVCOM EQU * 12275 5,0275 5 0,0466 0 TS DSPCOUNT 12276 5,0276 0 5,6540 0 TC _2BLANK 12277 5,0277 3 1,2051 1 CAF ONE 12300 5,0300 5 0,0467 1 TS DECBRNCH ; set for dec V/N code12301 5,0301 3 1,2050 0 CAF ZERO 12302 5,0302 5 0,0502 0 TS REQRET ; set for ENTPAS012303 5,0303 3 2,4553 0 CAF ENDINST ; if DSPALARM occurs before first ENTPAS012304 5,0304 5 0,0433 0 TS ENTRET ; or NVSUB, ENTRET must already be set ; to TC ENDOFJOB12305 5,0305 0 1,2723 0 TC ENDOFJOB NOUN EQU * 12306 5,0306 3 1,2050 0 CAF ZERO 12307 5,0307 5 0,0471 0 TS NOUNREG 12310 5,0310 3 2,4676 1 CAF ND1 ; ND1, OCT 21 (DEC 17)12311 5,0311 0 5,6275 1 TC NVCOM ;-------------------------------------------------------------------------- ; NEGSGN ; Turn the minus sign on for the register selected by DSPCOUNT. ; Call ENDOFJOB when done. ; ; POSGN ; Turn the plus sign on for the register selected by DSPCOUNT. ; Call ENDOFJOB when done. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.314. ;-------------------------------------------------------------------------- NEGSGN EQU *

Page 502: Apollo Guidance Computer AGC

12312 5,0312 0 5,6367 0 TC SIGNTEST 12313 5,0313 0 5,6353 1 TC M_ON 12314 5,0314 3 1,2052 1 CAF TWO BOTHSGN EQU * 12315 5,0315 2 0,0434 0 INDEX INREL ; set DEC compu bit to 1 (in DECBRNCH)12316 5,0316 6 1,2072 0 AD BIT7 ; Bit 5 for R1, bit 4 for R2, bit 3 for R312317 5,0317 6 0,0467 1 AD DECBRNCH 12320 5,0320 5 0,0467 1 TS DECBRNCH PIXCLPAS EQU * 12321 5,0321 1 0,0504 1 CCS CLPASS ; if CLPASS is + or +0, make it +012322 5,0322 3 1,2050 0 CAF ZERO 12323 5,0323 5 0,0504 0 TS CLPASS 12324 5,0324 0 5,6325 0 TC *+1 12325 5,0325 0 1,2723 0 TC ENDOFJOB POSGN EQU * 12326 5,0326 0 5,6367 0 TC SIGNTEST 12327 5,0327 0 5,6332 0 TC P_ON 12330 5,0330 3 1,2051 1 CAF ONE 12331 5,0331 0 5,6315 0 TC BOTHSGN ;-------------------------------------------------------------------------- ; P_ON ; Turn the plus sign on for register selected by DSPCOUNT. ; Return when done. ; ; M_ON ; Turn the minus sign on for register selected by DSPCOUNT. ; Return when done. ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.314. ;-------------------------------------------------------------------------- P_ON EQU * 12332 5,0332 3 0,0001 0 XCH Q ; was LXCH Q in block II12333 5,0333 5 0,0547 1 TS LXCH_LPRET ; save return address in faux LP 12334 5,0334 0 5,6241 0 TC GETINREL 12335 5,0335 2 0,0434 0 INDEX INREL 12336 5,0336 3 5,6362 0 CAF SGNTAB-2 12337 5,0337 5 0,0420 1 TS SGNOFF 12340 5,0340 6 1,2051 1 AD ONE 12341 5,0341 5 0,0417 0 TS SGNON SGNCOM EQU * 12342 5,0342 3 1,2050 0 CAF ZERO 12343 5,0343 5 0,0421 0 TS CODE 12344 5,0344 3 0,0420 1 XCH SGNOFF 12345 5,0345 0 5,7253 1 TC _11DSPIN 12346 5,0346 3 1,2066 0 CAF BIT11 12347 5,0347 5 0,0421 0 TS CODE 12350 5,0350 3 0,0417 0 XCH SGNON 12351 5,0351 0 5,7253 1 TC _11DSPIN 12352 5,0352 0 0,0547 1 TC LXCH_LPRET ; return M_ON EQU * 12353 5,0353 3 0,0001 0 XCH Q ; was LXCH Q in block II12354 5,0354 5 0,0547 1 TS LXCH_LPRET ; save return address in faux LP 12355 5,0355 0 5,6241 0 TC GETINREL 12356 5,0356 2 0,0434 0 INDEX INREL 12357 5,0357 3 5,6362 0 CAF SGNTAB-2 12360 5,0360 5 0,0417 0 TS SGNON 12361 5,0361 6 1,2051 1 AD ONE 12362 5,0362 5 0,0420 1 TS SGNOFF 12363 5,0363 0 5,6342 1 TC SGNCOM SGNTAB EQU * 12364 5,0364 00005 1 DS %5 ; -R112365 5,0365 00003 1 DS %3 ; -R212366 5,0366 00000 1 DS %0 ; -R3 ;-------------------------------------------------------------------------- ; SIGNTEST ; Test whether this is a valid point for entering a + or - sign character. ; Returns if valid; calls ENDOFJOB if invalid. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.314. ;--------------------------------------------------------------------------

Page 503: Apollo Guidance Computer AGC

SIGNTEST EQU * 12367 5,0367 3 0,0001 0 XCH Q ; was LXCH Q in block II12370 5,0370 5 0,0547 1 TS LXCH_LPRET ; save return address in faux LP ; allows +,- only when DSPCOUNT=R1D112371 5,0371 3 1,2053 0 CAF THREE ; R2D1, or D3D1. Allows only first of12372 5,0372 7 0,0467 0 MASK DECBRNCH ; consecutive +/- characters.12373 5,0373 1 0,0000 0 CCS A ; if low2 bits of DECBRNCH not=0, sign12374 5,0374 0 1,2723 0 TC ENDOFJOB ; for this word already in, reject. 12375 5,0375 4 2,4635 1 CS R1D1 12376 5,0376 0 5,6404 1 TC SGNTST1 ; DSPCOUNT is R1D1?12377 5,0377 4 2,4636 1 CS R2D1 12400 5,0400 0 5,6404 1 TC SGNTST1 12401 5,0401 4 2,4637 0 CS R3D1 12402 5,0402 0 5,6404 1 TC SGNTST1 12403 5,0403 0 1,2723 0 TC ENDOFJOB ; no match found, sign illegal SGNTST1 EQU * 12404 5,0404 6 0,0466 0 AD DSPCOUNT 12405 5,0405 1 0,0000 0 CCS A ; was BZF *+2 in Block II12406 5,0406 0 0,0001 0 TC Q ; >0, no match, check next register12407 5,0407 0 0,0547 1 TC LXCH_LPRET ; +0, match found, sign is legal12410 5,0410 0 0,0001 0 TC Q ; <0, no match, check next register12411 5,0411 0 0,0547 1 TC LXCH_LPRET ; -0, match found, sign is legal ;-------------------------------------------------------------------------- ; CLEAR -- PROCESS CLEAR KEY ; Clear blanks which R1, R2, R3 is current or last to be displayed (pertinent ; XREG, YREG, ZREG is cleared). Successive clears take care of each RX L/ ; RC until R1 is done, then no further action. ; ; The single component load verbs allow only the single RC that is appropriate ; to be cleared. ; ; CLPASS = 0, PASSO, can be backed up ; CLPASS = +NZ, HIPASS, can be backed up ; CLPASS = -NZ, PASSO, cannot be backed up ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.316. ;-------------------------------------------------------------------------- CLEAR EQU * 12412 5,0412 1 0,0466 1 CCS DSPCOUNT 12413 5,0413 6 1,2051 1 AD ONE 12414 5,0414 0 5,6416 1 TC *+2 12415 5,0415 6 1,2051 1 AD ONE 12416 5,0416 2 0,0000 0 INDEX A ; do not change DSPCOUNT because may later12417 5,0417 3 5,6245 1 CAF INRELTAB ; fail LEGALTST12420 5,0420 5 0,0434 1 TS INREL ; must set INREL, even for HIPASS12421 5,0421 1 0,0504 1 CCS CLPASS 12422 5,0422 0 5,6431 1 TC CLPASHI ; +12423 5,0423 0 5,6425 1 TC *+2 ; +0, if CCLPASS is +0 or -, it is PASS012424 5,0424 0 5,6425 1 TC *+1 ; -12425 5,0425 3 1,2050 0 CAF ZERO ; was CA INREL in Block II12426 5,0426 6 0,0434 1 AD INREL 12427 5,0427 0 5,6464 1 TC LEGALTST 12430 5,0430 0 5,6454 1 TC CLEAR1 CLPASHI EQU * 12431 5,0431 1 0,0434 0 CCS INREL 12432 5,0432 5 0,0434 1 TS INREL 12433 5,0433 0 5,6464 1 TC LEGALTST 12434 5,0434 3 5,6536 1 CAF DOUBLK+2 ; +3 to - number, backs data requests12435 5,0435 6 0,0502 0 AD REQRET ; was ADS REQRET in Block II12436 5,0436 5 0,0502 0 TS REQRET 12437 5,0437 3 1,2050 0 CAF ZERO ; was CA INREL in Block II12440 5,0440 6 0,0434 1 AD INREL 12441 5,0441 5 0,0422 0 TS MIXTEMP ; temp storage for INREL 12442 5,0442 1 0,0470 0 CCS VERBREG ; was DIM VERBREG in Block II12443 5,0443 0 5,6446 1 TC *+3 12444 5,0444 0 5,6446 1 TC *+2 12445 5,0445 0 5,6446 1 TC *+1 12446 5,0446 5 0,0470 1 TS VERBREG ; decrement VERB and redisplay 12447 5,0447 0 1,3565 1 TC BANKCALL 12450 5,0450 14327 1 DS UPDATVB 12451 5,0451 3 1,2050 0 CAF ZERO ; was CA MIXTEMP in Block II12452 5,0452 6 0,0422 0 AD MIXTEMP

Page 504: Apollo Guidance Computer AGC

12453 5,0453 5 0,0434 1 TS INREL ; restore INREL CLEAR1 EQU * 12454 5,0454 0 5,6461 1 TC CLR5 12455 5,0455 3 0,0504 0 XCH CLPASS ; was INCR CLPASS in Block II12456 5,0456 6 1,2051 1 AD ONE 12457 5,0457 5 0,0504 0 TS CLPASS ; only if CLPASS is + or +0 12460 5,0460 0 1,2723 0 TC ENDOFJOB ; set for higher pass ;-------------------------------------------------------------------------- ; CLR5 ; blanks 5 char display word by calling _5BLANK, but avoids TC GETINREL. ; Returns when done. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.316. ;-------------------------------------------------------------------------- CLR5 EQU * 12461 5,0461 3 0,0001 0 XCH Q ; was LXCH Q in block II12462 5,0462 5 0,0547 1 TS LXCH_LPRET ; save return address in faux LP12463 5,0463 0 5,6476 1 TC _5BLANK+3 ; uses _5BLANK, but avoids its TC GETINREL ;-------------------------------------------------------------------------- ; LEGALTST ; Returns if LEGAL, calls ENDOFJOB if illegal. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.316. ;-------------------------------------------------------------------------- LEGALTST EQU * 12464 5,0464 6 1,2047 0 AD NEG2 12465 5,0465 1 0,0000 0 CCS A 12466 5,0466 0 0,0001 0 TC Q ; LEGAL, INREL G/ 212467 5,0467 0 5,6271 0 TC CCSHOLE 12470 5,0470 0 1,2723 0 TC ENDOFJOB ; ILLEGAL, INREL = 0, 112471 5,0471 0 0,0001 0 TC Q ; LEGAL, INREL = 2 ;-------------------------------------------------------------------------- ; _5BLANK ; blanks 5 char display word in R1,R2,or R3. It also zeroes XREG, YREG or ; ZREG. Place any + DSPCOUNT number for pertinent RC into DSPCOUNT. ; DSPCOUNT is left set to left most DSP numb for RC just blanked. ; Returns when done. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.316. ;-------------------------------------------------------------------------- 12472 5,0472 5 0,0466 0 TS DSPCOUNT ; needed for BLANKSUB _5BLANK EQU * 12473 5,0473 3 0,0001 0 XCH Q ; was LXCH Q in block II12474 5,0474 5 0,0547 1 TS LXCH_LPRET ; save return address in faux LP 12475 5,0475 0 5,6241 0 TC GETINREL 12476 5,0476 3 1,2050 0 CAF ZERO 12477 5,0477 2 0,0434 0 INDEX INREL 12500 5,0500 5 0,0470 1 TS VERBREG ; zero X, Y, Z reg12501 5,0501 2 0,0434 0 INDEX INREL 12502 5,0502 5 0,0473 1 TS XREGLP-2 12503 5,0503 5 0,0421 0 TS CODE 12504 5,0504 2 0,0434 0 INDEX INREL ; zero pertinent DEC comp bit12505 5,0505 4 1,2072 1 CS BIT7 12506 5,0506 7 0,0467 0 MASK DECBRNCH 12507 5,0507 7 5,6537 1 MASK BRNCHCON ; zero low 3 bits12510 5,0510 5 0,0467 1 TS DECBRNCH 12511 5,0511 2 0,0434 0 INDEX INREL 12512 5,0512 3 5,6527 1 CAF SINBLANK-2 ; blank isolated char separately12513 5,0513 5 0,0440 1 TS COUNT 12514 5,0514 0 5,7161 0 TC DSPIN _5BLANK1 EQU * 12515 5,0515 2 0,0434 0 INDEX INREL 12516 5,0516 3 5,6532 0 CAF DOUBLK-2 12517 5,0517 5 0,0466 0 TS DSPCOUNT 12520 5,0520 0 5,6540 0 TC _2BLANK 12521 5,0521 4 1,2052 0 CS TWO 12522 5,0522 6 0,0466 0 AD DSPCOUNT ; was ADS DSPCOUNT in Block II12523 5,0523 5 0,0466 0 TS DSPCOUNT

Page 505: Apollo Guidance Computer AGC

12524 5,0524 0 5,6540 0 TC _2BLANK 12525 5,0525 2 0,0434 0 INDEX INREL 12526 5,0526 3 2,4633 0 CAF R1D1-2 12527 5,0527 5 0,0466 0 TS DSPCOUNT ; set DSPCOUNT to leftmost DSP number12530 5,0530 0 0,0547 1 TC LXCH_LPRET ; of REG, just blanked SINBLANK EQU * 12531 5,0531 00016 0 DS %16 ; DEC 1412532 5,0532 00005 1 DS %5 12533 5,0533 00004 0 DS %4 DOUBLK EQU * 12534 5,0534 00015 0 DS %15 ; DEC 1312535 5,0535 00011 1 DS %11 ; DEC 912536 5,0536 00003 1 DS %3 12537 5,0537 77774 0 BRNCHCON DS %77774 ;-------------------------------------------------------------------------- ; _2BLANK ; blanks 2 char, place DSP number of left char of the pair into DSPCOUNT. ; This number is left in DSPCOUNT. Returns when done. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.317. ;-------------------------------------------------------------------------- _2BLANK EQU * 12540 5,0540 3 0,0001 0 XCH Q 12541 5,0541 5 0,0602 0 TS SAVEQ 12542 5,0542 3 1,2050 0 CAF ZERO ; was CA DSPCOUNT in Block II12543 5,0543 6 0,0466 0 AD DSPCOUNT 12544 5,0544 5 0,0021 1 TS SR 12545 5,0545 4 5,6563 0 CS BLANKCON 12546 5,0546 2 0,0000 0 INHINT 12547 5,0547 2 0,0021 0 INDEX SR 12550 5,0550 3 0,0512 1 XCH DSPTAB 12551 5,0551 1 0,0000 0 CCS A ; was BZMF *+2 in Block II12552 5,0552 0 5,6556 1 TC *+4 ; >012553 5,0553 0 5,6555 1 TC *+2 ; +0, if old contents -, NOUT OK12554 5,0554 0 5,6555 1 TC *+1 ; <0, if old contents -, NOUT OK12555 5,0555 0 5,6557 0 TC *+2 ; -0, if old contents -, NOUT OK 12556 5,0556 3 0,0505 1 XCH NOUT ; was INCR NOUT in Block II12557 5,0557 6 1,2051 1 AD ONE 12560 5,0560 5 0,0505 1 TS NOUT ; if old contents +, +1 to NOUT12561 5,0561 2 0,0000 1 RELINT 12562 5,0562 0 0,0602 0 TC SAVEQ 12563 5,0563 04000 0 BLANKCON DS %4000 BANK40_2 EQU * ORG BANK41_1 ; COLOSSUS pp. 318-329 INCL bank41_1.asm ;========================================================================== ; DISPLAY ROUTINES (file:bank41_1.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 318-329. ;========================================================================== ;-------------------------------------------------------------------------- ; ENTER -- PROCESS ENTER KEY ; Enter pass 0 is the execute function. Higher order enters are to load ; data. The sign of REQRET determines the pass, + for pass 0, - for higher ; passes. ; Machine CADR to be specified (MCTBS) nouns desire an ECADR to be loaded ; when used with load verbs, monitor verbs, or display verbs (except ; verb = fixed memory display, which requires a FCADR). ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.318. ;-------------------------------------------------------------------------- 14000 6,0000 0 6,7505 0 NVSUBR TC NVSUB1 ; standard lead-ins, don't move14001 6,0001 0 6,6723 1 LOADLV1 TC LOADLV

Page 506: Apollo Guidance Computer AGC

ENTER EQU * 14002 6,0002 3 1,2050 0 CAF ZERO 14003 6,0003 5 0,0504 0 TS CLPASS 14004 6,0004 3 2,4553 0 CAF ENDINST 14005 6,0005 5 0,0433 0 TS ENTRET 14006 6,0006 1 0,0502 1 CCS REQRET 14007 6,0007 0 6,6040 0 TC ENTPAS0 ; if +, pass 014010 6,0010 0 6,6040 0 TC ENTPAS0 ; if +, pass 014011 6,0011 0 6,6012 1 TC *+1 ; if -, not pass 0 ; not first pass thru ENTER, so enter data word ENTPASHI EQU * 14012 6,0012 3 6,6036 1 CAF MMADREF 14013 6,0013 6 0,0502 0 AD REQRET ; if L/2 char in for MM code, alarm 14014 6,0014 1 0,0000 0 CCS A ; and recycle (decide at MMCHANG+1)14015 6,0015 0 6,6021 1 TC *+4 ; >014016 6,0016 0 6,6020 0 TC *+2 ; +014017 6,0017 0 6,6021 1 TC *+2 ; <014020 6,0020 0 6,6032 0 TC ACCEPTWD ; -0, was BZF ACCEPTWD in Block II 14021 6,0021 3 1,2053 0 CAF THREE ; if DEC, alarm if L/5 char in for data,14022 6,0022 7 0,0467 0 MASK DECBRNCH ; but leave REQRET - and flash on, so14023 6,0023 1 0,0000 0 CCS A ; operator can supply missing numerical14024 6,0024 0 6,6026 0 TC *+2 ; characters and continue.14025 6,0025 0 6,6032 0 TC ACCEPTWD ; octal, any number of char OK.14026 6,0026 1 0,0466 1 CCS DSPCOUNT 14027 6,0027 0 6,6341 1 TC GODSPALM ; less than 5 char DEC(DSPCOUNT is +)14030 6,0030 0 6,6341 1 TC GODSPALM ; less than 5 char DEC(DSPCOUNT is +)14031 6,0031 0 6,6032 0 TC *+1 ; 5 char in (DSPCOUNT is -) ACCEPTWD EQU * 14032 6,0032 4 0,0502 1 CS REQRET ; 5 char in (DSPCOUNT is -)14033 6,0033 5 0,0502 0 TS REQRET ; set REQRET +14034 6,0034 0 2,4770 0 TC FLASHOFF 14035 6,0035 0 0,0502 0 TC REQRET ENTEXIT EQU ENTRET 14036 6,0036 15357 1 MMADREF DS MMCHANG+1 ; assumes TC REGMM at MMCHANG 14037 6,0037 00034 0 LOWVERB DS 28 ; lower verb that avoids nount test. ; first pass thru ENTER, so execute VERB/NOUN ENTPAS0 EQU * 14040 6,0040 3 1,2050 0 CAF ZERO ; noun verb sub enters here14041 6,0041 5 0,0467 1 TS DECBRNCH 14042 6,0042 4 2,4675 0 CS VD1 ; block further num char, so that stray14043 6,0043 5 0,0466 0 TS DSPCOUNT ; char do not get into verb or nount lights. ; test VERB TESTVB EQU * 14044 6,0044 4 0,0470 0 CS VERBREG ; if verb is G/E LOWVB, skip noun test14045 6,0045 5 0,0530 1 TS VERBSAVE ; save verb for possible recycle.14046 6,0046 6 6,6037 0 AD LOWVERB ; LOWVERB - VB 14047 6,0047 1 0,0000 0 CCS A ; was BZMF VERBFAN in Block II14050 6,0050 0 6,6054 0 TC *+4 ; >014051 6,0051 0 6,6053 1 TC *+2 ; +0, VERB G/E LOWVERB14052 6,0052 0 6,6053 1 TC *+1 ; <0, VERB G/E LOWVERB14053 6,0053 0 6,6151 1 TC VERBFAN ; -0, VERB G/E LOWVERB ; test NOUN TESTNN EQU * ; set MIXBR and put the noun address into NNADTEM ; MIXBR is an enumerated type: ; 1 = normal nouns ; 2 = mixed nouns 14054 6,0054 3 6,6124 0 CAF LODNNLOC ; was DCA LODNNLOC, DXCH Z in Block II14055 6,0055 0 1,3526 0 TC DXCHJUMP ; bank jump to noun table read rtne 14056 6,0056 2 0,0435 1 INDEX MIXBR ; computed GOTO14057 6,0057 0 6,6057 0 TC *+0 14060 6,0060 0 6,6062 0 TC *+2 ; returns here for normal noun14061 6,0061 0 6,6237 1 TC MIXNOUN ; returns here for mixed noun

Page 507: Apollo Guidance Computer AGC

; normal noun, so test noun address table entry (NNADTEM) 14062 6,0062 1 0,0443 0 CCS NNADTEM ; normal14063 6,0063 0 6,6147 0 TC VERBFAN-2 ; normal if +14064 6,0064 0 6,6341 1 TC GODSPALM ; not in use if +014065 6,0065 0 6,6073 0 TC REQADD ; specify machine CADR if - ; NNADTEM was -0, so just increment noun address (in NOUNCADR) and ; set the result in NOUNADD 14066 6,0066 3 0,0506 1 XCH NOUNCADR ; augment machine CADR if -014067 6,0067 6 1,2051 1 AD ONE 14070 6,0070 5 0,0506 1 TS NOUNCADR ; was INCR NOUNCADR in Block II 14071 6,0071 0 2,4625 1 TC SETNADD ; set NOUNADD14072 6,0072 0 6,6132 1 TC INTMCTBS+3 ; NNADTEM was -, so noun address needs to be specified (loaded). REQADD EQU * 14073 6,0073 3 1,2062 1 CAF BIT15 ; set CLPASS for pass0 only14074 6,0074 5 0,0504 0 TS CLPASS 14075 6,0075 4 2,4553 1 CS ENDINST ; test if reach here from internal or14076 6,0076 6 0,0433 0 AD ENTEXIT ; from external 14077 6,0077 1 0,0000 0 CCS A ; was BZF *+2 in Block II14100 6,0100 0 6,6104 1 TC *+4 ; >014101 6,0101 0 6,6103 0 TC *+2 ; +014102 6,0102 0 6,6104 1 TC *+2 ; <014103 6,0103 0 6,6105 0 TC *+2 ; -0, external mach CADR to be specified 14104 6,0104 0 6,6127 0 TC INTMCTBS 14105 6,0105 0 6,6274 0 TC REQDATZ ; external mach CADR to be specified 14106 6,0106 1 0,0467 0 CCS DECBRNCH ; alarm and recycle if decimal used14107 6,0107 0 2,4474 1 TC ALMCYCLE ; for MCTBS14110 6,0110 4 2,4675 0 CS VD1 ; octal used OK14111 6,0111 5 0,0466 0 TS DSPCOUNT ; block num char in 14112 6,0112 1 0,0531 1 CCS CADRSTOR 14113 6,0113 0 6,6116 1 TC *+3 ; external MCTBS display will leave flash14114 6,0114 0 6,6117 0 TC USEADD ; on if ENDIDLE not = +014115 6,0115 0 6,6116 1 TC *+1 14116 6,0116 0 2,4760 1 TC FLASHON ; noun address has now been loaded into the Z register. Copy it into ; NOUNCADR and NOUNADD and then jump to the VERBFAN. USEADD EQU * 14117 6,0117 3 0,0474 0 XCH ZREG 14120 6,0120 0 2,4616 1 TC SETNCADR ; ECADR into NOUNCADR, set EB, NOUNADD 14121 6,0121 3 6,6124 0 CAF LODNNLOC ; was DCA LODNNLOC, DXCH Z in Block II14122 6,0122 0 1,3526 0 TC DXCHJUMP ; bank jump to noun table read rtne 14123 6,0123 0 6,6151 1 TC VERBFAN 14124 6,0124 16114 1 LODNNLOC DS LODNNTAB ; *** uses 2 words in Block II ***14125 6,0125 00000 1 DS 0 14126 6,0126 77772 0 NEG5 DS -5 ; If external (keyboard input), noun address is in register A. ; If internal (S/W input), noun address is in MPAC+2. ; Store the noun address into NOUNCADR and NOUNADD. If the verb ; is O5. go directly to the VERBFAN; for all other verbs, display ; the noun address in R3 and then go to the VERBFAN. INTMCTBS EQU * ; entry point for internal: 14127 6,0127 3 1,2050 0 CAF ZERO ; was CA MPAC+2 in Block II14130 6,0130 6 0,0132 1 AD MPAC+2 ; internal mach CADR to be specified ; entry point for external (keyboard input): 14131 6,0131 0 2,4616 1 TC SETNCADR ; store addr (A) into NOUNCADR and NOUNADD 14132 6,0132 4 1,2055 1 CS FIVE ; NVSUB call left CADR in MAPC+2 for mach14133 6,0133 6 0,0470 1 AD VERBREG ; CADR to be specified.

Page 508: Apollo Guidance Computer AGC

14134 6,0134 1 0,0000 0 CCS A ; was BZF VERBFAN in Block II14135 6,0135 0 6,6141 0 TC *+4 ; >014136 6,0136 0 6,6140 1 TC *+2 ; +014137 6,0137 0 6,6141 0 TC *+2 ; <014140 6,0140 0 6,6151 1 TC VERBFAN ; -0, don't display CADR if verb = 05 14141 6,0141 3 2,4637 1 CAF R3D1 ; verb not = 05, display CADR14142 6,0142 5 0,0466 0 TS DSPCOUNT 14143 6,0143 3 1,2050 0 CAF ZERO ; was CA NOUNCADR in Block II14144 6,0144 6 0,0506 1 AD NOUNCADR 14145 6,0145 0 6,7310 1 TC DSPOCTWD 14146 6,0146 0 6,6151 1 TC VERBFAN ; NNADTEM was + (normal), so just use the noun address straight from the ; noun table (currently in A). The CCS instruction used to test the ; address also decremented it, so we add one to restore the correct address. 14147 6,0147 6 1,2051 1 AD ONE 14150 6,0150 0 2,4616 1 TC SETNCADR ; store addr (A) into NOUNCADR and NOUNADD ; noun address is currently in NOUNCADR and NOUNADD. VERBFAN EQU * 14151 6,0151 4 6,6163 1 CS LST2CON 14152 6,0152 6 0,0470 1 AD VERBREG ; verb-LST2CON 14153 6,0153 1 0,0000 0 CCS A 14154 6,0154 6 1,2051 1 AD ONE ; ver G/ LST2CON14155 6,0155 0 6,6157 1 TC *+2 14156 6,0156 0 6,6164 1 TC VBFANDIR ; verb L/ LST2CON14157 6,0157 5 0,0130 0 TS MPAC 14160 6,0160 0 2,5003 1 TC RELDSP ; release display syst14161 6,0161 0 1,3653 1 TC POSTJUMP ; go to GOEXTVB with VB-40 in MPAC14162 6,0162 20000 0 DS GOEXTVB 14163 6,0163 00050 1 LST2CON DS 40 ; first list2 verb (extended verb) VBFANDIR EQU * 14164 6,0164 2 0,0470 0 INDEX VERBREG 14165 6,0165 3 6,6167 1 CAF VERBTAB 14166 6,0166 0 1,3712 0 TC BANKJUMP VERBTAB EQU * 14167 6,0167 14341 1 CADR GODSPALM ; VB00 Illegal14170 6,0170 14355 1 CADR DSPA ; VB01 display oct comp 1 (R1)14171 6,0171 14363 1 CADR DSPB ; VB02 display oct comp 2 (R1)14172 6,0172 14370 0 CADR DSPC ; VB03 display oct comp 3 (R1)14173 6,0173 14350 1 CADR DSPAB ; VB04 display oct comp 1,2 (R1,R2)14174 6,0174 14343 0 CADR DSPABC ; VB05 display oct comp 1,2,3 (R1,R2,R3)14175 6,0175 14510 0 CADR DECDSP ; VB06 decimal display14176 6,0176 12704 1 CADR DSPDPDEC ; VB07 DP decimal display (R1,R2)14177 6,0177 14341 1 CADR GODSPALM ; VB08 spare14200 6,0200 14341 1 CADR GODSPALM ; VB09 spare14201 6,0201 14341 1 CADR GODSPALM ; VB10 spare14202 6,0202 15146 0 CADR MONITOR ; VB11 monitor oct comp 1 (R1)14203 6,0203 15146 0 CADR MONITOR ; VB12 monitor oct comp 2 (R2)14204 6,0204 15146 0 CADR MONITOR ; VB13 monitor oct comp 3 (R3)14205 6,0205 15146 0 CADR MONITOR ; VB14 monitor oct comp 1,2 (R1,R2)14206 6,0206 15146 0 CADR MONITOR ; VB15 monitor oct comp 1,2,3 (R1,R2,R3)14207 6,0207 15146 0 CADR MONITOR ; VB16 monitor decimal14210 6,0210 15146 0 CADR MONITOR ; VB17 monitor DP decimal (R1,R2)14211 6,0211 14341 1 CADR GODSPALM ; VB18 spare14212 6,0212 14341 1 CADR GODSPALM ; VB19 spare14213 6,0213 14341 1 CADR GODSPALM ; VB20 spare14214 6,0214 14663 1 CADR ALOAD ; VB21 load comp 1 (R1)14215 6,0215 14673 0 CADR BLOAD ; VB22 load comp 2 (R2)14216 6,0216 14707 1 CADR CLOAD ; VB23 load comp 3 (R3)14217 6,0217 14635 1 CADR ABLOAD ; VB24 load comp 1,2 (R1,R2)14220 6,0220 14600 1 CADR ABCLOAD ; VB25 load comp 1,2,3 (R1,R2,R3)14221 6,0221 14341 1 CADR GODSPALM ; VB26 spare14222 6,0222 15301 1 CADR DSPFMEM ; VB27 fixed memory display14223 6,0223 14341 1 CADR GODSPALM ; VB28 spare14224 6,0224 14341 1 CADR GODSPALM ; VB29 spare14225 6,0225 15420 0 CADR VBRQEXEC ; VB30 request executive14226 6,0226 15446 0 CADR VBRQWAIT ; VB31 request waitlist14227 6,0227 13325 1 CADR VBRESEQ ; VB32 resequence14230 6,0230 13315 1 CADR VBPROC ; VB33 proceed (without data)14231 6,0231 13323 1 CADR VBTERM ; VB34 terminate14232 6,0232 15572 0 CADR VBTSTLTS ; VB35 test lights14233 6,0233 02126 0 CADR SLAP1 ; VB36 fresh start14234 6,0234 15356 0 CADR MMCHANG ; VB37 change major mode14235 6,0235 14341 1 CADR GODSPALM ; VB38 spare14236 6,0236 14341 1 CADR GODSPALM ; VB39 spare

Page 509: Apollo Guidance Computer AGC

;-------------------------------------------------------------------------- ; MIXNOUN ; NNADTAB contains a relative address, IDADDREL(in low 10 bits), referring ; to where 3 consecutive addresses are stored (in IDADDTAB). ; MIXNOUN gets data and stores in MIXTEMP, +1, +2. It sets NOUNADD for ; MIXTEMP. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.322. ;-------------------------------------------------------------------------- MIXNOUN EQU * 14237 6,0237 0 6,6341 1 TC GODSPALM ; not currently implemented ; ************ BUNCH OF MISSING STUFF ************ ;-------------------------------------------------------------------------- ; DPTEST ; enter with SF routine code number (SF ROUT) in A. Returns to L+1 if no DP. ; Returns to L+2 if DP. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.322. Also, see p. 263. ;-------------------------------------------------------------------------- DPTEST EQU * 14240 6,0240 5 0,0552 0 TS DPTEST_A 14241 6,0241 3 0,0001 0 XCH Q 14242 6,0242 5 0,0553 1 TS DPTEST_Q 14243 6,0243 2 0,0552 1 INDEX DPTEST_A 14244 6,0244 0 6,6245 1 TC *+1 14245 6,0245 0 0,0553 1 TC DPTEST_Q ; octal only, no DP14246 6,0246 0 0,0553 1 TC DPTEST_Q ; straight fractional, no DP14247 6,0247 0 0,0553 1 TC DPTEST_Q ; CDU degrees (XXX.XX), no DP14250 6,0250 0 0,0553 1 TC DPTEST_Q ; arithmetic SF, no DP14251 6,0251 0 6,6262 1 TC DPTEST1 ; DP1OUT14252 6,0252 0 6,6262 1 TC DPTEST1 ; DP2OUT14253 6,0253 0 0,0553 1 TC DPTEST_Q ; Y OPTICS DEGREES, no DP14254 6,0254 0 6,6262 1 TC DPTEST1 ; DP3OUT14255 6,0255 0 0,0553 1 TC DPTEST_Q ; HMS, no DP14256 6,0256 0 0,0553 1 TC DPTEST_Q ; MS, no DP14257 6,0257 0 6,6262 1 TC DPTEST1 ; DP4OUT14260 6,0260 0 0,0553 1 TC DPTEST_Q ; arith1, no DP14261 6,0261 0 0,0553 1 TC DPTEST_Q ; 2INTOUT, no DP to get hi part in MPAC DPTEST1 EQU * 14262 6,0262 2 0,0553 0 INDEX DPTEST_Q 14263 6,0263 0 0,0001 0 TC 1 ; return to L+2 ;-------------------------------------------------------------------------- ; REQDATX, REQDATY, REQDATZ ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.323. ;-------------------------------------------------------------------------- REQDATX EQU * 14264 6,0264 3 0,0001 0 XCH Q 14265 6,0265 5 0,0554 0 TS REQ_Q 14266 6,0266 3 2,4635 0 CAF R1D1 14267 6,0267 0 6,6277 0 TC REQCOM REQDATY EQU * 14270 6,0270 3 0,0001 0 XCH Q 14271 6,0271 5 0,0554 0 TS REQ_Q 14272 6,0272 3 2,4636 0 CAF R2D1 14273 6,0273 0 6,6277 0 TC REQCOM REQDATZ EQU * 14274 6,0274 3 0,0001 0 XCH Q 14275 6,0275 5 0,0554 0 TS REQ_Q 14276 6,0276 3 2,4637 1 CAF R3D1 14277 6,0277 5 0,0466 0 REQCOM TS DSPCOUNT 14300 6,0300 4 0,0554 1 CS REQ_Q 14301 6,0301 5 0,0502 0 TS REQRET 14302 6,0302 0 1,3565 1 TC BANKCALL 14303 6,0303 12473 1 DS _5BLANK 14304 6,0304 0 2,4760 1 TC FLASHON

Page 510: Apollo Guidance Computer AGC

ENDRQDAT EQU * 14305 6,0305 0 0,0433 0 TC ENTEXIT ;-------------------------------------------------------------------------- ; UPDATNN, UPDATVB ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.323. ;-------------------------------------------------------------------------- 14306 6,0306 5 0,0471 0 TS NOUNREG UPDATNN EQU * 14307 6,0307 3 0,0001 0 XCH Q 14310 6,0310 5 0,0414 0 TS UPDATRET 14311 6,0311 3 6,6124 0 CAF LODNNLOC ; was DCA LODNNLOC, DXCH Z in Block II14312 6,0312 0 1,3526 0 TC DXCHJUMP ; bank jump to noun table read rtne 14313 6,0313 1 0,0443 0 CCS NNADTEM 14314 6,0314 6 1,2051 1 AD ONE ; >0, normal14315 6,0315 0 6,6320 0 TC PUTADD ; +0, normal14316 6,0316 0 6,6321 1 TC PUTADD+1 ; <0, MCTBS don't change NOUNADD14317 6,0317 0 6,6321 1 TC PUTADD+1 ; -0, MCTBI don't change NOUNADD PUTADD EQU * 14320 6,0320 0 2,4616 1 TC SETNCADR ; ECADR into NOUNCADR, sets NOUNADD 14321 6,0321 3 2,4676 1 CAF ND1 14322 6,0322 5 0,0466 0 TS DSPCOUNT 14323 6,0323 3 1,2050 0 CAF ZERO ; was CA NOUNREG in Block II14324 6,0324 6 0,0471 0 AD NOUNREG 14325 6,0325 0 6,6335 1 TC UPDAT1 14326 6,0326 5 0,0470 1 TS VERBREG UPDATVB EQU * 14327 6,0327 3 0,0001 0 XCH Q 14330 6,0330 5 0,0414 0 TS UPDATRET 14331 6,0331 3 2,4675 1 CAF VD1 14332 6,0332 5 0,0466 0 TS DSPCOUNT 14333 6,0333 3 1,2050 0 CAF ZERO ; was CA VERBREG in Block II14334 6,0334 6 0,0470 1 AD VERBREG UPDAT1 EQU * 14335 6,0335 0 1,3653 1 TC POSTJUMP ; can't use SWCALL to go to DSPDECVN, since14336 6,0336 13156 1 DS GOVNUPDT ; UPDATVB can itself be called by SWCALL14337 6,0337 0 0,0414 0 TC UPDATRET ;-------------------------------------------------------------------------- ; GOALMCYC, GODSPALM ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.324. ;-------------------------------------------------------------------------- 14340 6,0340 0 2,4474 1 GOALMCYC TC ALMCYCLE ; needed because bankjump cant handle F/F

14341 6,0341 0 1,3653 1 GODSPALM TC POSTJUMP 14342 6,0342 13267 0 DS DSPALARM ;-------------------------------------------------------------------------- ; DISPLAY VERBS ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.326. ;-------------------------------------------------------------------------- DSPABC EQU * 14343 6,0343 4 1,2052 0 CS TWO 14344 6,0344 0 6,6414 0 TC COMPTEST 14345 6,0345 2 0,0442 1 INDEX NOUNADD 14346 6,0346 4 0,0002 1 CS 2 14347 6,0347 3 0,0427 0 XCH BUF+2 DSPAB EQU * 14350 6,0350 4 1,2051 0 CS ONE 14351 6,0351 0 6,6414 0 TC COMPTEST 14352 6,0352 2 0,0442 1 INDEX NOUNADD 14353 6,0353 4 0,0001 1 CS 1

Page 511: Apollo Guidance Computer AGC

14354 6,0354 3 0,0426 1 XCH BUF+1 DSPA EQU * 14355 6,0355 0 6,6435 0 TC DECTEST 14356 6,0356 0 6,6462 1 TC TSTFORDP 14357 6,0357 2 0,0442 1 INDEX NOUNADD 14360 6,0360 4 0,0000 0 CS 0 DSPCOM1 EQU * 14361 6,0361 3 0,0425 1 XCH BUF 14362 6,0362 0 6,6375 0 TC DSPCOM2 DSPB EQU * 14363 6,0363 4 1,2051 0 CS ONE 14364 6,0364 0 6,6430 0 TC DCOMPTST 14365 6,0365 2 0,0442 1 INDEX NOUNADD 14366 6,0366 4 0,0001 1 CS 1 14367 6,0367 0 6,6361 0 TC DSPCOM1 DSPC EQU * 14370 6,0370 4 1,2052 0 CS TWO 14371 6,0371 0 6,6430 0 TC DCOMPTST 14372 6,0372 2 0,0442 1 INDEX NOUNADD 14373 6,0373 4 0,0002 1 CS 2 14374 6,0374 0 6,6361 0 TC DSPCOM1 DSPCOM2 EQU * 14375 6,0375 4 1,2052 0 CS TWO ; A B C AB ABC14376 6,0376 6 0,0470 1 AD VERBREG ; -1 -0 +1 +2 +3 IN A14377 6,0377 1 0,0000 0 CCS A ; +0 +0 +0 +1 +2 IN A AFTER CCS14400 6,0400 0 6,6403 0 TC DSPCOM3 14401 6,0401 0 0,0433 0 TC ENTEXIT 14402 6,0402 0 6,6403 0 TC *+1 DSPCOM3 EQU * 14403 6,0403 5 0,0417 0 TS DISTEM ; +0, +1, +2 into DISTEM14404 6,0404 2 0,0000 0 INDEX A 14405 6,0405 3 2,4635 0 CAF R1D1 14406 6,0406 5 0,0466 0 TS DSPCOUNT 14407 6,0407 2 0,0417 1 INDEX DISTEM 14410 6,0410 4 0,0425 0 CS BUF 14411 6,0411 0 6,7310 1 TC DSPOCTWD 14412 6,0412 3 0,0417 0 XCH DISTEM 14413 6,0413 0 6,6377 1 TC DSPCOM2+2 ;-------------------------------------------------------------------------- ; COMPTEST ; alarms if component number of verb (load or oct display) is ; greater than the highest component number of noun. ; ; DCOMPTST ; alarms if decimal only bit (bit 4 of comp code number) = 1. ; If not, it performs regular COMPTEST. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.326. ;-------------------------------------------------------------------------- COMPTEST EQU * 14414 6,0414 5 0,0420 1 TS SFTEMP1 ; - verb comp14415 6,0415 3 0,0001 0 XCH Q ; was LXCH Q in block II14416 6,0416 5 0,0547 1 TS LXCH_LPRET ; save return address in faux LP COMPTST1 EQU * 14417 6,0417 0 6,6501 0 TC GETCOMP 14420 6,0420 0 2,4647 0 TC LEFT5 14421 6,0421 7 1,2053 1 MASK THREE ; noun comp14422 6,0422 6 0,0420 1 AD SFTEMP1 ; noun comp - verb comp14423 6,0423 1 0,0000 0 CCS A 14424 6,0424 0 0,0547 1 TC LXCH_LPRET ; noun comp G/ verb comp; return14425 6,0425 0 5,6271 0 TC CCSHOLE 14426 6,0426 0 6,6341 1 TC GODSPALM ; noun comp L/ verb comp NDOMPTST EQU * 14427 6,0427 0 0,0547 1 TC LXCH_LPRET ; noun comp = verb comp; return DCOMPTST EQU * 14430 6,0430 5 0,0420 1 TS SFTEMP1 ; - verb comp 14431 6,0431 3 0,0001 0 XCH Q ; was LXCH Q in block II14432 6,0432 5 0,0547 1 TS LXCH_LPRET ; save return address in faux LP 14433 6,0433 0 6,6435 0 TC DECTEST 14434 6,0434 0 6,6417 0 TC COMPTST1 ;--------------------------------------------------------------------------

Page 512: Apollo Guidance Computer AGC

; DECTEST ; alarms if dec only bit = 1 (bit 4 of comp code number1). Returns if not. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.327. ;-------------------------------------------------------------------------- DECTEST EQU * 14435 6,0435 3 0,0001 0 XCH Q ; was QXCH MPAC+2 in block II14436 6,0436 5 0,0132 1 TS MPAC+2 14437 6,0437 0 6,6501 0 TC GETCOMP 14440 6,0440 7 1,2063 1 MASK BIT14 14441 6,0441 1 0,0000 0 CCS A 14442 6,0442 0 6,6341 1 TC GODSPALM 14443 6,0443 0 0,0132 1 TC MPAC+2 ;-------------------------------------------------------------------------- ; DCTSTCYC ; alarms and recycles if dec only bit = 1 (bit 4 of comp code number). ; Returns if not. Used by load verbs. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.327. ;-------------------------------------------------------------------------- DCTSTCYC EQU * 14444 6,0444 3 0,0001 0 XCH Q ; was LXCH Q in block II14445 6,0445 5 0,0547 1 TS LXCH_LPRET ; save return address in faux LP 14446 6,0446 0 6,6501 0 TC GETCOMP 14447 6,0447 7 1,2063 1 MASK BIT14 14450 6,0450 1 0,0000 0 CCS A 14451 6,0451 0 2,4474 1 TC ALMCYCLE 14452 6,0452 0 0,0547 1 TC LXCH_LPRET ;-------------------------------------------------------------------------- ; NOUNTEST ; alarms if no-load bit (bit 5 of comp code number) = 1 ; if not, it returns. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.327. ;-------------------------------------------------------------------------- NOUNTEST EQU * 14453 6,0453 3 0,0001 0 XCH Q ; was LXCH Q in block II14454 6,0454 5 0,0547 1 TS LXCH_LPRET ; save return address in faux LP 14455 6,0455 0 6,6501 0 TC GETCOMP 14456 6,0456 1 0,0000 0 CCS A 14457 6,0457 0 0,0547 1 TC LXCH_LPRET 14460 6,0460 0 0,0547 1 TC LXCH_LPRET 14461 6,0461 0 6,6341 1 TC GODSPALM ;-------------------------------------------------------------------------- ; TSTFORDP ; test for DP. If so, get minor part only. ; The Block II version had some code that checked for a -1 in NNADTEM ; which meant use an I/O channel instead of memory. This was removed ; for the Block I. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.327. ;-------------------------------------------------------------------------- TSTFORDP EQU * 14462 6,0462 3 0,0001 0 XCH Q ; was LXCH Q in block II14463 6,0463 5 0,0547 1 TS LXCH_LPRET ; save return address in faux LP 14464 6,0464 2 0,0435 1 INDEX MIXBR 14465 6,0465 0 6,6465 0 TC * 14466 6,0466 0 6,6470 1 TC *+2 ; normal14467 6,0467 0 0,0547 1 TC LXCH_LPRET ; mixed case already handled in MIXNOUN 14470 6,0470 0 6,6762 1 TC SFRUTNOR 14471 6,0471 0 6,6240 1 TC DPTEST 14472 6,0472 0 0,0547 1 TC LXCH_LPRET ; no DP 14473 6,0473 3 0,0442 0 XCH NOUNADD ; was INCR NOUNADD in Block II14474 6,0474 6 1,2051 1 AD ONE ; DP E+1 into NOUNADD for minor part14475 6,0475 5 0,0442 0 TS NOUNADD

Page 513: Apollo Guidance Computer AGC

14476 6,0476 0 0,0547 1 TC LXCH_LPRET ;-------------------------------------------------------------------------- ; GETCOMP ; ; noun address is in NNADTEM ; noun type is in NNTYPTEM ; ; MIXBR is an enumerated type: ; 1 = normal nouns ; 2 = mixed nouns ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.328. ;-------------------------------------------------------------------------- 14477 6,0477 00444 0 COMPICK DS NNTYPTEM 14500 6,0500 00443 1 DS NNADTEM GETCOMP EQU * 14501 6,0501 2 0,0435 1 INDEX MIXBR ; normal mixed14502 6,0502 3 6,6476 1 CAF COMPICK-1 ; ADRES NNTYPTEM ADRES NNADTEM 14503 6,0503 2 0,0000 0 INDEX A 14504 6,0504 4 0,0000 0 CS 0 ; C(NNTYPTEM) C(NNADTEM)14505 6,0505 4 0,0000 0 COM ; was CA 0 in Block II14506 6,0506 7 2,4666 1 MASK HI5 14507 6,0507 0 0,0001 0 TC Q ;-------------------------------------------------------------------------- ; DECDSP -- DECIMAL DISPLAY ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.328. ;-------------------------------------------------------------------------- DECDSP EQU * 14510 6,0510 0 6,6501 0 TC GETCOMP 14511 6,0511 0 2,4647 0 TC LEFT5 14512 6,0512 7 1,2053 1 MASK THREE 14513 6,0513 5 0,0414 0 TS DECOUNT ; comp number into DECOUNT DSPDCGET EQU * 14514 6,0514 5 0,0417 0 TS DECTEM ; picks up data14515 6,0515 6 0,0442 0 AD NOUNADD ; DECTEM 1COMP +0, 2COMP +1, 3COMP +214516 6,0516 2 0,0000 0 INDEX A 14517 6,0517 4 0,0000 0 CS 0 14520 6,0520 2 0,0417 1 INDEX DECTEM 14521 6,0521 3 0,0472 0 XCH XREG ; cant use BUF since DMP uses it14522 6,0522 1 0,0417 1 CCS DECTEM 14523 6,0523 0 6,6514 1 TC DSPDCGET ; more to get DSPDCPUT EQU * 14524 6,0524 3 1,2050 0 CAF ZERO ; displays data14525 6,0525 5 0,0131 1 TS MPAC+1 ; DECOUNT 1COMP +0, 2COMP +1, 3COMP +214526 6,0526 5 0,0132 1 TS MPAC+2 14527 6,0527 2 0,0414 1 INDEX DECOUNT 14530 6,0530 3 2,4635 0 CAF R1D1 14531 6,0531 5 0,0466 0 TS DSPCOUNT 14532 6,0532 2 0,0414 1 INDEX DECOUNT 14533 6,0533 4 0,0472 1 CS XREG 14534 6,0534 5 0,0130 0 TS MPAC 14535 6,0535 0 6,7003 0 TC SFCONUM ; 2X (SF CON NUMB) in A14536 6,0536 5 0,0420 1 TS SFTEMP1 14537 6,0537 3 6,6550 1 CAF GTSFOUTL ; was DCA GTSFOUTL, DXCH Z in Block II14540 6,0540 0 1,3526 0 TC DXCHJUMP ; bank jump to SF constant table read rtne 14541 6,0541 2 0,0435 1 INDEX MIXBR 14542 6,0542 0 6,6542 1 TC *+0 14543 6,0543 0 6,6546 0 TC DSPSFNOR 14544 6,0544 0 6,6770 1 TC SFRUTMIX 14545 6,0545 0 6,6560 1 TC DECDSP3 DSPSFNOR EQU * 14546 6,0546 0 6,6762 1 TC SFRUTNOR 14547 6,0547 0 6,6560 1 TC DECDSP3 14550 6,0550 16162 0 GTSFOUTL DS GTSFOUT DSPDCEND EQU * 14551 6,0551 0 1,3565 1 TC BANKCALL ; all SFOUT routines end here14552 6,0552 13064 1 DS DSPDECWD 14553 6,0553 1 0,0414 1 CCS DECOUNT 14554 6,0554 0 6,6556 1 TC *+2 14555 6,0555 0 0,0433 0 TC ENTEXIT 14556 6,0556 5 0,0414 0 TS DECOUNT

Page 514: Apollo Guidance Computer AGC

14557 6,0557 0 6,6524 1 TC DSPDCPUT ; more to display DECDSP3 EQU * 14560 6,0560 2 0,0000 0 INDEX A 14561 6,0561 3 6,6563 1 CAF SFOUTABR 14562 6,0562 0 1,3712 0 TC BANKJUMP SFOUTABR EQU * 14563 6,0563 13265 1 CADR PREDSPAL ; 0, alarm if dec display with octal only noun14564 6,0564 14551 0 CADR DSPDCEND ; 1 14565 6,0565 12564 0 CADR DEGOUTSF ; 214566 6,0566 12644 1 CADR ARTOUTSF ; 3 14567 6,0567 00000 1 CADR 0 ; 4 **********14570 6,0570 00000 1 CADR 0 ; 5 **********14571 6,0571 00000 1 CADR 0 ; 6 **********14572 6,0572 00000 1 CADR 0 ; 7 **********14573 6,0573 16000 0 CADR HMSOUT ; 814574 6,0574 00000 1 CADR 0 ; 9 **********14575 6,0575 00000 1 CADR 0 ; 10 *********14576 6,0576 00000 1 CADR 0 ; 11 *********14577 6,0577 00000 1 CADR 0 ; 12 ********* BANK41_2 EQU * ORG BANK40_2 ; COLOSSUS pp. 330-332 INCL bank40_2.asm ;========================================================================== ; SCALE FACTOR ROUTINES (file:bank40_2.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 330-332. ;========================================================================== DEGOUTSF EQU * 12564 5,0564 3 1,2050 0 CAF ZERO 12565 5,0565 5 0,0132 1 TS MPAC+2 ; set index for full scale12566 5,0566 0 5,6603 1 TC FIXRANGE 12567 5,0567 0 5,6571 1 TC *+2 ; no augment needed (SFTEMP1 and 2 are 0)12570 5,0570 0 5,6572 1 TC SETAUG ; set augmenter according to C(MPAC+2)12571 5,0571 0 5,6616 0 TC DEGCOM SETAUG EQU * 12572 5,0572 3 1,2050 0 CAF ZERO ; loads SFTEMP1 and SFTEMP2 with the12573 5,0573 2 0,0132 0 INDEX MPAC+2 ; DP augmenter constant12574 5,0574 6 5,6640 0 AD DEGTAB ; was DCA DEGTAB, DXCH SFTEMP1 in Block II12575 5,0575 3 0,0420 1 XCH SFTEMP1 12576 5,0576 3 1,2050 0 CAF ZERO 12577 5,0577 2 0,0132 0 INDEX MPAC+2 12600 5,0600 6 5,6641 1 AD DEGTAB+1 12601 5,0601 3 0,0421 0 XCH SFTEMP1+1 12602 5,0602 0 0,0001 0 TC Q FIXRANGE EQU * 12603 5,0603 3 0,0001 0 XCH Q 12604 5,0604 5 0,0563 1 TS FR_RETQ 12605 5,0605 1 0,0130 1 CCS MPAC ; if MPAC is +, return to L+112606 5,0606 0 0,0563 1 TC FR_RETQ ; if MPAC is -, return to L+2 after12607 5,0607 0 0,0563 1 TC FR_RETQ ; masking out the sign bit12610 5,0610 0 5,6611 1 TC *+1 ; was TCF *+1 in Block II12611 5,0611 4 1,2062 0 CS BIT15 12612 5,0612 7 0,0130 1 MASK MPAC 12613 5,0613 5 0,0130 0 TS MPAC 12614 5,0614 2 0,0563 0 INDEX FR_RETQ 12615 5,0615 0 0,0001 0 TC 1 DEGCOM EQU * 12616 5,0616 3 1,2050 0 CAF ZERO ; was INDEX MPAC+2, DCA DEGTAB, DXCH MPAC inBlock II12617 5,0617 2 0,0132 0 INDEX MPAC+2 ; loads multiplier, does SHORTMP, and12620 5,0620 6 5,6641 1 AD DEGTAB+1 ; adds augmenter12621 5,0621 3 0,0131 1 XCH MPAC+1 ; adjusted angle in A 12622 5,0622 3 1,2050 0 CAF ZERO 12623 5,0623 2 0,0132 0 INDEX MPAC+2 12624 5,0624 6 5,6640 0 AD DEGTAB 12625 5,0625 3 0,0130 0 XCH MPAC 12626 5,0626 0 2,4353 0 TC SHORTMP 12627 5,0627 3 0,0421 0 XCH SFTEMP1+1 ; was DXCH SFTEMP1, DAS MPAC in Block II12630 5,0630 6 0,0131 1 AD MPAC+1

Page 515: Apollo Guidance Computer AGC

12631 5,0631 5 0,0131 1 TS MPAC+1 ; skip on overflow12632 5,0632 3 1,2050 0 CAF ZERO ; otherwise, make interword carry=0 12633 5,0633 6 0,0420 1 AD SFTEMP1 12634 5,0634 6 0,0130 0 AD MPAC 12635 5,0635 5 0,0130 0 TS MPAC ; skip on overflow12636 5,0636 3 1,2050 0 CAF ZERO ; otherwise, make interword carry=0 12637 5,0637 0 5,6651 0 TC SCOUTEND DEGTAB EQU * 12640 5,0640 05605 1 DS %05605 ; Hi part of .1812641 5,0641 03656 1 DS %03656 ; Lo part of .1812642 5,0642 16314 0 DS %16314 ; Hi part of .4512643 5,0643 31463 1 DS %31463 ; Lo part of .45 ARTOUTSF EQU * 12644 5,0644 3 0,0421 0 XCH SFTEMP1+1 ; was DXCH SFTEMP1, DXCH MPAC in Block II12645 5,0645 3 0,0131 1 XCH MPAC+1 ; assumes point at left of DP SFCON12646 5,0646 3 0,0420 1 XCH SFTEMP1 12647 5,0647 3 0,0130 0 XCH MPAC 12650 5,0650 0 2,4740 0 TC PRSHRTMP ; if C(A) = -0, SHORTMP fails to give -012651 5,0651 0 1,3653 1 SCOUTEND TC POSTJUMP 12652 5,0652 14551 0 CADR DSPDCEND ;-------------------------------------------------------------------------- ; READLO ; Picks up fresh data for both HI and LO and leaves it in MPAC, MPAC+1. ; This is needed for time display. It zeroes MPAC+2, but does not force ; TPAGREE. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.332. ;-------------------------------------------------------------------------- READLO EQU * 12653 5,0653 3 0,0001 0 XCH Q 12654 5,0654 5 0,0441 0 TS TEM4 ; save return address 12655 5,0655 2 0,0435 1 INDEX MIXBR 12656 5,0656 0 5,6656 1 TC * 12657 5,0657 0 5,6701 1 TC RDLONOR ; MIXBR=1, so normal noun 12660 5,0660 3 1,2050 0 CAF ZERO ; MIXBR=2, so mixed noun12661 5,0661 2 0,0414 1 INDEX DECOUNT ; was INDEX DECOUNT, CA IDAD1TEM in Block II12662 5,0662 6 0,0445 1 AD IDAD1TEM ; get IDADDTAB entry for comp K of noun12663 5,0663 7 2,4672 1 MASK LOW11 ; E bank12664 5,0664 0 2,4633 0 TC SETEBANK ; set EB, leave E address in A ; Dereference noun address to move components of noun into MPAC, MPAC+1 ; mixed normal ; C(E SUBK) C(E) ; C((E SUBK)+1) C(E+1) READLO1 EQU * 12665 5,0665 5 0,0576 0 TS ADDRWD1 ; temp store addr for immediate use below 12666 5,0666 3 1,2050 0 CAF ZERO ; was INDEX A, DCA Q, DXCH MPAC in Block II12667 5,0667 2 0,0576 1 INDEX ADDRWD1 12670 5,0670 6 0,0000 1 AD 0 12671 5,0671 5 0,0130 0 TS MPAC 12672 5,0672 3 1,2050 0 CAF ZERO 12673 5,0673 2 0,0576 1 INDEX ADDRWD1 12674 5,0674 6 0,0001 0 AD 1 12675 5,0675 5 0,0131 1 TS MPAC+1 12676 5,0676 3 1,2050 0 CAF ZERO 12677 5,0677 5 0,0132 1 TS MPAC+2 12700 5,0700 0 0,0441 0 TC TEM4 ; return 12701 5,0701 3 1,2050 0 RDLONOR CAF ZERO ; was CA NOUNADD in Block II12702 5,0702 6 0,0442 0 AD NOUNADD 12703 5,0703 0 5,6665 1 ENDRDLO TC READLO1 BANK40_3 EQU * ORG BANK42_1 ; COLOSSUS pp. 333-336 INCL bank42_1.asm

Page 516: Apollo Guidance Computer AGC

;========================================================================== ; DISPLAY ROUTINES (file:bank42_1.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 333-336. ;========================================================================== ;-------------------------------------------------------------------------- ; HMSOUT -- OUTPUT SCALE FACTOR ROUTINE ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.333. ;-------------------------------------------------------------------------- HMSOUT EQU * 16000 7,0000 0 1,3565 1 TC BANKCALL ; read fresh data for HI and LO into MPAC,16001 7,0001 12653 1 DS READLO ; MPAC+1. 16002 7,0002 0 2,4150 1 TC TPAGREE ; make DP data agree16003 7,0003 0 7,6053 1 TC SEPSECNR ; leave frac sec/60 in MPAC, MPAC+1, leave ; whole min in bit13 of LOWTEMOUT and above16004 7,0004 0 2,4374 0 TC DMP ; use only fract sec/60 mod 6016005 7,0005 06043 0 ADRES SECON2 ; mult by .06 16006 7,0006 3 2,4637 1 CAF R3D1 ; gives CENT1-SEC/10EXP5 mod 6016007 7,0007 5 0,0466 0 TS DSPCOUNT 16010 7,0010 0 1,3565 1 TC BANKCALL ; display sec mod 6016011 7,0011 13064 1 DS DSPDECWD 16012 7,0012 0 7,6074 1 TC SEPMIN ; remove rest of seconds16013 7,0013 3 7,6045 0 CAF MINCON2 ; leave fract min/60 in MPAC+1, leave16014 7,0014 3 0,0130 0 XCH MPAC ; whole hours in MPAC16015 7,0015 5 0,0476 1 TS HITEMOUT ; save whole hours16016 7,0016 3 7,6046 0 CAF MINCON2+1 16017 7,0017 3 0,0131 1 XCH MPAC+1 ; use only fract min/60 mod 6016020 7,0020 0 2,4740 0 TC PRSHRTMP ; if C(A) = -0, SHORTMP fails to give -0. ; mult by .000616021 7,0021 3 2,4636 0 CAF R2D1 ; gives min/10EXP5 mod 6016022 7,0022 5 0,0466 0 TS DSPCOUNT 16023 7,0023 0 1,3565 1 TC BANKCALL ; display min mod 6016024 7,0024 13064 1 DS DSPDECWD 16025 7,0025 3 7,6051 0 CAF HRCON1 ; was DCA HRCON1, DXCH MPAC in Block II16026 7,0026 5 0,0130 0 TS MPAC 16027 7,0027 3 7,6052 0 CAF HRCON1+1 16030 7,0030 5 0,0131 1 TS MPAC+1 ; minutes, seconds have been removed 16031 7,0031 3 1,2050 0 CAF ZERO ; was CA HITEMOUT in Block II16032 7,0032 6 0,0476 1 AD HITEMOUT ; use whole hours16033 7,0033 0 2,4740 0 TC PRSHRTMP ; if C(A) = -0, SHORTMP fails to give -0. ; mult by .1638416034 7,0034 3 2,4635 0 CAF R1D1 ; gives hours/10EXP516035 7,0035 5 0,0466 0 TS DSPCOUNT 16036 7,0036 0 1,3565 1 TC BANKCALL ; use regular DSPDECWD, with round off16037 7,0037 13064 1 DS DSPDECWD 16040 7,0040 0 0,0433 0 TC ENTEXIT 16041 7,0041 25660 0 SECON1 DS %25660 ; 2EXP12/600016042 7,0042 31742 1 DS %31742 16043 7,0043 01727 1 SECON2 DS %01727 ; .06 for seconds display16044 7,0044 01217 1 DS %01217 16045 7,0045 00011 1 MINCON2 DS %00011 ; .0006 for minutes display16046 7,0046 32445 0 DS %32445 16047 7,0047 02104 0 MINCON1 DS %02104 ; .066..66 upped by 2EXP-2816050 7,0050 10422 1 DS %10422 16051 7,0051 05174 0 HRCON1 DS %05174 ; .16384 decimal16052 7,0052 13261 0 DS %13261 ; ************* missing stuff **************** SEPSECNR EQU * 16053 7,0053 3 0,0001 0 XCH Q ; this entry avoid rounding by .5 secs16054 7,0054 5 0,0441 0 TS SEPSCRET 16055 7,0055 0 2,4374 0 TC DMP ; mult by 2EXP12/600016056 7,0056 06041 1 ADRES SECON1 ; gives fract sec/60 in bit12 of MPAC+1

Page 517: Apollo Guidance Computer AGC

16057 7,0057 3 1,2050 0 CAF ZERO ; was DCA MPAC, DXCH HITEMOUT in Block II16060 7,0060 6 0,0130 0 AD MPAC ; save minutes and hours16061 7,0061 3 0,0476 1 XCH HITEMOUT 16062 7,0062 3 1,2050 0 CAF ZERO 16063 7,0063 6 0,0131 1 AD MPAC+1 16064 7,0064 3 0,0477 0 XCH HITEMOUT+1 16065 7,0065 0 2,4721 1 TC TPSL1 16066 7,0066 0 2,4721 1 TC TPSL1 ; gives fract sec/60 in MPAC+1, MPAC+2 16067 7,0067 3 1,2050 0 CAF ZERO 16070 7,0070 3 0,0132 1 XCH MPAC+2 ; leave fract sec/60 in MPAC, MPAC+116071 7,0071 3 0,0131 1 XCH MPAC+1 16072 7,0072 3 0,0130 0 XCH MPAC 16073 7,0073 0 0,0441 0 TC SEPSCRET SEPMIN EQU * 16074 7,0074 3 0,0001 0 XCH Q ; finds whole minutes in bit1316075 7,0075 5 0,0441 0 TS SEPMNRET ; of LOWTEMOUT and above. 16076 7,0076 3 1,2050 0 CAF ZERO 16077 7,0077 6 0,0477 0 AD LOTEMOUT ; removes rest of seconds 16100 7,0100 2 0,0000 1 EXTEND ; leaves fract min/60 in MPAC+116101 7,0101 4 1,2076 0 MP BIT3 ; leaves whole hours in MPAC16102 7,0102 2 0,0000 1 EXTEND ; SR 12, throw away LP16103 7,0103 4 1,2064 0 MP BIT13 ; SR 2?, take from LP. = SL 12 16104 7,0104 3 0,0003 1 XCH LP ; was LXCH MPAC+1 in Block II16105 7,0105 5 0,0131 1 TS MPAC+1 ; this forces bits 12-1 to 0 if +, ; forces bits 12-1 to 1 if -. 16106 7,0106 3 1,2050 0 CAF ZERO 16107 7,0107 6 0,0476 1 AD HITEMOUT 16110 7,0110 5 0,0130 0 TS MPAC 16111 7,0111 0 2,4374 0 TC DMP ; mult by 1/1516112 7,0112 06047 1 ADRES MINCON1 ; gives fract min/60 in MPAC+116113 7,0113 0 0,0441 0 ENDSPMIN TC SEPMNRET ; gives whole hours in MPAC BANK42_2 EQU * ORG BANK40_3 ; COLOSSUS pp. 336 INCL bank40_3.asm ;========================================================================== ; WORD DISPLAY ROUTINES (file:bank40_3.asm) ; ; AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.336. ;========================================================================== ;-------------------------------------------------------------------------- ; DSPDPDEC ; This is a special purpose verb for displaying a double precision AGC ; word as 10 decimal digits on the AGC display panel. It can be used with ; any noun, except mixed nouns. It displays the contents of the register ; NOUNADD is pointing to. If used with nouns which are inherently not DP ; such as the CDU counters, the display will be garbage. ; Display is in R1 and R2 only with the sign in R1. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.353. ;-------------------------------------------------------------------------- DSPDPDEC EQU * 12704 5,0704 2 0,0435 1 INDEX MIXBR 12705 5,0705 0 5,6705 0 TC *+0 12706 5,0706 0 5,6710 1 TC *+2 ; normal noun12707 5,0707 0 5,7267 0 TC DSPALARM 12710 5,0710 3 1,2050 0 CAF ZERO 12711 5,0711 2 0,0442 1 INDEX NOUNADD 12712 5,0712 6 0,0000 1 AD 0 ; was DCA 0, DXCH MPAC in Block II12713 5,0713 5 0,0130 0 TS MPAC 12714 5,0714 3 1,2050 0 CAF ZERO 12715 5,0715 2 0,0442 1 INDEX NOUNADD 12716 5,0716 6 0,0001 0 AD 1 ; was DCA 0, DXCH MPAC in Block II12717 5,0717 5 0,0131 1 TS MPAC+1 12720 5,0720 3 2,4635 0 CAF R1D1 12721 5,0721 5 0,0466 0 TS DSPCOUNT

Page 518: Apollo Guidance Computer AGC

12722 5,0722 3 1,2050 0 CAF ZERO 12723 5,0723 5 0,0132 1 TS MPAC+2 12724 5,0724 0 2,4150 1 TC TPAGREE 12725 5,0725 0 5,7131 0 TC DSP2DEC 12726 5,0726 0 0,0433 0 ENDDPDEC TC ENTEXIT BANK40_4 EQU * ORG BANK41_2 ; COLOSSUS pp. 337-342 INCL bank41_2.asm ;========================================================================== ; DISPLAY ROUTINES (file:bank41_2.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 337-342. ;========================================================================== ;========================================================================== ; PINBALL GAME LOAD VERBS (file:bank41_2.asm) ; ; If alarm condition is detected during execute, check fail light is ; turned on and ENDOFJOB. If alarm condition is detected during enter ; of data, check fail is turned on and it recycles to execute of ; original load verb. Recycle caused by 1) decimal machine CADR, ; 2) mixture of octal/decimal data, 3) octal data into decimal only ; noun, 4) decimal data into octal only noun, 5) data too large for ; scale, 6) fewer than two data words loaded for HRS, MIN, SEC noun. ; For #2-6, alarm and recycle occur at final enter of set; for #1, ; alarm and recycle occur at enter of CADR. ; ; AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.337-343. ;========================================================================== ABCLOAD EQU * 14600 6,0600 4 1,2052 0 CS TWO 14601 6,0601 0 6,6414 0 TC COMPTEST 14602 6,0602 0 6,6453 0 TC NOUNTEST ; test if noun can be loaded 14603 6,0603 3 6,6733 0 CAF VBSP1LD 14604 6,0604 0 6,6326 0 TC UPDATVB-1 14605 6,0605 0 6,6264 1 TC REQDATX 14606 6,0606 3 6,6734 1 CAF VBSP2LD 14607 6,0607 0 6,6326 0 TC UPDATVB-1 14610 6,0610 0 6,6270 1 TC REQDATY 14611 6,0611 3 6,6735 0 CAF VBSP3LD 14612 6,0612 0 6,6326 0 TC UPDATVB-1 14613 6,0613 0 6,6274 0 TC REQDATZ PUTXYZ EQU * 14614 6,0614 4 1,2056 1 CS SIX ; test that the 3 data words loaded are14615 6,0615 0 6,6736 0 TC ALLDC_OC ; all dec or all oct 14616 6,0616 3 6,6124 0 CAF LODNNLOC ; was DCA LODNNLOC, DXCH Z in Block II14617 6,0617 0 1,3526 0 TC DXCHJUMP ; bank jump to noun table read rtne 14620 6,0620 3 1,2050 0 CAF ZERO ; X comp14621 6,0621 0 6,7031 1 TC PUTCOM 14622 6,0622 2 0,0442 1 INDEX NOUNADD 14623 6,0623 5 0,0000 1 TS 0 14624 6,0624 3 1,2051 1 CAF ONE ; Y comp14625 6,0625 0 6,7031 1 TC PUTCOM 14626 6,0626 2 0,0442 1 INDEX NOUNADD 14627 6,0627 5 0,0001 0 TS 1 14630 6,0630 3 1,2052 1 CAF TWO ; Z comp14631 6,0631 0 6,7031 1 TC PUTCOM 14632 6,0632 2 0,0442 1 INDEX NOUNADD 14633 6,0633 5 0,0002 0 TS 2 ; *************** missing stuff ***************** ; Omitted a bunch of code from here that does special stuff if the noun=7. ; (a noun that operates on I/O channels and flagbits) 14634 6,0634 0 6,6723 1 TC LOADLV ABLOAD EQU *

Page 519: Apollo Guidance Computer AGC

14635 6,0635 4 1,2051 0 CS ONE 14636 6,0636 0 6,6414 0 TC COMPTEST 14637 6,0637 0 6,6453 0 TC NOUNTEST ; test if noun can be loaded 14640 6,0640 3 6,6733 0 CAF VBSP1LD 14641 6,0641 0 6,6326 0 TC UPDATVB-1 14642 6,0642 0 6,6264 1 TC REQDATX 14643 6,0643 3 6,6734 1 CAF VBSP2LD 14644 6,0644 0 6,6326 0 TC UPDATVB-1 14645 6,0645 0 6,6270 1 TC REQDATY PUTXY EQU * 14646 6,0646 4 1,2055 1 CS FIVE ; test that the 2 data words loaded are14647 6,0647 0 6,6736 0 TC ALLDC_OC ; all dec or all oct 14650 6,0650 3 6,6124 0 CAF LODNNLOC ; was DCA LODNNLOC, DXCH Z in Block II14651 6,0651 0 1,3526 0 TC DXCHJUMP ; bank jump to noun table read rtne 14652 6,0652 3 1,2050 0 CAF ZERO ; X comp14653 6,0653 0 6,7031 1 TC PUTCOM 14654 6,0654 2 0,0442 1 INDEX NOUNADD 14655 6,0655 5 0,0000 1 TS 0 14656 6,0656 3 1,2051 1 CAF ONE ; Y comp14657 6,0657 0 6,7031 1 TC PUTCOM 14660 6,0660 2 0,0442 1 INDEX NOUNADD 14661 6,0661 5 0,0001 0 TS 1 14662 6,0662 0 6,6723 1 TC LOADLV ALOAD EQU * 14663 6,0663 0 6,6264 1 TC REQDATX 14664 6,0664 3 6,6124 0 CAF LODNNLOC ; was DCA LODNNLOC, DXCH Z in Block II14665 6,0665 0 1,3526 0 TC DXCHJUMP ; bank jump to noun table read rtne 14666 6,0666 3 1,2050 0 CAF ZERO ; X comp14667 6,0667 0 6,7031 1 TC PUTCOM 14670 6,0670 2 0,0442 1 INDEX NOUNADD 14671 6,0671 5 0,0000 1 TS 0 14672 6,0672 0 6,6723 1 TC LOADLV BLOAD EQU * 14673 6,0673 4 1,2051 0 CS ONE 14674 6,0674 0 6,6414 0 TC COMPTEST 14675 6,0675 3 1,2062 1 CAF BIT15 ; set CLPASS for PASS0 only14676 6,0676 5 0,0504 0 TS CLPASS 14677 6,0677 0 6,6270 1 TC REQDATY 14700 6,0700 3 6,6124 0 CAF LODNNLOC ; was DCA LODNNLOC, DXCH Z in Block II14701 6,0701 0 1,3526 0 TC DXCHJUMP ; bank jump to noun table read rtne14702 6,0702 3 1,2051 1 CAF ONE 14703 6,0703 0 6,7031 1 TC PUTCOM 14704 6,0704 2 0,0442 1 INDEX NOUNADD 14705 6,0705 5 0,0001 0 TS 1 14706 6,0706 0 6,6723 1 TC LOADLV CLOAD EQU * 14707 6,0707 4 1,2052 0 CS TWO 14710 6,0710 0 6,6414 0 TC COMPTEST 14711 6,0711 3 1,2062 1 CAF BIT15 ; set CLPASS for PASS0 only14712 6,0712 5 0,0504 0 TS CLPASS 14713 6,0713 0 6,6274 0 TC REQDATZ 14714 6,0714 3 6,6124 0 CAF LODNNLOC ; was DCA LODNNLOC, DXCH Z in Block II14715 6,0715 0 1,3526 0 TC DXCHJUMP ; bank jump to noun table read rtne14716 6,0716 3 1,2052 1 CAF TWO 14717 6,0717 0 6,7031 1 TC PUTCOM 14720 6,0720 2 0,0442 1 INDEX NOUNADD 14721 6,0721 5 0,0002 0 TS 2 14722 6,0722 0 6,6723 1 TC LOADLV ; yes, COLOSSUS actually did this LOADLV EQU * 14723 6,0723 3 1,2050 0 CAF ZERO 14724 6,0724 5 0,0467 1 TS DECBRNCH 14725 6,0725 4 1,2050 1 CS ZERO 14726 6,0726 5 0,0503 1 TS LOADSTAT 14727 6,0727 4 2,4675 0 CS VD1 ; to block numerical chars and14730 6,0730 5 0,0466 0 TS DSPCOUNT ; clears after a completed load14731 6,0731 0 1,3653 1 TC POSTJUMP ; after completed load, go to RECALTST14732 6,0732 13413 0 DS RECALTST ; to see if there is RECALL from ENDIDLE 14733 6,0733 00025 0 VBSP1LD DS 21 ; VB21 = ALOAD14734 6,0734 00026 0 VBSP2LD DS 22 ; VB22 = BLOAD14735 6,0735 00027 1 VBSP3LD DS 23 ; VB23 = CLOAD ALLDC_OC EQU * 14736 6,0736 5 0,0414 0 TS DECOUNT ; test that data words loaded are either

Page 520: Apollo Guidance Computer AGC

14737 6,0737 3 0,0001 0 XCH Q ; (needed to handle TCF conversion below)14740 6,0740 5 0,0556 1 TS ALLDC_OC_Q ; save return address 14741 6,0741 4 0,0467 0 CS DECBRNCH ; all dec or all oct; alarms if not14742 6,0742 5 0,0021 1 TS SR 14743 6,0743 4 0,0021 0 CS SR 14744 6,0744 4 0,0021 0 CS SR ; shifted right 214745 6,0745 1 0,0000 0 CCS A ; dec comp bits in low 314746 6,0746 0 6,6750 0 TC *+2 ; some ones in low 3 (was TCF in Block II)14747 6,0747 0 0,0556 1 TC ALLDC_OC_Q ; all zeros, all oct, OK so return14750 6,0750 6 0,0414 0 AD DECOUNT ; dec comp = 7 for 3comp, =6 for 2comp ; (but it has been decremented by CCS)14751 6,0751 1 0,0000 0 CCS A ; must match 6 for 3comp, 5 for 2comp14752 6,0752 0 6,6756 0 TC *+4 ; >014753 6,0753 0 6,6755 0 TC *+2 ; +014754 6,0754 0 6,6756 0 TC *+2 ; <014755 6,0755 0 6,6757 1 TC *+2 ; -0, was BZF *+2 in Block II 14756 6,0756 0 2,4474 1 TC ALMCYCLE ; alarm and recycle (does not return) 14757 6,0757 3 0,0556 1 XCH ALLDC_OC_Q ; restore return address14760 6,0760 5 0,0001 0 TS Q 14761 6,0761 0 0,0001 0 GOQ TC Q ; all required are dec, OK ;-------------------------------------------------------------------------- ; SFRUTNOR ; gets SF routine number for normal case. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.340. ;-------------------------------------------------------------------------- SFRUTNOR EQU * 14762 6,0762 3 0,0001 0 XCH Q 14763 6,0763 5 0,0411 0 TS EXITEM ; can't use L for return. TESTFORDP uses L.14764 6,0764 3 2,4665 0 CAF MID5 14765 6,0765 7 0,0444 1 MASK NNTYPTEM 14766 6,0766 0 2,4640 1 TC RIGHT5 14767 6,0767 0 0,0411 0 TC EXITEM ; SF routine number in A ;-------------------------------------------------------------------------- ; SFRUTMIX ; gets SF routine number for mixed case. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.340. ;-------------------------------------------------------------------------- SFRUTMIX EQU * 14770 6,0770 3 0,0001 0 XCH Q ; gets SF routine number for mixed case14771 6,0771 5 0,0411 0 TS EXITEM 14772 6,0772 2 0,0414 1 INDEX DECOUNT 14773 6,0773 3 6,7022 0 CAF DISPLACE ; put TC GOQ, TC RIGHT5, or TC LEFT5 in L14774 6,0774 5 0,0557 0 TS SFRUTMIX_L 14775 6,0775 2 0,0414 1 INDEX DECOUNT 14776 6,0776 3 2,4664 1 CAF LOW5 ; LOW5, MID5, or HI5 in A14777 6,0777 7 0,0450 1 MASK RUTMXTEM ; get HI5, MID5, or LOW5 of RUTMXTAB entry 15000 6,1000 2 0,0557 1 INDEX SFRUTMIX_L 15001 6,1001 0 0,0000 1 TC 0 ; do TC GOQ (DECOUNT=0), do TC RIGHT5 (DECOUNT=1), do TC LEFT5 (DECOUNT=2) 15002 6,1002 0 0,0411 0 SFRET1 TC EXITEM ; SF routine number in A SFCONUM EQU * 15003 6,1003 3 0,0001 0 XCH Q ; gets 2X (SF constant number)15004 6,1004 5 0,0411 0 TS EXITEM 15005 6,1005 2 0,0435 1 INDEX MIXBR 15006 6,1006 0 6,7006 0 TC *+0 15007 6,1007 0 6,7025 1 TC CONUMNOR ; normal noun15010 6,1010 2 0,0414 1 INDEX DECOUNT ; mixed noun15011 6,1011 3 6,7022 0 CAF DISPLACE 15012 6,1012 5 0,0560 1 TS SFCONUM_L ; put TC GOQ, TC RIGHT5, or TC LEFT5 in L15013 6,1013 2 0,0414 1 INDEX DECOUNT 15014 6,1014 3 2,4664 1 CAF LOW5 15015 6,1015 7 0,0444 1 MASK NNTYPTEM 15016 6,1016 2 0,0560 0 INDEX SFCONUM_L 15017 6,1017 0 0,0000 1 TC 0 ; do TC GOQ (DECOUNT=0), do TC RIGHT5 (DECOUNT=1), do TC LEFT5 (DECOUNT=2)

Page 521: Apollo Guidance Computer AGC

15020 6,1020 6 0,0000 1 SFRET DOUBLE ; 2X (SF constant number) in A15021 6,1021 0 0,0411 0 TC EXITEM DISPLACE EQU * 15022 6,1022 0 6,6761 1 TC GOQ 15023 6,1023 0 2,4640 1 TC RIGHT5 15024 6,1024 0 2,4647 0 TC LEFT5 CONUMNOR EQU * 15025 6,1025 3 2,4664 1 CAF LOW5 ; normal noun always gets low 5 of15026 6,1026 7 0,0444 1 MASK NNTYPTEM ; NNTYPTAB for SF CONUM15027 6,1027 6 0,0000 1 DOUBLE 15030 6,1030 0 0,0411 0 TC EXITEM ; 2X (SF constant number) in A PUTCOM EQU * 15031 6,1031 5 0,0414 0 TS DECOUNT 15032 6,1032 3 0,0001 0 XCH Q 15033 6,1033 5 0,0412 0 TS DECRET 15034 6,1034 3 1,2050 0 CAF ZERO 15035 6,1035 5 0,0136 0 TS MPAC+6 15036 6,1036 2 0,0414 1 INDEX DECOUNT 15037 6,1037 3 0,0475 1 XCH XREGLP 15040 6,1040 5 0,0131 1 TS MPAC+1 15041 6,1041 2 0,0414 1 INDEX DECOUNT 15042 6,1042 3 0,0472 0 XCH XREG 15043 6,1043 5 0,0130 0 TS MPAC 15044 6,1044 2 0,0435 1 INDEX MIXBR 15045 6,1045 0 6,7045 1 TC * 15046 6,1046 0 6,7077 0 TC PUTNORM ; normal noun ; if mixnoun, place address for component K into NOUNADD, set EBANK bits. 15047 6,1047 2 0,0414 1 INDEX DECOUNT ; set IDADDTAB entry for component K15050 6,1050 3 1,2050 0 CAF ZERO ; of noun15051 6,1051 6 0,0445 1 AD IDAD1TEM ; was CA IDAD1TEM in Block II15052 6,1052 7 2,4672 1 MASK LOW11 ; (ECADR) SUBK for current comp of noun15053 6,1053 0 2,4616 1 TC SETNCADR ; ECADR into NOUNCADR, sets EB, NOUNADD15054 6,1054 2 0,0000 1 EXTEND ; C(NOUNADD) in A upon return15055 6,1055 6 0,0414 0 SU DECOUNT ; place (ESUBK)-K into NOUNADD15056 6,1056 5 0,0442 0 TS NOUNADD 15057 6,1057 1 0,0467 0 CCS DECBRNCH 15060 6,1060 0 6,7114 1 TC PUTDECSF ; + dec15061 6,1061 0 6,6444 0 TC DCTSTCYC ; +0 octal15062 6,1062 0 6,6770 1 TC SFRUTMIX ; test if dec only bit = 1. If so,15063 6,1063 0 6,6240 1 TC DPTEST ; alarm and recycle. If not, continue.15064 6,1064 0 6,7111 1 TC PUTCOM2 ; no DP ; test for DP scale for oct load. If so, ; +0 into major part. Set NOUNADD for ; loading octal word into minor part. PUTDPCOM EQU * 15065 6,1065 3 1,2050 0 CAF ZERO ; was INCR NOUNADD in Block II15066 6,1066 6 0,0442 0 AD NOUNADD ; DP (RSUBK)-K+1 or E+115067 6,1067 6 1,2051 1 AD ONE 15070 6,1070 5 0,0442 0 TS NOUNADD 15071 6,1071 6 0,0414 0 AD DECOUNT ; (ESUBK)+1 or E+1 into DECOUNT15072 6,1072 5 0,0414 0 TS DECOUNT ; was ADS DECOUNT in Block II 15073 6,1073 3 1,2050 0 CAF ZERO ; NOUNADD set for minor part15074 6,1074 2 0,0414 1 INDEX DECOUNT 15075 6,1075 5 17,7776 0 TS -1 ; zero major part (ESUBK or E1)15076 6,1076 0 6,7111 1 TC PUTCOM2 PUTNORM EQU * 15077 6,1077 0 2,4625 1 TC SETNADD ; ECADR from NOUNCADR, sets EB, NOUNADD15100 6,1100 1 0,0467 0 CCS DECBRNCH 15101 6,1101 0 6,7114 1 TC PUTDECSF ; +DEC15102 6,1102 0 6,6444 0 TC DCTSTCYC ; +0 octal15103 6,1103 0 6,6762 1 TC SFRUTNOR ; test if dec only bit = 1. If so,15104 6,1104 0 6,6240 1 TC DPTEST ; alarm and recycle. If not, continue.15105 6,1105 0 6,7111 1 TC PUTNORM_1 ; no DP15106 6,1106 3 1,2050 0 CAF ZERO 15107 6,1107 5 0,0414 0 TS DECOUNT 15110 6,1110 0 6,7065 0 TC PUTDPCOM PUTNORM_1 EQU * ; eliminated Block II CHANNEL LOAD code PUTCOM2 EQU * 15111 6,1111 3 0,0130 0 XCH MPAC 15112 6,1112 0 0,0412 0 TC DECRET 15113 6,1113 16176 0 GTSFINLC DS GTSFIN ; *************** missing stuff *****************

Page 522: Apollo Guidance Computer AGC

; PUTDECSF ; Finds MIXBR and DECOUNT still set from PUTCOM PUTDECSF EQU * 15114 6,1114 0 6,7003 0 TC SFCONUM ; 2X (SF CON NUM) in A15115 6,1115 5 0,0420 1 TS SFTEMP1 15116 6,1116 3 6,7113 0 CAF GTSFINLC ; was DCA GTSFINLC, DXCH Z in Block II15117 6,1117 0 1,3526 0 TC DXCHJUMP ; bank jump to SF const table read rtne ; loads SFTEMP1, SFTEMP215120 6,1120 2 0,0435 1 INDEX MIXBR 15121 6,1121 0 6,7121 1 TC * 15122 6,1122 0 6,7125 0 TC PUTSFNOR 15123 6,1123 0 6,6770 1 TC SFRUTMIX 15124 6,1124 0 6,7126 0 TC PUTDCSF2 15125 6,1125 0 6,6762 1 PUTSFNOR TC SFRUTNOR 15126 6,1126 2 0,0000 0 PUTDCSF2 INDEX A 15127 6,1127 3 6,7131 0 CAF SFINTABR 15130 6,1130 0 1,3712 0 TC BANKJUMP ; switch banks for expansion room15131 6,1131 14340 0 SFINTABR CADR GOALMCYC ; 0, alarm and recycle if dec load15132 6,1132 13011 0 CADR BINROUND ; 115133 6,1133 12727 0 CADR DEGINSF ; 215134 6,1134 12776 1 CADR ARTHINSF ; 315135 6,1135 00000 1 CADR 0 ; 4 **********15136 6,1136 00000 1 CADR 0 ; 5 **********15137 6,1137 00000 1 CADR 0 ; 6 **********15140 6,1140 00000 1 CADR 0 ; 7 **********15141 6,1141 00000 1 CADR 0 ; 8 **********15142 6,1142 00000 1 CADR 0 ; 9 **********15143 6,1143 00000 1 CADR 0 ; 10 *********15144 6,1144 00000 1 CADR 0 ; 11 *********15145 6,1145 00000 1 CADR 0 ; 12 ********* ; BUNCH OF TABLE ENTRIES GO HERE!!!!! ; ************ NEED TO ADD THE REST ************* BANK41_3 EQU * ORG BANK40_4 ; COLOSSUS pp. 343-346 INCL bank40_4.asm ;========================================================================== ; SCALE FACTOR ROUTINES (file:bank40_4.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 343-346. ;========================================================================== DEGINSF EQU * 12727 5,0727 0 2,4374 0 TC DMP ; SF routine for dec degrees12730 5,0730 06772 0 ADRES DEGCON1 ; mult by 5.5 5(10)X2EXP-312731 5,0731 1 0,0131 0 CCS MPAC+1 ; this rounds off MPAC+1 before shift12732 5,0732 3 1,2066 0 CAF BIT11 ; left 3, and causes 360.00 to OF/UF12733 5,0733 0 5,6735 0 TC *+2 ; when shifted left and alarm12734 5,0734 4 1,2066 1 CS BIT11 12735 5,0735 6 0,0131 1 AD MPAC+1 12736 5,0736 0 5,7016 1 TC _2ROUND+2 12737 5,0737 0 2,4721 1 TC TPSL1 ; left 112740 5,0740 0 2,4721 1 DEGINSF2 TC TPSL1 ; left 212741 5,0741 0 5,7025 1 TC TESTOFUF 12742 5,0742 0 2,4721 1 TC TPSL1 ; returns if no OF/UF (left 3)12743 5,0743 1 0,0130 1 CCS MPAC 12744 5,0744 0 5,6750 0 TC SIGNFIX ; if +, go to SIGNFIX12745 5,0745 0 5,6750 0 TC SIGNFIX ; if +0, go to SIGNFIX12746 5,0746 4 0,0000 0 COM ; if -, use -MAGNITUDE + 112747 5,0747 5 0,0130 0 TS MPAC ; -f -0; use +012750 5,0750 1 0,0136 1 SIGNFIX CCS MPAC+6 12751 5,0751 0 5,6766 0 TC SGNTO1 ; if overflow12752 5,0752 0 5,6762 1 TC ENDSCALE ; no overflow/underflow12753 5,0753 1 0,0130 1 CCS MPAC ; if UF, force sign to 0 except -18012754 5,0754 0 5,6271 0 TC CCSHOLE 12755 5,0755 0 5,6764 1 TC NEG180 12756 5,0756 0 5,6757 1 TC *+1 12757 5,0757 3 0,0130 0 XCH MPAC 12760 5,0760 7 1,2106 0 MASK POSMAX 12761 5,0761 5 0,0130 0 TS MPAC ENDSCALE EQU * 12762 5,0762 0 1,3653 1 TC POSTJUMP 12763 5,0763 15111 1 CADR PUTCOM2 12764 5,0764 4 1,2106 0 NEG180 CS POSMAX 12765 5,0765 0 5,6761 1 TC ENDSCALE-1

Page 523: Apollo Guidance Computer AGC

SGNTO1 EQU * 12766 5,0766 4 0,0130 1 CS MPAC ; if OV force sign to 112767 5,0767 7 1,2106 0 MASK POSMAX 12770 5,0770 4 0,0000 0 CS A 12771 5,0771 0 5,6761 1 TC ENDSCALE-1 12772 5,0772 26161 0 DEGCON1 DS %26161 12773 5,0773 30707 1 DS %30707 12774 5,0774 21616 0 DEGCON2 DS %21616 12775 5,0775 07071 0 DS %07071 ; ************ missing stuff *************** ARTHINSF EQU * 12776 5,0776 0 2,4374 0 TC DMP ; scales MPAC, +1 by SFTEMP1, SFTEMP212777 5,0777 00420 1 ADRES SFTEMP1 ; assumes point between HI and LO parts13000 5,1000 3 0,0132 1 XCH MPAC+2 ; of SFCON, shifts results left by 14.13001 5,1001 3 0,0131 1 XCH MPAC+1 ; (by taking results from MPAC+1, MPAC+2)13002 5,1002 3 0,0130 0 XCH MPAC 13003 5,1003 1 0,0000 0 CCS A ; was BZF BINROUND in Block II13004 5,1004 0 5,7010 1 TC *+4 ; >013005 5,1005 0 5,7007 1 TC *+2 ; +013006 5,1006 0 5,7010 1 TC *+2 ; <013007 5,1007 0 5,7011 0 TC BINROUND ; -0 13010 5,1010 0 2,4474 1 TC ALMCYCLE ; too large a load, alarm and recycle BINROUND EQU * 13011 5,1011 0 5,7014 0 TC _2ROUND 13012 5,1012 0 5,7025 1 TC TESTOFUF 13013 5,1013 0 5,6762 1 TC ENDSCALE ; ************ missing stuff *************** _2ROUND EQU * 13014 5,1014 3 0,0131 1 XCH MPAC+1 13015 5,1015 6 0,0000 1 DOUBLE 13016 5,1016 5 0,0131 1 TS MPAC+1 13017 5,1017 0 0,0001 0 TC Q ; if MPAC+1 does not OF/UF13020 5,1020 6 0,0130 0 AD MPAC 13021 5,1021 5 0,0130 0 TS MPAC 13022 5,1022 0 0,0001 0 TC Q ; if MPAC does not OF/UF13023 5,1023 5 0,0136 0 TS MPAC+6 13024 5,1024 0 0,0001 0 _2RNDEND TC Q TESTOFUF EQU * 13025 5,1025 1 0,0136 1 CCS MPAC+6 ; returns if no OF/UF13026 5,1026 0 2,4474 1 TC ALMCYCLE ; OF, alarm and recycle13027 5,1027 0 0,0001 0 TC Q 13030 5,1030 0 2,4474 1 TC ALMCYCLE ; UF, alarm and recycle BANK40_5 EQU * ORG BANK42_2 BANK42_3 EQU * ORG BANK41_3 INCL bank41_3.asm ; COLOSSUS pp. 349-351 ;========================================================================== ; DISPLAY ROUTINES (file:bank41_3.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 349-351. ;========================================================================== ; MONITOR allows other keyboard activity. It is ended by verb TERMINATE ; verb PROCEED WITHOUT DATA, verb RESEQUENCE, another monitor, or any ; NVSUB call that passes DSPLOCK (provided that the operator has somehow ; allowed the ending of a monitor which he has initiated through the ; keyboard. ; ; MONITOR action is suspended, but not ended, by any keyboard action, ; except error light reset. It begins again when KEY RELEASE is performed. ; MONITOR saves the noun and appropriate display verb in MONSAVE. It saves ; NOUNCADR in MONSAVE1, if noun = machine CADR to be specified. Bit 15 of ; MONSAVE1 is the kill monitor signal (killer bit). Bit 14 of MONSAVE1 ; indicates the current monitor was externally initiated (external monitor ; bit). It is turned off by RELDSP and KILMONON. ; ; MONSAVE indicates if MONITOR is on (+=ON, +0=OFF) ; If MONSAVE is +, monitor enters no request, but turns killer bit off. ; If MONSAVE is +0, monitor enters request and turns killer bit off. ; ; NVSUB (if external monitor bit is off), VB=PROCEED WITHOUT DATA,

Page 524: Apollo Guidance Computer AGC

; VB=RESEQUENCE, and VB=TERMINATE turn kill monitor bit on. ; ; If killer bit is on, MONREQ enters no further requests, zeroes MONSAVE ; and MONSAVE1 (turning off killer bit and external monitor bit). ; ; MONITOR doesn't test for MATBS since NVSUB can handle internal MATBS now. MONITOR EQU * 15146 6,1146 4 6,7155 0 CS BIT15_14 15147 6,1147 7 0,0506 0 MASK NOUNCADR MONIT1 EQU * 15150 6,1150 5 0,0131 1 TS MPAC+1 ; temp storage 15151 6,1151 4 0,0433 1 CS ENTEXIT 15152 6,1152 6 2,4553 0 AD ENDINST 15153 6,1153 1 0,0000 0 CCS A 15154 6,1154 0 6,7164 0 TC MONIT2 15155 6,1155 60000 1 BIT15_14 DS %60000 15156 6,1156 0 6,7164 0 TC MONIT2 15157 6,1157 3 1,2063 0 CAF BIT14 ; externally initiated monitor15160 6,1160 6 0,0131 1 AD MPAC+1 ; was ADS MPAC+1 in Block II15161 6,1161 5 0,0131 1 TS MPAC+1 ; set bit 14 for MONSAVE1 15162 6,1162 3 1,2050 0 CAF ZERO 15163 6,1163 5 0,0511 1 TS MONSAVE2 ; zero NVMONOPT options MONIT2 EQU * 15164 6,1164 3 1,2101 0 CAF LOW7 15165 6,1165 7 0,0470 0 MASK VERBREG 15166 6,1166 0 2,4647 0 TC LEFT5 15167 6,1167 5 0,0022 1 TS CYL 15170 6,1170 4 0,0022 0 CS CYL 15171 6,1171 3 0,0022 1 XCH CYL 15172 6,1172 6 0,0471 0 AD NOUNREG 15173 6,1173 5 0,0130 0 TS MPAC ; temp storage15174 6,1174 3 1,2050 0 CAF ZERO 15175 6,1175 5 0,0501 0 TS DSPLOCK ; +0 into DSPLOCK so monitor can run15176 6,1176 1 0,0531 1 CCS CADRSTOR ; turn off KR lite if CADRSTOR and DSPLIST15177 6,1177 0 6,7201 0 TC *+2 ; are both empty. (Lite comes on if new15200 6,1200 0 2,5026 0 TC RELDSP1 ; monitor is keyed in over old monitor.)15201 6,1201 2 0,0000 0 INHINT 15202 6,1202 1 0,0507 1 CCS MONSAVE 15203 6,1203 0 6,7207 0 TC *+4 ; if MONSAVE was +, no request 15204 6,1204 3 1,2051 1 CAF ONE ; if MONSAVE was 0, request MONREQ15205 6,1205 0 1,2232 0 TC WAITLIST 15206 6,1206 15215 0 CADR MONREQ 15207 6,1207 3 0,0131 1 XCH MPAC+1 ; was DXCH MPAC, DXCH MONSAVE15210 6,1210 3 0,0510 0 XCH MONSAVE+1 15211 6,1211 3 0,0130 0 XCH MPAC ; place monitor verb and noun into MONSAVE15212 6,1212 3 0,0507 0 XCH MONSAVE ; zero the kill monitor bit 15213 6,1213 2 0,0000 1 RELINT ; set up external monitor bit15214 6,1214 0 0,0433 0 TC ENTRET MONREQ EQU * 15215 6,1215 0 6,7300 0 TC LODSAMPT ; called by waitlist (see COLOSSUS p. 374)15216 6,1216 1 0,0510 1 CCS MONSAVE1 ; time is snatched in RUPT for NOUN 6515217 6,1217 0 6,7223 0 TC *+4 ; if killer bit = 0, enter requests15220 6,1220 0 6,7223 0 TC *+3 ; if killer bit = 0, enter requests15221 6,1221 0 6,7232 0 TC KILLMON ; if killer bit = 1, no requests15222 6,1222 0 6,7232 0 TC KILLMON ; if killer bit = 1, no requests 15223 6,1223 3 6,7236 1 CAF MONDEL 15224 6,1224 0 1,2232 0 TC WAITLIST ; enter waitlist request for MONREQ15225 6,1225 15215 0 CADR MONREQ 15226 6,1226 3 2,4131 0 CAF CHRPRIO 15227 6,1227 0 1,3162 1 TC NOVAC ; enter EXEC request for MONDO15230 6,1230 15237 0 CADR MONDO 15231 6,1231 0 1,2413 0 TC TASKOVER KILLMON EQU * 15232 6,1232 3 1,2050 0 CAF ZERO ; zero MONSAVE and turn killer bit off15233 6,1233 5 0,0507 0 TS MONSAVE 15234 6,1234 5 0,0510 0 TS MONSAVE1 ; turn off kill monitor bit15235 6,1235 0 1,2413 0 TC TASKOVER ; turn off external monitor bit 15236 6,1236 00144 0 MONDEL DS %144 ; for 1 sec monitor intervals

Page 525: Apollo Guidance Computer AGC

MONDO EQU * 15237 6,1237 1 0,0510 1 CCS MONSAVE1 ; called by EXEC15240 6,1240 0 6,7244 1 TC *+4 ; if killer bit = 0, continue15241 6,1241 0 6,7244 1 TC *+3 ; if killer bit = 0, continue15242 6,1242 0 1,2723 0 TC ENDOFJOB ; in case TERMINATE came since last MONREQ15243 6,1243 0 1,2723 0 TC ENDOFJOB ; in case TERMINATE came since last MONREQ15244 6,1244 1 0,0501 1 CCS DSPLOCK 15245 6,1245 0 6,7276 0 TC MONBUSY ; NVSUB is busy15246 6,1246 3 1,2101 0 CAF LOW7 15247 6,1247 7 0,0507 1 MASK MONSAVE 15250 6,1250 0 6,6306 1 TC UPDATNN-1 ; place noun into NOUNREG and display it15251 6,1251 3 2,4473 0 CAF MID7 15252 6,1252 7 0,0507 1 MASK MONSAVE ; change monitor verb to display verb15253 6,1253 6 6,7274 1 AD MONREF ; -DEC10, starting in bit5 15254 6,1254 5 0,0020 0 TS CYR ; shift right 7, was TS EDOP, CA EDOP in BII15255 6,1255 4 0,0020 1 CS CYR 15256 6,1256 4 0,0020 1 CS CYR 15257 6,1257 4 0,0020 1 CS CYR 15260 6,1260 4 0,0020 1 CS CYR 15261 6,1261 4 0,0020 1 CS CYR 15262 6,1262 4 0,0020 1 CS CYR 15263 6,1263 3 0,0020 0 XCH CYR 15264 6,1264 7 1,2101 1 MASK LOW7 15265 6,1265 5 0,0470 1 TS VERBREG 15266 6,1266 3 6,7275 0 CAF MONBACK ; set return to PASTEVB after data display15267 6,1267 5 0,0433 0 TS ENTRET 15270 6,1270 4 6,7155 0 CS BIT15_14 15271 6,1271 7 0,0510 1 MASK MONSAVE1 15272 6,1272 5 0,0132 1 TS MPAC+2 ; display it and set NOUNCADR, NOUNADD,15273 6,1273 0 6,6054 0 ENDMONDO TC TESTNN ; EBANK ; COLOSSUS switches to fixed/fixed memory and inserts PASTEVB here-- ; Probably, because their assembler couldn't handle forward references. 15274 6,1274 75377 0 MONREF DS %75377 ; -dec10, starting in bit815275 6,1275 04435 1 MONBACK CADR PASTEVB 15276 6,1276 0 2,4713 0 MONBUSY TC RELDSPON ; turn key release light15277 6,1277 0 1,2723 0 TC ENDOFJOB 15300 6,1300 0 0,0001 0 LODSAMPT TC Q ; ************************** FIX**************************** BANK41_4 EQU * ORG BANKFF_1 INCL bankff_1.asm ; COLOSSUS pp. 351 ;========================================================================== ; DISPLAY ROUTINES (file:bankff_1.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 351. ;========================================================================== PASTEVB EQU * 04435 4435 3 2,4473 0 CAF MID7 04436 4436 7 0,0511 0 MASK MONSAVE2 ; NVMONOPT paste option04437 4437 5 0,0571 1 TS PASTE_TMP 04440 4440 1 0,0000 0 CCS A ; was BZF *+2 in Block II04441 4441 0 2,4443 0 TC *+2 ; >0,04442 4442 0 2,4444 1 TC *+2 ; +0,04443 4443 0 2,4445 0 TC *+2 ; <0,04444 4444 0 2,4447 1 TC *+3 ; -0, 04445 4445 3 0,0571 1 XCH PASTE_TMP 04446 4446 0 2,4451 0 TC PASTEOPT ; paste please verb for NVMONOPT 04447 4447 3 1,2050 0 CAF ZERO ; was CA MONSAVE in BII04450 4450 6 0,0507 0 AD MONSAVE ; paste monitor verb - paste option is 0 PASTEOPT EQU * 04451 4451 5 0,0020 0 TS CYR ; shift right 7, was TS EDOP, CA EDOP in BII04452 4452 4 0,0020 1 CS CYR 04453 4453 4 0,0020 1 CS CYR 04454 4454 4 0,0020 1 CS CYR 04455 4455 4 0,0020 1 CS CYR 04456 4456 4 0,0020 1 CS CYR 04457 4457 4 0,0020 1 CS CYR 04460 4460 3 0,0020 0 XCH CYR 04461 4461 7 1,2101 1 MASK LOW7 ; place monitor verb or please verb into 04462 4462 0 1,3565 1 TC BANKCALL ; VERBREG and display it.04463 4463 14326 0 CADR UPDATVB-1

Page 526: Apollo Guidance Computer AGC

04464 4464 3 1,2050 0 CAF ZERO ; zero REQRET so that pasted verbs can04465 4465 5 0,0502 0 TS REQRET ; be executed by operator. 04466 4466 3 1,2050 0 CAF ZERO 04467 4467 6 0,0511 1 AD MONSAVE2 ; was CA MONSAVE2 in BII04470 4470 0 2,4565 0 TC BLANKSUB ; process NVMONOPT blank option if any (p.368)04471 4471 0 2,4472 1 TC *+1 04472 4472 0 1,2723 0 ENDPASTE TC ENDOFJOB 04473 4473 37600 0 MID7 DS %37600 BANKFF_2 EQU * ORG BANK41_4 INCL bank41_4.asm ; COLOSSUS pp. 352 ;========================================================================== ; DISPLAY ROUTINES (file:bank41_4.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 352. ;========================================================================== ;-------------------------------------------------------------------------- ; DSPFMEM -- DISPLAY FIXED MEMORY ; Used to display (in octal) any fixed register. It is used with NOUN = ; machine CADR to be specified. The FCADR of the desired location is then ; punched in. It handles F/F (FCADR 4000-7777) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.352. ;-------------------------------------------------------------------------- DSPFMEM EQU * 15301 6,1301 3 2,4635 0 CAF R1D1 ; If F/F, DATACALL uses bank 02 or 0315302 6,1302 5 0,0466 0 TS DSPCOUNT 15303 6,1303 3 1,2050 0 CAF ZERO ; was CA NOUNCADR, TC SUPDACAL in Block II15304 6,1304 6 0,0506 1 AD NOUNCADR ; original FCADR loaded still in NOUNCADR15305 6,1305 0 1,3742 0 TC DATACALL ; call with FCADR in A 15306 6,1306 0 6,7310 1 TC DSPOCTWD 15307 6,1307 0 1,2723 0 ENDSPF TC ENDOFJOB BANK41_5 EQU * ORG BANK40_5 ; COLOSSUS pp. 353-355 INCL bank40_5.asm ;========================================================================== ; WORD DISPLAY ROUTINES (file:bank40_5.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 353-355. ;========================================================================== DSPSIGN EQU * 13031 5,1031 3 0,0001 0 XCH Q 13032 5,1032 5 0,0441 0 TS DSPWDRET 13033 5,1033 1 0,0130 1 CCS MPAC 13034 5,1034 0 5,7044 0 TC *+8 ; >0, positive sign13035 5,1035 0 5,7044 0 TC *+7 ; +0, positive sign 13036 5,1036 6 1,2051 1 AD ONE 13037 5,1037 5 0,0130 0 TS MPAC 13040 5,1040 0 5,6353 1 TC M_ON ; display minus sign13041 5,1041 4 0,0131 0 CS MPAC+1 13042 5,1042 5 0,0131 1 TS MPAC+1 13043 5,1043 0 0,0441 0 TC DSPWDRET 13044 5,1044 0 5,6332 0 TC P_ON ; display plus sign 13045 5,1045 0 0,0441 0 TC DSPWDRET ; return ;-------------------------------------------------------------------------- ; DSPRND ; Round up decimal fraction by 5 EXP -6. This was entirely coded in ; Block II instructions, so I translated it to the functional ; equivalent in Block I code. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.353. ;-------------------------------------------------------------------------- DSPRND EQU * 13046 5,1046 3 5,7117 1 CAF DECROUND 13047 5,1047 6 0,0131 1 AD MPAC+1

Page 527: Apollo Guidance Computer AGC

13050 5,1050 5 0,0131 1 TS MPAC+1 ; skip on overflow13051 5,1051 3 1,2050 0 CAF ZERO ; otherwise, make interword carry=013052 5,1052 6 0,0130 0 AD MPAC 13053 5,1053 5 0,0130 0 TS MPAC ; skip on overflow13054 5,1054 0 0,0001 0 TC Q ; return 13055 5,1055 3 5,7063 0 CAF DPOSMAX+1 ; number overflows, so set to max13056 5,1056 5 0,0131 1 TS MPAC+1 13057 5,1057 3 5,7062 1 CAF DPOSMAX 13060 5,1060 5 0,0130 0 TS MPAC 13061 5,1061 0 0,0001 0 TC Q ; return DPOSMAX EQU * ; max positive decimal fraction13062 5,1062 37777 1 DS %37777 13063 5,1063 34000 0 DS %34000 ;-------------------------------------------------------------------------- ; DSPDECTWD -- DISPLAY DECIMAL WORD ; Converts C(MPAC, MPAC+1) into a sign and 5 char decimal starting in loc ; specified in DSPCOUNT. it rounds by 5 exp 6. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.353. ;-------------------------------------------------------------------------- DSPDECWD EQU * 13064 5,1064 3 0,0001 0 XCH Q 13065 5,1065 5 0,0412 0 TS WDRET 13066 5,1066 0 5,7031 1 TC DSPSIGN 13067 5,1067 0 5,7046 1 TC DSPRND 13070 5,1070 3 1,2054 1 CAF FOUR DSPDCWD1 EQU * 13071 5,1071 5 0,0434 1 TS WDCNT 13072 5,1072 3 2,4700 1 CAF BINCON 13073 5,1073 0 2,4353 0 TC SHORTMP TRACE1 EQU * 13074 5,1074 2 0,0130 1 INDEX MPAC 13075 5,1075 3 1,3772 0 CAF RELTAB 13076 5,1076 7 2,4664 0 MASK LOW5 13077 5,1077 5 0,0421 0 TS CODE 13100 5,1100 3 1,2050 0 CAF ZERO 13101 5,1101 3 0,0132 1 XCH MPAC+2 13102 5,1102 3 0,0131 1 XCH MPAC+1 13103 5,1103 5 0,0130 0 TS MPAC 13104 5,1104 3 0,0466 0 XCH DSPCOUNT TRACE1S EQU * 13105 5,1105 5 0,0440 1 TS COUNT 13106 5,1106 1 0,0000 0 CCS A ; decrement DSPCOUNT except at +013107 5,1107 5 0,0466 0 TS DSPCOUNT 13110 5,1110 0 5,7161 0 TC DSPIN 13111 5,1111 1 0,0434 0 CCS WDCNT 13112 5,1112 0 5,7071 0 TC DSPDCWD1 ; >0, not done yet 13113 5,1113 4 2,4675 0 CS VD1 ; +013114 5,1114 5 0,0466 0 TS DSPCOUNT 13115 5,1115 0 0,0412 0 TC WDRET ; return 13116 5,1116 00000 1 DS %00000 13117 5,1117 02476 0 DECROUND DS %02476 ;-------------------------------------------------------------------------- ; DSPDECNR ; Converts C(MPAC, MPAC+1) into a sign and 5 char decimal starting in loc ; specified in DSPCOUNT. It does not round. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.354. ;-------------------------------------------------------------------------- DSPDECNR EQU * 13120 5,1120 3 0,0001 0 XCH Q 13121 5,1121 5 0,0412 0 TS WDRET 13122 5,1122 0 5,7031 1 TC DSPSIGN 13123 5,1123 0 5,7070 1 TC DSPDCWD1-1 ;-------------------------------------------------------------------------- ; DSPDC2NR ; Converts C(MPAC, MPAC+1) into a sign and 2 char decimal starting in loc ; specified by DSPCOUNT. It does not round. ;

Page 528: Apollo Guidance Computer AGC

; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.354. ;-------------------------------------------------------------------------- DSPDC2NR EQU * 13124 5,1124 3 0,0001 0 XCH Q 13125 5,1125 5 0,0412 0 TS WDRET 13126 5,1126 0 5,7031 1 TC DSPSIGN 13127 5,1127 3 1,2051 1 CAF ONE 13130 5,1130 0 5,7071 0 TC DSPDCWD1 ;-------------------------------------------------------------------------- ; DSP2DEC ; Converts C(MPAC) and C(MPAC+1) into a sign and 10 char decimal starting ; in the loc specified in DSPCOUNT. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.354. ;-------------------------------------------------------------------------- DSP2DEC EQU * 13131 5,1131 3 0,0001 0 XCH Q 13132 5,1132 5 0,0412 0 TS WDRET 13133 5,1133 3 1,2050 0 CAF ZERO 13134 5,1134 5 0,0421 0 TS CODE 13135 5,1135 3 1,2053 0 CAF THREE 13136 5,1136 0 5,7253 1 TC _11DSPIN ; -R2 off13137 5,1137 3 1,2054 1 CAF FOUR 13140 5,1140 0 5,7253 1 TC _11DSPIN ; +R2 off13141 5,1141 0 5,7031 1 TC DSPSIGN 13142 5,1142 3 2,4636 0 CAF R2D1 13143 5,1143 0 5,7071 0 END2DEC TC DSPDCWD1 ;-------------------------------------------------------------------------- ; DSPDECVN ; Displays C(A) upon entry as a 2 char decimal beginning in the ; loc specified in DSPCOUNT. ; C(A) should be in form N x 2EXP-14. This is scaled to form N/100 before ; display conversion. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.353. ;-------------------------------------------------------------------------- DSPDECVN EQU * 13144 5,1144 2 0,0000 1 EXTEND 13145 5,1145 4 5,7155 0 MP VNDSPCON ; mult by .01 13146 5,1146 3 0,0003 1 XCH LP ; was LXCH MPAC in Block II13147 5,1147 5 0,0130 0 TS MPAC ; take results from LP (mult by 2EXP14) 13150 5,1150 3 1,2050 0 CAF ZERO 13151 5,1151 5 0,0131 1 TS MPAC+1 13152 5,1152 3 0,0001 0 XCH Q 13153 5,1153 5 0,0412 0 TS WDRET 13154 5,1154 0 5,7127 1 TC DSPDC2NR+3 ; no sign, no round, 2 char 13155 5,1155 00244 0 VNDSPCON DS %00244 ; .01 rounded up GOVNUPDT EQU * 13156 5,1156 0 5,7144 1 TC DSPDECVN ; this is not for general use. Really part13157 5,1157 0 1,3653 1 TC POSTJUMP ; of UPDATVB13160 5,1160 14337 0 DS UPDAT1+2 BANK40_6 EQU * ORG BANK41_5 ; COLOSSUS pp. 355-356 INCL bank41_5.asm ;========================================================================== ; DISPLAY ROUTINES (file:bank41_5.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 355-356. ;========================================================================== ;-------------------------------------------------------------------------- ; DSPOCTWD -- DISPLAY OCTAL WORD ; Displays C(A) upon entry as a 5 char octal starting in the DSP char ; specified in DSPCOUNT. It stops after 5 char have been displayed. ; ; ; DSP2BIT -- DISPLAY 2 OCTAL CHARS ; Displays C(A) upon entry as a 2 char oct beginning in the DSP ; loc specified in DSPCOUNT by pre-cycling right C(A) and using ; the logic of the 5 char octal display. ;

Page 529: Apollo Guidance Computer AGC

; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.355/356. ;-------------------------------------------------------------------------- DSPOCTWD EQU * 15310 6,1310 5 0,0022 1 TS CYL 15311 6,1311 3 0,0001 0 XCH Q 15312 6,1312 5 0,0412 0 TS WDRET ; must use the same return as DSP2BIT 15313 6,1313 3 1,2063 0 CAF BIT14 ; to blank signs15314 6,1314 6 0,0466 0 AD DSPCOUNT ; was ADS DSPCOUNT in block II15315 6,1315 5 0,0466 0 TS DSPCOUNT 15316 6,1316 3 1,2054 1 CAF FOUR WDAGAIN EQU * 15317 6,1317 5 0,0434 1 TS WDCNT 15320 6,1320 4 0,0022 0 CS CYL 15321 6,1321 4 0,0022 0 CS CYL 15322 6,1322 4 0,0022 0 CS CYL 15323 6,1323 4 0,0000 0 CS A 15324 6,1324 7 1,2057 0 MASK DSPMSK 15325 6,1325 2 0,0000 0 INDEX A 15326 6,1326 3 1,3772 0 CAF RELTAB 15327 6,1327 7 2,4664 0 MASK LOW5 15330 6,1330 5 0,0421 0 TS CODE 15331 6,1331 3 0,0466 0 XCH DSPCOUNT 15332 6,1332 5 0,0440 1 TS COUNT 15333 6,1333 1 0,0000 0 CCS A ; decrement DSPCOUNT except at +015334 6,1334 5 0,0466 0 TS DSPCOUNT ; > 015335 6,1335 0 1,3653 1 TC POSTJUMP ; + 015336 6,1336 13261 0 DS DSPOCTIN OCTBACK EQU * 15337 6,1337 1 0,0434 0 CCS WDCNT 15340 6,1340 0 6,7317 0 TC WDAGAIN DSPLW EQU * 15341 6,1341 4 2,4675 0 CS VD1 ; to block numerical characters, clears15342 6,1342 5 0,0466 0 TS DSPCOUNT 15343 6,1343 0 0,0412 0 TC WDRET ; * return DSPMSK EQU SEVEN DSP2BIT EQU * 15344 6,1344 5 0,0020 0 TS CYR 15345 6,1345 3 0,0001 0 XCH Q 15346 6,1346 5 0,0412 0 TS WDRET 15347 6,1347 3 1,2051 1 CAF ONE 15350 6,1350 5 0,0434 1 TS WDCNT 15351 6,1351 4 0,0020 1 CS CYR 15352 6,1352 4 0,0020 1 CS CYR 15353 6,1353 3 0,0020 0 XCH CYR 15354 6,1354 5 0,0022 1 TS CYL 15355 6,1355 0 6,7324 0 TC WDAGAIN+5 BANK41_6 EQU * ORG BANK40_6 ; COLOSSUS pp. 356-358 INCL bank40_6.asm ;========================================================================== ; DISPLAY ROUTINES (file:bank40_6.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 356-358. ;========================================================================== ;-------------------------------------------------------------------------- ; DSPIN -- DISPLAY RELAY CODE ; ; For DSPIN, place 0-25 oct into COUNT to select the character (same as DSPCOUNT), ; 5 bit relay code into CODE. Both are destroyed. If bit 14 of COUNT is 1, sign is ; blanked with left char. ; For DSPIN11, place 0,1 into CODE, 2 into COUNT, rel address of DSPTAB entry ; into DSREL. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.356. ;-------------------------------------------------------------------------- DSPIN EQU * 13161 5,1161 3 0,0001 0 XCH Q ; cant use L for RETURN, since many of the13162 5,1162 5 0,0411 0 TS DSEXIT ; routines calling DSPIN use L as RETURN

Page 530: Apollo Guidance Computer AGC

; Set DSREL to index into DSPTAB; the index corresponds to the display character ; referenced by COUNT (which is derived from DSPCOUNT) 13163 5,1163 3 2,4664 1 CAF LOW5 13164 5,1164 7 0,0440 0 MASK COUNT 13165 5,1165 5 0,0021 1 TS SR ; divides by 213166 5,1166 3 0,0021 1 XCH SR 13167 5,1167 5 0,0436 0 TS DSREL ; Check COUNT (derived from DSPCOUNT) to find whether the character to be ; displayed is in the right (Bits 5-1) or left (Bits 10-6) bits of the ; DSPTAB word. 13170 5,1170 3 1,2100 1 CAF BIT1 13171 5,1171 7 0,0440 0 MASK COUNT 13172 5,1172 1 0,0000 0 CCS A 13173 5,1173 0 5,7175 0 TC *+2 ; >0, left if COUNT is odd13174 5,1174 0 5,7205 1 TC DSPIN1-1 ; +0, right if COUNT is even ; Character to be displayed should be in the left bits (Bit 10-6), so ; shift it left into bits 10-6. 13175 5,1175 3 0,0421 0 XCH CODE 13176 5,1176 0 2,4656 0 TC SLEFT5 ; does not use CYL13177 5,1177 5 0,0421 0 TS CODE ; Set COUNT as an enumerated type; tells how to mask the new character ; into the relay word. ; 0 = mask new character into right side of relayword (bits 5-1) ; 1 = mask into left side (bits 10-6) and leave old sign (bit 11) alone. ; 2 = mask into left side (bits 10-6) and blank sign bit (bit 11) 13200 5,1200 3 1,2063 0 CAF BIT14 13201 5,1201 7 0,0440 0 MASK COUNT 13202 5,1202 1 0,0000 0 CCS A 13203 5,1203 3 1,2052 1 CAF TWO ; >0, BIT14 = 1, blank sign13204 5,1204 6 1,2051 1 AD ONE ; +0, BIT14 = 0, leave sign alone 13205 5,1205 5 0,0440 1 TS COUNT ; New display character in CODE has been bit-shifted into the correct (left ; or right) bit position. All other bits are zeroed. DSPIN1 EQU * 13206 5,1206 2 0,0000 0 INHINT ; Get the existing display word from DSPTAB. Words that have already been ; displayed will be positive; words yet to be displayed will be negative. ; Use CCS to load the absolute value of the display word. Since CCS decrements ; it, we need to add 1 to restore the value. 13207 5,1207 2 0,0436 1 INDEX DSREL 13210 5,1210 1 0,0512 0 CCS DSPTAB 13211 5,1211 0 5,7213 0 TC *+2 ; >0, old word already displayed13212 5,1212 0 5,7245 0 TC DSLV ; +0, illegal DSPCOUNT (was TC CCSHOLE)13213 5,1213 6 1,2051 1 AD ONE ; <0, old word not displayed yet 13214 5,1214 5 0,0437 1 TS DSMAG ; store the old relay word ; Now, mask off the portion of the old relay word corresponding to the ; new character. Subtract the new character from the old to see whether ; they are the same. 13215 5,1215 2 0,0440 0 INDEX COUNT 13216 5,1216 7 5,7247 0 MASK DSMSK ; mask with 00037, 01740, 02000, or 0374013217 5,1217 2 0,0000 1 EXTEND 13220 5,1220 6 0,0421 0 SU CODE ; Old code same as new code? If so, we don't need to redisplay it. 13221 5,1221 1 0,0000 0 CCS A ; was BZF DSLV in Block II13222 5,1222 0 5,7226 0 TC DFRNT ; >013223 5,1223 0 5,7245 0 TC DSLV ; +0, same, so return13224 5,1224 0 5,7226 0 TC DFRNT ; <013225 5,1225 0 5,7245 0 TC DSLV ; -0, same, so return ; New code is different. DFRNT EQU * ; different13226 5,1226 2 0,0440 0 INDEX COUNT 13227 5,1227 4 5,7247 0 CS DSMSK ; mask with 77740, 76037, 75777, or 7403713230 5,1230 7 0,0437 0 MASK DSMAG 13231 5,1231 6 0,0421 0 AD CODE ; Store new DSPTAB word and get the old (previous) word. If the old word is ; negative, it had not been displayed yet, so NOUT (the count of undisplayed

Page 531: Apollo Guidance Computer AGC

; words) has already been incremented for this DSPTAB word. If the old word ; is positive, it has already been displayed, so we need to increment NOUT ; to tell DSPOUT to display the new word. 13232 5,1232 4 0,0000 0 CS A 13233 5,1233 2 0,0436 1 INDEX DSREL 13234 5,1234 3 0,0512 1 XCH DSPTAB 13235 5,1235 1 0,0000 0 CCS A ; was BZMF DSLV in Block II13236 5,1236 0 5,7242 1 TC *+4 ; >013237 5,1237 0 5,7241 1 TC *+2 ; +0, DSPTAB entry was -13240 5,1240 0 5,7241 1 TC *+1 ; <0, DSPTAB entry was -13241 5,1241 0 5,7245 0 TC DSLV ; -0, DSPTAB entry was - 13242 5,1242 3 0,0505 1 XCH NOUT ; DSPTAB entry was + (was INCR NOUT in BlockII)13243 5,1243 6 1,2051 1 AD ONE 13244 5,1244 5 0,0505 1 TS NOUT 13245 5,1245 2 0,0000 1 DSLV RELINT 13246 5,1246 0 0,0411 0 TC DSEXIT ; return DSMSK EQU * 13247 5,1247 00037 0 DS %00037 ; COUNT=013250 5,1250 01740 0 DS %01740 ; COUNT=113251 5,1251 02000 0 DS %02000 ; COUNT=213252 5,1252 03740 1 DS %03740 ; COUNT=3 ; For 11DSPIN, put rel address of DSPTAB entry into A, 1 in BIT11 or 0 in ; BIT11 of CODE. I changed the name to _11DSPIN because my assembler doesn't ; like labels that start with a digit. _11DSPIN EQU * 13253 5,1253 5 0,0436 0 TS DSREL 13254 5,1254 3 1,2052 1 CAF TWO 13255 5,1255 5 0,0440 1 TS COUNT 13256 5,1256 3 0,0001 0 XCH Q ; must use same return as DSPIN13257 5,1257 5 0,0411 0 TS DSEXIT 13260 5,1260 0 5,7206 1 TC DSPIN1 DSPOCTIN EQU * 13261 5,1261 0 5,7161 0 TC DSPIN ; so DSPOCTWD doesn't use SWCALL13262 5,1262 3 5,7264 0 CAF *+2 13263 5,1263 0 1,3712 0 TC BANKJUMP 13264 5,1264 15337 1 ENDSPOCT DS OCTBACK ; DSPALARM finds TC NVSUBEND in ENTRET for NVSUB initiated routines. ; Abort with 01501. ; DSPALARM finds TC ENDOFJOB in ENTRET for keyboard initiated routines. ; do TC ENTRET. PREDSPAL EQU * 13265 5,1265 4 2,4675 0 CS VD1 13266 5,1266 5 0,0466 0 TS DSPCOUNT DSPALARM EQU * 13267 5,1267 4 5,7314 1 CS NVSBENDL 13270 5,1270 6 0,0433 0 AD ENTEXIT 13271 5,1271 1 0,0000 0 CCS A ; was BZF CHARALRM+2 in Block II13272 5,1272 0 5,7276 0 TC *+4 ; >013273 5,1273 0 5,7275 0 TC *+2 ; +013274 5,1274 0 5,7276 0 TC *+2 ; <013275 5,1275 0 5,7311 0 TC CHARALRM+2 ; -0 13276 5,1276 4 5,7313 0 CS MONADR ; if this is a monitor, kill it13277 5,1277 6 0,0433 0 AD ENTEXIT 13300 5,1300 1 0,0000 0 CCS A ; was BZF *+2 in Block II13301 5,1301 0 5,7305 0 TC *+4 ; >013302 5,1302 0 5,7304 1 TC *+2 ; +013303 5,1303 0 5,7305 0 TC *+2 ; <013304 5,1304 0 5,7306 0 TC *+2 ; -0 13305 5,1305 0 5,7307 1 TC *+2 13306 5,1306 0 2,4536 0 TC KILMONON CHARALRM EQU * 13307 5,1307 0 2,4701 0 TC FALTON ; not NVSUB initiated, turn on OPR error13310 5,1310 0 1,2723 0 TC ENDOFJOB 13311 5,1311 0 2,5050 1 TC POODOO 13312 5,1312 01501 1 DS %01501 13313 5,1313 04435 1 MONADR DS PASTEVB 13314 5,1314 0 2,4532 1 NVSBENDL TC NVSUBEND

Page 532: Apollo Guidance Computer AGC

BANK40_7 EQU * ORG BANKFF_2 ; COLOSSUS pp. 358 INCL bankff_2.asm ;========================================================================== ; DISPLAY ROUTINES (file:bankff_2.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 358. ;========================================================================== ;-------------------------------------------------------------------------- ; ALMCYCLE ; Turns on check fail light, redisplays the original verb that was executed, ; and recycles to execute the original verb/noun combination that was last ; executed. Used for bad data during load verbs and by MCTBS. Also by MMCHANG ; if 2 numerical chars were not punched in for MM code. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.358. ;-------------------------------------------------------------------------- ALMCYCLE EQU * 04474 4474 0 2,4701 0 TC FALTON ; turn on check fail light04475 4475 4 0,0530 0 CS VERBSAVE ; get original verb that was executed04476 4476 5 0,0502 0 TS REQRET ; set for ENTPAS004477 4477 0 1,3565 1 TC BANKCALL ; puts original verb into VERBREG and04500 4500 14326 0 DS UPDATVB-1 ; displays it in verb lights04501 4501 0 1,3653 1 TC POSTJUMP 04502 4502 14002 0 ENDALM DS ENTER BANKFF_3 EQU * ORG BANK41_6 ; COLOSSUS pp. 359-360 INCL bank41_6.asm ;========================================================================== ; DISPLAY ROUTINES (file:bank41_6.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 359-360. ;========================================================================== ;-------------------------------------------------------------------------- ; MMCHANG -- MAJOR MODE CHANGE ; Uses noun display until ENTER; then it uses MODE display. It goes to ; MODROUT with the new MM code in A, but not displayed in MM lights. ; It demands 2 numerical characters be punched in for new MM code. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.359. ;-------------------------------------------------------------------------- MMCHANG EQU * 15356 6,1356 0 6,7404 0 TC REQMM ; ENTPASHI assumes the TC GRQMM at MMCHANG ; if this moves at all, must change ; MMADREF at ENTPASHI15357 6,1357 3 1,2074 0 CAF BIT5 ; OCT 20 = ND215360 6,1360 6 0,0466 0 AD DSPCOUNT ; DSPCOUNT must = -ND2 15361 6,1361 1 0,0000 0 CCS A ; was BZF *+2 in Block II15362 6,1362 0 6,7366 0 TC *+4 ; >015363 6,1363 0 6,7365 0 TC *+2 ; +015364 6,1364 0 6,7366 0 TC *+2 ; <015365 6,1365 0 6,7367 1 TC *+2 ; -0 15366 6,1366 0 2,4474 1 TC ALMCYCLE ; DSPCOUNT not -ND2. Alarm and recycle. 15367 6,1367 3 1,2050 0 CAF ZERO 15370 6,1370 3 0,0471 0 XCH NOUNREG 15371 6,1371 5 0,0130 0 TS MPAC 15372 6,1372 3 2,4676 1 CAF ND1 15373 6,1373 5 0,0466 0 TS DSPCOUNT 15374 6,1374 0 1,3565 1 TC BANKCALL 15375 6,1375 12540 0 DS _2BLANK 15376 6,1376 4 2,4675 0 CS VD1 ; block num char in15377 6,1377 5 0,0466 0 TS DSPCOUNT 15400 6,1400 3 1,2050 0 CAF ZERO ; was CA MPAC in Block II15401 6,1401 6 0,0130 0 AD MPAC 15402 6,1402 0 1,3653 1 TC POSTJUMP 15403 6,1403 10000 0 DS MODROUTR ; go thru standard loc. MODROUTR EQU V37

Page 533: Apollo Guidance Computer AGC

REQMM EQU * 15404 6,1404 4 0,0001 1 CS Q 15405 6,1405 5 0,0502 0 TS REQRET 15406 6,1406 3 2,4676 1 CAF ND1 15407 6,1407 5 0,0466 0 TS DSPCOUNT 15410 6,1410 3 1,2050 0 CAF ZERO 15411 6,1411 5 0,0471 0 TS NOUNREG 15412 6,1412 0 1,3565 1 TC BANKCALL 15413 6,1413 12540 0 DS _2BLANK 15414 6,1414 0 2,4760 1 TC FLASHON 15415 6,1415 3 1,2051 1 CAF ONE 15416 6,1416 5 0,0467 1 TS DECBRNCH ; set for dec15417 6,1417 0 0,0433 0 TC ENTEXIT ;-------------------------------------------------------------------------- ; VBRQEXEC -- REQUEST EXECUTIVE ; ; Enters request to EXEC for any address with any priority. It does ENDOFJOB ; after entering request. Display syst is released. It assumes NOUN 26 has been ; preloaded with: ; COMPONENT 1 -- priority (bits 10-14), bit1=0 for NOVAC, bit1=1 for FINDVAC ; COMPONENT 2 -- job CADR (14 bit; was 12 bit in Block II) ; COMPONENT 3 -- not used (was BBCON in Block II) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.360. ;-------------------------------------------------------------------------- VBRQEXEC EQU * 15420 6,1420 3 1,2100 1 CAF BIT1 15421 6,1421 7 0,0534 1 MASK DSPTEM1 15422 6,1422 1 0,0000 0 CCS A 15423 6,1423 0 6,7444 1 TC SETVAC ; if bit1=1, FINDVAC15424 6,1424 3 2,4667 1 CAF TCNOVAC ; if bit1=0, NOVAC ; sets up to call NOVAC or FINDVAC thru MPAC as follows: ; MPAC = TC NOVAC ; MPAC+1 = job CADR ; MPAC+2 = TC ENDOFJOB ; MPAC+3 = temp store for job PRIO REQEX1 EQU * 15425 6,1425 5 0,0130 0 TS MPAC ; TC NOVAC or TC FINDVAC into MPAC15426 6,1426 4 1,2100 0 CS BIT1 15427 6,1427 7 0,0534 1 MASK DSPTEM1 15430 6,1430 5 0,0133 0 TS MPAC+3 ; PRIO into MPAC+3 as a temp (was +4) REQUESTC EQU * 15431 6,1431 0 2,5003 1 TC RELDSP 15432 6,1432 3 1,2050 0 CAF ZERO ; was CA ENDINST in Block II15433 6,1433 6 2,4553 0 AD ENDINST 15434 6,1434 5 0,0132 1 TS MPAC+2 ; TC ENDOFJOB into MPAC+2 (was +3) 15435 6,1435 3 1,2050 0 CAF ZERO ; set BBCON for Block II dropped15436 6,1436 6 0,0535 1 AD DSPTEM1+1 ; job adres into MPAC+115437 6,1437 5 0,0131 1 TS MPAC+1 15440 6,1440 3 1,2050 0 CAF ZERO ; was CA MPAC+4 in Block II15441 6,1441 6 0,0133 0 AD MPAC+3 ; PRIO in A15442 6,1442 2 0,0000 0 INHINT 15443 6,1443 0 0,0130 0 TC MPAC SETVAC EQU * 15444 6,1444 3 2,4671 0 CAF TCFINDVAC 15445 6,1445 0 6,7425 0 TC REQEX1 ;-------------------------------------------------------------------------- ; VBRQWAIT -- REQUEST WAITLIST ; ; Enters request to WAITLIST for any address with any delay. It does ENDOFJOB ; after entering request. Display syst is released. It assumes NOUN 26 has been ; preloaded with: ; COMPONENT 1 -- delay (low bits) ; COMPONENT 2 -- task CADR (14 bit; was 12 bit in Block II) ; COMPONENT 3 -- not used (was BBCON in Block II) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.360. ;-------------------------------------------------------------------------- VBRQWAIT EQU * 15446 6,1446 3 2,4670 1 CAF TCWAIT 15447 6,1447 5 0,0130 0 TS MPAC ; TC WAITLIST into MPAC

Page 534: Apollo Guidance Computer AGC

15450 6,1450 3 1,2050 0 CAF ZERO ; was CA DSPTEM1 in Block II15451 6,1451 6 0,0534 0 AD DSPTEM1 ; time delay15452 6,1452 0 6,7430 1 ENDRQWT TC REQUESTC-1 ; REQUESTC will put task address in MPAC+1, TC ENDOFJOB in MPAC+2. ; It will take the time delay out of MPAC+3 and leave it in A, INHINT ; and TC MPAC. BANK41_7 EQU * ORG BANK40_7 ; COLOSSUS pp. 360-362 INCL bank40_7.asm ;========================================================================== ; DISPLAY ROUTINES (file:bank40_7.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 360-362. ;========================================================================== ;-------------------------------------------------------------------------- ; VBPROC -- PROCEED WITHOUT DATA ; VBTERM -- TERMINATE ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.360. ;-------------------------------------------------------------------------- VBPROC EQU * 13315 5,1315 3 1,2051 1 CAF ONE ; proceed without data13316 5,1316 5 0,0503 1 TS LOADSTAT 13317 5,1317 0 2,4536 0 TC KILMONON ; turn on kill monitor bit13320 5,1320 0 2,5003 1 TC RELDSP 13321 5,1321 0 2,4770 0 TC FLASHOFF 13322 5,1322 0 5,7413 0 TC RECALTST ; see if there is any recall from endidle VBTERM EQU * 13323 5,1323 4 1,2051 0 CS ONE 13324 5,1324 0 5,7316 1 TC VBPROC+1 ; term verb sets loadstat neg ;-------------------------------------------------------------------------- ; VBRESEQ ; Wakes ENDIDLE at same line as final enter of load (L+3). Main use is ; intended as response to internally initiated flashing displays in ENDIDLE. ; Should not be used with load verbs, please perform, or please mark verbs ; because they already use L+3 in another context. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.361. ;-------------------------------------------------------------------------- VBRESEQ EQU * 13325 5,1325 4 1,2050 1 CS ZERO ; make it look like data in.13326 5,1326 0 5,7316 1 TC VBPROC+1 ; flash is turned off by proceed without data, terminate, ; resequence, end of load. ;-------------------------------------------------------------------------- ; VBRELDSP ; This routine always turns off the UPACT light and always clears ; DSPLOCK. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.362. ;-------------------------------------------------------------------------- VBRELDSP EQU * ; some code here to turn off the UPACT light is omitted 13327 5,1327 1 0,0412 1 CCS _2122REG ; old DSPLOCK13330 5,1330 3 1,2063 0 CAF BIT14 13331 5,1331 7 0,0510 1 MASK MONSAVE1 ; external monitor bit (EMB)13332 5,1332 1 0,0000 0 CCS A 13333 5,1333 0 5,7342 0 TC UNSUSPEN ; old DSPLOCK and EMB both 1, unsuspend 13334 5,1334 0 2,5003 1 TSTLTS4 TC RELDSP ; not unsuspending external monitor,13335 5,1335 1 0,0531 1 CCS CADRSTOR ; release display system and13336 5,1336 0 5,7340 1 TC *+2 ; do reestablish if CADRSTOR is full13337 5,1337 0 1,2723 0 TC ENDOFJOB 13340 5,1340 0 1,3653 1 TC POSTJUMP 13341 5,1341 05067 0 CADR PINBRNCH UNSUSPEN EQU * 13342 5,1342 3 1,2050 0 CAF ZERO ; external monitor is suspended13343 5,1343 5 0,0501 0 TS DSPLOCK ; just unsuspend it by clearing DSPLOCK

Page 535: Apollo Guidance Computer AGC

13344 5,1344 1 0,0531 1 CCS CADRSTOR ; turn key release light off if both13345 5,1345 0 1,2723 0 TC ENDOFJOB ; CADRSTOR and DSPLIST are empty13346 5,1346 0 2,5026 0 TC RELDSP1 13347 5,1347 0 1,2723 0 TC ENDOFJOB BANK40_8 EQU * ORG BANKFF_3 ; COLOSSUS pp. 363-364 INCL bankff_3.asm ;========================================================================== ; DISPLAY ROUTINES (file:bankff_3.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 363-364. ;========================================================================== ; COLOSSUS p. 364 - comments are taken from the Block I flow charts with some ; additional annotations by me. NVSUB EQU * 04503 4503 5 0,0565 1 TS NVSUB_A ; more gymnastics for Block II conversion 04504 4504 3 1,2050 0 CAF ZERO ; was LXCH 7 in Block II04505 4505 5 0,0564 0 TS NVSUB_L ; zero NVMONOPT options ; save C(A). C(A) should be holding the noun/verb code; C(L) should ; be holding NVMONOPT options. In this Block I version, the NVMONOPT ; options should be placed in NVSUB_L before calling NVMONOPT. 04506 4506 3 0,0565 1 XCH NVSUB_A NVMONOPT EQU * 04507 4507 5 0,0420 1 TS NVTEMP ; Test DSPLOCK (+NZ=busy; +0=display system available) ; Display is blocked by DSPLOCK=1 or external monitor bit set (bit 14) 04510 4510 3 1,2063 0 CAF BIT14 04511 4511 7 0,0510 1 MASK MONSAVE1 ; external monitor bit04512 4512 6 0,0501 0 AD DSPLOCK 04513 4513 1 0,0000 0 CCS A 04514 4514 0 0,0001 0 TC Q ; dsp syst blocked, ret to 1, calling loc ; Store calling line +2 in NVQTEM 04515 4515 3 1,2051 1 CAF ONE ; dsp syst available04516 4516 6 0,0001 0 NVSBCOM AD Q 04517 4517 5 0,0526 0 TS NVQTEM ; 2+calling loc into NVQTEM ; Force bit 15 of MONSAVE to 1, turn off bit 14. 04520 4520 3 0,0564 0 XCH NVSUB_L ; was LXCH MONSAVE2 in Block II04521 4521 3 0,0511 1 XCH MONSAVE2 ; store NVMONOPT options04522 4522 5 0,0564 0 TS NVSUB_L ; replaces LXCH by working through A instead 04523 4523 0 2,4536 0 TC KILMONON ; turn on kill monitor bit ; Store calling bank in NVBNKTEM ; ** this was changed quite a bit from Block II ** NVSUBCOM EQU * 04524 4524 3 1,2050 0 CAF ZERO 04525 4525 6 0,0015 0 AD BANK 04526 4526 5 0,0527 1 TS NVBNKTEM 04527 4527 0 1,3624 1 TC MYBANKCALL ; go to NVSUB1 thru standard loc04530 4530 14000 1 CADR NVSUBR 04531 4531 15505 0 NVSRRBNK CADR NVSUB1 ; ****** WHAT'S THIS FOR?? ******** ; Restore calling bank and TC NVQTEM ; ** this was changed quite a bit from Block II ** NVSUBEND EQU * 04532 4532 3 1,2050 0 CAF ZERO 04533 4533 6 0,0527 1 AD NVBNKTEM 04534 4534 5 0,0015 0 TS BANK ; restore calling bank04535 4535 0 0,0526 0 TC NVQTEM BANKFF_4 EQU * ORG BANK41_7 ; COLOSSUS pp. 365-366 INCL bank41_7.asm ;==========================================================================

Page 536: Apollo Guidance Computer AGC

; DISPLAY ROUTINES (file:bank41_7.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 365-366. ;========================================================================== ; BLANKDSP blanks display according to option number in NVTEMP as follows: ; -4 full blank, -3 leave mode, -2 leave mode and verb, -1 blank R-S only BLANKDSP EQU * 15453 6,1453 6 1,2057 1 AD SEVEN ; 7,8,9,or 10 (A had 0,1,2,or 3)15454 6,1454 2 0,0000 0 INHINT 15455 6,1455 5 0,0421 0 TS CODE ; blank specified DSPTABS15456 6,1456 4 1,2065 1 CS BIT12 15457 6,1457 2 0,0421 1 INDEX CODE 15460 6,1460 3 0,0512 1 XCH DSPTAB 15461 6,1461 1 0,0000 0 CCS A 15462 6,1462 0 6,7501 1 TC INCR_NOUT ; was INCR NOUT in Block II15463 6,1463 0 6,7464 0 INCR_NOUT_RET TC *+1 15464 6,1464 1 0,0421 1 CCS CODE 15465 6,1465 0 6,7455 1 TC BLANKDSP+2 15466 6,1466 2 0,0000 1 RELINT 15467 6,1467 2 0,0420 0 INDEX NVTEMP 15470 6,1470 0 6,7475 0 TC *+5 15471 6,1471 0 6,7472 1 TC *+1 ; NVTEMP has -4 (never touch MODREG)15472 6,1472 5 0,0470 1 TS VERBREG ; -315473 6,1473 5 0,0471 0 TS NOUNREG ; -215474 6,1474 5 0,0504 0 TS CLPASS ; -1 15475 6,1475 4 2,4675 0 CS VD1 15476 6,1476 5 0,0466 0 TS DSPCOUNT 15477 6,1477 0 2,4770 0 TC FLASHOFF ; protect against invisible flash15500 6,1500 0 6,7540 1 TC ENTSET-2 ; zeroes REQRET INCR_NOUT EQU * 15501 6,1501 3 0,0505 1 XCH NOUT ; was INCR NOUT in Block II15502 6,1502 6 1,2051 1 AD ONE ; have to make it a separate routine15503 6,1503 5 0,0505 1 TS NOUT ; because it was nested inside15504 6,1504 0 6,7463 1 TC INCR_NOUT_RET ; a CCS. NVSUB1 EQU * 15505 6,1505 3 6,7542 0 CAF ENTSET ; in bank15506 6,1506 5 0,0433 0 TS ENTRET ; set return to NVSUBEND 15507 6,1507 1 0,0420 0 CCS NVTEMP ; what now15510 6,1510 0 6,7514 0 TC *+4 ; normal NVSUB call (execute VN or paste)15511 6,1511 0 6,6341 1 TC GODSPALM 15512 6,1512 0 6,7453 1 TC BLANKDSP ; blank display as specified15513 6,1513 0 6,6341 1 TC GODSPALM 15514 6,1514 3 1,2101 0 CAF LOW7 15515 6,1515 7 0,0420 0 MASK NVTEMP 15516 6,1516 5 0,0133 0 TS MPAC+3 ; temp for noun (can't use MPAC, DSPDECVN ; uses MPAC, +1, +215517 6,1517 3 1,2050 0 CAF ZERO ; was CA NVTEMP15520 6,1520 6 0,0420 1 AD NVTEMP 15521 6,1521 5 0,0020 0 TS CYR ; shift right 7, was TS EDOP, CA EDOP in BII15522 6,1522 4 0,0020 1 CS CYR 15523 6,1523 4 0,0020 1 CS CYR 15524 6,1524 4 0,0020 1 CS CYR 15525 6,1525 4 0,0020 1 CS CYR 15526 6,1526 4 0,0020 1 CS CYR 15527 6,1527 4 0,0020 1 CS CYR 15530 6,1530 3 0,0020 0 XCH CYR 15531 6,1531 7 1,2101 1 MASK LOW7 15532 6,1532 5 0,0134 1 TS MPAC+4 ; temp for verb (can't use MPAC, DSPDECVN ; uses MPAC, +1, +2 15533 6,1533 1 0,0133 1 CCS MPAC+3 ; test noun (+NZ or +0)15534 6,1534 0 6,7543 1 TC NVSUB2 ; if noun not +0, DC on 15535 6,1535 3 1,2050 0 CAF ZERO ; was CA MPAC+4 in Block II15536 6,1536 6 0,0134 1 AD MPAC+4 15537 6,1537 0 6,6326 0 TC UPDATVB-1 ; if noun = +0, display verb then return 15540 6,1540 3 1,2050 0 CAF ZERO ; zero REQRET so that pasted verbs can15541 6,1541 5 0,0502 0 TS REQRET ; be executed by operator 15542 6,1542 0 2,4532 1 ENTSET TC NVSUBEND

Page 537: Apollo Guidance Computer AGC

15543 6,1543 1 0,0134 0 NVSUB2 CCS MPAC+4 ; test verb (+NZ or +0)15544 6,1544 0 6,7551 1 TC *+5 ; if verb not +0, go on 15545 6,1545 3 1,2050 0 CAF ZERO ; was CA MPAC+3 in Block II15546 6,1546 6 0,0133 0 AD MPAC+3 15547 6,1547 0 6,6306 1 TC UPDATNN-1 ; if verb = +0, display noun, then return15550 6,1550 0 2,4532 1 TC NVSUBEND 15551 6,1551 3 1,2050 0 CAF ZERO ; was CA MPAC+2 in Block II15552 6,1552 6 0,0132 1 AD MPAC+2 ; temp for mach CADR to be spec, (DSPDECVN15553 6,1553 5 0,0135 0 TS MPAC+5 ; uses MPAC, +1, +2 15554 6,1554 3 1,2050 0 CAF ZERO ; was CA MPAC+4 in Block II15555 6,1555 6 0,0134 1 AD MPAC+4 15556 6,1556 0 6,6326 0 TC UPDATVB-1 ; if both noun and verb not +0, display 15557 6,1557 3 1,2050 0 CAF ZERO ; was CA MPAC+3 in Block II15560 6,1560 6 0,0133 0 AD MPAC+3 ; both and go to ENTPAS015561 6,1561 0 6,6306 1 TC UPDATNN-1 15562 6,1562 3 1,2050 0 CAF ZERO 15563 6,1563 5 0,0503 1 TS LOADSTAT ; set for waiting for data condition15564 6,1564 5 0,0504 0 TS CLPASS 15565 6,1565 5 0,0502 0 TS REQRET ; set request for pass 0 15566 6,1566 3 1,2050 0 CAF ZERO ; was CA MPAC+5 in Block II15567 6,1567 6 0,0135 0 AD MPAC+5 ; restores mach CADR to be spec to MPAC+215570 6,1570 5 0,0132 1 TS MPAC+2 ; for use in INTMCTBS (in ENTPAS0) 15571 6,1571 0 6,6040 0 ENDNVSB1 TC ENTPAS0 ; if internal mach CADR to be specified, MPAC+2 will be placed into ; NOUNCADR in ENTPAS0 (INTMCTBS) BANK41_8 EQU * ORG BANKFF_4 ; COLOSSUS pp. 366-368 INCL bankff_4.asm ;========================================================================== ; DISPLAY ROUTINES (file:bankff_4.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 366-368. ;========================================================================== KILMONON EQU * ; force bit 15 of MONSAVE1 to 1.04536 4536 3 1,2062 1 CAF BIT15 ; this is the kill monitor bit.04537 4537 5 0,0510 0 TS MONSAVE1 ; turn off bit 14, the external04540 4540 0 0,0001 0 TC Q ; monitor bit. ; COLOSSUS p. 367 ENDIDLE EQU * 04541 4541 3 0,0001 0 XCH Q ; was LXCH Q in Block II04542 4542 5 0,0566 1 TS ENDIDLE_L ; return address into L 04543 4543 0 2,4554 1 TC ISCADR_P0 ; abort if CADRSTOR not= +004544 4544 0 2,4560 0 TC ISLIST_P0 ; abort if DSPLIST not= +0 04545 4545 3 1,2050 0 CAF ZERO ; was CA L in Block II04546 4546 6 0,0566 1 AD ENDIDLE_L ; don't set DSPLOCK to 1 so can use04547 4547 7 2,4674 1 MASK LOW10 ; ENDIDLE with NVSUB initiated monitor.04550 4550 6 0,0015 0 AD BANK ; same strategy for CADR as MAKECADR04551 4551 5 0,0531 0 TS CADRSTOR 04552 4552 0 1,2725 0 TC JOBSLEEP 04553 4553 0 1,2723 0 ENDINST TC ENDOFJOB ISCADR_P0 EQU * 04554 4554 1 0,0531 1 CCS CADRSTOR ; aborts (code 1206 if CADRSTOR not= +004555 4555 0 2,4563 0 TC DSPABORT ; returns if CADRSTOR = +004556 4556 0 0,0001 0 TC Q 04557 4557 0 2,4563 0 TC DSPABORT ISLIST_P0 EQU * 04560 4560 1 0,0532 1 CCS DSPLIST ; aborts (code 1206 if DSPLIST not= +004561 4561 0 2,4563 0 TC DSPABORT ; returns if DSPLIST = +004562 4562 0 0,0001 0 TC Q 04563 4563 0 2,5050 1 DSPABORT TC POODOO 04564 4564 01206 1 DS %1206

Page 538: Apollo Guidance Computer AGC

; BLANKSUB blanks any combination of R1, R2, R3. Call with blanking code in A. ; BIT1=1 blanks R1, BIT2=1 blanks R2, BIT3=1 blanks R3. Any combination of these ; three bits is accepted. ; ; DSPCOUNT is restored to the state it was in before BLANKSUB was executed. BLANKSUB EQU * 04565 4565 7 1,2057 0 MASK SEVEN 04566 4566 5 0,0420 1 TS NVTEMP ; store blanking code in NVTEMP04567 4567 3 1,2063 0 CAF BIT14 04570 4570 7 0,0510 1 MASK MONSAVE1 ; external monitor bit04571 4571 6 0,0501 0 AD DSPLOCK 04572 4572 1 0,0000 0 CCS A 04573 4573 0 0,0001 0 TC Q ; dsp syst blocked. Return to 1+calling loc04574 4574 3 0,0001 0 XCH Q ; was INCR Q in Block II04575 4575 6 1,2051 1 AD ONE ; set return for 2+calling location04576 4576 5 0,0561 0 TS BLANKSUB_Q ; was TC Q in Block II 04577 4577 1 0,0420 0 CCS NVTEMP 04600 4600 0 2,4602 1 TC *+2 ; was TCF in Block II04601 4601 0 0,0561 0 TC BLANKSUB_Q ; nothing to blank, Return to 2+calling loc ; the return address+2 is now in BLANKSUB_Q. We need to call BLNKSUB1 in ; in "bank 40", so we'll have to save the bank register so that we can ; return to the address in BLANKSUB_Q. The block II code had a bunch of ; tricky stuff involving the both bank bits and superbit. Block I doesn't ; need to worry about that, so we can substitute this simplified code. ; As in the Block II code, the return bank gets saved to BUF and the return ; address+2 gets saved to BUF+1. 04602 4602 3 1,2050 0 CAF ZERO 04603 4603 6 0,0561 0 AD BLANKSUB_Q 04604 4604 3 0,0426 1 XCH BUF+1 ; set return for 2+calling loc 04605 4605 3 1,2050 0 CAF ZERO 04606 4606 6 0,0015 0 AD BANK 04607 4607 3 0,0425 1 XCH BUF ; save return bank 04610 4610 3 2,4612 0 CAF BSUB1ADDR 04611 4611 0 1,3526 0 TC DXCHJUMP ; bank jump to BLNKSUB1 rtne 04612 4612 13350 0 BSUB1ADDR CADR BLNKSUB1 ; this is my attempt to implement the return from BLNKSUB1. In BII, it executes ; as part of the BLNKSUB1 routine: ; DXCH BUF ; TC SUPDXCHZ+1 ; to jump from the BLNKSUB1 bank to the calling bank. BS_SUPDXCHZ EQU * 04613 4613 3 0,0425 1 XCH BUF 04614 4614 3 0,0015 0 XCH BANK ; restore the calling bank bits04615 4615 0 0,0426 1 TC BUF+1 ; return to calling loc+2 (set in BLANKSUB) BANKFF_5 EQU * ORG BANK04_2 ; COLOSSUS pp. 369 INCL bank04_2.asm ;========================================================================== ; DSPMM - DISPLAY MODREG (file: bank04_2.asm) ; ; DSPMM does not display MODREG directly. It puts EXEC request with ; prio=CHARPRIO for DSPMMJB and returns to caller. ; ; If MODREG contains -0, DSPMMJB blanks the MODE lights. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 369. ;========================================================================== DSPMM EQU * 10047 4,0047 3 0,0001 0 XCH Q 10050 4,0050 5 0,0130 0 TS MPAC 10051 4,0051 2 0,0000 0 INHINT 10052 4,0052 3 2,4131 0 CAF CHRPRIO 10053 4,0053 0 1,3162 1 TC NOVAC 10054 4,0054 13400 1 CADR DSPMMJB 10055 4,0055 2 0,0000 1 RELINT 10056 4,0056 0 0,0130 0 ENDSPMM TC MPAC BANK04_3 EQU * ORG BANK40_8 ; COLOSSUS pp. 369-371 INCL bank40_8.asm ;==========================================================================

Page 539: Apollo Guidance Computer AGC

; DISPLAY ROUTINES (file:bank40_8.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 369-371. ;========================================================================== BLNKSUB1 EQU * 13350 5,1350 3 1,2050 0 CAF ZERO ; was CA DSPCOUNT in Block II13351 5,1351 6 0,0466 0 AD DSPCOUNT ; save old DSPCOUNT for later restoration13352 5,1352 5 0,0427 0 TS BUF+2 13353 5,1353 3 1,2100 1 CAF BIT1 ; test bit 1. See if R1 to be blanked.13354 5,1354 0 5,7373 1 TC TESTBIT 13355 5,1355 3 2,4635 0 CAF R1D1 13356 5,1356 0 5,6472 0 TC _5BLANK-1 13357 5,1357 3 1,2077 0 CAF BIT2 ; test bit 2. See if R2 to be blanked.13360 5,1360 0 5,7373 1 TC TESTBIT 13361 5,1361 3 2,4636 0 CAF R2D1 13362 5,1362 0 5,6472 0 TC _5BLANK-1 13363 5,1363 3 1,2076 1 CAF BIT3 ; test bit 3. See if R3 to be blanked.13364 5,1364 0 5,7373 1 TC TESTBIT 13365 5,1365 3 2,4637 1 CAF R3D1 13366 5,1366 0 5,6472 0 TC _5BLANK-1 13367 5,1367 3 1,2050 0 CAF ZERO ; was CA BUF+2 in Block II13370 5,1370 6 0,0427 0 AD BUF+2 ; restore DSPCOUNT to state it had13371 5,1371 5 0,0466 0 TS DSPCOUNT ; before BLANKSUB 13372 5,1372 0 2,4613 1 TC BS_SUPDXCHZ ; was DXCH BUF, TC SUPDXCHZ+1 in BII TESTBIT EQU * 13373 5,1373 7 0,0420 0 MASK NVTEMP ; NVTEMP contains blanking code13374 5,1374 1 0,0000 0 CCS A 13375 5,1375 0 0,0001 0 TC Q ; if current bit = 1, return to L+113376 5,1376 2 0,0001 1 INDEX Q ; if current bit = 0, return to L+313377 5,1377 0 0,0002 0 TC 2 DSPMMJB EQU * 13400 5,1400 3 2,4677 0 CAF MD1 ; gets here thru DSPMM13401 5,1401 3 0,0466 0 XCH DSPCOUNT 13402 5,1402 5 0,0435 0 TS DSPMMTEM ; save DSPCOUNT13403 5,1403 1 0,0500 0 CCS MODREG 13404 5,1404 6 1,2051 1 AD ONE 13405 5,1405 0 5,7144 1 TC DSPDECVN ; if MODREG is + or +0, display MODREG13406 5,1406 0 5,7410 0 TC *+2 ; if MODREG is -NZ, do nothing13407 5,1407 0 5,6540 0 TC _2BLANK ; if MODREG is -0, blank MM13410 5,1410 3 0,0435 0 XCH DSPMMTEM ; restore DSPCOUNT13411 5,1411 5 0,0466 0 TS DSPCOUNT 13412 5,1412 0 1,2723 0 TC ENDOFJOB ;-------------------------------------------------------------------------- ; RECALTST ; Entered directly after data is loaded (or resequence verb is executed), ; terminate verb is executed, or proceed without data verb is executed. ; It wakes up job that did TC ENDIDLE. ; If CADRSTOR not = +0, it puts +0 into DSPLOCK, and turns off KEY RLSE ; light if DSPLIST is empty (leaves KEY RLSE light alone if not empty). ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.370. ;-------------------------------------------------------------------------- RECALTST EQU * 13413 5,1413 1 0,0531 1 CCS CADRSTOR 13414 5,1414 0 5,7416 0 TC RECAL1 13415 5,1415 0 1,2723 0 TC ENDOFJOB ; normal exit if keyboard initiated. RECAL1 EQU * 13416 5,1416 3 1,2050 0 CAF ZERO 13417 5,1417 3 0,0531 0 XCH CADRSTOR 13420 5,1420 2 0,0000 0 INHINT 13421 5,1421 0 1,3003 1 TC JOBWAKE 13422 5,1422 1 0,0503 0 CCS LOADSTAT 13423 5,1423 0 5,7450 1 TC DOPROC ; + proceed without data13424 5,1424 0 1,2723 0 TC ENDOFJOB ; pathological case exit13425 5,1425 0 5,7446 0 TC DOTERM ; - terminate13426 5,1426 3 1,2052 1 CAF TWO ; -0, data in or resequence RECAL2 EQU * 13427 5,1427 2 0,0300 0 INDEX LOCCTR 13430 5,1430 6 0,0140 1 AD LOC ; loc is + for basic jobs13431 5,1431 2 0,0300 0 INDEX LOCCTR 13432 5,1432 5 0,0140 1 TS LOC

Page 540: Apollo Guidance Computer AGC

13433 5,1433 3 1,2050 0 CAF ZERO ; save verb in MPAC, noun in MPAC+1 at13434 5,1434 6 0,0471 0 AD NOUNREG ; time of response to ENDIDLE for13435 5,1435 2 0,0300 0 INDEX LOCCTR ; possible later testing by job that has13436 5,1436 5 0,0131 1 TS MPAC+1 ; been waked up 13437 5,1437 3 1,2050 0 CAF ZERO 13440 5,1440 6 0,0470 1 AD VERBREG 13441 5,1441 2 0,0300 0 INDEX LOCCTR 13442 5,1442 5 0,0130 0 TS MPAC 13443 5,1443 2 0,0000 1 RELINT RECAL3 EQU * 13444 5,1444 0 2,5003 1 TC RELDSP 13445 5,1445 0 1,2723 0 TC ENDOFJOB DOTERM EQU * 13446 5,1446 3 1,2050 0 CAF ZERO 13447 5,1447 0 5,7427 1 TC RECAL2 DOPROC EQU * 13450 5,1450 3 1,2051 1 CAF ONE 13451 5,1451 0 5,7427 1 TC RECAL2 BANK40_8a EQU * ORG BANKFF_5 ; COLOSSUS pp. 372-376 INCL bankff_5.asm ;========================================================================== ; DISPLAY ROUTINES (file:bankff_5.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 372-376. ;========================================================================== ;-------------------------------------------------------------------------- ; MISCELLANEOUS SERVICE ROUTINES IN FIXED-FIXED ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.372. ;-------------------------------------------------------------------------- ; SETNCADR ; Store the eraseable memory address from A into NOUNCADR and NOUNADD. ; (changed from Block II, because there is no bank addressing for block I) ; SETNADD ; Get the eraseable memory address from NOUNCADR and store it into NOUNADD. ; (changed from Block II, because there is no bank addressing for block I) ; ; SETEBANK ; E CADR arrives in A. E ADRES is "derived" and left in A. ; (changed from Block II, because there is no bank addressing for block I) SETNCADR EQU * 04616 4616 3 0,0001 0 XCH Q 04617 4617 5 0,0555 1 TS SETNCADR_Q ; save return address04620 4620 3 0,0001 0 XCH Q ; restore A 04621 4621 5 0,0506 1 TS NOUNCADR ; store ECADR04622 4622 7 2,4674 1 MASK LOW10 04623 4623 5 0,0442 0 TS NOUNADD ; put E ADRES into NOUNADD04624 4624 0 0,0555 1 TC SETNCADR_Q SETNADD EQU * 04625 4625 3 0,0001 0 XCH Q 04626 4626 5 0,0555 1 TS SETNCADR_Q ; save return address04627 4627 3 0,0001 0 XCH Q ; restore A 04630 4630 3 1,2050 0 CAF ZERO 04631 4631 6 0,0506 1 AD NOUNCADR ; get NOUNCADR04632 4632 0 2,4622 0 TC SETNCADR+4 SETEBANK EQU * 04633 4633 7 2,4674 1 MASK LOW10 04634 4634 0 0,0001 0 TC Q 04635 4635 00016 0 R1D1 DS %16 ; these 3 constants form a packed table04636 4636 00011 1 R2D1 DS %11 ; don't separate04637 4637 00004 0 R3D1 DS %4 ; must stay here RIGHT5 EQU * 04640 4640 5 0,0020 0 TS CYR 04641 4641 4 0,0020 1 CS CYR 04642 4642 4 0,0020 1 CS CYR

Page 541: Apollo Guidance Computer AGC

04643 4643 4 0,0020 1 CS CYR 04644 4644 4 0,0020 1 CS CYR 04645 4645 3 0,0020 0 XCH CYR 04646 4646 0 0,0001 0 TC Q LEFT5 EQU * 04647 4647 5 0,0022 1 TS CYL 04650 4650 4 0,0022 0 CS CYL 04651 4651 4 0,0022 0 CS CYL 04652 4652 4 0,0022 0 CS CYL 04653 4653 4 0,0022 0 CS CYL 04654 4654 3 0,0022 1 XCH CYL 04655 4655 0 0,0001 0 TC Q SLEFT5 EQU * 04656 4656 6 0,0000 1 DOUBLE 04657 4657 6 0,0000 1 DOUBLE 04660 4660 6 0,0000 1 DOUBLE 04661 4661 6 0,0000 1 DOUBLE 04662 4662 6 0,0000 1 DOUBLE 04663 4663 0 0,0001 0 TC Q 04664 4664 00037 0 LOW5 DS %00037 ; these 3 constants form a packed table04665 4665 01740 0 MID5 DS %01740 ; don't separate04666 4666 76000 0 HI5 DS %76000 ; must stay here 04667 4667 0 1,3162 1 TCNOVAC TC NOVAC 04670 4670 0 1,2232 0 TCWAIT TC WAITLIST ;TCTSKOVR TC TASKOVER 04671 4671 0 1,3161 1 TCFINDVAC TC FINDVAC ;CHRPRIO DS %30000 ; EXEC priority of CHARIN04672 4672 03777 0 LOW11 DS %3777 B12M1 EQU LOW11 04673 4673 00377 1 LOW8 DS %377 04674 4674 01777 1 LOW10 DS %01777 04675 4675 00023 0 VD1 DS %23 ; these 3 constants form a packed table04676 4676 00021 1 ND1 DS %21 ; don't separate04677 4677 00025 0 MD1 DS %25 ; must stay here 04700 4700 00012 1 BINCON DS 10 ;**************** TURN ON/OFF OPERATOR ERROR LIGHT ******* p. 373 DSALMOUT EQU OUT1 ; channel 11 in Block II is OUT1 in Block I FALTON EQU * 04701 4701 4 0,0011 0 CS DSALMOUT ; inclusive OR bit 7 with 1 using04702 4702 7 2,4712 0 MASK FALTOR ; Demorgan's theorem04703 4703 4 0,0000 0 COM 04704 4704 5 0,0011 1 TS DSALMOUT ; was bit 7 of channel 11 in Block II04705 4705 0 0,0001 0 TC Q FALTOF EQU * 04706 4706 4 1,2072 1 CS BIT7 04707 4707 7 0,0011 0 MASK DSALMOUT 04710 4710 5 0,0011 1 TS DSALMOUT ; was bit 7 of channel 11 in Block II04711 4711 0 0,0001 0 TC Q 04712 4712 77677 1 FALTOR DS %77677 ; 1's compliment of bit 7 ;**************** TURN ON KEY RELEASE LIGHT ******* p. 373 RELDSPON EQU * 04713 4713 4 0,0011 0 CS DSALMOUT ; inclusive OR bit 5 with 1 using04714 4714 7 2,4720 1 MASK RELDSPOR ; Demorgan's theorem04715 4715 4 0,0000 0 COM 04716 4716 5 0,0011 1 TS DSALMOUT ; was bit 5 of channel 11 in Block II04717 4717 0 0,0001 0 TC Q 04720 4720 77757 1 RELDSPOR DS %77757 ; 1's compliment of bit 5 ; TPSL1 ; Shift triple word MPAC, MPAC+1, MPAC+2 left 1 bit TPSL1 EQU * 04721 4721 3 1,2050 0 CAF ZERO 04722 4722 6 0,0132 1 AD MPAC+2 04723 4723 6 0,0132 1 AD MPAC+2 04724 4724 5 0,0132 1 TS MPAC+2 ; skip on overflow 04725 4725 3 1,2050 0 CAF ZERO ; otherwise, make interword carry=004726 4726 6 0,0131 1 AD MPAC+1 04727 4727 6 0,0131 1 AD MPAC+1

Page 542: Apollo Guidance Computer AGC

04730 4730 5 0,0131 1 TS MPAC+1 ; skip on overflow 04731 4731 3 1,2050 0 CAF ZERO ; otherwise, make interword carry=004732 4732 6 0,0130 0 AD MPAC 04733 4733 6 0,0130 0 AD MPAC 04734 4734 5 0,0130 0 TS MPAC ; skip on overflow 04735 4735 0 0,0001 0 TC Q ; no net OV/UF04736 4736 5 0,0136 0 TS MPAC+6 ; MPAC+6 set to +/- 1 for OV/UF04737 4737 0 0,0001 0 TC Q ; PRSHRTMP ; if MPAC, +1 are each +NZ or +0 and C(A)=-0, SHORTMP wrongly gives +0. ; if MPAC, +1 are each -NZ or -0 and C(A)=+0, SHORTMP wrongly gives +0. ; PRSHRTMP fixes first case only, by merely testing C(A) and if it = -0, ; setting result to -0. ; (Do not use PRSHRTMP unless MPAC, +1 are each +NZ or +0, as they are ; when they contain the SF constants). PRSHRTMP EQU * 04740 4740 5 0,0432 1 TS MPTEMP 04741 4741 3 0,0001 0 XCH Q 04742 4742 5 0,0600 1 TS PRSHRTMP_Q 04743 4743 1 0,0432 0 CCS MPTEMP 04744 4744 0 2,4754 0 TC DOSHRTMP ; C(A) +, do regular SHORTMP04745 4745 0 2,4754 0 TC DOSHRTMP ; C(A) +0, do regular SHORTMP04746 4746 0 2,4754 0 TC DOSHRTMP ; C(A) -, do regular SHORTMP04747 4747 4 1,2050 1 CS ZERO ; C(A) -0, force result to -0 and return04750 4750 5 0,0130 0 TS MPAC 04751 4751 5 0,0131 1 TS MPAC+1 04752 4752 5 0,0132 1 TS MPAC+2 04753 4753 0 0,0600 1 TC PRSHRTMP_Q DOSHRTMP EQU * 04754 4754 3 1,2050 0 CAF ZERO 04755 4755 6 0,0432 1 AD MPTEMP 04756 4756 0 2,4353 0 TC SHORTMP 04757 4757 0 0,0600 1 TC PRSHRTMP_Q ;**************** TURN ON/OFF V/N FLASH ******* p. 374 ; this is handled by setting a bit in channel 11 in Block II. ; In Block I, it has to be set through the display table, so I ; borrowed this method from SGNCOM (the DSKY +/- sign routine) ; Uses MYBANKCALL because BANKCALL is not reentrant and I dont ; understand its usage in COLOSSUS well enough to be certain ; that FLASHON/FLASHOFF isn't being called somewhere through ; BANKCALL. FLASHON EQU * 04760 4760 3 0,0001 0 XCH Q 04761 4761 5 0,0570 0 TS FLASHRET 04762 4762 3 1,2066 0 CAF BIT11 04763 4763 5 0,0421 0 TS CODE 04764 4764 3 2,5000 1 CAF FLSHTAB 04765 4765 0 1,3624 1 TC MYBANKCALL 04766 4766 13253 1 CADR _11DSPIN 04767 4767 0 0,0570 0 TC FLASHRET FLASHOFF EQU * 04770 4770 3 0,0001 0 XCH Q 04771 4771 5 0,0570 0 TS FLASHRET 04772 4772 3 1,2050 0 CAF ZERO 04773 4773 5 0,0421 0 TS CODE 04774 4774 3 2,5000 1 CAF FLSHTAB 04775 4775 0 1,3624 1 TC MYBANKCALL 04776 4776 13253 1 CADR _11DSPIN 04777 4777 0 0,0570 0 TC FLASHRET 05000 5000 00011 1 FLSHTAB DS %11 ; V/N flash NVSUBUSY EQU * 05001 5001 0 1,3653 1 TC POSTJUMP 05002 5002 13452 0 CADR NVSUBSY1

Page 543: Apollo Guidance Computer AGC

BANKFF_5a EQU * ORG BANK40_8a ; COLOSSUS pp. 376 INCL bank40_8a.asm ;========================================================================== ; DISPLAY ROUTINES (file:bank40_8a.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 376. ;========================================================================== ;-------------------------------------------------------------------------- ; MISCELLANEOUS SERVICE ROUTINES IN FIXED-FIXED ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.376. ;-------------------------------------------------------------------------- NVSUBSY1 EQU * 13452 5,1452 5 0,0567 0 TS NBSUBSY1_L ; save CADR13453 5,1453 0 2,4554 1 TC ISCADR_P0 ; abort if CADRSTOR not = +013454 5,1454 0 2,4560 0 TC ISLIST_P0 ; abort if DSPLIST not = +013455 5,1455 0 2,4713 0 TC RELDSPON 13456 5,1456 3 1,2050 0 CAF ZERO ; was CA L in Block II13457 5,1457 6 0,0567 0 AD NBSUBSY1_L 13460 5,1460 5 0,0532 0 TS DSPLIST 13461 5,1461 0 1,2725 0 ENDNVBSY TC JOBSLEEP BANK40_9 EQU * ORG BANKFF_5a ; COLOSSUS pp. 376-378 INCL bankff_5a.asm ;========================================================================== ; DISPLAY ROUTINES (file:bankff_5a.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 376-378. ;========================================================================== ;-------------------------------------------------------------------------- ; MISCELLANEOUS SERVICE ROUTINES IN FIXED-FIXED ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.376. ;-------------------------------------------------------------------------- ; RELDSP ; used by VBPROC, VBTERM, VBRQEXEC, VBRQWAIT, VBRELDSP, EXTENDED VERB ; DISPATCHER, VBRESEQ, and RECALTST. ; RELDSP1 ; used by monitor set up, VBRELDSP RELDSP EQU * 05003 5003 3 0,0001 0 XCH Q ; set DSPLOCK to +0, turn RELDSP light05004 5004 5 0,0441 0 TS RELRET ; off, search DSPLIST05005 5005 4 1,2063 1 CS BIT14 05006 5006 2 0,0000 0 INHINT 05007 5007 7 0,0510 1 MASK MONSAVE1 05010 5010 5 0,0510 0 TS MONSAVE1 ; turn off external monitor bit05011 5011 1 0,0532 1 CCS DSPLIST 05012 5012 0 2,5014 1 TC *+2 05013 5013 0 2,5017 1 TC RELDSP2 ; list empty05014 5014 3 1,2050 0 CAF ZERO 05015 5015 3 0,0532 0 XCH DSPLIST 05016 5016 0 1,3003 1 TC JOBWAKE RELDSP2 EQU * 05017 5017 2 0,0000 1 RELINT 05020 5020 4 1,2074 1 CS BIT5 ; turn off KEY RLSE light05021 5021 7 0,0011 0 MASK DSALMOUT ; was WAND DSALMOUT in Block II05022 5022 5 0,0011 1 TS DSALMOUT 05023 5023 3 1,2050 0 CAF ZERO 05024 5024 5 0,0501 0 TS DSPLOCK 05025 5025 0 0,0441 0 TC RELRET RELDSP1 EQU * 05026 5026 3 0,0001 0 XCH Q ; set DSPLOCK to +0, No DSPLIST search05027 5027 5 0,0441 0 TS RELRET ; turn KEY RLSE light off if DSPLIST is ; empty. Leave KEY RLSE light alone if ; DSPLIST is not empty.05030 5030 1 0,0532 1 CCS DSPLIST 05031 5031 0 2,5033 1 TC *+2 ; + not empty, leave KEY RLSE light alone05032 5032 0 2,5017 1 TC RELDSP2 ; +0, list empty, turn off KEY RLSE light05033 5033 3 1,2050 0 CAF ZERO ; - not empty, leave KEY RLSE light alone

Page 544: Apollo Guidance Computer AGC

05034 5034 5 0,0501 0 TS DSPLOCK 05035 5035 0 0,0441 0 TC RELRET ;-------------------------------------------------------------------------- ; NEWMODEA ; ; The new major mode is in register A. Store the major mode in MODREG and update ; the major mode display. ; ; I couldn't find this in my COLOSSUS listing, so I borrowed it from UPDATVB-1 ; (but modified it to work with the major mode instead of the verb). ;-------------------------------------------------------------------------- NEWMODEA EQU * 05036 5036 5 0,0500 1 TS MODREG ; store new major mode05037 5037 3 0,0001 0 XCH Q 05040 5040 5 0,0572 1 TS NEWMODEA_Q ; save Q 05041 5041 3 2,4677 0 CAF MD1 05042 5042 5 0,0466 0 TS DSPCOUNT 05043 5043 3 1,2050 0 CAF ZERO 05044 5044 6 0,0500 1 AD MODREG 05045 5045 0 1,3565 1 TC BANKCALL 05046 5046 13144 1 CADR DSPDECVN 05047 5047 0 0,0572 1 TC NEWMODEA_Q ; return ;------------------------------------------------------------------------- ; POODOO - Program alarm. ; ; Turn on program alarm light and store alarm code in FAILREG. The alarm code ; is retrieved from the address pointed to by Q. The most recent code is stored ; in FAILREG. Older codes are scrolled to FAILREG+1,+2. Older CADRs are ; scrolled down. ; ; This was missing from my COLOSSUS listing, so I had to guess at the ; implementation, based upon calling references in COLOSSUS, and textual ; descriptions of normal noun 9 which retrieves alarm codes. ;------------------------------------------------------------------------- POODOO EQU * 05050 5050 3 0,0001 0 XCH Q 05051 5051 5 0,0130 0 TS MPAC 05052 5052 4 0,0011 0 CS DSALMOUT ; inclusive OR bit 9 with 1 using05053 5053 7 2,5066 0 MASK NOTPALT ; Demorgan's theorem05054 5054 4 0,0000 0 COM 05055 5055 5 0,0011 1 TS DSALMOUT ; turn on PROG ALM light05056 5056 3 0,0461 1 XCH FAILREG+1 ; scroll previous codes down05057 5057 5 0,0462 1 TS FAILREG+2 05060 5060 3 0,0460 0 XCH FAILREG 05061 5061 5 0,0461 1 TS FAILREG+1 05062 5062 2 0,0130 1 INDEX MPAC ; indirectly address Q05063 5063 3 0,0000 1 CAF 0 ; (gets alarm code)05064 5064 5 0,0460 0 TS FAILREG ; store alarm code05065 5065 0 1,2723 0 TC ENDOFJOB 05066 5066 77377 1 NOTPALT DS %77377 ; 1's compliment of bit9 (PROG ALM) ;------------------------------------------------------------------------- ; PINBRNCH ; ; This is supposed to restore the DSKY display to its former state in the ; event of error. According to COLOSSUS, it works if you use "Margaret's" ; code. I don't have that portion of the listing, so I just terminate ; the job, which seems to be an acceptable work-around, even though the ; old display is not restored. ;------------------------------------------------------------------------- 05067 5067 0 1,2723 0 PINBRNCH TC ENDOFJOB BANKFF_6 EQU * ORG BANK41_8 ; COLOSSUS pp. 379-380 INCL bank41_8.asm ;========================================================================== ; DISPLAY ROUTINES (file:bank41_8.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 379-380. ;==========================================================================

Page 545: Apollo Guidance Computer AGC

VBTSTLTS EQU * 15572 6,1572 2 0,0000 0 INHINT ; heavily modified from the original Block II code... 15573 6,1573 4 0,0011 0 CS DSALMOUT ; turn on lights15574 6,1574 7 6,7623 0 MASK TSTCON1 ; inclusive OR light bits with 1's using15575 6,1575 4 0,0000 0 COM ; Demorgan's theorem15576 6,1576 5 0,0011 1 TS DSALMOUT 15577 6,1577 3 1,2060 0 CAF TEN 15600 6,1600 5 0,0414 0 TSTLTS1 TS ERCNT 15601 6,1601 4 6,7621 1 CS FULLDSP 15602 6,1602 2 0,0414 1 INDEX ERCNT 15603 6,1603 5 0,0512 1 TS DSPTAB 15604 6,1604 1 0,0414 1 CCS ERCNT 15605 6,1605 0 6,7600 0 TC TSTLTS1 15606 6,1606 4 6,7622 1 CS FULLDSP1 15607 6,1607 5 0,0513 0 TS DSPTAB+1 ; turn on 3 plus signs15610 6,1610 5 0,0516 0 TS DSPTAB+4 15611 6,1611 5 0,0520 0 TS DSPTAB+6 15612 6,1612 3 1,2061 1 CAF ELEVEN 15613 6,1613 5 0,0505 1 TS NOUT 15614 6,1614 0 2,4760 1 TC FLASHON 15615 6,1615 3 6,7624 0 CAF SHOLTS 15616 6,1616 0 1,2232 0 TC WAITLIST 15617 6,1617 15625 1 CADR TSTLTS2 15620 6,1620 0 1,2723 0 TC ENDOFJOB ; DSPLOCK is left busy (from keyboard ; action) until TSTLTS3 to ensure that ; lights test will be seen. 15621 6,1621 05675 0 FULLDSP DS %05675 ; display all 8's15622 6,1622 07675 1 FULLDSP1 DS %07675 ; display all 8's and + ; 1's Comp of UPTEL=bit3, KEY REL=bit5, oper err=bit7, PROG ALM=bit 9 15623 6,1623 77253 0 TSTCON1 DS %77253 15624 6,1624 00764 1 SHOLTS DS %764 ; 5 sec TSTLTS2 EQU * 15625 6,1625 3 2,4131 0 CAF CHRPRIO ; called by WAITLIST15626 6,1626 0 1,3162 1 TC NOVAC 15627 6,1627 15631 1 CADR TSTLTS3 15630 6,1630 0 1,2413 0 TC TASKOVER TSTLTS3 EQU * 15631 6,1631 2 0,0000 0 INHINT 15632 6,1632 3 6,7623 1 CAF TSTCON1 ; turn off lights15633 6,1633 7 0,0011 0 MASK DSALMOUT 15634 6,1634 5 0,0011 1 TS DSALMOUT 15635 6,1635 2 0,0000 1 RELINT 15636 6,1636 0 1,3565 1 TC BANKCALL ; redisplay C(MODREG)15637 6,1637 10047 0 CADR DSPMM 15640 6,1640 0 2,4536 0 TC KILMONON ; turn on kill monitor bit15641 6,1641 0 2,4770 0 TC FLASHOFF ; turn off V/N flash15642 6,1642 0 1,3653 1 TC POSTJUMP ; does RELDSP and goes to PINBRNCH if15643 6,1643 13334 1 CADR TSTLTS4 ; ENDIDLE is awaiting operator response BANK41_9 EQU * ORG BANK40_9 ; COLOSSUS pp. 381-382 INCL bank40_9.asm ;========================================================================== ; DISPLAY ROUTINES (file:bank40_9.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 381-382. ;========================================================================== ;-------------------------------------------------------------------------- ; ERROR - Error light reset. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.381. ;--------------------------------------------------------------------------

Page 546: Apollo Guidance Computer AGC

ERROR EQU * 13462 5,1462 3 0,0412 0 XCH _2122REG ; restore original C(DSPLOCK), thus error13463 5,1463 5 0,0501 0 TS DSPLOCK ; light reset leaves DSPLOCK unchanged ; omitted some stuff in COLOSSUS here 13464 5,1464 4 5,7520 0 CS ERCON ; turn off UPTL, OPER ERR, PROG ALM13465 5,1465 7 0,0011 0 MASK DSALMOUT 13466 5,1466 5 0,0011 1 TS DSALMOUT 13467 5,1467 3 2,4700 1 TSTAB CAF BINCON ; dec 1013470 5,1470 5 0,0414 0 TS ERCNT ; ERCNT = count13471 5,1471 2 0,0000 0 INHINT 13472 5,1472 2 0,0414 1 INDEX ERCNT 13473 5,1473 1 0,0512 0 CCS DSPTAB 13474 5,1474 6 1,2051 1 AD ONE 13475 5,1475 0 5,7502 1 TC ERPLUS 13476 5,1476 6 1,2051 1 AD ONE 13477 5,1477 4 0,0000 0 ERMINUS CS A 13500 5,1500 7 5,7517 1 MASK NOTBIT12 13501 5,1501 0 5,7505 0 TC ERCOM 13502 5,1502 4 0,0000 0 ERPLUS CS A 13503 5,1503 7 5,7517 1 MASK NOTBIT12 13504 5,1504 4 0,0000 0 CS A 13505 5,1505 2 0,0414 1 ERCOM INDEX ERCNT 13506 5,1506 5 0,0512 1 TS DSPTAB 13507 5,1507 2 0,0000 1 RELINT 13510 5,1510 1 0,0414 1 CCS ERCNT 13511 5,1511 0 5,7470 0 TC TSTAB+1 13512 5,1512 3 1,2050 0 CAF ZERO ; clear the error codes for PROG ALM13513 5,1513 5 0,0460 0 TS FAILREG 13514 5,1514 5 0,0461 1 TS FAILREG+1 13515 5,1515 5 0,0462 1 TS FAILREG+2 13516 5,1516 0 1,2723 0 TC ENDOFJOB 13517 5,1517 73777 1 NOTBIT12 DS %73777 13520 5,1520 00504 0 ERCON DS %504 ; channel 11 bits 3,7,9 BANK40_10 EQU * ; end of PINBALL routines ; PINBALL NOUN tables ORG BANK42_3 INCL bank42_3.asm ; COLOSSUS pp. 263-279 ;========================================================================== ; PINBALL NOUN TABLES (file:bank42_3.asm) ; ; The following routines are for reading the noun tables and the scale ; factor (SF) tables (which are in a separate bank from the rest of ; PINBALL). These reading routines are in the same bank as the tables. ; They are called by DXCH Z (translated to DXCHJUMP for Block I). ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 263-279. ;========================================================================== ;-------------------------------------------------------------------------- ; Noun table info from COLOSSUS, p.325 ; ; noun code < 40 : normal noun case ; noun code >= 40: mixed noun case ;-------------------------------------------------------------------------- ; NNADTAB: ; for normal noun case, NNADTAB contains one CADR for each noun. ; +entry = noun CADR ; +0 = noun not used. ; -entry = machine CADR (E or F) to be specified. ; -1 = channel to be specified (not used for Block I); ; -0 = augment of last machine CADR supplied. ; for mixed noun case, NNADTAB contains one indirect address (IDADDREL) ; in low 10 bits, and the component code number in the high 5 bits. ; Examples: ; NNADTAB = %00042 ; CADR for octal address 42 ; NNADTAB = %00000 ; noun not used ; NNADTAB = %40000 ; specify machine address ; NNADTAB = %77777 ; augment last address

Page 547: Apollo Guidance Computer AGC

;-------------------------------------------------------------------------- ; NNTYPETAB (normal case): ; a packed table of the form: MMMMM NNNNN PPPPP ; for the normal case: ; MMMMM (bits 15-11): COMPONENT CODE NUMBER (p.263) ; 00000 = 1 component ; 00001 = 2 component ; 00010 = 3 component ; X1XXX = bit4=1, decimal only ; 1XXXX = bit5=1, no load ; ; NNNNN (bits 10-6): SF ROUTINE CODE NUMBER (p.263) ; 00000 = octal only ; 00001 = straight fractional (decimal) ; 00010 = CDU degrees (XXX.XX) ; 00011 = arithmetic SF ; 00100 = arith DP1, OUT(mult by 2EXP14 at end), IN(straight) ; 00101 = arith DP2, OUT(straight), IN(SL 7 at end) ; 00110 = Y optics degrees (XX.XXX max at 89.999) ; 00111 = arith DP3, OUT(SL 7 at end) IN(straight) ; 01000 = whole hours in R1, whole minutes (mod 60) in R2, ; seconds (mod 60) 0XX.XX in R3 *** alarms if used withoctal ; ; PPPPP (bits 5-1): SF CONSTANT CODE NUMBER (p.263) ; 00000 = whole, use arith ; Examples: ; NNTYPTAB = %00000 ; 1 comp, octal only ; NNTYPTAB = %02000 ; 2 comp, octal only ; NNTYPTAB = %04000 ; 3 comp, octal only ; NNTYPTAB = %00040 ; 1 comp ,straight fractional ; NNTYPTAB = %04040 ; 3 comp ,straight fractional ;-------------------------------------------------------------------------- ; NNTYPETAB (mixed case): ; a packed table of the form: MMMMM NNNNN PPPPP ; for the mixed case (3 component): ; MMMMM (bits 15-11) = SF constant3 code number. ; NNNNN (bits 10-6) = SF constant2 code number. ; PPPPP (bits 5-1) = SF constant1 code number. ; for the mixed case (2 component): ; NNNNN (bits 10-6) = SF constant2 code number. ; PPPPP (bits 5-1) = SF constant1 code number. ; for the mixed case (1 component): ; PPPPP (bits 5-1) = SF constant1 code number. ;-------------------------------------------------------------------------- ; IDADDTAB (mixed case only): ; there is also an indirect address table for mixed case only. ; Each entry contains one ECADR. IDADDREL is the relative address of ; the first of these entries. ; There is one entry in this table for each component of a mixed noun. ; They are listed in order of ascending K. ;-------------------------------------------------------------------------- ; RUTMXTAB (mixed case only): ; there is also a scale factor routine number table for mixed case only. ; There is one entry per mixed noun. The form is: QQQQQ RRRRR SSSSS ; for the 3 component case ; QQQQQ (bits 15-11) = SF routine3 code number. ; RRRRR (bits 10-6) = SF routine2 code number. ; SSSSS (bits 5-1) = SF routine1 code number. ; for the 2 component case ; RRRRR (bits 10-6) = SF routine2 code number. ; SSSSS (bits 5-1) = SF routine1 code number. ; In octal display and load (oct or dec) verbs, exclude use of verbs whose ; component number is greater than the number of components in noun. ; (All machine address to be specified nouns are 3 component) ; In multi-component load verbs, no mixing of octal and decimal data ; component words is allowed; alarm if violation. ; In decimal loads of data, 5 numerical chars must be keyed in before ; each enter; if not, alarm. ;--------------------------------------------------------------------------

Page 548: Apollo Guidance Computer AGC

; LODNNTAB ; loads NNADTEM with the NNADTAB entry, NNTYPTEM with the NNTYPTAB ; entry. If the noun is mixed, IDAD1TEM is loaded with the first IDADTAB ; entry, IDAD2TEM the second IDADTAB entry, IDAD3TEM the third IDADTAB ; entry, RUTMXTEM with the RUTMXTAB entry. MIXBR is set for mixed=2 ; or normal=1 noun. ; ; NOTE: in BlockII, NNADTEM = -1 means use an I/O channel instead of a ; memory address (channel specified in NOUNCADR). Block I does not have ; I/O channels. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.265. ;-------------------------------------------------------------------------- LODNNTAB EQU * 16114 7,0114 5 0,0562 0 TS GTSF_RET ; save return CADR 16115 7,0115 2 0,0471 1 INDEX NOUNREG 16116 7,0116 3 7,6210 1 CAF NNADTAB 16117 7,0117 5 0,0443 1 TS NNADTEM 16120 7,0120 2 0,0471 1 INDEX NOUNREG 16121 7,0121 3 7,6354 0 CAF NNTYPTAB 16122 7,0122 5 0,0444 0 TS NNTYPTEM 16123 7,0123 4 0,0471 1 CS NOUNREG 16124 7,0124 6 7,6161 1 AD MIXCON 16125 7,0125 1 0,0000 0 CCS A ; was BZMF LODMIXNN in Block II16126 7,0126 0 7,6132 1 TC *+4 ; >016127 7,0127 0 7,6131 1 TC *+2 ; +0, noun number G/E first mixed noun16130 7,0130 0 7,6131 1 TC *+1 ; <0, noun number G/E first mixed noun16131 7,0131 0 7,6135 0 TC LODMIXNN ; -0, noun number G/E first mixed noun 16132 7,0132 3 1,2051 1 CAF ONE ; noun number L/ first mixed noun16133 7,0133 5 0,0435 0 TS MIXBR ; normal, +1 into MIXBR 16134 7,0134 0 7,6156 0 TC LODNLV LODMIXNN EQU * 16135 7,0135 3 1,2052 1 CAF TWO ; mixed, +2 into MIXBR16136 7,0136 5 0,0435 0 TS MIXBR 16137 7,0137 2 0,0471 1 INDEX NOUNREG 16140 7,0140 3 7,7054 1 CAF RUTMXTAB-40 ; first mixed noun = 4016141 7,0141 5 0,0450 0 TS RUTMXTEM 16142 7,0142 3 2,4674 0 CAF LOW10 16143 7,0143 7 0,0443 0 MASK NNADTEM 16144 7,0144 5 0,0001 0 TS Q ; temp 16145 7,0145 2 0,0000 0 INDEX A 16146 7,0146 3 7,6640 0 CAF IDADDTAB 16147 7,0147 5 0,0445 1 TS IDAD1TEM ; load IDAD1TEM with first IDADDTAB entry 16150 7,0150 2 0,0001 1 INDEX Q 16151 7,0151 3 7,6641 1 CAF IDADDTAB+1 16152 7,0152 5 0,0446 1 TS IDAD2TEM ; load IDAD2TEM with 2nd IDADDTAB entry 16153 7,0153 2 0,0001 1 INDEX Q 16154 7,0154 3 7,6642 1 CAF IDADDTAB+2 16155 7,0155 5 0,0447 0 TS IDAD3TEM ; load IDAD3TEM with 3rd IDADDTAB entry LODNLV EQU * 16156 7,0156 3 1,2050 0 CAF ZERO 16157 7,0157 6 0,0562 0 AD GTSF_RET ; load return CADR16160 7,0160 0 1,3526 0 TC DXCHJUMP ; return 16161 7,0161 00050 1 MIXCON DS %50 ; 1st mixed noun = 40 (DEC 40) ;-------------------------------------------------------------------------- ; GTSFOUT ; On entry, SFTEMP1 contains SFCONUM X 2. ; Loads SFTEMP1, SFTEMP2 with the DP SFOUTAB entries ; ; GTSFIN ; On entry, SFTEMP1 contains SFCONUM X 2. ; Loads SFTEMP1, SFTEMP2 with the DP SFINTAB entries ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.266. ;-------------------------------------------------------------------------- GTSFOUT EQU * 16162 7,0162 5 0,0562 0 TS GTSF_RET ; save return CADR

Page 549: Apollo Guidance Computer AGC

16163 7,0163 3 0,0420 1 XCH SFTEMP1 16164 7,0164 5 0,0001 0 TS Q ; temp 16165 7,0165 2 0,0001 1 INDEX Q 16166 7,0166 3 7,6570 0 CAF SFOUTAB 16167 7,0167 5 0,0420 1 TS SFTEMP1 16170 7,0170 2 0,0001 1 INDEX Q 16171 7,0171 3 7,6571 1 CAF SFOUTAB+1 16172 7,0172 5 0,0421 0 TS SFTEMP2 SFCOM EQU * 16173 7,0173 3 1,2050 0 CAF ZERO 16174 7,0174 6 0,0562 0 AD GTSF_RET ; load return CADR16175 7,0175 0 1,3526 0 TC DXCHJUMP ; return GTSFIN EQU * 16176 7,0176 5 0,0562 0 TS GTSF_RET ; save return CADR 16177 7,0177 3 0,0420 1 XCH SFTEMP1 16200 7,0200 5 0,0001 0 TS Q ; temp 16201 7,0201 2 0,0001 1 INDEX Q 16202 7,0202 3 7,6520 0 CAF SFINTAB 16203 7,0203 5 0,0420 1 TS SFTEMP1 16204 7,0204 2 0,0001 1 INDEX Q 16205 7,0205 3 7,6521 1 CAF SFINTAB+1 16206 7,0206 5 0,0421 0 TS SFTEMP2 16207 7,0207 0 7,6173 1 TC SFCOM ;-------------------------------------------------------------------------- ; NOUN ADDRESS TABLE (NNADTAB) ; Indexed by noun number (0-39 decimal for normal nouns). ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.266. ;-------------------------------------------------------------------------- NNADTAB EQU * ; NN - NORMAL NOUNS16210 7,0210 00000 1 DS %0 ; 00 - not in use16211 7,0211 40000 0 DS %40000 ; 01 - specify machine address (fractional)16212 7,0212 40000 0 DS %40000 ; 02 - specify machine address (whole)16213 7,0213 40000 0 DS %40000 ; 03 - specify machine address (degrees)16214 7,0214 00036 1 DS %00036 ; 04 - spare *********** TEST, CHANGE TO ZERO16215 7,0215 00000 1 DS %0 ; 05 - spare16216 7,0216 00000 1 DS %0 ; 06 - spare16217 7,0217 00000 1 DS %0 ; 07 - spare16220 7,0220 00000 1 DS %0 ; 08 - spare16221 7,0221 00460 0 ECADR FAILREG ; 09 - alarm codes16222 7,0222 00000 1 DS %0 ; 10 - spare16223 7,0223 00000 1 DS %0 ; 11 - spare16224 7,0224 00000 1 DS %0 ; 12 - spare16225 7,0225 00000 1 DS %0 ; 13 - spare16226 7,0226 00000 1 DS %0 ; 14 - spare16227 7,0227 77777 0 DS %77777 ; 15 - increment machine address16230 7,0230 00000 1 DS %0 ; 16 - spare16231 7,0231 00000 1 DS %0 ; 17 - spare16232 7,0232 00000 1 DS %0 ; 18 - spare16233 7,0233 00000 1 DS %0 ; 19 - spare16234 7,0234 00000 1 DS %0 ; 20 - spare16235 7,0235 00000 1 DS %0 ; 21 - spare16236 7,0236 00000 1 DS %0 ; 22 - spare16237 7,0237 00000 1 DS %0 ; 23 - spare16240 7,0240 00000 1 DS %0 ; 24 - spare16241 7,0241 00000 1 DS %0 ; 25 - spare16242 7,0242 00534 0 ECADR DSPTEM1 ; 26 - prio/delay, adres, BBCON16243 7,0243 00000 1 DS %0 ; 27 - spare16244 7,0244 00000 1 DS %0 ; 28 - spare16245 7,0245 00000 1 DS %0 ; 29 - spare16246 7,0246 00000 1 DS %0 ; 30 - spare16247 7,0247 00000 1 DS %0 ; 31 - spare16250 7,0250 00000 1 DS %0 ; 32 - spare16251 7,0251 00000 1 DS %0 ; 33 - spare16252 7,0252 00000 1 DS %0 ; 34 - spare16253 7,0253 00000 1 DS %0 ; 35 - spare16254 7,0254 00035 1 ECADR TIME2 ; 36 - time of AGC clock (hrs, min, sec)16255 7,0255 00000 1 DS %0 ; 37 - spare16256 7,0256 00000 1 DS %0 ; 38 - spare16257 7,0257 00000 1 DS %0 ; 39 - spare ; end of normal nouns ; start of mixed nouns 16260 7,0260 00000 1 DS %0 ; 40 - spare16261 7,0261 00000 1 DS %0 ; 41 - spare

Page 550: Apollo Guidance Computer AGC

16262 7,0262 00000 1 DS %0 ; 42 - spare16263 7,0263 00000 1 DS %0 ; 43 - spare16264 7,0264 00000 1 DS %0 ; 44 - spare16265 7,0265 00000 1 DS %0 ; 45 - spare16266 7,0266 00000 1 DS %0 ; 46 - spare16267 7,0267 00000 1 DS %0 ; 47 - spare16270 7,0270 00000 1 DS %0 ; 48 - spare16271 7,0271 00000 1 DS %0 ; 49 - spare16272 7,0272 00000 1 DS %0 ; 50 - spare16273 7,0273 00000 1 DS %0 ; 51 - spare16274 7,0274 00000 1 DS %0 ; 52 - spare16275 7,0275 00000 1 DS %0 ; 53 - spare16276 7,0276 00000 1 DS %0 ; 54 - spare16277 7,0277 00000 1 DS %0 ; 55 - spare16300 7,0300 00000 1 DS %0 ; 56 - spare16301 7,0301 00000 1 DS %0 ; 57 - spare16302 7,0302 00000 1 DS %0 ; 58 - spare16303 7,0303 00000 1 DS %0 ; 59 - spare16304 7,0304 00000 1 DS %0 ; 60 - spare16305 7,0305 00000 1 DS %0 ; 61 - spare16306 7,0306 00000 1 DS %0 ; 62 - spare16307 7,0307 00000 1 DS %0 ; 63 - spare16310 7,0310 00000 1 DS %0 ; 64 - spare16311 7,0311 00000 1 DS %0 ; 65 - spare16312 7,0312 00000 1 DS %0 ; 66 - spare16313 7,0313 00000 1 DS %0 ; 67 - spare16314 7,0314 00000 1 DS %0 ; 68 - spare16315 7,0315 00000 1 DS %0 ; 69 - spare16316 7,0316 00000 1 DS %0 ; 70 - spare16317 7,0317 00000 1 DS %0 ; 71 - spare16320 7,0320 00000 1 DS %0 ; 72 - spare16321 7,0321 00000 1 DS %0 ; 73 - spare16322 7,0322 00000 1 DS %0 ; 74 - spare16323 7,0323 00000 1 DS %0 ; 75 - spare16324 7,0324 00000 1 DS %0 ; 76 - spare16325 7,0325 00000 1 DS %0 ; 77 - spare16326 7,0326 00000 1 DS %0 ; 78 - spare16327 7,0327 00000 1 DS %0 ; 79 - spare16330 7,0330 00000 1 DS %0 ; 80 - spare16331 7,0331 00000 1 DS %0 ; 81 - spare16332 7,0332 00000 1 DS %0 ; 82 - spare16333 7,0333 00000 1 DS %0 ; 83 - spare16334 7,0334 00000 1 DS %0 ; 84 - spare16335 7,0335 00000 1 DS %0 ; 85 - spare16336 7,0336 00000 1 DS %0 ; 86 - spare16337 7,0337 00000 1 DS %0 ; 87 - spare16340 7,0340 00000 1 DS %0 ; 88 - spare16341 7,0341 00000 1 DS %0 ; 89 - spare16342 7,0342 00000 1 DS %0 ; 90 - spare16343 7,0343 00000 1 DS %0 ; 91 - spare16344 7,0344 00000 1 DS %0 ; 92 - spare16345 7,0345 00000 1 DS %0 ; 93 - spare16346 7,0346 00000 1 DS %0 ; 94 - spare16347 7,0347 00000 1 DS %0 ; 95 - spare16350 7,0350 00000 1 DS %0 ; 96 - spare16351 7,0351 00000 1 DS %0 ; 97 - spare16352 7,0352 00000 1 DS %0 ; 98 - spare16353 7,0353 00000 1 DS %0 ; 99 - spare ; end of mixed nouns ;-------------------------------------------------------------------------- ; NOUN TYPE TABLE (NNTYPTAB) ; Indexed by noun number (0-39 decimal for normal nouns). ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.269. ;-------------------------------------------------------------------------- NNTYPTAB EQU * ; NN - NORMAL NOUNS16354 7,0354 00000 1 DS %0 ; 00 - not in use16355 7,0355 04040 1 DS %04040 ; 01 - 3 component (fractional)16356 7,0356 04140 0 DS %04140 ; 02 - 3 component (whole)16357 7,0357 04102 0 DS %04102 ; 03 - 3 component (CDU degrees)16360 7,0360 00000 1 DS %0 ; 04 - spare16361 7,0361 00000 1 DS %0 ; 05 - spare16362 7,0362 00000 1 DS %0 ; 06 - spare16363 7,0363 00000 1 DS %0 ; 07 - spare16364 7,0364 00000 1 DS %0 ; 08 - spare16365 7,0365 04000 0 DS %04000 ; 09 - 3 component, octal only16366 7,0366 00000 1 DS %0 ; 10 - spare16367 7,0367 00000 1 DS %0 ; 11 - spare16370 7,0370 00000 1 DS %0 ; 12 - spare16371 7,0371 00000 1 DS %0 ; 13 - spare16372 7,0372 00000 1 DS %0 ; 14 - spare16373 7,0373 00000 1 DS %0 ; 15 - 1 component, octal only16374 7,0374 00000 1 DS %0 ; 16 - spare16375 7,0375 00000 1 DS %0 ; 17 - spare

Page 551: Apollo Guidance Computer AGC

16376 7,0376 00000 1 DS %0 ; 18 - spare16377 7,0377 00000 1 DS %0 ; 19 - spare16400 7,0400 00000 1 DS %0 ; 20 - spare16401 7,0401 00000 1 DS %0 ; 21 - spare16402 7,0402 00000 1 DS %0 ; 22 - spare16403 7,0403 00000 1 DS %0 ; 23 - spare16404 7,0404 00000 1 DS %0 ; 24 - spare16405 7,0405 00000 1 DS %0 ; 25 - spare16406 7,0406 04000 0 DS %04000 ; 26 - 3 component, octal only16407 7,0407 00000 1 DS %0 ; 27 - spare16410 7,0410 00000 1 DS %0 ; 28 - spare16411 7,0411 00000 1 DS %0 ; 29 - spare16412 7,0412 00000 1 DS %0 ; 30 - spare16413 7,0413 00000 1 DS %0 ; 31 - spare16414 7,0414 00000 1 DS %0 ; 32 - spare16415 7,0415 00000 1 DS %0 ; 33 - spare16416 7,0416 00000 1 DS %0 ; 34 - spare16417 7,0417 00000 1 DS %0 ; 35 - spare16420 7,0420 24400 0 DS %24400 ; 36 - 3 component, HMS, (dec only)16421 7,0421 00000 1 DS %0 ; 37 - spare16422 7,0422 00000 1 DS %0 ; 38 - spare16423 7,0423 00000 1 DS %0 ; 39 - spare ; end of normal nouns ; start of mixed nouns 16424 7,0424 00000 1 DS %0 ; 40 - spare16425 7,0425 00000 1 DS %0 ; 41 - spare16426 7,0426 00000 1 DS %0 ; 42 - spare16427 7,0427 00000 1 DS %0 ; 43 - spare16430 7,0430 00000 1 DS %0 ; 44 - spare16431 7,0431 00000 1 DS %0 ; 45 - spare16432 7,0432 00000 1 DS %0 ; 46 - spare16433 7,0433 00000 1 DS %0 ; 47 - spare16434 7,0434 00000 1 DS %0 ; 48 - spare16435 7,0435 00000 1 DS %0 ; 49 - spare16436 7,0436 00000 1 DS %0 ; 50 - spare16437 7,0437 00000 1 DS %0 ; 51 - spare16440 7,0440 00000 1 DS %0 ; 52 - spare16441 7,0441 00000 1 DS %0 ; 53 - spare16442 7,0442 00000 1 DS %0 ; 54 - spare16443 7,0443 00000 1 DS %0 ; 55 - spare16444 7,0444 00000 1 DS %0 ; 56 - spare16445 7,0445 00000 1 DS %0 ; 57 - spare16446 7,0446 00000 1 DS %0 ; 58 - spare16447 7,0447 00000 1 DS %0 ; 59 - spare16450 7,0450 00000 1 DS %0 ; 60 - spare16451 7,0451 00000 1 DS %0 ; 61 - spare16452 7,0452 00000 1 DS %0 ; 62 - spare16453 7,0453 00000 1 DS %0 ; 63 - spare16454 7,0454 00000 1 DS %0 ; 64 - spare16455 7,0455 00000 1 DS %0 ; 65 - spare16456 7,0456 00000 1 DS %0 ; 66 - spare16457 7,0457 00000 1 DS %0 ; 67 - spare16460 7,0460 00000 1 DS %0 ; 68 - spare16461 7,0461 00000 1 DS %0 ; 69 - spare16462 7,0462 00000 1 DS %0 ; 70 - spare16463 7,0463 00000 1 DS %0 ; 71 - spare16464 7,0464 00000 1 DS %0 ; 72 - spare16465 7,0465 00000 1 DS %0 ; 73 - spare16466 7,0466 00000 1 DS %0 ; 74 - spare16467 7,0467 00000 1 DS %0 ; 75 - spare16470 7,0470 00000 1 DS %0 ; 76 - spare16471 7,0471 00000 1 DS %0 ; 77 - spare16472 7,0472 00000 1 DS %0 ; 78 - spare16473 7,0473 00000 1 DS %0 ; 79 - spare16474 7,0474 00000 1 DS %0 ; 80 - spare16475 7,0475 00000 1 DS %0 ; 81 - spare16476 7,0476 00000 1 DS %0 ; 82 - spare16477 7,0477 00000 1 DS %0 ; 83 - spare16500 7,0500 00000 1 DS %0 ; 84 - spare16501 7,0501 00000 1 DS %0 ; 85 - spare16502 7,0502 00000 1 DS %0 ; 86 - spare16503 7,0503 00000 1 DS %0 ; 87 - spare16504 7,0504 00000 1 DS %0 ; 88 - spare16505 7,0505 00000 1 DS %0 ; 89 - spare16506 7,0506 00000 1 DS %0 ; 90 - spare16507 7,0507 00000 1 DS %0 ; 91 - spare16510 7,0510 00000 1 DS %0 ; 92 - spare16511 7,0511 00000 1 DS %0 ; 93 - spare16512 7,0512 00000 1 DS %0 ; 94 - spare16513 7,0513 00000 1 DS %0 ; 95 - spare16514 7,0514 00000 1 DS %0 ; 96 - spare16515 7,0515 00000 1 DS %0 ; 97 - spare16516 7,0516 00000 1 DS %0 ; 98 - spare16517 7,0517 00000 1 DS %0 ; 99 - spare ; end of mixed nouns

Page 552: Apollo Guidance Computer AGC

;-------------------------------------------------------------------------- ; SCALE FACTOR INPUT TABLE (SFINTAB) ; Indexed by SF constant code number x 2 PPPPP (0-19 decimal; 0-23 octal) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.272. ;-------------------------------------------------------------------------- SFINTAB EQU * 16520 7,0520 00006 1 DS %00006 ; 00 - whole, DP time (sec)16521 7,0521 03240 1 DS %03240 ; 00 16522 7,0522 00000 1 DS %00000 ; 01 - spare16523 7,0523 00000 1 DS %00000 ; 01 16524 7,0524 00000 1 DS %00000 ; 02 - CDU degrees, Y optics degrees16525 7,0525 00000 1 DS %00000 ; 02 (SFCONs in DEGINSF, OPTDEGIN 16526 7,0526 00000 1 DS %00000 ; 0316527 7,0527 00000 1 DS %00000 ; 03 16530 7,0530 00000 1 DS %00000 ; 0416531 7,0531 00000 1 DS %00000 ; 04 16532 7,0532 00000 1 DS %00000 ; 0516533 7,0533 00000 1 DS %00000 ; 05 16534 7,0534 00000 1 DS %00000 ; 0616535 7,0535 00000 1 DS %00000 ; 06 16536 7,0536 00000 1 DS %00000 ; 0716537 7,0537 00000 1 DS %00000 ; 07 16540 7,0540 00000 1 DS %00000 ; 1016541 7,0541 00000 1 DS %00000 ; 10 16542 7,0542 00000 1 DS %00000 ; 1116543 7,0543 00000 1 DS %00000 ; 11 16544 7,0544 00000 1 DS %00000 ; 1216545 7,0545 00000 1 DS %00000 ; 12 16546 7,0546 00000 1 DS %00000 ; 1316547 7,0547 00000 1 DS %00000 ; 13 16550 7,0550 00000 1 DS %00000 ; 1416551 7,0551 00000 1 DS %00000 ; 14 16552 7,0552 00000 1 DS %00000 ; 1516553 7,0553 00000 1 DS %00000 ; 15 16554 7,0554 00000 1 DS %00000 ; 1616555 7,0555 00000 1 DS %00000 ; 16 16556 7,0556 00000 1 DS %00000 ; 1716557 7,0557 00000 1 DS %00000 ; 17 16560 7,0560 00000 1 DS %00000 ; 2016561 7,0561 00000 1 DS %00000 ; 20 16562 7,0562 00000 1 DS %00000 ; 2116563 7,0563 00000 1 DS %00000 ; 21 16564 7,0564 00000 1 DS %00000 ; 2216565 7,0565 00000 1 DS %00000 ; 22 16566 7,0566 00000 1 DS %00000 ; 2316567 7,0567 00000 1 DS %00000 ; 23 ;-------------------------------------------------------------------------- ; SCALE FACTOR OUTPUT TABLE (SFOUTAB) ; Indexed by SF constant code number x 2 PPPPP (0-19 decimal; 0-23 octal) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.273. ;-------------------------------------------------------------------------- SFOUTAB EQU * 16570 7,0570 05174 0 DS %05174 ; 00 - whole, DP time (sec)16571 7,0571 13261 0 DS %13261 ; 00 16572 7,0572 00000 1 DS %00000 ; 01 - spare16573 7,0573 00000 1 DS %00000 ; 01 16574 7,0574 00000 1 DS %00000 ; 02 - CDU degrees, Y optics degrees16575 7,0575 00000 1 DS %00000 ; 02 (SFCONs in DEGOURSF, OPTDEGOUT

Page 553: Apollo Guidance Computer AGC

16576 7,0576 00000 1 DS %00000 ; 0316577 7,0577 00000 1 DS %00000 ; 03 16600 7,0600 00000 1 DS %00000 ; 0416601 7,0601 00000 1 DS %00000 ; 04 16602 7,0602 00000 1 DS %00000 ; 0516603 7,0603 00000 1 DS %00000 ; 05 16604 7,0604 00000 1 DS %00000 ; 0616605 7,0605 00000 1 DS %00000 ; 06 16606 7,0606 00000 1 DS %00000 ; 0716607 7,0607 00000 1 DS %00000 ; 07 16610 7,0610 00000 1 DS %00000 ; 1016611 7,0611 00000 1 DS %00000 ; 10 16612 7,0612 00000 1 DS %00000 ; 1116613 7,0613 00000 1 DS %00000 ; 11 16614 7,0614 00000 1 DS %00000 ; 1216615 7,0615 00000 1 DS %00000 ; 12 16616 7,0616 00000 1 DS %00000 ; 1316617 7,0617 00000 1 DS %00000 ; 13 16620 7,0620 00000 1 DS %00000 ; 1416621 7,0621 00000 1 DS %00000 ; 14 16622 7,0622 00000 1 DS %00000 ; 1516623 7,0623 00000 1 DS %00000 ; 15 16624 7,0624 00000 1 DS %00000 ; 1616625 7,0625 00000 1 DS %00000 ; 16 16626 7,0626 00000 1 DS %00000 ; 1716627 7,0627 00000 1 DS %00000 ; 17 16630 7,0630 00000 1 DS %00000 ; 2016631 7,0631 00000 1 DS %00000 ; 20 16632 7,0632 00000 1 DS %00000 ; 2116633 7,0633 00000 1 DS %00000 ; 21 16634 7,0634 00000 1 DS %00000 ; 2216635 7,0635 00000 1 DS %00000 ; 22 16636 7,0636 00000 1 DS %00000 ; 2316637 7,0637 00000 1 DS %00000 ; 23 ; SCALE FACTOR INPUT ROUTINE TABLE is on pp. 342, 343 of COLOSSUS ; SCALE FACTOR OUTPUT ROUTINE TABLE is on p. 329 of COLOSSUS ;-------------------------------------------------------------------------- ; MIXED NOUN ADDRESS TABLE (IDADDTAB) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.274. ;-------------------------------------------------------------------------- ; ** currently, the table is not populated ** IDADDTAB EQU * 16640 7,0640 00000 1 DS %0 ; 40 - spare component16641 7,0641 00000 1 DS %0 ; 40 - spare component16642 7,0642 00000 1 DS %0 ; 40 - spare component 16643 7,0643 00000 1 DS %0 ; 41 - spare component16644 7,0644 00000 1 DS %0 ; 41 - spare component16645 7,0645 00000 1 DS %0 ; 41 - spare component 16646 7,0646 00000 1 DS %0 ; 42 - spare component16647 7,0647 00000 1 DS %0 ; 42 - spare component16650 7,0650 00000 1 DS %0 ; 42 - spare component 16651 7,0651 00000 1 DS %0 ; 43 - spare component16652 7,0652 00000 1 DS %0 ; 43 - spare component16653 7,0653 00000 1 DS %0 ; 43 - spare component 16654 7,0654 00000 1 DS %0 ; 44 - spare component16655 7,0655 00000 1 DS %0 ; 44 - spare component16656 7,0656 00000 1 DS %0 ; 44 - spare component 16657 7,0657 00000 1 DS %0 ; 45 - spare component

Page 554: Apollo Guidance Computer AGC

16660 7,0660 00000 1 DS %0 ; 45 - spare component16661 7,0661 00000 1 DS %0 ; 45 - spare component 16662 7,0662 00000 1 DS %0 ; 46 - spare component16663 7,0663 00000 1 DS %0 ; 46 - spare component16664 7,0664 00000 1 DS %0 ; 46 - spare component 16665 7,0665 00000 1 DS %0 ; 47 - spare component16666 7,0666 00000 1 DS %0 ; 47 - spare component16667 7,0667 00000 1 DS %0 ; 47 - spare component 16670 7,0670 00000 1 DS %0 ; 48 - spare component16671 7,0671 00000 1 DS %0 ; 48 - spare component16672 7,0672 00000 1 DS %0 ; 48 - spare component 16673 7,0673 00000 1 DS %0 ; 49 - spare component16674 7,0674 00000 1 DS %0 ; 49 - spare component16675 7,0675 00000 1 DS %0 ; 49 - spare component 16676 7,0676 00000 1 DS %0 ; 50 - spare component16677 7,0677 00000 1 DS %0 ; 50 - spare component16700 7,0700 00000 1 DS %0 ; 50 - spare component 16701 7,0701 00000 1 DS %0 ; 51 - spare component16702 7,0702 00000 1 DS %0 ; 51 - spare component16703 7,0703 00000 1 DS %0 ; 51 - spare component 16704 7,0704 00000 1 DS %0 ; 52 - spare component16705 7,0705 00000 1 DS %0 ; 52 - spare component16706 7,0706 00000 1 DS %0 ; 52 - spare component 16707 7,0707 00000 1 DS %0 ; 53 - spare component16710 7,0710 00000 1 DS %0 ; 53 - spare component16711 7,0711 00000 1 DS %0 ; 53 - spare component 16712 7,0712 00000 1 DS %0 ; 54 - spare component16713 7,0713 00000 1 DS %0 ; 54 - spare component16714 7,0714 00000 1 DS %0 ; 54 - spare component 16715 7,0715 00000 1 DS %0 ; 55 - spare component16716 7,0716 00000 1 DS %0 ; 55 - spare component16717 7,0717 00000 1 DS %0 ; 55 - spare component 16720 7,0720 00000 1 DS %0 ; 56 - spare component16721 7,0721 00000 1 DS %0 ; 56 - spare component16722 7,0722 00000 1 DS %0 ; 56 - spare component 16723 7,0723 00000 1 DS %0 ; 57 - spare component16724 7,0724 00000 1 DS %0 ; 57 - spare component16725 7,0725 00000 1 DS %0 ; 57 - spare component 16726 7,0726 00000 1 DS %0 ; 58 - spare component16727 7,0727 00000 1 DS %0 ; 58 - spare component16730 7,0730 00000 1 DS %0 ; 58 - spare component 16731 7,0731 00000 1 DS %0 ; 59 - spare component16732 7,0732 00000 1 DS %0 ; 59 - spare component16733 7,0733 00000 1 DS %0 ; 59 - spare component 16734 7,0734 00000 1 DS %0 ; 60 - spare component16735 7,0735 00000 1 DS %0 ; 60 - spare component16736 7,0736 00000 1 DS %0 ; 60 - spare component 16737 7,0737 00000 1 DS %0 ; 61 - spare component16740 7,0740 00000 1 DS %0 ; 61 - spare component16741 7,0741 00000 1 DS %0 ; 61 - spare component 16742 7,0742 00000 1 DS %0 ; 62 - spare component16743 7,0743 00000 1 DS %0 ; 62 - spare component16744 7,0744 00000 1 DS %0 ; 62 - spare component 16745 7,0745 00000 1 DS %0 ; 63 - spare component16746 7,0746 00000 1 DS %0 ; 63 - spare component16747 7,0747 00000 1 DS %0 ; 63 - spare component 16750 7,0750 00000 1 DS %0 ; 64 - spare component16751 7,0751 00000 1 DS %0 ; 64 - spare component16752 7,0752 00000 1 DS %0 ; 64 - spare component 16753 7,0753 00000 1 DS %0 ; 65 - spare component16754 7,0754 00000 1 DS %0 ; 65 - spare component16755 7,0755 00000 1 DS %0 ; 65 - spare component 16756 7,0756 00000 1 DS %0 ; 66 - spare component16757 7,0757 00000 1 DS %0 ; 66 - spare component16760 7,0760 00000 1 DS %0 ; 66 - spare component

Page 555: Apollo Guidance Computer AGC

16761 7,0761 00000 1 DS %0 ; 67 - spare component16762 7,0762 00000 1 DS %0 ; 67 - spare component16763 7,0763 00000 1 DS %0 ; 67 - spare component 16764 7,0764 00000 1 DS %0 ; 68 - spare component16765 7,0765 00000 1 DS %0 ; 68 - spare component16766 7,0766 00000 1 DS %0 ; 68 - spare component 16767 7,0767 00000 1 DS %0 ; 69 - spare component16770 7,0770 00000 1 DS %0 ; 69 - spare component16771 7,0771 00000 1 DS %0 ; 69 - spare component 16772 7,0772 00000 1 DS %0 ; 70 - spare component16773 7,0773 00000 1 DS %0 ; 70 - spare component16774 7,0774 00000 1 DS %0 ; 70 - spare component 16775 7,0775 00000 1 DS %0 ; 71 - spare component16776 7,0776 00000 1 DS %0 ; 71 - spare component16777 7,0777 00000 1 DS %0 ; 71 - spare component 17000 7,1000 00000 1 DS %0 ; 72 - spare component17001 7,1001 00000 1 DS %0 ; 72 - spare component17002 7,1002 00000 1 DS %0 ; 72 - spare component 17003 7,1003 00000 1 DS %0 ; 73 - spare component17004 7,1004 00000 1 DS %0 ; 73 - spare component17005 7,1005 00000 1 DS %0 ; 73 - spare component 17006 7,1006 00000 1 DS %0 ; 74 - spare component17007 7,1007 00000 1 DS %0 ; 74 - spare component17010 7,1010 00000 1 DS %0 ; 74 - spare component 17011 7,1011 00000 1 DS %0 ; 75 - spare component17012 7,1012 00000 1 DS %0 ; 75 - spare component17013 7,1013 00000 1 DS %0 ; 75 - spare component 17014 7,1014 00000 1 DS %0 ; 76 - spare component17015 7,1015 00000 1 DS %0 ; 76 - spare component17016 7,1016 00000 1 DS %0 ; 76 - spare component 17017 7,1017 00000 1 DS %0 ; 77 - spare component17020 7,1020 00000 1 DS %0 ; 77 - spare component17021 7,1021 00000 1 DS %0 ; 77 - spare component 17022 7,1022 00000 1 DS %0 ; 78 - spare component17023 7,1023 00000 1 DS %0 ; 78 - spare component17024 7,1024 00000 1 DS %0 ; 78 - spare component 17025 7,1025 00000 1 DS %0 ; 79 - spare component17026 7,1026 00000 1 DS %0 ; 79 - spare component17027 7,1027 00000 1 DS %0 ; 79 - spare component 17030 7,1030 00000 1 DS %0 ; 80 - spare component17031 7,1031 00000 1 DS %0 ; 80 - spare component17032 7,1032 00000 1 DS %0 ; 80 - spare component 17033 7,1033 00000 1 DS %0 ; 81 - spare component17034 7,1034 00000 1 DS %0 ; 81 - spare component17035 7,1035 00000 1 DS %0 ; 81 - spare component 17036 7,1036 00000 1 DS %0 ; 82 - spare component17037 7,1037 00000 1 DS %0 ; 82 - spare component17040 7,1040 00000 1 DS %0 ; 82 - spare component 17041 7,1041 00000 1 DS %0 ; 83 - spare component17042 7,1042 00000 1 DS %0 ; 83 - spare component17043 7,1043 00000 1 DS %0 ; 83 - spare component 17044 7,1044 00000 1 DS %0 ; 84 - spare component17045 7,1045 00000 1 DS %0 ; 84 - spare component17046 7,1046 00000 1 DS %0 ; 84 - spare component 17047 7,1047 00000 1 DS %0 ; 85 - spare component17050 7,1050 00000 1 DS %0 ; 85 - spare component17051 7,1051 00000 1 DS %0 ; 85 - spare component 17052 7,1052 00000 1 DS %0 ; 86 - spare component17053 7,1053 00000 1 DS %0 ; 86 - spare component17054 7,1054 00000 1 DS %0 ; 86 - spare component 17055 7,1055 00000 1 DS %0 ; 87 - spare component17056 7,1056 00000 1 DS %0 ; 87 - spare component17057 7,1057 00000 1 DS %0 ; 87 - spare component 17060 7,1060 00000 1 DS %0 ; 88 - spare component17061 7,1061 00000 1 DS %0 ; 88 - spare component17062 7,1062 00000 1 DS %0 ; 88 - spare component

Page 556: Apollo Guidance Computer AGC

17063 7,1063 00000 1 DS %0 ; 89 - spare component17064 7,1064 00000 1 DS %0 ; 89 - spare component17065 7,1065 00000 1 DS %0 ; 89 - spare component 17066 7,1066 00000 1 DS %0 ; 90 - spare component17067 7,1067 00000 1 DS %0 ; 90 - spare component17070 7,1070 00000 1 DS %0 ; 90 - spare component 17071 7,1071 00000 1 DS %0 ; 91 - spare component17072 7,1072 00000 1 DS %0 ; 91 - spare component17073 7,1073 00000 1 DS %0 ; 91 - spare component 17074 7,1074 00000 1 DS %0 ; 92 - spare component17075 7,1075 00000 1 DS %0 ; 92 - spare component17076 7,1076 00000 1 DS %0 ; 92 - spare component 17077 7,1077 00000 1 DS %0 ; 93 - spare component17100 7,1100 00000 1 DS %0 ; 93 - spare component17101 7,1101 00000 1 DS %0 ; 93 - spare component 17102 7,1102 00000 1 DS %0 ; 94 - spare component17103 7,1103 00000 1 DS %0 ; 94 - spare component17104 7,1104 00000 1 DS %0 ; 94 - spare component 17105 7,1105 00000 1 DS %0 ; 95 - spare component17106 7,1106 00000 1 DS %0 ; 95 - spare component17107 7,1107 00000 1 DS %0 ; 95 - spare component 17110 7,1110 00000 1 DS %0 ; 96 - spare component17111 7,1111 00000 1 DS %0 ; 96 - spare component17112 7,1112 00000 1 DS %0 ; 96 - spare component 17113 7,1113 00000 1 DS %0 ; 97 - spare component17114 7,1114 00000 1 DS %0 ; 97 - spare component17115 7,1115 00000 1 DS %0 ; 97 - spare component 17116 7,1116 00000 1 DS %0 ; 98 - spare component17117 7,1117 00000 1 DS %0 ; 98 - spare component17120 7,1120 00000 1 DS %0 ; 98 - spare component 17121 7,1121 00000 1 DS %0 ; 99 - spare component17122 7,1122 00000 1 DS %0 ; 99 - spare component17123 7,1123 00000 1 DS %0 ; 99 - spare component ; end of mixed noun address table ;-------------------------------------------------------------------------- ; MIXED NOUN SCALE FACTOR ROUTINE TABLE (RUTMXTAB) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.278. ;-------------------------------------------------------------------------- ; ** currently, the table is not populated ** RUTMXTAB EQU * 17124 7,1124 00000 1 DS %0 ; 40 - spare17125 7,1125 00000 1 DS %0 ; 41 - spare17126 7,1126 00000 1 DS %0 ; 42 - spare17127 7,1127 00000 1 DS %0 ; 43 - spare17130 7,1130 00000 1 DS %0 ; 44 - spare17131 7,1131 00000 1 DS %0 ; 45 - spare17132 7,1132 00000 1 DS %0 ; 46 - spare17133 7,1133 00000 1 DS %0 ; 47 - spare17134 7,1134 00000 1 DS %0 ; 48 - spare17135 7,1135 00000 1 DS %0 ; 49 - spare17136 7,1136 00000 1 DS %0 ; 50 - spare17137 7,1137 00000 1 DS %0 ; 51 - spare17140 7,1140 00000 1 DS %0 ; 52 - spare17141 7,1141 00000 1 DS %0 ; 53 - spare17142 7,1142 00000 1 DS %0 ; 54 - spare17143 7,1143 00000 1 DS %0 ; 55 - spare17144 7,1144 00000 1 DS %0 ; 56 - spare17145 7,1145 00000 1 DS %0 ; 57 - spare17146 7,1146 00000 1 DS %0 ; 58 - spare17147 7,1147 00000 1 DS %0 ; 59 - spare17150 7,1150 00000 1 DS %0 ; 60 - spare17151 7,1151 00000 1 DS %0 ; 61 - spare17152 7,1152 00000 1 DS %0 ; 62 - spare17153 7,1153 00000 1 DS %0 ; 63 - spare17154 7,1154 00000 1 DS %0 ; 64 - spare17155 7,1155 00000 1 DS %0 ; 65 - spare17156 7,1156 00000 1 DS %0 ; 66 - spare17157 7,1157 00000 1 DS %0 ; 67 - spare17160 7,1160 00000 1 DS %0 ; 68 - spare17161 7,1161 00000 1 DS %0 ; 69 - spare17162 7,1162 00000 1 DS %0 ; 70 - spare

Page 557: Apollo Guidance Computer AGC

17163 7,1163 00000 1 DS %0 ; 71 - spare17164 7,1164 00000 1 DS %0 ; 72 - spare17165 7,1165 00000 1 DS %0 ; 73 - spare17166 7,1166 00000 1 DS %0 ; 74 - spare17167 7,1167 00000 1 DS %0 ; 75 - spare17170 7,1170 00000 1 DS %0 ; 76 - spare17171 7,1171 00000 1 DS %0 ; 77 - spare17172 7,1172 00000 1 DS %0 ; 78 - spare17173 7,1173 00000 1 DS %0 ; 79 - spare17174 7,1174 00000 1 DS %0 ; 80 - spare17175 7,1175 00000 1 DS %0 ; 81 - spare17176 7,1176 00000 1 DS %0 ; 82 - spare17177 7,1177 00000 1 DS %0 ; 83 - spare17200 7,1200 00000 1 DS %0 ; 84 - spare17201 7,1201 00000 1 DS %0 ; 85 - spare17202 7,1202 00000 1 DS %0 ; 86 - spare17203 7,1203 00000 1 DS %0 ; 87 - spare17204 7,1204 00000 1 DS %0 ; 88 - spare17205 7,1205 00000 1 DS %0 ; 89 - spare17206 7,1206 00000 1 DS %0 ; 90 - spare17207 7,1207 00000 1 DS %0 ; 91 - spare17210 7,1210 00000 1 DS %0 ; 92 - spare17211 7,1211 00000 1 DS %0 ; 93 - spare17212 7,1212 00000 1 DS %0 ; 94 - spare17213 7,1213 00000 1 DS %0 ; 95 - spare17214 7,1214 00000 1 DS %0 ; 96 - spare17215 7,1215 00000 1 DS %0 ; 97 - spare17216 7,1216 00000 1 DS %0 ; 98 - spare17217 7,1217 00000 1 DS %0 ; 99 - spare ; end of mixed noun scale factor routine table BANK42_4 EQU * ; extended verb tables ORG BANK43_1 INCL bank43_1.asm ; COLOSSUS pp. 230-232 ;========================================================================== ; DISPLAY ROUTINES (file:bank43_1.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp. 230. ;========================================================================== ;-------------------------------------------------------------------------- ; GOEXTVB -- EXTENDED VERBS ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p.230. ;-------------------------------------------------------------------------- GOEXTVB EQU * 20000 10,0000 2 0,0130 1 INDEX MPAC ; verb-40 is in MPAC20001 10,0001 0 10,6002 0 TC LST2FAN ; fan as before LST2FAN EQU * 20002 10,0002 0 10,6076 0 TC ALM_END ; VB40 - spare20003 10,0003 0 10,6076 0 TC ALM_END ; VB41 - spare20004 10,0004 0 10,6076 0 TC ALM_END ; VB42 - spare20005 10,0005 0 10,6076 0 TC ALM_END ; VB43 - spare20006 10,0006 0 10,6076 0 TC ALM_END ; VB44 - spare20007 10,0007 0 10,6076 0 TC ALM_END ; VB45 - spare20010 10,0010 0 10,6076 0 TC ALM_END ; VB46 - spare20011 10,0011 0 10,6076 0 TC ALM_END ; VB47 - spare20012 10,0012 0 10,6076 0 TC ALM_END ; VB48 - spare20013 10,0013 0 10,6076 0 TC ALM_END ; VB49 - spare20014 10,0014 0 10,6076 0 TC ALM_END ; VB50 - spare20015 10,0015 0 10,6076 0 TC ALM_END ; VB51 - spare20016 10,0016 0 10,6076 0 TC ALM_END ; VB52 - spare20017 10,0017 0 10,6076 0 TC ALM_END ; VB53 - spare20020 10,0020 0 10,6076 0 TC ALM_END ; VB54 - spare20021 10,0021 0 10,6076 0 TC ALM_END ; VB55 - spare20022 10,0022 0 10,6076 0 TC ALM_END ; VB56 - spare20023 10,0023 0 10,6076 0 TC ALM_END ; VB57 - spare20024 10,0024 0 10,6076 0 TC ALM_END ; VB58 - spare20025 10,0025 0 10,6076 0 TC ALM_END ; VB59 - spare20026 10,0026 0 10,6076 0 TC ALM_END ; VB60 - spare20027 10,0027 0 10,6076 0 TC ALM_END ; VB61 - spare20030 10,0030 0 10,6076 0 TC ALM_END ; VB62 - spare20031 10,0031 0 10,6076 0 TC ALM_END ; VB63 - spare20032 10,0032 0 10,6076 0 TC ALM_END ; VB64 - spare20033 10,0033 0 10,6076 0 TC ALM_END ; VB65 - spare20034 10,0034 0 10,6076 0 TC ALM_END ; VB66 - spare20035 10,0035 0 10,6076 0 TC ALM_END ; VB67 - spare20036 10,0036 0 10,6076 0 TC ALM_END ; VB68 - spare20037 10,0037 0 10,6076 0 TC ALM_END ; VB69 - spare20040 10,0040 0 10,6076 0 TC ALM_END ; VB70 - spare

Page 558: Apollo Guidance Computer AGC

20041 10,0041 0 10,6076 0 TC ALM_END ; VB71 - spare20042 10,0042 0 10,6076 0 TC ALM_END ; VB72 - spare20043 10,0043 0 10,6076 0 TC ALM_END ; VB73 - spare20044 10,0044 0 10,6076 0 TC ALM_END ; VB74 - spare20045 10,0045 0 10,6076 0 TC ALM_END ; VB75 - spare20046 10,0046 0 10,6076 0 TC ALM_END ; VB76 - spare20047 10,0047 0 10,6076 0 TC ALM_END ; VB77 - spare20050 10,0050 0 10,6076 0 TC ALM_END ; VB78 - spare20051 10,0051 0 10,6076 0 TC ALM_END ; VB79 - spare20052 10,0052 0 10,6076 0 TC ALM_END ; VB80 - spare20053 10,0053 0 10,6076 0 TC ALM_END ; VB81 - spare20054 10,0054 0 10,6076 0 TC ALM_END ; VB82 - spare20055 10,0055 0 10,6076 0 TC ALM_END ; VB83 - spare20056 10,0056 0 10,6076 0 TC ALM_END ; VB84 - spare20057 10,0057 0 10,6076 0 TC ALM_END ; VB85 - spare20060 10,0060 0 10,6076 0 TC ALM_END ; VB86 - spare20061 10,0061 0 10,6076 0 TC ALM_END ; VB87 - spare20062 10,0062 0 10,6076 0 TC ALM_END ; VB88 - spare20063 10,0063 0 10,6076 0 TC ALM_END ; VB89 - spare20064 10,0064 0 10,6076 0 TC ALM_END ; VB90 - spare20065 10,0065 0 10,6076 0 TC ALM_END ; VB91 - spare20066 10,0066 0 10,6076 0 TC ALM_END ; VB92 - spare20067 10,0067 0 10,6076 0 TC ALM_END ; VB93 - spare20070 10,0070 0 10,6076 0 TC ALM_END ; VB94 - spare20071 10,0071 0 10,6076 0 TC ALM_END ; VB95 - spare20072 10,0072 0 10,6076 0 TC ALM_END ; VB96 - spare20073 10,0073 0 10,6076 0 TC ALM_END ; VB97 - spare20074 10,0074 0 10,6076 0 TC ALM_END ; VB98 - spare20075 10,0075 0 10,6076 0 TC ALM_END ; VB99 - spare ALM_END EQU * 20076 10,0076 0 2,4701 0 TC FALTON ; turn on operator error light20077 10,0077 0 1,3653 1 GOPIN TC POSTJUMP 20100 10,0100 05067 0 FCADR PINBRNCH BANK43_2 EQU * ;-------------------------------------------------------------------------- ; TEST JOBS & TASKS ;-------------------------------------------------------------------------- ORG BANKFF_6 ;-------------------------------------------------------------------------- ; MAJOR MODES ;-------------------------------------------------------------------------- ORG BANK11 ;-------------------------------------------------------------------------- ; P00 CMC IDLE PROGRAM ; ; Does nothing ;-------------------------------------------------------------------------- P00 EQU * ; Start any jobs or tasks needed at AGC initialization. 22000 11,0000 3 11,6004 0 CAF time1 ; add a test task22001 11,0001 0 1,2232 0 TC WAITLIST 22002 11,0002 22005 1 CADR task1 ; 14-bit task address22003 11,0003 0 1,2723 0 TC ENDOFJOB ; TEST CODE - task started by P00 22004 11,0004 01750 1 time1 DS 1000 ; 10 seconds task1 EQU * 22005 11,0005 3 11,6011 1 XCH prio1 ; job priority22006 11,0006 0 1,3162 1 TC NOVAC 22007 11,0007 22012 1 CADR job1 ; 14 bit job address 22010 11,0010 0 1,2413 0 TC TASKOVER ; TEST CODE - job started by task 22011 11,0011 00003 1 prio1 DS %3 ; lowest priority job1 EQU * 22012 11,0012 3 1,2050 0 CAF ZERO

Page 559: Apollo Guidance Computer AGC

22013 11,0013 6 0,0053 1 AD %53 22014 11,0014 6 1,2051 1 AD ONE 22015 11,0015 5 0,0053 1 TS %53 ; incr data at this address22016 11,0016 0 1,2723 0 TC ENDOFJOB ;-------------------------------------------------------------------------- ; P01 DEMO PROGRAM ; ; Calls pinball: verb 1, noun 4. ;-------------------------------------------------------------------------- 22017 11,0017 00204 1 nvcode1 DS %0204 ; verb 01, noun 0422020 11,0020 22024 1 restart1_addr DS P01_restart 22021 11,0021 00042 1 tcadr1 DS %42 P01 EQU * 22022 11,0022 3 11,6021 1 CAF tcadr1 ; load 'machine address to be specified'22023 11,0023 5 0,0132 1 TS MPAC+2 P01_restart EQU * 22024 11,0024 3 11,6017 1 CAF nvcode1 22025 11,0025 0 2,4503 0 TC NVSUB 22026 11,0026 0 11,6030 1 TC *+2 ; display busy22027 11,0027 0 1,2723 0 TC ENDOFJOB ; execution of verb/noun succeeded 22030 11,0030 3 11,6020 0 CAF restart1_addr 22031 11,0031 0 2,5001 0 TC NVSUBUSY ; go to sleep until display released 22032 11,0032 0 1,2723 0 TC ENDOFJOB ; error: another job is already waiting ;-------------------------------------------------------------------------- ; P02 DEMO PROGRAM ; ; Calls pinball: verb 21, noun 2. ; ; Sleeps if DSKY is busy until KEYREL. Executes verb 21, noun 2 to do ; an external load. Then it sleeps with ENDIDLE until the user loads ; the data or terminatest the load with PROCEED or TERMINATE. ; NOTE: routines that call ENDIDLE must be in fixed-switchable memory ;-------------------------------------------------------------------------- 22033 11,0033 05202 1 nvcode2 DS %05202 ; verb 21, noun 0222034 11,0034 22040 0 restart2_addr DS P02_restart 22035 11,0035 00042 1 tcadr2 DS %42 P02 EQU * 22036 11,0036 3 11,6035 1 CAF tcadr2 22037 11,0037 5 0,0132 1 TS MPAC+2 P02_restart EQU * 22040 11,0040 3 11,6033 1 CAF nvcode2 22041 11,0041 0 2,4503 0 TC NVSUB 22042 11,0042 0 11,6044 1 TC *+2 ; display busy22043 11,0043 0 11,6047 1 TC P02_wait ; execution of verb/noun succeeded 22044 11,0044 3 11,6034 0 CAF restart2_addr 22045 11,0045 0 2,5001 0 TC NVSUBUSY ; go to sleep until display released22046 11,0046 0 1,2723 0 TC ENDOFJOB ; another job is already sleeping P02_wait EQU * 22047 11,0047 0 2,4541 0 TC ENDIDLE 22050 11,0050 0 11,6060 1 TC P02_ter ; terminate22051 11,0051 0 11,6055 1 TC P02_pwd ; proceed without data22052 11,0052 3 1,2051 1 CAF ONE ; data in22053 11,0053 5 0,0043 0 TS %43 ; set loc=122054 11,0054 0 1,2723 0 TC ENDOFJOB P02_pwd EQU * ; proceed without data22055 11,0055 3 1,2052 1 CAF TWO 22056 11,0056 5 0,0043 0 TS %43 ; set loc=222057 11,0057 0 1,2723 0 TC ENDOFJOB P02_ter EQU * ; terminate22060 11,0060 3 1,2053 0 CAF THREE 22061 11,0061 5 0,0043 0 TS %43 ; set loc=322062 11,0062 0 1,2723 0 TC ENDOFJOB ;-------------------------------------------------------------------------- ; P03 DEMO PROGRAM ;

Page 560: Apollo Guidance Computer AGC

; Nearly identical to P02, except that the job does not go to sleep ; waiting for the load with ENDIDLE. Instead, it busy-waits on LOADSTAT. ; NOTE: routines that call ENDIDLE must be in fixed-switchable memory ;-------------------------------------------------------------------------- 22063 11,0063 05202 1 nvcode3 DS %05202 ; verb 21, noun 0222064 11,0064 22070 0 restart3_addr DS P03_restart 22065 11,0065 00042 1 tcadr3 DS %42 P03 EQU * 22066 11,0066 3 11,6065 1 CAF tcadr3 22067 11,0067 5 0,0132 1 TS MPAC+2 P03_restart EQU * 22070 11,0070 3 11,6063 1 CAF nvcode3 22071 11,0071 0 2,4503 0 TC NVSUB 22072 11,0072 0 11,6074 1 TC *+2 ; display busy22073 11,0073 0 11,6077 1 TC P03_wait ; execution of verb/noun succeeded 22074 11,0074 3 11,6064 0 CAF restart3_addr 22075 11,0075 0 2,5001 0 TC NVSUBUSY ; go to sleep until display released22076 11,0076 0 1,2723 0 TC ENDOFJOB ; another job is already sleeping P03_wait EQU * 22077 11,0077 1 0,0503 0 CCS LOADSTAT 22100 11,0100 0 11,6115 1 TC P03_pwd ; >0, verb "proceed w/o data" has been keyedin22101 11,0101 0 11,6107 1 TC P03_yield ; +0, waiting for data22102 11,0102 0 11,6120 1 TC P03_ter ; <0, verb "terminate" has been keyed in22103 11,0103 3 0,0000 1 NOOP ; -0, load has been completed 22104 11,0104 3 1,2051 1 CAF ONE ; data in22105 11,0105 5 0,0043 0 TS %43 ; set loc=122106 11,0106 0 1,2723 0 TC ENDOFJOB P03_yield EQU * 22107 11,0107 3 1,2051 1 CAF ONE 22110 11,0110 6 0,0043 0 AD %43 22111 11,0111 5 0,0043 0 TS %43 ; incr loc while busy-waiting 22112 11,0112 1 0,0307 1 CCS newJob ; yield to higher priority job?22113 11,0113 0 1,2733 1 TC CHANG1 ; yes22114 11,0114 0 11,6077 1 TC P03_wait ; no, keep busy-waiting P03_pwd EQU * ; proceed without data22115 11,0115 3 1,2052 1 CAF TWO 22116 11,0116 5 0,0043 0 TS %43 ; set loc=222117 11,0117 0 1,2723 0 TC ENDOFJOB P03_ter EQU * ; terminate22120 11,0120 3 1,2053 0 CAF THREE 22121 11,0121 5 0,0043 0 TS %43 ; set loc=322122 11,0122 0 1,2723 0 TC ENDOFJOB ;-------------------------------------------------------------------------- ; P04 DEMO PROGRAM ; ; Calls pinball: monitor verb 11, noun 04. ;-------------------------------------------------------------------------- 22123 11,0123 02604 1 nvcode4 DS %02604 ; verb 11, noun 0422124 11,0124 22131 1 restart4_addr DS P04_restart 22125 11,0125 00042 1 tcadr4 DS %42 ;mon_option DS %6 22126 11,0126 02206 1 mon_option DS %2206 P04 EQU * 22127 11,0127 3 11,6125 1 CAF tcadr4 ; load 'machine address to be specified'22130 11,0130 5 0,0132 1 TS MPAC+2 P04_restart EQU * 22131 11,0131 3 11,6126 1 CAF mon_option ; paste verb 09, blank R2, R322132 11,0132 5 0,0564 0 TS NVSUB_L 22133 11,0133 3 11,6123 1 CAF nvcode4 22134 11,0134 0 2,4507 1 TC NVMONOPT ; was NVSUB 22135 11,0135 0 11,6137 1 TC *+2 ; display busy22136 11,0136 0 1,2723 0 TC ENDOFJOB ; execution of verb/noun succeeded 22137 11,0137 3 11,6124 0 CAF restart4_addr 22140 11,0140 0 2,5001 0 TC NVSUBUSY ; go to sleep until display released

Page 561: Apollo Guidance Computer AGC

22141 11,0141 0 1,2723 0 TC ENDOFJOB ; error: another job is already waiting ;-------------------------------------------------------------------------- ; P78 DEMO PROGRAM ; ;-------------------------------------------------------------------------- P78 EQU * 22142 11,0142 3 1,2050 0 CAF ZERO 22143 11,0143 6 0,0051 0 AD %51 22144 11,0144 6 1,2051 1 AD ONE 22145 11,0145 5 0,0051 0 TS %51 ; incr data at this address22146 11,0146 0 1,2723 0 TC ENDOFJOB ;-------------------------------------------------------------------------- ; P79 DEMO PROGRAM ; ;-------------------------------------------------------------------------- P79 EQU * 22147 11,0147 3 1,2050 0 CAF ZERO 22150 11,0150 6 0,0052 0 AD %52 22151 11,0151 6 1,2051 1 AD ONE 22152 11,0152 5 0,0052 0 TS %52 ; incr data at this address22153 11,0153 0 1,2723 0 TC ENDOFJOB

Assembly complete. Errors = 0

Symbol table:BANK0 000057 MAXTASK 000007 MAXVAL 037777 MAXDELAY 027340 MAXTIMEOUT 010440 TSKTIME 000000 TSKADDR 000001 TRECSZ 000002 WL_taskList 000057 WL_IN_saveQ 000075 WL_IN_taskPtr 000076 WL_IN_loopCnt 000077 WL_AT_saveQ 000100 WL_AT_taskPtr 000101 WL_AT_newTime 000102 WL_AT_timeLeft 000103 WL_AT_loopCnt 000104 WL_T3_saveQ 000105 WL_T3_oldBank 000106 WL_ST_saveQ 000107 WL_ST_taskPtr 000110 WL_ST_newTime 000111 WL_ST_loopCnt 000112 WL_RT_saveQ 000113 WL_RT_runAddr 000114 WL_RM_saveQ 000115 WL_RM_taskPtr 000116 WL_RM_taskPtr2 000117 WL_RM_loopCnt 000120 WL_RM_retval 000121 WL_IS_newTime 000122 WL_IS_newAddr 000123 WL_IS_saveQ 000124 WL_IS_taskPtr 000125 WL_IS_taskPtr2 000126 WL_IS_loopCnt 000127 MAXJOBS 000007 JRECSZ 000015 EX_currentJob 000130 MPAC 000130 MODE 000137 LOC 000140 BANKSET 000141 PUSHLOC 000142 PRIORITY 000143 JOBPRIOBASE 000144 JREC0 000145 JREC1 000162 JREC2 000177 JREC3 000214 JREC4 000231 JREC5 000246 JREC6 000263 EX_jobList 000300 LOCCTR 000300 CHGJOB 000001 KEEPJOB 000000 newJob 000307 EX_JW_saveQ 000310 EX_JW_loopCnt 000311 EX_JW_CADR 000312 EX_JW_foundit 000313 EX_JW_jobPtr 000314 EX_JW_jobPtr2 000315 EX_JW_fndIndx 000316 EX_AJ_saveQ 000317 EX_AJ_loopCnt 000320 EX_AJ_jobPrio 000321 EX_AJ_jobPtr 000322 EX_AJ_field 000323 EX_AJ_findx 000324 EX_IN_saveQ 000325 EX_IN_loopCnt 000326 EX_IN_jobPtr 000327 EX_IN_recIndex 000330 EX_IN_field 000331 EX_IN_findx 000332 EX_MN_runAddr 000333 EX_MN_field 000334 EX_MN_findx 000335 EX_RM_saveQ 000336 EX_RM_jobPtr 000337 EX_RM_jobPtr2 000340 EX_RM_savePtr 000341 EX_RM_loopCnt 000342 EX_RM_retval 000343 EX_RM_field 000344 EX_RM_findx 000345 EX_IS_newPrio 000346 EX_IS_newPrioB 000347 EX_IS_newLoc 000350 EX_IS_saveQ 000351 EX_IS_jobPtr 000352 EX_IS_jobPtr2 000353 EX_IS_loopCnt 000354 FLAGWRD5 000355 ITEMP1 000356 WAITEXIT 000356 EXECTEM1 000356 ITEMP2 000357 WAITBANK 000357 EXECTEM2 000357 ITEMP3 000360 RUPTSTOR 000360 WAITADR 000360 NEWPRIO 000360 ITEMP4 000361 WAITTEMP 000361 ITEMP5 000362 NEWLOC 000362 ITEMP6 000363 NEWLOCP1 000363 NEWJOB 000364 RUPTREG1 000365 RUPTREG2 000366 RUPTREG3 000367 RUPTREG4 000370 KEYTEMP1 000370 DSRUPTEM 000370 STATE 000371 FLAGFILL 000405 EMDOT 000405 STATEXIT 000407 INTB15P 000411 DSEXIT 000411 EXITEM 000411 BLANKRET 000411 INTBIT15 000412 WRDRET 000412 WDRET 000412 DECRET 000412 _2122REG 000412 ADDRWD 000413 POLISH 000414 UPDATRET 000414 CHAR 000414 ERCNT 000414 DECOUNT 000414 FIXLOC 000415 OVFIND 000416 VBUF 000417 SGNON 000417 NOUNTEM 000417 DISTEM 000417 DECTEM 000417 SGNOFF 000420 NVTEMP 000420 SFTEMP1 000420 HITEMIN 000420 CODE 000421 SFTEMP2 000421 LOWTEMIN 000421 MIXTEMP 000422 SIGNRET 000422 BUF 000425 BUF2 000430 INDEXLOC 000425 SWWORD 000425 SWBIT 000426 MPTEMP 000432 DMPNTEMP 000432 DOTINC 000433

Page 562: Apollo Guidance Computer AGC

DVSIGN 000433 ESCAPE 000433 ENTRET 000433 DOTRET 000434 DVNORMCT 000434 ESCAPE2 000434 WDCNT 000434 INREL 000434 MATINC 000435 MAXDVSW 000435 POLYCNT 000435 DSPMMTEM 000435 MIXBR 000435 TEM1 000436 POLYRET 000436 DSREL 000436 TEM2 000437 DSMAG 000437 IDADDTEM 000437 TEM3 000440 COUNT 000440 TEM4 000441 LSTPTR 000441 RELRET 000441 FREERET 000441 DSPWDRET 000441 SEPSCRET 000441 SEPMNRET 000441 TEM5 000442 NOUNADD 000442 NNADTEM 000443 NNTYPTEM 000444 IDAD1TEM 000445 IDAD2TEM 000446 IDAD3TEM 000447 RUTMXTEM 000450 DEXDEX 000437 DEX1 000440 DEX2 000441 RTNSAVER 000442 TERM1TMP 000430 RESTREG 000451 NVWORD 000452 MARXNV 000453 NVSAVE 000454 CADRFLSH 000455 CADRMARK 000456 TEMPFLSH 000457 FAILREG 000460 MINDEX 000463 MMNUMBER 000464 DSPCNT 000465 DSPCOUNT 000466 DECBRNCH 000467 VERBREG 000470 NOUNREG 000471 XREG 000472 YREG 000473 ZREG 000474 XREGLP 000475 YREGLP 000476 HITEMOUT 000476 ZREGLP 000477 LOTEMOUT 000477 MODREG 000500 DSPLOCK 000501 REQRET 000502 LOADSTAT 000503 CLPASS 000504 NOUT 000505 NOUNCADR 000506 MONSAVE 000507 MONSAVE1 000510 MONSAVE2 000511 DSPTAB 000512 NVQTEM 000526 NVBNKTEM 000527 VERBSAVE 000530 CADRSTOR 000531 DSPLIST 000532 EXTVRACT 000533 DSPTEM1 000534 DSPTEM2 000537 DSPTEMX 000537 NORMTEM1 000534 OPTIONX 000537 MMTEMP 000542 DSRUPTSW 000543 T4RET 000544 DSPOUTRET 000545 DK_IN_saveQ 000546 LXCH_LPRET 000547 LXCH_A 000550 KP_MPAC 000551 DPTEST_A 000552 DPTEST_Q 000553 REQ_Q 000554 SETNCADR_Q 000555 ALLDC_OC_Q 000556 SFRUTMIX_L 000557 SFCONUM_L 000560 BLANKSUB_Q 000561 GTSF_RET 000562 FR_RETQ 000563 NVSUB_L 000564 NVSUB_A 000565 ENDIDLE_L 000566 NBSUBSY1_L 000567 FLASHRET 000570 PASTE_TMP 000571 NEWMODEA_Q 000572 SHORTMP_A 000573 SHORTMP_OVFL 000574 SHORTMP_OVFH 000575 ADDRWD1 000576 MATH_Q 000577 PRSHRTMP_Q 000600 KEYRET 000601 SAVEQ 000602 BJBANK 000603 BJRET 000604 PJBANK 000605 PJRET 000606 PJA 000607 BCBANK 000610 BCRET 000611 BCA 000612 MBCBANK 000613 MBCRET 000614 MBCA 000615 DCBANK 000616 DCRET 000617 EXTENDER 005777 GOPROG 002000 T3RUPT 002004 ERRUPT 002010 DSRUPT 002014 KEYRUPT 002020 UPRUPT 002024 endRUPT 002030 goT3 002034 goER 002036 goDS 002037 goKEY 002041 goUP 002043 ofbit 002044 NEG0 002045 NEG1 002046 NEG2 002047 ZERO 002050 ONE 002051 TWO 002052 THREE 002053 FOUR 002054 FIVE 002055 SIX 002056 SEVEN 002057 TEN 002060 ELEVEN 002061 BIT15 002062 BIT14 002063 BIT13 002064 BIT12 002065 BIT11 002066 BIT10 002067 BIT9 002070 BIT8 002071 BIT7 002072 BIT6 002073 BIT5 002074 BIT4 002075 BIT3 002076 BIT2 002077 BIT1 002100 LOW7 002101 bankAddr 002102 lowAddr 002103 OCT1400 002104 NOUTCON 002105 POSMAX 002106 CLRMEM 002107 CLRMEM_CHK 002113 CLRMEM_WORD 002116 CLRMEM_VAL 002050 TIME3 000037 CLRMEM_BADDR 000037 CLRMEM_WC 002123 V37BANK 002124 SAMASK 002125 goMAIN 002126 SLAP1 002126 goMMchange 002147 V37XEQ 002153 V37XEQC 002166 WL_taskRecSize 002174 WL_tskLstStart 002175 WL_tskLstEnd 002176 WL_numTasks 002177 WL_numTasks1 002200 WL_maxVal 002201 WL_maxDelay 002202 WL_maxTimeOut 002203 WL_initWL 002204 WL_IN_loop 002213 WAITLIST 002232 WL_AT_noOvf 002264 WL_AT_chkOrder 002270 WL_AT_mkFirst 002306 WL_AT_loop 002311 WL_AT_schTsk 002333 WL_AT_done 002343 WL_TIME3task 002347 WL_runTasks 002362 WL_RT_loop 002364 WL_RT_runIt 002411 TASKOVER 002413 WL_RT_done 002414 WL_schedTask 002417 WL_ST_loop 002436 WL_ST_setT3 002461 WL_ST_noTask 002466 WL_ST_done 002470 WL_insert 002473 WL_IS_loop 002510 WL_IS_bumpPtr 002541 WL_IS_insRec 002552 WL_IS_done 002562 WL_remove 002565 WL_RM_loop 002603 WL_RM_done 002636 EX_WAKE_PRIO 002642 EX_DUMMY_PRIO 002643 EX_SLEEP_PRIO 002644 EX_jobCurStart 002645 EX_jobRecSize 002646 EX_jobLstStart 002647 EX_jobLstEnd 002650 EX_jobLstEnd1 002651 EX_numJobs 002652 EX_numJobs1 002653 EX_changeJob 002654 EX_keepJob 002655 EX_exec 002656 EX_MN_findJob 002662 EX_MN_setFlg 002677 EX_MN_runJob 002701 EX_MN_runIt 002720 ENDOFJOB 002723 JOBSLEEP 002725 CHANG1 002733 EX_MN_notBank 002750 EX_MN_saveIt 002752 EX_MN_mvRec 002757 EX_MN_loop3 002763 EX_MN_done3 003002 JOBWAKE 003003 EX_JW_loop 003015 EX_JW_moveRec 003035 EX_JW_bumpPtr 003041 EX_JW_done 003056 EX_JW_return 003074

Page 563: Apollo Guidance Computer AGC

SPVAC 003075 EX_SP_loop1 003110 EX_SP_done1 003127 EX_SP_testFlg 003146 EX_SP_done2 003156 FINDVAC 003161 NOVAC 003162 EX_AJ_loop1 003200 EX_AJ_done1 003217 EX_AJ_testFlg 003236 EX_AJ_done2 003246 EX_initEX 003252 EX_IN_loop1 003266 EX_IN_loop2 003304 EX_IN_loop3 003307 EX_IN_done 003324 EX_findIns 003332 EX_FI_loop 003347 EX_FI_bumpPtr 003376 EX_FI_insRec 003405 EX_FI_done 003405 EX_remove 003410 EX_RM_loop1 003420 EX_RM_done1 003437 EX_RM_loop2 003446 EX_RM_done2 003465 EX_RM_loop3 003472 EX_RM_done3 003507 dumJob 003510 dumJob1 003514 dumJob2 003517 NOTACTLT 003525 DXCHJUMP 003526 DODXCHCALL 003547 DC_NOTBANK 003561 BANKCALL 003565 DOBANKCALL 003611 MYBANKCALL 003624 POSTJUMP 003653 DOPOSTJUMP 003677 BANKJUMP 003712 DOBANKJUMP 003733 DATACALL 003742 DODATACALL 003763 RELTAB 003772 RELTAB11 004005 DKTESTINIT 004006 DK_initDK 004007 DSPOFF 004012 T4PROG 004047 DSPOUTSR 004057 DSPSCAN 004065 TABLNTH 004072 _120MRUPT 004074 DSPLAY 004103 DSPOUT 004116 NODSPOUT 004126 DSPOUTEXIT 004126 CHRPRIO 004131 KEYPROG 004132 TPAGREE 004150 TPA_SGN0 004152 TPA_P0 004157 TPA_PZ0 004167 TPA_PZ0FIX 004200 TPA_M0 004210 TPA_MZ0 004220 TPA_MZ0FIX 004231 TPA_SGN1 004241 TPA_P1 004246 TPA_M1 004262 TPA_SGN2 004277 TPA_P2 004304 TPA_M2 004306 TPA_P3 004310 MAXPOS 004315 MAXNEG 004316 TPA_MPAC0 004317 TPA_MPAC1 004320 TPA_FIXM 004321 TPA_FIXP 004337 SHORTMP 004353 DMP 004374 BANKFF_1 004435 BANK4 010000 BANK04_1 010000 BANK5 012000 BANK40_1 012000 BANK6 014000 BANK41_1 014000 BANK7 016000 BANK42_1 016000 BANK10 020000 BANK43_1 020000 V37 010000 V37BAD 010002 CHECKTAB 010005 AGAINMM 010007 V37NONO 010026 FCADRMM1 010030 PREMM1 010037 EPREMM1 010046 NOV37MM 010046 BANK04_2 010047 CHARIN 012000 CHARIN2 012016 ELRCODE1 012062 ENTERJMP 012063 _89TEST 012065 NUM 012101 DECTOBIN 012137 ENDNMTST 012155 ENDNUM 012170 ENDALL 012174 DECEND 012176 PDECSGN 012220 MORNUM 012227 CRITCON 012232 DECON 012237 GETINREL 012241 INRELTAB 012245 CCSHOLE 012271 VERB 012272 NVCOM 012275 NOUN 012306 NEGSGN 012312 BOTHSGN 012315 PIXCLPAS 012321 POSGN 012326 P_ON 012332 SGNCOM 012342 M_ON 012353 SGNTAB 012364 SIGNTEST 012367 SGNTST1 012404 CLEAR 012412 CLPASHI 012431 CLEAR1 012454 CLR5 012461 LEGALTST 012464 _5BLANK 012473 _5BLANK1 012515 SINBLANK 012531 DOUBLK 012534 BRNCHCON 012537 _2BLANK 012540 BLANKCON 012563 BANK40_2 012564 NVSUBR 014000 LOADLV1 014001 ENTER 014002 ENTPASHI 014012 ACCEPTWD 014032 ENTEXIT 000433 MMADREF 014036 LOWVERB 014037 ENTPAS0 014040 TESTVB 014044 TESTNN 014054 REQADD 014073 USEADD 014117 LODNNLOC 014124 NEG5 014126 INTMCTBS 014127 VERBFAN 014151 LST2CON 014163 VBFANDIR 014164 VERBTAB 014167 MIXNOUN 014237 DPTEST 014240 DPTEST1 014262 REQDATX 014264 REQDATY 014270 REQDATZ 014274 REQCOM 014277 ENDRQDAT 014305 UPDATNN 014307 PUTADD 014320 UPDATVB 014327 UPDAT1 014335 GOALMCYC 014340 GODSPALM 014341 DSPABC 014343 DSPAB 014350 DSPA 014355 DSPCOM1 014361 DSPB 014363 DSPC 014370 DSPCOM2 014375 DSPCOM3 014403 COMPTEST 014414 COMPTST1 014417 NDOMPTST 014427 DCOMPTST 014430 DECTEST 014435 DCTSTCYC 014444 NOUNTEST 014453 TSTFORDP 014462 COMPICK 014477 GETCOMP 014501 DECDSP 014510 DSPDCGET 014514 DSPDCPUT 014524 DSPSFNOR 014546 GTSFOUTL 014550 DSPDCEND 014551 DECDSP3 014560 SFOUTABR 014563 BANK41_2 014600 DEGOUTSF 012564 SETAUG 012572 FIXRANGE 012603 DEGCOM 012616 DEGTAB 012640 ARTOUTSF 012644 SCOUTEND 012651 READLO 012653 READLO1 012665 RDLONOR 012701 ENDRDLO 012703 BANK40_3 012704 HMSOUT 016000 SECON1 016041 SECON2 016043 MINCON2 016045 MINCON1 016047 HRCON1 016051 SEPSECNR 016053 SEPMIN 016074 ENDSPMIN 016113 BANK42_2 016114 DSPDPDEC 012704 ENDDPDEC 012726 BANK40_4 012727 ABCLOAD 014600 PUTXYZ 014614 ABLOAD 014635 PUTXY 014646 ALOAD 014663 BLOAD 014673 CLOAD 014707 LOADLV 014723 VBSP1LD 014733 VBSP2LD 014734 VBSP3LD 014735 ALLDC_OC 014736 GOQ 014761 SFRUTNOR 014762 SFRUTMIX 014770 SFRET1 015002 SFCONUM 015003 SFRET 015020 DISPLACE 015022 CONUMNOR 015025 PUTCOM 015031 PUTDPCOM 015065 PUTNORM 015077 PUTNORM_1 015111 PUTCOM2 015111 GTSFINLC 015113 PUTDECSF 015114

Page 564: Apollo Guidance Computer AGC

PUTSFNOR 015125 PUTDCSF2 015126 SFINTABR 015131 BANK41_3 015146 DEGINSF 012727 DEGINSF2 012740 SIGNFIX 012750 ENDSCALE 012762 NEG180 012764 SGNTO1 012766 DEGCON1 012772 DEGCON2 012774 ARTHINSF 012776 BINROUND 013011 _2ROUND 013014 _2RNDEND 013024 TESTOFUF 013025 BANK40_5 013031 BANK42_3 016114 MONITOR 015146 MONIT1 015150 BIT15_14 015155 MONIT2 015164 MONREQ 015215 KILLMON 015232 MONDEL 015236 MONDO 015237 ENDMONDO 015273 MONREF 015274 MONBACK 015275 MONBUSY 015276 LODSAMPT 015300 BANK41_4 015301 PASTEVB 004435 PASTEOPT 004451 ENDPASTE 004472 MID7 004473 BANKFF_2 004474 DSPFMEM 015301 ENDSPF 015307 BANK41_5 015310 DSPSIGN 013031 DSPRND 013046 DPOSMAX 013062 DSPDECWD 013064 DSPDCWD1 013071 TRACE1 013074 TRACE1S 013105 DECROUND 013117 DSPDECNR 013120 DSPDC2NR 013124 DSP2DEC 013131 END2DEC 013143 DSPDECVN 013144 VNDSPCON 013155 GOVNUPDT 013156 BANK40_6 013161 DSPOCTWD 015310 WDAGAIN 015317 OCTBACK 015337 DSPLW 015341 DSPMSK 002057 DSP2BIT 015344 BANK41_6 015356 DSPIN 013161 DSPIN1 013206 DFRNT 013226 DSLV 013245 DSMSK 013247 _11DSPIN 013253 DSPOCTIN 013261 ENDSPOCT 013264 PREDSPAL 013265 DSPALARM 013267 CHARALRM 013307 MONADR 013313 NVSBENDL 013314 BANK40_7 013315 ALMCYCLE 004474 ENDALM 004502 BANKFF_3 004503 MMCHANG 015356 MODROUTR 010000 REQMM 015404 VBRQEXEC 015420 REQEX1 015425 REQUESTC 015431 SETVAC 015444 VBRQWAIT 015446 ENDRQWT 015452 BANK41_7 015453 VBPROC 013315 VBTERM 013323 VBRESEQ 013325 VBRELDSP 013327 TSTLTS4 013334 UNSUSPEN 013342 BANK40_8 013350 NVSUB 004503 NVMONOPT 004507 NVSBCOM 004516 NVSUBCOM 004524 NVSRRBNK 004531 NVSUBEND 004532 BANKFF_4 004536 BLANKDSP 015453 INCR_NOUT_RET 015463 INCR_NOUT 015501 NVSUB1 015505 ENTSET 015542 NVSUB2 015543 ENDNVSB1 015571 BANK41_8 015572 KILMONON 004536 ENDIDLE 004541 ENDINST 004553 ISCADR_P0 004554 ISLIST_P0 004560 DSPABORT 004563 BLANKSUB 004565 BSUB1ADDR 004612 BS_SUPDXCHZ 004613 BANKFF_5 004616 DSPMM 010047 ENDSPMM 010056 BANK04_3 010057 BLNKSUB1 013350 TESTBIT 013373 DSPMMJB 013400 RECALTST 013413 RECAL1 013416 RECAL2 013427 RECAL3 013444 DOTERM 013446 DOPROC 013450 BANK40_8a 013452 SETNCADR 004616 SETNADD 004625 SETEBANK 004633 R1D1 004635 R2D1 004636 R3D1 004637 RIGHT5 004640 LEFT5 004647 SLEFT5 004656 LOW5 004664 MID5 004665 HI5 004666 TCNOVAC 004667 TCWAIT 004670 TCFINDVAC 004671 LOW11 004672 B12M1 004672 LOW8 004673 LOW10 004674 VD1 004675 ND1 004676 MD1 004677 BINCON 004700 OUT1 000011 DSALMOUT 000011 FALTON 004701 FALTOF 004706 FALTOR 004712 RELDSPON 004713 RELDSPOR 004720 TPSL1 004721 PRSHRTMP 004740 DOSHRTMP 004754 FLASHON 004760 FLASHOFF 004770 FLSHTAB 005000 NVSUBUSY 005001 BANKFF_5a 005003 NVSUBSY1 013452 ENDNVBSY 013461 BANK40_9 013462 RELDSP 005003 RELDSP2 005017 RELDSP1 005026 NEWMODEA 005036 POODOO 005050 NOTPALT 005066 PINBRNCH 005067 BANKFF_6 005070 VBTSTLTS 015572 TSTLTS1 015600 FULLDSP 015621 FULLDSP1 015622 TSTCON1 015623 SHOLTS 015624 TSTLTS2 015625 TSTLTS3 015631 BANK41_9 015644 ERROR 013462 TSTAB 013467 ERMINUS 013477 ERPLUS 013502 ERCOM 013505 NOTBIT12 013517 ERCON 013520 BANK40_10 013521 LODNNTAB 016114 LODMIXNN 016135 LODNLV 016156 MIXCON 016161 GTSFOUT 016162 SFCOM 016173 GTSFIN 016176 NNADTAB 016210 NNTYPTAB 016354 SFINTAB 016520 SFOUTAB 016570 IDADDTAB 016640 RUTMXTAB 017124 BANK42_4 017220 GOEXTVB 020000 LST2FAN 020002 ALM_END 020076 GOPIN 020077 BANK43_2 020101 BANK11 022000 P00 022000 time1 022004 task1 022005 prio1 022011 job1 022012 nvcode1 022017 restart1_addr 022020 tcadr1 022021 P01 022022 P01_restart 022024 nvcode2 022033 restart2_addr 022034 tcadr2 022035 P02 022036 P02_restart 022040 P02_wait 022047 P02_pwd 022055 P02_ter 022060 nvcode3 022063 restart3_addr 022064 tcadr3 022065 P03 022066 P03_restart 022070 P03_wait 022077 P03_yield 022107 P03_pwd 022115 P03_ter 022120 nvcode4 022123 restart4_addr 022124 tcadr4 022125 mon_option 022126 P04 022127 P04_restart 022131 P78 022142 P79 022147 ARUPT 000026 Q 000001 QRUPT 000027 TIME1 000036

Page 565: Apollo Guidance Computer AGC

TIME2 000035 BANK 000015 A 000000 TIME4 000040 OUT0 000010 IN0 000004 LP 000003 OVCTR 000034 CYL 000022 SR 000021 CYR 000020

Page 566: Apollo Guidance Computer AGC

Block IApollo Guidance Computer (AGC)

How to build one in your basement

Part 9: Test and Checkout Software

John Pultorak

December, 2004

Page 567: Apollo Guidance Computer AGC

Abstract

This report describes my successful project to build a working reproduction of the 1964

prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the

Apollo moon landings, and is the world’s first integrated circuit computer.

I built it in my basement. It took me 4 years.

If you like, you can build one too. It will take you less time, and yours will be better than

mine.

I documented my project in 9 separate .pdf files:

Part 1 Overview: Introduces the project.

Part 2 CTL Module: Design and construction of the control module.

Part 3 PROC Module: Design and construction of the processing (CPU) module.

Part 4 MEM Module: Design and construction of the memory module.

Part 5 IO Module: Design and construction of the display/keyboard (DSKY) module.

Part 6 Assembler: A cross-assembler for AGC software development.

Part 7 C++ Simulator: A low-level simulator that runs assembled AGC code.

Part 8 Flight Software: My translation of portions of the COLOSSUS 249 flight

software.

Part 9 Test & Checkout: A suite of test programs in AGC assembly language.

Page 568: Apollo Guidance Computer AGC

Overview

A suite of test and checkout programs were coded to verify the operation of the AGC

simulators and the hardware AGC.

TECO1First test and checkout program for the Block 1 AGC. Tests basic instructions: TC, CCS,

INDEX, XCH, CS, TS, AD, MASK. Enters an infinite loop at the end of the test. The A register

contains the code for the test that failed, or the PASS code if all tests succeeded. See test

codes (in octal) below.

Code Interpretation

01 TC check failed

02 CCS check failed

03 INDEX check failed

04 XCH check failed

05 CS check failed

06 TS check failed

07 AD check failed

10 MASK check failed

12345 PASSED all checks

TECO2Second test and checkout program for the Block 1 AGC. Tests extracode instructions: MP,

DV, SU. Enters an infinite loop at the end of the test. The A register contains the code for

the test that failed, or the PASS code if all tests succeeded. See test codes (in octal) below.

Code Interpretation

01 MP check failed

02 DV check failed

03 SU check failed

12345 PASSED all checks

TECO3Third test and checkout program for the Block 1 AGC. Tests editing registers: CYR, SR, CYL,

SL. Enters an infinite loop at the end of the test. The A register contains the code for the

test that failed, or the PASS code if all tests succeeded. See test codes (in octal) below.

Code Interpretation

01 CYR check failed

02 SR check failed

03 CYL check failed

04 SL check failed

12345 PASSED all checks

Page 569: Apollo Guidance Computer AGC

TECO5Exercises AGC interrupts by initializing 4 counters, and then entering into a loop that

increments the first counter on each iteration. Each of the other 3 counters is assigned to an

interrupt and is incremented in the interrupt service routine for that interrupt: KEYRUPT,

T3RUPT, and DSRUPT. Interrupts are inhib ited and enabled during each iteration of the main

loop with INHINT and RELINT instructions, and are automatically inhibited during part of

each iteration by an overflow condition in register A.

TECO_STBYAn extremely simple program for testing the STANDBY function. STANDBY is disabled for 2

NOOP instructions and then is enabled. After that, the program infinitely loops (TC TRAP)

with STANDBY enabled.

Page 570: Apollo Guidance Computer AGC

TECO1 assembler listing

Block I Apollo Guidance Computer (AGC4) assembler version 1.6 for EPROM

First pass: generate symbol table.Second pass: generate object code.

; TECO1 (file:teco1.asm) ; ; Version: 1.0 ; Author: John Pultorak ; Date: 9/14/2001 ; ; PURPOSE: ; Test and checkout program for the Block 1 Apollo Guidance Computer. ; Tests basic instructions: TC, CCS, INDEX, XCH, CS, TS, AD, MASK. ; ; OPERATION: ; Enters an infinite loop at the end of the test. The A register ; contains the code for the test that failed, or the PASS code if all ; tests succeeded. See test codes below. ; ; ERRATA: ; - Written for the AGC4R assembler. The assembler directives and ; syntax differ somewhat from the original AGC assembler. ; - The tests attempt to check all threads, but are not exhaustive. ; ; SOURCES: ; Information on the Block 1 architecture: instruction set, instruction ; sequences, registers, register transfers, control pulses, memory and ; memory addressing, I/O assignments, interrupts, and involuntary ; counters was obtained from: ; ; A. Hopkins, R. Alonso, and H. Blair-Smith, "Logical Description ; for the Apollo Guidance Computer (AGC4)", R-393, ; MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963. ; ; Supplementary information was obtained from: ; ; R. Alonso, J. H. Laning, Jr. and H. Blair-Smith, "Preliminary ; MOD 3C Programmer's Manual", E-1077, MIT Instrumentation ; Laboratory, Cambridge, MA, Nov. 1961. ; ; B. I. Savage and A. Drake, "AGC4 Basic Training Manual, Volume I", ; E-2052, MIT Instrumentation Laboratory, Cambridge, ; MA, Jan. 1967. ; ; E. C. Hall, "MIT's Role in Project Apollo, Volume III, Computer ; Subsystem", R-700, MIT Charles Stark Draper Laboratory, ; Cambridge, MA, Aug. 1972. ; ; A. Hopkins, "Guidance Computer Design, Part VI", source unknown. ; ; A. I. Green and J. J. Rocchio, "Keyboard and Display System Program ; for AGC (Program Sunrise)", E-1574, MIT Instrumentation ; Laboratory, Cambridge, MA, Aug. 1964. ; ; E, C. Hall, "Journey to the Moon: The History of the Apollo ; Guidance Computer", AIAA, Reston VA, 1996. ; START EQU %00 TCtst EQU %01 ; TC check failed CCStst EQU %02 ; CCS check failed INDEXtst EQU %03 ; INDEX check failed XCHtst EQU %04 ; XCH check failed CStst EQU %05 ; CS check failed TStst EQU %06 ; TS check failed ADtst EQU %07 ; AD check failed MASKtst EQU %10 ; MASK check failed PASS EQU %12345 ; PASSED all checks ; ----------------------------------------------

Page 571: Apollo Guidance Computer AGC

ORG EXTENDER 05777 5777 47777 0 DS %47777 ; needed for EXTEND OVFCNTR EQU %00034 ; overflow counter ; ---------------------------------------------- ; ERASEABLE MEMORY -- DATA SEGMENT ORG %100 ; start of data area00100 0100 00000 1 curtest DS START ; current test00101 0101 00000 1 savQ DS %0 ; CCS test00102 0102 00000 1 CCSk DS %0 ; INDEX test00103 0103 00000 1 INDXval DS 0 ; XCH test ; pre-set in erasable memory because we don't ; want to use XCH to initialize them prior to testing XCH.00104 0104 00000 1 XCHkP0 DS +0 00105 0105 77777 0 XCHkM0 DS -0 00106 0106 52525 1 XCHkalt1 DS %52525 ; alternating bit pattern 100107 0107 25252 0 XCHkalt2 DS %25252 ; alternating bit pattern 2 ; TS test00110 0110 77777 0 TSk DS -0 ; AD test00111 0111 77777 0 ADk DS -0 ; ---------------------------------------------- ; ENTRY POINTS ; program (re)start ORG GOPROG 02000 2000 0 1,2030 0 TC goMAIN ; interrupt service entry points ORG T3RUPT 02004 2004 5 0,0026 0 TS ARUPT 02005 2005 3 0,0001 0 XCH Q 02006 2006 5 0,0027 1 TS QRUPT 02007 2007 0 1,2717 1 TC goT3 ORG ERRUPT 02010 2010 5 0,0026 0 TS ARUPT 02011 2011 3 0,0001 0 XCH Q 02012 2012 5 0,0027 1 TS QRUPT 02013 2013 0 1,2717 1 TC goER ORG DSRUPT 02014 2014 5 0,0026 0 TS ARUPT 02015 2015 3 0,0001 0 XCH Q 02016 2016 5 0,0027 1 TS QRUPT 02017 2017 0 1,2717 1 TC goDS ORG KEYRUPT 02020 2020 5 0,0026 0 TS ARUPT 02021 2021 3 0,0001 0 XCH Q 02022 2022 5 0,0027 1 TS QRUPT 02023 2023 0 1,2717 1 TC goKEY ORG UPRUPT 02024 2024 5 0,0026 0 TS ARUPT 02025 2025 3 0,0001 0 XCH Q 02026 2026 5 0,0027 1 TS QRUPT 02027 2027 0 1,2717 1 TC goUP ; ---------------------------------------------- ; FIXED MEMORY -- SHARED DATA SEGMENT ; ----------------------------------------------

Page 572: Apollo Guidance Computer AGC

; MAIN PROGRAM goMAIN EQU * 02030 2030 2 0,0000 0 INHINT ; disable interrupts 02031 2031 0 1,2047 0 TCR begin ; Test basic instructions.02032 2032 0 1,2054 1 TCR chkTC 02033 2033 0 1,2110 0 TCR chkCCS 02034 2034 0 1,2244 1 TCR chkINDEX 02035 2035 0 1,2274 1 TCR chkXCH 02036 2036 0 1,2400 1 TCR chkCS 02037 2037 0 1,2446 0 TCR chkTS 02040 2040 0 1,2573 1 TCR chkAD 02041 2041 0 1,2674 0 TCR chkMASK ; Passed all tests.02042 2042 0 1,2714 1 TCR finish fail EQU * 02043 2043 3 0,0100 0 XCH curtest ; load last passed test into A02044 2044 5 0,0100 0 TS curtest end EQU * 02045 2045 0 1,2045 1 TC end ; finished, TC trap ; ---------------------------------------------- ; INITIALIZE FOR START OF TESTING 02046 2046 00000 1 STRTcode DS START begin EQU * 02047 2047 3 1,2046 1 XCH STRTcode 02050 2050 5 0,0100 0 TS curtest ; set current test code to START02051 2051 0 0,0000 0 RETURN ; ---------------------------------------------- ; TEST TC INSTRUCTION SUBROUTINE ; L: TC K ; Verifies the following: ; - Set C(Q) = TC L+1 ; - Take next instruction from K, and proceed from there. 02052 2052 00001 0 TCcode DS TCtst ; code for this test02053 2053 02061 1 Qtest DS TCret1 ; expected return address chkTC EQU * 02054 2054 3 0,0001 0 XCH Q 02055 2055 5 0,0101 1 TS savQ ; save return address 02056 2056 3 1,2052 1 CAF TCcode 02057 2057 5 0,0100 0 TS curtest ; set test code to this test ; attempt a jump02060 2060 0 1,2062 1 TC *+2 ; make test jump02061 2061 0 1,2043 1 TCret1 TC fail ; failed to jump ; verify correct return address in Q02062 2062 4 0,0001 1 CS Q 02063 2063 6 1,2053 0 AD Qtest ; put (-Q) + val2 in A02064 2064 1 0,0000 0 CCS A ; A = DABS02065 2065 0 1,2043 1 TC fail ; >0 (Q < Qtest)02066 2066 0 1,2043 1 TC fail ; +0 (never happens)02067 2067 0 1,2043 1 TC fail ; <0 (Q > Qtest) ; passed the test02070 2070 3 0,0101 1 XCH savQ 02071 2071 5 0,0001 0 TS Q ; restore return address02072 2072 0 0,0000 0 RETURN ; ---------------------------------------------- ; TEST CCS INSTRUCTION SUBROUTINE ; L: CCS K ; Verifies the following: ; - take next instruction from L+n and proceed from there, where: ; -- n = 1 if C(K) > 0

Page 573: Apollo Guidance Computer AGC

; -- n = 2 if C(K) = +0 ; -- n = 3 if C(K) < 0 ; -- n = 4 if C(K) = -0 ; - set C(A) = DABS[C(K)], where DABS (diminished abs value): ; -- DABS(a) = abs(a) - 1, if abs(a) > 1 ; -- DABS(a) = +0, if abs(a) <= 1 02073 2073 00002 0 CCScode DS CCStst ; code for this test ; test values (K)02074 2074 77775 1 CCSkM2 DS -2 02075 2075 77776 1 CCSkM1 DS -1 02076 2076 77777 0 CCSkM0 DS -0 02077 2077 00000 1 CCSkP0 DS +0 02100 2100 00001 0 CCSkP1 DS +1 02101 2101 00002 0 CCSkP2 DS +2 ; expected DABS values02102 2102 00001 0 CCSdM2 DS 1 ; for K=-2, DABS = +102103 2103 00000 1 CCSdM1 DS 0 ; for K=-1, DABS = +002104 2104 00000 1 CCSdM0 DS 0 ; for K=-0, DABS = +002105 2105 00000 1 CCSdP0 DS 0 ; for K=+0, DABS = +002106 2106 00000 1 CCSdP1 DS 0 ; for K=+1, DABS = +002107 2107 00001 0 CCSdP2 DS 1 ; for K=+2, DABS = +1 chkCCS EQU * 02110 2110 3 0,0001 0 XCH Q 02111 2111 5 0,0101 1 TS savQ ; save return address 02112 2112 3 1,2073 1 CAF CCScode 02113 2113 5 0,0100 0 TS curtest ; set test code to this test ; set K to -2 and execute CCS: ; check for correct branch02114 2114 3 1,2074 0 CAF CCSkM2 ; set K = -202115 2115 5 0,0102 1 TS CCSk 02116 2116 1 0,0102 0 CCS CCSk ; A = DABS[C(K)]02117 2117 0 1,2043 1 TC fail ; K > 002120 2120 0 1,2043 1 TC fail ; K= +002121 2121 0 1,2123 0 TC *+2 ; K < 002122 2122 0 1,2043 1 TC fail ; K= -0 ; check for correct DABS in A (for K=-2, it should be 1)02123 2123 4 0,0000 0 COM ; 1's compliment of A02124 2124 6 1,2102 0 AD CCSdM2 ; put (-A) + expected value in A02125 2125 1 0,0000 0 CCS A ; A = DABS02126 2126 0 1,2043 1 TC fail ; >0 (A < expected value)02127 2127 0 1,2043 1 TC fail ; +002130 2130 0 1,2043 1 TC fail ; <0 (A > expected value) ; set K to -1 and execute CCS: ; check for correct branch02131 2131 3 1,2075 1 CAF CCSkM1 ; set K = -102132 2132 5 0,0102 1 TS CCSk 02133 2133 1 0,0102 0 CCS CCSk ; A = DABS[C(K)]02134 2134 0 1,2043 1 TC fail ; K > 002135 2135 0 1,2043 1 TC fail ; K= +002136 2136 0 1,2140 0 TC *+2 ; K < 002137 2137 0 1,2043 1 TC fail ; K= -0 ; check for correct DABS in A (for K=-1, it should be +0)02140 2140 4 0,0000 0 COM ; 1's compliment of A02141 2141 6 1,2103 1 AD CCSdM1 ; put (-A) + expected value in A02142 2142 1 0,0000 0 CCS A ; A = DABS02143 2143 0 1,2043 1 TC fail ; >0 (A < expected value)02144 2144 0 1,2043 1 TC fail ; +002145 2145 0 1,2043 1 TC fail ; <0 (A > expected value) ; set K to -0 and execute CCS: ; check for correct branch02146 2146 3 1,2076 1 CAF CCSkM0 ; set K = -002147 2147 5 0,0102 1 TS CCSk 02150 2150 1 0,0102 0 CCS CCSk ; A = DABS[C(K)]02151 2151 0 1,2043 1 TC fail ; K > 002152 2152 0 1,2043 1 TC fail ; K= +002153 2153 0 1,2043 1 TC fail ; K < 0 ; check for correct DABS in A (for K=-0, it should be +0)02154 2154 4 0,0000 0 COM ; 1's compliment of A02155 2155 6 1,2104 0 AD CCSdM0 ; put (-A) + expected value in A

Page 574: Apollo Guidance Computer AGC

02156 2156 1 0,0000 0 CCS A ; A = DABS02157 2157 0 1,2043 1 TC fail ; >0 (A < expected value)02160 2160 0 1,2043 1 TC fail ; +002161 2161 0 1,2043 1 TC fail ; <0 (A > expected value) ; set K to +0 and execute CCS: ; check for correct branch02162 2162 3 1,2077 0 CAF CCSkP0 ; set K = +002163 2163 5 0,0102 1 TS CCSk 02164 2164 1 0,0102 0 CCS CCSk ; A = DABS[C(K)]02165 2165 0 1,2043 1 TC fail ; K > 002166 2166 0 1,2171 1 TC *+3 ; K= +002167 2167 0 1,2043 1 TC fail ; K < 002170 2170 0 1,2043 1 TC fail ; K= -0 ; check for correct DABS in A (for K=+0, it should be +0)02171 2171 4 0,0000 0 COM ; 1's compliment of A02172 2172 6 1,2105 1 AD CCSdP0 ; put (-A) + expected value in A02173 2173 1 0,0000 0 CCS A ; A = DABS02174 2174 0 1,2043 1 TC fail ; >0 (A < expected value)02175 2175 0 1,2043 1 TC fail ; +002176 2176 0 1,2043 1 TC fail ; <0 (A > expected value) ; set K to +1 and execute CCS: ; check for correct branch02177 2177 3 1,2100 1 CAF CCSkP1 ; set K = +102200 2200 5 0,0102 1 TS CCSk 02201 2201 1 0,0102 0 CCS CCSk ; A = DABS[C(K)]02202 2202 0 1,2206 1 TC *+4 ; K > 002203 2203 0 1,2043 1 TC fail ; K= +002204 2204 0 1,2043 1 TC fail ; K < 002205 2205 0 1,2043 1 TC fail ; K= -0 ; check for correct DABS in A (for K=+1, it should be +0)02206 2206 4 0,0000 0 COM ; 1's compliment of A02207 2207 6 1,2106 1 AD CCSdP1 ; put (-A) + expected value in A02210 2210 1 0,0000 0 CCS A ; A = DABS02211 2211 0 1,2043 1 TC fail ; >0 (A < expected value)02212 2212 0 1,2043 1 TC fail ; +002213 2213 0 1,2043 1 TC fail ; <0 (A > expected value) ; set K to +2 and execute CCS: ; check for correct branch02214 2214 3 1,2101 0 CAF CCSkP2 ; set K = +202215 2215 5 0,0102 1 TS CCSk 02216 2216 1 0,0102 0 CCS CCSk ; A = DABS[C(K)]02217 2217 0 1,2223 0 TC *+4 ; K > 002220 2220 0 1,2043 1 TC fail ; K= +002221 2221 0 1,2043 1 TC fail ; K < 002222 2222 0 1,2043 1 TC fail ; K= -0 ; check for correct DABS in A (for K=+2, it should be +1)02223 2223 4 0,0000 0 COM ; 1's compliment of A02224 2224 6 1,2107 0 AD CCSdP2 ; put (-A) + expected value in A02225 2225 1 0,0000 0 CCS A ; A = DABS02226 2226 0 1,2043 1 TC fail ; >0 (A < expected value)02227 2227 0 1,2043 1 TC fail ; +002230 2230 0 1,2043 1 TC fail ; <0 (A > expected value) ; passed the test02231 2231 3 0,0101 1 XCH savQ 02232 2232 5 0,0001 0 TS Q ; restore return address02233 2233 0 0,0000 0 RETURN ; ---------------------------------------------- ; TEST INDEX INSTRUCTION SUBROUTINE ; L: INDEX K (where K != 0025) ; Verifies the following; ; - Use the sum of C(L+1) + C(K) as the next instruction ; -- just as if that sum had been taken from L+1. 02234 2234 00003 1 INDXcode DS INDEXtst ; code for this test02235 2235 00005 1 INDXst DS 5 ; somewhere in fixed memory 02236 2236 00000 1 INDXbas DS 0 ; base address for indexing02237 2237 00001 0 DS 1 02240 2240 00002 0 DS 2 02241 2241 00003 1 DS 3 02242 2242 00004 0 DS 4 02243 2243 00005 1 DS 5

Page 575: Apollo Guidance Computer AGC

chkINDEX EQU * 02244 2244 3 0,0001 0 XCH Q 02245 2245 5 0,0101 1 TS savQ ; save return address 02246 2246 3 1,2234 0 CAF INDXcode 02247 2247 5 0,0100 0 TS curtest ; set test code to this test ; Decrementing loop ; - always executes at least once (tests at end of loop) ; - loops 'INDXst+1' times; decrements INDXval 02250 2250 3 1,2235 1 XCH INDXst ; initialize loop counter INDXlop EQU * 02251 2251 5 0,0103 0 TS INDXval ; perform indexed CAF of values in INDXbas array; ; index values range from 5 to 002252 2252 2 0,0103 1 INDEX INDXval 02253 2253 3 1,2236 1 CAF INDXbas ; verify value retrieved using INDEX matches expected value02254 2254 4 0,0000 0 COM ; get -A02255 2255 6 0,0103 0 AD INDXval ; put (-A) + expected value in A02256 2256 1 0,0000 0 CCS A ; compare02257 2257 0 1,2043 1 TC fail ; >0 (A < expected value)02260 2260 0 1,2043 1 TC fail ; +002261 2261 0 1,2043 1 TC fail ; <0 (A > expected value) 02262 2262 1 0,0103 1 CCS INDXval ; done?02263 2263 0 1,2251 0 TC INDXlop ; not yet 02264 2264 3 0,0101 1 XCH savQ 02265 2265 5 0,0001 0 TS Q ; restore return address02266 2266 0 0,0000 0 RETURN ; ---------------------------------------------- ; TEST XCH INSTRUCTION SUBROUTINE ; L: XCH K ; Verifies the following: ; - set C(A) = b(K) ; - set C(K) = b(A) ; - take next instruction from L+1 02267 2267 00004 0 XCHcode DS XCHtst ; code for this test ; XCH test values02270 2270 00000 1 XCHfP0 DS +0 02271 2271 77777 0 XCHfM0 DS -0 02272 2272 52525 1 XCHfalt1 DS %52525 ; alternating bit pattern 102273 2273 25252 0 XCHfalt2 DS %25252 ; alternating bit pattern 2 chkXCH EQU * 02274 2274 3 0,0001 0 XCH Q 02275 2275 5 0,0101 1 TS savQ ; save return address 02276 2276 3 1,2267 0 CAF XCHcode 02277 2277 5 0,0100 0 TS curtest ; set test code to this test ; test - initial conditions: K=+0, A=-0 ; initialize A02300 2300 4 1,2270 1 CS XCHfP0 ; exchange A and K02301 2301 3 0,0104 1 XCH XCHkP0 ; test contents of A for expected value02302 2302 4 0,0000 0 COM ; get -A02303 2303 6 1,2270 0 AD XCHfP0 ; put (-A) + expected value in A02304 2304 1 0,0000 0 CCS A ; A = DABS02305 2305 0 1,2043 1 TC fail ; >0 (A < expected value)02306 2306 0 1,2043 1 TC fail ; +002307 2307 0 1,2043 1 TC fail ; <0 (A > expected value) ; test contents of K for expected value02310 2310 4 0,0104 0 CS XCHkP0 ; get -A02311 2311 6 1,2271 1 AD XCHfM0 ; put (-A) + expected value in A02312 2312 1 0,0000 0 CCS A ; A = DABS02313 2313 0 1,2043 1 TC fail ; >0 (A < expected value)02314 2314 0 1,2043 1 TC fail ; +0

Page 576: Apollo Guidance Computer AGC

02315 2315 0 1,2043 1 TC fail ; <0 (A > expected value) ; test - initial conditions: K=-0, A=+0 ; initialize A02316 2316 4 1,2271 0 CS XCHfM0 ; exchange A and K02317 2317 3 0,0105 0 XCH XCHkM0 ; test contents of A for expected value02320 2320 4 0,0000 0 COM ; get -A02321 2321 6 1,2271 1 AD XCHfM0 ; put (-A) + expected value in A02322 2322 1 0,0000 0 CCS A ; A = DABS02323 2323 0 1,2043 1 TC fail ; >0 (A < expected value)02324 2324 0 1,2043 1 TC fail ; +002325 2325 0 1,2043 1 TC fail ; <0 (A > expected value) ; test contents of K for expected value02326 2326 4 0,0105 1 CS XCHkM0 ; get -A02327 2327 6 1,2270 0 AD XCHfP0 ; put (-A) + expected value in A02330 2330 1 0,0000 0 CCS A ; A = DABS02331 2331 0 1,2043 1 TC fail ; >0 (A < expected value)02332 2332 0 1,2043 1 TC fail ; +002333 2333 0 1,2043 1 TC fail ; <0 (A > expected value) ; test - initial conditions: K=52525, A=25252 ; initialize A02334 2334 4 1,2272 0 CS XCHfalt1 ; exchange A and K02335 2335 3 0,0106 0 XCH XCHkalt1 ; test contents of A for expected value02336 2336 4 0,0000 0 COM ; get -A02337 2337 6 1,2272 1 AD XCHfalt1 ; put (-A) + expected value in A02340 2340 1 0,0000 0 CCS A ; A = DABS02341 2341 0 1,2043 1 TC fail ; >0 (A < expected value)02342 2342 0 1,2043 1 TC fail ; +002343 2343 0 1,2043 1 TC fail ; <0 (A > expected value) ; test contents of K for expected value02344 2344 4 0,0106 1 CS XCHkalt1 ; get -A02345 2345 6 1,2273 0 AD XCHfalt2 ; put (-A) + expected value in A02346 2346 1 0,0000 0 CCS A ; A = DABS02347 2347 0 1,2043 1 TC fail ; >0 (A < expected value)02350 2350 0 1,2043 1 TC fail ; +002351 2351 0 1,2043 1 TC fail ; <0 (A > expected value) ; test - initial conditions: K=25252, A=52525 ; initialize A02352 2352 4 1,2273 1 CS XCHfalt2 ; exchange A and K02353 2353 3 0,0107 1 XCH XCHkalt2 ; test contents of A for expected value02354 2354 4 0,0000 0 COM ; get -A02355 2355 6 1,2273 0 AD XCHfalt2 ; put (-A) + expected value in A02356 2356 1 0,0000 0 CCS A ; A = DABS02357 2357 0 1,2043 1 TC fail ; >0 (A < expected value)02360 2360 0 1,2043 1 TC fail ; +002361 2361 0 1,2043 1 TC fail ; <0 (A > expected value) ; test contents of K for expected value02362 2362 4 0,0107 0 CS XCHkalt2 ; get -A02363 2363 6 1,2272 1 AD XCHfalt1 ; put (-A) + expected value in A02364 2364 1 0,0000 0 CCS A ; A = DABS02365 2365 0 1,2043 1 TC fail ; >0 (A < expected value)02366 2366 0 1,2043 1 TC fail ; +002367 2367 0 1,2043 1 TC fail ; <0 (A > expected value) ; passed the test02370 2370 3 0,0101 1 XCH savQ 02371 2371 5 0,0001 0 TS Q ; restore return address02372 2372 0 0,0000 0 RETURN ; ---------------------------------------------- ; TEST CS INSTRUCTION SUBROUTINE ; L: CS K ; Verifies the following: ; - Set C(A) = -C(K) ; - Take next instruction from L+1 02373 2373 00005 1 CScode DS CStst ; code for this test ; test values (K)

Page 577: Apollo Guidance Computer AGC

02374 2374 00000 1 CSkP0 DS +0 02375 2375 77777 0 CSkM0 DS -0 02376 2376 52525 1 CSkalt1 DS %52525 ; 1's C of CSkalt202377 2377 25252 0 CSkalt2 DS %25252 ; 1's C of CSkalt1 chkCS EQU * 02400 2400 3 0,0001 0 XCH Q 02401 2401 5 0,0101 1 TS savQ ; save return address 02402 2402 3 1,2373 1 CAF CScode 02403 2403 5 0,0100 0 TS curtest ; set test code to this test ; clear and subtract +002404 2404 4 1,2374 1 CS CSkP0 ; load 1's comp of K into A02405 2405 6 1,2374 0 AD CSkP0 ; put (-A) + expected value in A02406 2406 1 0,0000 0 CCS A ; compare02407 2407 0 1,2043 1 TC fail ; >0 (A < expected value)02410 2410 0 1,2043 1 TC fail ; +002411 2411 0 1,2043 1 TC fail ; <0 (A > expected value) ; clear and subtract -002412 2412 4 1,2375 0 CS CSkM0 ; load 1's comp of K into A02413 2413 6 1,2375 1 AD CSkM0 ; put (-A) + expected value in A02414 2414 1 0,0000 0 CCS A ; compare02415 2415 0 1,2043 1 TC fail ; >0 (A < expected value)02416 2416 0 1,2043 1 TC fail ; +002417 2417 0 1,2043 1 TC fail ; <0 (A > expected value) ; clear and subtract alternating bit pattern %5252502420 2420 4 1,2376 0 CS CSkalt1 ; load 1's comp of K into A02421 2421 6 1,2376 1 AD CSkalt1 ; put (-A) + expected value in A02422 2422 1 0,0000 0 CCS A ; compare02423 2423 0 1,2043 1 TC fail ; >0 (A < expected value)02424 2424 0 1,2043 1 TC fail ; +002425 2425 0 1,2043 1 TC fail ; <0 (A > expected value) ; clear and subtract alternating bit pattern %2525202426 2426 4 1,2377 1 CS CSkalt2 ; load 1's comp of K into A02427 2427 6 1,2377 0 AD CSkalt2 ; put (-A) + expected value in A02430 2430 1 0,0000 0 CCS A ; compare02431 2431 0 1,2043 1 TC fail ; >0 (A < expected value)02432 2432 0 1,2043 1 TC fail ; +002433 2433 0 1,2043 1 TC fail ; <0 (A > expected value) ; passed the test02434 2434 3 0,0101 1 XCH savQ 02435 2435 5 0,0001 0 TS Q ; restore return address02436 2436 0 0,0000 0 RETURN ; ---------------------------------------------- ; TEST TS INSTRUCTION SUBROUTINE ; L; TS K ; Verifies the following: ; - Set C(K) = b(A) ; - If b(A) contains no overflow, ; -- C(A) = b(A); take next instruction from L+1 ; - If b(A) has positive overflow, C(A) = 000001; ; -- take next instruction from L+2 ; - If b(A) has negative overflow, C(A) = 177776; ; -- take next instruction from L+2 02437 2437 00006 1 TScode DS TStst ; code for this test02440 2440 00001 0 TSone DS +1 02441 2441 00000 1 TSzero DS +0 02442 2442 77777 0 TSmzero DS -0 02443 2443 77776 1 TSmone DS -1 02444 2444 37777 1 TSkP1 DS %37777 ; TEST1: largest + num w/no ovf02445 2445 40000 0 TSkM1 DS %40000 ; TEST2: largest - num w/no ovf chkTS EQU * 02446 2446 3 0,0001 0 XCH Q 02447 2447 5 0,0101 1 TS savQ ; save return address 02450 2450 3 1,2437 0 CAF TScode 02451 2451 5 0,0100 0 TS curtest ; set test code to this test ; initialize TSk to -0

Page 578: Apollo Guidance Computer AGC

02452 2452 3 1,2442 1 CAF TSmzero 02453 2453 3 0,0110 1 XCH TSk ; TEST 1: store positive number, no overflow02454 2454 3 1,2444 1 CAF TSkP1 02455 2455 5 0,0110 1 TS TSk 02456 2456 0 1,2460 1 TC *+2 ; no overflow02457 2457 0 1,2043 1 TC fail ; overflow ; verify C(A) = b(A)02460 2460 4 0,0000 0 COM ; get -A02461 2461 6 1,2444 1 AD TSkP1 ; put (-A) + expected value in A02462 2462 1 0,0000 0 CCS A ; compare02463 2463 0 1,2043 1 TC fail ; >0 (A < expected value)02464 2464 0 1,2043 1 TC fail ; +002465 2465 0 1,2043 1 TC fail ; <0 (A > expected value) ; verify C(K) = b(A)02466 2466 4 1,2444 0 CS TSkP1 ; get -expected value02467 2467 6 0,0110 1 AD TSk ; put value + C(K) into A02470 2470 1 0,0000 0 CCS A ; compare02471 2471 0 1,2043 1 TC fail ; >0 (A < expected value)02472 2472 0 1,2043 1 TC fail ; +002473 2473 0 1,2043 1 TC fail ; <0 (A > expected value) ; TEST 2: store negative number, no overflow02474 2474 3 1,2445 0 CAF TSkM1 02475 2475 5 0,0110 1 TS TSk 02476 2476 0 1,2500 0 TC *+2 ; no overflow02477 2477 0 1,2043 1 TC fail ; overflow ; verify C(A) = b(A)02500 2500 4 0,0000 0 COM ; get -A02501 2501 6 1,2445 0 AD TSkM1 ; put (-A) + expected value in A02502 2502 1 0,0000 0 CCS A ; compare02503 2503 0 1,2043 1 TC fail ; >0 (A < expected value)02504 2504 0 1,2043 1 TC fail ; +002505 2505 0 1,2043 1 TC fail ; <0 (A > expected value) ; verify C(K) = b(A)02506 2506 4 1,2445 1 CS TSkM1 ; get -expected value02507 2507 6 0,0110 1 AD TSk ; put value + C(K) into A02510 2510 1 0,0000 0 CCS A ; compare02511 2511 0 1,2043 1 TC fail ; >0 (A < expected value)02512 2512 0 1,2043 1 TC fail ; +002513 2513 0 1,2043 1 TC fail ; <0 (A > expected value) ; TEST 3: store positive number, overflow02514 2514 3 1,2444 1 CAF TSkP1 ; get largest positive number02515 2515 6 1,2440 0 AD TSone ; make it overflow; A = neg ovf02516 2516 5 0,0110 1 TS TSk ; store the positive overflow02517 2517 0 1,2043 1 TC fail ; no overflow ; verify C(A) = 00000102520 2520 4 0,0000 0 COM ; get -A02521 2521 6 1,2440 0 AD TSone ; put (-A) + expected value in A02522 2522 1 0,0000 0 CCS A ; compare02523 2523 0 1,2043 1 TC fail ; >0 (A < expected value)02524 2524 0 1,2043 1 TC fail ; +002525 2525 0 1,2043 1 TC fail ; <0 (A > expected value) ; verify C(K) = positive overflow02526 2526 4 1,2441 0 CS TSzero ; get -expected value02527 2527 6 0,0110 1 AD TSk ; put value + C(K) into A02530 2530 1 0,0000 0 CCS A ; compare02531 2531 0 1,2043 1 TC fail ; >0 (A < expected value)02532 2532 0 1,2043 1 TC fail ; +002533 2533 0 1,2043 1 TC fail ; <0 (A > expected value) ; TEST 4: store negative number, overflow02534 2534 3 1,2445 0 CAF TSkM1 ; get largest negative number02535 2535 6 1,2443 0 AD TSmone ; make it overflow; A = neg ovf02536 2536 5 0,0110 1 TS TSk ; store the negative overflow02537 2537 0 1,2043 1 TC fail ; no overflow ; verify C(A) = 17777602540 2540 4 0,0000 0 COM ; get -A02541 2541 6 1,2443 0 AD TSmone ; put (-A) + expected value in A02542 2542 1 0,0000 0 CCS A ; compare02543 2543 0 1,2043 1 TC fail ; >0 (A < expected value)02544 2544 0 1,2043 1 TC fail ; +002545 2545 0 1,2043 1 TC fail ; <0 (A > expected value) ; verify C(K) = negative overflow

Page 579: Apollo Guidance Computer AGC

02546 2546 4 1,2442 0 CS TSmzero ; get -expected value02547 2547 6 0,0110 1 AD TSk ; put value + C(K) into A02550 2550 1 0,0000 0 CCS A ; compare02551 2551 0 1,2043 1 TC fail ; >0 (A < expected value)02552 2552 0 1,2043 1 TC fail ; +002553 2553 0 1,2043 1 TC fail ; <0 (A > expected value) 02554 2554 3 0,0101 1 XCH savQ 02555 2555 5 0,0001 0 TS Q ; restore return address02556 2556 0 0,0000 0 RETURN ; ---------------------------------------------- ; TEST AD INSTRUCTION SUBROUTINE ; L: AD K ; Verifies the following: ; - Set C(A) = b(A) + C(K) ; - Take next instruction from L+1 ; - if C(A) has positive overflow, ; -- increment overflow counter by 1 ; - if C(A) has negative overflow, ; -- decrement overflow counter by 1 02557 2557 00007 0 ADcode DS ADtst ; code for this test02560 2560 00000 1 ADplus0 DS +0 02561 2561 00001 0 ADplus1 DS 1 02562 2562 77776 1 ADmin1 DS -1 02563 2563 25252 0 AD25252 DS %25252 ; +10922 decimal02564 2564 12525 0 AD12525 DS %12525 ; +5461 decimal02565 2565 37777 1 AD37777 DS %37777 ; largest positive number02566 2566 12524 1 AD12524 DS %12524 ; + overflow of %25252+%25252 02567 2567 52525 1 AD52525 DS %52525 ; -10922 decimal02570 2570 65252 1 AD65252 DS %65252 ; -5461 decimal02571 2571 40000 0 AD40000 DS %40000 ; largest negative number02572 2572 65253 0 AD65253 DS %65253 ; neg overflow of %52525+65252 chkAD EQU * 02573 2573 3 0,0001 0 XCH Q 02574 2574 5 0,0101 1 TS savQ ; save return address 02575 2575 3 1,2557 1 CAF ADcode 02576 2576 5 0,0100 0 TS curtest ; set test code to this test ; TEST1: sum positive, no overflow ; add: %25252 + %12525 = %37777 (sign + 14 magnitude)02577 2577 3 1,2563 0 CAF AD25252 02600 2600 6 1,2564 1 AD AD12525 ; verify C(A) = %3777702601 2601 4 0,0000 0 COM ; get -A02602 2602 6 1,2565 0 AD AD37777 ; put (-A) + expected value in A02603 2603 1 0,0000 0 CCS A ; compare02604 2604 0 1,2043 1 TC fail ; >0 (A < expected value)02605 2605 0 1,2043 1 TC fail ; +002606 2606 0 1,2043 1 TC fail ; <0 (A > expected value) ; TEST2: sum negative, no overflow (sign + 14 magnitude) ; add: %52525 + %65252 = %4000002607 2607 3 1,2567 1 CAF AD52525 02610 2610 6 1,2570 1 AD AD65252 ; verify C(A) = %4000002611 2611 4 0,0000 0 COM ; get -A02612 2612 6 1,2571 0 AD AD40000 ; put (-A) + expected value in A02613 2613 1 0,0000 0 CCS A ; compare02614 2614 0 1,2043 1 TC fail ; >0 (A < expected value)02615 2615 0 1,2043 1 TC fail ; +002616 2616 0 1,2043 1 TC fail ; <0 (A > expected value) ; TEST3: sum positive, overflow ; initialize overflow counter and positive overflow storage02617 2617 3 1,2560 0 CAF ADplus0 02620 2620 5 0,0034 0 TS OVFCNTR 02621 2621 5 0,0111 0 TS ADk ; add: %25252 + %25252 = %52524 (sign + 14 magnitude)02622 2622 3 1,2563 0 CAF AD25252 02623 2623 6 1,2563 0 AD AD25252 02624 2624 5 0,0111 0 TS ADk ; store positive overflow

Page 580: Apollo Guidance Computer AGC

02625 2625 0 1,2043 1 TC fail ; verify ADk = %1252402626 2626 4 0,0111 1 CS ADk ; get -A02627 2627 6 1,2566 0 AD AD12524 ; put (-A) + expected value in A02630 2630 1 0,0000 0 CCS A ; compare02631 2631 0 1,2043 1 TC fail ; >0 (A < expected value)02632 2632 0 1,2043 1 TC fail ; +002633 2633 0 1,2043 1 TC fail ; <0 (A > expected value) ; verify overflow counter =%0000102634 2634 4 0,0034 1 CS OVFCNTR ; get -A02635 2635 6 1,2561 1 AD ADplus1 ; put (-A) + expected value in A02636 2636 1 0,0000 0 CCS A ; compare02637 2637 0 1,2043 1 TC fail ; >0 (A < expected value)02640 2640 0 1,2043 1 TC fail ; +002641 2641 0 1,2043 1 TC fail ; <0 (A > expected value) ; TEST4: sum negative, overflow02642 2642 3 1,2560 0 CAF ADplus0 02643 2643 5 0,0034 0 TS OVFCNTR 02644 2644 5 0,0111 0 TS ADk ; add: %52525 + %52525 = %25253 (sign + 14 magnitude)02645 2645 3 1,2567 1 CAF AD52525 02646 2646 6 1,2567 1 AD AD52525 02647 2647 5 0,0111 0 TS ADk ; store negative overflow02650 2650 0 1,2043 1 TC fail ; verify ADk = %6525302651 2651 4 0,0111 1 CS ADk ; get -A02652 2652 6 1,2572 0 AD AD65253 ; put (-A) + expected value in A02653 2653 1 0,0000 0 CCS A ; compare02654 2654 0 1,2043 1 TC fail ; >0 (A < expected value)02655 2655 0 1,2043 1 TC fail ; +002656 2656 0 1,2043 1 TC fail ; <0 (A > expected value) ; verify overflow counter =%7777602657 2657 4 0,0034 1 CS OVFCNTR ; get -A02660 2660 6 1,2562 1 AD ADmin1 ; put (-A) + expected value in A02661 2661 1 0,0000 0 CCS A ; compare02662 2662 0 1,2043 1 TC fail ; >0 (A < expected value)02663 2663 0 1,2043 1 TC fail ; +002664 2664 0 1,2043 1 TC fail ; <0 (A > expected value) 02665 2665 3 0,0101 1 XCH savQ 02666 2666 5 0,0001 0 TS Q ; restore return address02667 2667 0 0,0000 0 RETURN ; ---------------------------------------------- ; TEST MASK INSTRUCTION SUBROUTINE ; L: MASK K ; Verifies the following: ; - Set C(A) = b(A) & C(K) 02670 2670 00010 0 MASKcode DS MASKtst ; code for this test02671 2671 46314 0 MASK1 DS %46314 02672 2672 25252 0 MASK2 DS %25252 02673 2673 04210 0 MASKval DS %04210 ; expected result: MASK1 & MASK2 chkMASK EQU * 02674 2674 3 0,0001 0 XCH Q 02675 2675 5 0,0101 1 TS savQ ; save return address ; perform logical and of MASK1 and MASK202676 2676 3 1,2671 0 CAF MASK1 02677 2677 7 1,2672 1 MASK MASK2 ; verify C(A) = b(A) & C(K)02700 2700 4 0,0000 0 COM ; get -A02701 2701 6 1,2673 1 AD MASKval ; put (-A) + expected value in A02702 2702 1 0,0000 0 CCS A ; compare02703 2703 0 1,2043 1 TC fail ; >0 (A < expected value)02704 2704 0 1,2043 1 TC fail ; +002705 2705 0 1,2043 1 TC fail ; <0 (A > expected value) 02706 2706 3 1,2670 1 CAF MASKcode 02707 2707 5 0,0100 0 TS curtest ; set test code to this test ; passed the test02710 2710 3 0,0101 1 XCH savQ 02711 2711 5 0,0001 0 TS Q ; restore return address02712 2712 0 0,0000 0 RETURN

Page 581: Apollo Guidance Computer AGC

; ---------------------------------------------- ; PASSED ALL TESTS! 02713 2713 12345 0 PASScode DS PASS finish EQU * 02714 2714 3 1,2713 0 CAF PASScode 02715 2715 5 0,0100 0 TS curtest ; set current test code to PASS02716 2716 0 0,0000 0 RETURN ; ---------------------------------------------- ; INTERRUPT SERVICE ROUTINE goT3 EQU * goER EQU * goDS EQU * goKEY EQU * goUP EQU * endRUPT EQU * 02717 2717 3 0,0027 1 XCH QRUPT ; restore Q02720 2720 5 0,0001 0 TS Q 02721 2721 3 0,0026 0 XCH ARUPT ; restore A02722 2722 2 0,0000 1 RESUME ; finished, go back

Assembly complete. Errors = 0

Symbol table:START 000000 TCtst 000001 CCStst 000002 INDEXtst 000003 XCHtst 000004 CStst 000005 TStst 000006 ADtst 000007 MASKtst 000010 PASS 012345 EXTENDER 005777 OVFCNTR 000034 curtest 000100 savQ 000101 CCSk 000102 INDXval 000103 XCHkP0 000104 XCHkM0 000105 XCHkalt1 000106 XCHkalt2 000107 TSk 000110 ADk 000111 GOPROG 002000 T3RUPT 002004 ERRUPT 002010 DSRUPT 002014 KEYRUPT 002020 UPRUPT 002024 goMAIN 002030 fail 002043 end 002045 STRTcode 002046 begin 002047 TCcode 002052 Qtest 002053 chkTC 002054 TCret1 002061 CCScode 002073 CCSkM2 002074 CCSkM1 002075 CCSkM0 002076 CCSkP0 002077 CCSkP1 002100 CCSkP2 002101 CCSdM2 002102 CCSdM1 002103 CCSdM0 002104 CCSdP0 002105 CCSdP1 002106 CCSdP2 002107 chkCCS 002110 INDXcode 002234 INDXst 002235 INDXbas 002236 chkINDEX 002244 INDXlop 002251 XCHcode 002267 XCHfP0 002270 XCHfM0 002271 XCHfalt1 002272 XCHfalt2 002273 chkXCH 002274 CScode 002373 CSkP0 002374 CSkM0 002375 CSkalt1 002376 CSkalt2 002377 chkCS 002400 TScode 002437 TSone 002440 TSzero 002441 TSmzero 002442 TSmone 002443 TSkP1 002444 TSkM1 002445 chkTS 002446 ADcode 002557 ADplus0 002560 ADplus1 002561 ADmin1 002562 AD25252 002563 AD12525 002564 AD37777 002565 AD12524 002566 AD52525 002567 AD65252 002570 AD40000 002571 AD65253 002572 chkAD 002573 MASKcode 002670 MASK1 002671 MASK2 002672 MASKval 002673 chkMASK 002674 PASScode 002713 finish 002714 goT3 002717 goER 002717 goDS 002717 goKEY 002717 goUP 002717 endRUPT 002717 ARUPT 000026 Q 000001 QRUPT 000027 A 000000

Page 582: Apollo Guidance Computer AGC

TECO2 assembler listing

Block I Apollo Guidance Computer (AGC4) assembler version 1.6 for EPROM

First pass: generate symbol table.Second pass: generate object code.

; TECO2 (file:teco2.asm) ; ; Version: 1.0 ; Author: John Pultorak ; Date: 9/14/2001 ; ; PURPOSE: ; Test and checkout program for the Block 1 Apollo Guidance Computer. ; Tests extracode instructions: MP, DV, SU ; ; OPERATION: ; Enters an infinite loop at the end of the test. The A register ; contains the code for the test that failed, or the PASS code if all ; tests succeeded. See test codes below. ; ; ERRATA: ; - Written for the AGC4R assembler. The assembler directives and ; syntax differ somewhat from the original AGC assembler. ; - The tests attempt to check all threads, but are not exhaustive. ; ; SOURCES: ; Information on the Block 1 architecture: instruction set, instruction ; sequences, registers, register transfers, control pulses, memory and ; memory addressing, I/O assignments, interrupts, and involuntary ; counters was obtained from: ; ; A. Hopkins, R. Alonso, and H. Blair-Smith, "Logical Description ; for the Apollo Guidance Computer (AGC4)", R-393, ; MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963. ; ; Supplementary information was obtained from: ; ; R. Alonso, J. H. Laning, Jr. and H. Blair-Smith, "Preliminary ; MOD 3C Programmer's Manual", E-1077, MIT Instrumentation ; Laboratory, Cambridge, MA, Nov. 1961. ; ; B. I. Savage and A. Drake, "AGC4 Basic Training Manual, Volume I", ; E-2052, MIT Instrumentation Laboratory, Cambridge, ; MA, Jan. 1967. ; ; E. C. Hall, "MIT's Role in Project Apollo, Volume III, Computer ; Subsystem", R-700, MIT Charles Stark Draper Laboratory, ; Cambridge, MA, Aug. 1972. ; ; A. Hopkins, "Guidance Computer Design, Part VI", source unknown. ; ; A. I. Green and J. J. Rocchio, "Keyboard and Display System Program ; for AGC (Program Sunrise)", E-1574, MIT Instrumentation ; Laboratory, Cambridge, MA, Aug. 1964. ; ; E, C. Hall, "Journey to the Moon: The History of the Apollo ; Guidance Computer", AIAA, Reston VA, 1996. ; START EQU %00 MPtst EQU %01 ; MP check failed DVtst EQU %02 ; DV check failed SUtst EQU %03 ; SU check failed PASS EQU %12345 ; PASSED all checks ; ---------------------------------------------- ORG EXTENDER 05777 5777 47777 0 DS %47777 ; needed for EXTEND

Page 583: Apollo Guidance Computer AGC

OVFCNTR EQU %00034 ; overflow counter ; ---------------------------------------------- ; ERASEABLE MEMORY -- DATA SEGMENT ORG %100 ; start of data area00100 0100 00000 1 curtest DS START ; current test00101 0101 00000 1 savQ DS %0 ; MP test00102 0102 00000 1 MPindex DS %0 00103 0103 00000 1 MPXTND DS %0 ; indexed extend ; DV test00104 0104 00000 1 DVsavA DS %0 00105 0105 00000 1 DVindex DS %0 00106 0106 00000 1 DVXTND DS %0 ; indexed extend ; SU test00107 0107 77777 0 SUk DS -0 ; ---------------------------------------------- ; ENTRY POINTS ; program (re)start ORG GOPROG 02000 2000 0 1,2030 0 TC goMAIN ; interrupt service entry points ORG T3RUPT 02004 2004 5 0,0026 0 TS ARUPT 02005 2005 3 0,0001 0 XCH Q 02006 2006 5 0,0027 1 TS QRUPT 02007 2007 0 1,2742 1 TC goT3 ORG ERRUPT 02010 2010 5 0,0026 0 TS ARUPT 02011 2011 3 0,0001 0 XCH Q 02012 2012 5 0,0027 1 TS QRUPT 02013 2013 0 1,2742 1 TC goER ORG DSRUPT 02014 2014 5 0,0026 0 TS ARUPT 02015 2015 3 0,0001 0 XCH Q 02016 2016 5 0,0027 1 TS QRUPT 02017 2017 0 1,2742 1 TC goDS ORG KEYRUPT 02020 2020 5 0,0026 0 TS ARUPT 02021 2021 3 0,0001 0 XCH Q 02022 2022 5 0,0027 1 TS QRUPT 02023 2023 0 1,2742 1 TC goKEY ORG UPRUPT 02024 2024 5 0,0026 0 TS ARUPT 02025 2025 3 0,0001 0 XCH Q 02026 2026 5 0,0027 1 TS QRUPT 02027 2027 0 1,2742 1 TC goUP ; ---------------------------------------------- ; FIXED MEMORY -- SHARED DATA SEGMENT ; ---------------------------------------------- ; MAIN PROGRAM goMAIN EQU * 02030 2030 2 0,0000 0 INHINT ; disable interrupts 02031 2031 0 1,2042 0 TCR begin ; Test extracode instructions.02032 2032 0 1,2247 1 TCR chkMP 02033 2033 0 1,2551 1 TCR chkDV 02034 2034 0 1,2635 0 TCR chkSU

Page 584: Apollo Guidance Computer AGC

; Passed all tests.02035 2035 0 1,2737 0 TCR finish fail EQU * 02036 2036 3 0,0100 0 XCH curtest ; load last passed test into A02037 2037 5 0,0100 0 TS curtest end EQU * 02040 2040 0 1,2040 1 TC end ; finished, TC trap ; ---------------------------------------------- ; INITIALIZE FOR START OF TESTING 02041 2041 00000 1 STRTcode DS START begin EQU * 02042 2042 3 1,2041 0 XCH STRTcode 02043 2043 5 0,0100 0 TS curtest ; set current test code to START02044 2044 0 0,0000 0 RETURN ; ---------------------------------------------- ; TEST MP INSTRUCTION SUBROUTINE ; L: MP K ; Verifies the following ; - Set C(A,LP) = b(A) * C(K) ; - Take next instruction from L+1 02045 2045 00001 0 MPcode DS MPtst ; code for this test ; MP test values ; 02046 2046 00037 0 MPstart DS 31 ; loop MPstart+1 times ; C(A) test values mp1 EQU * ; check boundary conditions02047 2047 37777 1 DS %37777 ; check #00 (+16383 * +16383)02050 2050 37777 1 DS %37777 ; check #01 (+16383 * -16383)02051 2051 40000 0 DS %40000 ; check #02 (-16383 * +16383)02052 2052 40000 0 DS %40000 ; check #03 (-16383 * -16383)02053 2053 00000 1 DS %00000 ; check #04 (+0 * +0)02054 2054 00000 1 DS %00000 ; check #05 (+0 * -0)02055 2055 77777 0 DS %77777 ; check #06 (-0 * +0)02056 2056 77777 0 DS %77777 ; check #07 (-0 * -0) ; randomly selected checks (one word product)02057 2057 00007 0 DS %00007 ; check #08 (7 * 17)02060 2060 00021 1 DS %00021 ; check #09 (17 * 7)02061 2061 00035 1 DS %00035 ; check #10 (29 * 41)02062 2062 00051 0 DS %00051 ; check #11 (41 * 29)02063 2063 00065 1 DS %00065 ; check #12 (53 * 67)02064 2064 00103 0 DS %00103 ; check #13 (67 * 53)02065 2065 00117 0 DS %00117 ; check #14 (79 * 97)02066 2066 00141 0 DS %00141 ; check #15 (97 * 79)02067 2067 00153 0 DS %00153 ; check #16 (107 * 127)02070 2070 00177 0 DS %00177 ; check #17 (127 * 107) ; randomly selected checks (two word product)02071 2071 00375 0 DS %00375 ; check #18 (253 * 197)02072 2072 00305 1 DS %00305 ; check #19 (197 * 253)02073 2073 00655 1 DS %00655 ; check #20 (429 * 351)02074 2074 00537 0 DS %00537 ; check #21 (351 * 429)02075 2075 02455 1 DS %02455 ; check #22 (1325 * 1067)02076 2076 02053 0 DS %02053 ; check #23 (1067 * 1325)02077 2077 11151 1 DS %11151 ; check #24 (4713 * 3605)02100 2100 07025 1 DS %07025 ; check #25 (3605 * 4713)02101 2101 20032 1 DS %20032 ; check #26 (8218 * 7733)02102 2102 17065 1 DS %17065 ; check #27 (7733 * 8218)02103 2103 30273 1 DS %30273 ; check #28 (12475 * 11501)02104 2104 26355 0 DS %26355 ; check #29 (11501 * 12475)02105 2105 37553 0 DS %37553 ; check #30 (16235 * 15372)02106 2106 36014 1 DS %36014 ; check #31 (15372 * 16235) ; C(K) test values mp2 EQU * ; check boundary conditions02107 2107 37777 1 DS %37777 ; check #00 (+16383 * +16383)

Page 585: Apollo Guidance Computer AGC

02110 2110 40000 0 DS %40000 ; check #01 (+16383 * -16383)02111 2111 37777 1 DS %37777 ; check #02 (-16383 * +16383)02112 2112 40000 0 DS %40000 ; check #03 (-16383 * -16383)02113 2113 00000 1 DS %00000 ; check #04 (+0 * +0)02114 2114 77777 0 DS %77777 ; check #05 (+0 * -0)02115 2115 00000 1 DS %00000 ; check #06 (-0 * +0)02116 2116 77777 0 DS %77777 ; check #07 (-0 * -0) ; randomly selected checks (one word product)02117 2117 00021 1 DS %00021 ; check #08 (7 * 17)02120 2120 00007 0 DS %00007 ; check #09 (17 * 7)02121 2121 00051 0 DS %00051 ; check #10 (29 * 41)02122 2122 00035 1 DS %00035 ; check #11 (41 * 29)02123 2123 00103 0 DS %00103 ; check #12 (53 * 67)02124 2124 00065 1 DS %00065 ; check #13 (67 * 53)02125 2125 00141 0 DS %00141 ; check #14 (79 * 97)02126 2126 00117 0 DS %00117 ; check #15 (97 * 79)02127 2127 00177 0 DS %00177 ; check #16 (107 * 127)02130 2130 00153 0 DS %00153 ; check #17 (127 * 107) ; randomly selected checks (two word product)02131 2131 00305 1 DS %00305 ; check #18 (253 * 197)02132 2132 00375 0 DS %00375 ; check #19 (197 * 253)02133 2133 00537 0 DS %00537 ; check #20 (429 * 351)02134 2134 00655 1 DS %00655 ; check #21 (351 * 429)02135 2135 02053 0 DS %02053 ; check #22 (1325 * 1067)02136 2136 02455 1 DS %02455 ; check #23 (1067 * 1325)02137 2137 07025 1 DS %07025 ; check #24 (4713 * 3605)02140 2140 11151 1 DS %11151 ; check #25 (3605 * 4713)02141 2141 17065 1 DS %17065 ; check #26 (8218 * 7733)02142 2142 20032 1 DS %20032 ; check #27 (7733 * 8218)02143 2143 26355 0 DS %26355 ; check #28 (12475 * 11501)02144 2144 30273 1 DS %30273 ; check #29 (11501 * 12475)02145 2145 36014 1 DS %36014 ; check #30 (16235 * 15372)02146 2146 37553 0 DS %37553 ; check #31 (15372 * 16235) ; A = upper product MPchkA EQU * ; check boundary conditions02147 2147 37776 0 DS %37776 ; check #0002150 2150 40001 1 DS %40001 ; check #0102151 2151 40001 1 DS %40001 ; check #0202152 2152 37776 0 DS %37776 ; check #0302153 2153 00000 1 DS %00000 ; check #0402154 2154 77777 0 DS %77777 ; check #0502155 2155 77777 0 DS %77777 ; check #0602156 2156 00000 1 DS %00000 ; check #07 ; randomly selected checks02157 2157 00000 1 DS %00000 ; check #08 (7 * 17)02160 2160 00000 1 DS %00000 ; check #09 (17 * 7)02161 2161 00000 1 DS %00000 ; check #10 (29 * 41)02162 2162 00000 1 DS %00000 ; check #11 (41 * 29)02163 2163 00000 1 DS %00000 ; check #12 (53 * 67)02164 2164 00000 1 DS %00000 ; check #13 (67 * 53)02165 2165 00000 1 DS %00000 ; check #14 (79 * 97)02166 2166 00000 1 DS %00000 ; check #15 (97 * 79)02167 2167 00000 1 DS %00000 ; check #16 (107 * 127)02170 2170 00000 1 DS %00000 ; check #17 (127 * 107) ; randomly selected checks (two word product)02171 2171 00003 1 DS %00003 ; check #18 (253 * 197)02172 2172 00003 1 DS %00003 ; check #19 (197 * 253)02173 2173 00011 1 DS %00011 ; check #20 (429 * 351)02174 2174 00011 1 DS %00011 ; check #21 (351 * 429)02175 2175 00126 1 DS %00126 ; check #22 (1325 * 1067)02176 2176 00126 1 DS %00126 ; check #23 (1067 * 1325)02177 2177 02015 1 DS %02015 ; check #24 (4713 * 3605)02200 2200 02015 1 DS %02015 ; check #25 (3605 * 4713)02201 2201 07446 0 DS %07446 ; check #26 (8218 * 7733)02202 2202 07446 0 DS %07446 ; check #27 (7733 * 8218)02203 2203 21065 1 DS %21065 ; check #28 (12475 * 11501)02204 2204 21065 1 DS %21065 ; check #29 (11501 * 12475)02205 2205 35600 1 DS %35600 ; check #30 (16235 * 15372)02206 2206 35600 1 DS %35600 ; check #31 (15372 * 16235) ; LP = lower product MPchkLP EQU * ; check boundary conditions02207 2207 00001 0 DS %00001 ; check #00

Page 586: Apollo Guidance Computer AGC

02210 2210 77776 1 DS %77776 ; check #0102211 2211 77776 1 DS %77776 ; check #0202212 2212 00001 0 DS %00001 ; check #0302213 2213 00000 1 DS %00000 ; check #0402214 2214 77777 0 DS %77777 ; check #0502215 2215 77777 0 DS %77777 ; check #0602216 2216 00000 1 DS %00000 ; check #07 ; randomly selected checks02217 2217 00167 1 DS %00167 ; check #08 (7 * 17)02220 2220 00167 1 DS %00167 ; check #09 (17 * 7)02221 2221 02245 0 DS %02245 ; check #10 (29 * 41)02222 2222 02245 0 DS %02245 ; check #11 (41 * 29)02223 2223 06737 1 DS %06737 ; check #12 (53 * 67)02224 2224 06737 1 DS %06737 ; check #13 (67 * 53)02225 2225 16757 0 DS %16757 ; check #14 (79 * 97)02226 2226 16757 0 DS %16757 ; check #15 (97 * 79)02227 2227 32425 0 DS %32425 ; check #16 (107 * 127)02230 2230 32425 0 DS %32425 ; check #17 (127 * 107) ; randomly selected checks (two word product)02231 2231 01261 0 DS %01261 ; check #18 (253 * 197)02232 2232 01261 0 DS %01261 ; check #19 (197 * 253)02233 2233 06063 1 DS %06063 ; check #20 (429 * 351)02234 2234 06063 1 DS %06063 ; check #21 (351 * 429)02235 2235 11217 0 DS %11217 ; check #22 (1325 * 1067)02236 2236 11217 0 DS %11217 ; check #23 (1067 * 1325)02237 2237 00235 0 DS %00235 ; check #24 (4713 * 3605)02240 2240 00235 0 DS %00235 ; check #24 (3605 * 4713)02241 2241 30542 1 DS %30542 ; check #26 (8218 * 7733)02242 2242 30542 1 DS %30542 ; check #27 (7733 * 8218)02243 2243 00437 1 DS %00437 ; check #28 (12475 * 11501)02244 2244 00437 1 DS %00437 ; check #29 (11501 * 12475)02245 2245 06404 1 DS %06404 ; check #30 (16235 * 15372)02246 2246 06404 1 DS %06404 ; check #31 (15372 * 16235) chkMP EQU * 02247 2247 3 0,0001 0 XCH Q 02250 2250 5 0,0101 1 TS savQ ; save return address 02251 2251 3 1,2045 1 CAF MPcode 02252 2252 5 0,0100 0 TS curtest ; set test code to this test ; Decrementing loop ; - always executes at least once (tests at end of loop)

; - loops 'MPstart+1' times; decrements MPindex02253 2253 3 1,2046 1 XCH MPstart ; initialize loop counter ;------------------------------ ; MP check starts here ; uses MPindex to access test values MPloop EQU * 02254 2254 5 0,0102 1 TS MPindex ; save new index 02255 2255 3 2,5777 0 CAF EXTENDER 02256 2256 6 0,0102 1 AD MPindex 02257 2257 5 0,0103 0 TS MPXTND 02260 2260 2 0,0102 0 INDEX MPindex 02261 2261 3 1,2047 0 CAF mp1 02262 2262 2 0,0103 1 INDEX MPXTND ; EXTEND using MPindex02263 2263 4 1,2107 1 MP mp2 ; verify C(A)02264 2264 4 0,0000 0 COM ; get -A02265 2265 2 0,0102 0 INDEX MPindex 02266 2266 6 1,2147 1 AD MPchkA ; put (-A) + expected value in A02267 2267 1 0,0000 0 CCS A ; compare02270 2270 0 1,2036 0 TC fail ; >0 (A < expected value)02271 2271 0 1,2036 0 TC fail ; +002272 2272 0 1,2036 0 TC fail ; <0 (A > expected value) ; verify C(LP)02273 2273 4 0,0003 0 CS LP ; get -A02274 2274 2 0,0102 0 INDEX MPindex 02275 2275 6 1,2207 0 AD MPchkLP ; put (-A) + expected value in A02276 2276 1 0,0000 0 CCS A ; compare

Page 587: Apollo Guidance Computer AGC

02277 2277 0 1,2036 0 TC fail ; >0 (A < expected value)02300 2300 0 1,2036 0 TC fail ; +002301 2301 0 1,2036 0 TC fail ; <0 (A > expected value) ; end of MP check ;------------------------------ 02302 2302 1 0,0102 0 CCS MPindex ; done?02303 2303 0 1,2254 0 TC MPloop ; not yet, do next check 02304 2304 3 0,0101 1 XCH savQ 02305 2305 5 0,0001 0 TS Q ; restore return address02306 2306 0 0,0000 0 RETURN ; ---------------------------------------------- ; TEST DV INSTRUCTION SUBROUTINE ; L: DV K ; Verifies the following: ; - Set C(A) = b(A) / C(K) ; - Set C(Q) = - abs(remainder) ; - Set C(LP) > 0 if quotient is positive ; - Set C(LP) < 0 if quotient is negative ; - Take next instruction from L+1 02307 2307 00002 0 DVcode DS DVtst ; code for this test ; DV test values ; 02310 2310 00037 0 DVstart DS 31 ; loop DVstart+1 times ; C(A) test values div1 EQU * 02311 2311 00000 1 DS %00000 ; check #00 (+0/+0)02312 2312 00000 1 DS %00000 ; check #01 (+0/-0)02313 2313 77777 0 DS %77777 ; check #02 (-0/+0)02314 2314 77777 0 DS %77777 ; check #03 (-0/-0) 02315 2315 00000 1 DS %00000 ; check #04 (+0/+1)02316 2316 00000 1 DS %00000 ; check #05 (+0/-1)02317 2317 77777 0 DS %77777 ; check #06 (-0/+1)02320 2320 77777 0 DS %77777 ; check #07 (-0/-1) 02321 2321 00000 1 DS %00000 ; check #08 (+0/+16383)02322 2322 00000 1 DS %00000 ; check #09 (+0/-16383)02323 2323 77777 0 DS %77777 ; check #10 (-0/+16383)02324 2324 77777 0 DS %77777 ; check #11 (-0/-16383) 02325 2325 37776 0 DS %37776 ; check #12 (+16382/+16383)02326 2326 37776 0 DS %37776 ; check #13 (+16382/-16383)02327 2327 40001 1 DS %40001 ; check #14 (-16382/+16383)02330 2330 40001 1 DS %40001 ; check #15 (-16382/-16383) 02331 2331 37777 1 DS %37777 ; check #16 (+16383/+16383)02332 2332 37777 1 DS %37777 ; check #17 (+16383/-16383)02333 2333 40000 0 DS %40000 ; check #18 (-16383/+16383)02334 2334 40000 0 DS %40000 ; check #19 (-16383/-16383) 02335 2335 00001 0 DS %00001 ; check #20 (+1/+2)02336 2336 00001 0 DS %00001 ; check #21 (+1/+3)02337 2337 00001 0 DS %00001 ; check #22 (+1/+4)02340 2340 00001 0 DS %00001 ; check #23 (+1/+5)02341 2341 00001 0 DS %00001 ; check #24 (+1/+6)02342 2342 00001 0 DS %00001 ; check #25 (+1/+7)02343 2343 00001 0 DS %00001 ; check #26 (+1/+8) 02344 2344 00001 0 DS %00001 ; check #27 (+1/+6)02345 2345 00002 0 DS %00002 ; check #28 (+2/+12)02346 2346 00004 0 DS %00004 ; check #29 (+4/+24)02347 2347 00010 0 DS %00010 ; check #30 (+8/+48)02350 2350 00020 0 DS %00020 ; check #31 (+16/+96) ; C(K) test values div2 EQU * 02351 2351 00000 1 DS %00000 ; check #00 (+0/+0)02352 2352 77777 0 DS %77777 ; check #01 (+0/-0)02353 2353 00000 1 DS %00000 ; check #02 (-0/+0)02354 2354 77777 0 DS %77777 ; check #03 (-0/-0)

Page 588: Apollo Guidance Computer AGC

02355 2355 00001 0 DS %00001 ; check #04 (+0/+1)02356 2356 77776 1 DS %77776 ; check #05 (+0/-1)02357 2357 00001 0 DS %00001 ; check #06 (-0/+1)02360 2360 77776 1 DS %77776 ; check #07 (-0/-1) 02361 2361 37777 1 DS %37777 ; check #08 (+0/+16383)02362 2362 40000 0 DS %40000 ; check #09 (+0/-16383)02363 2363 37777 1 DS %37777 ; check #10 (-0/+16383)02364 2364 40000 0 DS %40000 ; check #11 (-0/-16383) 02365 2365 37777 1 DS %37777 ; check #12 (+16382/+16383)02366 2366 40000 0 DS %40000 ; check #13 (+16382/-16383)02367 2367 37777 1 DS %37777 ; check #14 (-16382/+16383)02370 2370 40000 0 DS %40000 ; check #15 (-16382/-16383) 02371 2371 37777 1 DS %37777 ; check #16 (+16383/+16383)02372 2372 40000 0 DS %40000 ; check #17 (+16383/-16383)02373 2373 37777 1 DS %37777 ; check #18 (-16383/+16383)02374 2374 40000 0 DS %40000 ; check #19 (-16383/-16383) 02375 2375 00002 0 DS %00002 ; check #20 (+1/+2)02376 2376 00003 1 DS %00003 ; check #21 (+1/+3)02377 2377 00004 0 DS %00004 ; check #22 (+1/+4)02400 2400 00005 1 DS %00005 ; check #23 (+1/+5)02401 2401 00006 1 DS %00006 ; check #24 (+1/+6)02402 2402 00007 0 DS %00007 ; check #25 (+1/+7)02403 2403 00010 0 DS %00010 ; check #26 (+1/+8) 02404 2404 00006 1 DS %00006 ; check #27 (+1/+6)02405 2405 00014 1 DS %00014 ; check #28 (+2/+12)02406 2406 00030 1 DS %00030 ; check #29 (+4/+24)02407 2407 00060 1 DS %00060 ; check #30 (+8/+48)02410 2410 00140 1 DS %00140 ; check #31 (+16/+96) ; A = quotient DVchkA EQU * 02411 2411 37777 1 DS %37777 ; check #00 (+0/+0)02412 2412 40000 0 DS %40000 ; check #01 (+0/-0)02413 2413 40000 0 DS %40000 ; check #02 (-0/+0)02414 2414 37777 1 DS %37777 ; check #03 (-0/-0) 02415 2415 00000 1 DS %00000 ; check #04 (+0/+1)02416 2416 77777 0 DS %77777 ; check #05 (+0/-1)02417 2417 77777 0 DS %77777 ; check #06 (-0/+1)02420 2420 00000 1 DS %00000 ; check #07 (-0/-1) 02421 2421 00000 1 DS %00000 ; check #08 (+0/+16383)02422 2422 77777 0 DS %77777 ; check #09 (+0/-16383)02423 2423 77777 0 DS %77777 ; check #10 (-0/+16383)02424 2424 00000 1 DS %00000 ; check #11 (-0/-16383) 02425 2425 37776 0 DS %37776 ; check #12 (+16382/+16383)02426 2426 40001 1 DS %40001 ; check #13 (+16382/-16383)02427 2427 40001 1 DS %40001 ; check #14 (-16382/+16383)02430 2430 37776 0 DS %37776 ; check #15 (-16382/-16383) 02431 2431 37777 1 DS %37777 ; check #16 (+16383/+16383)02432 2432 40000 0 DS %40000 ; check #17 (+16383/-16383)02433 2433 40000 0 DS %40000 ; check #18 (-16383/+16383)02434 2434 37777 1 DS %37777 ; check #19 (-16383/-16383) 02435 2435 20000 0 DS %20000 ; check #20 (+1/+2)02436 2436 12525 0 DS %12525 ; check #21 (+1/+3)02437 2437 10000 0 DS %10000 ; check #22 (+1/+4)02440 2440 06314 1 DS %06314 ; check #23 (+1/+5)02441 2441 05252 1 DS %05252 ; check #24 (+1/+6)02442 2442 04444 1 DS %04444 ; check #25 (+1/+7)02443 2443 04000 0 DS %04000 ; check #26 (+1/+8) 02444 2444 05252 1 DS %05252 ; check #27 (+1/+6)02445 2445 05252 1 DS %05252 ; check #28 (+2/+12)02446 2446 05252 1 DS %05252 ; check #29 (+4/+24)02447 2447 05252 1 DS %05252 ; check #30 (+8/+48)02450 2450 05252 1 DS %05252 ; check #31 (+16/+96)

Page 589: Apollo Guidance Computer AGC

; Q = remainder DVchkQ EQU * 02451 2451 77777 0 DS %77777 ; check #00 (+0/+0)02452 2452 77777 0 DS %77777 ; check #01 (+0/-0)02453 2453 77777 0 DS %77777 ; check #02 (-0/+0)02454 2454 77777 0 DS %77777 ; check #03 (-0/-0) 02455 2455 77777 0 DS %77777 ; check #04 (+0/+1)02456 2456 77777 0 DS %77777 ; check #05 (+0/-1)02457 2457 77777 0 DS %77777 ; check #06 (-0/+1)02460 2460 77777 0 DS %77777 ; check #07 (-0/-1) 02461 2461 77777 0 DS %77777 ; check #08 (+0/+16383)02462 2462 77777 0 DS %77777 ; check #09 (+0/-16383)02463 2463 77777 0 DS %77777 ; check #10 (-0/+16383)02464 2464 77777 0 DS %77777 ; check #11 (-0/-16383) 02465 2465 40001 1 DS %40001 ; check #12 (+16382/+16383)02466 2466 40001 1 DS %40001 ; check #13 (+16382/-16383)02467 2467 40001 1 DS %40001 ; check #14 (-16382/+16383)02470 2470 40001 1 DS %40001 ; check #15 (-16382/-16383) 02471 2471 40000 0 DS %40000 ; check #16 (+16383/+16383)02472 2472 40000 0 DS %40000 ; check #17 (+16383/-16383)02473 2473 40000 0 DS %40000 ; check #18 (-16383/+16383)02474 2474 40000 0 DS %40000 ; check #19 (-16383/-16383) 02475 2475 77777 0 DS %77777 ; check #20 (+1/+2)02476 2476 77776 1 DS %77776 ; check #21 (+1/+3)02477 2477 77777 0 DS %77777 ; check #22 (+1/+4)02500 2500 77773 1 DS %77773 ; check #23 (+1/+5)02501 2501 77773 1 DS %77773 ; check #24 (+1/+6)02502 2502 77773 1 DS %77773 ; check #25 (+1/+7)02503 2503 77777 0 DS %77777 ; check #26 (+1/+8) 02504 2504 77773 1 DS %77773 ; check #27 (+1/+6)02505 2505 77767 1 DS %77767 ; check #28 (+2/+12)02506 2506 77757 1 DS %77757 ; check #29 (+4/+24)02507 2507 77737 1 DS %77737 ; check #30 (+8/+48)02510 2510 77677 1 DS %77677 ; check #31 (+16/+96) ; LP = sign DVchkLP EQU * 02511 2511 00001 0 DS %00001 ; check #00 (+0/+0)02512 2512 40000 0 DS %40000 ; check #01 (+0/-0)02513 2513 40001 1 DS %40001 ; check #02 (-0/+0)02514 2514 00001 0 DS %00001 ; check #03 (-0/-0) 02515 2515 00001 0 DS %00001 ; check #04 (+0/+1)02516 2516 40000 0 DS %40000 ; check #05 (+0/-1)02517 2517 40001 1 DS %40001 ; check #06 (-0/+1)02520 2520 00001 0 DS %00001 ; check #07 (-0/-1) 02521 2521 00001 0 DS %00001 ; check #08 (+0/+16383)02522 2522 40000 0 DS %40000 ; check #09 (+0/-16383)02523 2523 40001 1 DS %40001 ; check #10 (-0/+16383)02524 2524 00001 0 DS %00001 ; check #11 (-0/-16383) 02525 2525 00001 0 DS %00001 ; check #12 (+16382/+16383)02526 2526 40000 0 DS %40000 ; check #13 (+16382/-16383)02527 2527 40001 1 DS %40001 ; check #14 (-16382/+16383)02530 2530 00001 0 DS %00001 ; check #15 (-16382/-16383) 02531 2531 00001 0 DS %00001 ; check #16 (+16383/+16383)02532 2532 40000 0 DS %40000 ; check #17 (+16383/-16383)02533 2533 40001 1 DS %40001 ; check #18 (-16383/+16383)02534 2534 00001 0 DS %00001 ; check #19 (-16383/-16383) 02535 2535 00001 0 DS %00001 ; check #20 (+1/+2)02536 2536 00001 0 DS %00001 ; check #21 (+1/+3)02537 2537 00001 0 DS %00001 ; check #22 (+1/+4)02540 2540 00001 0 DS %00001 ; check #23 (+1/+5)02541 2541 00001 0 DS %00001 ; check #24 (+1/+6)02542 2542 00001 0 DS %00001 ; check #25 (+1/+7)02543 2543 00001 0 DS %00001 ; check #26 (+1/+8)

Page 590: Apollo Guidance Computer AGC

02544 2544 00001 0 DS %00001 ; check #27 (+1/+6)02545 2545 00001 0 DS %00001 ; check #28 (+2/+12)02546 2546 00001 0 DS %00001 ; check #29 (+4/+24)02547 2547 00001 0 DS %00001 ; check #30 (+8/+48)02550 2550 00001 0 DS %00001 ; check #31 (+16/+96) chkDV EQU * 02551 2551 3 0,0001 0 XCH Q 02552 2552 5 0,0101 1 TS savQ ; save return address 02553 2553 3 1,2307 1 CAF DVcode 02554 2554 5 0,0100 0 TS curtest ; set code identifying test ; Decrementing loop ; - always executes at least once (tests at end of loop)

; - loops 'DVstart+1' times; decrements DVindex02555 2555 3 1,2310 1 XCH DVstart ; initialize loop counter ;------------------------------ ; DV check starts here ; uses DVindex to access test values DVloop EQU * 02556 2556 5 0,0105 0 TS DVindex ; save new index 02557 2557 3 2,5777 0 CAF EXTENDER 02560 2560 6 0,0105 0 AD DVindex 02561 2561 5 0,0106 0 TS DVXTND 02562 2562 2 0,0105 1 INDEX DVindex 02563 2563 3 1,2311 0 CAF div1 02564 2564 2 0,0106 1 INDEX DVXTND ; EXTEND using DVindex02565 2565 5 1,2351 1 DV div2 02566 2566 5 0,0104 1 TS DVsavA ; verify C(Q)02567 2567 4 0,0001 1 CS Q ; get -A02570 2570 2 0,0105 1 INDEX DVindex 02571 2571 6 1,2451 0 AD DVchkQ ; put (-A) + expected value in A02572 2572 1 0,0000 0 CCS A ; compare02573 2573 0 1,2036 0 TC fail ; >0 (A < expected value)02574 2574 0 1,2036 0 TC fail ; +002575 2575 0 1,2036 0 TC fail ; <0 (A > expected value) ; verify C(A)02576 2576 4 0,0104 0 CS DVsavA ; get -A02577 2577 2 0,0105 1 INDEX DVindex 02600 2600 6 1,2411 1 AD DVchkA ; put (-A) + expected value in A02601 2601 1 0,0000 0 CCS A ; compare02602 2602 0 1,2036 0 TC fail ; >0 (A < expected value)02603 2603 0 1,2036 0 TC fail ; +002604 2604 0 1,2036 0 TC fail ; <0 (A > expected value) ; verify C(LP)02605 2605 4 0,0003 0 CS LP ; get -A02606 2606 2 0,0105 1 INDEX DVindex 02607 2607 6 1,2511 0 AD DVchkLP ; put (-A) + expected value in A02610 2610 1 0,0000 0 CCS A ; compare02611 2611 0 1,2036 0 TC fail ; >0 (A < expected value)02612 2612 0 1,2036 0 TC fail ; +002613 2613 0 1,2036 0 TC fail ; <0 (A > expected value) ; end of DV check ;------------------------------ 02614 2614 1 0,0105 1 CCS DVindex ; done?02615 2615 0 1,2556 0 TC DVloop ; not yet, do next check 02616 2616 3 0,0101 1 XCH savQ 02617 2617 5 0,0001 0 TS Q ; restore return address02620 2620 0 0,0000 0 RETURN ; ---------------------------------------------- ; TEST SU INSTRUCTION SUBROUTINE

Page 591: Apollo Guidance Computer AGC

; L: SU K ; Verifies the following: ; - Set C(A) = b(A) - C(K) ; - Take next instruction from L+1 ; - if C(A) has positive overflow, ; -- increment overflow counter by 1 ; - if C(A) has negative overflow, ; -- decrement overflow counter by 1 02621 2621 00003 1 SUcode DS SUtst ; code for this test 02622 2622 00000 1 SUplus0 DS +0 02623 2623 00001 0 SUplus1 DS 1 02624 2624 77776 1 SUmin1 DS -1 02625 2625 25252 0 SU25252 DS %25252 ; +10922 decimal02626 2626 12525 0 SU12525 DS %12525 ; +5461 decimal02627 2627 37777 1 SU37777 DS %37777 ; largest positive number02630 2630 12524 1 SU12524 DS %12524 ; + overflow of %25252+%25252 02631 2631 52525 1 SU52525 DS %52525 ; -10922 decimal02632 2632 65252 1 SU65252 DS %65252 ; -5461 decimal02633 2633 40000 0 SU40000 DS %40000 ; largest negative number02634 2634 65253 0 SU65253 DS %65253 ; - overflow of %52525+65252 chkSU EQU * 02635 2635 3 0,0001 0 XCH Q 02636 2636 5 0,0101 1 TS savQ ; save return address 02637 2637 3 1,2621 0 CAF SUcode 02640 2640 5 0,0100 0 TS curtest ; set test code to this test ; NOTE: these test are similar to the checks for AD, but ; the AD augend value has been changed to negative and AD has ; been changed to SU. The results produced by this change ; are identical to AD, and so the checks are the same. ; TEST1: difference positive, no overflow ; sub: %25252 - %65252 = %37777 (sign + 14 magnitude)02641 2641 3 1,2625 1 CAF SU25252 02642 2642 2 0,0000 1 EXTEND 02643 2643 6 1,2632 1 SU SU65252 ; verify C(A) = %3777702644 2644 4 0,0000 0 COM ; get -A02645 2645 6 1,2627 0 AD SU37777 ; put (-A) + expected value in A02646 2646 1 0,0000 0 CCS A ; compare02647 2647 0 1,2036 0 TC fail ; >0 (A < expected value)02650 2650 0 1,2036 0 TC fail ; +002651 2651 0 1,2036 0 TC fail ; <0 (A > expected value) ; TEST2: difference negative, no overflow (sign + 14 magnitude) ; sub: %52525 - %12525 = %4000002652 2652 3 1,2631 1 CAF SU52525 02653 2653 2 0,0000 1 EXTEND 02654 2654 6 1,2626 1 SU SU12525 ; verify C(A) = %4000002655 2655 4 0,0000 0 COM ; get -A02656 2656 6 1,2633 0 AD SU40000 ; put (-A) + expected value in A02657 2657 1 0,0000 0 CCS A ; compare02660 2660 0 1,2036 0 TC fail ; >0 (A < expected value)02661 2661 0 1,2036 0 TC fail ; +002662 2662 0 1,2036 0 TC fail ; <0 (A > expected value) ; TEST3: difference positive, overflow ; initialize overflow counter and positive overflow storage02663 2663 3 1,2622 0 CAF SUplus0 02664 2664 5 0,0034 0 TS OVFCNTR 02665 2665 5 0,0107 1 TS SUk ; sub: %25252 - %52525 = %52524 (sign + 14 magnitude)02666 2666 3 1,2625 1 CAF SU25252 02667 2667 2 0,0000 1 EXTEND 02670 2670 6 1,2631 1 SU SU52525 02671 2671 5 0,0107 1 TS SUk ; store positive overflow02672 2672 0 1,2036 0 TC fail ; verify SUk = %1252402673 2673 4 0,0107 0 CS SUk ; get -A

Page 592: Apollo Guidance Computer AGC

02674 2674 6 1,2630 0 AD SU12524 ; put (-A) + expected value in A02675 2675 1 0,0000 0 CCS A ; compare02676 2676 0 1,2036 0 TC fail ; >0 (A < expected value)02677 2677 0 1,2036 0 TC fail ; +002700 2700 0 1,2036 0 TC fail ; <0 (A > expected value) ; verify overflow counter =%0000102701 2701 4 0,0034 1 CS OVFCNTR ; get -A02702 2702 6 1,2623 1 AD SUplus1 ; put (-A) + expected value in A02703 2703 1 0,0000 0 CCS A ; compare02704 2704 0 1,2036 0 TC fail ; >0 (A < expected value)02705 2705 0 1,2036 0 TC fail ; +002706 2706 0 1,2036 0 TC fail ; <0 (A > expected value) ; TEST4: difference negative, overflow02707 2707 3 1,2622 0 CAF SUplus0 02710 2710 5 0,0034 0 TS OVFCNTR 02711 2711 5 0,0107 1 TS SUk ; add: %52525 + %25252 = %25253 (sign + 14 magnitude)02712 2712 3 1,2631 1 CAF SU52525 02713 2713 2 0,0000 1 EXTEND 02714 2714 6 1,2625 1 SU SU25252 02715 2715 5 0,0107 1 TS SUk ; store negative overflow02716 2716 0 1,2036 0 TC fail ; verify SUk = %6525302717 2717 4 0,0107 0 CS SUk ; get -A02720 2720 6 1,2634 1 AD SU65253 ; put (-A) + expected value in A02721 2721 1 0,0000 0 CCS A ; compare02722 2722 0 1,2036 0 TC fail ; >0 (A < expected value)02723 2723 0 1,2036 0 TC fail ; +002724 2724 0 1,2036 0 TC fail ; <0 (A > expected value) ; verify overflow counter =%7777602725 2725 4 0,0034 1 CS OVFCNTR ; get -A02726 2726 6 1,2624 0 AD SUmin1 ; put (-A) + expected value in A02727 2727 1 0,0000 0 CCS A ; compare02730 2730 0 1,2036 0 TC fail ; >0 (A < expected value)02731 2731 0 1,2036 0 TC fail ; +002732 2732 0 1,2036 0 TC fail ; <0 (A > expected value) 02733 2733 3 0,0101 1 XCH savQ 02734 2734 5 0,0001 0 TS Q ; restore return address02735 2735 0 0,0000 0 RETURN ; ---------------------------------------------- ; PASSED ALL TESTS! 02736 2736 12345 0 PASScode DS PASS finish EQU * 02737 2737 3 1,2736 1 CAF PASScode 02740 2740 5 0,0100 0 TS curtest ; set current test code to PASS02741 2741 0 0,0000 0 RETURN ; ---------------------------------------------- ; INTERRUPT SERVICE ROUTINE goT3 EQU * goER EQU * goDS EQU * goKEY EQU * goUP EQU * endRUPT EQU * 02742 2742 3 0,0027 1 XCH QRUPT ; restore Q02743 2743 5 0,0001 0 TS Q 02744 2744 3 0,0026 0 XCH ARUPT ; restore A02745 2745 2 0,0000 1 RESUME ; finished, go back

Assembly complete. Errors = 0

Symbol table:START 000000 MPtst 000001 DVtst 000002 SUtst 000003 PASS 012345 EXTENDER 005777 OVFCNTR 000034 curtest 000100 savQ 000101

Page 593: Apollo Guidance Computer AGC

MPindex 000102 MPXTND 000103 DVsavA 000104 DVindex 000105 DVXTND 000106 SUk 000107 GOPROG 002000 T3RUPT 002004 ERRUPT 002010 DSRUPT 002014 KEYRUPT 002020 UPRUPT 002024 goMAIN 002030 fail 002036 end 002040 STRTcode 002041 begin 002042 MPcode 002045 MPstart 002046 mp1 002047 mp2 002107 MPchkA 002147 MPchkLP 002207 chkMP 002247 MPloop 002254 DVcode 002307 DVstart 002310 div1 002311 div2 002351 DVchkA 002411 DVchkQ 002451 DVchkLP 002511 chkDV 002551 DVloop 002556 SUcode 002621 SUplus0 002622 SUplus1 002623 SUmin1 002624 SU25252 002625 SU12525 002626 SU37777 002627 SU12524 002630 SU52525 002631 SU65252 002632 SU40000 002633 SU65253 002634 chkSU 002635 PASScode 002736 finish 002737 goT3 002742 goER 002742 goDS 002742 goKEY 002742 goUP 002742 endRUPT 002742 ARUPT 000026 Q 000001 QRUPT 000027 A 000000 LP 000003

Page 594: Apollo Guidance Computer AGC

TECO3 assembler listing

Block I Apollo Guidance Computer (AGC4) assembler version 1.6 for EPROM

First pass: generate symbol table.Second pass: generate object code.

; TECO3 (file:teco3.asm) ; ; Version: 1.0 ; Author: John Pultorak ; Date: 9/14/2001 ; ; PURPOSE: ; Test and checkout program for the Block 1 Apollo Guidance Computer. ; Tests editing registers: CYR, SR, CYL, SL. ; ; OPERATION: ; Enters an infinite loop at the end of the test. The A register ; contains the code for the test that failed, or the PASS code if all ; tests succeeded. See test codes below. ; ; ERRATA: ; - Written for the AGC4R assembler. The assembler directives and ; syntax differ somewhat from the original AGC assembler. ; - The tests attempt to check all threads, but are not exhaustive. ; ; SOURCES: ; Information on the Block 1 architecture: instruction set, instruction ; sequences, registers, register transfers, control pulses, memory and ; memory addressing, I/O assignments, interrupts, and involuntary ; counters was obtained from: ; ; A. Hopkins, R. Alonso, and H. Blair-Smith, "Logical Description ; for the Apollo Guidance Computer (AGC4)", R-393, ; MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963. ; ; Supplementary information was obtained from: ; ; R. Alonso, J. H. Laning, Jr. and H. Blair-Smith, "Preliminary ; MOD 3C Programmer's Manual", E-1077, MIT Instrumentation ; Laboratory, Cambridge, MA, Nov. 1961. ; ; B. I. Savage and A. Drake, "AGC4 Basic Training Manual, Volume I", ; E-2052, MIT Instrumentation Laboratory, Cambridge, ; MA, Jan. 1967. ; ; E. C. Hall, "MIT's Role in Project Apollo, Volume III, Computer ; Subsystem", R-700, MIT Charles Stark Draper Laboratory, ; Cambridge, MA, Aug. 1972. ; ; A. Hopkins, "Guidance Computer Design, Part VI", source unknown. ; ; A. I. Green and J. J. Rocchio, "Keyboard and Display System Program ; for AGC (Program Sunrise)", E-1574, MIT Instrumentation ; Laboratory, Cambridge, MA, Aug. 1964. ; ; E, C. Hall, "Journey to the Moon: The History of the Apollo ; Guidance Computer", AIAA, Reston VA, 1996. ; START EQU %00 CYRtst EQU %01 ; CYR check failed SRtst EQU %02 ; SR check failed CYLtst EQU %03 ; CYL check failed SLtst EQU %04 ; SL check failed PASS EQU %12345 ; PASSED all checks ; ---------------------------------------------- ORG EXTENDER 05777 5777 47777 0 DS %47777 ; needed for EXTEND

Page 595: Apollo Guidance Computer AGC

; ---------------------------------------------- ; ERASEABLE MEMORY -- DATA SEGMENT ORG %100 ; start of data area00100 0100 00000 1 curtest DS START ; current test00101 0101 00000 1 savQ DS %0 ; CYR test values00102 0102 00000 1 CYRval DS %0 ; current test value00103 0103 00000 1 iCYR DS %0 ; current index ; SR test values00104 0104 00000 1 SRval DS %0 ; current test value00105 0105 00000 1 iSR DS %0 ; current index ; CYL test values00106 0106 00000 1 CYLval DS %0 ; current test value00107 0107 00000 1 iCYL DS %0 ; current index ; SL test values00110 0110 00000 1 SLval DS %0 ; current test value00111 0111 00000 1 iSL DS %0 ; current index ; ---------------------------------------------- ; ENTRY POINTS ; program (re)start ORG GOPROG 02000 2000 0 1,2030 0 TC goMAIN ; interrupt service entry points ORG T3RUPT 02004 2004 5 0,0026 0 TS ARUPT 02005 2005 3 0,0001 0 XCH Q 02006 2006 5 0,0027 1 TS QRUPT 02007 2007 0 1,2424 1 TC goT3 ORG ERRUPT 02010 2010 5 0,0026 0 TS ARUPT 02011 2011 3 0,0001 0 XCH Q 02012 2012 5 0,0027 1 TS QRUPT 02013 2013 0 1,2424 1 TC goER ORG DSRUPT 02014 2014 5 0,0026 0 TS ARUPT 02015 2015 3 0,0001 0 XCH Q 02016 2016 5 0,0027 1 TS QRUPT 02017 2017 0 1,2424 1 TC goDS ORG KEYRUPT 02020 2020 5 0,0026 0 TS ARUPT 02021 2021 3 0,0001 0 XCH Q 02022 2022 5 0,0027 1 TS QRUPT 02023 2023 0 1,2424 1 TC goKEY ORG UPRUPT 02024 2024 5 0,0026 0 TS ARUPT 02025 2025 3 0,0001 0 XCH Q 02026 2026 5 0,0027 1 TS QRUPT 02027 2027 0 1,2424 1 TC goUP ; ---------------------------------------------- ; FIXED MEMORY -- SHARED DATA SEGMENT ; ---------------------------------------------- ; MAIN PROGRAM goMAIN EQU * 02030 2030 2 0,0000 0 INHINT ; disable interrupts 02031 2031 0 1,2043 1 TCR begin ; Test extracode instructions.02032 2032 0 1,2070 1 TCR chkCYR

Page 596: Apollo Guidance Computer AGC

02033 2033 0 1,2162 0 TCR chkSR 02034 2034 0 1,2255 1 TCR chkCYL 02035 2035 0 1,2347 0 TCR chkSL ; Passed all tests.02036 2036 0 1,2421 1 TCR finish fail EQU * 02037 2037 3 0,0100 0 XCH curtest ; load last passed test into A02040 2040 5 0,0100 0 TS curtest end EQU * 02041 2041 0 1,2041 0 TC end ; finished, TC trap ; ---------------------------------------------- ; INITIALIZE FOR START OF TESTING 02042 2042 00000 1 STRTcode DS START begin EQU * 02043 2043 3 1,2042 0 XCH STRTcode 02044 2044 5 0,0100 0 TS curtest ; set current test code to START02045 2045 0 0,0000 0 RETURN ; ---------------------------------------------- ; TEST CYR EDITING FUNCTION SUBROUTINE ; Rotate a test value right through CYR 15 times. ; Test the value against an expected value for each time. ; After 15 rotations, the value should equal the initial ; value. 02046 2046 00001 0 CYRcode DS CYRtst ; code for this test ; CYR test values02047 2047 03431 1 CYRinit DS %03431 ; init test value02050 2050 00016 0 CYRindx DS 14 ; loop CYRindx+1 times ; check CYR against these values CYRbase EQU * 02051 2051 03431 1 DS %03431 ; check #0 (back to start)02052 2052 07062 1 DS %07062 ; check #102053 2053 16144 1 DS %16144 ; check #202054 2054 34310 1 DS %34310 ; check #302055 2055 70620 1 DS %70620 ; check #402056 2056 61441 1 DS %61441 ; check #502057 2057 43103 1 DS %43103 ; check #602060 2060 06207 1 DS %06207 ; check #702061 2061 14416 1 DS %14416 ; check #802062 2062 31034 1 DS %31034 ; check #902063 2063 62070 1 DS %62070 ; check #1002064 2064 44161 1 DS %44161 ; check #1102065 2065 10343 1 DS %10343 ; check #1202066 2066 20706 1 DS %20706 ; check #1302067 2067 41614 1 DS %41614 ; check #14 chkCYR EQU * 02070 2070 3 0,0001 0 XCH Q 02071 2071 5 0,0101 1 TS savQ ; save return address 02072 2072 3 1,2046 1 CAF CYRcode 02073 2073 5 0,0100 0 TS curtest ; set test code to this test 02074 2074 3 1,2047 0 XCH CYRinit ; init value to rotate02075 2075 5 0,0102 1 TS CYRval 02076 2076 3 1,2050 0 XCH CYRindx ; load init index CYRloop EQU * 02077 2077 5 0,0103 0 TS iCYR ; save index ; rotate A right (CYR)02100 2100 3 0,0102 1 XCH CYRval 02101 2101 5 0,0020 0 TS CYR ; rotate02102 2102 3 0,0020 0 XCH CYR ; put result in A02103 2103 5 0,0102 1 TS CYRval

Page 597: Apollo Guidance Computer AGC

; verify C(A)02104 2104 4 0,0000 0 COM ; get -A02105 2105 2 0,0103 1 INDEX iCYR 02106 2106 6 1,2051 1 AD CYRbase ; put (-A) + expected value in A02107 2107 1 0,0000 0 CCS A ; compare02110 2110 0 1,2037 1 TC fail ; >0 (A < expected value)02111 2111 0 1,2037 1 TC fail ; +002112 2112 0 1,2037 1 TC fail ; <0 (A > expected value) ; loop back to test next value02113 2113 1 0,0103 1 CCS iCYR ; done?02114 2114 0 1,2077 0 TC CYRloop ; not yet, do next check 02115 2115 3 0,0101 1 XCH savQ 02116 2116 5 0,0001 0 TS Q ; restore return address02117 2117 0 0,0000 0 RETURN ; ---------------------------------------------- ; TEST SR EDITING FUNCTION SUBROUTINE ; Shift a test value right through SR 15 times. ; Test the value against an expected value for each time. ; After 15 shifts, the value should equal the sign (SG). 02120 2120 00002 0 SRcode DS SRtst ; code for this test ; SR test values02121 2121 03431 1 SRinitP DS %03431 ; positive init test value02122 2122 44346 0 SRinitN DS %44346 ; negative init test value02123 2123 00016 0 SRindx DS 14 ; loop SRindx+1 times ; check SR against these values (positive) SRbaseP EQU * 02124 2124 00000 1 DS %00000 ; check #0 (back to start)02125 2125 00000 1 DS %00000 ; check #102126 2126 00000 1 DS %00000 ; check #202127 2127 00000 1 DS %00000 ; check #302130 2130 00000 1 DS %00000 ; check #402131 2131 00001 0 DS %00001 ; check #502132 2132 00003 1 DS %00003 ; check #602133 2133 00007 0 DS %00007 ; check #702134 2134 00016 0 DS %00016 ; check #802135 2135 00034 0 DS %00034 ; check #902136 2136 00070 0 DS %00070 ; check #1002137 2137 00161 1 DS %00161 ; check #1102140 2140 00343 0 DS %00343 ; check #1202141 2141 00706 0 DS %00706 ; check #1302142 2142 01614 0 DS %01614 ; check #14 ; check SR against these values (negative) SRbaseN EQU * 02143 2143 77777 0 DS %77777 ; check #0 (back to start)02144 2144 77777 0 DS %77777 ; check #102145 2145 77776 1 DS %77776 ; check #202146 2146 77774 0 DS %77774 ; check #302147 2147 77771 0 DS %77771 ; check #402150 2150 77762 1 DS %77762 ; check #502151 2151 77744 0 DS %77744 ; check #602152 2152 77710 1 DS %77710 ; check #702153 2153 77621 1 DS %77621 ; check #802154 2154 77443 1 DS %77443 ; check #902155 2155 77107 1 DS %77107 ; check #1002156 2156 76216 0 DS %76216 ; check #1102157 2157 74434 1 DS %74434 ; check #1202160 2160 71071 1 DS %71071 ; check #1302161 2161 62163 1 DS %62163 ; check #14 chkSR EQU * 02162 2162 3 0,0001 0 XCH Q 02163 2163 5 0,0101 1 TS savQ ; save return address 02164 2164 3 1,2120 0 CAF SRcode 02165 2165 5 0,0100 0 TS curtest ; set test code to this test ; TEST 1: shift a postive value.02166 2166 3 1,2121 1 XCH SRinitP ; init value to shift02167 2167 5 0,0104 1 TS SRval

Page 598: Apollo Guidance Computer AGC

02170 2170 3 1,2123 0 XCH SRindx ; load init index SRloopP EQU * 02171 2171 5 0,0105 0 TS iSR ; save index ; shift A right (SR)02172 2172 3 0,0104 1 XCH SRval 02173 2173 5 0,0021 1 TS SR ; shift02174 2174 3 0,0021 1 XCH SR ; put result in A02175 2175 5 0,0104 1 TS SRval ; verify C(A)02176 2176 4 0,0000 0 COM ; get -A02177 2177 2 0,0105 1 INDEX iSR 02200 2200 6 1,2124 1 AD SRbaseP ; put (-A) + expected value in A02201 2201 1 0,0000 0 CCS A ; compare02202 2202 0 1,2037 1 TC fail ; >0 (A < expected value)02203 2203 0 1,2037 1 TC fail ; +002204 2204 0 1,2037 1 TC fail ; <0 (A > expected value) ; loop back to test next value02205 2205 1 0,0105 1 CCS iSR ; done?02206 2206 0 1,2171 1 TC SRloopP ; not yet, do next check ; TEST 2: shift a negative value02207 2207 3 1,2122 1 XCH SRinitN ; init value to shift02210 2210 5 0,0104 1 TS SRval 02211 2211 3 1,2123 0 XCH SRindx ; load init index SRloopN EQU * 02212 2212 5 0,0105 0 TS iSR ; save index ; shift A left (SR)02213 2213 3 0,0104 1 XCH SRval 02214 2214 5 0,0021 1 TS SR ; shift02215 2215 3 0,0021 1 XCH SR ; put result in A02216 2216 5 0,0104 1 TS SRval ; verify C(A)02217 2217 4 0,0000 0 COM ; get -A02220 2220 2 0,0105 1 INDEX iSR 02221 2221 6 1,2143 0 AD SRbaseN ; put (-A) + expected value in A02222 2222 1 0,0000 0 CCS A ; compare02223 2223 0 1,2037 1 TC fail ; >0 (A < expected value)02224 2224 0 1,2037 1 TC fail ; +002225 2225 0 1,2037 1 TC fail ; <0 (A > expected value) ; loop back to test next value02226 2226 1 0,0105 1 CCS iSR ; done?02227 2227 0 1,2212 1 TC SRloopN ; not yet, do next check 02230 2230 3 0,0101 1 XCH savQ 02231 2231 5 0,0001 0 TS Q ; restore return address02232 2232 0 0,0000 0 RETURN ; ---------------------------------------------- ; TEST CYL EDITING FUNCTION SUBROUTINE ; Rotate a test value left through CYL 15 times. ; Test the value against an expected value for each time. ; After 15 rotations, the value should equal the initial ; value. 02233 2233 00003 1 CYLcode DS CYLtst ; code for this test ; CYL test values02234 2234 03431 1 CYLinit DS %03431 ; init test value02235 2235 00016 0 CYLindx DS 14 ; loop CYLindx+1 times ; check CYL against these values CYLbase EQU * 02236 2236 03431 1 DS %03431 ; check #0 (back to start)02237 2237 41614 1 DS %41614 ; check #1

Page 599: Apollo Guidance Computer AGC

02240 2240 20706 1 DS %20706 ; check #202241 2241 10343 1 DS %10343 ; check #302242 2242 44161 1 DS %44161 ; check #402243 2243 62070 1 DS %62070 ; check #502244 2244 31034 1 DS %31034 ; check #602245 2245 14416 1 DS %14416 ; check #702246 2246 06207 1 DS %06207 ; check #802247 2247 43103 1 DS %43103 ; check #902250 2250 61441 1 DS %61441 ; check #1002251 2251 70620 1 DS %70620 ; check #1102252 2252 34310 1 DS %34310 ; check #1202253 2253 16144 1 DS %16144 ; check #1302254 2254 07062 1 DS %07062 ; check #14 chkCYL EQU * 02255 2255 3 0,0001 0 XCH Q 02256 2256 5 0,0101 1 TS savQ ; save return address 02257 2257 3 1,2233 1 CAF CYLcode 02260 2260 5 0,0100 0 TS curtest ; set test code to this test 02261 2261 3 1,2234 0 XCH CYLinit ; init value to rotate02262 2262 5 0,0106 0 TS CYLval 02263 2263 3 1,2235 1 XCH CYLindx ; load init index CYLloop EQU * 02264 2264 5 0,0107 1 TS iCYL ; save index ; rotate A left (CYL)02265 2265 3 0,0106 0 XCH CYLval 02266 2266 5 0,0022 1 TS CYL ; rotate02267 2267 3 0,0022 1 XCH CYL ; put result in A02270 2270 5 0,0106 0 TS CYLval ; verify C(A)02271 2271 4 0,0000 0 COM ; get -A02272 2272 2 0,0107 0 INDEX iCYL 02273 2273 6 1,2236 1 AD CYLbase ; put (-A) + expected value in A02274 2274 1 0,0000 0 CCS A ; compare02275 2275 0 1,2037 1 TC fail ; >0 (A < expected value)02276 2276 0 1,2037 1 TC fail ; +002277 2277 0 1,2037 1 TC fail ; <0 (A > expected value) ; loop back to test next value02300 2300 1 0,0107 0 CCS iCYL ; done?02301 2301 0 1,2264 0 TC CYLloop ; not yet, do next check 02302 2302 3 0,0101 1 XCH savQ 02303 2303 5 0,0001 0 TS Q ; restore return address02304 2304 0 0,0000 0 RETURN ; ---------------------------------------------- ; TEST SL EDITING FUNCTION SUBROUTINE ; Shift a test value left through SL 15 times. ; Test the value against an expected value for each time. ; After 15 shifts, the value should equal the sign (SG). 02305 2305 00004 0 SLcode DS SLtst ; code for this test ; SL test values02306 2306 03431 1 SLinitP DS %03431 ; positive init test value02307 2307 44346 0 SLinitN DS %44346 ; negative init test value02310 2310 00016 0 SLindx DS 14 ; loop SLindx+1 times ; check SL against these values (positive) SLbaseP EQU * 02311 2311 00000 1 DS %00000 ; check #0 (back to start)02312 2312 00000 1 DS %00000 ; check #102313 2313 20000 0 DS %20000 ; check #202314 2314 10000 0 DS %10000 ; check #302315 2315 04000 0 DS %04000 ; check #402316 2316 22000 1 DS %22000 ; check #502317 2317 31000 0 DS %31000 ; check #602320 2320 14400 0 DS %14400 ; check #702321 2321 06200 0 DS %06200 ; check #8

Page 600: Apollo Guidance Computer AGC

02322 2322 03100 0 DS %03100 ; check #902323 2323 21440 1 DS %21440 ; check #1002324 2324 30620 0 DS %30620 ; check #1102325 2325 34310 1 DS %34310 ; check #1202326 2326 16144 1 DS %16144 ; check #1302327 2327 07062 1 DS %07062 ; check #14 ; check SL against these values (negative) SLbaseN EQU * 02330 2330 77777 0 DS %77777 ; check #0 (back to start)02331 2331 77777 0 DS %77777 ; check #102332 2332 57777 1 DS %57777 ; check #202333 2333 67777 1 DS %67777 ; check #302334 2334 73777 1 DS %73777 ; check #402335 2335 55777 0 DS %55777 ; check #502336 2336 46777 1 DS %46777 ; check #602337 2337 63377 1 DS %63377 ; check #702340 2340 71577 1 DS %71577 ; check #802341 2341 74677 1 DS %74677 ; check #902342 2342 56337 0 DS %56337 ; check #1002343 2343 47157 1 DS %47157 ; check #1102344 2344 43467 0 DS %43467 ; check #1202345 2345 61633 0 DS %61633 ; check #1302346 2346 50715 1 DS %50715 ; check #14 chkSL EQU * 02347 2347 3 0,0001 0 XCH Q 02350 2350 5 0,0101 1 TS savQ ; save return address 02351 2351 3 1,2305 0 CAF SLcode 02352 2352 5 0,0100 0 TS curtest ; set test code to this test ; TEST 1: shift a postive value.02353 2353 3 1,2306 0 XCH SLinitP ; init value to shift02354 2354 5 0,0110 1 TS SLval 02355 2355 3 1,2310 1 XCH SLindx ; load init index SLloopP EQU * 02356 2356 5 0,0111 0 TS iSL ; save index ; shift A left (SL)02357 2357 3 0,0110 1 XCH SLval 02360 2360 5 0,0023 0 TS SL ; shift02361 2361 3 0,0023 0 XCH SL ; put result in A02362 2362 5 0,0110 1 TS SLval ; verify C(A)02363 2363 4 0,0000 0 COM ; get -A02364 2364 2 0,0111 1 INDEX iSL 02365 2365 6 1,2311 0 AD SLbaseP ; put (-A) + expected value in A02366 2366 1 0,0000 0 CCS A ; compare02367 2367 0 1,2037 1 TC fail ; >0 (A < expected value)02370 2370 0 1,2037 1 TC fail ; +002371 2371 0 1,2037 1 TC fail ; <0 (A > expected value) ; loop back to test next value02372 2372 1 0,0111 1 CCS iSL ; done?02373 2373 0 1,2356 0 TC SLloopP ; not yet, do next check ; TEST 2: shift a negative value02374 2374 3 1,2307 1 XCH SLinitN ; init value to shift02375 2375 5 0,0110 1 TS SLval 02376 2376 3 1,2310 1 XCH SLindx ; load init index SLloopN EQU * 02377 2377 5 0,0111 0 TS iSL ; save index ; shift A left (SL)02400 2400 3 0,0110 1 XCH SLval 02401 2401 5 0,0023 0 TS SL ; shift02402 2402 3 0,0023 0 XCH SL ; put result in A02403 2403 5 0,0110 1 TS SLval

Page 601: Apollo Guidance Computer AGC

; verify C(A)02404 2404 4 0,0000 0 COM ; get -A02405 2405 2 0,0111 1 INDEX iSL 02406 2406 6 1,2330 0 AD SLbaseN ; put (-A) + expected value in A02407 2407 1 0,0000 0 CCS A ; compare02410 2410 0 1,2037 1 TC fail ; >0 (A < expected value)02411 2411 0 1,2037 1 TC fail ; +002412 2412 0 1,2037 1 TC fail ; <0 (A > expected value) ; loop back to test next value02413 2413 1 0,0111 1 CCS iSL ; done?02414 2414 0 1,2377 0 TC SLloopN ; not yet, do next check 02415 2415 3 0,0101 1 XCH savQ 02416 2416 5 0,0001 0 TS Q ; restore return address02417 2417 0 0,0000 0 RETURN ; ---------------------------------------------- ; PASSED ALL TESTS! 02420 2420 12345 0 PASScode DS PASS finish EQU * 02421 2421 3 1,2420 0 CAF PASScode 02422 2422 5 0,0100 0 TS curtest ; set current test code to PASS02423 2423 0 0,0000 0 RETURN ; ---------------------------------------------- ; INTERRUPT SERVICE ROUTINE goT3 EQU * goER EQU * goDS EQU * goKEY EQU * goUP EQU * endRUPT EQU * 02424 2424 3 0,0027 1 XCH QRUPT ; restore Q02425 2425 5 0,0001 0 TS Q 02426 2426 3 0,0026 0 XCH ARUPT ; restore A02427 2427 2 0,0000 1 RESUME ; finished, go back

Assembly complete. Errors = 0

Symbol table:START 000000 CYRtst 000001 SRtst 000002 CYLtst 000003 SLtst 000004 PASS 012345 EXTENDER 005777 curtest 000100 savQ 000101 CYRval 000102 iCYR 000103 SRval 000104 iSR 000105 CYLval 000106 iCYL 000107 SLval 000110 iSL 000111 GOPROG 002000 T3RUPT 002004 ERRUPT 002010 DSRUPT 002014 KEYRUPT 002020 UPRUPT 002024 goMAIN 002030 fail 002037 end 002041 STRTcode 002042 begin 002043 CYRcode 002046 CYRinit 002047 CYRindx 002050 CYRbase 002051 chkCYR 002070 CYRloop 002077 SRcode 002120 SRinitP 002121 SRinitN 002122 SRindx 002123 SRbaseP 002124 SRbaseN 002143 chkSR 002162 SRloopP 002171 SRloopN 002212 CYLcode 002233 CYLinit 002234 CYLindx 002235 CYLbase 002236 chkCYL 002255 CYLloop 002264 SLcode 002305 SLinitP 002306 SLinitN 002307 SLindx 002310 SLbaseP 002311 SLbaseN 002330 chkSL 002347 SLloopP 002356 SLloopN 002377 PASScode 002420 finish 002421 goT3 002424 goER 002424 goDS 002424 goKEY 002424 goUP 002424 endRUPT 002424 ARUPT 000026 Q 000001 QRUPT 000027 CYR 000020 A 000000 SR 000021 CYL 000022 SL 000023

Page 602: Apollo Guidance Computer AGC

TECO5 assembler listing

Block I Apollo Guidance Computer (AGC4) assembler version 1.6 for EPROM

First pass: generate symbol table.Second pass: generate object code.

; TECO5 (file:teco5.asm) ; ; Version: 1.0 ; Author: John Pultorak ; Date: 9/14/2001 ; ; PURPOSE: ; Test and checkout program for the Block 1 Apollo Guidance Computer. ; Tests interrupts. ; ; OPERATION: ; Tests the interrupts by initializing 4 counters to zero and then ; entering a loop where the 1st counter (mainCtr) is incremented on ; each iteration of the loop. ; ; Interrupts are disabled and enabled during each iteration by INHINT ; and RELINT instructions. ; ; Interrupts are automatically inhibited during part of each iteration ; by an overflow condition in register A. ; ; Interrupt service routines for T3RUPT, DSRUPT (aka T4RUPT) and ; KEYRUPT increment their own counters upon each interrupt. ; ; ERRATA: ; - Written for the AGC4R assembler. The assembler directives and ; syntax differ somewhat from the original AGC assembler. ; - The tests attempt to check all threads, but are not exhaustive. ; ; SOURCES: ; Information on the Block 1 architecture: instruction set, instruction ; sequences, registers, register transfers, control pulses, memory and ; memory addressing, I/O assignments, interrupts, and involuntary ; counters was obtained from: ; ; A. Hopkins, R. Alonso, and H. Blair-Smith, "Logical Description ; for the Apollo Guidance Computer (AGC4)", R-393, ; MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963. ; ; Supplementary information was obtained from: ; ; R. Alonso, J. H. Laning, Jr. and H. Blair-Smith, "Preliminary ; MOD 3C Programmer's Manual", E-1077, MIT Instrumentation ; Laboratory, Cambridge, MA, Nov. 1961. ; ; B. I. Savage and A. Drake, "AGC4 Basic Training Manual, Volume I", ; E-2052, MIT Instrumentation Laboratory, Cambridge, ; MA, Jan. 1967. ; ; E. C. Hall, "MIT's Role in Project Apollo, Volume III, Computer ; Subsystem", R-700, MIT Charles Stark Draper Laboratory, ; Cambridge, MA, Aug. 1972. ; ; A. Hopkins, "Guidance Computer Design, Part VI", source unknown. ; ; A. I. Green and J. J. Rocchio, "Keyboard and Display System Program ; for AGC (Program Sunrise)", E-1574, MIT Instrumentation ; Laboratory, Cambridge, MA, Aug. 1964. ; ; E, C. Hall, "Journey to the Moon: The History of the Apollo ; Guidance Computer", AIAA, Reston VA, 1996. ; ; ---------------------------------------------- ; ---------------------------------------------- ; ERASEABLE MEMORY -- DATA SEGMENT

Page 603: Apollo Guidance Computer AGC

ORG %47 ; start of data area00047 0047 00000 1 mainCtr DS %0 00050 0050 00000 1 T3Ctr DS %0 ; counts T3RUPTs00051 0051 00000 1 DSCtr DS %0 ; counts DSRUPTs (T4RUPT)00052 0052 00000 1 KYCtr DS %0 ; counts KEYRUPT ; ---------------------------------------------- ; ENTRY POINTS ; program (re)start ORG GOPROG 02000 2000 0 1,2030 0 TC goMAIN ; interrupt service entry points ORG T3RUPT 02004 2004 5 0,0026 0 TS ARUPT 02005 2005 3 0,0001 0 XCH Q 02006 2006 5 0,0027 1 TS QRUPT 02007 2007 0 1,2064 1 TC goT3 ORG DSRUPT ; aka T4RUPT02014 2014 5 0,0026 0 TS ARUPT 02015 2015 3 0,0001 0 XCH Q 02016 2016 5 0,0027 1 TS QRUPT 02017 2017 0 1,2071 0 TC goDS ORG KEYRUPT 02020 2020 5 0,0026 0 TS ARUPT 02021 2021 3 0,0001 0 XCH Q 02022 2022 5 0,0027 1 TS QRUPT 02023 2023 0 1,2076 1 TC goKEY ; ---------------------------------------------- ; FIXED MEMORY -- SHARED DATA SEGMENT 02024 2024 00000 1 ZERO DS %0 02025 2025 00001 0 ONE DS %1 02026 2026 25252 0 AD25252 DS %25252 ;+10922 dec, see TECO1 AD test02027 2027 52525 1 AD52525 DS %52525 ;-10922 dec, see TECO1 AD test ; ---------------------------------------------- ; MAIN PROGRAM goMAIN EQU * 02030 2030 2 0,0000 0 INHINT ; disable interrupts ; clear counters for interrupts and for interations ; though main loop. 02031 2031 3 1,2024 0 CAF ZERO 02032 2032 5 0,0047 1 TS mainCtr ; mainCtr = 002033 2033 5 0,0050 1 TS T3Ctr ; T3Ctr = 002034 2034 5 0,0051 0 TS DSCtr ; DSCtr = 002035 2035 5 0,0052 0 TS KYCtr ; KYCtr = 0 ; keeps bumping mainCtr in an infinite loop. ; interrupts are disabled and enabled on each ; iteration of the loop. infLoop EQU * 02036 2036 2 0,0000 0 INHINT ; disable interrupt ; increment mainCtr while interrupt is inhibited. 02037 2037 3 1,2024 0 CAF ZERO 02040 2040 6 0,0047 1 AD mainCtr ; load mainCtr into A02041 2041 6 1,2025 1 AD ONE ; incr 02042 2042 2 0,0000 1 RELINT ; enable interrupts 02043 2043 5 0,0047 1 TS mainCtr ; store increment value

Page 604: Apollo Guidance Computer AGC

; create a positive overflow in A. Interrupts are inhibited ; while A contains an overflow. The overflow is produced ; by adding %25252 + %25252 = %52524 (sign + 14 magnitude). ; This is the overflow test in TECO1 for the AD instruction. 02044 2044 3 1,2026 1 CAF AD25252 02045 2045 6 1,2026 1 AD AD25252 ; positive overflow 02046 2046 3 0,0000 1 NOOP ; interrupt should be inhib02047 2047 3 0,0000 1 NOOP ; remove the overflow, this reenables the interrupt. 02050 2050 3 1,2024 0 CAF ZERO ; clear the overflow in A 02051 2051 3 0,0000 1 NOOP ; interrupt should be reenab02052 2052 3 0,0000 1 NOOP ; create a negative overflow in A. Interrupts are inhibited ; while A contains an overflow. The overflow is produced ; by adding %52525 + %52525 = %25253 (sign + 14 magnitude). ; This is the overflow test in TECO1 for the AD instruction. 02053 2053 3 1,2027 0 CAF AD52525 02054 2054 6 1,2027 0 AD AD52525 ; positive overflow 02055 2055 3 0,0000 1 NOOP ; interrupt should be inhib02056 2056 3 0,0000 1 NOOP ; remove the overflow, this reenables the interrupt. 02057 2057 3 1,2024 0 CAF ZERO ; clear the overflow in A 02060 2060 3 0,0000 1 NOOP ; interrupt should be reenab02061 2061 3 0,0000 1 NOOP 02062 2062 0 1,2036 0 TC infLoop ; mainCtr no overflow02063 2063 0 1,2036 0 TC infLoop ; mainCtr overflowed ; ---------------------------------------------- ; INTERRUPT SERVICE ROUTINE goT3 EQU * 02064 2064 3 1,2024 0 CAF ZERO 02065 2065 6 0,0050 1 AD T3Ctr ; load T3Ctr into A02066 2066 6 1,2025 1 AD ONE ; incr02067 2067 5 0,0050 1 TS T3Ctr ; store02070 2070 0 1,2103 1 TC endRUPT goDS EQU * 02071 2071 3 1,2024 0 CAF ZERO 02072 2072 6 0,0051 0 AD DSCtr ; load DSCtr into A02073 2073 6 1,2025 1 AD ONE ; incr02074 2074 5 0,0051 0 TS DSCtr ; store02075 2075 0 1,2103 1 TC endRUPT goKEY EQU * 02076 2076 3 1,2024 0 CAF ZERO 02077 2077 6 0,0052 0 AD KYCtr ; load KYCtr into A02100 2100 6 1,2025 1 AD ONE ; incr02101 2101 5 0,0052 0 TS KYCtr ; store02102 2102 0 1,2103 1 TC endRUPT endRUPT EQU * 02103 2103 3 0,0027 1 XCH QRUPT ; restore Q02104 2104 5 0,0001 0 TS Q 02105 2105 3 0,0026 0 XCH ARUPT ; restore A02106 2106 2 0,0000 1 RESUME ; finished, go back

Assembly complete. Errors = 0

Symbol table:

Page 605: Apollo Guidance Computer AGC

mainCtr 000047 T3Ctr 000050 DSCtr 000051 KYCtr 000052 GOPROG 002000 T3RUPT 002004 DSRUPT 002014 KEYRUPT 002020 ZERO 002024 ONE 002025 AD25252 002026 AD52525 002027 goMAIN 002030 infLoop 002036 goT3 002064 goDS 002071 goKEY 002076 endRUPT 002103 ARUPT 000026 Q 000001 QRUPT 000027

Page 606: Apollo Guidance Computer AGC

TECO_STBY assembler listing

Block I Apollo Guidance Computer (AGC4) assembler version 1.6

First pass: generate symbol table.Second pass: generate object code.

; TECO_STBY (file:stby.asm) ; ; Tests the standby operation. ; program (re)start ORG GOPROG 02000 2000 0 1,2002 1 TC goMAIN 02001 2001 00200 0 ofbit DS %200 ; OUT1, bit 8 initiates standby ; MAIN PROGRAM goMAIN EQU * ; standby is disabled02002 2002 3 0,0000 1 NOOP 02003 2003 3 0,0000 1 NOOP ; enable standby02004 2004 3 1,2001 1 XCH ofbit 02005 2005 5 0,0011 1 TS OUT1 infLoop EQU * 02006 2006 0 1,2006 0 TC infLoop

Assembly complete. Errors = 0

Symbol table:GOPROG 002000 ofbit 002001 goMAIN 002002 infLoop 002006 OUT1 000011

Page 607: Apollo Guidance Computer AGC