1557 lines
64 KiB
Plaintext
1557 lines
64 KiB
Plaintext
|
|
|
|
|
|
|
|
================================================================================
|
|
|
|
H A L C Y O N I N S T R U M E N T & C O N T R O L
|
|
|
|
================================================================================
|
|
|
|
|
|
|
|
|
|
MODEL HC-33 FLIGHT COMPUTER
|
|
|
|
PROGRAMMER'S REFERENCE MANUAL
|
|
|
|
Including the Ship Peripheral Interface
|
|
|
|
|
|
|
|
|
|
+----------------------------------+
|
|
| |
|
|
| 32-BIT * 16 REGISTERS |
|
|
| 35 INSTRUCTIONS * 8 KB RAM |
|
|
| 1 KB DAILY WORMHOLE LINK |
|
|
| |
|
|
+----------------------------------+
|
|
|
|
|
|
|
|
|
|
Publication No. HIC-0033-A
|
|
First Edition
|
|
|
|
For use with command ships of the Halcyon
|
|
Prospector class and compatible hulls.
|
|
|
|
|
|
|
|
|
|
RETAIN THIS MANUAL WITH THE SHIP RECORDS.
|
|
THE COMPUTER CANNOT BE REPROGRAMMED
|
|
AFTER LAUNCH. READ BEFORE YOU FLY.
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
NOTICE
|
|
|
|
The information in this manual is subject to change at the discretion of
|
|
Halcyon Instrument & Control. Constants quoted as "standard" are the values
|
|
set at the factory; belt operators may adjust them. Halcyon accepts no
|
|
liability for ships lost to the Star, to the Belt, or to programmer error.
|
|
The last of these is by far the most common.
|
|
|
|
Halcyon and the Halcyon crescent are trademarks of Halcyon Instrument &
|
|
Control. All other names are the property of their respective owners.
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
================================================================================
|
|
CONTENTS
|
|
================================================================================
|
|
|
|
1. INTRODUCTION
|
|
1.1 What the HC-33 Is
|
|
1.2 Specifications
|
|
1.3 A Day in the Life of a Ship
|
|
1.4 Conventions Used in This Manual
|
|
|
|
2. ARCHITECTURE
|
|
2.1 Registers
|
|
2.2 Program Memory
|
|
2.3 Data Memory and the Memory Map
|
|
2.4 The Stack
|
|
2.5 Execution, Ticks and the Cycle Budget
|
|
2.6 Processor States
|
|
|
|
3. INSTRUCTION SET
|
|
3.1 Instruction Format
|
|
3.2 Summary of Instructions
|
|
3.3 Instruction Reference
|
|
3.4 Missing Instructions and How to Live Without Them
|
|
|
|
4. THE ASSEMBLER
|
|
4.1 Source Format
|
|
4.2 Directives and Pseudo-Instructions
|
|
4.3 Numbers and Names
|
|
4.4 Running the Assembler
|
|
|
|
5. PERIPHERALS
|
|
5.1 The Port Interface
|
|
5.2 Units and Conventions
|
|
5.3 System Clock
|
|
5.4 Navigation Unit
|
|
5.5 Main Engine
|
|
5.6 Scanner
|
|
5.7 Mining Laser and Cargo Hold
|
|
5.8 Dropoff Station and Market
|
|
5.9 Wormhole Link
|
|
5.10 Math Coprocessor
|
|
|
|
6. OPERATIONS
|
|
6.1 Life Cycle of a Ship
|
|
6.2 The Daily Run
|
|
6.3 Ground Interface
|
|
|
|
7. THE SHIP AND ITS ENVIRONMENT
|
|
7.1 The Prospector Hull
|
|
7.2 Space, Orbits and the Star
|
|
7.3 Fuel and Delta-V
|
|
|
|
8. PROGRAMMING NOTES
|
|
|
|
9. SAMPLE PROGRAMS
|
|
|
|
APPENDIX A Opcode Table
|
|
APPENDIX B Port Map
|
|
APPENDIX C Standard Equate File
|
|
APPENDIX D Fault Conditions
|
|
APPENDIX E Quick Reference Card
|
|
|
|
|
|
|
|
|
|
================================================================================
|
|
CHAPTER 1 INTRODUCTION
|
|
================================================================================
|
|
|
|
1.1 WHAT THE HC-33 IS
|
|
------------------------
|
|
|
|
The HC-33 is the flight computer fitted to every Halcyon command ship. It is
|
|
a small, slow, utterly predictable 32-bit processor. It has no operating
|
|
system, no clock interrupts and no operator. Once your ship leaves the dock
|
|
the HC-33 is the only intelligence on board.
|
|
|
|
You cannot fly the ship. You can only tell the computer, in advance, how to
|
|
fly the ship. The program is written by you, assembled on the ground into
|
|
raw machine code, and sealed into the computer's program memory before launch.
|
|
From that moment it is fixed for the life of the ship.
|
|
|
|
The computer talks to the outside world through two channels:
|
|
|
|
o PERIPHERAL PORTS, which connect it to the engine, scanner, mining laser
|
|
and the rest of the ship. (Chapter 5.)
|
|
|
|
o THE WORMHOLE LINK, a message channel through which you may send the
|
|
computer exactly one kilobyte per day and receive exactly one kilobyte
|
|
per day. The link has no delay. The content is entirely up to you and
|
|
your program. (Section 5.9.)
|
|
|
|
Because the link is so narrow, a good program is one that can run the ship
|
|
for days on its own and needs only a few bytes of guidance from home.
|
|
|
|
|
|
1.2 SPECIFICATIONS
|
|
------------------------
|
|
|
|
Word size ............................ 32 bits, two's complement
|
|
Registers ............................ 16 general purpose (r15 = stack ptr)
|
|
Instruction length ................... 4 bytes, fixed
|
|
Instruction set ...................... 35 instructions
|
|
Program memory (ROM) ................. 4096 bytes standard (1024 words)
|
|
Data memory (RAM) .................... 8192 bytes standard
|
|
Wormhole buffers ..................... 1024 bytes uplink, 1024 bytes downlink
|
|
Cycle budget ......................... 2000 cycles per tick, standard
|
|
Ticks per day ........................ 1440 standard (one tick = 60 s)
|
|
Effective speed ...................... 33.3 cycles per second of ship time
|
|
Cycles per day ....................... 2,880,000
|
|
I/O .................................. IN and OUT to 16-bit port numbers
|
|
Byte order ........................... little-endian
|
|
|
|
NOTE: The program size, RAM size, cycle budget and tick rate are settings
|
|
of the belt, not of the computer. Your belt operator can tell you the
|
|
values in force. This manual quotes the standard values.
|
|
|
|
|
|
1.3 A DAY IN THE LIFE OF A SHIP
|
|
------------------------
|
|
|
|
Once every day the belt is simulated from start to finish. For your ship the
|
|
day runs as follows:
|
|
|
|
1. Any waiting uplink is placed in the computer's uplink buffer.
|
|
2. The day is divided into ticks. On each tick, the computer runs
|
|
until it executes a YIELD or uses up its cycle budget.
|
|
3. After the computer has stopped, the ship's physical world advances by
|
|
one tick: the engine fires, the Star pulls, the ship moves, the mining
|
|
laser works.
|
|
4. After the last tick the contents of the downlink buffer are captured
|
|
and made available to you.
|
|
|
|
At standard settings that is 1440 rounds of "think, then move". Between days
|
|
nothing happens to your ship: it is frozen with its registers and memory intact.
|
|
|
|
|
|
1.4 CONVENTIONS USED IN THIS MANUAL
|
|
------------------------
|
|
|
|
ra, rb ......... any of the sixteen registers r0..r15
|
|
imm ............ a signed 16-bit immediate value, -32768 .. 32767
|
|
port ........... a port number, 0..32767 (all standard ports are below 256)
|
|
[rb+imm] ....... the RAM byte address obtained by adding imm to register rb
|
|
<- ............. "is assigned"
|
|
0x ............. prefix for hexadecimal numbers
|
|
|
|
Text in this manual marked NOTE is helpful. Text marked CAUTION describes
|
|
something that can cost you a ship.
|
|
|
|
|
|
|
|
|
|
================================================================================
|
|
CHAPTER 2 ARCHITECTURE
|
|
================================================================================
|
|
|
|
The HC-33 is a HARVARD MACHINE: program and data live in separate memories.
|
|
The program cannot be read or written by the program itself.
|
|
|
|
|
|
2.1 REGISTERS
|
|
------------------------
|
|
|
|
There are sixteen 32-bit registers, r0 through r15. They are interchangeable
|
|
except for r15, which the CALL, RET, PUSH and POP instructions use as the
|
|
STACK POINTER. The assembler accepts the name SP as a synonym for r15.
|
|
|
|
There is also a PROGRAM COUNTER, which holds the byte address of the next
|
|
instruction. It cannot be read or written directly; it is changed only by
|
|
jumps, branches, CALL and RET.
|
|
|
|
There are no condition flags. Comparison and branching are a single
|
|
operation (BEQ, BNE, BLT, BGE), so no state is left behind.
|
|
|
|
At launch every register is zero, except r15, which holds the size of RAM
|
|
(8192) so that the stack starts empty at the top of memory.
|
|
|
|
|
|
2.2 PROGRAM MEMORY
|
|
------------------------
|
|
|
|
The program occupies up to 4096 bytes (1024 instructions) starting at byte
|
|
address 0. Each instruction is four bytes, so a program is always a whole
|
|
number of words. Program addresses are byte addresses and are always a
|
|
multiple of four.
|
|
|
|
If execution runs off the end of the program the computer HALTS. This is not
|
|
a fault.
|
|
|
|
|
|
2.3 DATA MEMORY AND THE MEMORY MAP
|
|
------------------------
|
|
|
|
RAM is byte addressable from address 0 and is standard 8192 bytes. Words and
|
|
half-words are stored least-significant byte first. No alignment is
|
|
required. Any access outside RAM is a FAULT.
|
|
|
|
+-------------------------+ 8192
|
|
| |
|
|
| STACK (grows down) | r15 starts here
|
|
| | |
|
|
| v |
|
|
| |
|
|
| . . . . . . . |
|
|
| |
|
|
| GENERAL DATA |
|
|
| (about 6 KB) |
|
|
+-------------------------+ 2048
|
|
| DOWNLINK BUFFER (TX) |
|
|
| 1024 bytes |
|
|
+-------------------------+ 1024
|
|
| UPLINK BUFFER (RX) |
|
|
| 1024 bytes |
|
|
+-------------------------+ 0
|
|
|
|
The two wormhole buffers are ordinary RAM. The link hardware writes the
|
|
uplink into the bottom kilobyte before the first tick of the day and copies
|
|
the second kilobyte out at the end of the day. Your program may read and
|
|
write both buffers freely. The buffer boundaries are 0, 1024 and 2048 at
|
|
standard settings.
|
|
|
|
RAM is not cleared between days, and there is no reset.
|
|
|
|
CAUTION: There is no memory protection. A runaway stack, or a store through
|
|
a bad pointer, will happily overwrite your own buffers or data.
|
|
|
|
|
|
2.4 THE STACK
|
|
------------------------
|
|
|
|
The stack grows downward from the top of RAM. PUSH first subtracts four from
|
|
r15 and then stores a word at the new address. POP loads the word at r15 and
|
|
then adds four. CALL pushes the address of the instruction following it and
|
|
jumps. RET pops an address and jumps to it.
|
|
|
|
Popping from an empty stack, or pushing past the bottom of RAM, is a fault.
|
|
Nothing stops the stack from growing down into your data.
|
|
|
|
|
|
2.5 EXECUTION, TICKS AND THE CYCLE BUDGET
|
|
------------------------
|
|
|
|
Time on the HC-33 is measured in TICKS. On each tick the computer is given a
|
|
CYCLE BUDGET, standard 2000 cycles, and runs until one of these happens:
|
|
|
|
o the program executes YIELD;
|
|
o the budget is used up;
|
|
o the program HALTs or FAULTs.
|
|
|
|
Most instructions cost one cycle. MUL costs two. DIV and MOD cost eight.
|
|
The budget is checked before each instruction, so the last instruction of a
|
|
tick may overrun the budget by a few cycles.
|
|
|
|
WHEN THE BUDGET RUNS OUT THE COMPUTER IS NOT RESET. It is simply stopped
|
|
where it was, and on the next tick it carries on from the very next
|
|
instruction. A long calculation is therefore spread across as many ticks as
|
|
it needs. Meanwhile the ship goes on moving, which may or may not be what
|
|
you want.
|
|
|
|
YIELD ends the computer's turn immediately and gives up the rest of the
|
|
budget. The next tick begins with the instruction after the YIELD. A
|
|
typical control program is a loop that reads sensors, decides, writes the
|
|
controls, YIELDs, and jumps back to the top.
|
|
|
|
CAUTION: The ship's controls are LATCHED. Throttle, azimuth and pitch keep
|
|
whatever value was last written to them until you write another. A ship whose
|
|
computer has halted or faulted continues to burn at its last setting until it
|
|
runs out of fuel.
|
|
|
|
|
|
2.6 PROCESSOR STATES
|
|
------------------------
|
|
|
|
At any moment the computer is in one of four states:
|
|
|
|
RUNNING Executing, or interrupted by the end of its budget.
|
|
YIELDED Gave up the rest of the tick with YIELD. Resumes next tick.
|
|
HALTED Executed HALT or ran off the end of the program. Permanent.
|
|
FAULTED Executed an illegal instruction or made an illegal access.
|
|
Permanent.
|
|
|
|
HALTED and FAULTED are final. The processor never runs again, its engine
|
|
settings are frozen, and there is no way to restart it. Appendix D lists the
|
|
fault conditions.
|
|
|
|
|
|
|
|
|
|
================================================================================
|
|
CHAPTER 3 INSTRUCTION SET
|
|
================================================================================
|
|
|
|
3.1 INSTRUCTION FORMAT
|
|
------------------------
|
|
|
|
Every instruction is one 32-bit word:
|
|
|
|
31 16 15 12 11 8 7 0
|
|
+--------------------+--------+--------+-----------------+
|
|
| IMM16 | RA | RB | OPCODE |
|
|
+--------------------+--------+--------+-----------------+
|
|
|
|
OPCODE bits 0-7 which instruction (Appendix A)
|
|
RB bits 8-11 second register field
|
|
RA bits 12-15 first register field
|
|
IMM16 bits 16-31 signed 16-bit immediate, sign-extended to 32 bits
|
|
|
|
The word is stored in program memory least-significant byte first, so the
|
|
four bytes of an instruction appear in the file as:
|
|
|
|
byte 0 = opcode byte 1 = (RA * 16) + RB bytes 2-3 = IMM16, low first
|
|
|
|
Unused fields are zero. You will normally never build these words by hand;
|
|
the assembler does it for you.
|
|
|
|
Jump and branch offsets are counted in INSTRUCTIONS, not bytes, and are
|
|
relative to the instruction FOLLOWING the jump. An offset of zero therefore
|
|
continues at the next instruction, and an offset of -1 jumps to the
|
|
instruction just executed. The reach is 32K instructions either way, which
|
|
is more than the whole program memory.
|
|
|
|
|
|
3.2 SUMMARY OF INSTRUCTIONS
|
|
------------------------
|
|
|
|
CONTROL NOP YIELD HALT JMP BEQ BNE BLT BGE CALL RET
|
|
LOAD CONSTANT LDI LUI
|
|
REGISTER MOV ADD SUB MUL DIV MOD AND OR XOR
|
|
SHL SHR SAR ADDI
|
|
STACK PUSH POP
|
|
MEMORY LDB LDH LDW STB STH STW
|
|
INPUT/OUTPUT IN OUT
|
|
|
|
|
|
3.3 INSTRUCTION REFERENCE
|
|
------------------------
|
|
|
|
All arithmetic is 32-bit two's complement and WRAPS on overflow. No
|
|
instruction sets flags.
|
|
|
|
NOP 1 cycle
|
|
No operation.
|
|
|
|
YIELD 1 cycle
|
|
End this tick. Execution resumes with the next instruction on the next
|
|
tick.
|
|
|
|
HALT 1 cycle
|
|
Stop the computer permanently.
|
|
|
|
LDI ra, imm 1 cycle
|
|
ra <- imm (sign-extended)
|
|
Loads a constant from -32768 to 32767.
|
|
|
|
LUI ra, imm 1 cycle
|
|
ra <- (imm << 16) OR (ra AND 0xFFFF)
|
|
Replaces the upper half of ra and keeps the lower half. LDI followed by
|
|
LUI builds any 32-bit constant; the assembler's LI does exactly this.
|
|
|
|
MOV ra, rb 1 cycle
|
|
ra <- rb
|
|
|
|
ADD ra, rb 1 cycle
|
|
ra <- ra + rb
|
|
|
|
SUB ra, rb 1 cycle
|
|
ra <- ra - rb
|
|
|
|
MUL ra, rb 2 cycles
|
|
ra <- ra * rb (low 32 bits of the product)
|
|
|
|
DIV ra, rb 8 cycles
|
|
ra <- ra / rb (signed, truncated toward zero)
|
|
Dividing by zero is a FAULT. Dividing by -1 negates ra.
|
|
|
|
MOD ra, rb 8 cycles
|
|
ra <- ra REM rb (signed; the sign of the result follows ra)
|
|
Modulus by zero is a FAULT. Modulus by -1 gives zero.
|
|
|
|
AND ra, rb 1 cycle
|
|
OR ra, rb 1 cycle
|
|
XOR ra, rb 1 cycle
|
|
Bitwise operations: ra <- ra AND/OR/XOR rb.
|
|
|
|
SHL ra, rb 1 cycle
|
|
SHR ra, rb 1 cycle
|
|
SAR ra, rb 1 cycle
|
|
Shift ra left (SHL), right logical with zero fill (SHR) or right
|
|
arithmetic with sign fill (SAR). The shift count is the low five bits
|
|
of rb, so only counts 0..31 are possible.
|
|
|
|
ADDI ra, imm 1 cycle
|
|
ra <- ra + imm (imm sign-extended)
|
|
|
|
JMP imm 1 cycle
|
|
PC <- next instruction + imm * 4
|
|
|
|
BEQ ra, rb, imm 1 cycle
|
|
BNE ra, rb, imm 1 cycle
|
|
BLT ra, rb, imm 1 cycle
|
|
BGE ra, rb, imm 1 cycle
|
|
If the condition holds, PC <- next instruction + imm * 4.
|
|
Conditions: ra = rb, ra <> rb, ra < rb, ra >= rb. BLT and BGE compare as
|
|
SIGNED numbers. In assembly source, imm is normally a label.
|
|
|
|
CALL imm 1 cycle
|
|
Push the address of the next instruction, then jump as for JMP.
|
|
Faults if the stack cannot be pushed.
|
|
|
|
RET 1 cycle
|
|
Pop an address from the stack and jump to it. Faults on an empty stack.
|
|
|
|
PUSH ra 1 cycle
|
|
r15 <- r15 - 4; memory word at [r15] <- ra
|
|
|
|
POP ra 1 cycle
|
|
ra <- memory word at [r15]; r15 <- r15 + 4
|
|
|
|
LDB ra, [rb+imm] 1 cycle
|
|
LDH ra, [rb+imm] 1 cycle
|
|
LDW ra, [rb+imm] 1 cycle
|
|
Load a byte, half-word (2 bytes) or word (4 bytes) from RAM address
|
|
rb + imm. Bytes and half-words are ZERO-EXTENDED. Fault if any part of
|
|
the access lies outside RAM.
|
|
|
|
STB ra, [rb+imm] 1 cycle
|
|
STH ra, [rb+imm] 1 cycle
|
|
STW ra, [rb+imm] 1 cycle
|
|
Store the low byte, half-word or word of ra at RAM address rb + imm.
|
|
Note that ra is the SOURCE. Fault if outside RAM.
|
|
|
|
IN ra, port 1 cycle
|
|
ra <- the value of the peripheral port. Ports that do not exist read
|
|
as zero.
|
|
|
|
OUT port, ra 1 cycle
|
|
Write ra to the peripheral port. Writes to ports that do not exist, or
|
|
that are read-only, are ignored.
|
|
|
|
NOTE: In IN and OUT the port number occupies the immediate field. Port
|
|
numbers should be kept below 32768.
|
|
|
|
|
|
3.4 MISSING INSTRUCTIONS AND HOW TO LIVE WITHOUT THEM
|
|
------------------------
|
|
|
|
The HC-33 is a small machine. Everything below is done with what exists.
|
|
|
|
Negate ra ........... ldi r9, 0 / sub r9, ra / mov ra, r9
|
|
Invert bits ......... ldi r9, -1 / xor ra, r9
|
|
Zero a register ..... ldi ra, 0
|
|
Branch if ra > rb ... blt rb, ra, label
|
|
Branch if ra <= rb .. bge rb, ra, label
|
|
Branch if ra = 0 .... keep a zero in some register and use BEQ
|
|
Compare to constant . load the constant into a register first
|
|
Absolute value ...... ldi r9, 0 / bge ra, r9, skip / sub r9, ra / mov ra, r9
|
|
Unsigned compare .... not available; keep values below 2^31
|
|
Computed jump ....... not available; use a chain of compares
|
|
|
|
A register may be used for an unusual purpose provided you keep track of it.
|
|
Conventional practice: r0 as a permanent zero for base addressing, r1-r7 as
|
|
scratch, r8-r14 as saved values, r15 as the stack pointer. This is a habit,
|
|
not a rule.
|
|
|
|
|
|
|
|
|
|
================================================================================
|
|
CHAPTER 4 THE ASSEMBLER
|
|
================================================================================
|
|
|
|
Programs are written in assembly language and converted to machine code by
|
|
the assembler ASM. The output is the raw binary program that is uplinked to
|
|
the ship (Chapter 6).
|
|
|
|
4.1 SOURCE FORMAT
|
|
------------------------
|
|
|
|
One statement per line. A line may hold a label, an instruction, or both.
|
|
|
|
label: mnemonic operand, operand ; comment
|
|
|
|
o Case does not matter in mnemonics and register names. It DOES matter in
|
|
labels and constant names.
|
|
o Comments start with a semicolon (;) or a hash (#) and run to the end of
|
|
the line.
|
|
o Labels end with a colon and may stand alone on a line. A label names
|
|
the position of the next instruction.
|
|
o Operands are separated by commas.
|
|
o Memory operands are written [rb], [rb+off] or [rb-off]. There must be
|
|
no arithmetic beyond a single register and a single offset.
|
|
o Registers are r0 to r15. SP is another name for r15.
|
|
|
|
Examples:
|
|
|
|
start: ldi r1, 100
|
|
add r1, r2
|
|
beq r1, r2, start
|
|
ldw r3, [r2+8]
|
|
stb r3, [sp-4]
|
|
in r4, 0x10
|
|
out 0x20, r4
|
|
|
|
4.2 DIRECTIVES AND PSEUDO-INSTRUCTIONS
|
|
------------------------
|
|
|
|
.EQU name value
|
|
Defines a constant. The name may then be used in place of a number
|
|
anywhere a number is expected, including as a port number or a memory
|
|
offset. A definition may appear anywhere, but its value may refer only
|
|
to constants defined on earlier lines; in practice put all .EQU lines at
|
|
the top.
|
|
|
|
LI rd, value
|
|
Load a full 32-bit constant. The assembler always generates TWO
|
|
instructions (LDI then LUI) so that labels and branch distances are never
|
|
surprised. The value must be a number or a constant name, not a label.
|
|
|
|
Jump, branch and CALL instructions take a label. They also accept a plain
|
|
number, which is then used unchanged as the instruction offset.
|
|
|
|
LDI, LUI and ADDI accept values from -32768 to 65535.
|
|
|
|
CAUTION: The immediate is stored in 16 bits and SIGN-EXTENDED by the machine.
|
|
LDI r1, 65535 therefore loads -1, and ADDI r1, 40000 subtracts 25536. If you
|
|
want a large positive value, use LI.
|
|
|
|
4.3 NUMBERS AND NAMES
|
|
------------------------
|
|
|
|
Numbers may be written in decimal (100, -7), hexadecimal (0x64) or binary
|
|
(0b1100100). A number with a leading zero and no other prefix is read as
|
|
OCTAL: 010 is eight, not ten. This has cost many programmers an afternoon.
|
|
|
|
There is no expression evaluation. Write 1028, not 1024+4.
|
|
|
|
4.4 RUNNING THE ASSEMBLER
|
|
------------------------
|
|
|
|
asm prog.s > prog.bin
|
|
|
|
reads the source file and writes the binary program to standard output.
|
|
Errors are reported with the line number and the assembler stops at the first.
|
|
The size of the file must be a multiple of four (it always is) and must not
|
|
exceed the program memory of your belt (4096 bytes standard). The ground
|
|
interface rejects programs that are too large.
|
|
|
|
Typical assembler messages:
|
|
|
|
line 12: unknown mnemonic "lod"
|
|
line 15: bad register "r16"
|
|
line 20: immediate 70000 out of 16-bit range (use li)
|
|
line 31: bad number or unknown name "LOOP"
|
|
line 40: offset 40000 out of range
|
|
|
|
|
|
|
|
|
|
================================================================================
|
|
CHAPTER 5 PERIPHERALS
|
|
================================================================================
|
|
|
|
5.1 THE PORT INTERFACE
|
|
------------------------
|
|
|
|
Everything the ship can sense or do is reached through PORTS. A port is a
|
|
numbered 32-bit register outside the computer's memory, accessed with IN and
|
|
OUT.
|
|
|
|
in r1, 0x10 ; read port 0x10 (position X) into r1
|
|
out 0x20, r2 ; write r2 to port 0x20 (throttle)
|
|
|
|
Ports come in two kinds, and it matters which:
|
|
|
|
o An INPUT port can be read. Writing to it has no effect.
|
|
o An OUTPUT port can be written. READING AN OUTPUT PORT RETURNS ZERO,
|
|
not the last value written. If you need to remember what you sent,
|
|
keep a copy in a register or in RAM.
|
|
|
|
A port that does not exist reads as zero and ignores writes. No port
|
|
operation ever faults. Port numbers are grouped by function in blocks of 16
|
|
(0x10), as listed below and collected in Appendix B.
|
|
|
|
There are no interrupts. The computer must poll.
|
|
|
|
5.2 UNITS AND CONVENTIONS
|
|
------------------------
|
|
|
|
Every port value is a signed 32-bit integer. There are no fractions.
|
|
|
|
Distances and positions ...... kilometres (km)
|
|
Velocities ................... metres per second (m/s)
|
|
Angles ....................... milliradians (1000 = 1 radian, 3142 = pi)
|
|
Mass ......................... kilograms (kg)
|
|
Time ......................... ticks, and days
|
|
Money ........................ credits
|
|
|
|
Fractional readings are ROUNDED DOWN (toward minus infinity). A position of
|
|
-0.4 km reads as -1; 0.9 km reads as 0. So position is known to no better
|
|
than one kilometre and velocity to no better than one metre per second.
|
|
|
|
COORDINATES. The frame is fixed in space and centred on the Star. It is
|
|
right-handed. The X and Y axes lie in the ECLIPTIC, the plane in which the
|
|
Station orbits. The Z axis is perpendicular to it, positive "north".
|
|
|
|
AZIMUTH is the direction in the XY plane, measured from +X towards +Y.
|
|
ELEVATION (called PITCH on the engine) is the angle above the XY plane,
|
|
positive towards +Z.
|
|
|
|
Azimuth 0, pitch 0 ........ along +X
|
|
Azimuth 1571, pitch 0 ..... along +Y
|
|
Azimuth any, pitch 1571 ... along +Z
|
|
|
|
5.3 SYSTEM CLOCK
|
|
------------------------
|
|
|
|
0x00 TICK input Tick number within the current day, 0 upwards.
|
|
0x01 DAY input Day number. The first day of the belt is day 0.
|
|
0x02 TICKS input Ticks per day (standard 1440).
|
|
|
|
The ship does not have a wristwatch. These three ports are how a program
|
|
knows when it is. Tick length is 86400 divided by TICKS seconds.
|
|
|
|
|
|
5.4 NAVIGATION UNIT
|
|
------------------------
|
|
|
|
Reports the ship's position relative to the Star, and its velocity.
|
|
|
|
0x10 POSX input Position X, km
|
|
0x11 POSY input Position Y, km
|
|
0x12 POSZ input Position Z, km
|
|
0x13 VELX input Velocity X, m/s
|
|
0x14 VELY input Velocity Y, m/s
|
|
0x15 VELZ input Velocity Z, m/s
|
|
|
|
The belt lies between 1,500,000 and 3,000,000 km from the Star, so the
|
|
positions fit comfortably in a word. Velocity is the ship's velocity in the
|
|
fixed frame, not relative to anything else.
|
|
|
|
|
|
5.5 MAIN ENGINE
|
|
------------------------
|
|
|
|
The engine produces thrust along a direction chosen by two angles, at a power
|
|
chosen by the throttle.
|
|
|
|
0x20 THROTTLE output Engine power, 0 to 1000 (permille of full thrust).
|
|
Values above 1000 act as 1000; zero or negative
|
|
switches the engine off.
|
|
0x21 AZIMUTH output Thrust direction azimuth, milliradians.
|
|
0x22 PITCH output Thrust direction elevation, milliradians.
|
|
0x23 FUEL input Fuel remaining, kg.
|
|
0x24 MASS input Total ship mass (hull + fuel + cargo), kg.
|
|
|
|
THE ENGINE FIRES ALONG THE DIRECTION GIVEN, for the whole of the tick, at
|
|
the throttle in effect when the computer stopped. Direction is:
|
|
|
|
( cos(pitch) cos(azimuth), cos(pitch) sin(azimuth), sin(pitch) )
|
|
|
|
The three controls are latched, as described in section 2.5. Set them once
|
|
and the ship keeps burning. Set THROTTLE to zero to coast.
|
|
|
|
Thrust and fuel. For a Prospector at standard tick length:
|
|
|
|
Full thrust ................ 6000 newtons
|
|
Exhaust velocity ........... 30,000 m/s
|
|
Fuel used at full throttle . 12 kg per tick (thrust x tick / exhaust vel.)
|
|
Acceleration ............... thrust / mass, 0.33 to 0.75 m/s^2
|
|
|
|
Fuel use is proportional to throttle. When fuel runs out the engine falls
|
|
silent; the throttle setting is remembered but has no effect. If the tank has
|
|
less fuel than a full tick needs, the engine delivers a proportionally
|
|
shortened burn.
|
|
|
|
CAUTION: Fuel is your ship's only means of changing course. There is no
|
|
way to refuel. See section 7.3 before designing a manoeuvre.
|
|
|
|
|
|
5.6 SCANNER
|
|
------------------------
|
|
|
|
The scanner tracks one asteroid at a time, which you choose by number.
|
|
Asteroids are numbered from 1. The standard belt has 500. The scanner has
|
|
unlimited range: every asteroid in the belt is visible from anywhere in it.
|
|
|
|
0x30 SELECT output Asteroid number to track. Zero, or a number that
|
|
does not exist, clears the selection.
|
|
0x31 NEAREST input Number of the asteroid nearest to the ship.
|
|
|
|
The following ports describe the TRACKED asteroid and all read zero if none
|
|
is tracked.
|
|
|
|
0x32 RELX input Position of the target relative to the ship, X, km
|
|
0x33 RELY input ... Y, km
|
|
0x34 RELZ input ... Z, km
|
|
0x35 RELVX input Velocity of the target relative to the ship, X, m/s
|
|
0x36 RELVY input ... Y, m/s
|
|
0x37 RELVZ input ... Z, m/s
|
|
0x38 DIST input Straight-line distance to the target, km
|
|
0x40 ORE0 input Iron remaining in the target, kg
|
|
0x41 ORE1 input Nickel remaining, kg
|
|
0x42 ORE2 input Ice remaining, kg
|
|
0x43 ORE3 input Platinum remaining, kg
|
|
(0x44-0x47 exist for future ores and read zero.)
|
|
|
|
Relative values are TARGET MINUS SHIP: RELX is positive if the target is on
|
|
the +X side of you. To fly towards the target, point the engine along
|
|
(RELX, RELY, RELZ). To match its velocity, apply a thrust along
|
|
(RELVX, RELVY, RELVZ).
|
|
|
|
NEAREST is decided among all asteroids by true three-dimensional distance;
|
|
if two are exactly equally near, the lower number wins.
|
|
|
|
NOTE: Every asteroid in the belt moves at the same speed, 3 km/s (section
|
|
7.2). For a ship travelling at that speed, the velocity of a target relative
|
|
to the ship is therefore decided by the difference in DIRECTION of travel, not
|
|
by any difference in speed.
|
|
|
|
|
|
5.7 MINING LASER AND CARGO HOLD
|
|
------------------------
|
|
|
|
0x50 MINE output Non-zero: mine the tracked asteroid. Zero: stop.
|
|
0x51 CARGO input Total mass in the hold, kg.
|
|
0x52 CARGOCAP input Capacity of the hold, kg (Prospector: 6000).
|
|
0x58 CARGO0 input Iron in the hold, kg
|
|
0x59 CARGO1 input Nickel in the hold, kg
|
|
0x5A CARGO2 input Ice in the hold, kg
|
|
0x5B CARGO3 input Platinum in the hold, kg
|
|
(0x5C-0x5F exist for future ores and read zero.)
|
|
|
|
The laser stays on, once MINE has been set, until MINE is set to zero. In
|
|
each tick in which ALL of the following are true, it moves ore from the
|
|
asteroid into the hold:
|
|
|
|
o an asteroid is tracked and still has ore;
|
|
o the asteroid is within 5 km of the ship;
|
|
o the ship's velocity relative to the asteroid is at most 100 m/s;
|
|
o the hold is not full.
|
|
|
|
The Prospector mines 10 kg per tick. The ore taken is a mixture in the same
|
|
proportions as the asteroid's remaining ore. You cannot choose what to mine.
|
|
The conditions are tested at the END of the tick, after the ship has moved.
|
|
|
|
To fill an empty hold takes 600 ticks, 10 hours of ship time.
|
|
|
|
Ore has to be brought to the Station before it is worth anything. An asteroid
|
|
does not replenish.
|
|
|
|
NOTE: The scanner reports whole kilometres (rounded down). The range to
|
|
mine is 5 km. Aim for the middle of the range; do not try to close to the
|
|
last kilometre.
|
|
|
|
|
|
5.8 DROPOFF STATION AND MARKET
|
|
------------------------
|
|
|
|
The Station is the belt's only dropoff point. It sits on a circular orbit in
|
|
the ecliptic, half way through the belt, at a radius of 2,250,000 km. Your
|
|
ship is launched from it.
|
|
|
|
0x60 STNX input Position of the Station relative to the ship, X, km
|
|
0x61 STNY input ... Y, km
|
|
0x62 STNZ input ... Z, km
|
|
0x63 STNVX input Velocity of the Station relative to the ship, X, m/s
|
|
0x64 STNVY input ... Y, m/s
|
|
0x65 STNVZ input ... Z, m/s
|
|
0x66 SELL output Non-zero: sell the entire hold.
|
|
0x67 EARNED input Credits earned by this ship so far
|
|
|
|
As with the scanner, relative values are STATION MINUS SHIP.
|
|
|
|
Writing a non-zero value to SELL sells everything in the hold at once, if
|
|
ALL of the following are true, and otherwise does nothing (there is no error
|
|
signal):
|
|
|
|
o the ship is within 20 km of the Station;
|
|
o its velocity relative to the Station is at most 100 m/s;
|
|
o the hold is not empty.
|
|
|
|
The hold is emptied, the credits go to your account, and EARNED goes up.
|
|
|
|
PRICES. Each ore has a standard price per kilogram. The price FALLS as ore
|
|
floods the market and recovers as it is used up. Prices are set once per day
|
|
and do not change during the day, so it does not matter when in the day you
|
|
sell.
|
|
|
|
ore number standard price price is halved at
|
|
(credits per kg) supply of (kg)
|
|
----------------------------------------------------------------
|
|
iron 0 2 400,000
|
|
nickel 1 6 200,000
|
|
ice 2 3 300,000
|
|
platinum 3 300 5,000
|
|
|
|
price = standard price x half-point / (half-point + supply)
|
|
|
|
"Supply" is a running total of the ore sold by everyone. At the end of each
|
|
day today's sales are added to it and 10 percent of the old total is
|
|
forgotten. A price never falls below one credit. Current prices are
|
|
available from the ground interface (section 6.3). Your program cannot read
|
|
them: it must be told, by uplink, if it should care.
|
|
|
|
|
|
5.9 WORMHOLE LINK
|
|
------------------------
|
|
|
|
The link is a pair of one-kilobyte buffers in RAM and two ports.
|
|
|
|
0x70 UPNEW input 1 if an uplink arrived for today and has not been
|
|
acknowledged, else 0.
|
|
UPNEW output Any value: acknowledge (clear the flag).
|
|
0x71 UPLEN input Length of today's uplink in bytes, 0 to 1024.
|
|
|
|
UPLINK. Before tick 0 of the day, the uplink is copied to RAM addresses 0 to
|
|
UPLEN-1. Bytes beyond the end of the message are left as they were. UPNEW is
|
|
set and stays set until acknowledged or until the day ends. An uplink is
|
|
meant for the day on which it arrives; the flag is cleared at the end of every
|
|
day whether or not you noticed.
|
|
|
|
If you send more than one uplink in a day, only the last is delivered.
|
|
|
|
DOWNLINK. At the end of the last tick of the day the ENTIRE transmit buffer,
|
|
RAM addresses 1024 to 2047, is captured and made available to you. It is
|
|
always exactly 1024 bytes. Whatever is in it is sent; the link does not care
|
|
whether it was written today.
|
|
|
|
The wormhole has no delay and is not affected by distance. It is affected by
|
|
size: the buffers are all you have. The format of the data is entirely your
|
|
own invention. The link does not check it, compress it, or understand it.
|
|
|
|
NOTE: A ship that is destroyed sends no more downlinks. Its last message
|
|
remains on file. A ship that has merely halted still sends its buffer,
|
|
unchanged, every day.
|
|
|
|
|
|
5.10 MATH COPROCESSOR
|
|
------------------------
|
|
|
|
The HC-33 cannot take a square root or an arctangent. The coprocessor
|
|
can, at no cost in cycles. Write the operands, then read the answer.
|
|
|
|
0x80 MATHX output Operand x
|
|
0x81 MATHY output Operand y
|
|
0x82 MATHZ output Operand z
|
|
0x83 ATAN2 input atan2(y, x), in milliradians (-3142 to 3141)
|
|
0x84 HYPOT input sqrt(x*x + y*y)
|
|
0x85 NORM3 input sqrt(x*x + y*y + z*z)
|
|
|
|
Operands are whole numbers, and results are rounded down. The internal
|
|
arithmetic is wide enough that squaring even large operands cannot overflow,
|
|
so you may feed it positions in kilometres directly. ATAN2 of (0, 0) is zero.
|
|
|
|
To find the direction from the ship to a target (dx, dy, dz):
|
|
|
|
azimuth = ATAN2 with x = dx, y = dy
|
|
range = HYPOT with x = dx, y = dy
|
|
pitch = ATAN2 with x = range, y = dz
|
|
|
|
Sample program 3 (Chapter 9) does exactly this.
|
|
|
|
|
|
|
|
|
|
================================================================================
|
|
CHAPTER 6 OPERATIONS
|
|
================================================================================
|
|
|
|
6.1 LIFE CYCLE OF A SHIP
|
|
------------------------
|
|
|
|
A ship is always in one of four conditions.
|
|
|
|
INVENTORY Built and waiting on the dock. It can be given a program.
|
|
LAUNCHING Cleared to launch. It will enter the belt on the next daily run.
|
|
Its program can no longer be changed.
|
|
ACTIVE In the belt.
|
|
DESTROYED Lost. It cannot be recovered.
|
|
|
|
On registration each player is issued one command ship, in INVENTORY, with
|
|
no program.
|
|
|
|
1. Write a program and assemble it.
|
|
2. Upload it. It replaces any earlier program. Repeat as often as you
|
|
like.
|
|
3. Launch. There is no going back.
|
|
4. On the next daily run the ship is placed at the Station, moving with the
|
|
Station, with full tanks and a zeroed computer, and the program starts.
|
|
|
|
A launched ship can be sent an uplink, and you can collect its downlink, but
|
|
that is all. You cannot alter the program, recall the ship, or restart it.
|
|
|
|
A ship is destroyed if it comes within 200,000 km of the Star.
|
|
|
|
|
|
6.2 THE DAILY RUN
|
|
------------------------
|
|
|
|
The belt is simulated once per day, in a single run for every ship. The run is
|
|
DETERMINISTIC: the same belt, the same programs and the same uplinks always
|
|
produce the same day, bit for bit. There is no luck in it.
|
|
|
|
Order of events within the run:
|
|
|
|
1. Ships waiting to launch are placed at the Station.
|
|
2. Uplinks are delivered to their ships.
|
|
3. For each tick of the day, for each ship in order of ship number:
|
|
a. the computer runs until it yields or exhausts its budget;
|
|
b. the engine fires and the Star pulls: velocity, then position, are
|
|
updated;
|
|
c. the mining laser, if on, works.
|
|
4. Downlinks are captured, and the market is updated for tomorrow.
|
|
|
|
Ships do not collide with one another or with asteroids. They cannot see each
|
|
other. Each ship's sales, however, feed the same market as everybody else's.
|
|
|
|
|
|
6.3 GROUND INTERFACE
|
|
------------------------
|
|
|
|
You reach your ship over the HTTP interface of the belt operator. Every
|
|
request except registration and the market carries your API key:
|
|
|
|
Authorization: Bearer <your key>
|
|
|
|
POST /register {"name": "yourname"}
|
|
Create a player and its command ship. The reply gives the player
|
|
number, the API KEY (shown once only: keep it) and the ship number.
|
|
|
|
GET /me Your name, your credits, the current day.
|
|
|
|
GET /market Current ore prices, in the order iron,
|
|
nickel, ice, platinum. No key needed.
|
|
|
|
GET /ships Your ships: number, condition, program size
|
|
in bytes, and day of the latest downlink.
|
|
|
|
PUT /ships/{n}/program Body: the assembled program, raw bytes.
|
|
Allowed only while the ship is in INVENTORY. The program must be
|
|
between 4 and 4096 bytes and a multiple of four.
|
|
|
|
POST /ships/{n}/launch Launch the ship on the next run. The ship
|
|
must be in INVENTORY and have a program.
|
|
|
|
PUT /ships/{n}/uplink Body: up to 1024 raw bytes. Replaces any
|
|
message queued for the next run. Allowed while LAUNCHING or ACTIVE.
|
|
|
|
GET /ships/{n}/downlink The latest downlink, exactly 1024 raw
|
|
bytes. The header X-Downlink-Day tells you which day's run
|
|
produced it. A ship's first downlink appears after its first day.
|
|
|
|
Typical use:
|
|
|
|
asm miner.s > miner.bin
|
|
curl -X PUT -H "Authorization: Bearer $KEY" \
|
|
--data-binary @miner.bin http://belt.example/ships/1/program
|
|
curl -X POST -H "Authorization: Bearer $KEY" \
|
|
http://belt.example/ships/1/launch
|
|
|
|
An uplink queued today is delivered at the START of the next run and is the
|
|
day's message; the downlink you collect afterwards was written during that
|
|
run. In steady state you therefore exchange one kilobyte in each direction
|
|
per day, as the name of the link says.
|
|
|
|
Errors are reported in the usual way: 401 for a missing or wrong key, 404 for
|
|
a ship that is not yours, 409 when the ship is in the wrong condition for the
|
|
request, 413 when your data is too large, 400 for malformed data.
|
|
|
|
|
|
|
|
|
|
================================================================================
|
|
CHAPTER 7 THE SHIP AND ITS ENVIRONMENT
|
|
================================================================================
|
|
|
|
7.1 THE PROSPECTOR HULL
|
|
------------------------
|
|
|
|
Dry mass ............................. 8000 kg
|
|
Fuel tank ............................ 4000 kg
|
|
Hold ................................. 6000 kg
|
|
Total mass, full tank, empty hold .... 12,000 kg
|
|
Total mass, empty tank, full hold .... 14,000 kg
|
|
Engine ............................... 6000 N, exhaust velocity 30 km/s
|
|
Mining laser ......................... 10 kg per tick
|
|
|
|
The ship is a point. It has no orientation of its own; the engine simply
|
|
pushes in whatever direction the two angles command. There are no
|
|
thrusters, no spin, no fuel used to turn.
|
|
|
|
|
|
7.2 SPACE, ORBITS AND THE STAR
|
|
------------------------
|
|
|
|
The Star sits at the origin and pulls on everything with an acceleration
|
|
|
|
a = v^2 / r
|
|
|
|
directed towards it, where r is the distance from the Star and v is a
|
|
constant, the ORBIT SPEED, standard 3 km/s. (In a real solar system the pull
|
|
falls with the square of the distance. In the belt it falls only with the
|
|
distance. Ask a cosmologist.)
|
|
|
|
The remarkable consequence is that a body on a circular orbit at ANY radius
|
|
travels at exactly the same speed, v. Every asteroid, the Station, and any
|
|
ship that has matched their motion, all travel at 3 km/s. What differs is the
|
|
time taken to go round:
|
|
|
|
radius (km) period of one orbit
|
|
------------------------------------------------------
|
|
1,500,000 (inner edge of belt) 36.4 days
|
|
2,250,000 (the Station) 54.5 days
|
|
3,000,000 (outer edge of belt) 72.7 days
|
|
|
|
Asteroids travel on circles, in slightly different planes. Each orbit is tilted
|
|
from the ecliptic by up to about 0.2 radian (11 degrees), most of them by a
|
|
good deal less, so the belt is a thick disc with the Station in the middle. At
|
|
the outer edge an asteroid may lie as much as 600,000 km above or below the
|
|
ecliptic.
|
|
Asteroids are not disturbed by anything you do; they follow their circles for
|
|
ever.
|
|
|
|
A ship in free flight has a great deal of velocity and very little spare
|
|
acceleration. At the Station's radius the Star pulls at about 4 millimetres
|
|
per second squared; your engine, at 0.33 to 0.75 m/s^2, is around a hundred
|
|
times stronger. The engine is the master, but the Star never relents, and a
|
|
ship left alone drifts from its orbit at once if its velocity differs from
|
|
3 km/s. A ship at 3 km/s, moving tangentially, stays on its circle for ever
|
|
and needs no fuel to do it.
|
|
|
|
CAUTION: A ship that comes within 200,000 km of the Star is destroyed. A
|
|
ship that is too slow at the wrong radius falls inward and will not stop
|
|
until it hits this limit.
|
|
|
|
|
|
7.3 FUEL AND DELTA-V
|
|
------------------------
|
|
|
|
The total change of velocity available from one tank is given by
|
|
|
|
dv = exhaust velocity x ln( mass before / mass after )
|
|
|
|
For a Prospector with an empty hold and full tank:
|
|
|
|
30 km/s x ln( 12000 / 8000 ) = about 12.2 km/s
|
|
|
|
That is roughly four times the orbit speed. Nothing is ever free: every
|
|
metre per second gained going out must be paid again to slow down, and every
|
|
kilogram of ore carried home makes the ship heavier to turn around. The
|
|
engine at full power uses the whole tank in 333 ticks, a little over five
|
|
hours of ship time, and yet the day is 24. Plan accordingly.
|
|
|
|
A rendezvous takes two burns: one to intercept, and one to match velocity. A
|
|
program that only does the first will arrive, at speed, and pass on. See the
|
|
comments in sample program 3.
|
|
|
|
|
|
|
|
|
|
================================================================================
|
|
CHAPTER 8 PROGRAMMING NOTES
|
|
================================================================================
|
|
|
|
1. THE BUDGET IS A BUDGET. At standard settings a tick allows 2000 cycles.
|
|
A loop that copies the full kilobyte uplink a byte at a time uses over
|
|
5000, and needs three ticks. That is fine, as long as the rest of the
|
|
program can cope with the ship moving on meanwhile. If a control loop
|
|
matters, keep it short and let the slow work run between calls.
|
|
|
|
2. ALWAYS YIELD. A program with no YIELD uses its whole budget every tick,
|
|
all day. Its main loop will read the sensors dozens of times per tick and
|
|
see the same numbers each time, since the world does not move until the
|
|
computer stops. Finish your work, YIELD, and start again next tick.
|
|
|
|
3. 32 BITS IS NOT MANY. Positions of two million kilometres times a
|
|
velocity of a few thousand metres per second overflows a word at once.
|
|
MUL wraps silently. Scale before you multiply, or divide first.
|
|
|
|
4. THE PORTS ROUND DOWN. The error is up to one kilometre and one metre per
|
|
second on every reading. Differences of nearby readings are meaningless.
|
|
Distance, sampled over a few ticks, is a much better guide to closing
|
|
speed than the RELV ports on a slow approach.
|
|
|
|
5. PORTS ARE NOT MEMORY. Output ports cannot be read back. Keep a copy of
|
|
every control value you might need.
|
|
|
|
6. THE WORLD ONLY MOVES BETWEEN TICKS. Whatever you write to the engine takes
|
|
effect when the computer stops for the tick and stays in force until you
|
|
write something else. Do not expect any reaction in the readings until
|
|
your next YIELD.
|
|
|
|
7. DEFEND AGAINST FAULTS. A faulted computer is dead, and the engine
|
|
remains latched at its last throttle. Check array bounds. Never divide
|
|
by a value that might be zero. Never POP more than you PUSHed.
|
|
|
|
8. DO NOT WASTE THE UPLINK. A kilobyte a day is 1024 bytes. A program can
|
|
use it to change a target number, a threshold, or a mode. It cannot
|
|
carry the whole belt. Design the ship so that most days need no uplink at
|
|
all.
|
|
|
|
9. TEST ON THE GROUND. The belt is deterministic. A program that misbehaves
|
|
once will misbehave in exactly the same way every time, so a run of the
|
|
belt simulator, on the same belt seed, will find the fault. Do this
|
|
before you launch.
|
|
|
|
10. AN IDLE SHIP IS A SAFE SHIP. A program that does nothing at all keeps
|
|
the ship on its launch orbit for ever. You can only do worse.
|
|
|
|
|
|
|
|
|
|
================================================================================
|
|
CHAPTER 9 SAMPLE PROGRAMS
|
|
================================================================================
|
|
|
|
The three programs below are complete. Each has been assembled and run.
|
|
Program sizes are those of the assembled binary.
|
|
|
|
|
|
PROGRAM 1: ECHO 52 bytes
|
|
------------------------
|
|
|
|
Sends back whatever you send. A useful first test of the link: uplink a
|
|
message, wait for the next run, and read the same message in the downlink.
|
|
|
|
Notice how the copy loop uses the UPLEN port to stop at the length of the
|
|
message, and how the acknowledge (OUT to UPNEW) comes last, so that the flag
|
|
stays set for as long as the copy is unfinished. A full kilobyte takes three
|
|
ticks to copy at standard settings; the computer simply carries on where it
|
|
left off (section 2.5).
|
|
|
|
; ECHO -- copy each day's uplink into the downlink buffer.
|
|
;
|
|
.equ RX 0 ; uplink buffer
|
|
.equ TX 1024 ; downlink buffer
|
|
.equ P_UPNEW 0x70 ; uplink-arrived flag / acknowledge
|
|
.equ P_UPLEN 0x71 ; uplink length in bytes
|
|
|
|
wait: in r1, P_UPNEW
|
|
ldi r2, 0
|
|
beq r1, r2, sleep ; nothing new today
|
|
in r4, P_UPLEN
|
|
ldi r5, 0 ; r5 = byte index
|
|
copy: bge r5, r4, done
|
|
ldb r6, [r5+RX]
|
|
stb r6, [r5+TX]
|
|
addi r5, 1
|
|
jmp copy
|
|
done: out P_UPNEW, r1 ; acknowledge
|
|
sleep: yield
|
|
jmp wait
|
|
|
|
|
|
PROGRAM 2: TELEMETRY 52 bytes
|
|
------------------------
|
|
|
|
Reports tick number, fuel, and position to home. The five words appear in the
|
|
downlink at byte offsets 0, 4, 8, 12 and 16, least-significant byte first.
|
|
Because it overwrites them every tick, what you receive is the ship's state as
|
|
sampled at the start of the last tick of the day.
|
|
|
|
; TELEMETRY -- every tick, write tick number, fuel and position to the
|
|
; downlink buffer as five 32-bit words.
|
|
;
|
|
.equ P_TICK 0x00
|
|
.equ P_POSX 0x10
|
|
.equ P_POSY 0x11
|
|
.equ P_POSZ 0x12
|
|
.equ P_FUEL 0x23
|
|
.equ T_TICK 1024 ; TX + 0
|
|
.equ T_FUEL 1028 ; TX + 4
|
|
.equ T_X 1032 ; TX + 8
|
|
.equ T_Y 1036 ; TX + 12
|
|
.equ T_Z 1040 ; TX + 16
|
|
|
|
ldi r0, 0 ; r0 = 0, the base register
|
|
loop: in r1, P_TICK
|
|
stw r1, [r0+T_TICK]
|
|
in r1, P_FUEL
|
|
stw r1, [r0+T_FUEL]
|
|
in r1, P_POSX
|
|
stw r1, [r0+T_X]
|
|
in r1, P_POSY
|
|
stw r1, [r0+T_Y]
|
|
in r1, P_POSZ
|
|
stw r1, [r0+T_Z]
|
|
yield
|
|
jmp loop
|
|
|
|
|
|
PROGRAM 3: PURSUE 72 bytes
|
|
------------------------
|
|
|
|
Selects the nearest asteroid, points the engine at it, and burns at full
|
|
throttle. The bearing is recomputed every tick with the math coprocessor.
|
|
|
|
This program is a beginning, not an end. It will reach its target and fly
|
|
straight past it at several kilometres per second, and it will burn its whole
|
|
tank in about five hours doing so. A working program brakes: it must compare
|
|
its velocity with the target's (RELVX, RELVY, RELVZ), turn the engine towards
|
|
the difference, and throttle back as the distance closes. It must also
|
|
watch its fuel. That is left as an exercise.
|
|
|
|
; PURSUE -- point the engine at the nearest asteroid and burn.
|
|
; Crude: it makes no attempt to match velocity, so it will fly straight past.
|
|
;
|
|
.equ P_THROTTLE 0x20
|
|
.equ P_AZIMUTH 0x21
|
|
.equ P_PITCH 0x22
|
|
.equ P_SELECT 0x30
|
|
.equ P_NEAREST 0x31
|
|
.equ P_RELX 0x32
|
|
.equ P_RELY 0x33
|
|
.equ P_RELZ 0x34
|
|
.equ P_MATHX 0x80
|
|
.equ P_MATHY 0x81
|
|
.equ P_ATAN2 0x83
|
|
.equ P_HYPOT 0x84
|
|
|
|
in r1, P_NEAREST ; id of the nearest asteroid
|
|
out P_SELECT, r1 ; track it
|
|
ldi r7, 1000
|
|
out P_THROTTLE, r7 ; full power
|
|
|
|
aim: in r1, P_RELX ; where is it?
|
|
in r2, P_RELY
|
|
in r3, P_RELZ
|
|
out P_MATHX, r1
|
|
out P_MATHY, r2
|
|
in r4, P_ATAN2 ; azimuth = atan2(dy, dx)
|
|
out P_AZIMUTH, r4
|
|
in r5, P_HYPOT ; horizontal range = hypot(dx, dy)
|
|
out P_MATHX, r5
|
|
out P_MATHY, r3
|
|
in r6, P_ATAN2 ; elevation = atan2(dz, range)
|
|
out P_PITCH, r6
|
|
yield
|
|
jmp aim
|
|
|
|
|
|
================================================================================
|
|
APPENDIX A OPCODE TABLE
|
|
================================================================================
|
|
|
|
hex mnemonic operands cycles operation
|
|
--- -------- -------------------- ------ -------------------------------
|
|
00 NOP 1 no operation
|
|
01 YIELD 1 end this tick
|
|
02 HALT 1 stop permanently
|
|
03 LDI ra, imm 1 ra <- sign-extended imm
|
|
04 LUI ra, imm 1 ra <- imm<<16 | (ra & 0xFFFF)
|
|
05 MOV ra, rb 1 ra <- rb
|
|
06 ADD ra, rb 1 ra <- ra + rb
|
|
07 SUB ra, rb 1 ra <- ra - rb
|
|
08 MUL ra, rb 2 ra <- ra * rb
|
|
09 DIV ra, rb 8 ra <- ra / rb (fault if 0)
|
|
0A MOD ra, rb 8 ra <- ra rem rb (fault if 0)
|
|
0B AND ra, rb 1 ra <- ra & rb
|
|
0C OR ra, rb 1 ra <- ra | rb
|
|
0D XOR ra, rb 1 ra <- ra ^ rb
|
|
0E SHL ra, rb 1 ra <- ra << (rb & 31)
|
|
0F SHR ra, rb 1 ra <- ra >> (rb & 31), logical
|
|
10 SAR ra, rb 1 ra <- ra >> (rb & 31), signed
|
|
11 ADDI ra, imm 1 ra <- ra + imm
|
|
12 JMP imm 1 pc <- next + imm*4
|
|
13 BEQ ra, rb, imm 1 if ra = rb branch
|
|
14 BNE ra, rb, imm 1 if ra <> rb branch
|
|
15 BLT ra, rb, imm 1 if ra < rb branch (signed)
|
|
16 BGE ra, rb, imm 1 if ra >= rb branch (signed)
|
|
17 CALL imm 1 push next; jump
|
|
18 RET 1 pop pc
|
|
19 PUSH ra 1 sp -= 4; [sp] <- ra
|
|
1A POP ra 1 ra <- [sp]; sp += 4
|
|
1B LDB ra, [rb+imm] 1 ra <- byte, zero-extended
|
|
1C LDH ra, [rb+imm] 1 ra <- half-word, zero-extended
|
|
1D LDW ra, [rb+imm] 1 ra <- word
|
|
1E STB ra, [rb+imm] 1 byte <- ra
|
|
1F STH ra, [rb+imm] 1 half-word <- ra
|
|
20 STW ra, [rb+imm] 1 word <- ra
|
|
21 IN ra, port 1 ra <- port
|
|
22 OUT port, ra 1 port <- ra
|
|
|
|
Any opcode of 23 hex or above is illegal and faults the computer.
|
|
|
|
Pseudo-instruction (assembler only):
|
|
LI rd, value 2 LDI rd, low16 ; LUI rd, high16
|
|
|
|
|
|
================================================================================
|
|
APPENDIX B PORT MAP
|
|
================================================================================
|
|
|
|
port name dir description units
|
|
---- --------- --- ---------------------------------------------- -----
|
|
SYSTEM
|
|
0x00 TICK in tick within the day ticks
|
|
0x01 DAY in day number days
|
|
0x02 TICKS in ticks per day ticks
|
|
|
|
NAVIGATION
|
|
0x10 POSX in position X (Star at origin) km
|
|
0x11 POSY in position Y km
|
|
0x12 POSZ in position Z km
|
|
0x13 VELX in velocity X m/s
|
|
0x14 VELY in velocity Y m/s
|
|
0x15 VELZ in velocity Z m/s
|
|
|
|
ENGINE
|
|
0x20 THROTTLE out 0..1000, latched permille
|
|
0x21 AZIMUTH out thrust direction, latched mrad
|
|
0x22 PITCH out thrust elevation, latched mrad
|
|
0x23 FUEL in fuel remaining kg
|
|
0x24 MASS in total mass kg
|
|
|
|
SCANNER
|
|
0x30 SELECT out asteroid to track (0 = none)
|
|
0x31 NEAREST in number of nearest asteroid
|
|
0x32 RELX in target minus ship, X km
|
|
0x33 RELY in target minus ship, Y km
|
|
0x34 RELZ in target minus ship, Z km
|
|
0x35 RELVX in target velocity minus ship, X m/s
|
|
0x36 RELVY in ... Y m/s
|
|
0x37 RELVZ in ... Z m/s
|
|
0x38 DIST in distance to target km
|
|
0x40 ORE0 in iron in target kg
|
|
0x41 ORE1 in nickel in target kg
|
|
0x42 ORE2 in ice in target kg
|
|
0x43 ORE3 in platinum in target kg
|
|
|
|
MINING AND HOLD
|
|
0x50 MINE out non-zero = laser on, latched
|
|
0x51 CARGO in hold contents kg
|
|
0x52 CARGOCAP in hold capacity kg
|
|
0x58 CARGO0 in iron in hold kg
|
|
0x59 CARGO1 in nickel in hold kg
|
|
0x5A CARGO2 in ice in hold kg
|
|
0x5B CARGO3 in platinum in hold kg
|
|
|
|
STATION
|
|
0x60 STNX in station minus ship, X km
|
|
0x61 STNY in ... Y km
|
|
0x62 STNZ in ... Z km
|
|
0x63 STNVX in station velocity minus ship, X m/s
|
|
0x64 STNVY in ... Y m/s
|
|
0x65 STNVZ in ... Z m/s
|
|
0x66 SELL out non-zero = sell hold (if docked)
|
|
0x67 EARNED in credits earned by this ship
|
|
|
|
WORMHOLE LINK
|
|
0x70 UPNEW i/o in: uplink pending; out: acknowledge
|
|
0x71 UPLEN in uplink length bytes
|
|
|
|
MATH COPROCESSOR
|
|
0x80 MATHX out operand x
|
|
0x81 MATHY out operand y
|
|
0x82 MATHZ out operand z
|
|
0x83 ATAN2 in atan2(y, x) mrad
|
|
0x84 HYPOT in sqrt(x^2 + y^2)
|
|
0x85 NORM3 in sqrt(x^2 + y^2 + z^2)
|
|
|
|
All other ports read zero and ignore writes.
|
|
|
|
|
|
================================================================================
|
|
APPENDIX C STANDARD EQUATE FILE
|
|
================================================================================
|
|
|
|
Paste this at the top of any program. Unused equates cost nothing.
|
|
|
|
.equ RX 0 ; uplink buffer
|
|
.equ TX 1024 ; downlink buffer
|
|
.equ RAMTOP 8192 ; initial stack pointer
|
|
|
|
.equ P_TICK 0x00
|
|
.equ P_DAY 0x01
|
|
.equ P_TICKS 0x02
|
|
.equ P_POSX 0x10
|
|
.equ P_POSY 0x11
|
|
.equ P_POSZ 0x12
|
|
.equ P_VELX 0x13
|
|
.equ P_VELY 0x14
|
|
.equ P_VELZ 0x15
|
|
.equ P_THROTTLE 0x20
|
|
.equ P_AZIMUTH 0x21
|
|
.equ P_PITCH 0x22
|
|
.equ P_FUEL 0x23
|
|
.equ P_MASS 0x24
|
|
.equ P_SELECT 0x30
|
|
.equ P_NEAREST 0x31
|
|
.equ P_RELX 0x32
|
|
.equ P_RELY 0x33
|
|
.equ P_RELZ 0x34
|
|
.equ P_RELVX 0x35
|
|
.equ P_RELVY 0x36
|
|
.equ P_RELVZ 0x37
|
|
.equ P_DIST 0x38
|
|
.equ P_ORE0 0x40
|
|
.equ P_ORE1 0x41
|
|
.equ P_ORE2 0x42
|
|
.equ P_ORE3 0x43
|
|
.equ P_MINE 0x50
|
|
.equ P_CARGO 0x51
|
|
.equ P_CARGOCAP 0x52
|
|
.equ P_CARGO0 0x58
|
|
.equ P_CARGO1 0x59
|
|
.equ P_CARGO2 0x5A
|
|
.equ P_CARGO3 0x5B
|
|
.equ P_STNX 0x60
|
|
.equ P_STNY 0x61
|
|
.equ P_STNZ 0x62
|
|
.equ P_STNVX 0x63
|
|
.equ P_STNVY 0x64
|
|
.equ P_STNVZ 0x65
|
|
.equ P_SELL 0x66
|
|
.equ P_EARNED 0x67
|
|
.equ P_UPNEW 0x70
|
|
.equ P_UPLEN 0x71
|
|
.equ P_MATHX 0x80
|
|
.equ P_MATHY 0x81
|
|
.equ P_MATHZ 0x82
|
|
.equ P_ATAN2 0x83
|
|
.equ P_HYPOT 0x84
|
|
.equ P_NORM3 0x85
|
|
|
|
|
|
================================================================================
|
|
APPENDIX D FAULT CONDITIONS
|
|
================================================================================
|
|
|
|
A fault stops the computer permanently. The cause is recorded on the ship
|
|
but is not reported to you; the symptom is a ship that no longer responds.
|
|
|
|
ILLEGAL OPCODE
|
|
The instruction word's opcode is 23 hex or greater. Usually means the
|
|
program has run into data, or the binary was not produced by ASM.
|
|
|
|
DIVISION BY ZERO
|
|
DIV or MOD with a zero divisor.
|
|
|
|
MEMORY ACCESS OUT OF RANGE
|
|
A load or store, a PUSH, a POP, a CALL or a RET touched an address
|
|
below 0 or above the end of RAM. Includes a pop from an empty stack and
|
|
a return with nothing to return to.
|
|
|
|
Not faults: arithmetic overflow (wraps), shifts of 32 or more (the count
|
|
is masked), writing to a port that does not exist, running off the end of
|
|
the program (HALT), commanding a throttle greater than 1000 (clamped).
|
|
|
|
|
|
================================================================================
|
|
APPENDIX E QUICK REFERENCE CARD
|
|
================================================================================
|
|
|
|
+------------------------------------------------------------------------------+
|
|
| HC-33 QUICK REFERENCE |
|
|
+------------------------------------------------------------------------------+
|
|
| REGISTERS r0-r14 general r15 = SP (starts at 8192) |
|
|
| MEMORY 0-1023 uplink 1024-2047 downlink 2048-8191 data + stack |
|
|
| WORD 32 bit, little-endian, no flags |
|
|
+------------------------------------------------------------------------------+
|
|
| ldi ra,imm lui ra,imm li rd,val mov ra,rb |
|
|
| add sub mul div mod and or xor shl shr sar ra,rb addi ra,imm |
|
|
| jmp L beq/bne/blt/bge ra,rb,L call L ret push ra pop ra |
|
|
| ldb/ldh/ldw ra,[rb+imm] stb/sth/stw ra,[rb+imm] |
|
|
| in ra,port out port,ra yield halt nop |
|
|
+------------------------------------------------------------------------------+
|
|
| COSTS most 1 mul 2 div,mod 8 BUDGET 2000/tick |
|
|
| UNITS km m/s milliradians kg READINGS ROUND DOWN |
|
|
+------------------------------------------------------------------------------+
|
|
| 00 tick 01 day 02 ticks/day |
|
|
| 10-12 pos km 13-15 vel m/s |
|
|
| 20 throttle 0-1000 21 azimuth 22 pitch 23 fuel 24 mass |
|
|
| 30 select 31 nearest 32-34 rel pos 35-37 rel vel 38 dist 40-43 ore |
|
|
| 50 mine 51 cargo 52 cap 58-5B cargo by ore |
|
|
| 60-62 stn pos 63-65 stn vel 66 sell 67 earned |
|
|
| 70 uplink flag / ack 71 uplink length |
|
|
| 80 x 81 y 82 z 83 atan2 84 hypot 85 norm3 |
|
|
+------------------------------------------------------------------------------+
|
|
| MINE within 5 km, rel speed <= 100 m/s 10 kg/tick |
|
|
| SELL within 20 km, rel speed <= 100 m/s whole hold |
|
|
| STAR a = v^2/r, v = 3 km/s. Inside 200,000 km = destroyed. |
|
|
+------------------------------------------------------------------------------+
|
|
|
|
|
|
* * * END OF MANUAL * * *
|
|
|
|
--------------------------------------------------------------------------------
|
|
HALCYON INSTRUMENT & CONTROL Publication HIC-0033-A
|
|
Printed in the Outer System. First Edition
|