Lesson 4. A program with a menu: seven pictures

In pictures

The circuit is done — now the program. The disk PLOTTER4.dsk holds the PLOTTER program in Applesoft BASIC: a menu of seven pictures, each in several colours. The computer leads the pen point by point, names the colour, waits for the turret to turn — all through the same three addresses you checked in lesson 3. In this lesson we build nothing: we insert the disk, run it and take apart how the program works.


4.1. Idea: the whole program is three addresses

The program knows nothing about flip-flops and motors. It only uses what the card promises on the bus:

In the programWhat it is
B = 49296$C090: POKE B,D — steps, directions, pen
PEEK (49297)$C091: limit switches and BUSY
R = 49298$C092: POKE R,C — colour, the turret turns

All computer devices work this way: the program on one side of the addresses, the hardware on the other. The beginning of the program — the addresses in variables and the menu:

10 REM COLOR PLOTTER20 B = 49296: R = 4929830 P = 0: X = 0: Y = 0: C = 040 C2 = 0: GOSUB 1300: GOSUB 90050 HOME : PRINT "COLOR PLOTTER": PRINT60 PRINT "1 HOUSE       5 SPIRAL"62 PRINT "2 RAINBOW     6 HELLO"64 PRINT "3 FLOWER      7 SPIROGRAPH"66 PRINT "4 STAR        0 EXIT": PRINT70 INPUT "PICTURE: ";K72 IF K = 0 THEN C2 = 0: GOSUB 1300: END80 IF K < 1 OR K > 7 THEN 5090 PRINT "PUT A NEW SHEET, PRESS RETURN";92 GET A$: PRINT100 ON K GOSUB 2000,2100,2200,2300,2400,2500,2600110 P = 0: GOSUB 900: GOTO 50

4.2. Idea: «home» by the limit switches (lines 900–940)

The computer does not know where the carriages are. So at the start and after every picture — «home»: lift the pen and step towards the motor until the limit switch lights.

900 REM HOME: TO THE LIMIT SWITCHES910 P = 0: POKE B,0920 L = PEEK (49297)922 IF L - INT (L / 2) * 2 THEN 930924 POKE B,1: POKE B,0: GOTO 920930 L = INT ( PEEK (49297) / 4)932 IF L - INT (L / 2) * 2 THEN 940934 POKE B,4: POKE B,0: GOTO 930940 X = 0: Y = 0: RETURN
  • 920–924: while XL0 = 0 — an X step towards the motor (POKE B,1: POKE B,0 — an edge on XSTEP, XDIR = 0);
  • 930–934: the same for Y until YL0.

BASIC gets a bit out of a number by division: bit 0 is L - INT(L/2)*2 (the remainder after dividing by 2), bit 2 is the same of INT(PEEK(49297)/4). IF … THEN 930 fires if the bit is not 0. At home X = 0, Y = 0: from then on the program counts where the pen is by itself.

4.3. Idea: a straight line from steps (lines 1000–1090)

The motor steps only in X or in Y, exactly one point. A line from (X, Y) to (TX, TY) is built from steps: there are N steps in all — the larger of the differences, AX = |TX - X| or AY = |TY - Y|. On each of the N steps AX and AY are added to the counters EX and EY; when one reaches N — a step on that axis, the counter minus N. On the long axis there is a step every pass, on the short one every second, every third… evenly. This is Bresenham’s algorithm; plotters and screens both draw with it.

1000 REM LINE TO TX,TY, PEN P1010 DX = TX - X: DY = TY - Y1012 AX = ABS (DX): AY = ABS (DY)1020 D = P + (DX > 0) * 2 + (DY > 0) * 81022 POKE B,D1030 N = AX: IF AY > N THEN N = AY1040 IF N = 0 THEN 10901050 EX = INT (N / 2): EY = EX1060 FOR I = 1 TO N: S = 01062 EX = EX + AX: EY = EY + AY1070 IF EX > = N THEN EX = EX - N: S = 11080 IF EY > = N THEN EY = EY - N: S = S + 41085 POKE B,D + S: POKE B,D: NEXT I1090 X = TX: Y = TY: RETURN1100 REM MOVE TO TX,TY, PEN UP1110 P = 0: GOTO 1000

One line 1085 is one step: POKE B,D + S (edges on the chosen axes) and POKE B,D (back, so that the next step is an edge again). D holds the directions and the pen: P + (DX > 0) * 2 + (DY > 0) * 8.

4.4. Idea: colour and waiting (lines 1300–1330)

