Doom Boy ESP32. Вторая итерация

в 21:55, , рубрики: diy или сделай сам, DOOM, esp32, littlevgl, lvgl, программирование микроконтроллеров, Производство и разработка электроники, разработка игр, схемотехника

Так и не дождавшись DoomWatch платы сделал новый заказ с доставкой Fedex. В этот раз развел платы в KiCad. Как ни странна, Kicad понравился даже больше Eagle AutoDesk

Doom Boy ESP32. Вторая итерация - 1

Основная цель была попробовать распаять чип esp32d0wdq6. Не сам готовый модуль, а именно отдельно микросхемой с отдельным Flash и PSRAM. Как это сделано и работает, с видеодемками, читаете и смотрите дальше

Здесь можно прочитать про первую итерация платы

Boot

Boot Log

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:4
load:0x3fff0034,len:7076
load:0x40078000,len:14600
load:0x40080400,len:4160
0x40080400: _init at ??:?

entry 0x40080684
I (28) boot: ESP-IDF v4.2-dev-2243-gcf056a7d0-dirty 2nd stage bootloader
I (29) boot: compile time 18:51:57
I (30) boot: chip revision: 1
I (33) boot_comm: chip revision: 1, min. bootloader chip revision: 0
I (52) boot.esp32: SPI Speed: 40MHz
I (53) boot.esp32: SPI Mode: DIO
I (53) boot.esp32: SPI Flash Size: 8MB
I (56) boot: Enabling RNG early entropy source…
I (62) boot: Partition Table:
I (65) boot: ## Label Usage Type ST Offset Length
I (73) boot: 0 factory factory app 00 00 00010000 000e8000
I (80) boot: 1 wifidata WiFi data 01 02 000fc000 00004000
I (88) boot: 2 wad unknown 42 06 00100000 004f4000
I (95) boot: End of partition table
I (99) boot_comm: chip revision: 1, min. application chip revision: 0
I (106) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x38f98 (233368) map
I (216) esp_image: segment 1: paddr=0x00048fc0 vaddr=0x3ffb0000 size=0x07058 ( 28760) load
I (230) esp_image: segment 2: paddr=0x00050020 vaddr=0x400d0020 size=0x86370 (549744) map
0x400d0020: _stext at ??:?

I (468) esp_image: segment 3: paddr=0x000d6398 vaddr=0x3ffb7058 size=0x04ec4 ( 20164) load
I (478) esp_image: segment 4: paddr=0x000db264 vaddr=0x40080000 size=0x00404 ( 1028) load
0x40080000: _WindowOverflow4 at /esp/v3.3.2/esp-idf/components/freertos/xtensa/xtensa_vectors.S:1730

I (479) esp_image: segment 5: paddr=0x000db670 vaddr=0x40080404 size=0x12b7c ( 76668) load
I (538) boot: Loaded app from partition at offset 0x10000
I (538) boot: Disabling RNG early entropy source…
I (549) psram: This chip is ESP32-D0WD
I (551) spiram: Found 64MBit SPI RAM device
I (551) spiram: SPI RAM mode: flash 40m sram 40m
I (555) spiram: PSRAM initialized, cache is in low/high (2-core) mode.
I (562) cpu_start: Pro cpu up.
I (566) cpu_start: Starting app cpu, entry point is 0x4008191c
0x4008191c: start_cpu0_default at /esp/v3.3.2/esp-idf/components/esp32/cpu_start.c:466

I (0) cpu_start: App cpu up.
I (1454) spiram: SPI SRAM memory test OK
I (1462) cpu_start: Pro cpu start user code
I (1462) cpu_start: Application information:
I (1462) cpu_start: Project name: esp32_doom
I (1466) cpu_start: App version: 085f21b-dirty
I (1472) cpu_start: Compile time: Jul 26 2020 18:51:49
I (1478) cpu_start: ELF file SHA256: 9166eca39a0109f9…
I (1484) cpu_start: ESP-IDF: v4.2-dev-2243-gcf056a7d0-dirty
I (1491) heap_init: Initializing. RAM available for dynamic allocation:
I (1498) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (1504) heap_init: At 3FFCF628 len 000109D8 (66 KiB): DRAM
I (1511) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (1517) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (1524) heap_init: At 40092F80 len 0000D080 (52 KiB): IRAM
I (1530) spiram: Adding pool of 4096K of external SPI memory to heap allocator
I (1539) spi_flash: detected chip: generic
I (1543) spi_flash: flash io: dio
I (1548) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (1557) spiram: Reserving pool of 32K of internal memory for DMA/internal allocations

KiCad PCB

В KiCad как мне показалось все проще. На мой вкус конечно. Немного по другому чем в Eagle Autodesk. Главный плюс в том, что нет ограничения на размер платы если не хотите платить за лицензию. Напомню что в Eagle есть ограничение на размер 100x80мм для бесплатной разработки. Если плата больше надо платить годовую лицензию. По моему, есть также ограничение на количество слоев

