Приставка для 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

С большими планами на расширения функционала посредством портов контроллера, решил немного сэкономить на портах ввода вывода самого микроконтроллера, поставив 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.

Надо бы сделать еще одну редакцию печатной платы. Эта никуда не годится!


На видео версия без звука.

И еще у меня приплавился контакт джойстика для поворота когда паял. В общем первый блин комом