-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Added support for DFRobot Unihiker K10 #11193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # CircuitPython Port: DFRobot UNIHIKER K10 (ESP32-S3) | ||
|
|
||
| **Status**: ✅ Functional — All major hardware features working: | ||
| - PMIC (TCA9555 I2C expander: backlight, camera reset, buttons, audio amp) | ||
| - Display ILI9341 (240×320, oriented correctly via MADCTL=0x88) | ||
| - NeoPixel (single RGB LED) | ||
| - Camera GC2145 (2MP, QVGA via espcamera) | ||
| - Audio I2S (MAX98357 speaker amp, 440Hz tone) | ||
| - Buttons A/B (PMIC-controlled, NOT GPIOs) | ||
| - Sensors: SC7A20H (accelerometer), LTR303ALS (light), AHT20 (temp/humidity) | ||
| - PSRAM 8MB OPI @ 80MHz ✅ | ||
| - Flash 16MB DIO @ 80MHz ✅ | ||
| - USB Serial/JTAG console ✅ | ||
| - Frozen Python libraries (27 modules pre-loaded) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| // This file is part of the CircuitPython project: https://circuitpython.org | ||
| // SPDX-FileCopyrightText: Copyright (c) 2026 Djair Guilherme | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| #include "supervisor/board.h" | ||
| #include "mpconfigboard.h" | ||
| #include "shared-bindings/busio/SPI.h" | ||
| #include "shared-bindings/fourwire/FourWire.h" | ||
| #include "shared-bindings/microcontroller/Pin.h" | ||
| #include "shared-module/displayio/__init__.h" | ||
| #include "shared-module/displayio/mipi_constants.h" | ||
| #include "shared-bindings/board/__init__.h" | ||
|
|
||
| #define DELAY 0x80 | ||
|
|
||
| // ILI9341 init sequence (standard) | ||
| uint8_t display_init_sequence[] = { | ||
| // sw reset | ||
| 0x01, 0 | DELAY, 150, | ||
| // sleep out | ||
| 0x11, 0 | DELAY, 255, | ||
| // normal display mode on | ||
| 0x13, 0, | ||
| // pixel format: 16-bit RGB565 | ||
| 0x3A, 1, 0x55, | ||
| // frame rate control | ||
| 0xB1, 2, 0x00, 0x1B, | ||
| // display function control | ||
| 0xB6, 4, 0x0A, 0x82, 0x27, 0x00, | ||
| // power control 1 | ||
| 0xC0, 1, 0x23, | ||
| // power control 2 | ||
| 0xC1, 1, 0x10, | ||
| // VCOM control 1 | ||
| 0xC5, 2, 0x3E, 0x28, | ||
| // VCOM control 2 | ||
| 0xC7, 1, 0x86, | ||
| // memory access control (MV=0, MX=0, MY=0, ML=0, BGR=1) | ||
| 0x36, 1, 0x88, | ||
| // column address set (0..239) | ||
| 0x2A, 4, 0x00, 0x00, 0x00, 0xEF, | ||
| // page address set (0..319) | ||
| 0x2B, 4, 0x00, 0x00, 0x01, 0x3F, | ||
| // positive gamma | ||
| 0xE0, 15, 0x00, 0x07, 0x10, 0x09, 0x17, 0x0B, 0x41, 0x89, 0x4B, 0x0A, 0x0C, 0x0E, 0x18, 0x1A, 0x0F, | ||
| // negative gamma | ||
| 0xE1, 15, 0x00, 0x17, 0x1D, 0x02, 0x0C, 0x05, 0x23, 0x75, 0x4B, 0x05, 0x0E, 0x11, 0x27, 0x38, 0x0F, | ||
| // display on | ||
| 0x29, 0 | DELAY, 100, | ||
| }; | ||
|
|
||
| void board_init(void) { | ||
| // Backlight is controlled by PMIC via init_board() in libunihiker_k10.a | ||
| // No direct GPIO backlight control needed | ||
|
|
||
| busio_spi_obj_t *spi = common_hal_board_create_spi(0); | ||
| fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; | ||
| bus->base.type = &fourwire_fourwire_type; | ||
|
|
||
| common_hal_fourwire_fourwire_construct( | ||
| bus, | ||
| spi, | ||
| MP_OBJ_FROM_PTR(&pin_GPIO13), // DC | ||
| MP_OBJ_FROM_PTR(&pin_GPIO14), // CS | ||
| mp_const_none, // RST (tied to 3.3V) | ||
| 40000000, // baudrate | ||
| 0, // polarity | ||
| 0 // phase | ||
| ); | ||
|
|
||
| busdisplay_busdisplay_obj_t *display = &allocate_display()->display; | ||
| display->base.type = &busdisplay_busdisplay_type; | ||
|
|
||
| common_hal_busdisplay_busdisplay_construct( | ||
| display, | ||
| bus, | ||
| 240, // width | ||
| 320, // height | ||
| 0, // column start | ||
| 0, // row start | ||
| 0, // rotation (0=default from MADCTL) | ||
| 16, // color depth | ||
| false, // grayscale | ||
| false, // pixels in a byte share a row | ||
| 1, // bytes per cell | ||
| false, // reverse_pixels_in_byte | ||
| true, // reverse_pixels_in_word | ||
| MIPI_COMMAND_SET_COLUMN_ADDRESS, | ||
| MIPI_COMMAND_SET_PAGE_ADDRESS, | ||
| MIPI_COMMAND_WRITE_MEMORY_START, | ||
| display_init_sequence, | ||
| sizeof(display_init_sequence), | ||
| NULL, // backlight pin (PMIC controlled) | ||
| NO_BRIGHTNESS_COMMAND, | ||
| 1.0f, // brightness | ||
| false, // single_byte_bounds | ||
| false, // data_as_commands | ||
| true, // auto_refresh | ||
| 60, // native_frames_per_second | ||
| true, // backlight_on_high | ||
| false, // SH1107_addressing | ||
| 50000 // backlight pwm frequency | ||
| ); | ||
| } | ||
|
|
||
| // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| // This file is part of the CircuitPython project: https://circuitpython.org | ||
| // SPDX-FileCopyrightText: Copyright (c) 2026 Djair Guilherme | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| #pragma once | ||
|
|
||
| #define MICROPY_HW_BOARD_NAME "DFRobot UNIHIKER K10" | ||
| #define MICROPY_HW_MCU_NAME "ESP32S3" | ||
|
|
||
| // I2C bus - sensors (AHT20, LTR303ALS, SC7A20H) | ||
| #define CIRCUITPY_BOARD_I2C (1) | ||
| #define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO48, .sda = &pin_GPIO47}} | ||
|
|
||
| // SPI bus - Display ILI9341 | ||
| #define CIRCUITPY_BOARD_SPI (1) | ||
| #define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO12, .mosi = &pin_GPIO21, .miso = &pin_GPIO41}} | ||
|
|
||
| // Display (ILI9341 via SPI) | ||
| #define MICROPY_HW_DISPLAY_SPI_CS (&pin_GPIO14) | ||
| #define MICROPY_HW_DISPLAY_SPI_DC (&pin_GPIO13) | ||
| //#define MICROPY_HW_DISPLAY_SPI_RST (NULL) // tied to 3.3V, not used - RST handled in board.c | ||
| #define MICROPY_HW_DISPLAY_WIDTH (240) | ||
| #define MICROPY_HW_DISPLAY_HEIGHT (320) | ||
|
|
||
| // Backlight - controlled via PMIC (not direct GPIO) | ||
| // eLCD_BLK is handled by init_board() in libunihiker_k10.a | ||
|
|
||
| // NeoPixel (3x WS2812) | ||
| #define MICROPY_HW_NEOPIXEL (&pin_GPIO46) | ||
|
|
||
| // Status LED | ||
| #define MICROPY_HW_LED_STATUS (&pin_GPIO46) | ||
|
|
||
| // Default UART | ||
| //#define DEFAULT_UART_BUS_RX (NULL) // No UART on default pins | ||
| //#define DEFAULT_UART_BUS_TX (NULL) // No UART on default pins | ||
|
|
||
| // Camera (GC2145) - pins from who_camera.h | ||
| #define CIRCUITPY_ESPCAMERA_PWDN (-1) | ||
| #define CIRCUITPY_ESPCAMERA_RESET (-1) | ||
| #define CIRCUITPY_ESPCAMERA_XCLK (7) | ||
| #define CIRCUITPY_ESPCAMERA_SIOD (47) | ||
| #define CIRCUITPY_ESPCAMERA_SIOC (48) | ||
| #define CIRCUITPY_ESPCAMERA_D7 (6) | ||
| #define CIRCUITPY_ESPCAMERA_D6 (15) | ||
| #define CIRCUITPY_ESPCAMERA_D5 (16) | ||
| #define CIRCUITPY_ESPCAMERA_D4 (18) | ||
| #define CIRCUITPY_ESPCAMERA_D3 (9) | ||
| #define CIRCUITPY_ESPCAMERA_D2 (11) | ||
| #define CIRCUITPY_ESPCAMERA_D1 (10) | ||
| #define CIRCUITPY_ESPCAMERA_D0 (8) | ||
| #define CIRCUITPY_ESPCAMERA_VSYNC (4) | ||
| #define CIRCUITPY_ESPCAMERA_HREF (5) | ||
| #define CIRCUITPY_ESPCAMERA_PCLK (17) | ||
|
|
||
| // I2S Audio | ||
| #define CIRCUITPY_I2S_BCLK (&pin_GPIO0) | ||
| #define CIRCUITPY_I2S_LRCLK (&pin_GPIO38) | ||
| #define CIRCUITPY_I2S_DIN (&pin_GPIO39) | ||
| #define CIRCUITPY_I2S_DOUT (&pin_GPIO45) | ||
| #define CIRCUITPY_I2S_MCLK (&pin_GPIO3) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| # This file is part of the CircuitPython project: https://circuitpython.org | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 Djair Guilherme | ||
| # SPDX-License-Identifier: MIT | ||
|
|
||
| USB_VID = 0x303A | ||
| USB_PID = 0x1001 | ||
|
Comment on lines
+5
to
+6
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a generic PID. Please get a specific one. Espressif allocates them here: https://github.com/espressif/usb-pids |
||
| USB_MANUFACTURER = "DFRobot" | ||
| USB_PRODUCT = "UNIHIKER K10" | ||
|
|
||
| IDF_TARGET = esp32s3 | ||
|
|
||
| # Flash configuration - 16MB QSPI Flash | ||
| CIRCUITPY_ESP_FLASH_SIZE = 16MB | ||
| CIRCUITPY_ESP_FLASH_MODE = dio | ||
| CIRCUITPY_ESP_FLASH_FREQ = 80m | ||
|
|
||
| # PSRAM configuration - 8MB QSPI PSRAM | ||
| CIRCUITPY_ESP_PSRAM_SIZE = 8MB | ||
| CIRCUITPY_ESP_PSRAM_MODE = opi | ||
| CIRCUITPY_ESP_PSRAM_FREQ = 80m | ||
|
|
||
| OPTIMIZATION_FLAGS = -Os | ||
|
|
||
| # Display via SPI (ILI9341) | ||
| CIRCUITPY_PARALLELDISPLAYBUS = 0 | ||
|
|
||
| # Camera (GC2145) | ||
| CIRCUITPY_ESPCAMERA = 1 | ||
|
|
||
| # I2S for audio (microphone + speaker) | ||
| CIRCUITPY_AUDIOBUSIO = 1 | ||
|
|
||
| # SD card via SDMMC - disabled until pin mapping verified | ||
| CIRCUITPY_SDIOIO = 0 | ||
|
|
||
| # Frozen Python modules (built-in libraries) | ||
| FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel | ||
| FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ILI9341 | ||
| FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_AHTx0 | ||
| FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_SD | ||
| FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Wave | ||
| FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Shapes | ||
| FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Text | ||
| FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice | ||
| FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register | ||
| FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_SimpleIO | ||
| FROZEN_MPY_DIRS += $(TOP)/frozen/adafruit_tca9555 | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| // This file is part of the CircuitPython project: https://circuitpython.org | ||
| // SPDX-FileCopyrightText: Copyright (c) 2026 Djair Guilherme | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| #include "py/obj.h" | ||
| #include "py/mphal.h" | ||
| #include "shared-bindings/board/__init__.h" | ||
| #include "shared-bindings/microcontroller/Pin.h" | ||
| #include "shared-module/displayio/__init__.h" | ||
|
|
||
| static const mp_rom_map_elem_t board_module_globals_table[] = { | ||
| CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS | ||
|
|
||
| // ================================================================= | ||
| // ONBOARD PERIPHERALS - Functional Names | ||
| // ================================================================= | ||
|
|
||
| // Buttons are PMIC-controlled (TCA9555), not direct GPIOs | ||
| { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, | ||
|
|
||
| // NeoPixel (3x WS2812) | ||
| { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO46) }, | ||
| { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO46) }, | ||
|
|
||
| // I2C (sensors: AHT20, LTR303ALS, SC7A20H) | ||
| { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO47) }, | ||
| { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO48) }, | ||
| { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, | ||
|
|
||
| // SPI (Display ILI9341) | ||
| { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO21) }, | ||
| { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO12) }, | ||
| { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, | ||
|
|
||
| // Display control | ||
| { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO14) }, | ||
| { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO13) }, | ||
| // TFT_RESET is tied to 3.3V (no GPIO) | ||
|
|
||
| // Camera (GC2145) | ||
| { MP_ROM_QSTR(MP_QSTR_CAM_XCLK), MP_ROM_PTR(&pin_GPIO7) }, | ||
| { MP_ROM_QSTR(MP_QSTR_CAM_SIOD), MP_ROM_PTR(&pin_GPIO47) }, | ||
| { MP_ROM_QSTR(MP_QSTR_CAM_SIOC), MP_ROM_PTR(&pin_GPIO48) }, | ||
| { MP_ROM_QSTR(MP_QSTR_CAM_D7), MP_ROM_PTR(&pin_GPIO6) }, | ||
| { MP_ROM_QSTR(MP_QSTR_CAM_D6), MP_ROM_PTR(&pin_GPIO15) }, | ||
| { MP_ROM_QSTR(MP_QSTR_CAM_D5), MP_ROM_PTR(&pin_GPIO16) }, | ||
| { MP_ROM_QSTR(MP_QSTR_CAM_D4), MP_ROM_PTR(&pin_GPIO18) }, | ||
| { MP_ROM_QSTR(MP_QSTR_CAM_D3), MP_ROM_PTR(&pin_GPIO9) }, | ||
| { MP_ROM_QSTR(MP_QSTR_CAM_D2), MP_ROM_PTR(&pin_GPIO11) }, | ||
| { MP_ROM_QSTR(MP_QSTR_CAM_D1), MP_ROM_PTR(&pin_GPIO10) }, | ||
| { MP_ROM_QSTR(MP_QSTR_CAM_D0), MP_ROM_PTR(&pin_GPIO8) }, | ||
| { MP_ROM_QSTR(MP_QSTR_CAM_VSYNC), MP_ROM_PTR(&pin_GPIO4) }, | ||
| { MP_ROM_QSTR(MP_QSTR_CAM_HREF), MP_ROM_PTR(&pin_GPIO5) }, | ||
| { MP_ROM_QSTR(MP_QSTR_CAM_PCLK), MP_ROM_PTR(&pin_GPIO17) }, | ||
|
|
||
| // I2S Audio | ||
| { MP_ROM_QSTR(MP_QSTR_I2S_BCLK), MP_ROM_PTR(&pin_GPIO0) }, | ||
| { MP_ROM_QSTR(MP_QSTR_I2S_LRCLK), MP_ROM_PTR(&pin_GPIO38) }, | ||
| { MP_ROM_QSTR(MP_QSTR_I2S_DIN), MP_ROM_PTR(&pin_GPIO39) }, | ||
| { MP_ROM_QSTR(MP_QSTR_I2S_DOUT), MP_ROM_PTR(&pin_GPIO45) }, | ||
| { MP_ROM_QSTR(MP_QSTR_I2S_MCLK), MP_ROM_PTR(&pin_GPIO3) }, | ||
|
|
||
| // SD Card (SDMMC) - internal to SDMMC peripheral, no discrete GPIOs | ||
|
|
||
| // ================================================================= | ||
| // GENERAL PURPOSE I/O | ||
| // ================================================================= | ||
| { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, | ||
| { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, | ||
| { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, | ||
| { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, | ||
| { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, | ||
| { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, | ||
| { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, | ||
|
|
||
| // Display | ||
| { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, | ||
| }; | ||
| MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should be able to use circuitpython settings for these instead of your own. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # | ||
| # | ||
| # Debug/Diagnostic settings for K10 | ||
| # | ||
|
|
||
| # | ||
| # Bootloader config | ||
| # | ||
| CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y | ||
| # CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set | ||
| # CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set | ||
| # CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set | ||
| # default: | ||
| CONFIG_BOOTLOADER_LOG_LEVEL=3 | ||
|
|
||
| # | ||
| # ESP-STDIO (USB Serial/JTAG console) | ||
| # | ||
| # CONFIG_ESP_CONSOLE_NONE is not set | ||
| CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y | ||
| # default: | ||
| CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y | ||
| # default: | ||
| CONFIG_ESP_CONSOLE_UART_NUM=-1 | ||
| # default: | ||
| CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=6 | ||
|
|
||
| # | ||
| # ESP System Settings - panic behavior | ||
| # | ||
| CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y | ||
| # CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set | ||
| # CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set | ||
|
|
||
| # | ||
| # PSRAM - allow boot even if memtest fails | ||
| # | ||
| CONFIG_SPIRAM_IGNORE_NOTFOUND=y | ||
|
|
||
| # Espressif IoT Development Framework Configuration | ||
| # | ||
| # | ||
| # Component config | ||
| # | ||
| # | ||
| # LWIP | ||
| # | ||
| # end of LWIP | ||
|
|
||
| # end of Component config | ||
|
|
||
| # end of Espressif IoT Development Framework Configuration | ||
|
|
||
| # | ||
| # Camera sensor support - GC2145 | ||
| # | ||
| CONFIG_GC2145_SUPPORT=y |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for this. Please add a concise summary to circuitpython-org after this is merged instead.