Doom Boy ESP32. Вторая итерация - 2

Посмотреть 3D View в Eagle я так и не смог. Надо ставить Eagle Fusion 360. В Kicad это отдельный пункт меню. Хотя может я не там смотрел. В общем можно сказать перешел полностью на KiCad

Разделил все на модули, оставив на главной странице то что связано с ESP32 непосредственно. Сам чип и память
Doom Boy ESP32. Вторая итерация - 3

Ошибки

Рисовал плату в попыхах. В результате забыл вывести GPIO0. Подвел ее во внешний DAC как MCCLK, а вот вывести на кнопку режима загрузки забыл. Пришлось сдирать лак с дорожки для пайки вывода кнопки. Так же резистор в цепи кварца развел на XTAL_N а в мануале надо на XTAL_P. Повесил резистор несколько Ом, но можно было и перемычку кинуть

Не развелись резисторы Address и Reset для MCP23017. Чипу можно задать адрес I2C тремя выводами. 0x20h когда все три вывода на земле. Все потому что не указал FootPrint
Doom Boy ESP32. Вторая итерация - 4
На ошибку не обратил внимания

Error: Cannot add R10 (no footprint assigned).
Error: Cannot add R9 (no footprint assigned)

Перепутал i2C для ES8374. Бывает и такое. В принципе можно использовать переключив 21 -> 22 и 22 -> 21 выводы. Или перерезать дорожки и отскоблить лак, ну как это мы обычно делали с TX RX Uart (Грустный смайл)

Doom Boy ESP32. Вторая итерация - 5

На удивление запаяв ESP32 и FLASH плата завелась без каких то проблем. Но, поставив SPRAM, получил бесконечный reboot. Оказался банальный непропай по питанию. Вот бы я искал если ESP32 не припаялся!

Doom Boy ESP32. Вторая итерация - 6

Мультиплексор MCP23017

Предусмотрел возможность альтернативного опроса кнопок как через мультиплексор MCP23017 так и с помощью ЦАП. На резистивном делителе. Если нет возможности поставить мультиплексор можно задействовать внутренний ADC. По уровню напряжения на входе GPIO34 можно детектировать нажатие кнопки. Минус в том что невозможно опрашивать несколько кнопок одновременно. Плюс соответственно, что не надо дополнительной микросхемы. Только несколько резисторов
Doom Boy ESP32. Вторая итерация - 7
Мультиплексор имеет 2 порта по 8 выводов. Один порт, в нашем случае, можно сконфигурировать как выход и повесить на них светодиоды. Хотел предусмотреть мигание если жизни осталось меньше 20% или кончились патроны. Тогда можно будет играть без панели. Получилось реализовать. Остался один зеленый светодиод. Если в комнате нет врагов или в прямой видимости можно подсветить

Doom Boy ESP32. Вторая итерация - 8
Thread of the health and ammo indicator

void ledTask(void *arg){

    while(1){
            p = &players[cur_player];

            if (p->mo != NULL && p->mo->health < 20) {
                mcp23x17_set_level(&dev, 9, on);
            } else {
                mcp23x17_set_level(&dev, 9, true);
            }

            if(p->ammo[weaponinfo[p->readyweapon].ammo] < 5){
              mcp23x17_set_level(&dev, 10, on);
            } else {
              mcp23x17_set_level(&dev, 10, true);
            }

            printf("p->ammo[am_clip] = %dn", p->ammo[weaponinfo[p->readyweapon].ammo]);

            if (p->mo != NULL) {
                printf("p->mo->health = %d n", p->mo->health);
            }

            printf("Ammo N = %dn", weaponinfo[p->readyweapon].ammo);

             on = !on;
             vTaskDelay(1000/portTICK_PERIOD_MS);
    }
}

Аудио чип ES8374

Для звука, в качестве ЦАП и АЦП применил ES8374. Микросхема содержит встроенный усилитель низкой частоты ~ 1.25 Ватт. Она поддерживается Espressif Audio Development Framework из коробки. В маленьком корпусе QFN-28 получаем Моно ЦАП, АЦП для микрофона и УНЧ с поддержкой SDK. То что надо для такого устройства

Doom Boy ESP32. Вторая итерация - 9
Запустил BT Speaker из примера pipeline_bt_sink

Взял в настройках борду lyrat_v4_3. Исправил кодек на AUDIO_CODEC_ES8374_DEFAULT_HANDLE
Настроил порты GPIO

