...

суббота, 14 марта 2015 г.

Олдскул, хардкор, AY-3-8912. «Железный» чиптюн с последовательным входом


Клона Spectrum 128K, оснащенного музыкальным сопроцессором AY-3-8910 (YM2149F) у меня не было. Был 48K с расширенной клавиатурой и убогим блоком питания, перегревающим внутренности через час-два работы. От этого, помнится. домики посреди моря в Sim City образовывались и другие веселые артефакты. Но к делу данные воспоминания не относятся. Вдохновившись материалом tronix286, я решил восполнить пробел в ретро-образовании и склепать что-нибудь на легендарном (и при этом, легко добываемом и недорогом) чипе.


В ходе изучения различных поделок, идея сформировалась следующая: надо делать модуль с последовательным (UART) входом. Чтобы его уже можно было подключить с минимальными затратами к любому девайсу, добавляя тем самым +146 к чиптюновости. В процессе также было решено освоить пару дополнительных навыков, вроде программирования AVR и изготовления печатных плат с применением фоторезиста.


Сразу опишу результаты: модуль разработан и пиликает, побочные навыки прокачаны, грабли собраны, можно радоваться, расширять и углублять.




Синтезатор


AY-3-8910 — это большой красивый DIP-чип на 40 ножек. Помимо нужных вещей, там еще два 8-разрядных порта, которые для вывода звука нормальными людьми (не пытающимися на них сколхозить адский аналог Covox) не используются. AY-3-8912 не менее красив, но одним «лишним» портом обделен и упакован уже в DIP28. И еще бывает AY-3-8913, вообще без параллельного порта (DIP24). И это только General Instrument / Microchip. Yamaha клепала еще больше вариаций: от YM2149F (аналог AY-3-8910 с делителем тактовой частоты) до YMZ284 (DIP16, один смикшированный выход каналов). Подробнее о чипах на Wiki (англ.).


Управление


Для загрузки данных используется 8-разрядный параллельный порт. Плюс, три управляющих линии (одну, которая BC2, подтягиваем к плюсу питания). Логика следующая:


1. Исходное состояние — BC1=0, BDIR=0.

2. Устанавливаем на ножках порта AY адрес регистра.

3. BC1=1, BDIR=1. Загрузка адреса. Задержка между включением линий должна составлять не более 50 нс, поэтому всякие медленные подергивания ножек (типа ардуинского DigitalWrite) не годятся, надо, например, PORTC |= 0b00110000;

4. BC1=0, BDIR=0.

5. Устанавливаем на ножках порта AY значение регистра.

6. BC1=0, BDIR=1. Загрузка значения.


Повторяем последовательность 14 раз (для каждого нужного регистра). И все это — 50 раз в секунду. Получаем музыку.


Выбор конкретного железа


В моем случае следующий:

1. AY-3-8912 — был дешевле.

2. Atmega8A (DIP28) — доступно, достаточно выводов.

3. Кварцевый генератор на 4 МГц — для тактирования AY.

4. Счетчик К555ИЕ5 — как делитель частоты для тактирования AY.

5. Кварц на 16 МГц — для Atmega8A.

6. Для подключения к ПК — USB UART на FT232R.



Плата разведена именно под это дело. В процессе отладки и более вдумчивого изучения возникли следующие мысли:


1. Если использовать YM2149F, то не нужен счетчик, т.к. в этом чипе есть встроенный делитель частоты на 2.

2. Похоже, что кварц для Atmega тоже не нужен — все прилично работает и от внутреннего генератора на 8 МГц.

3. В теории, можно попробовать вообще избавиться от кварцевого генератора для AY, если поковыряться с аппаратными таймерами и счетчиками Atmega. Но! В этом случае мы сможем тактировать AY только на 2 МГц. А по-хорошему, надо иметь возможность тактирования на 1.7(много цифр) МГц — как это делается в Speccy. У меня кварцевый генератор на 4 МГц стоит в DIP-колодке, чтобы потом его заменить на 3.5(много цифр) МГц.


Выход звука срисован у tronix286, там горстка резисторов и два конденсатора.


Софт


Для вдохновления изучалась вот эта (недо)реализация. Там описан общий принцип работы связки «источник — UART — Atmega — AY», но использование на «меге» загрузчика Arduino в данном случае показалось мне совершенно лишним. Ну и, программа на ПК, написання на C#, мне не понравилась. Шарп здесь примерно так же «нужен», как и Arduino. Формат YM разложен по полочкам здесь.


Прошивка Atmega


Исходный код и hex доступны на гитхабе (ссылка в конце материала), пробегусь просто по основным функциям.


valToPort — запись 8-разрядного значения в «порт», состоящий из половинки порта B и половинки C. Так было удобнее разводить.

sendToAY — запись 8-разрядного значения в регистр AY. Здесь как раз реализована логика, описанная в пункте «Управление».

setup — инициализация портов и UART.

main — зацикленное «получить 16 байт — записать в AY».


Демонстрационный пример на PC



Написан на Python 3 с использованием PySerial. Как и прошивка, лежит на гитхабе. Берет файл 1.ym (несжатый!) из текущей директории, разбирает его и заталкивает в COM6. Ради интереса пример проверен на OS X, работает «из коробки», достаточно только поменять название порта. Подозреваю, что столь же успешно будет работать на Linux, в т.ч. на «малинке».


В выдаче дампа регистров на AY есть один нюанс. Формат YM хранит данные в виде «все значения регистра 0, все значения регистра 1...». Это очень правильно с точки зрения дальнейшего сжатия. Я же работаю с несжатым YM, и мне нужно выдавать пачки байт «регистр 0, регистр 1...». Для PC задача решена в лоб — читаем данные из файла в нужном порядке в большой массив, затем из него последовательно отдаем контроллеру. Когда нужно будет делать «головное устройство» на базе чипа с малым объемом памяти, придется изобретать какие-то буферы.


Итого


Стоит помнить о том, что перед запуском воспроизведения неплохо бы сбросить «мегу» и AY. Потому что если в буфере контроллера что-то есть, при передаче новых данных весь поток сместится, и звуки будут воистину душераздирающие. Пин сброса на модуле предусмотрен, но в демонстрационном примере не используется. Сброс осуществляется тычком провода в сидящий на «земле» корпус кварцевого генератора.


Имеется и недопойманный баг. Который, наверное, прячется где-то в районе «Windows 10 — Python 3 — UART». Периодически скорость обновления падает с 50 Гц до 20 (осциллоскопировано). Системы в явлении не обнаружено, на другом компьютере глюк не воспроизвелся. Если поймаю когда-нибудь, сделаю UPD.


В дальнейшем модуль будет прикручен к находящейся в процессе разработке поделке, об этом в относительно обозримом будущем будет статья. Ну, и к «малинке» надо попробовать подцепить. Простор для экспериментов имеется.


Исходники, разводка платы (SL6), схема модуля (Eagle) на гитхабе.


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий