Урок 3. Плата в слоте: компьютер рисует
В картинкахПосле этого урока плоттер подключён к Apple ][ платой в слоте 1, как настоящий. Тумблер REMOTE отдаёт управление компьютеру: POKE двигает перья и выбирает цвет, PEEK читает концевики и BUSY. Выключил REMOTE — снова работает пульт.
3.1. Идея: у платы три адреса
Процессор Apple разговаривает со всем вокруг через адреса: память, клавиатура, диск. Слоту 1 отведены адреса $C090…$C09F; плата плоттера берёт четыре из них:
| Адрес | BASIC | Что |
|---|---|---|
| $C090 | 49296 | запись: шаг X, куда X, шаг Y, куда Y, перо |
| $C091 | 49297 | чтение: концевики XL0 XL1 YL0 YL1 и BUSY |
| $C092 | 49298 | запись: цвет 0–3 |
| $C093 | 49299 | не занят |
3.2. Идея: дешифратор — «ни один бит не отличается»
$C090…$C093 в двоичном виде — 1100 0000 1001 00xx: 14 старших бит заданы, два младших выбирают регистр. Проверить 14 бит разом проще наоборот: найти хоть один не тот. Бит, который должен быть 1, — не тот, когда он 0 (берём его инверсию с CD4069: NA15, NA14, NA7, NA4); бит, который должен быть 0, — не тот, когда он 1 (берём как есть). Все 14 «не тех» — на ИЛИ:
G1 = NA15 ИЛИ NA14 ИЛИ ADDR13 ИЛИ ADDR12,G2 = ADDR11 ИЛИ … ИЛИ ADDR8— CD4072 (ИЛИ на 4 входа);G3 = NA7 ИЛИ ADDR6 ИЛИ ADDR5 ИЛИ NA4,G4 = ADDR3 ИЛИ ADDR2;ANYB = G1 ИЛИ G2 ИЛИ G3 ИЛИ G4(CD4071) — «хоть один бит не тот»;SELP = НЕ ANYB— адрес наш.
3.3. Идея: запись в регистр
Регистр — D-триггеры CD4013: по фронту такта CL запоминают то, что на D. На D — данные процессора DOUT0…DOUT4, а такт должен прийти, только когда процессор пишет именно по этому адресу:
SELW = SELP И НЕ ADDR0—$C090или$C092;WR = SELW И write— и это запись;WE0 = WR И НЕ ADDR1—$C090,WE2 = WR И ADDR1—$C092;- такты регистров:
LCK0 = WE0 И CLK,LCK2 = WE2 И CLK— фронт такта машины, когда данные на шине уже стоят.
$C090 — пять триггеров (AXS, AXD, AYS, AYD, APEN), $C092 — два (AC0, AC1). RST машины сбрасывает их: перо поднято, цвет чёрный.
3.4. Идея: чтение $C091 — на ту же шину
Когда процессор читает $C091, плата должна выставить свои биты на шину данных DIN0…DIN4, а в остальное время — не мешать машине:
SELR1 = SELP И ADDR0 И НЕ ADDR1—$C091;OEP = SELR1 И RnW— и это чтение;- бит платы на шину:
PRD0 = XL0 И OEP, …PRD4 = BUSY И OEP— при чужом адресе всеPRD = 0; - шина к процессору:
DIN = MUX ИЛИ PRD(CD4071).MUX— то, что выдаёт сама машина (чип DataInMux); по адресу$C091у неё ничего нет — там нули, и проходят биты платы. По чужим адресамPRD = 0— проходят данные машины.
Поэтому у машины выходы DataInMux переименовываются в MUX0…MUX4: имя DIN теперь у выхода ИЛИ.
3.5. Идея: кто управляет — CD4019
У CD4019 четыре ячейки «И-ИЛИ»: D = A И KA ИЛИ B И KB. Если KA = REMOTE, а KB = НЕ REMOTE, ячейка — переключатель:
| REMOTE | KA | KB | D |
|---|---|---|---|
| 1 | 1 | 0 | A — регистр компьютера |
| 0 | 0 | 1 | B — пульт |
Две CD4019 — семь переключателей: шаг и направление X и Y, перо, два бита цвета. Их выходы XSTEP, XDIR, YSTEP, YDIR, PEN, COL0, COL1 теперь ведут плоттер — поэтому ноги осей, пера и сравнения цвета перецепляются на них. Револьвер, BUSY и концевики работают как прежде — им всё равно, кто назвал цвет.
3.6. Сборка
Поверх урока 2. Плата — в слот 1 машины: она слушает шину Apple (адрес ADDR0…ADDR15, данные DOUT0…DOUT4, write, RnW, CLK, RST — метки машины) и отвечает на DIN0…DIN4. Тумблер REMOTE выбирает, кто управляет плоттером: компьютер или пульт.
Шаг 1. Дешифратор адреса
| Деталь | Нога / действие | Метка / куда |
|---|---|---|
| TI CD4069UB | A G B H C I D J E K F L | ADDR15 NA15 ADDR14 NA14 ADDR7 NA7 ADDR4 NA4 ANYB SELP ADDR0 NA0 |
| TI CD4072B | A B C D J E F G H K | NA15 NA14 ADDR13 ADDR12 G1 ADDR11 ADDR10 ADDR9 ADDR8 G2 |
| TI CD4072B | A B C D J E F G H K | NA7 ADDR6 ADDR5 NA4 G3 ADDR3 ADDR2 GND GND G4 |
| TI CD4071B | A B J C D K E F L G H M | G1 G2 H1 G3 G4 H2 H1 H2 ANYB MUX0 PRD0 DIN0 |
| Деталь | Нога | Отцепить от | Прицепить к |
|---|---|---|---|
| TI CD4069UB, выход которой = NBUSY | A | GND | ADDR1 |
| TI CD4069UB, выход которой = NBUSY | G | — (не подключена) | NA1 |
| TI CD4069UB, выход которой = NBUSY | B | GND | REMOTE |
| TI CD4069UB, выход которой = NBUSY | H | — (не подключена) | NREM |
Шаг 2. Запись и чтение
| Деталь | Нога / действие | Метка / куда |
|---|---|---|
| TI CD4081B | A B J C D K E F L G H M | SELP NA0 SELW SELW write WR WR NA1 WE0 WR ADDR1 WE2 |
| TI CD4081B | A B J C D K E F L G H M | WE0 CLK LCK0 WE2 CLK LCK2 SELP ADDR0 SELR SELR NA1 SELR1 |
| TI CD4081B | A B J C D K E F L G H M | SELR1 RnW OEP XL0 OEP PRD0 XL1 OEP PRD1 YL0 OEP PRD2 |
| TI CD4071B | A B J C D K E F L G H M | MUX1 PRD1 DIN1 MUX2 PRD2 DIN2 MUX3 PRD3 DIN3 MUX4 PRD4 DIN4 |
| Деталь | Нога | Отцепить от | Прицепить к |
|---|---|---|---|
| TI CD4081B, выход которой = LXS | A | GND | YL1 |
| TI CD4081B, выход которой = LXS | B | GND | OEP |
| TI CD4081B, выход которой = LXS | J | — (не подключена) | PRD3 |
| TI CD4081B, выход которой = LXS | C | GND | BUSYH |
| TI CD4081B, выход которой = LXS | D | GND | OEP |
| TI CD4081B, выход которой = LXS | K | — (не подключена) | PRD4 |
Шаг 3. Регистры
| Деталь | Нога / действие | Метка / куда |
|---|---|---|
| TI CD4013B | S1 R1 D1 CL1 Q1 S2 R2 D2 CL2 Q2 | GND RST DOUT0 LCK0 AXS GND RST DOUT1 LCK0 AXD |
| TI CD4013B | S1 R1 D1 CL1 Q1 S2 R2 D2 CL2 Q2 | GND RST DOUT2 LCK0 AYS GND RST DOUT3 LCK0 AYD |
| TI CD4013B | S1 R1 D1 CL1 Q1 S2 R2 D2 CL2 Q2 | GND RST DOUT4 LCK0 APEN GND RST DOUT0 LCK2 AC0 |
| Деталь | Нога | Отцепить от | Прицепить к |
|---|---|---|---|
| TI CD4013B, выход которой = MOVED | R1 | GND | RST |
| TI CD4013B, выход которой = MOVED | D1 | GND | DOUT1 |
| TI CD4013B, выход которой = MOVED | CL1 | GND | LCK2 |
| TI CD4013B, выход которой = MOVED | Q1 | — (не подключена) | AC1 |
Не подключать: QN1, QN2 у каждой из трёх CD4013B.
Шаг 4. REMOTE и CD4019
Тумблер — Input из палитры.
| Деталь | Нога / действие | Метка / куда |
|---|---|---|
| Input (тумблер) | выход | REMOTE |
| TI CD4019B | KA 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 CD4019B | KA 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 |
Не подключать: D4 у CD4019B.
Шаг 5. Оси, перо и цвет — от CD4019
Ноги механики переименовать так же: двойной клик по метке на ноге.
| Деталь | Нога | Отцепить от | Прицепить к |
|---|---|---|---|
| Linear axis — ось X | STEP | LXS | XSTEP |
| Linear axis — ось X | DIR | RIGHT | XDIR |
| Linear axis — ось Y | STEP | LYS | YSTEP |
| Linear axis — ось Y | DIR | DOWN | YDIR |
| TI CD4081B, выход которой = STEPT | C | LPEN | PEN |
| TI CD4070B, выход которой = X0 | A | LC0 | COL0 |
| TI CD4070B, выход которой = X0 | C | LC1 | COL1 |
Шаг 6. Шина данных Apple
У чипа машины DataInMux метки DIN0…DIN4 на его выходах переименуй в MUX0…MUX4 (у процессора MOS6502 метки DIN0…DIN4 остаются). Теперь данные к процессору идут через плату: CD4071 складывает биты чтения платы с данными машины.
| Деталь | Нога | Отцепить от | Прицепить к |
|---|---|---|---|
| DataInMux (чип машины), выход которого = DIN0 | DIN0 | DIN0 | MUX0 |
| DataInMux (чип машины), выход которого = DIN1 | DIN1 | DIN1 | MUX1 |
| DataInMux (чип машины), выход которого = DIN2 | DIN2 | DIN2 | MUX2 |
| DataInMux (чип машины), выход которого = DIN3 | DIN3 | DIN3 | MUX3 |
| DataInMux (чип машины), выход которого = DIN4 | DIN4 | DIN4 | MUX4 |
3.7. Проверка
- Режим Turbo, включи питание. REMOTE выключен — плоттер слушается пульта, как в уроке 2.
- Включи REMOTE. Машина загрузилась — набери в BASIC (Return после каждой строки):
PRINT PEEK(49297)POKE 49298,2PRINT PEEK(49297)- Первое число — 5, если обе каретки у моторов (горят концевики XL0 и YL0); если каретки ты отвёл пультом — другое.
POKE 49298,2— компьютер назвал зелёный: загорается BUSY, головка поворачивается. Пока крутится,PEEKдаёт число на 16 больше (бит BUSY); когда встала — снова прежнее. - Короткая программа — квадрат зелёным:
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| Команда | Что делает плоттер |
|---|---|
| POKE 49296,V | $C090: биты V — шаг X, куда X, шаг Y, куда Y, перо (1, 2, 4, 8, 16) |
| POKE 49298,C | $C092: цвет 0–3 — головка доворачивает |
| PEEK(49297) | $C091: XL0 1, XL1 2, YL0 4, YL1 8, BUSY 16 |
| REMOTE выключен | пульт, как в уроках 1–2 |
Вставка урока 3 (Cmd+I)
Вставлять в машину Apple ][ (кнопка DEMO) вместо уроков 1–3: ставит всё устройство, переименовывает выходы DataInMux.
# Урок 3 — плата в слоте: дешифратор $C090–$C093, регистры, чтение концевиков и BUSY; REMOTE/LOCAL на CD4019.# $C090 запись: 0 XSTEP 1 XDIR 2 YSTEP 3 YDIR 4 PEN. $C091 чтение: 0 XL0 1 XL1 2 YL0 3 YL1 4 BUSY. $C092 запись: 0–1 цвет.# ---------- механика: ось X, ось Y на её каретке, головка на каретке Y, чёрное перо, бумага ----------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)# ---------- пульт: генератор шагов, стрелки, 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: нажата стрелка по X, по Y; ERROR — каретка упёрлась ----------"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: шаги — такт 60 Гц, пока нажата стрелка ----------"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 — триггер-переключатель ----------"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 и ERROR ----------led{color=green}(VCC)led{color=red}(ERROR)# ---------- кнопка SELECT ----------button{label="SELECT"}(SELB)# ---------- CD4013: старший бит цвета ----------"TI CD4013B"(S1=GND, R1=RST, D1=NLC1, CL1=NLC0, Q1=LC1, QN1=NLC1, S2=GND, R2=GND, D2=GND, CL2=GND)# ---------- генератор мотора револьвера ----------clock{rt=10}(CKT)# ---------- CD4070: цвет ≠ перо у рабочей точки ----------"TI CD4070B"(A=COL0, B=CP0, J=X0, C=COL1, D=CP1, K=X1, E=GND, F=GND, G=GND, H=GND)# ---------- CD4071: MOVE — крутить; BUSY — крутит или только что докрутил ----------"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 полтакта назад (второй триггер; первый — в уроке 3) ----------"TI CD4013B"(S1=GND, R1=RST, D1=DOUT1, CL1=LCK2, S2=GND, R2=RST, D2=MOVE, CL2=NCKT, Q2=MOVED, Q1=AC1)# ---------- CD4069: НЕ BUSY, НЕ такта (входы A и B — в уроке 3) ----------"TI CD4069UB"(A=ADDR1, B=REMOTE, C=BUSYH, I=NBUSY, D=CKT, J=NCKT, E=GND, F=GND, G=NA1, H=NREM)# ---------- CD4081: шаг мотора, перо можно опустить, пара перьев ----------"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: какое перо опустить ----------"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: фазы мотора — два триггера по кругу ----------"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: четверть оборота = 6 шагов ----------"TI CD4017B"(CLOCK=STEPT, RESET=QR, INH=GND, O6=Q6, CO=QCO)# ---------- CD4013: номер пера у рабочей точки ----------"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)# ---------- лампа BUSY ----------led{color=yellow}(BUSYH)# ---------- перья: красное, зелёное, синее ----------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)# ---------- дешифратор адреса $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: запись в $C090 и в $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: такт регистров, чтение $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: биты чтения ----------"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: биты чтения — на шину данных ----------"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)# ---------- регистр $C090: шаги, направления, перо ----------"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)# ---------- тумблер REMOTE ----------input(REMOTE)# ---------- CD4019: кто управляет — компьютер (REMOTE = 1) или пульт ----------"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)Не получается? Что-то не работает →