esp_err_t get_i2s_pins(i2s_port_t port, i2s_pin_config_t *i2s_config)
{
    AUDIO_NULL_CHECK(TAG, i2s_config, return ESP_FAIL);
    if (port == I2S_NUM_0 || port == I2S_NUM_1) {
        i2s_config->bck_io_num = GPIO_NUM_18;
        i2s_config->ws_io_num = GPIO_NUM_26;
        i2s_config->data_out_num = GPIO_NUM_27;
        i2s_config->data_in_num = GPIO_NUM_35;
    } else {
        memset(i2s_config, -1, sizeof(i2s_pin_config_t));
        ESP_LOGE(TAG, "i2s port %d is not supported", port);
        return ESP_FAIL;
    }
    return ESP_OK;
}

И выкинул инициализацию audio_board_key_init и audio_board_led_init. По правильному надо определять свою кастомную плату

Гироскоп L3GD20

Решил добавить гироскоп L3GD20. Интересная особенность, что его можно подключить как SPI или I2C устройство. R27, R28 в случае подключения по I2C задают адрес

// L3GD20H addresses
#define L3GD20H_I2C_ADDRESS_1 0x6a // SDO pin is low
#define L3GD20H_I2C_ADDRESS_2 0x6b // SDO pin is high

На GitHub есть библиотека l3gd20h-esp-idf

Doom Boy ESP32. Вторая итерация - 10
Таким образом на I2C имеем 3 устройства. Управление ADC-DAC ES8374, кнопки на MCP23017 и собственно L3GD20. Запустил все три

i2cdetect

i2c-tools> i2cdetect
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: — -- — -- — -- — -- — -- — -- — -- — --
10: 10 — -- — -- — -- — -- — -- — -- — -- —
20: — -- — -- 24 — -- — -- — -- — -- — -- —
30: — -- — -- — -- — -- — -- — -- — -- — --
40: — -- — -- — -- — -- — -- — -- — -- — --
50: — -- — -- — -- — -- — -- — -- — -- — --
60: — -- — -- — -- — -- — -- 6a — -- — -- —
70: — -- — -- — -- — -- — -- — -- — -- — --

Но почемуто L3GD20 не отдает координаты. WHO_AM_I корректо отвечает 0xd4. углы не меняются. У меня нет конденсатора С1 — 10nF, попытался поставить который нашел самый близкий 100nF. Думал пусть хотя бы врет, но похоже не запускается внутрений преобразователь. И это важно

i2cdump

i2c-tools> i2cdump -c 0x6a
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: b6 5e 81 fc 05 50 31 83 c4 f9 85 d0 48 c6 00 d4 ?^???P1?????H?.?
10: 1a 15 16 ea c0 b9 4f 72 07 d8 a1 21 a1 00 14 02 ??????Or???!?.??
20: 07 00 00 80 00 00 0c 00 1a 00 13 00 16 00 00 20 ?..?..?.?.?.?..
30: 00 00 00 00 00 00 00 00 00 05 00 00 00 00 00 00 .........?..
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00…
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00…
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00…
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00…

Дисплей 18 pin ILI9341

Doom Boy ESP32. Вторая итерация - 11
Рассчитал ток подсветки так. Требуется 90mA. Поскольку падение на открытом транзисторе ~0.7V питание для светодиодов подсветки 3.3V — 0.7V = 2.6V. И по закону Ома 2.6V / 0.090A = 28.8 Ohm. Поставил 47 Ohm. Получилось немного темновато. Надо будет уменьшить сопротивление
Doom Boy ESP32. Вторая итерация - 12

Также развел Touch XPT2046TS. SPI выводы повесил параллельно дисплею. XPT_CS выведен отдельным выводом. Есть сомнение что заработает. Если бы дисплей не завелся, сделал бы эксперименты. Для приставки он не особо нужен. Взял из примера

Doom Boy ESP32. Вторая итерация - 13

Демки

Запустил демо LVGL. В настройках примера пробовал выставлять 40MHz для шины SPI. Пример заработал немного быстрее чем на видео

А вот Doom запустился и стабильно работал только на 32MHz. Хотя 26MHz для ILI9341 уже считается разгон

spi_device_interface_config_t devcfg={
        .clock_speed_hz=26000000,               //Clock out at 26 MHz. Yes, that's heavily overclocked.
        .mode=0,                                //SPI mode 0
        .spics_io_num=PIN_NUM_CS,               //CS pin
        .queue_size=NO_SIM_TRANS,               //We want to be able to queue this many transfers
        .pre_cb=ili_spi_pre_transfer_callback,  //Specify pre-transfer callback to handle D/C line
    };

Заключение

Портов ввода вывода ESP32 не всегда хватает чтобы нафаршировать по максимуму. В этом плане STM32 выглядит привлекательнее. Но у нее нет встроенной поддержки Wi-Fi

В заключении отмечу, что на устройстве можно запустить Nintendo эмулятор ESP32-NESEMU, a Nintendo Entertainment System emulator for the ESP32
Я заказал Game Console с Али. Интересно будет посмотреть что там внутри. Возможно тоже ESP32

Doom Boy ESP32. Вторая итерация - 14

Обсуждение и советы жду в комментариях

Автор: Andreev Dmitry

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js