0% found this document useful (0 votes)
31 views4 pages

Minskytron Annotated

PDP1 programming

Uploaded by

krapivindm
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
31 views4 pages

Minskytron Annotated

PDP1 programming

Uploaded by

krapivindm
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 4

Minskytron annotated

/ source: http://textfiles.com/bitsavers/bits/DEC/pdp1/from_peter_samson/dpys5.mac
/ all additional annotations by me, Norbert Landsteiner, prefixed by "//".

// Code for PDP-1 Macro assembler


// PDP-1 characteristics:
// 18-bit words, 1's complement, deposit AC (dac) non-destructive, all values octal
// address parts of instructions in lower 12 bits - absolute address range
(0..7777)
// opcodes in highest 2 nibbles of instruction word (bit 5 is defer bit "i", here
unused)
// shift instructions are micro-coded, number of high bits give number of bit-
positions
// as encoded in constants "s1" (1 = 1 hi-bit) .. "s9" (0777 = 9 hi-bits).
// AC and IO may be combined for shift instructions to form a temporary 36-bit
register
// display instruction "dpy" displays a dot at x = AC, y = IO (only highest 10 bits
used)
// display is -512..+512 with origin at center, -x = left, -y = top.
// "dpy-i" modifies the display instruction not to wait for the completion pulse
from the
// display,normally triggered after 50 microseconds. Since the code takes longer to
run
// in between display commands, there's no need to wait in this particular program.
// timing: memory cycle = 5 microseconds
// internal instruction = 1 mem-cycle, address-lookup adds another one (as would do
a defer)
// i.e.: cla (clear AC, internal instr) = 5 us, lac addr (memory instr) = 10 us,
// see http://www.masswerk.at/spacewar/inside/pdp1-instructions.html for details.

// The Minskytron interconnects 3 oscillators based on a code for displaying


circles
// as discovered by Marvin Minsky:

// > Here is an elegant way to draw almost circles on a point-plotting


// > display:
// >
// > NEW X = OLD X – epsilon * OLD Y
// > NEW Y = OLD Y + epsilon * NEW(!) X
// >
// > This makes a very round ellipse centered at the origin with its size
// > determined by the initial point. epsilon determines the angular velocity
// > of the circulating point, and slightly affects the eccentricity. If
// > epsilon is a power of 2, then we don't even need multiplication, let
// > alone square roots, sines, and cosines! The "circle" will be perfectly
// > stable because the points soon become periodic.
// >
// > The circle algorithm was invented by mistake when I tried to save one
// > register in a display hack! Ben Gurley had an amazing display hack using
// > only about six or seven instructions, and it was a great wonder. But it
// > was basically line-oriented. It occurred to me that it would be exciting
// > to have curves, and I was trying to get a curve display hack with
// > minimal instructions.

// "Item 149 (Minsky): Circle Algorithm" in HAKMEM,


// http://www.inwap.com/pdp10/hbaker/hakmem/hacks.html
/ start at 500 for Minskytron
/ (uses TW)

// initially read the testword and swap contents into IO


// (IO will be unaffected by computations, so it serves here as an 18-bits store)

500/ lat // read testword (18 bits) into AC


rcl 9s // two rotational shifts by 9 bits across combined AC and IO
registers
rcl 9s // effect: swap AC and IO, testword contents now in IO

// assemble a shift instruction for every 3 bits of the contents of IO (from


testword)

m1, jsp gsh // call subroutine gsh to get first shift instruction (in AC)
dac sh0 // store it in address sh0 (osc. #1, x-factor)
jsp gsh // get next shift
dac sh1 // store it in sh1 (osc. #1, y-factor)
jsp gsh // get next
dac sh2 // store it in sh2 (osc. #2, x-factor)
jsp gsh // get next
dac sh3 // store it in sh3 (osc. #2, y-factor)
jsp gsh // get next
dac sh4 // store it in sh4 (osc. #3, x-factor)
jsp gsh // get next
dac sh5 // store it in sh5 (osc. #3, y-factor)

// set up x/y values of oscillators from initial values table

