Эмуляция z80 на ардуино

Союз Arduino и классического процессора

Ретрокомпьютерщики бывают различной степени привередливости. Одни довольствуются эмуляцией. Другие предпочитают ПЛИС, потому что тогда получается не эмуляция, а воссоздание. Наконец, третьим подавай настоящий процессор.

Но процессору для работы нужно столько всего! Снова дилемма: взять настоящие микросхемы тех же лет, или поместить всё в ПЛИС, оставив снаружи процессор? Впрочем, почему обязательно ПЛИС? Да здравствует союз Arduino и классического процессора!

Подарите своему Arduino «второй мозг» и сделайте его «умнее».

Настоящий восьмибитный микропроцессор выполняет программы, а Arduino эмулирует ПЗУ, ОЗУ и простейшую периферию.

Проектируйте виртуальную периферию в Arduino IDE, а на микропроцессоре запускайте код на ассемблере. Не нужно собирать сложные схемы и прошивать параллельные ПЗУ.

Поддерживаемые микропроцессоры: 6502, 6809 и Z80 (КР1858ВМ1), на подходе — другие.

Шилд с микропроцессором не мешает подключать другие шилды: с ЖКИ, картами памяти, и др.

Помимо самостоятельного программирования на ассемблере, можно попробовать запустить на микропроцессоре какой-нибудь классический код.

Правда, микропроцессор будет работать на очень небольшой частоте — порядка 95 кГц, точное её значение зависит от оптимизации кода эмуляции периферии.

Распределение адресного пространства задаётся программно в скетче. Микропроцессору можно выделить от 4 до 6 кБ ОЗУ из 8 кБ, имеющихся на Arduino Mega. ПЗУ можно выделить более 200 кБ из имеющихся 256.

При помощи последовательного порта Arduino Mega можно эмулировать UART.

Схемы, чертежи плат, Gerber-файлы доступны под CC-BY-SA 4.0 здесь. При этом имеется требование обязательно прикладывать файл README.md, потому что в нём содержится следующее предупреждение:

Не подключайте шилд, пока не залит скетч эмуляции периферии! Иначе возможно закорачивание выходных линий микропроцессора.

Да и в самом скетче что-нибудь переделывать нужно осторожно по той же причине.

Схема устройства на 6502:

Схема устройства на 6809:

Схема устройства на Z80:

Уже можно запустить:

На устройстве с Z80 — пока только эхо-тест последовательного порта, позволяющий проверить работоспособность виртуального 8251 (КР580ВВ51А).

Прошивки для эмуляции периферии — под лицензией MIT.

Краткие описания принципа действия:

К устройству на Z80 — в процессе подготовки.

Разработчик пытается продавать устройства, но с доставкой только по США. Особого смысла покупать нет, поскольку схема очень простая, повторить её на куске макетки можно за час.

Запланирована разработка аналогичных плат на RCA1802, 68008, 8085 (КР1821ВМ85А), 8088 (КР1810ВМ88). Про К1801ВМ1 не сказано, но можно подкинуть автору такую идею.

Рассмотрим взаимодействие Arduino и устройства на 6502. Arduino периодически меняет уровень на входе микропроцессора, предназначенном для подачи тактовых импульсов, с нуля на единицу и обратно. На каждом такте оно проверяет, что происходит на линиях управления и шине адреса, и, в зависимости от ситуации, считывает информацию с шины данных или отправляет её туда. Arduino может также управлять линиями IRQ и NMI, вызывая прерывания. На рисунке показаны виды данных и направления их передачи:

Соответствие портов Arduino и выводов микропроцессора сконфигурировано в скетче:

Разобьём каждый такт на следующие события:

CLK меняет состояние с единицы на нуль (спад)
CLK находится в состоянии нуля
CLK меняет состояние с единицы на нуль (нарастание)
CLK находится в состоянии единицы
CLK снова меняет состояние с единицы на нуль…

Что происходит в моменты смены состояний?

