Уровень 24: Ручной пиксель
Открыть уровень →Где это в машине →
Задание
Цель: Прежде чем программировать дисплей (уровень 27), посмотрите на его порты в железе: подключите 4 BusConstant к MatrixDisplay и зажгите пиксель в (0,0).
MatrixDisplay — матричный дисплей 16×16. У него 4 входа:
- DevAddr (порт 0): номер порта (0x1C = установить X, 0x1D = установить Y, 0x1F = запись пикселя; 0x1C = 28, 0x1D = 29, 0x1F = 31)
- DataIn (порт 1): значение (для X/Y — координата 0–15, для записи — 1=зажечь, 0=погасить)
- WE (порт 2): разрешение записи (1 = писать)
- IO_SEL (порт 3): выбор устройства (1 = дисплей активен)
Главная идея уровня: дисплей — не магия, а протокол: три записи в память подряд (X, затем Y, затем пиксель) превращают запись в рисование на экране. Программе достаточно знать порты, чтобы рисовать.
Материалы по теме
- Memory-Mapped I/O: Гениальный обман процессора
- Справка по ассемблеру →
- MatrixDisplay — матричный дисплей
- AddrDecoder — дешифратор адреса
Решение для самопроверки
Сначала попробуйте собрать схему сами. Решение ниже — способ свериться, если застряли или уже справились.
Что должно получиться: пиксель в левом верхнем углу (0,0) горит.
Здесь дисплей управляется не адресами памяти, а четырьмя отдельными шинами: DevAddr выбирает операцию, DataIn несёт значение, WE разрешает запись, IO_SEL активирует устройство. Это отличается от уровней 28–29, где экран прячется за адресами MMIO (252/253/255) — Memory-Mapped I/O, «ввод-вывод, отображённый на память»: устройство выглядит для процессора как ячейка памяти — и процессор общается с ним как с памятью.
Изначально X=0, Y=0. Чтобы зажечь пиксель в (0,0):
- Выставьте первый BusConstant (DevAddr) в 0x1F (31) — режим записи пикселя.
- Выставьте второй BusConstant (DataIn) в 1 — зажечь.
- Выставьте третий BusConstant (WE) в 1 — разрешить запись.
- Четвёртый BusConstant (IO_SEL) уже равен 1 — оставьте.
5. Соедините провода:
- BusConstant#1 (Q) → MatrixDisplay (DevAddr, порт 0)
- BusConstant#2 (Q) → MatrixDisplay (DataIn, порт 1)
- BusConstant#3 (Q) → MatrixDisplay (WE, порт 2)
- BusConstant#4 (Q) → MatrixDisplay (IO_SEL, порт 3)
Нажмите чекпойнт — пиксель в левом верхнем углу должен загореться!
Проверь себя
Чем порты дисплея здесь отличаются от уровней 28–29?
Здесь 4 отдельных входа (DevAddr/DataIn/WE/IO_SEL); на уровнях 28–29 дисплей прячется за MMIO-адресами 252/253/255.