m2, lac xa0 // load contents of xa0


dac xa // store it in xa
lac xb0 // same for xb, xc, ya, yb, and yc
dac xb
lac xc0
dac xc
lac ya0
dac ya
lac yb0
dac yb
lac yc0
dac yc

// set up complete
// main loop, consisting of code to drive 3 interconnected oscillators

m3a, lac xa // osc. #1, load contents of xa


add xb // add contents of xb to it (x from osc. #2)
xct sh0 // execute shift instruction stored in sh0
add ya // add contents of ya to it
dac ya // deposit contents of AC in ya
sub yb // subtract contents of yb (y from osc #2)
xct sh1 // execute shift in sh1
cma // complement AC
add xa // add contents of xa
dac xa // deposit contents of AC in address xa
lio ya // load contents of ya into IO (y-coor for display)
dpy-i // display a dot at x = xa, y = ya (only highest 10 bits
significant)
// range: -512 .. +512 (display 1024 x 1024, origin at center, -x
left, -y: top)

// so, we just calculated


// ya += (xa + xb) >> sh0; xa -= (ya - yb) >> sh1;
// and display it at ( xa >> 8 | ya >> 8 )

m3b, lac xb // osc #2: yb += (xb - xc) >> sh2; xb -= (yb - yc) >> sh3;
sub xc // here we subtract the x from osc #3 (is add above)!
xct sh2
add yb
dac yb
sub yc
xct sh3
cma
add xb
dac xb
lio yb
dpy-i // display it at ( xb >> 8 | yb >> 8 )

m3c, lac xc // osc #3: yc += (xc - xa) >> sh4; xc -= (yc - ya) >> sh5;
sub xa // subtraction as in osc. #2
xct sh4
add yc
dac yc
sub ya
xct sh5
cma
add xc
dac xc
lio yc
dpy-i // display it at ( xc >> 8 | yc >> 8 )

jmp m3a // end of main loop, jump to osc. #1 and redo

// here we extract the next 3 bits from the testword contents (in IO)
// by rotating them into the 3 highest bits of a previously clean AC
// this serves as an offset to addr gst (stored in gsc), thus selecting
// an instruction for an arithmetic shift to the right by 1 to 8 bits,
// put in AC as we return from the subroutine

gsh, dap gsx // (subroutine) deposit return address in address part of gsx
cla // clear AC
rcl 3s // rotate combined AC and IO right by 3 bits (get next 3 bits
into AC)
add gsc // add contents of gsc to it (result: addr of gst + offset 0..7)
dap .+1 // put it in address part of next location
lac . // execute "load contents of address into AC" (get shift instr
from table)
gsx, jmp . // return

gsc, gst // addr of table (starting directly below, used above)


gst, sar 1s // here's a table of shift instructions to load
sar 2s // containing instr. for right shifts by 1 to 8 bits
sar 3s
sar 4s
sar 5s
sar 6s
sar 7s
sar 8s
sar 9s / not used, but was in orig.

// end of shift-assembly routine

// constants for initial values for oscillators


// encoded as instructions, but used as numerical values.
// (this may be the result of a disassembly?)
//
// these initial positions give the corners of an upright triangle
// with the base through the center origin of the screen (+):
//
// b (0 | 0100)
//
//
// (-040 | 0) a + c (040 | 0)
//
// (points in screen coordinates = 10 most significant bits of 18-bit words)

xa0, dpy i 17770 // (730007 + 10000) + 17770 = 757777 = -020000 (1's complement!)
xb0, 0 // 0
xc0, and // 020000
ya0, 0 // 0
yb0, ior // 040000
yc0, 0 // 0

// and here are the addresses for these variables

xa, 0
xb, 0
xc, 0
ya, 0
yb, 0
yc, 0

// space for assembled shift instructions (x/y modifying factors)

sh0, xx // values inserted by program at runtime


sh1, xx // "xx" actually resolves to 760400, same as "hlt" (halt)
sh2, xx
sh3, xx
sh4, xx
sh5, xx

start 500 // end of program (not in original code)

// eof

You might also like