6502 получает тактовые импульсы по входу CLK0, буферизует их и отправляет на два выхода: CLK1 и CLK2. Хотя в микропроцессоре все события привязаны к CLK1, будем считать, что задержка невелика, и они привязаны к CLK0 — той линии, по которой здесь микропроцессор получает тактовые импульсы из Arduino. И называть сигнал просто CLK.

1. CLK меняет состояние с единицы на нуль.

2. Микропроцессор выводит на шину адреса новый адрес, а на выход R/W — сигнал переключения между чтением и записью. Но он ещё не готов к обмену данными.

3. CLK переходит в состояние единицы, и это означает, что обмен данными начался. Если это операция чтения, микропроцессор переводит выводы шины данных в состояние входов и принимает по рим данные, а если операция записи — переводит их в состояние выходов и отправляет данные. А сигнал R/W переключает внешнее устройство в режим записи или чтения, противоположный соответствующему состоянию микропроцессора.

4. CLK переходит в состояние нуля. Теперь на шину даннных ничего не выводят ни микропроцессор, ни устройства ввода-вывода. Микропроцессор может установить в новое состояние линии шины данных и вывод R/W.

Простое объяснение, понятное и ребёнку. Который никогда и не задумается об этих «закулисных интригах», если будет программировать только микроконтроллеры. Даже на ассемблере.

Если нужно подключить своё периферийное устройство, оно должно успевать подготавливать данные до того, как на линии CLK появится единица (время подготовки), а пока там единица — не менять их. Если периферийное устройство не успеет подготовить данные, пока на CLK нуль, или поменяет их, когда там единица, вы будете долго недоумевать, почему ваш код не работает. Поскольку тактовая частота микропроцессора здесь в десять-пятнадцать раз ниже номинальной, соблюсти это требование просто. Но нужно обязательно.

Итак, нужно «научить» Arduino генерировать тактовые импульсы, непрерывно проверяя, что при этом происходит на шине адреса и линии R/W, и соответствующим образом взаимодействуя с шиной данных. Для этого в скетче задействовано прерывание по таймеру timer1, вырабатывающему импульсы с частотой в 95 кГц. Arduino работает значительно быстрее микропроцессора, и потому между его тактами успевает всё и считывать, и подготавливать. Важно проследить, чтобы после модификации скетча это условие продолжало соблюдаться.

Вот выдержка из скетча, по которой понятно, как CLK переходит из нуля в единицу, и что происходит далее:

Распределение адресного пространства можно сделать каким угодно, в немодифицированном скетче оно такое же, как в Apple 1 с 256 байтами ПЗУ, 8 килобайтами ПЗУ для Бейсика, 4 килобайтами ОЗУ и устройством ввода-вывода 6821.

ОЗУ эмулируется массивом byte RAM[RAM_END-RAM_START+1]. Два ключевых слова PROGMEM нужны, чтобы содержимое эмулируемых ПЗУ хранилось во флеш-памяти микроконтроллера.

6821 эмулирован в достаточной мере, чтобы через «терминалку» работали виртуальные клавиатура и дисплей. Woz Monitor и Бейсик работают, чего и добивался автор.

Чтобы эмулировать любое периферийное устройство, нужно внимательно ознакомиться с его даташитом и выяснить, какие у него есть регистры, и для чего они предназначены. Удобство эмуляции — в гибкости, с которой можно делать программные аналоги периферии.

Устройства ввода-вывода находятся в адресном пространестве микропроцессора, обращение к ним происходит так же, как к ячейкам памяти. Чтобы использовать «железную» периферию, такую, как ЖК-дисплей, карту памяти, выход звука, нужно выделить им в адресном пространстве место.

Переходим к 6809, в нём имеются:

Два восьмибитных аккумулятора A и B, которые могут быть объединены в один шестрадцатиразрядный аккумулятор
Два 16-битных индексных указателя стека
Адресация относительно счётчика команд
Автоматическое прибавление или вычитание числа 1 или 2
Перемножение двух восьмиразрядных чисел без знака
16-битная арифметика
Перенос и обмен данными между всеми регистрами
Запись и чтение всех регистров и любого их сочетания

