Приставка для Doom на ESP32 своими руками на драйвере MCP23017 для кнопок от UncleRus
В ожидании Doom часов пришла плата давнего проекта. На плате разведено внешние MCP23017 и CS4344 и еще много чего
Для кнопок используется расширитель портов MCP23017 подключенный по I2C. Для него есть драйвер который можно взять у UncleRus.
Сделана попытка запуска внешнего АЦП CS4344.
Doom от Espressif
Скачав порт Дум пришлось немного повозится чтобы его собрать. В конечном итоге все собралось и залилиось в ESP32 но… я поймал крэш на старте. На githab Issue проекта увидел аналогичное обсуждение проблемы:
Автор порта предлагал сделать
You probably need to use the malloc() option as well as reserve some memory for DMA. I'll see if I can get this compiling on master and update the sdkconfig when I have time.
В общем я «недолго думая» заменил все портированые функции выделения памяти на malloc()
Демка запустилась. Впереди меня ждало подключение кнопок
MCP23017 GPIO extender
С большими планами на расширения функционала посредством портов контроллера, решил немного сэкономить на портах ввода вывода самого микроконтроллера, поставив MCP23017. Это простой расширитель с доступом к сигналам ввода вывода через интерфейс I2C. Я не изобретал драйвер, а просто взял его у UncleRus.
Пять кнопок использует джойстик для навигации. Пару кнопок на выстрел и выбор меню. На самом деле этого недостаточно, надо еще открывать двери и двигаться влево-вправо без поворота то есть как краб. Контакты подтянуты внутри MCP23017 к VDD. Контакт замыкается на землю. Очень круто что внутри микросхемы есть резисторы подтяжки. Можно было бы еще заморочится с прерываниями от MCP23017. В ней есть два вывода на каждый порт INTA и INTB, но как нибудь в другой раз.
static const JsKeyMap keymap[]={
{0x10, &key_up},
{0x40, &key_down},
{0x80, &key_left},
{0x20, &key_right},
{0x4000, &key_use}, //cross
{0x2000, &key_fire}, //circle
{0x2000, &key_menu_enter}, //circle
{0x8000, &key_pause}, //square
{0x1000, &key_weapontoggle}, //triangle
{0x8, &key_escape}, //start
{0x1, &key_map}, //select
{0x400, &key_strafeleft}, //L1
{0x100, &key_speed}, //L2
{0x800, &key_straferight}, //R1
{0x200, &key_strafe}, //R2
{0, NULL},
};
Впилить обработку кнопок оказалось проще чем я думал. Я снизил частоту I2С для улучшения стабильности. Во всяком случае на заявленных 1MHz не пошло. Частоты 100kHz оказалось вполне достаточно для опроса в цикле с задержкой 20ms.
CMake
Убил кучу времени на дописывание CMakeList.txt для компонентов. Что-то не работало с make. И хотелось взять посвежее SDK. Изначальный порт не собирался даже на 3.2.x. Взял esp-idf-v3.3.1 возможно будет работать и на esp-idf-4.0
Звук через ЦАП
На самом деле есть еще один форк. Он отличается подключенной SD-CARD и звуком через встроенный DAC. Первоначальный порт от Espressif позволяет грузить wad файл только во внутреннюю Flash память программ и то надо использовать порезанный файл в котором нет звука!
Идея подключить вместо встроенного DAC внешний меня захватила. Хотя бы и самый копеечный от Cirrus Logic
Дальше я настроил DAC на CS4344 и тут меня ждало разочарование. Звук работал с прерываниями. Когда я впиливал в свой проект файл i_sound.c то заметил что один файл dma.h не используется. Как бы ссылка на него есть и сам он есть но все за комментировано. Может я невнимательно смотрел? Но думаю автор тоже заметил, что со звуком что-то не то и пытался устранить. Возможно устранил и не выложил последний коммит. А может на внутренний ЦАП все работает как надо. Однако выводить звук через встроенный ЦАП и на крошечный динамик можно и пренебречь искажениями-прерываниями. Я поигрался битрейтом и в целом по изменению кода. Это ничего не принесло.
И да, по поводу подключения SD-CARD. Изначально Я повесил ее параллельно дисплею по шине SPI, разведя раздельно сигнал выбор чипа CS. Идея провалилась. Провентилировав вопрос Support SD-SPI bus sharing пришел к выводу что не все SD-CARD сделаны одинаково или мои руки не такие прямые.
пришлось распаять ее через адаптер на плату вместо микрофона. Завелось без подтяжек внешними резисторами к VDD.
gpio_set_pull_mode(PIN_NUM_MOSI, GPIO_PULLUP_ONLY);
gpio_set_pull_mode(PIN_NUM_MISO, GPIO_PULLUP_ONLY);
gpio_set_pull_mode(PIN_NUM_CLK, GPIO_PULLUP_ONLY);
gpio_set_pull_mode(PIN_NUM_CS, GPIO_PULLUP_ONLY);
На этом я бросил это занятие и выложил исходники на GitHub.
Надо бы сделать еще одну редакцию печатной платы. Эта никуда не годится!
На видео версия без звука.
И еще у меня приплавился контакт джойстика для поворота когда паял. В общем первый блин комом
Автор: Andreev Dmitry