http://habrahabr.ru/post/248115/
Прошло около года, с момента успешного
подключения музыкального синтезатора YM2149F к LPT порту компьютера. LPT это конечно хорошо, однако время не стоит на месте, и найти компьютер или ноутбук с LPT портом становится все сложнее и сложнее. Да и сам автор (то есть я) устал лазить каждый раз под стол, где стоит системник, и перетыкать LPT плату на что-то другое, например программатор (у меня LPT-программатор Willem, ну да не суть). Поэтому на сей раз подключать чип YM2149F будем к USB. Ну и конечно, чтобы соотвествовать эпохе, будем это делать на копеечном древнем микроконтроллере
PIC16F628.
Вкратце, YM2149F (или ее функциональный аналог
AY-3-8910) — микросхема звукового трехголосного синтезатора, применялась в старых компьютерах типа Atari ST, Amstrad CPC, ZX Spectrum, MSX и некоторых других для проигрывания музыки. В России чип приобрел определенную известность благодаря установки в различные клоны ZX Spectrum'а. За время шествования ZX Spectrum по бывшему СССР музыкантами были написаны тысячи мелодий под этот звуковой программируемый генератор. Да и сейчас можно вполне найти людей, создающих музыку именно под этот чип. В конце статьи будут приведены ссылки на огромнейший архив чип-тюнов для YM/AY на сотни часов непрерывного прослушивания.
Демо
Как и в прошлый раз, перед началом, даю сразу ссылку на прослушивания конечного результата:
https://soundcloud.com/tronix286 Последние записи сделаны как раз с этого устройства. Записывал так-себе плеером, который пишет максимум в 128Kb/s MP3, поэтому в реальности устройство звучит «ярче». Но составить общее представление о звуке можно.
Железо
Почему такой странный выбор контроллера? Почему не AVR/ARM/iCore i7/FTDI на худой конец? Частично ответ на этот вопрос дан в начале топика: ретро синтезатору — ретро микроконтроллер! Тем более, что у AY-3-8910 и фирмы Microchip, можно сказать, общие корни. А вообще, так сложилась серия странных обстоятельств. Во-первых я наткнулся в интернете на библиотеку, реализующую программный (софтварный) стек USB 1.1 для микроконтроллеров PIC16F628 — вот эта библиотека:
16FUSB. Во-вторых, у меня давно лежала и пылилась парочка PIC16F628A, которые я не знал куда деть. В третьих, на компе уже стоял настроенный софт (MPLABX, MPASM) и имеется программатор для PIC. Ну и в отличии от программного стека
V-USB на AVR, известного многим, на PIC'ах без аппаратного USB проектов мало или даже вообще нет. А это значит, что нужно восстановить историческую несправедливость.
Вот типовая схема включения с сайта библиотеки 16fusb:
В комплекте с библиотекой 16fusb идет хороший пример под названием «direct-io». Смысл прост — посылаем через USB байт и он «отображается» на восьми ножках микроконтроллера. Так же можно посылать дополнительно два управляющих сигнала, то есть еще два бита (или две ножки). И в обратном направлении, то есть от контроллера к хосту (компьютеру).
Для управления YM2149F используется восьмибитная шина данных D0-D7 и три управляющих сигнала BC1, BDIR и RESET. BC1 и BDIR управляют выбором адреса регистра и его значением, а так же переводят микросхему в неактивное состояние. Сигнал RESET используется для сброса всех регистров на первоначальное значение. Таким образом, чтение из PIC в компьютер не нужно; нужна только возможность посылать команды на YM. И нужен еще третий управляющий сигнал, а значит еще одна ножка МК.
В своей прошивке для управления конкретно YM2149F было сделано следующее:
- выкинуто все, что связано с чтением сигналов из PIC в хост (компьютер) для увеличения быстродействия обработки реквестов USB;
- состояние направлений портов ввода-вывода жёстко задано при инициализации МК и не изменяется в процедурах выдачи байта на ноги.
- организован кольцевой буфер на 64 байта. При декодировании запроса от хоста байты складываются в буфер. Когда есть свободное время, данные из буфера выдаются на YM.
- оптимизирована скорость выдачи байта на ноги МК. Частично за счет жестко указанных направлений ввода-вывода, частично из-за известности предыдущего состояния управляющих бит.
- пофикшен глюк с зацикливанием PIC через несколько тысяч пакетов (развернут цикл RxLoop в файле isr.asm, вместо goto RxLoop вставлена проверка на признак конца пакета)
- что-то еще, не помню
Как уже сказано выше, возникает потребность в еще одном управляющем сигнале — RESET, а свободных ножек уже нет. Поэтому для тактирования PIC применен кварцевый генератор, а не кварц, тем самым высвобождая одну ногу МК (RA6), необходимую для управления сигналом RESET. Нога RA5, торчащая в воздухе, в данном семействе работает только на вход и не может быть использована для управления выходным сигналом. На нее можно было-бы переложить функционал по отлавливанию конца USB пакета (EOP) с ножки RB2, однако это не так просто — в отличии от ножки RB2 ножка RA5 делит функционал с MCLR и VPP для программирования и внутри организован вход как триггер шмитта. Ему просто не хватит напряжения после диодов для сработки. С другой стороны, для тактирования YM2149F собран генератор на микросхеме 74HC02 и кварце 3.579545 MHz. Можно было бы попробовать использовать вторую свободную половину микросхемы для сборки аналогичного генератора и для PIC, но остановило два момента: 1) у меня нету кварца на 24МГц (а кварцевый генератор был, с какой-то древней мамки) 2) я не знаю, как поведет себя 74HC02, если с «разных боков» у нее будут разные частоты, причем одна из них довольно высокая (24МГц все таки очень большая частота). Еще один из вариантов, как освободить ногу RA6 для кварца: Сигналы BC1 и BDIR принимают только такие значения:
BC1 BDIR
0 0
0 1
1 1
И никогда BC1 = 1, BDIR = 0. Это можно использовать как RESET, добавив NOT и NOR логику из половинки микросхемы 74HC02 и проинвертировав сигнал на выходе с помощью транзистора. Конечно для выдачи BC = 1 и BDIR = 0 нужно немного подправить прошивку.
И еще, нога RA4, которая управляет сигналом BDIR, с открытым коллектором, поэтому ее обязательно нужно подтянуть к питанию — на схеме это 10K резистор R5.
Софт
Со стороны компьютера, в качестве музыкального проигрывателя, выступает отличный кросс-платформенный плеер чип-тюнов
ZX Tune:
Напрямую он не поддерживает USB, зато если находит у себя в директории одну из библиотек dlportio.dll/inpout32.dll/inpoutx64.dll, то позволяет переключится в настройках вывода звука на YM-LPT (
для прошлого проекта), а затем использует функцию __stdcall void DlPortWritePortUchar(unsigned short port, unsigned char val); для выдачи байт YM2149. Порт 0x378 данные, Порт 0x37a передача управляющих сигналов (D1 — ~BDIR, D2 — BC1, D3 — ~RESET). Таким образом, можно написать маленькую библиотеку-заглушку с одной единственной функцией DlPortWritePortUchar, в которой перенаправлять выдачу байт на USB-устройство, что и было сделано. Я просто взял исходники библиотеки
inpout32 за основу и написал функцию-заглушку для перенаправления выдачи байт на это устройство. В итоге, достаточно положить эту библиотеку-заглушку
inpout32.dll или
inpoutx64.dll, в зависимости от используемой версии плеера (x86/x64), в одну директорию с плеером
ZX Tune, запустить его и в настройках звука переместить устройство
aylpt на самый верх (как на скриншоте выше).
Скачать бесплатно и без СМС
Драйвера для Win XP, Win 7 (x32/x64) можно скачать здесь:
16FUSB_driver-libusb-win32-1.2.6.0.zip
Схема устройства:
ym-usb_scheme_1.0.rar
Скомпилированная прошивка (.hex) и скомпилированные DLL-заглушки:
ym-usb_firmware_and_DLLs_v1.2.rar
Исходные коды прошивки:
ym-usb_PIC16F628A_source_v1.2.rar
Исходные коды библиотеки-заглушки:
inpout32-64_DLL_source_v1.2.rar
General Instruments AY-3-8910 / 8912 Programmable Sound Generator (PSG) data Manual:
http://bulba.untergrund.net/AY-3-8910.rar
Тема на форуме ZX.PK.ru, из которой «родилось» устройство:
http://zx-pk.ru/showthread.php?t=22202
Огромный архив трекерной музыки:
Modland (
ФТП)
ZX музыка онлайн:
http://zxtunes.com/
Всем добра!