Я люблю старые компьютерные игры. Люблю старое железо, но не настолько, чтобы коллекционировать его дома. Другое дело – поковырять какой-нибудь старый чип и попробовать самому что-нибудь воспроизвести, совместить старое с новым. В данной статье история о том, как я подключил AVR-микроконтроллер к YM3812, применявшуюся в таких звуковых картах как Adlib, Sound Blaster и Pro AudioSpectrum. Я не создал что-то принципиально новое, просто объединил разные идеи. Возможно кому-то будет интересна моя реализация. А может мой опыт подтолкнет кого-нибудь на создание свого ретро-проекта.  Гуляя по просторам интернета, как-то раз я наткнулся на интересный проект OPL2 Audio Board for Arduino & Raspberry Pi. Если кратко: подключаем к Arduino или Raspberry Pi плату, загружаем скетч или софт соответственно, слушаем. Заманчивая идея поковырять OPL2 чип, послушать как он звучит и попробовать сделать что-нибудь свое не покидала меня, и я заказал, собрал и начал разбираться как оно работает. Чтобы музыка заиграла, мы должны выставлять регистры. Какие-то отвечают за настройку инструментов, какие-то за воспроизведение нот и т.д. Адрес регистра – 8 бит. Значение регистра – 8 бит. Список регистров приведен в спецификации. Для передачи регистров мы должны правильно выставить показания на управляющих входах CS, RD,WR и A0 и шины данных D0..D7. Вход CS нужен для блокировки шины данных в процессе ее установки. Устанавливаем CS=1 (отключаем вход), выставляем D0..D7, устанавливаем CS=0 (включаем). На входе RD должна быть логическая единица
Для записи адреса регистра устанавливаем WR=0, A0=0
Для записи значения регистра устанавливаем WR=0, A0=1  Порядок передачи регистров: На инверторе 7404 и кварце XTAL1 реализован генератор прямоугольных импульсов с частотой 3.579545МГц, необходимый для работы YM3812.
YM3014B преобразует цифровой сигнал в аналоговый, который усиливается операционным усилителем LM358.
Аудио усилитель LM386 нужен, чтобы можно было подключать к устройству пассивные динамики или наушники, т.к. мощности LM358 недостаточно. Теперь попробуем извлечь из всего этого звук. Первое о чем я (и наверное не только я) подумал, это как бы заставить все это работать в DosBox. К сожалению «из коробки» поиграть с железным аналогом Adlib не получится, т.к. DosBox не знает о нашем устройстве ничего, и передавать OPL2 команды куда-либо не умеет (пока не умеет). Автор проекта предлагает скетч для Teensy, работающий как MIDI устройство. Естественно звук будет состоять из заранее составленных инструментов и звучание будет не то, мы получим эмуляцию MIDI устройства на OPL2 чипе. Teensy у меня нет, и попробовать этот вариант не получилось. Есть скетч SerialPassthrough. С ним мы сможем передавать команды через последовательный порт. Остается только реализовать поддержку в DoxBox. Я использовал версию из SVN: svn://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk В файле src/hardware/adlib.cpp меняем реализацию OPL2: Перед сборкой номер COM порта заменить на актуальный. Если убрать комментарий в строчке //adlib_write(reg,val);, то звук будет играть одновременно через эмулятор и девайс. В настройке DosBox надо будет указать использование OPL2: Вот как это получилось у меня: Выглядит довольно громоздко. Даже если использовать Arduino вместо макетки, нужно подключать провода. Номер порта в системе может измениться и придется пересобирать DosBox. Очень хотелось все привести к какому-нибудь лаконичному виду, убрать лишние детали и собрать все на одной плате. Появилась идея, а почему бы не сделать самостоятельное устройство с минимумом компонентов и заморочек при подключении. Во первых можно убрать 74595 и использовать порты атмеги. Тут она используется только для уменьшения количества проводов. Во вторых можно использовать готовый кварцевый генератор и избавиться от микросхемы 7404. Аудио усилитель тоже не нужен, если подключать устройство к колонкам. И наконец можно избавиться от USB-UART, если подключить атмегу к USB напрямую, например с использованием библиотеки V-USB: https://www.obdev.at/products/vusb/index.html. Чтобы не заморачиваться с написанием драйверов и их установкой, можно сделать микроконтроллер кастомным HID-устройством.  Порты B и С частично заняты подключением к программатору ISP и кварцу. Полностью свободным остался порт D, его используем для передачи данных. Оставшиеся порты я назначил в процессе проектирования печатной платы. Полную схему можно изучить тут: https://easyeda.com/marchukov.ivan/opl2usb Светодиод LED1 с его резистором опциональны и при сборке я не стал их устанавливать. Предохранитель U4 нужен, чтобы не сжечь случайно USB-порт. Его тоже можно не ставить, а заменить на перемычку. Чтобы устройство было компактным, я решил попробовать собрать его на SMD-компонентах. 
 "Безопасный" вариант в термоусадке 50/25мм

 Цифровая часть слева, аналоговая справа. Для меня это был первый опыт проектирования и сборки готового устройства и не обошлось без косяков. Например отверстия по углам платы по задумке должны быть диаметром 3мм для стоек, но получились 1,5мм. Прошивку можно посмотреть на github. В ранней версии одна команда отправлялась одним USB-пакетом. Потом выяснилось, что на динамичных треках DosBox начинает тормозить из-за большого оверхеда и низкой скорости USB 1.0, DosBox висит на отправке пакета и получении ответа. Пришлось сделать асинхронную очередь и отправлять команды пачкой. Это добавило небольшую задержку, но она не ощутима. Если с отправкой данных в YM3812 мы уже разобрались раньше, то с USB придется повозиться. Переименовываем usbconfig-prototype.h в usbconfig.h и дописываем его (ниже только правки): В файле main.c определяем структуры данных посылок Объявляем дескриптор для HID Обработчики событий: Рекомендую эти рускоязычные статьи про V-USB:
http://microsin.net/programming/avr-working-with-usb/avr-v-usb-tutorial.html
http://we.easyelectronics.ru/electro-and-pc/usb-dlya-avr-chast-2-hid-class-na-v-usb.html Код для DosBox можно посмотреть во все том же репозитории. Для работы с устройством на стороне PC я использовал библиотеку hidlibrary.h (ссылки на оригинал, к сожалению, не нашел), которую пришлось немного доработать. Эмулятор OPL я решил не трогать, а реализовать свой отдельный класс. Переключение на USB в конфигах теперь выглядит так: В констркуторе модуля Adlib в adlib.cpp добавляем условие: И в dosbox.cpp новый вариант настройки: Скомпилированный exe можно забрать тут: https://github.com/deadman2000/usb_opl2/releases/tag/0.1 Подключение: Звук записанный через звуковую карту: Результатом я остался доволен. Подключать устройство легко, проблем никаких. Само собой мои модификации DosBox'а никогда не попадут в официальную версию и популярные ветки, т.к. это очень специфическое решение. Далее на очереди ковыряние OPL3. Есть еще идея собрать трекер на OPL-чипах Проигрыватель VGM-файлов Звуковая карта OPL2 на шине ISA Программист