Микропроцессору 6809E (external) нужен внешний тактовый генератор, у 6809 он внутренний. У Hitachi они называются, соответственно, 6309E и 6309, от обычных они отличаются тем, что внутри операции у них выполняются в 32-разрядном виде, но возможно переключение в режим совместимости с классическим вариантом.

Собственно, весь проект RetroShield потому и начался, что автор хотел модернизировать свой же самодельный компьютер Simon6809 и назвать результат Simon6809 Turbo. Но оказалось, что микросхем стандартной логики для всего, что он хотел там реализовать, потребовалось бы очень много. Поэтому идею RetroShield автор впервые сформулировал именно применительно к 6809, и лишь затем подумал: «а что если и с другими процессорами то же проделать?».

В устройстве, разумеется, применён 6809E, требующий внешнего тактового генератора, чтобы можно было синхронизировать его работу извне. Линии E и Q у обоих процессоров называются одинаково, только у 6809 это выходы, а у 6809E — входы.

С 6809 Arduino взаимодействует так же, как с 6502, но входов тактовой частоты у него два: E и Q, а входов для прерываний — три: IRQ, FIRQ и NMI.

В этот раз соответствие портов Arduino и выводов микропроцессора сконфигурировано так:

Как видно из графиков, сигнал Q сдвинут относительно E на четверть периода:

Обращать внимание на Q мы почти не будем, так как все события привязаны к E. А происходит всё так:

  1. E переключается в нуль. Процессор выставляет на шину адреса новый адрес и меняет состояние линии R/W.
  2. E переключается в единицу, процессор становится готов к обмену данными.
  3. Неважно, что происходит с шиной данных, пока на E единица, главное, чтобы требуемые данные там присутствовали в момент перехода E обратно в нуль.
  4. При чтении данных устройство ввода-вывод должно подать на шину данных требуемые данные до перехода линии E из единицы в нуль (минимальная задержка показана числом 17 в кружке).
  5. При записи устройство ввода-вывода должно зафиксировать данные у себя в каком-нибудь регистре в том виде, в каком они были в момент перехода E из единицы в нуль. Процессор же подаст эти данные на шине даже раньше — в момент перехода Q в единицу (число 20 в кружке).
  6. После перехода E в нуль всё повторяется.

Всё сказанное выше про 6502 о необходимости выработки периферийным устройством (в т.ч. виртуальным) всех сигналов вовремя касается и 6809.

Генерация сигналов E и Q, как и в случае с 6502, с той лишь разницей, что сигналов два, и переключать их надо в соответствии с графиками. И точно так же подпрограмма, вызываемая по прерыванию, выполняет в требуемые моменты ввод или вывод данных.

Адресное пространство в немодифицированном скетче распределено так же, как в самодельном компьютере Simon6809:

ОЗУ и ПЗУ хранятся в массивах так же как в варианте на 6502, с той лишь разницей, что здесь массив с данными ПЗУ — один.

Устройствам ввода-вывода здесь также выделены участки адресного пространства, и они могут быть как виртуальными, так и реальными. Так как Simon6809 — современная машина на винтажной элементной базе, с ПК, на котором запущена «терминалка», она обменивается данными через FTDI. Здесь эмулировано и это.

Источник

Как заставить Arduino петь как ZX Spectrum. Часть 1: исторический экскурс

ZX Spectrum 128 и его многочисленные клоны имели встроенный звукогенератор AY-3-8912, благодаря чему как зарубежные музыканты, так и наши соотечественники успели написать огромное количество музыки под этот компьютер.

В двух частях этой статьи, приправленных щепоткой ностальгии, мы вспомним основные способы звукоизвлечения на ZX Spectrum 128, обозначим характеристики “музыкального сопроцессора” AY-3-8912, перечислим наиболее известные музыкальные редакторы, продизассемблируем музыкальный модуль от популярной игры Dizzy IV и воссоздадим его на Arduino. Приглашаем под кат всех любителей компьютерной музыки, DIY, а также тех, кто заинтересовался, почему словосочетание “музыкальный сопроцессор” мы взяли в кавычки.