1300 REM PEN C2: WAIT WHILE BUSY1310 P = 0: POKE B,01312 POKE R,C2: C = C21320 BU = INT ( PEEK (49297) / 16)1322 IF BU - INT (BU / 2) * 2 THEN 13201330 RETURN
  • 1310–1312: lift the pen and name the colour: POKE R,C2;
  • 1320–1322: read $C091 while bit 4 (BUSY) is 1: divide by 16 and take the remainder after dividing by 2.

While the turret turns, the program waits on this line. The pen at the work point comes down only after the turn — the lesson 2 hardware does that, the program just waits.

4.5. Idea: a picture is a table in DATA (lines 1500–1570, 3000…)

A house, a flower, a word are sets of line segments. So as not to write every segment as code, the pictures sit in DATA lines in a small «plotter language»:

WordWhat it does
P,Kstart of picture number K
C,ntake pen n (0–3)
M,x,ymove, the pen up
L,x,yline, the pen down
Eend of the picture

The house in DATA:

3000 REM PICTURES: P,K C,PEN M,X,Y L,X,Y E3010 DATA P,1,C,0,M,80,140,L,200,1403020 DATA L,200,250,L,80,250,L,80,1403030 DATA C,1,M,70,140,L,140,803040 DATA L,210,140,L,70,1403050 DATA C,3,M,100,165,L,140,1653060 DATA L,140,205,L,100,205,L,100,1653070 DATA M,120,165,L,120,205,M,100,1853080 DATA L,140,1853090 DATA C,0,M,160,250,L,160,1953100 DATA L,185,195,L,185,2503110 DATA C,2,M,20,250,L,380,2503120 DATA M,30,250,L,36,236,L,42,2503130 DATA M,230,250,L,236,236,L,242,2503140 DATA M,300,250,L,306,236,L,312,2503150 DATA E

Subroutine 1500 finds P,K and carries out the words one by one:

1500 REM PICTURE K FROM DATA1510 RESTORE1520 READ A$: IF A$ < > "P" THEN 15201530 READ N: IF N < > K THEN 15201540 READ A$: IF A$ = "E" THEN P = 0: RETURN1550 IF A$ < > "C" THEN 15601552 READ C2: GOSUB 1300: GOTO 15401560 READ TX,TY1562 IF A$ = "M" THEN GOSUB 1100: GOTO 15401570 P = 16: GOSUB 1000: GOTO 1540

The rainbow, the spiral and the spirograph are computed with a formula (sine and cosine), and the sun by the house and the centre of the flower are a circle of short segments:

1400 REM CIRCLE CX,CY, RADIUS RR1410 TX = CX + RR: TY = CY: GOSUB 11001412 P = 161420 FOR J = 1 TO NS1422 A = 6.28318 * J / NS1424 TX = INT (CX + RR * COS (A) + .5)1426 TY = INT (CY + RR * SIN (A) + .5)1428 GOSUB 1000: NEXT J1430 P = 0: RETURN

The spirograph is the hypotrochoid formula: a wheel of radius 45 rolls inside a ring of 105, the pen 60 from its centre:

2600 REM 7 SPIROGRAPH2610 TX = 320: TY = 150: GOSUB 11002620 FOR Q = 0 TO 22622 C2 = Q + 1: GOSUB 1300: P = 162630 FOR J = 1 TO 602632 T = 6.28318 * (Q + J / 60)2634 TX = 200 + 60 * COS (T)2636 TX = INT (TX + 60 * COS (4 * T / 3) + .5)2638 TY = 150 + 60 * SIN (T)2640 TY = INT (TY - 60 * SIN (4 * T / 3) + .5)2642 GOSUB 1000: NEXT J2644 P = 0: NEXT Q: RETURN

4.6. How to run it

  1. Turbo mode, speed MAX (a picture takes a minute or two).
  2. REMOTE is on; the carriages can be anywhere — the program sends them home itself.
  3. At the disk drive (Disk II), ⬆ on its panel — choose the kit file PLOTTER4.dsk.
  4. In BASIC: RUN PLOTTER.
  5. The menu: the picture digit and Return. «PUT A NEW SHEET, PRESS RETURN» — clear the sheet (on the paper’s panel) and press Return.
  6. Done — the carriages go home, the menu again. 0 — exit: the turret brings the black pen back.

4.7. Check

№PictureWhat is on the sheet
1HOUSEthe house in black, the roof and the sun with rays
in red, the window in blue, the door in black, grass
in green
2RAINBOWfour arcs: red, green, blue, black
3FLOWERsix red petals, a green stem with leaves, a black
centre
4STARa five-pointed star, each side its own colour
5SPIRALa spiral of four turns: black, red, green, blue
6HELLOletters: H red, E green, L L blue, O black
7SPIROGRAPHa pattern of three laps: red, green, blue

While the turret turns, BUSY is lit and no pen touches the paper — there are no arcs from turning on the sheet.


The whole PLOTTER program

It is already on the disk. You can also type it yourself — in BASIC, line by line (spaces may be left out), then SAVE PLOTTER.

10 REM COLOR PLOTTER20 B = 49296: R = 4929830 P = 0: X = 0: Y = 0: C = 040 C2 = 0: GOSUB 1300: GOSUB 90050 HOME : PRINT "COLOR PLOTTER": PRINT60 PRINT "1 HOUSE       5 SPIRAL"62 PRINT "2 RAINBOW     6 HELLO"64 PRINT "3 FLOWER      7 SPIROGRAPH"66 PRINT "4 STAR        0 EXIT": PRINT70 INPUT "PICTURE: ";K72 IF K = 0 THEN C2 = 0: GOSUB 1300: END80 IF K < 1 OR K > 7 THEN 5090 PRINT "PUT A NEW SHEET, PRESS RETURN";92 GET A$: PRINT100 ON K GOSUB 2000,2100,2200,2300,2400,2500,2600110 P = 0: GOSUB 900: GOTO 50900 REM HOME: TO THE LIMIT SWITCHES910 P = 0: POKE B,0920 L = PEEK (49297)922 IF L - INT (L / 2) * 2 THEN 930924 POKE B,1: POKE B,0: GOTO 920930 L = INT ( PEEK (49297) / 4)932 IF L - INT (L / 2) * 2 THEN 940934 POKE B,4: POKE B,0: GOTO 930940 X = 0: Y = 0: RETURN1000 REM LINE TO TX,TY, PEN P1010 DX = TX - X: DY = TY - Y1012 AX = ABS (DX): AY = ABS (DY)1020 D = P + (DX > 0) * 2 + (DY > 0) * 81022 POKE B,D1030 N = AX: IF AY > N THEN N = AY1040 IF N = 0 THEN 10901050 EX = INT (N / 2): EY = EX1060 FOR I = 1 TO N: S = 01062 EX = EX + AX: EY = EY + AY1070 IF EX > = N THEN EX = EX - N: S = 11080 IF EY > = N THEN EY = EY - N: S = S + 41085 POKE B,D + S: POKE B,D: NEXT I1090 X = TX: Y = TY: RETURN1100 REM MOVE TO TX,TY, PEN UP1110 P = 0: GOTO 10001300 REM PEN C2: WAIT WHILE BUSY1310 P = 0: POKE B,01312 POKE R,C2: C = C21320 BU = INT ( PEEK (49297) / 16)1322 IF BU - INT (BU / 2) * 2 THEN 13201330 RETURN1400 REM CIRCLE CX,CY, RADIUS RR1410 TX = CX + RR: TY = CY: GOSUB 11001412 P = 161420 FOR J = 1 TO NS1422 A = 6.28318 * J / NS1424 TX = INT (CX + RR * COS (A) + .5)1426 TY = INT (CY + RR * SIN (A) + .5)1428 GOSUB 1000: NEXT J1430 P = 0: RETURN1500 REM PICTURE K FROM DATA1510 RESTORE1520 READ A$: IF A$ < > "P" THEN 15201530 READ N: IF N < > K THEN 15201540 READ A$: IF A$ = "E" THEN P = 0: RETURN1550 IF A$ < > "C" THEN 15601552 READ C2: GOSUB 1300: GOTO 15401560 READ TX,TY1562 IF A$ = "M" THEN GOSUB 1100: GOTO 15401570 P = 16: GOSUB 1000: GOTO 15402000 REM 1 HOUSE AND SUN2010 GOSUB 15002012 C2 = 1: GOSUB 13002014 CX = 320: CY = 60: RR = 28: NS = 162016 GOSUB 14002020 FOR Q = 0 TO 7: A = Q * .7853982022 TX = INT (CX + 36 * COS (A) + .5)2024 TY = INT (CY + 36 * SIN (A) + .5)2026 GOSUB 11002030 TX = INT (CX + 50 * COS (A) + .5)2032 TY = INT (CY + 50 * SIN (A) + .5)2034 P = 16: GOSUB 1000: P = 02036 NEXT Q: RETURN2100 REM 2 RAINBOW2110 FOR Q = 0 TO 32112 C2 = Q + 1 - 4 * (Q = 3): GOSUB 13002114 RR = 150 - Q * 182116 TX = 200 - RR: TY = 250: GOSUB 11002118 P = 162120 FOR J = 1 TO 242122 A = 3.14159 + 3.14159 * J / 242124 TX = INT (200 + RR * COS (A) + .5)2126 TY = INT (250 + RR * SIN (A) + .5)2128 GOSUB 1000: NEXT J2130 P = 0: NEXT Q: RETURN2200 REM 3 FLOWER2210 C2 = 1: GOSUB 13002212 TX = 200: TY = 110: GOSUB 11002214 P = 162220 FOR J = 1 TO 722222 A = 6.28318 * J / 722224 RR = 70 * ABS ( SIN (3 * A))2226 TX = INT (200 + RR * COS (A) + .5)2228 TY = INT (110 + RR * SIN (A) + .5)2230 GOSUB 1000: NEXT J: P = 02232 GOSUB 1500: C2 = 0: GOSUB 13002234 CX = 200: CY = 110: RR = 8: NS = 82236 GOSUB 1400: RETURN2300 REM 4 STAR2310 FOR Q = 0 TO 42312 A = - 1.5708 + Q * 2.513272314 TX = INT (200 + 120 * COS (A) + .5)2316 TY = INT (150 + 120 * SIN (A) + .5)2320 IF Q = 0 THEN GOSUB 1100: GOTO 23402330 C2 = Q - 4 * (Q = 4): GOSUB 13002332 P = 16: GOSUB 1000: P = 02340 NEXT Q2342 C2 = 0: GOSUB 13002344 TX = 200: TY = 302346 P = 16: GOSUB 1000: P = 0: RETURN2400 REM 5 SPIRAL2410 TX = 210: TY = 150: GOSUB 11002420 FOR Q = 0 TO 32422 C2 = Q: GOSUB 1300: P = 162430 FOR J = 1 TO 362432 A = 6.28318 * (Q + J / 36)2434 RR = 10 + 30 * (Q + J / 36)2436 TX = INT (200 + RR * COS (A) + .5)2438 TY = INT (150 + RR * SIN (A) + .5)2440 GOSUB 1000: NEXT J2442 P = 0: NEXT Q: RETURN2500 REM 6 HELLO2510 GOSUB 1500: RETURN2600 REM 7 SPIROGRAPH2610 TX = 320: TY = 150: GOSUB 11002620 FOR Q = 0 TO 22622 C2 = Q + 1: GOSUB 1300: P = 162630 FOR J = 1 TO 602632 T = 6.28318 * (Q + J / 60)2634 TX = 200 + 60 * COS (T)2636 TX = INT (TX + 60 * COS (4 * T / 3) + .5)2638 TY = 150 + 60 * SIN (T)2640 TY = INT (TY - 60 * SIN (4 * T / 3) + .5)2642 GOSUB 1000: NEXT J2644 P = 0: NEXT Q: RETURN3000 REM PICTURES: P,K C,PEN M,X,Y L,X,Y E3010 DATA P,1,C,0,M,80,140,L,200,1403020 DATA L,200,250,L,80,250,L,80,1403030 DATA C,1,M,70,140,L,140,803040 DATA L,210,140,L,70,1403050 DATA C,3,M,100,165,L,140,1653060 DATA L,140,205,L,100,205,L,100,1653070 DATA M,120,165,L,120,205,M,100,1853080 DATA L,140,1853090 DATA C,0,M,160,250,L,160,1953100 DATA L,185,195,L,185,2503110 DATA C,2,M,20,250,L,380,2503120 DATA M,30,250,L,36,236,L,42,2503130 DATA M,230,250,L,236,236,L,242,2503140 DATA M,300,250,L,306,236,L,312,2503150 DATA E3160 DATA P,3,C,2,M,200,180,L,200,2903170 DATA M,200,250,L,170,225,L,200,2353180 DATA M,200,230,L,230,205,L,200,2153190 DATA E3200 DATA P,6,C,1,M,30,100,L,30,2003210 DATA M,30,150,L,90,150,M,90,1003220 DATA L,90,2003230 DATA C,2,M,170,100,L,110,1003240 DATA L,110,200,L,170,200,M,110,1503250 DATA L,155,1503260 DATA C,3,M,190,100,L,190,2003270 DATA L,250,200,M,270,100,L,270,2003280 DATA L,330,2003290 DATA C,0,M,350,100,L,390,1003300 DATA L,390,200,L,350,200,L,350,1003310 DATA E

Stuck? Something doesn't work →