diff --git a/ports/raspberrypi/boards/tinycircuits_thumby/board.c b/ports/raspberrypi/boards/tinycircuits_thumby/board.c new file mode 100644 index 0000000000000..15a7eeb93a4c6 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby/board.c @@ -0,0 +1,81 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// 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" + + +uint8_t display_init_sequence[] = { + 0xAE, 0, // DISPLAY_OFF + 0x20, 1, 0x00, // Set memory addressing to horizontal mode. + 0x81, 1, 0xcf, // set contrast control + 0xA1, 0, // Column 127 is segment 0 + 0xA6, 0, // Normal display + 0xc8, 0, // Normal display + 0xA8, 1, 0x3f, // Mux ratio is 1/64 + 0xd5, 1, 0x80, // Set divide ratio + 0xd9, 1, 0xf1, // Set pre-charge period + 0xda, 1, 0x12, // Set com configuration + 0xdb, 1, 0x40, // Set vcom configuration + 0x8d, 1, 0x14, // Enable charge pump + 0xAF, 0, // DISPLAY_ON +}; + +void board_init(void) { + 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, + CIRCUITPY_BOARD_OLED_DC, // Command or data + CIRCUITPY_BOARD_OLED_CS, // Chip select + CIRCUITPY_BOARD_OLED_RESET, // Reset + 10000000, // 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, + 72, // Width (after rotation) + 40, // Height (after rotation) + 28, // column start + 28, // row start + 0, // rotation + 1, // Color depth + true, // grayscale + false, // pixels in byte share row. only used for depth < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + 0x21, // Set column command + 0x22, // Set row command + 44, // Write memory command + display_init_sequence, + sizeof(display_init_sequence), + NULL, // backlight pin + 0x81, + 1.0f, // brightness + true, // single_byte_bounds + true, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 0); // backlight pwm frequency +} + +void reset_board(void) { +} diff --git a/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.h b/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.h new file mode 100644 index 0000000000000..91430966d232e --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.h @@ -0,0 +1,23 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "TinyCircuits Thumby" +#define MICROPY_HW_MCU_NAME "rp2040" + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) + +#define CIRCUITPY_BOARD_OLED_DC (&pin_GPIO17) +#define CIRCUITPY_BOARD_OLED_CS (&pin_GPIO16) +#define CIRCUITPY_BOARD_OLED_RESET (&pin_GPIO20) + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = DEFAULT_SPI_BUS_SCK, .mosi = DEFAULT_SPI_BUS_MOSI, .miso = NULL}} + +// For entering safe mode +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO6) diff --git a/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.mk b/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.mk new file mode 100644 index 0000000000000..44dc0d671001b --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.mk @@ -0,0 +1,18 @@ +USB_VID = 0x1D6B +USB_PID = 0x0003 +USB_PRODUCT = "Thumby" +USB_MANUFACTURER = "TinyCircuits" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" + +CIRCUITPY_STAGE = 1 +CIRCUITPY_AUDIOIO = 1 +CIRCUITPY_AUDIOPWMIO = 1 +CIRCUITPY_KEYPAD = 1 + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_framebuf +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_SSD1306 +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DisplayIO_SSD1306 diff --git a/ports/raspberrypi/boards/tinycircuits_thumby/pico-sdk-configboard.h b/ports/raspberrypi/boards/tinycircuits_thumby/pico-sdk-configboard.h new file mode 100644 index 0000000000000..ce5a7645b4e22 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby/pico-sdk-configboard.h @@ -0,0 +1,12 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. + +// Allow extra time for xosc to start. +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 diff --git a/ports/raspberrypi/boards/tinycircuits_thumby/pins.c b/ports/raspberrypi/boards/tinycircuits_thumby/pins.c new file mode 100644 index 0000000000000..0a087bb8db8a9 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby/pins.c @@ -0,0 +1,48 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Link Cable (ASR00074) + { MP_ROM_QSTR(MP_QSTR_EXT_TX), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_EXT), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_EXT_PU), MP_ROM_PTR(&pin_GPIO1) }, + + // 0.42 inch OLED AST1042 + { MP_ROM_QSTR(MP_QSTR_OLED_CS), MP_ROM_PTR(CIRCUITPY_BOARD_OLED_CS) }, + { MP_ROM_QSTR(MP_QSTR_OLED_DC), MP_ROM_PTR(CIRCUITPY_BOARD_OLED_DC) }, + { MP_ROM_QSTR(MP_QSTR_OLED_RESET), MP_ROM_PTR(CIRCUITPY_BOARD_OLED_RESET) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(DEFAULT_SPI_BUS_SCK) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(DEFAULT_SPI_BUS_MOSI) }, + + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, + + // Buttons + { MP_ROM_QSTR(MP_QSTR_BUTTON_LEFT), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_UP), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_RIGHT), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_DOWN), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_1), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_2), MP_ROM_PTR(&pin_GPIO27) }, + + // Mono PWM Speaker + { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_GPIO28) }, + + // Hardware revision ID pins + { MP_OBJ_NEW_QSTR(MP_QSTR_ID3), MP_ROM_PTR(&pin_GPIO12) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ID2), MP_ROM_PTR(&pin_GPIO13) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ID1), MP_ROM_PTR(&pin_GPIO14) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ID0), MP_ROM_PTR(&pin_GPIO15) }, + + // Power pins + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_GPIO26) } +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/tinycircuits_thumby_color/board.c b/ports/raspberrypi/boards/tinycircuits_thumby_color/board.c new file mode 100644 index 0000000000000..abd80dafc62c8 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby_color/board.c @@ -0,0 +1,108 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// 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 + +// display init sequence according to TinyCircuits-Tiny-Game-Engine +uint8_t display_init_sequence[] = { + 0xFE, 0, // inter register enable 1 + 0xEF, 0, // inter register enable 2 + 0xB0, 1, 0xC0, + 0xB1, 1, 0x80, + 0xB2, 1, 0x2F, + 0xB3, 1, 0x03, + 0xB7, 1, 0x01, + 0xB6, 1, 0x19, + 0xAC, 1, 0xC8, // Complement Principle of RGB 5, 6, 5 + 0xAB, 1, 0x0f, // ? + 0x3A, 1, 0x05, // COLMOD: Pixel Format Set + 0xB4, 1, 0x04, // ? + 0xA8, 1, 0x07, // Frame Rate Set + 0xB8, 1, 0x08, // ? + 0xE7, 1, 0x5A, // VREG_CTL + 0xE8, 1, 0x23, // VGH_SET + 0xE9, 1, 0x47, // VGL_SET + 0xEA, 1, 0x99, // VGH_VGL_CLK + 0xC6, 1, 0x30, // ? + 0xC7, 1, 0x1F, // ? + 0xF0, 14, 0x05, 0x1D, 0x51, 0x2F, 0x85, 0x2A, 0x11, 0x62, 0x00, 0x07, 0x07, 0x0F, 0x08, 0x1F, // SET_GAMMA1 + 0xF1, 14, 0x2E, 0x41, 0x62, 0x56, 0xA5, 0x3A, 0x3f, 0x60, 0x0F, 0x07, 0x0A, 0x18, 0x18, 0x1D, // SET_GAMMA2 + 0x11, 0 | DELAY, 120, + 0x29, 0 | DELAY, 10, // display on +}; + +void board_init(void) { + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct( + spi, + DEFAULT_SPI_BUS_SCK, // CLK + DEFAULT_SPI_BUS_MOSI, // MOSI + NULL, // MISO not connected + false // Not half-duplex + ); + + common_hal_busio_spi_never_reset(spi); + + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + CIRCUITPY_BOARD_LCD_DC, // DC + CIRCUITPY_BOARD_LCD_CS, // CS + CIRCUITPY_BOARD_LCD_RESET, // RST + 80000000, // 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, + 128, // width (after rotation) + 128, // height (after rotation) + 0, // column start + 0, // row start + 0, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + CIRCUITPY_BOARD_LCD_BACKLIGHT, // backlight pin + 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 + ); +} + +void reset_board(void) { +} diff --git a/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.h b/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.h new file mode 100644 index 0000000000000..ce5d015db5867 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.h @@ -0,0 +1,27 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "TinyCircuits Thumby Color" +#define MICROPY_HW_MCU_NAME "rp2350" + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO9) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO8) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = DEFAULT_I2C_BUS_SCL, .sda = DEFAULT_I2C_BUS_SDA}} + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) + +#define CIRCUITPY_BOARD_LCD_DC (&pin_GPIO16) +#define CIRCUITPY_BOARD_LCD_CS (&pin_GPIO17) +#define CIRCUITPY_BOARD_LCD_RESET (&pin_GPIO11) +#define CIRCUITPY_BOARD_LCD_BACKLIGHT (&pin_GPIO20) + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = DEFAULT_SPI_BUS_SCK, .mosi = DEFAULT_SPI_BUS_MOSI, .miso = NULL}} diff --git a/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.mk b/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.mk new file mode 100644 index 0000000000000..ed1255e2b96ed --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.mk @@ -0,0 +1,15 @@ +USB_VID = 0x1D6B +USB_PID = 0x0003 +USB_PRODUCT = "Thumby Color" +USB_MANUFACTURER = "TinyCircuits" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +CIRCUITPY_STAGE = 1 +CIRCUITPY_AUDIOIO = 1 +CIRCUITPY_AUDIOPWMIO = 1 +CIRCUITPY_KEYPAD = 1 diff --git a/ports/raspberrypi/boards/tinycircuits_thumby_color/pico-sdk-configboard.h b/ports/raspberrypi/boards/tinycircuits_thumby_color/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby_color/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/tinycircuits_thumby_color/pins.c b/ports/raspberrypi/boards/tinycircuits_thumby_color/pins.c new file mode 100644 index 0000000000000..d0e63512d7ab6 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby_color/pins.c @@ -0,0 +1,58 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Buttons + { MP_ROM_QSTR(MP_QSTR_BUTTON_UP), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_LEFT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_DOWN), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_RIGHT), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_A), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_B), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_BUMPER_LEFT), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_BUMPER_RIGHT), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_MENU), MP_ROM_PTR(&pin_GPIO26) }, + + // LED + { MP_ROM_QSTR(MP_QSTR_LED_R), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_GPIO12) }, + + // Rumble + { MP_ROM_QSTR(MP_QSTR_RUMBLE), MP_ROM_PTR(&pin_GPIO5) }, + + // Mono PWM Speaker + { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_SPEAKER_ENABLE), MP_ROM_PTR(&pin_GPIO20) }, + + // 0.85 inch TFT GC9107 + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(CIRCUITPY_BOARD_LCD_CS) }, + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(CIRCUITPY_BOARD_LCD_DC) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RESET), MP_ROM_PTR(CIRCUITPY_BOARD_LCD_RESET) }, + { MP_ROM_QSTR(MP_QSTR_LCD_BACKLIGHT), MP_ROM_PTR(CIRCUITPY_BOARD_LCD_BACKLIGHT) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SCK), MP_ROM_PTR(DEFAULT_SPI_BUS_SCK) }, + { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(DEFAULT_SPI_BUS_MOSI) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SPI), MP_ROM_PTR(&board_spi_obj) }, + + // RTC I2C + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(DEFAULT_I2C_BUS_SDA) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(DEFAULT_I2C_BUS_SCL) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + // Power pins + { MP_ROM_QSTR(MP_QSTR_CHARGE_STAT), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);