Скриншот стартового экрана Dizzy IV

Помню, первый компьютер — клон ZX Spectrum “Компаньон” — мы с братом никак не могли подключить к телевизору. Как я сейчас понимаю, в компьютере был только низкочастотный видеовыход, который мы пытались подключить к высокочастотному входу черно-белого телевизора. Удивительно, но каким-то образом видеосигнал пробивался через все эти гетеродины, так что можно было разглядеть смутные очертания символов, но только если ты знаешь, что там было написано… Поэтому какое-то время наши возможности ограничивались написанием почти вслепую простейших программ на бейсике и загрузкой с магнитофона игр, в которые было не поиграть.

Одной из игр, которая привлекала внимание, была “Legend of the Amazon” (или “Амазоники”, как мы их тогда называли). На старте была отличная музыка, воспроизводимая через 1-битный динамик. Ее можно было запустить “вслепую” и слушать до бесконечности. Мы замучили кассету так, что еле прочитали игру, когда наконец подключили “Компаньон” к низкочастотному входу телевизора и стало все видно. Увы, но других воспоминаний от игры у меня не осталось — gameplay был посредственный (ну или я ничего не понял).

Научившись паять, я собрал больше информации о ZX Spectrum и смог подключить к нашему многострадальному на тот момент “Компаньону” “магический” музыкальный сопроцессор. Тогда это был YAMAHA YM2149F, аналог AY-3-8912, устанавливавшегося в оригинальных ZX Spectrum 128. Следует отметить, что название “музыкальный сопроцессор” неверно, потому что чип не выполняет никакого кода, а является конечным автоматом. В документации на чип предлагается название “программируемый звуковой генератор”, поэтому в дальнейшем в статье я буду называть чип звукогенератором.

Эксперимент завершился и удачей, и разочарованием. С одной стороны, звукогенератор работал, с другой стороны, оказалось, что во многих играх память в 48К была занята под завязку и на музыку ее уже не оставалось. В те времена было принято выносить музыкальные модули в дополнительные страницы памяти, которые были в 128-килобайтном спектруме, но отсутствовали в нашем 48-килобайтном “Компаньоне”, поэтому звукогенератор в большинстве случаев оставался лишним балластом. Однако в журнале ZX Ревю, из которого я и взял схему подключения, была заметка о том, как его проверить: музыкальный модуль от игры Dizzy IV загружался в память отдельно от игры и его можно было запустить. На картинке выше — скриншот стартового экрана игры.

Для ностальгирующих — вот как загружался дополнительный модуль:

Периодически мне нравилось загружать этот модуль и слушать ту чудесную стартовую музыку (сейчас ее можно послушать тут; это не только стартотвая музыка, но и мелодия внутри игры).

О возможностях звукогенератора AY-3-8912

Звукогенератор AY-3-8912 фирмы General Instrument, который устанавливался в ZX Spectrum 128, а также его аналоги, — достаточно популярный способ добавить музыкальные возможности в компьютеры того времени. Это семейство чипов устанавливали, в том числе в компьютеры Amstrad CPC и в японские MSX.

AY-3-8912 имел 3 канала для генерации сигналов прямоугольной формы (тона); один генератор шума; генератор огибающей, позволяющий производить амплитудную модуляцию сигналов тона и шума; микшер сигналов для смешения сигналов тона, шума и огибающей; модуль контроля громкости и цифро-аналоговый преобразователь.

На выходе у генератора было 3 аналоговых канала, именуемых A, B и C. В оригинальных спектрумах сигналы объединялись в один и получался моно-сигнал, однако каналы можно было соединять попарно и получать стерео сигнал. Мне чаще попадалось объединение A + C -> левый канал, B + C -> правый канал, т.е. канал C отправлялся и в левый, и правый выходы, являясь средним каналом. До момента написания этой статьи такое соединение мне представлялось каноническим. Но оказалось, что часто средним делали канал B и иногда в софте можно было найти настройку, какой канал считать средним.

Справедливости ради стоит добавить, что было несколько модификаций чипа. Вот самые распространенные из них:

AY-3-8910 — выпускался в корпусе DIP 40 и дополнительно имел 2 восьмибитных порта ввода/вывода;

AY-3-8912 — выпускался в корпусе DIP 28 и дополнительно имел только один восьмибитный порт ввода/вывода;

YAMAHA YM2149F — полностью совместим с AY-3-8910, но имел некоторые дополнительные возможности.

Используя порты ввода-вывода AY-3-8910, к компьютеру можно было подключить еще и, например принтер с параллельным интерфейсом. Но насколько мне известно, для клонов спектрума так никто не делал.

Музыкальные редакторы для спектрума

Любой спектрум, даже не оборудованный звукогенератором, мог воспроизводить звуки при помощи 1-битного выходного канала. Сигнал выводился на встроенный миниатюрный громкоговоритель, как в оригинальном спектруме, а в клонах вместо него иногда применяли пьезо-пищалки или иные воспроизводящие звук устройства. Интересно, что в оригинальном спектруме за ввод/вывод с магнитофона и за воспроизведение звуков отвечал всего лишь один вывод микросхемы ULA. Встроенный бейсик поддерживал команду BEEP, которая принимала два параметра — смещение в полутонах относительно ноты “до” первой октавы и длительность звука в секундах (можно в долях). Вооружившись операторами DATA и FOR, можно было воспроизвести любую одноголосную мелодию.

Самым известным редактором для бипера стал “Wham! The Music Box” или просто “Wham!”. Думаю, что отсылка к музыкальному поп-дуэту “Wham” с участием Джорджа Майкла была не случайна — редактор поставлялся с несколькими демо-композициями, одной из которых была песня “Careless Whisper” того времени. Но какого-либо подтверждения этому факту я не нашел.

Версия Джорджа Майкла

Wham! позволял одновременно воспроизводить 2 голоса или звуковой эффект, что для бипера в то время было редкостью.

Тут стоит упомянуть хоть и не редактор, но игру Manic Miner, в которой в 1983 году (всего через год после появления ZX Spectrum) на стартовом экране была попытка воспроизводить 2 звука одновременно, а во время игры звучала музыка, что требовало немалого процессорного времени. Но после написания этой статьи мой мир никогда не будет прежним — проверяя свои воспоминания, я обнаружил, что автор игры Matthew Smith в одном из интервью говорит, что использовал для написания игры компьютер TRS-80, подключенный к спектруму через порт расширения. Какое жульничество! (шутка)

Истории создания игр Manic Miner и Jet Set Willy посвящены некоторые видео на Youtube, там не все так просто. Например, многие помнят, что в Manic Miner был cheat-код 6031769, дававший бесконечное количество жизней. Этот код был основан на номере автомобиля автора игры. Думаю, было мало людей, прошедших эту игру без кода.

Этот же код использовался и в Grand Theft Auto и тоже давал бесконечное количество жизней. Пруф

На изображении — обложка игры для пользователей США (источник), по иронии судьбы мало знакомых с ZX Spectrum в целом и с Manic Miner в частности.

До звукогенератора мы с братом тоже проводили эксперименты по созданию многоголосной музыки. Процессор Z80 был достаточно медленный, чтобы генерировать многоголосный сигнал на ходу, но если его сгенерировать заранее и поместить в оперативную память, то выводить данные в звуковой порт можно было с достаточной скоростью. Тогда я еще не знал что такое ШИМ…

Наш подход позволял воспроизводить большое количество звуков, каждый с различной громкостью. Проблема заключалась в том, что в момент генерации сигнала в оперативной памяти звук прерывался. В итоге звуки, издаваемые нашим бипером, напоминали игру на плохой балалайке, поэтому дальнейшее развитие эта идея не получила. Беглый поиск на Youtube показывает, что из спектрумовского бипера можно было выжать гораздо больше, и энтузиасты так развлекаются до сих пор.

Существовала версия Wham! и для 128-килобайтного спектрума с AY-3-8912, но идеи, сработавшие в предыдущей версии, стали серьезным ограничением в текущей — нельзя было воспроизвести ноту большой длительности. Да и нотная запись для 8-битной музыки не самая подходящая.

