Сорцы
Q: Где их брать?
A: Репозиторий с сорцами находится по адресу:
https://github.com/tslabs/zx-evo/
Можно скачивать прямо с сайта в архиве, можно использовать TortoiseGit клиент. В командлайне выполнить:
git clone https://github.com/tslabs/zx-evo.git
Краткая документация по TS Config:
https://github.com/tslabs/zx-evo/raw/ma ... TSconf.xls
Краткая документация по портам ZiFi:
https://github.com/tslabs/zx-evo/blob/m ... Fi/zifi.md
Прошивки
Q: Где их брать?
A: Там же, где сорцы.
Прошивки контроллера искать по пути:
pentevo/avr/current/default/
zxevo_fw.bin - прошивка со стандартной раскладкой клавиатуры
Прошивки ПЗУ:
pentevo/rom/bin/
ts-bios.rom - 64кБ образ, достаточный для работы конфигурации. Может быть прошит из Baseconf ERS как Custom ROM
zxevo.rom - 512кБ образ, совместимый с обеими конфигурациями.
Как шить
Метод 1. Прошивка с нуля.
1. Записываем на СД-карту файлы:
https://github.com/tslabs/zx-evo/raw/ma ... evo_fw.bin
https://github.com/tslabs/zx-evo/raw/ma ... /zxevo.rom
Вставляем карту в пентеву.
2. Зажимаем софт ресет и нажимаем хард ресет, ждем пока зашьется Тест-н-Сервис.
3. Заходим в меню прошивки ПЗУ, выбираем zxevo.rom, шьем ПЗУ.
4. Вынимаем карту, записываем на карту файл:
https://github.com/tslabs/zx-evo/raw/ma ... evo_fw.bin
Вставляем карту в пентеву.
5. Зажимаем софт ресет и нажимаем хард ресет, ждем пока зашьется конфа.
Метод2. Перешивка с ERS.
1. Записываем на СД-карту файлы:
https://github.com/tslabs/zx-evo/raw/ma ... s-bios.rom
https://github.com/tslabs/zx-evo/raw/ma ... evo_fw.bin
Вставляем карту в пентеву.
2. Заходим в ЕРС в пункт программирования Custom ROM, выбираем ts-bios.rom, шьем.
3. Зажимаем софт ресет и нажимаем хард ресет, ждем окончания прошивки.
Метод3. Перешивка при помощи утилиты Migrator by Budder.
https://forum.tslabs.info/viewtopic.php?f=26&t=160
Настройка BIOS
По RESET в ТСконфе управление передается на страницу ПЗУ 0 (а не 31, как в бейзконфе).
Для захода в BIOS зажимаем SS, нажимаем F12.
Есть 2 опции ресета - обычный с зажатым CS. Оба варианта совершенно равноправны.
Reset to
- ROM #00 - запуск выбранного банка (см. ниже) из страниц ПЗУ #00-03.
- ROM #04 - запуск выбранного банка из страниц ПЗУ #04-07. Это дает возможность держать в одной ПЗУ разные биосы, в т.ч. собственные, параллельно с основным.
- RAM #F8 - виртуальное ПЗУ из ОЗУ. При запуске с этой опцией на адресное пространство z80 0000-3FFF подключаются соотв. страницы ОЗУ с аппаратной защитой записи по этим адресам. Т.е., загрузив на страницы ОЗУ #F4-F7 нужные прошивки, можно невозбранно их юзать. Полезно для отладки собственных биосов, например. Все страницы 48/128/тр-дос мапятся так же, как и в ПЗУ.
Прошивки в 4-х смежных страницах ПЗУ/ОЗУ расположены так:
0 - SYS (доступна только с помощью программирования порта MemConf и при RESET)
1 - TR-DOS (включается при выполнении кода по адресам #3D00-#3DFF при 4-м бите #7FFD =1)
2 - Basic 128 (4-й бит #7FFD =0)
3 - Basic 48 (4-й бит #7FFD =1)
- BD boot.$c - загрузка хобетного кодеблока с именем boot.$c, расположенного в корневой папке Boot Device. Поддерживаются SD-карта, IDE, RS-232.
bank
- TR-DOS (сброс в тырдос)
- Basic 48 (сброс в барсик)
- Basic 128 (сброс в барсик128)
- SYS (сброс в пейджу 0 выбранного блока ПЗУ/ОЗУ)
Boot Device
- Устройство, в корне которого должен лежать boot.$c, который загружается и запускается при нажатии на ресет.
Разработка
Q: Можно ли принимать участие в разработке?
A: Да хоть щас. Приветствуется акк на гуглкодах, я просто добавляю в коммитеры, по запросу.

Программирование системы:
Документация, примеры

TS-Config Datasheet: (English/ Russian)
Краткая памятка программиста: основная дока по конфе, божественный Excel
Цикл статей на HYPE
Примеры кодов
Сорцы TS TechDemo в качестве примера

Расширенные графические режимы - цвет на точку
Видеоконтроллер TS-Config адресует экранную область в виде растра 512x512 пикселей, который расположен на идущих подряд страницах памяти, начиная с номера, заданного в регистре VPage (0x01AF). Номер должен быть кратен 8 для режима 16 цветов на точку и 16 для 256 цветов на точку.
Растр отображается на экран через "окно", размер которого определяется битами RRES[1:0] регистра VConfig (0x00AF). Таким образом, на экране виден лишь тот участок растра, который попадает в окно.
Координаты верхнего левого угла окна внутри растра задаются регистрами GXOffs и GYOffs в диапазоне от 0 до 511 пикселей. Окно зациклено по Х и У координатам внутри растра.
Режим 16 цветов на точку.
Один байт кодирует цвета двух смежных пикселей: биты 7:4 - левый, 3:0 - правый
Длина строки растра в байтах: 512/2 = 256 байт.
В одной 16к-странице памяти умещается 64 строки растра.
Весь растр занимает 512/64 = 8 страниц памяти.
Пересчет координат в номер страницы и смещение в ней.
Работа ведется с банком по адресу 0xC000, регистр выбора страницы - Page3.
Вход:
D - маска для адреса процессорного окна (#00, #40, #80 или #C0 для окон 0,1,2 или 3, соответственно)
E - номер начальной страницы растра,
HL - Y-координата,
BC - X-координата.
Выход:
A - номер страницы, которую нужно включить,
DE - адрес байта с пикселями,
CF - какому полубайту принадлежит пиксель: 0 - левому, 1 - правому.
- Code: Select all
crd2pixaddr16c:
ld a,l
and #3f ; thanks for Buyan
or d
ld d,a
add hl,hl
add hl,hl
ld a,h
add a,e
srl b
rr c
ld e,c
<ret>
Описание работы с графическим слоем, с примерами

Текстовый режим
В VPage указывается страница текстового экрана, в страницу VPage XOR 1 загружается фонт в обычном формате 8 байт на символ, байты друг за другом. Включаем текстмод и работаем. Строка текстового экрана представляет собой 128 байт букв и 128 байт их атрибутов, таких строк 64. Соответственно показывается только рамка, которую можно двигать. В атрибутах младшие 4 бита - цвет букв, старшие 4 - цвет фона.

Палитра
Q: Есть квикстарт по сабжу?
А: Да. https://forum.tslabs.info/viewtopic.php?f=35&t=178
Q: Сколько ячеек?
А: 256.
Q: Какой формат ячейки?
А: Ячейка палитры состоит из 2х байт. Формат их следующий:
Мл.байт: gggBBbbb
Ст.байт: 0RRrrrGG
RR, GG, BB - цветовые компоненты видео-ЦАПа,
rrr, ggg, bbb - дополнительные биты чанкового ШИМа. Если хотите чтоб на LCD все было гладко, тут должны быть нули.
Примеры (в скобках - HTML код цвета):
синий (#0000FF): 00011000, 00000000 = 0x18, 0x00 = 24, 0
красный (#FF0000: 00000000, 01100000 = 0x00, 0x60 = 0, 96
зеленый (#00FF00): 00000000, 00000011 = 0x00, 0x03 = 0, 3
темносерый с использованием ШИМа (#212121): 10000100, 00010000 = 0x84, 0x10 = 132, 16
Q: Какие ячейки используются в режиме спектрума (6912)?
А: Сразу после сброса 240-255 (0хF0..0xFF). Для цветов с BRIGHT 0 - 0хF0..0xF7, BRIGHT 1 - 0хF8..0xFF. Цвета BORDER через порт бордюра - 0хF0..0xF7.
В режимах, где используется 16 цветов (ZX, 16c) используются ячейки 0хn0..0xnF, где n - биты 3:0 регистра PalSel (0x07AF). При ресете туда записывается 0xF.
Q: Как загрузить палитру?
А: Поскольку палитра хранится во внутренней памяти FPGA, надо включить отображение оной на память процессора. Для этого надо записать в регистр FMAddr (0x15AF) значение 0001bbbb, где bbbb - 4 старших бита адреса, куда мапится массив палитры, а 1 - разрешение записи. Например: значение 0х18 откроет палитру на запись с адреса 0х8000, а 0х10 - с 0х0000. После записи палитры в FMAddr надо записать 0 для отключения маппинга.
Палитра работает ТОЛЬКО на запись. Чтение из выбранной памяти равносильно чтению из ПЗУ/ОЗУ, которое там находится.
Палитру можно загружать через DMA, FMAddr при этом открывать не нужно, а в качестве адреса назначения (DMADAddr) надо указывать адрес ячейки в массиве палитры (0-510).
Q: Пример кода для загрузки палитры зетником?
А:
- Code: Select all
;open FMAddr access from 0x0000
ld bc, 0x15AF
ld a, 0x10
out (c), a
;load CRAM
ld hl, PAL ;some palette array address
ld de, 0x0000 ;CRAM access window address
ld bc, 512 ;any size here up to 512
ldir
;close FMAddr
ld bc, 0x15AF
xor a
out (c), a
Файл палитры для фотошопа (64 цвета)

TSU (Тайло-спрайтовый двиг)
Q: Терминология
A:
Тайл - Кусочек графики размером 8х8 пикселей в формате 4 бита на пиксель (левый пиксель - биты 4-7, правый - 0-3), цвет с кодом 0 - прозрачный.
Спрайт - Набор из расположенных рядом тайлов. Размер задается произвольно в диапазоне 1-8 тайлов (8-64 пикселей) независимо для высоты и ширины.
Битмап - банк графики, содержащий нарисованные тайлы. Хранится в виде 64х64 тайлов / 512х512 пикселей / 256х512 байт / 128кБ / 8 последовательных страниц, начиная с кратной 8-ми.
Тайлмап - карта, содержащая информацию про отображаемые тайлы. Содержит элементы по 2 байта, описывающие тайлы в определенных местах экрана. Хранится в виде (64 (слой0) + 64 (слой1) ) х 64 тайла / (128 + 128) х 64 байт / 16кБ / 1 страница. Формат: биты0-11 - номер тайла в битмапе (0-5 - Х координата, 6-11 - У), биты 12-13 - выбор палитры из набора из 4х (номер набора задается в порту PalSel в битах 4-5 для слоя 0 и в 6-7 для слоя 1), биты 14-15 - зеркальное отображения для Х и У соотв.
Палитра - содержит физические значения цвета для набора из 16 логических цветов (цвет с кодом 0 зарезервирован как прозрачный, поэтому не используется). Формат палитры: мл.байт - gggBBbbb, ст. байт - 0RRrrrGG, где NN - цвет, физически выводимый на ЦАП, nnn - ШИМ-составляющая. Всего доступно 16 палитр, которые используются совместно графикой, тайловыми и спрайтовыми плоскостями. Для спрайтов выбор палитры возможен 1 из 16 индивидуально, для тайлов возможен выбор 1 из 4 наборов по 4 палитры индивидуально для каждого слоя, с последующим выбором 1 из 4 палитр из набора индивидуально для тайла. Для графики выбор палитры зависит от режима.
Q: Как расположены слои ТС/графики?
A: Вот так, снизу вверх:
- бордюр
- основная графика (256с, 16с, ZX, текстмод)
- спрайтовый слой 0
- тайловый слой 0
- спрайтовый слой 1
- тайловый слой 1
- спрайтовый слой 2
Q: Как задать к какому слою (0-2) принадлежит спрайт?
A: Битом LEAP, переход на следующий слой. Бит работает следующим образом: если он включен и спрайт активен/видим в данной строке, то спрайт рисуется и заканчивается обработка данного слоя и осуществляется переход на следующий. Если неактивен - просто переход. Если LEAP=1 во время рисования спрайтового слоя 2, заканчивается работа ТС-двига.
Q: Как приоритизируются спрайты?
A: По номеру - чем больше номер, тем спрайт сверху.
Q: Как рисовать тайловую плоскость?
A: Примерно так:
1. Записать в порт T0GPage (0x17AF) номер 1й страницы битмапа, номер обязан быть кратным 8 (0, 8, 192, 240 и т.д.)
2. Записать в порт TMPage (0x16AF) номер страницы тайлмапа.
3. Загрузить битмап, тайлмап на соответствующие страницы.
4. Загрузить палитру(палитры), выбрать наборы палитр в PalSel (0x07AF) биты 4-5 и 6-7.
5. Записать в порт TSConfig (0x06AF) режим отображения слоев (бит 6 - слой 1 разрешен, бит 5 - слой 0).
Q: Как узнасть адрес тайла на битмапе?
A: Примерно так:
Q: Как устроен TSU?
A: Для работы TSU отведено 1792 такта 28МГц (строка видео). TSU живет исключительно в пределах одной строки изображения и работает в строке, предшествующей той, которая видна в данный момент на экране. Двиг разбит на 2 функциональные части: обработчик объектов (парсер) и рендерер. Парсер последовательно проходит по слоям графики и объектам внутри слоев. Как только парсер готов сформировать задание для рендера (от 1 до 8 тайлов в ряд, с заданной палитрой, координатой, направлением рисования а также, адресом ОЗУ, откуда читать битмап), а рендер - его принять - начинается трах ОЗУ/рисование в буфер оверлея, а обработчик объектов двигается дальше. Рендерер рисует пиксели в буфер, который состоит из 360 байт, и буфер этот накладывается поверх основной графики по маске !=0 в течении отображения строки видео. Формат буфера - биты 4-7 - палитра, биты 0-3 - цвет в палитре, если биты 0-3 == 0, то пиксель в буфере прозрачный. Буферов 2, чтоб чередовать.Все это происходит в фоне относительно Z80, не тормозя его работу. На рисование одного пикселя уходит 1 такт 28МГц, следовательно производительность приближается к 1792 пикселей за строку, за вычетом ожиданий ОЗУ и накладных расходов на парсер, когда рендерер свободен, а задание для него не готово.

Вывод спрайтов

DMA
Q: Почему в регистрах младших битов адресов не используется 0-й бит?
А: Для получения наибольшего быстродействия и минимальных затрат логики ДМА работает с 16-битными данными, следовательно адреса четные.
Записывая в младший байт регистра адреса число, младший бит НЕОБХОДИМО занулять.
Q: Почему в регистрах адреса DMAхAddrH не используются биты 7, 6?
А: Чтоб сохранить совместимость со страничной адресацией и упростить операции по вычислению адреса. В эти биты можно писать произвольные значения.
В младшие регистры адреса записывается смещение внутри страницы, а оно лежит в диапазоне 16кБ.
Q: Как установить адрес источника
А: В регистры DMASAddrH:DMASAddrL надо записать адрес внутри страницы $0000..$3FFE (в привычной адресации можно и $C000..$FFFE, и не забываем про четность!),
в регистр DMASAddrX - страницу в диапазоне $00..$FF.
Q: Как установить адрес приёмника
А: Аналогично источнику, но записывать регистры DMADAddrL, DMADAddrH, DMADAddrX
Q: Как установить длину пересылаемого массива?
A: Для установки длины массива используются два регистра: DMALen и DMANum.
DMALen определяет длину бурста в диапазоне 2..512 байт с шагом 2 байта. Значение 0 регистра соответствует 2 байта, 255 - 512 байт.
DMANum определяет количество бурстов диапазоне от 1 до 256. Значение 0 соответствует 1 бурсту, 255 - 256 бурстов.
Q: Как запустить пересылку?
А: Записать в регистр DMACtrl значение с параметрами транзакции.
Битовые поля ~R/W, DDEV[2:0] выбирают устройства источника/приемника (подробнее см. эксель).
Биты S_ALGN, D_ALGN указывают, требуется ли выравнивать адрес на границу 256/512 байт после каждого бурста для адреса источника и приемника. Выравнивание для источника и приёмника включается раздельно битами 5 (S_ALGN) и 4 (D_ALGN) регистра DMACtrl. Таким образом, можно установить выравнивание только для источника либо только приёмника (применимо для преобразования форматов) или обоих одновременно (применимо для копирования участков растра).
A_SZ - выбор величины выравнивания (256/512 байт). Размер выравнивания определяется битом 3 (A_SZ). 0 соответствует 256 байтам, 1 - 512. Этот параметр является общим для источника и приёмника, т.е. невозможно установить для источника один размер выравнивания, а для приёмника - другой.
Q: Зачем нужно выравнивание адреса?
А: Полезно для работы с графикой. Также возможно копирование прямоугольных областей текстового экрана.
Пример:
Нужно переслать кусок графики в режиме 256с размером 32х32 пикселя. Графика хранится в памяти в виде массива 1024 байта (32*32).
В регистры DMASAddr записываем адрес спрайта.
В регистры DMADAddr записываем адрес в экранной области.
В DMALen пишем значение 15 (длина бурста 32 байта).
В DMANum пишем 31 (32 бурста).
В S_ALGN выставляем 0 - источник выравнивать не надо, графика там лежит подряд.
D_ALGN выставляем 1 - приемник НАДО выравнивать после каждого бурста, чтоб получить прямоугольник.
В A_SZ выставляем 1 - режим выравнивания 512 байт, поскольку в экранке 256с линия изображения занимает 512 байт.
~R/W = 0, DDEV[2:0] = %001 - RAM/RAM
Все битовые поля задаются константой в каком-нить реге, например вот так:
LD A, %00011001 ; по экселю

а потом пишутся в DMACtrl.
Вуаля, должно получиться.
DMASAddr = $08 2000 ;page 8, address $E000
DMADAddr = $10 0000 ;page 16, address $C000, верхний левый угол экрана
Как будут изменяться адреса при пересылке:
Бурст 1: DMASAddr = $08 2000.. $08 201E, DMADAddr = $10 0000..$10 001E
Бурст 2: DMASAddr = $08 2020.. $08 203E, DMADAddr = $10 0200..$10 021E
Бурст 3: DMASAddr = $08 2040.. $08 205E, DMADAddr = $10 0400..$10 041E
...
Бурст 32: DMASAddr = $08 23E0.. $08 23FE, DMADAddr = $10 3E00..$10 3E1E
После транзакции адреса будут:
DMASAddr = $08 2400, DMADAddr = $11 0000 <- произошел переход на следующую страницу.
DMALen и DMANum сохраняют свои значения между транзакциями, поэтому их не нужно писать повторно, если требуются те же параметры.
Адреса, как указано выше, указывают на следующие значения (HL и DE при LDIR - хорошая аналогия).

Q: Как проверить, закончилась ли пересылка?
А: Прочитать регистр DMAStatus. На время пересылки бит 7 регистра установлен в 1.
А еще, можно сделать так, чтоб пришел INT


Диспетчер памяти
Q: Сколько страниц памяти всего?
А: 256 - ОЗУ и 32 - ПЗУ, размер страниц - 16кБ.
Q: Куда какие страницы можно включать?
А: Страницы можно включать индивидуально для окон #0000, #4000, #8000, #C000.
ОЗУ можно включить в любом из 4-х окон. ПЗУ - только в окне #0000.
Q: Как?
А: Регистры Page0-Page3. Номер страницы задается линейно 0-255. Для страниц ПЗУ используются только биты 4:0, биты 7:5 игнорируются.
Q: Что творится в в окне #0000, как использовать регистр MemConfig?
А: Отображаемая страница в окне #0000 задается в регистре Page0.
MemConfig указывает что и каким образом там отображать.
W0_RAM: что отображать - 0 - ПЗУ, 1 - ОЗУ
W0_WE: 0 - запись запрещена, 1 - разрешена. Для ПЗУ - это соответствующая ножка чипа EEPROM. Для ОЗУ - просто запрет записи. Нужно для правильной работы прошивки бейсика из ОЗУ, поскольку бейсик пишет в адреса ПЗУ и портит прошивку.
!W0_MAP: включает "маппинг" четвертинок ПЗУ в окне 0. При этом номер страницы образуется так: биты 7:2 (или 4:2 для ПЗУ) берутся из Page0, а биты 1:0 заменяются на то, что должно быть в окне 0 в зависимости от бита 4 из #7FFD и включенности TR-DOS:
00 Service
01 DOS
10 128
11 48
Это позволяет загрузить в ОЗУ прошивку ПЗУ (64кБ) и использовать например для отладки.
ROM128 - копия бита 4 из #7FFD.


Контроллер маскируемых прерываний
В TS-Conf можно запрограммировать несколько источников маскируемого прерывания. Среди них:
- кадровый (frame, индекс 0),
- строчный (line, индекс 1),
- окончание DMA транзакции (dma, индекс 2).
Источник frame срабатывает, когда значение счетчиков растра совпадает с регистрами HSINT и VSINT. Источник line срабатывает в каждой строке, когда горизонтальный счетчик растра равен 0. Источник dma срабатывает после окончания любой транзакции DMA.
Каждый источник прерывания формирует сигнал ~INT и выставляет собственный байт D[7:0] на ШД в цикле ~IORQ || ~M1.
- $FF - кадровый,
- $FD - строчный,
- $FB - DMA.
В случае прихода нескольких событий одновременно, сначала обработается прерывание с меньшим индексом. При завершении ISR инструкциями EI : RET сразу произойдет обработка следующего по порядку ~INT, который разпознается в последнем машцикле инструкции RET.
Регистр конфигурации INTMask содержит биты разрешения индивидуального источника маскируемого прерывания, 0 - запрещен / 1 - разрешен. По ~RESET туда записывается значение $01: разрешен frame, все остальные запрещены. Если из ISR прерывания с меньшим приоритетом записать 0 в соответствующий бит маски источника прерывания, ожидающего в данный момент обработки, то произойдет его сброс и прерывание обработано не будет. Запись 1 не влияет на состояние ожидающего прерывания. Структура INTMask следующая:
бит 0, FRAME - разрешение источника frame,
бит 1, LINE - разрешение источника line,
бит 2, DMA - разрешение источника dma,
биты 3-7 - не используются, записывать 0.


Общее

Необходимые для работы программы
Работа с оборудованием

Драйвер WiFi, esp8266