You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
NM-Display-2.8inch Factory Test Firmware (Arduino)
This project is the PlatformIO / Arduino-framework port of the NM-Display 2.8-inch factory-test firmware for the NM-Display 2.8-inch development board (ESP32-S3).
It provides a sequential 10-item hardware self-test driven by an LVGL 8.x touch UI.
Note: The original IDF version lives in a separate repository. This repo targets PlatformIO + Arduino framework only. The build system, library management, and driver APIs differ significantly — do not mix the two.
AXP2101 (power management, I2C 0x34; Chip ID = 0x47 on this board, standard is 0x4A)
RTC
PCF85063 (real-time clock, I2C)
IO Expander
TCA9554 (I2C, addr 0x20)
Camera
DVP interface (OV series), RGB565 320×480
SD Card
SDMMC 1-bit mode
Wi-Fi
ESP32-S3 built-in
Backlight
LEDC PWM (10-bit, 5 kHz, CH1)
Button
BOOT button on GPIO0 (active low)
IO Pin Assignment
I2C Bus (Shared)
GPIO
Function
IO7
I2C SCL
IO8
I2C SDA
All peripherals share one I2C bus at 400 kHz: TCA9554 (0x20), FT6336 (0x38), AXP2101 (0x34), ES8311 (0x18), QMI8658 (0x6A), PCF85063 (0x51).
LCD Display (ST7789, SPI)
GPIO
Function
IO1
SPI MOSI
IO5
SPI SCLK
IO3
LCD DC
IO6
Backlight (PWM)
NC
SPI CS (tied low on board)
NC
LCD RST (via TCA9554 IO1)
SPI clock: 80 MHz, Mode 3
Logical resolution after 90° rotation: 320×240
Touch Panel (FT6336, I2C)
GPIO
Function
IO7
I2C SCL
IO8
I2C SDA
Reset: controlled by TCA9554 IO1
IO Expander (TCA9554, I2C 0x20)
TCA9554 Pin
Function
IO1
LCD + Touch module RESET (output)
IO7
PA_CTRL — NS4150B amp enable (output)
Config register 0x03 = 0x7D (IO1 and IO7 as output, rest input)
Output register 0x01: 0x82 = PA ON, 0x02 = PA OFF
Audio Codec (ES8311, I2C 0x18 + I2S)
GPIO
Function
IO7
I2C SCL (control)
IO8
I2C SDA (control)
IO12
I2S MCLK (256 × SR)
IO13
I2S BCLK
IO15
I2S LRCK
IO16
I2S DOUT (playback)
IO14
I2S DIN (record)
Sample rate: 16 000 Hz, 16-bit stereo, Philips/I2S format
MCLK = 256 × 16 000 = 4 096 000 Hz
PA amplifier (NS4150B) controlled via TCA9554 IO7
IMU (QMI8658, I2C 0x6A)
GPIO
Function
IO7
I2C SCL
IO8
I2C SDA
Accel: ±4 G, ODR 1000 Hz
Gyro: ±512 DPS, ODR 1000 Hz
Mahony AHRS fusion (quaternion output)
RTC (PCF85063, I2C 0x51)
Resets to 2025-01-01 12:00:00 if stored year < 2025
PMU (AXP2101, I2C 0x34)
Monitors battery, VBUS, system voltage, DC/LDO rails
Chip ID reported as 0x47 on this board (handled in driver)
Camera (DVP)
GPIO
Function
IO38
XCLK (20 MHz, LEDC CH0)
IO17
VSYNC
IO18
HREF
IO41
PCLK
IO45–IO21
D0–D7
IO8
SCCB SDA
IO7
SCCB SCL
SD Card (SDMMC 1-bit)
GPIO
Function
IO9
SDMMC D0
IO10
SDMMC CMD
IO11
SDMMC CLK
Button
GPIO
Function
IO0
BOOT button (active low)
Environment & Dependencies
Required Tools
Tool
Version / Note
PlatformIO IDE
VS Code extension or CLI
Python
3.9 – 3.12 (required by PlatformIO)
Platform
espressif32 @ 6.6.0
Framework
Arduino (via PlatformIO)
Library Dependencies (auto-resolved by PlatformIO)
Library
Version
Note
lvgl/lvgl
^8.4.0
Declared in platformio.inilib_deps
All other drivers (ST7789, FT6336, ES8311, QMI8658, AXP2101, PCF85063, TCA9554, camera) are included as source files inside this repository under src/drivers/ and src/bsp/. No separate installation is required.
# Via pip (if not using VS Code extension)
pip install platformio
2. Build firmware
cd NM-Display-28inch
pio run -e nm-display-28
3. Flash firmware + SPIFFS in one step
The project includes a post-build script (scripts/upload_all.py) that automatically builds and uploads the SPIFFS filesystem image after the firmware upload completes.
pio run -e nm-display-28 --target upload --upload-port COMx
Replace COMx with the actual serial port (e.g. COM48 on Windows, /dev/ttyACM0 on Linux).
Tip: In VS Code with PlatformIO extension, clicking the "Upload" button performs both steps automatically.
4. Flash firmware only (skip SPIFFS)
pio run -e nm-display-28 --target upload --upload-port COMx
pio run -e nm-display-28 --target uploadfs --upload-port COMx
5. Serial monitor
pio device monitor -e nm-display-28 --port COMx
Baud rate: 115 200. The monitor filter includes esp32_exception_decoder and time prefix.
6. Partition table
Partition
Type
Offset
Size
nvs
data
0x009000
20 KB
otadata
data
0x00E000
8 KB
app0
ota_0
0x010000
4 MB
app1
ota_1
0x410000
4 MB
spiffs
spiffs
0x810000
6 MB
Factory Test Flow
On power-on, the board runs a boot animation (GIF), then launches the factory test sequence automatically.
Power-on
↓
Boot animation (SPIFFS GIF)
↓
FactoryTest::run()
├─ T01 Display — color fill (R/G/B/W/K) + PASS/FAIL
├─ T02 Touch — draw touch trail, tap OK when done
├─ T03 SD Card — mount + read capacity
├─ T04 Wi-Fi — scan + connect (credentials in config)
├─ T05 IMU — QMI8658 WHO_AM_I + accel/gyro live data
├─ T06 PMU — AXP2101 chip ID + voltage rails
├─ T07 RTC — PCF85063 probe + time read/write
├─ T08 Camera — DVP capture + live preview
├─ T09 Codec — ES8311 ID check + sweep (500~4 kHz) + Ode to Joy
└─ T10 Mic — ES8311 ADC record 5 s + auto-playback
↓
Summary screen (P/F/S per item) + Reboot button
Each test shows a title bar with Failed / Ok buttons. The tester can override the automatic result at any time.
Test Items
#
Name
Pass Criteria
1
Display
All 5 colors (R/G/B/W/K) render correctly, tester confirms
Chip ID = 0x47, all voltage rails within expected range
7
RTC
I2C probe OK, time can be set and read back
8
Camera
Frame captured and displayed (non-black image)
9
Codec
ID[FD]=0x83 + ID[FE]=0x11; sweep tone and melody audible
10
Mic
Record 5 s via analog MIC (ES8311 ADC), playback audible
Porting Guide
Change board pins
All GPIO numbers are centralised in src/bsp/nm_display_28/config.h. Edit only that file for hardware changes.
Change Wi-Fi credentials
Edit src/app/application.cpp (or wherever wifi_init() is called):
wifi_connect("YOUR_SSID", "YOUR_PASSWORD");
Add a new BSP
Create src/bsp/<board_name>/config.h with the new pin definitions.
Create src/bsp/<board_name>/<board_name>.cpp for board bring-up.
Add a new [env:<board_name>] section in platformio.ini.
Update build_src_filter to include the new BSP and exclude the old one.
LVGL configuration
Edit src/drivers/display/lv_conf.h. Key settings for this board:
#defineLV_COLOR_DEPTH 16
#defineLV_COLOR_16_SWAP 0 // ST7789 on this board does NOT need byte-swap
#defineLV_HOR_RES_MAX 320
#defineLV_VER_RES_MAX 240
Notes
AXP2101 Chip ID: The standard AXP2101 Chip ID is 0x4A. This board reports 0x47 instead. The driver accepts both values; no user action is required. board_build.arduino.memory_type = qio_opi in platformio.ini is mandatory. Removing it will cause a boot crash.
I2S driver: This project uses the legacydriver/i2s.h API (IDF 4.4 style), not the newer i2s_std / i2s_pdm APIs available in IDF 5.x. This is intentional for compatibility with the Arduino-ESP32 framework version pinned in platformio.ini.
LEDC channel conflict: Camera XCLK uses LEDC_TIMER_0 / LEDC_CHANNEL_0. Backlight PWM uses LEDC_CHANNEL_1. Do not share channels.
TCA9554 IO7 (PA_CTRL): The power amplifier (NS4150B) is not directly connected to an ESP32 GPIO — it is controlled via TCA9554 IO7. Writing to the TCA9554 output register is required before audio playback; omitting this step results in silence.
ES8311 register read: The ES8311 does not support register auto-increment. Registers 0xFD and 0xFE (chip ID) must be read individually with separate requestFrom() calls.
Boot animation: The GIF file must be uploaded to SPIFFS. If the SPIFFS partition is empty, the boot animation is skipped and the factory test starts immediately.
Firmware version: Defined in src/version.h as APP_VERSION_STR "0.1.0".
About
The 2.8 inch ESP32-S3 display, collaborate with the NMTech Team.