Огромным прорывом для любителей компьютерной музыки стал выпуск польского трекерного редактора Sound Tracker для ZX Spectrum (отметим, что это не первый трекерный редактор вообще, он первый только для спектрума).

Это был переход от традиционной нотной записи музыки к буквенной записи нот в 3 колонки, по количеству каналов в звукогенераторе.

Под спойлером вы найдете основные понятия, которые используются в редакторах с интерфейсом типа “трекер”. Специально не останавливаюсь на всех тонкостях восьмибитной музыки, перечисляю здесь лишь основные понятия, которые мы будем использовать во второй части статьи, когда перейдем к разбору кода музыкального модуля Dizzy IV.

Pattern (или паттерн) — “строительный” блок, музыкальная композиция делится на небольшие куски. Обычно состоит из нескольких музыкальных тактов и содержит 1-2 фразы.

Position (или позиция) — слоты, в которые можно вставить паттерны. Они определяют, в какой последовательности должны исполняться паттерны, какие паттерны должны повторяться. Написав несколько коротких паттернов и в дальнейшем комбинируя их в разном порядке с помощью позиций, можно создать достаточно длинную, пусть и несколько однообразную мелодию, впрочем, так и принято было делать.

Sample (инструмент) — описание изменения характеристик звуков с течением времени. С частотой 50 Гц плеер музыки рассчитывал относительную высоту звука, который проигрывался в канале, его громкость, накладывал звуковые эффекты. Инструменты позволяли наложить окраску звукам, можно было настроить плавное нарастание или затухание, фронт и т.д.

Ornament (орнамент) — аналогично сэмплу орнамент определяет относительную высоту звука, но в данном случае она определяется тем, насколько тонов необходимо сместить звук. Из-за того, что звукогененратор имеет всего лишь три канала, а хочется намного больше, появились орнаменты, которые позволяли поочередно с большой частотой проигрывать несколько звуков на одном канале. Орнаменты — эффективное средство воспроизвести на одном канале звуки одной октавы или даже аккорды, например трезвучия. Кончено, звуки воспроизводились поочередно с большой частотой и напоминали балалайку, но это тоже было за гранью возможности для трех каналов, т.е. супер круто.

Другим весьма известным музыкальным редактором был ASC Sound Master (ASM) А.Сендецкого. К сожалению, автора этого редактора уже нет с нами (пруф). Этот редактор мне запомнился, как очень крутой, ведь автор даже не поленился, а разработал свою собственную файловую систему, чтобы сохранять музыкальные композиции. Помню, там была композиция “Boom”, которая мне очень нравилась. Я слушал ее бесконечно, тогда не зная, что это была музыка из одноименного французского фильма.

Без музыки на тот момент обходилась редкая демка. Лучшие образцы (например, Insult или Satisfaction) можно нагуглить до сих пор. А одним из самых зрелых редакторов был Pro Tracker, который появился достаточно поздно — в 1995 году. С его помощью было написано довольно много музыки.

Наверняка у каждого, кто был знаком с играми на спектруме, есть свои любимые музыкальные воспоминания. На меня в свое время неизгладимое впечатление произвел загрузчик с дискет под названием ZYX. Эта программа запускалась самой первой, показывала каталог программ, которые были на диске, и позволяла загрузить одну из них. Существовало огромное множество этих загрузчиков с разной популярной музыкой того времени. Особенно мне нравился Jean Michel Jarre.

Jean Michael Jarre

Удивительно, но демки разрабатывают до сих пор. Для AY-3-8912 даже существует вполне современный музыкальный редактор “Vortex Tracker”, который позволяет писать 8-битную музыку под Windows.

На этом я закончу свой исторический экскурс. Во второй части статьи будем дизассемблировать музыкальный модуль Dizzy IV и писать прошивку для Arduino, которая повторит музыку из этой игры, эмулируя музыкальный процессор и используя музыкальный модуль Dizzy IV.

Источник

Adblock
detector