«Портативная» ретро-консоль своими руками
Пятничный привет, Хабр!
В данной статье речь пойдет о том, как познать дзен самостоятельной сборки гаджета, о том, что любой опыт это тоже знания, а так же немного ценных советов для тех, кто вдруг решит повторить нечто подобное.
В результате мы окунемся в период, когда слова Dendy и Sega вызывали трепет, и получим вот такую «карманную» консоль:
Под катом много картинок и краткое видео для тех кто любит смотреть, а не читать
Предисловие
К сборке данного проекта меня подтолкнула целая череда событий. Дело в том, что я очень много времени провожу в дороге по пути на работу. Как правило время приходится коротать за прослушиванием книг или казуальными игрушками в телефоне. Ну или как сейчас — делать черновики для статьи на хабр. И вот так, в дороге, когда все эти казуалки сильно приелись, я начал вспоминать, что раньше трава была зеленее, а игры осмысленнее. Вспомнил как в детстве, днями напролет, играл в dendy, и решил, что на китайских площадках наверняка есть карманные приставки, которые скрасят долгую дорогу.
Ну и заказал себе одну такую приставку. Продавец обещал аж 168 игр из детства. Дни шли… Доставка заказа затягивалась.
Время шло, я в предвкушении решил еще раз пробежаться по списку игр, которые должны были быть на приставке. Пока читал список — освежил в памяти игры в которые проводил целые дни, и с досадой обнаружил, что многих из них нет в обещаемом наборе. Кроме того, плитой воспоминаний легла приставка Sega mega drive, с её Comix zone, Rock’n’Roll Racing и Earthworm Jim… Время шло, а моя «нинтендовая» приставка нет. Написав продавцу, я получил ответ, что он просто забыл ее отправить, а трек который он дал — недействительный. Деньги я за нее вернул, но детство мне не вернули.
Плюнув в сердцах на совесть этого нехорошего человека, я задумался, что поиграть в денди можно и на эмуляторе в телефоне. Но как оказалось — ощущения совсем не те. Нет тактильных кнопок, а вместе с тем и комфорта игры. Тем более, что старые игры гораздо сложнее современных и промазать по кнопке прыжка зачастую может означать старт уровня с начала.
И решил — почему бы не собрать свою приставку, с Cannon fodder и кнопками. И я собрал. Допустил кучу ошибок, где-то по неопытности, где по криворукости. И поделиться с вами хочу именно опытом с ошибками, потому что умный человек учится на чужих ошибках, а на Хабре собираются только умные люди 🙂
Видео, с процессами сборки:
Выбор платформы
У меня завалялась raspberry pi 2, и недорогой 3,5 дюймовый дисплей к ней. С поиска решений для нее я и решил начать. И как оказалось — не зря. Для Raspberry уже имеется операционная система RetroPie, которая и превращает ее в полноценный эмулятор самых разных консолей. (подробнее по ссылке).
Кроме того, в интернете полно инструкций как подключить к ней джойстики и сунуть в корпус от старой приставки.
Но это не наш путь, мы же собираем «карманную» консоль. Значит джойстик нужен встроенный.
Ошибка 1: Лучше использовать raspberry pi 3 или 4 модели из-за наличия wi-fi и bluetooth. Это сильно упростит настройку уже собранной консоли в дальнейшем. Так же можно использовать Orange pi, решение получится ничуть не хуже.
Проектируем джойстик
За основу джойстика я решил взять 6 кнопочный контроллер от sega-mega-drive. В первую очередь из-за того что, 6 кнопок позволять играть в сегавские игры и не будут мешать дендевским.
Дальше, у Adafruit нашлась библиотека, которая может эмулировать клавиатуру, считывая сигналы с ножек gpio самой raspberry. И пользоваться ей очень просто. Её нужно скопировать в уже установленную RetroPie и подключить кнопки к пинам. Кнопки, при нажатии должны замыкаться на землю (любой GND пин).
Для начала были собраны все кнопки на макетной плате и проверены на работоспособность.
Схему подключения использовал следующую:
Т.к. проект собирался под Sega’вский джойстик — то и обозначения соответствующие. Вообще в RetroPie принято использовать «TL» и «TR» вместо «C» и «Z», видимо используемые в джойстиках от PlayStation. На самом же деле кнопки всегда можно переназначить, в том числе, для каждой конкретной игры.
Кнопки собраны, теперь нужно подумать над корпусом для карманной приставки. И вот тут я получил как положительный, так и отрицательный опыт:
Собираем корпус
В одном из своих постов я уже упоминал, что создание корпуса это прям головная боль для некоммерческой сборки гаджетов, если у вас нет 3д принтера. Можно поискать либо готовые боксы и плясать от их размеров, либо что-то собирать самому. Я решил опробовать новый для себя способ — склеивание акрила. Тем более, что хабравчанин millercutter предлагал свою помощь в нарезке акрила к одному из прошлых постов. За что ему отдельная и большая благодарность!
Прикинув размеры начинки — был сделан чертеж и отдан на резку. Изначально идея была в следующем: скруглить наждачкой «острые» края в собранном корпусе и покрыть его жидкой резиной из баллончика. В воображении вырисовывалось soft-touch покрытие и дизайн Porsche.
Склеивать акрил рекомендуют дихлорэтанолом. Его я в строительном магазине не нашел, поэтому взял первый попавшийся клей для пластика Bison. Прошу не считать это рекламой, но склеился корпус очень хорошо. Взгляните какой красивый прозрачный корпус получился:
Акрил легко и надежно клеится, хорошо выглядит и вообще приятный материал.
Корпус собран, кнопки впаяны в макетные платы, готовимся красить…
После высыхания клея я прошёлся наждачной бумагой по углам, а так же по всему корпусу, чтобы «краска лучше легла». Так как дома красить негде — я вышел на покраску на улицу. И вот тут я получил свою вторую ошибку:
Красить нужно в сухом и теплом помещении, а не в мокром и холодном Петербурге.
В общем, либо я нарушил технологический процесс, либо звёзды не сошлись, но резина легла отвратительно. С пузырьками и подтеками.
Пришлось отрывать это покрытие и снова шкурить корпус. Покраску корпуса было решено отложить на некоторое время. Поэтому сейчас сквозь корпус просматриваются подтеки термоклея, что выглядит не очень. И если вы знаете чем и как аккуратно покрасить акрил — обязательно последую вашим советам, потому что в текущем виде сборку оставлять нельзя:
Сборка консоли
Крепить электронные элементы к корпусу было решено болтами. Это должно придать корпусу своеобразный шарм, а если честно — иных способов я не придумал.
Все места соединений и пайки я промазывал термоклеем. Да, это некрасиво, но зато верный способ закрепить навесной монтаж.
Ошибка 3: навесной монтаж это в любом случае ненадежно и некрасиво, поэтому если у вас есть возможность заказать или заЛУТить печатную плату — у вас получится надежнее и компактнее
Собираем звук
Сборка звука это одна большая ошибка номер 4:
Я решил, что для воспроизведения звука идеально подойдет динамик от телефона. Тот, что воспроизводит мелодию звонка. Но по ошибке приобрел голосовой динамик (тот что к уху прикладывается) Ну и после подключения его к микросхеме усилителя — динамик просто не справился с громкостью. Пришлось усилитель изъять.
Честно говоря, до сих пор не знаю что сделать со звуком. использовал микросхему усилителя MC34119L. Может быть в подключении была проблема. Если кто-то знает какой динамик будет подходящим и какой простейший усилитель для него подойдет — пожалуйста подскажите. Желательно без дополнительных обвесов типа конденсаторов.
Собираем питание
Тут все довольно просто. Нужно собрать powerbank. У меня имеется запас аккумуляторов 18650 и разные готовые платы для их зарядки.
Ошибка 5: Сначала я использовал безымянную с Китая на 3 Ампера с круглым гнездом питания. У нее не оказалось стабилизатора на 5В поэтому дополнительно пришлось припаять DC-DC преобразователь. Чуть позже переделал на уже готовый модуль сразу со стабилизатором и индикатором заряженности батарей, но из-за уже готового отверстия в корпусе — круглое гнездо осталось. Сейчас же понимаю, что следовало делать для microUSB. Пары аккумуляторов на 2300mAh хватает на несколько дней безудержной игры. Так же, сразу не пришла в голову возможность поставить кнопку с фиксацией для включения устройства. Можно оправдывать большой тумблер, единственный оказавшийся под рукой, но… Нет ему оправдания, кнопка была бы лучше. Кроме того, аккумуляторы 18650 довольно громоздкие, можно подумать над использованием плоских литиевых аккумуляторов.
Окончательно собранное устройство
Заключение
В целом консоль получилась приятная. Окунуться в старые игрушки это прям как пережить второе рождение. Консоль в карман все-таки не помещается (разве что в пуховик), но в рюкзаке легко переносить.
На просторах интернета можно найти целые коллекции игр на 30 Гигабайт. На данном сайте можно легально скачать бесплатные игры для данной консоли.
Для тех же, кто решит повторить данный проект — смею дать несколько советов:
Android приставка своими руками! часть №1
Часть №1 (эта часть)- всего будет 6 частей.
Часть №2 — читать
Привет. Меня зовут Олег, я работаю в сервисном центре 54DA.ru, у нас имеется куча ( ну не куча конечно, но штук 10-15 точно есть) планшетов, у которых имеются разные поломки. Есть как полный хлам, так и очень интересные и редкие экземпляры. Из планшета будет делать эксклюзивный, быстрый, красивый мультимедиа центр — для видео, игр, сериалов и фильмов.
Из этого хлама был выбран редкий и не дешевый планшет Chuwi Hi10: Процессор Intel с четырьмя ядрами тактовой частотой 1.44-1.84 ГГц и графический адаптер с поддержкой DirectX 11.2, контроллер памяти DDR3L-RS-1600, оперативки 4 гига. На борту имеем Windows и Android. И самое главное HDMI выход для подключения к телевизору.
ВОТ ТАК ОН ВЫГЛЯДИТ НА ДАННЫЙ МОМЕНТ.
Но есть несколько проблем:
1) Не включается, не заряжается — главная поломка, которую требуется решить, произвести ремонт.
2) сломано сенсорное стекло — для приставки данная поломка не интересна, тачскрин ТВ приставки не нужен.
2) Не показывает картинку дисплей — тоже не интересная поломка для наших задач.
3) Сломан корпус, можно сказать он отсутствует.
Немного истории из жизни данного планшета (для установки диагноза, это крайне важно, опытные сервисные инженеры смогут сразу поставить диагноз, основываясь на выше сказанном и на след. двух предложениях): Данное тело принесли со словами: «Отключился сам по себе, просто лежал и отключился, более не включается и не заряжается». Человек на приемке сразу начал задавать вопросы: Сколько лежал включенным, был запущен Windows или Android? Клиент: «Был включен Windows, лежал больше двух суток».
Опытный инженер уже может сказать, что за поломка. Для людей далеких от ремонта мобильной техники: на планшете был запущен Windows и планшет ушел в спящий режим, в спящем режиме сел аккумулятор, из-за особенности BIOS (самой программы) планшет не может выйти из спящего режима при таком стечении обстоятельств. В большинстве случаев в такой ситуации умирает сам микро чип BIOS.
Задача: определить исправен ли чип BIOS, если не исправен замена на новый, прошивка (запись) новой программы в чип, установка в планшет и проверка работы. (это в идеальной ситуации, но не бывает все идеально!). Делов то на 10 минут — а растянулось на 3 недели!
Чтоб прошить (записать программу в чип) требуется программатор:
2 дня назад
Прошло 3 недели. Приехал переходник и 5 чипов Bios, работы продолжаются. Буду описывать процесс прошивки очень подробно, в интернете «хороших» инструкций нет, может кому — то будет полезно. Кому не интересно как прошивать переходите к концу статьи (там первое включение и первые впечатления от планшета).
Прошивка, проверка чипа BIOS на корректную работу:
Внимание: ниже описана процедура прошивки микро чипа, данная схема применима к большинству микро чипов Bios, все, что вы делаете, Вы делаете на свой страх и риск. Ниже описанное не призыв к действию, а схема, алгоритм — как прошить микро чип.
1) Скачиваем программу для прошивки. Для данного программатора есть 3 самых популярных программы, из трех две штуки крайне нестабильны, а вот одна — работает вполне терпимо. Название — AsProgrammer_1.4.0. Простите ссылки дать не могу, реклама и бла, бла, бла и подобное (вообщем могу «ОГРЕСТИ» за ссылки).
2) Скачиваем саму программу Bios — обычно это файл с расширением BIN. В нашем случаи микросхема имеет память в 8 мегабайт (кстати, эту микруху можно использовать как обычную флешку, переносить маленькие файлы)
3) Выпаиваем чип из системной платы планшета, сделать это не сложно, но есть несколько нюансов: А) Если выпаивать паяльником, чего лучше не делать, будьте крайне осторожны — микруха окружена мелочью, обвязкой самой Bios (маленькие электронные компоненты), B) Если выпаивать термофеном, то можно повредить дисплей, дисплей может получить термоудар, у нас дисплея нет поэтому бояться нечего.
4) Впаиваем чип Bios на подложку программатора — в нашем случаи это новая микросхема, опыт и «ЧУЙКА» показывает, что старый чип неисправен. Мы же заказали 5 штук новых, дабы не тратить время на проверку старого, сразу новый пойдет на прожарку (прошивку).
4.1) Как собрать конструктор из программатора, подложки, чипа и переходника с 3 вольт на 1.8 вольта — смотри фото ниже.
2 дня назад
Чип еще «горячий» только из печки, выпаиваем из программатора и впаиваем в наш планшет. Пока производили прошивку аккумулятор от планшета стоял на зарядке. Включаем и видим:
1) Зачищаем окружность вокруг «ног» разъема
2) Пропаиваем ноги разъема к зачищенной поверхности
Первое впечатление: планшет быстрый, тормозов, глюков, зависаний не было.
Ну, что! Часть №1 оживление «ДОХЛЯКА» прошла успешно. В следующей части №2:
1) Увеличение памяти Android — именно на ANDROID будем строить мультимедийный центр
2) Настройка Android и танцы с бубном — ожидается огромное количество «осадков в виде мелких проблем»!
3) Замер и тест нагрева «КАМНЯ» (процессора), если нужно делаем систему охлаждения.
Читать статью №2— подписывайся и увидишь продолжение, будет интересно!
Это материал на дзене
Ретро игровая приставка своими руками
Этот пост является введением в мой проект «самодельной» консольной видеоприставки сделаной с нуля. Я вдохновлялся как ретро консолями так и современными образцами, но у меня получилась своя собственная архитектура. Мои друзья постоянно мне говорили, что я должен рассказать о своём проекте, а не делать всё исключительно «для себя», так что вот я публикую этот пост.
Внимание, это — перевод
Как всё началось
Меня зовут Серхио Виейра (Sérgio Vieira) я выроc в Португалии в 80-е и 90-е годы, у меня давно ностальгия по ретро-геймингу, особенно по приставкам третьего и четвертого поколения.
Несколько лет назад я решил получше разобраться в электронике и попытаться сделать свою собственную приставку.
По профессии я программист и не имел никакого опыта как электронщик, если не считать (и не стоит этого считать) самостоятельных апгрейдов своего десткопа.
Хотя у меня и не было опыта, я сказал себе «почему бы и нет?», купил несколько книжек, несколько наборов электронщика и начал изучать исходя из своих ощущений о том, что именно стоит изучать.
Я хотел сделать приставку похожую на те которые вызывают у меня ностальгические чувства, я хотел что-то между NES и Super Nintendo, или может между Sega Master System и Mega Drive.
У этих приставок были CPU, оригинальный видео чип (тогда их ещё не называли GPU) и аудио чип, иногда встроеный, а иногда внешний.
Игры распространялись на картриджах, которые в общем были расширениями железа иногда просто ROM чипами, а иногда имели дополнительные компоненты.
Изначальный план был сделать приставку со следущими характеристиками:
Почему именно SD карты, а не картриджи, ну в основном просто так намного практичнее, их можно копировать с компа. А картриджи это значило бы, во-первых больше железа в приставке, а во-вторых производить железо для каждой программы.
Производство
Видео сигнал
Первое чем я занялся это генерация видео сигнала.
Любая консоль того периода, который я взял за образец, имела различные проприетарные графические чипы, что означает, что у всех у них были различные технические характеристики.
По этой причине я не хотел использовать готовый графический чип, я хотел чтобы и моя консоль имела уникальные технические характеристики по графике. И поскольку я не мог сделать свой собственный графический чип, и в то время ещё не умел использовать FPGA, я решил ограничиться софтварным генерированием графического сигнала используя 8-битный, 20 мегагерцовый микроконтроллер.
Это не перебор, и как раз достаточно мощное решение для графики того уровня который мне был интересен.
И так, я начал использовать микроконтроллер Atmega644 на чистоте 20 Мгц для генерации видеосигнала в формате PAL для телевизора. Мне пришлось бит-бангить протокол PAL, поскольку сам чип не умеет его.
Микроконтроллер выдаёт 8-битный цвет (RGB332, 3 бита красный, 3 бита зелёный и 2 синий) и пассивный ЦАП преобразует это всё в RGB. К счастью в Португалии почти все телевизоры оборудованы разъёмом SCART и они поддерживают RGB вход.
Правильная графическая подсистема
Поскольку микроконтроллер довольно мощный, а использовать его я решил исключительно для генерации видео сигнала (я назвал это VPU — Video Processing Unit), то я решил заодно организовать дабл-буфер.
У меня получилось что второй микроконтроллер (PPU, Picture Processing Unit, чип Atmega1284 тоже на 20 МГц) генерировал картинку в микросхему ОЗУ номер 1 (я назвал её VRAM1), а первый в это же время отправлял содержимое второй микросхемы (VRAM2) в телевизор.
После одного кадра, а два кадра в системе PAL это 1/25 секунды, VPU переключает VRAM-ы и они меняются местами, PPU генерирует картинку в VRAM2, а VPU дампит VRAM1 на ТВ вывод.
Видео плата получилась очень сложной поскольку мне пришлось использовать внешнее железо чтобы оба микроконтроллера могли пользоваться обоими модулями памяти и чтобы ускорить доступ к ОЗУ, ведь там тоже бит-бангинг, так что пришлось добавить чипы 74 серии как счётчики, line-селекторы, трансиверы и тд.
Прошивки для VPU и PPU тоже получились громоздкие поскольку пришлось писать много кода чтобы выжать максимум скорости из графики. Сначала всё было написано на ассемблере, потом часть была переписана на Си.
В результате PPU генерирует картинку 224×192 пикселей, которая потом отпраляется на ТВ через VPU. Может разрешение вам покажется низким, но вообще-то это почти столько, сколько консоли того времени имели на самом деле, обычно 256×224. Несколько меньшее разрешение зато позволило мне добавить больше фич которые система успевает просчитать за один кадр.
Как и в старину, PPU имеет свою жёсткую механику которой надо уметь пользоваться. Подложка (бэк) рендерится из символов 8×8 пикселей, так же называемых тайлами. Получается что размер бэкграунда 28х24 тайла.
Чтобы бэк мог скроллиться плавно, попиксельно, я сделал так что всего есть 4 виртуальных экрана, каждый по 28х24 тайла которые идут в памяти последовательно и обёрнуты вокруг друг друга, на картинке это понятнее.
Поверх бэкграунда, PPU может отрендерить 64 спрайта которые могут быть 8 или 16 пикселей по высоте или ширине, то есть 1, 2 или 4 тайла и ещё могут быть флипнуты горизонтально и/или вертикально.
Сверху бэка можно ещё рендерить оверлеем один буфер размером 28х6 тайлов, это было задумано для отрисовки HUD-ов, скоров так чтобы не мешать основным спрайтам и скроллингу бэка.
Одна «продвинутая» фича в том, что бэк можно скролить не целиком, а каждую линию в отдельности, что позволяет всякие интересные эффекты вроде сплит скрина или почти-параллакса.
Ещё есть таблица аттрибутов, которая позволяет задавать каждому тайлу значение от 0 до 3, и потом можно всем тайлам с одним аттрибутом задать страницу тайлов или инкрементировать их символьное значение. Это удобно когда есть части бэка которые надо регулярно изменять и CPU не придётся обсчитывать каждый тайл в отдельности, ему достаточно только сказать что-то вроде: «все тайлы с аттрибутом 1 инкрементируйте числовое значение своего символа на 2», подобные вещи реализованые разными техниками можно наблюдать, например, в блочных тайлах в Mario где знак вопроса анимируется или в играх где есть водопад в котором все тайлы постоянно меняются создавая эффект падающей воды.
Когда моя видеоплата заработала, я начал работать с CPU в качестве которого для моей приставки был выбран Zilog 80.
Одна из причин по который был выбран именно Z80, ну кроме того, что это классный ретро CPU, это его способность адресовать два 16 битных пространства, одно для памяти и второе для портов ввода-вывода, не менее легендарный 6502, например, так не может, он может только одно адресовать 16 битное пространство и в него приходится мапить как память так и различные внешние устройства, видео, аудио, джойстики, апаратный генератор случайных чисел и тд. Удобнее иметь два адресных пространства, одно полность отданное на 64 килобайта кода и данных в памяти и второе для доступа к внешним устройствам.
Сначала я подсоединил CPU к EEPROM в котором разместилась моя тестовая программка и ещё присоединил его через пространство ввода-вывода к микроконтроллеру который я установил чтобы можно было общаться с моим компом через RS232, и мониторить как работает CPU и всё остальное. Этот микроконтроллер Atmega324 работающий на 20 МГц я называю IO MCU — input/output microcontroller unit, он отвечает за контроль доступа к игровым контроллерам (джойстикам), SD карт ридеру, клавиатуре PS/2 и коммуникатору по RS232.
CPU подключается к микросхеме памяти на 128 килобайт, из которых только 56 килобайт доступны, это конечно бред, но я мог достать только микросхемы по 128 или 32 килобайта. Получилось, что память состоит из 8 килобайт ПЗУ и 56 килобайт ОЗУ.
После этого я обновил прошивку IO MCU с помощью этой библиотеки и у меня появилась поддержка SD карт ридера.
Теперь CPU мог ходить по директориям, смотреть что в них лежит, открывать и читать файлы. Всё это делается посредством записи и чтения в определённые адреса пространства ввода-вывода.
Подключение CPU к PPU
Следущее, что я сделал это связь между CPU и PPU. Для этого я применил «простое решение» которое заключалось в приобретении двухпортового ОЗУ, это такая микросхема ОЗУ которую можно подключать сразу к двум разным шинам. Это позволяет избавиться он дополнительных микросхем вроде лайн-селекторов и, к тому-же, позволяет практически одновременный доступ к памяти с обоих чипов. Ещё PPU напрямую может обращаться к CPU на каждом кадре активируя свои немаскируемые прерывания. Получается, что CPU получает прерывание на каждом кадре, что полезно для разных задач по таймингу и для понимания когда пора заняться апдейтом графики.
Каждый кадр взаимодествия CPU, PPU и VPU происходит согласно следующей схеме:
Примерно тогда же я занялся поддержкой игровых контроллеров, сначала я хотел использовать контроллеры от Nintendo, но сокеты для них проприетарные и вообще их трудно найти, поэтому я остановился на 6-кнопочных контроллерах совместимых с Mega Drive/Genesis, у них стандартные сокеты DB-9 которые везде есть.
Написание первой настоящей игры
В это время у меня уже был CPU способный контролировать PPU, работать с джойстиками, читать SD карточки… пора было писать первую игру, конечно на ассемблере Z80, у меня на это ушло несколько дней из свободного времени.
Добавляем динамическую графику
Всё было супер, у меня была своя игровая приставка, но мне этого было мало, потому-что приходилось в игре использовать графику прошитую в памяти PPU и нельзя было нарисовать тайлы для конкретной игры и изменить её можно было только перепрошив ПЗУ. Я стал думать как добавить ещё памяти, чтобы CPU в неё мог бы загружать символы для тайлов, а PPU потом мог оттуда это всё считывать и как это сделать попроще поскольку приставка и так уже получалась сложной и большой.
И я придумал следущее: только PPU будет иметь доступ к этой новой памяти, а CPU будет загружать туда данные через PPU и пока этот процесс загрузки происходит, эта память не может быть использована для отрисовки, но можно будет в это время рисовать из ПЗУ.
После конца загрузки CPU переключит внутреннюю ПЗУ память на эту новую память, которую я назвал Character RAM (CHR-RAM) и в этом режиме PPU начнет рисовать динамическую графику, это наверное не лучшее решение, но оно работает. В результате новая память была установлена 128 килобайт и может хранить 1024 символа 8х8 пикселей каждый для бэкаграунда и ещё столько-же символов для спрайтов.
И наконец звук
До звука руки дошли в последнюю очередь. Сперва я хотел звук наподобие того что есть в Uzebox, то есть чтобы микроконтроллер генерировал 4 канала ШИМ-звука.
Однако, оказалось, что я могу легко достать винтажные чипы и я заказал несколько микросхем FM синтеза YM3438, эти ребята полностью совместимы с YM2612 которые использовались в Mega Drive/Genesis. Установив их можно получить музыку качества Mega Drive и звуковые эффекты производимые микроконтроллером.
Я установил ещё один микроконтроллер и назвал его SPU (Sound Processor Unit), он управляет YM3438 и сам может генерировать звуки. CPU управляет им через двух-портовую память, в этот раз она всего 2 килобайта.
Как и в графическом блоке, звуковой блок имеет 128 килобайта памяти для хранения PCM сэмплов и звуковых патчей, CPU загружает данные в эту память обращаясь к SPU. Получилось, что CPU либо говорит SPU исполнять комманды из этой памяти или обновляет комманды для SPU каждый кадр.
CPU управляет четырьмя ШИМ каналами через четыре циркулярных буфера находящихся в памяти SPU. SPU проходит через эти буферы и исполняет комманды записаные в них. Ещё есть один такой-же буфер для микросхемы FM синтеза.
Итого, как и в графике взаимодействие между CPU и SPU идёт согласно схеме:
Что вышло в итоге
После того как все блоки были готовы, некоторые пошли на макетные платы.
Для блока CPU я смог разработать и заказать кастомную PCB, не знаю стоит ли сделать это и для остальных модулей, думаю мне на самом деле повезло, что моя PCB сразу заработала.
На макетной плате сейчас (пока) остался только звук.
Вот как всё выглядит на сегодняшний день:
Архитектура
Диаграмма иллюстрирует компоненты в каждом блоке и как они взаимодействуют друг с другом. Единственное, что не показано это сигнал от PPU к CPU на каждом кадре в виде прерывания и такой-же сигнал который идёт в SPU.
Окончательные спецификации
Видео:
Звук:
Разработка для приставки
Для приставки был написан загрузчик. Загрузчик помещается в CPU ПЗУ и может занимать до 8 килобайт. Он использует первые 256 байт ОЗУ. Загрузчик это первое, что исполняет CPU. Он нужен чтобы показать программы находящиеся на SD карте.
Эти программы находятся в файлах которые содержат скомпилированый код и могут также содержать графику и звук.
После выбора программы она загружается в память CPU, память CHR и память SPU. После чего программный код исполняется. Максимальный размер кода загружаемого в приставку 56 килобайт, кроме первых 256 байт и конечно надо учесть место для стека и данных.
И этот загрузчик и другие программы написаные для этой приставки создавались одинаковым нижеописаным способом.
Memory/IO Mapping
Что важно при разработке под эту приставку, так это учитывать как CPU обращается к различным блокам, и правильно распределять адресное пространство ввода вывода и адресное пространство памяти.
CPU обращается к оперативной и постоянной памяти загрузчика через адресное пространство памяти.
Адресное пространство памяти
А к PPU-RAM, SPU-RAM и IO MCU через адресное пространство ввода-вывода.
Адресное пространство ввода-вывода
Как видно из таблицы, внутри адресного пространства ввода-вывода выделены адреса для всех устройств, IO MCU, PPU и SPU.
Управление PPU
Из информации в таблице видно, что для управления PPU надо писать в память PPU которая доступна по адресам 1000h-1FFFh в адресном пространстве ввода-вывода.
Распределение адресного пространства PPU
PPU Status может принимать следущие значения:
Вот, например, как можно работать со спрайтами:
Приставка может рисовать 64 спрайта одновременно. Данные по ним доступны через CPU через адресное пространство ввода-вывода по адресам 1004h-1143h (320 байт), на каждый спрайт приходится 5 байт информации (5 * 64 = 320):
Итого, чтобы увидеть спрайт, надо установить флаг Active в 1, и задать координаты X и Y в пределах видимости, координаты 32/32 помещают спрайт в верхний левый угол экрана, меньшие значения спрячут его либо сделают частично видимым.
Потом мы можем установить код символа и цвет прозрачности.
Например, если нам нужно показать спрайт номер 10, то адрес будет 4145 (1004h + (5 x 9)), пишем значение 1 для активирования и координаты, например, x=100 и y=120, пишем по адресу 4148 значение 100 и по адресу 4149 значение 120.
Используем ассемблер
Один из способов программирования для приставки это ассемблер.
Вот пример как показать один спрайт и анимировать его чтобы он двигался и отталкивался от краёв экрана.
Использование языка Си
Можно также использовать язык Си, для этого нам понадобится компилятор SDCC и некоторые дополнительные утилиты.
Код на Си может получится медленнее, но зато написать его быстрее и проще.
Вот пример кода, который делает то же самое, что и код на ассемблере выше, тут используется библиотека которая помогает делать вызовы к PPU:
Динамическая графика
(В оригинале Custom graphics. прим. пер.)
В ПЗУ приставки зашиты 1 страница тайлов для бэка и ещё страница готовых спрайтов), по умолчанию можно использовать только эту фиксированую графику, однако можно переключиться на динамическую.
Цель у меня была такая, чтобы вся необходимая графика в бинарной форме сразу грузилась в оперативную память CHR, причём делать это умеет код в загрузчике из ПЗУ. Для этого я сделал несколько картинок правильного размера с разными полезными символами:
Поскольку память динамической графики состоит из 4-х страниц по 256 символов 8х8 пикселей каждый и 4-х страниц таких же символов для спрайтов, я перевёл картинки в PNG формат, удалил повторяющиеся одинаковые:
И потом использовал самописную тулзу чтобы перевести это всё в бинарный формат RGB332 с блоками 8х8.
В результате имеем файлы с символами, где все символы идут последовательно один за другим и каждый занимает по 64 байта.
Волновые RAW сэмплы переведены в 8-битный 8-килогерцовые PCM сэмплы.
Патчи для звуковых эффектов на ШИМ и музыки пишутся особыми инструкциями.
Что касается микросхемы FM синтеза Yamaha YM3438, то я нашел программку называемую DefleMask которая выдаёт музыку синхронизируемую по PAL и предназначеную для YM2612 микросхемы из Genesis, которая совместима с YM3438.
DefleMask экспортирует музыку в формате VGM и я её конвертирую ещё одной самописной утилитой в свой собственный двоичный формат.
Все бинарники всех трёх типов звука комбинируются в один двоичный файл, который мой загрузчик умеет читать и загружать в звуковую память SDN RAM.
Линковка окончательного файла
Двоичный исполняемый код, графика и звук соединяются в один PRG файл. PRG файл имеет заголовок в котором всё описано, есть ли звуковые и графические данные, сколько они занимают и сами эти данные.
Такой файл можно записать на SD карту и загрузчик приставки считает его и загрузит всё в соотвествующие места и запустит исполняемый код программы.
Эмулятор
Я написал эмулятор своей приставки на С++ с применением wxWidgets, чтобы проще было девелопить для неё.
CPU эмулируется библиотекой libz80.
В эмулятор добавлены фичи для отладки, я могу его остановить в любой момент и заняться пошаговой отладкой ассемблера, есть маппинг к исходному коду на Си если для игры был использован этот язык.
По графике, я могу заглянуть в видео память, в таблицы символов и в саму CHR память.
Вот пример программы запущеной на эмуляторе со включёнными средствами отладки.
Демка программирования
Эти видео снимались камерой смартфона направленой на экран ЭЛТ телевизора, прошу прощения за неидеальное качество картинки.
Интерпретатор БЭЙСИКа программируемый с PS/2 клавиатуры, после первой программы, я показываю как писать напрямую в память PPU через адресное пространство ввода-вывода активируя и двигая спрайт:
Демка графики, в этом видео программно скачут 64 спрайта 16х16, на фоне бэкграунда с динамическим скроллингом и оверлеем который двигается под и над спрайтами:
Звуковая демка показывает возможности YM3438 и ШИМ звук, звуковые данные этой демки и FM музыка и ШИМ звуки вместе занимают почти все доступные 128 килобайт звуковой памяти.
Тетрис, для графики использваны почти только возможности бэкграунда, музыка на YM3438, звуковые эффекты на ШИМ патчах.
Заключение
Этот проект поистине воплощение мечты, я над ним работал уже несколько лет, с перерывами, смотря по свободному времени, никогда не думал, что дойду так далеко в создании собственной игровой ретро видео приставки. Она, естественно, не идеальна, я уж точно не эксперт в электронике, в приставке явно вышло слишком много элементов и несомненно можно было сделать лучше и наверное кто-то из читателей как раз об этом думает.
Но всё-же, в процессе работы над этим проектом, я узнал многое об электронике, игровых приставках и дизайне компьютеров, языке ассемблера и других интересных вещах, и главное я получил огромное удовлетворение играя в игры которые я сам написал на железе которое я сам разработал и собрал.
У меня есть планы делать приставки/компьютеры и дальше. Вообще-то, я уже делаю новую приставку, она почти готова, и является упрощёной ретро приставкой на базе FPGA платы и нескольких дополнительных компонетов, (в намного меньшем количестве чем в этом проекте, уж точно), задуманой быть намного дешевле и повторяемее.
Хотя я тут очень много написал об этом проекте, несомненно ещё многое можно обсудить, я едва упомянул как звуковой движок работает, как CPU с ним взаимодействует, да и о графической системе и других входах-выходах и обо всей приставке в целом ещё много чего можно было бы расказать.
Смотря на реакцию читателей я может быть напишу ещё статей сфокусировавшись на обновлениях, подробностях об отдельных блоках приставки или других проектах.
Проекты, сайты, каналы Youtube которые вдохновляли меня и помогали мне с техническими знаниями:
Эти сайты/каналы не только вдохновляли, но и помогли мне найти решения сложных проблем которые возникали по ходу работы над этим проектом.
Спасибо, если дочитали до сюда. 🙂
Если у вас есть вопросы или фидбек пишите в комментариях внизу (Оригинальной статьи на английском языке на Гитхабе. прим. пер.)



















