Lesson 3. The card in the slot: the computer draws

In pictures

After this lesson the plotter is connected to the Apple ][ through a card in slot 1, like a real one. The REMOTE switch hands control to the computer: POKE moves the pens and picks the colour, PEEK reads the limit switches and BUSY. Switch REMOTE off — the panel works again.


3.1. Idea: the card has three addresses

The Apple processor talks to everything around it through addresses: memory, keyboard, disk. Slot 1 owns the addresses $C090…$C09F; the plotter card takes four of them:

AddressBASICWhat
$C09049296write: X step, X direction, Y step, Y dir.,
pen
$C09149297read: limit switches XL0 XL1 YL0 YL1 and BUSY
$C09249298write: colour 0–3
$C09349299unused
1A151A140A130A120A110A100A90A81A70A60A51A40A30A2xA1xA0$C09xa bit must be 1 → «wrong» if it is 0: take NOT (CD4069) — NA15, NA14, NA7, NA4a bit must be 0 → «wrong» if it is 1: take it as it isG1 … G4CD4072 · OR4ANYBCD4071SELPNOT ANYBA1 A0:00 — $C09001 — $C09110 — $C092
The address decoder: the top 14 bits must match $C09x. It is simpler to look for «at least one wrong» — four 4-input ORs, an OR and a NOT: SELP = 1 only if none differs.

3.2. Idea: the decoder — «no bit differs»

$C090…$C093 in binary is 1100 0000 1001 00xx: the top 14 bits are fixed, the two lowest pick the register. Checking 14 bits at once is easier the other way round: look for at least one wrong bit. A bit that must be 1 is wrong when it is 0 (take its inverse from the CD4069: NA15, NA14, NA7, NA4); a bit that must be 0 is wrong when it is 1 (take it as it is). All 14 «wrongs» go into ORs:

  • G1 = NA15 OR NA14 OR ADDR13 OR ADDR12, G2 = ADDR11 OR … OR ADDR8 — CD4072 (4-input OR);
  • G3 = NA7 OR ADDR6 OR ADDR5 OR NA4, G4 = ADDR3 OR ADDR2;
  • ANYB = G1 OR G2 OR G3 OR G4 (CD4071) — «at least one bit is wrong»;
  • SELP = NOT ANYB — the address is ours.

3.3. Idea: writing to a register

A register is CD4013 D flip-flops: on a rising edge at CL they store what is on D. On D — the processor’s data DOUT0…DOUT4, and the clock must come only when the processor writes to exactly this address:

  • SELW = SELP AND NOT ADDR0 — $C090 or $C092;
  • WR = SELW AND write — and it is a write;
  • WE0 = WR AND NOT ADDR1 — $C090, WE2 = WR AND ADDR1 — $C092;
  • register clocks: LCK0 = WE0 AND CLK, LCK2 = WE2 AND CLK — the rising edge of the machine clock, when the data on the bus has settled.

$C090 is five flip-flops (AXS, AXD, AYS, AYD, APEN), $C092 is two (AC0, AC1). The machine’s RST clears them: pen up, colour black.

3.4. Idea: reading $C091 — onto the same bus

When the processor reads $C091, the card must put its bits onto the data bus DIN0…DIN4, and at all other times it must not disturb the machine:

  • SELR1 = SELP AND ADDR0 AND NOT ADDR1 — $C091; OEP = SELR1 AND RnW — and it is a read;
  • a card bit onto the bus: PRD0 = XL0 AND OEP, … PRD4 = BUSY AND OEP — at any other address all PRD = 0;
  • the bus to the processor: DIN = MUX OR PRD (CD4071). MUX is what the machine itself gives (the DataInMux chip); at address $C091 it has nothing — zeros — so the card’s bits pass. At other addresses PRD = 0 — the machine’s data passes.

That is why the machine’s DataInMux outputs are renamed to MUX0…MUX4: the name DIN now belongs to the OR output.

3.5. Idea: who drives — the CD4019

The CD4019 has four «AND-OR» cells: D = A AND KA OR B AND KB. With KA = REMOTE and KB = NOT REMOTE, a cell is a switch:

REMOTEKAKBD
110A — the computer’s reg.
001B — the panel

Two CD4019s are seven switches: X and Y step and direction, the pen, two colour bits. Their outputs XSTEP, XDIR, YSTEP, YDIR, PEN, COL0, COL1 now drive the plotter — that is why the pins of the axes, the pen and the colour compare are rewired to them. The turret, BUSY and the limit switches work as before — they don’t care who named the colour.

3.6. Build

On top of lesson 2. The card sits in slot 1 of the machine: it listens to the Apple bus (address ADDR0…ADDR15, data DOUT0…DOUT4, write, RnW, CLK, RST — the machine's labels) and answers on DIN0…DIN4. The REMOTE switch picks who drives the plotter: the computer or the panel.

Step 1. The address decoder

PartPin / actionLabel / where
TI CD4069UBA
G
B
H
C
I
D
J
E
K
F
L
ADDR15
NA15
ADDR14
NA14
ADDR7
NA7
ADDR4
NA4
ANYB
SELP
ADDR0
NA0
TI CD4072BA
B
C
D
J
E
F
G
H
K
NA15
NA14
ADDR13
ADDR12
G1
ADDR11
ADDR10
ADDR9
ADDR8
G2
TI CD4072BA
B
C
D
J
E
F
G
H
K
NA7
ADDR6
ADDR5
NA4
G3
ADDR3
ADDR2
GND
GND
G4
TI CD4071BA
B
J
C
D
K
E
F
L
G
H
M
G1
G2
H1
G3
G4
H2
H1
H2
ANYB
MUX0
PRD0
DIN0
PartPinDetach fromAttach to
TI CD4069UB, the one whose output = NBUSYAGNDADDR1
TI CD4069UB, the one whose output = NBUSYG— (not connected)NA1
TI CD4069UB, the one whose output = NBUSYBGNDREMOTE
TI CD4069UB, the one whose output = NBUSYH— (not connected)NREM

Step 2. Writing and reading

PartPin / actionLabel / where
TI CD4081BA
B
J
C
D
K
E
F
L
G
H
M
SELP
NA0
SELW
SELW
write
WR
WR
NA1
WE0
WR
ADDR1
WE2
TI CD4081BA
B
J
C
D
K
E
F
L
G
H
M
WE0
CLK
LCK0
WE2
CLK
LCK2
SELP
ADDR0
SELR
SELR
NA1
SELR1
TI CD4081BA
B
J
C
D
K
E
F
L
G
H
M
SELR1
RnW
OEP
XL0
OEP
PRD0
XL1
OEP
PRD1
YL0
OEP
PRD2
TI CD4071BA
B
J
C
D
K
E
F
L
G
H
M
MUX1
PRD1
DIN1
MUX2
PRD2
DIN2
MUX3
PRD3
DIN3
MUX4
PRD4
DIN4
PartPinDetach fromAttach to
TI CD4081B, the one whose output = LXSAGNDYL1
TI CD4081B, the one whose output = LXSBGNDOEP
TI CD4081B, the one whose output = LXSJ— (not connected)PRD3
TI CD4081B, the one whose output = LXSCGNDBUSYH
TI CD4081B, the one whose output = LXSDGNDOEP
TI CD4081B, the one whose output = LXSK— (not connected)PRD4

Step 3. Registers

PartPin / actionLabel / where
TI CD4013BS1
R1
D1
CL1
Q1
S2
R2
D2
CL2
Q2
GND
RST
DOUT0
LCK0
AXS
GND
RST
DOUT1
LCK0
AXD
TI CD4013BS1
R1
D1
CL1
Q1
S2
R2
D2
CL2
Q2
GND
RST
DOUT2
LCK0
AYS
GND
RST
DOUT3
LCK0
AYD
TI CD4013BS1
R1
D1
CL1
Q1
S2
R2
D2
CL2
Q2
GND
RST
DOUT4
LCK0
APEN
GND
RST
DOUT0
LCK2
AC0
PartPinDetach fromAttach to
TI CD4013B, the one whose output = MOVEDR1GNDRST
TI CD4013B, the one whose output = MOVEDD1GNDDOUT1
TI CD4013B, the one whose output = MOVEDCL1GNDLCK2
TI CD4013B, the one whose output = MOVEDQ1— (not connected)AC1

Leave unconnected: QN1, QN2 on each of the three CD4013Bs.

Step 4. REMOTE and the CD4019

The switch is an Input from the palette.

PartPin / actionLabel / where
Input (switch)outputREMOTE
TI CD4019BKA
KB
A1
B1
D1
A2
B2
D2
A3
B3
D3
A4
B4
D4
REMOTE
NREM
AXS
LXS
XSTEP
AXD
RIGHT
XDIR
AYS
LYS
YSTEP
AYD
DOWN
YDIR
TI CD4019BKA
KB
A1
B1
D1
A2
B2
D2
A3
B3
D3
A4
B4
REMOTE
NREM
APEN
LPEN
PEN
AC0
LC0
COL0
AC1
LC1
COL1
GND
GND

Leave unconnected: D4 on the CD4019B.

Step 5. Axes, pen and colour — from the CD4019

Mechanics pins are renamed the same way: double-click the label on the pin.

PartPinDetach fromAttach to
Linear axis — X axisSTEPLXSXSTEP
Linear axis — X axisDIRRIGHTXDIR
Linear axis — Y axisSTEPLYSYSTEP
Linear axis — Y axisDIRDOWNYDIR
TI CD4081B, the one whose output = STEPTCLPENPEN
TI CD4070B, the one whose output = X0ALC0COL0
TI CD4070B, the one whose output = X0CLC1COL1

Step 6. The Apple data bus

On the machine chip DataInMux, rename the labels DIN0…DIN4 on its outputs to MUX0…MUX4 (the MOS6502 processor keeps its DIN0…DIN4 labels). Now data reaches the processor through the card: the CD4071 ORs the card’s read bits with the machine’s data.

PartPinDetach fromAttach to
DataInMux (machine chip), the one whose output = DIN0DIN0DIN0MUX0
DataInMux (machine chip), the one whose output = DIN1DIN1DIN1MUX1
DataInMux (machine chip), the one whose output = DIN2DIN2DIN2MUX2
DataInMux (machine chip), the one whose output = DIN3DIN3DIN3MUX3
DataInMux (machine chip), the one whose output = DIN4DIN4DIN4MUX4

3.7. Check

  1. Turbo mode, switch the power on. REMOTE is off — the plotter obeys the panel, as in lesson 2.
  2. Switch REMOTE on. When the machine has booted, type in BASIC (Return after each line):
PRINT PEEK(49297)POKE 49298,2PRINT PEEK(49297)
  1. The first number is 5 if both carriages are at the motors (the XL0 and YL0 limit switches are on); if you moved the carriages with the panel, it is a different one. POKE 49298,2 — the computer named green: BUSY lights up, the head turns. While it turns, PEEK gives a number 16 higher (the BUSY bit); when it stops — the old one again.
  2. A short program — a green square:
10 FOR I = 1 TO 40: POKE 49296,19: POKE 49296,18: NEXT20 FOR I = 1 TO 40: POKE 49296,28: POKE 49296,24: NEXT30 FOR I = 1 TO 40: POKE 49296,17: POKE 49296,16: NEXT40 FOR I = 1 TO 40: POKE 49296,20: POKE 49296,16: NEXT50 POKE 49296,0RUN
CommandWhat the plotter does
POKE 49296,V$C090: bits of V — X step, X direction,
Y step, Y direction, pen (1, 2, 4, 8, 16)
POKE 49298,C$C092: colour 0–3 — the head turns to it
PEEK(49297)$C091: XL0 1, XL1 2, YL0 4, YL1 8, BUSY 16
REMOTE offthe panel, as in lessons 1–2

Lesson 3 paste (Cmd+I)

Paste into the Apple ][ machine (the DEMO button) instead of lessons 1–3: it places the whole device and renames the DataInMux outputs.

# Lesson 3 - the card in the slot: decoder $C090-$C093, registers, reading the limit switches and BUSY; REMOTE/LOCAL on the CD4019.# $C090 write: 0 XSTEP 1 XDIR 2 YSTEP 3 YDIR 4 PEN. $C091 read: 0 XL0 1 XL1 2 YL0 3 YL1 4 BUSY. $C092 write: 0-1 colour.# ---------- mechanics: X axis, Y axis on its carriage, the head on the Y carriage, black pen, paper ----------maxis ax{len=400}(STEP=XSTEP, DIR=XDIR, L0=XL0, L1=XL1, STALL=XSTALL)maxis ay{len=300, ang=90}(STEP=YSTEP, DIR=YDIR, L0=YL0, L1=YL1, STALL=YSTALL)mount(ay, ax.car)mtable tt(A=NJ1, B=NJ2, C=J1, D=J2)mount(tt, ay.car)mpen k0{color=black}(DOWN=DOWN0)mount(k0, tt.d0)mpaper p{w=460, h=360}at(p, 0, 0)at(ax, p, -41, -138)# ---------- panel: step clock, arrows, PEN UP/DOWN ----------clock{rt=60}(CKL)button{label="LEFT"}(LEFT)button{label="RIGHT"}(RIGHT)button{label="UP"}(UP)button{label="DOWN"}(DOWN)button{label="PEN UP/DOWN"}(PENB)# ---------- CD4071: an X arrow pressed, a Y arrow pressed; ERROR - a carriage is stuck ----------"TI CD4071B"(A=LEFT, B=RIGHT, J=LR, C=UP, D=DOWN, K=UD, E=XSTALL, F=YSTALL, L=ERROR, G=Q6, H=RST, M=QR)# ---------- CD4081: steps - the 60 Hz clock while an arrow is pressed ----------"TI CD4081B"(A=YL1, B=OEP, C=BUSYH, D=OEP, E=CKL, F=LR, L=LXS, G=CKL, H=UD, M=LYS, J=PRD3, K=PRD4)# ---------- CD4013: PEN UP/DOWN - a toggle flip-flop ----------"TI CD4013B"(S1=GND, R1=RST, D1=NLPEN, CL1=PENB, Q1=LPEN, QN1=NLPEN, S2=GND, R2=RST, D2=NLC0, CL2=SELB, Q2=LC0, QN2=NLC0)# ---------- POWER and ERROR LEDs ----------led{color=green}(VCC)led{color=red}(ERROR)# ---------- the SELECT button ----------button{label="SELECT"}(SELB)# ---------- CD4013: the high bit of the colour ----------"TI CD4013B"(S1=GND, R1=RST, D1=NLC1, CL1=NLC0, Q1=LC1, QN1=NLC1, S2=GND, R2=GND, D2=GND, CL2=GND)# ---------- the turret motor clock ----------clock{rt=10}(CKT)# ---------- CD4070: colour differs from the pen at the work point ----------"TI CD4070B"(A=COL0, B=CP0, J=X0, C=COL1, D=CP1, K=X1, E=GND, F=GND, G=GND, H=GND)# ---------- CD4071: MOVE - turn; BUSY - turning or has just finished ----------"TI CD4071B"(A=X0, B=X1, J=MOVE, C=MOVE, D=MOVED, K=BUSYH, E=GND, F=GND, G=GND, H=GND)# ---------- CD4013: MOVED - MOVE half a tick ago (second flip-flop; the first one - lesson 3) ----------"TI CD4013B"(S1=GND, R1=RST, D1=DOUT1, CL1=LCK2, S2=GND, R2=RST, D2=MOVE, CL2=NCKT, Q2=MOVED, Q1=AC1)# ---------- CD4069: NOT BUSY, NOT the clock (inputs A and B - lesson 3) ----------"TI CD4069UB"(A=ADDR1, B=REMOTE, C=BUSYH, I=NBUSY, D=CKT, J=NCKT, E=GND, F=GND, G=NA1, H=NREM)# ---------- CD4081: motor step, the pen may go down, a pair of pens ----------"TI CD4081B"(A=CKT, B=MOVE, J=STEPT, C=PEN, D=NBUSY, K=PDN, E=PDN, F=NCP1, L=E0, G=PDN, H=CP1, M=E1)# ---------- CD4081: which pen to lower ----------"TI CD4081B"(A=E0, B=NCP0, J=DOWN0, C=E0, D=CP0, K=DOWN1, E=E1, F=NCP0, L=DOWN2, G=E1, H=CP0, M=DOWN3)# ---------- CD4013: motor phases - two flip-flops in a ring ----------"TI CD4013B"(S1=GND, R1=RST, D1=NJ2, CL1=STEPT, Q1=J1, QN1=NJ1, S2=GND, R2=RST, D2=J1, CL2=STEPT, Q2=J2, QN2=NJ2)# ---------- CD4017: a quarter turn = 6 steps ----------"TI CD4017B"(CLOCK=STEPT, RESET=QR, INH=GND, O6=Q6, CO=QCO)# ---------- CD4013: the number of the pen at the work point ----------"TI CD4013B"(S1=GND, R1=RST, D1=NCP0, CL1=QCO, Q1=CP0, QN1=NCP0, S2=GND, R2=RST, D2=NCP1, CL2=NCP0, Q2=CP1, QN2=NCP1)# ---------- the BUSY LED ----------led{color=yellow}(BUSYH)# ---------- pens: red, green, blue ----------mpen k1{color=red}(DOWN=DOWN1)mount(k1, tt.d3)mpen k2{color=green}(DOWN=DOWN2)mount(k2, tt.d2)mpen k3{color=blue}(DOWN=DOWN3)mount(k3, tt.d1)# ---------- address decoder $C090-$C093 ----------"TI CD4069UB"(A=ADDR15, G=NA15, B=ADDR14, H=NA14, C=ADDR7, I=NA7, D=ADDR4, J=NA4, E=ANYB, K=SELP, F=ADDR0, L=NA0)"TI CD4072B"(A=NA15, B=NA14, C=ADDR13, D=ADDR12, J=G1, E=ADDR11, F=ADDR10, G=ADDR9, H=ADDR8, K=G2)"TI CD4072B"(A=NA7, B=ADDR6, C=ADDR5, D=NA4, J=G3, E=ADDR3, F=ADDR2, G=GND, H=GND, K=G4)"TI CD4071B"(A=G1, B=G2, J=H1, C=G3, D=G4, K=H2, E=H1, F=H2, L=ANYB, G=MUX0, H=PRD0, M=DIN0)# ---------- CD4081: write to $C090 and to $C092 ----------"TI CD4081B"(A=SELP, B=NA0, J=SELW, C=SELW, D=write, K=WR, E=WR, F=NA1, L=WE0, G=WR, H=ADDR1, M=WE2)# ---------- CD4081: register clocks, read $C091 ----------"TI CD4081B"(A=WE0, B=CLK, J=LCK0, C=WE2, D=CLK, K=LCK2, E=SELP, F=ADDR0, L=SELR, G=SELR, H=NA1, M=SELR1)# ---------- CD4081: read bits ----------"TI CD4081B"(A=SELR1, B=RnW, J=OEP, C=XL0, D=OEP, K=PRD0, E=XL1, F=OEP, L=PRD1, G=YL0, H=OEP, M=PRD2)# ---------- CD4071: read bits - onto the data bus ----------"TI CD4071B"(A=MUX1, B=PRD1, J=DIN1, C=MUX2, D=PRD2, K=DIN2, E=MUX3, F=PRD3, L=DIN3, G=MUX4, H=PRD4, M=DIN4)# ---------- register $C090: steps, directions, pen ----------"TI CD4013B"(S1=GND, R1=RST, D1=DOUT0, CL1=LCK0, Q1=AXS, S2=GND, R2=RST, D2=DOUT1, CL2=LCK0, Q2=AXD)"TI CD4013B"(S1=GND, R1=RST, D1=DOUT2, CL1=LCK0, Q1=AYS, S2=GND, R2=RST, D2=DOUT3, CL2=LCK0, Q2=AYD)"TI CD4013B"(S1=GND, R1=RST, D1=DOUT4, CL1=LCK0, Q1=APEN, S2=GND, R2=RST, D2=DOUT0, CL2=LCK2, Q2=AC0)# ---------- the REMOTE switch ----------input(REMOTE)# ---------- CD4019: who drives - the computer (REMOTE = 1) or the panel ----------"TI CD4019B"(KA=REMOTE, KB=NREM, A1=AXS, B1=LXS, D1=XSTEP, A2=AXD, B2=RIGHT, D2=XDIR, A3=AYS, B3=LYS, D3=YSTEP, A4=AYD, B4=DOWN, D4=YDIR)"TI CD4019B"(KA=REMOTE, KB=NREM, A1=APEN, B1=LPEN, D1=PEN, A2=AC0, B2=LC0, D2=COL0, A3=AC1, B3=LC1, D3=COL1, A4=GND, B4=GND)reconnect(DIN0.DIN0 = MUX0)reconnect(DIN1.DIN1 = MUX1)reconnect(DIN2.DIN2 = MUX2)reconnect(DIN3.DIN3 = MUX3)reconnect(DIN4.DIN4 = MUX4)

Stuck? Something doesn't work →