Skip to content

Commit dab889d

Browse files
committed
add(board): add Pimoroni Explorer RP2350 (PIM720)
1 parent 57aec3a commit dab889d

File tree

5 files changed

+306
-0
lines changed

5 files changed

+306
-0
lines changed
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
4+
//
5+
// SPDX-License-Identifier: MIT
6+
7+
#include "supervisor/board.h"
8+
#include "mpconfigboard.h"
9+
#include "shared-bindings/microcontroller/Pin.h"
10+
#include "shared-bindings/paralleldisplaybus/ParallelBus.h"
11+
#include "shared-module/displayio/__init__.h"
12+
#include "shared-module/displayio/mipi_constants.h"
13+
#include "hardware/gpio.h"
14+
15+
// Display pins from Pimoroni Explorer parallel bus: {cs=27, dc=28, wr=30, rd=31, d0=32, bl=26}
16+
#define LCD_BACKLIGHT_PIN 26
17+
#define LCD_CS_PIN 27
18+
#define LCD_DC_PIN 28
19+
#define LCD_WR_PIN 30
20+
#define LCD_RD_PIN 31
21+
#define LCD_D0_PIN 32 // Data pins are GPIO32-39 (8 consecutive pins)
22+
23+
#define DELAY 0x80
24+
25+
// ST7789V display init sequence for 320x240 parallel bus
26+
// Based on Pimoroni's pimoroni-pico ST7789 driver configuration
27+
uint8_t display_init_sequence[] = {
28+
// Software reset
29+
0x01, 0 | DELAY, 150,
30+
// Sleep out
31+
0x11, 0 | DELAY, 255,
32+
// Tearing effect line on (frame sync)
33+
0x35, 1, 0x00,
34+
// COLMOD: 16-bit color (5-6-5 RGB)
35+
0x3A, 1, 0x55,
36+
// Porch control (PORCTRL)
37+
0xB2, 5, 0x0C, 0x0C, 0x00, 0x33, 0x33,
38+
// Gate control (GCTRL) - VGH=13.26V, VGL=-10.43V
39+
0xB7, 1, 0x35,
40+
// VCOM setting (VCOMS)
41+
0xBB, 1, 0x1F,
42+
// LCM control (LCMCTRL)
43+
0xC0, 1, 0x2C,
44+
// VDV and VRH command enable (VDVVRHEN)
45+
0xC2, 1, 0x01,
46+
// VRH set (VRHS)
47+
0xC3, 1, 0x12,
48+
// VDV set (VDVS)
49+
0xC4, 1, 0x20,
50+
// Frame rate control (FRCTRL2)
51+
0xC6, 1, 0x0F,
52+
// Power control 1 (PWCTRL1)
53+
0xD0, 2, 0xA4, 0xA1,
54+
// RAM control (RAMCTRL) - for proper endianness
55+
0xB0, 2, 0x00, 0xC0,
56+
// Positive gamma correction
57+
0xE0, 14, 0xD0, 0x08, 0x11, 0x08, 0x0C, 0x15, 0x39, 0x33, 0x50, 0x36, 0x13, 0x14, 0x29, 0x2D,
58+
// Negative gamma correction
59+
0xE1, 14, 0xD0, 0x08, 0x10, 0x08, 0x06, 0x06, 0x39, 0x44, 0x51, 0x0B, 0x16, 0x14, 0x2F, 0x31,
60+
// Inversion on
61+
0x21, 0,
62+
// Normal display mode on
63+
0x13, 0 | DELAY, 10,
64+
// MADCTL: MX=0, MY=1, MV=1, ML=1 (COL_ORDER | SWAP_XY | SCAN_ORDER) = 0x70
65+
// This configures the 320x240 display in landscape orientation
66+
0x36, 1, 0x70,
67+
// Display on
68+
0x29, 0 | DELAY, 100,
69+
};
70+
71+
static void display_init(void) {
72+
paralleldisplaybus_parallelbus_obj_t *bus = &allocate_display_bus()->parallel_bus;
73+
bus->base.type = &paralleldisplaybus_parallelbus_type;
74+
75+
common_hal_paralleldisplaybus_parallelbus_construct(bus,
76+
&pin_GPIO32, // Data0 (D0) - data pins are sequential GPIO32-39
77+
&pin_GPIO28, // Command/Data (DC)
78+
&pin_GPIO27, // Chip select (CS)
79+
&pin_GPIO30, // Write (WR)
80+
&pin_GPIO31, // Read (RD)
81+
NULL, // Reset (directly connected to board reset)
82+
15000000); // Frequency - ST7789 min clock cycle ~66ns = ~15MHz
83+
84+
busdisplay_busdisplay_obj_t *display = &allocate_display()->display;
85+
display->base.type = &busdisplay_busdisplay_type;
86+
87+
common_hal_busdisplay_busdisplay_construct(display,
88+
bus,
89+
320, // Width
90+
240, // Height
91+
0, // column start
92+
0, // row start
93+
0, // rotation
94+
16, // Color depth
95+
false, // grayscale
96+
false, // pixels_in_byte_share_row
97+
1, // bytes per cell
98+
false, // reverse_pixels_in_byte
99+
true, // reverse_pixels_in_word
100+
MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command
101+
MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command
102+
MIPI_COMMAND_WRITE_MEMORY_START, // write memory command
103+
display_init_sequence,
104+
sizeof(display_init_sequence),
105+
&pin_GPIO26, // Backlight pin (BL)
106+
NO_BRIGHTNESS_COMMAND,
107+
1.0f, // brightness
108+
false, // single_byte_bounds
109+
false, // data_as_commands
110+
true, // auto_refresh
111+
60, // native_frames_per_second
112+
true, // backlight_on_high
113+
false, // SH1107_addressing
114+
50000 // backlight pwm frequency
115+
);
116+
}
117+
118+
void board_init(void) {
119+
// Ensure backlight is on before display init
120+
board_reset_pin_number(LCD_BACKLIGHT_PIN);
121+
display_init();
122+
}
123+
124+
// Prevent the backlight pin from being reset, keeping display visible across soft resets
125+
bool board_reset_pin_number(uint8_t pin_number) {
126+
if (pin_number == LCD_BACKLIGHT_PIN) {
127+
// Keep backlight on - set high output without glitching
128+
gpio_put(pin_number, 1);
129+
gpio_set_dir(pin_number, GPIO_OUT);
130+
gpio_set_function(pin_number, GPIO_FUNC_SIO);
131+
return true;
132+
}
133+
return false;
134+
}
135+
136+
void reset_board(void) {
137+
// Keep backlight on during reset
138+
board_reset_pin_number(LCD_BACKLIGHT_PIN);
139+
}
140+
141+
void board_deinit(void) {
142+
// Backlight will be handled by board_reset_pin_number
143+
}
144+
145+
// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries
4+
//
5+
// SPDX-License-Identifier: MIT
6+
7+
#pragma once
8+
9+
#define MICROPY_HW_BOARD_NAME "Pimoroni Explorer"
10+
#define MICROPY_HW_MCU_NAME "rp2350b"
11+
12+
#define MICROPY_HW_LED_STATUS (&pin_GPIO25)
13+
14+
#define CIRCUITPY_BOARD_I2C (1)
15+
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO21, .sda = &pin_GPIO20}}
16+
17+
#define DEFAULT_UART_BUS_RX (&pin_GPIO1)
18+
#define DEFAULT_UART_BUS_TX (&pin_GPIO0)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
USB_VID = 0x2E8A
2+
USB_PID = 0x10C0
3+
USB_PRODUCT = "Explorer"
4+
USB_MANUFACTURER = "Pimoroni"
5+
6+
CHIP_VARIANT = RP2350
7+
CHIP_PACKAGE = B
8+
CHIP_FAMILY = rp2
9+
10+
EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ"
11+
12+
CIRCUITPY__EVE = 1
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
4+
//
5+
// SPDX-License-Identifier: MIT
6+
7+
// Put board-specific pico-sdk definitions here. This file must exist.
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// This file is part of the CircuitPython project: https://circuitpython.org
2+
//
3+
// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries
4+
//
5+
// SPDX-License-Identifier: MIT
6+
7+
#include "shared-bindings/board/__init__.h"
8+
#include "shared-module/displayio/__init__.h"
9+
10+
static const mp_rom_map_elem_t board_module_globals_table[] = {
11+
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
12+
13+
// User GPIOs (accent connector)
14+
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) },
15+
{ MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) },
16+
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) },
17+
{ MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) },
18+
{ MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) },
19+
{ MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) },
20+
{ MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) },
21+
{ MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) },
22+
23+
// Servo pins
24+
{ MP_ROM_QSTR(MP_QSTR_SERVO1), MP_ROM_PTR(&pin_GPIO9) },
25+
{ MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) },
26+
{ MP_ROM_QSTR(MP_QSTR_SERVO2), MP_ROM_PTR(&pin_GPIO8) },
27+
{ MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) },
28+
{ MP_ROM_QSTR(MP_QSTR_SERVO3), MP_ROM_PTR(&pin_GPIO7) },
29+
{ MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) },
30+
{ MP_ROM_QSTR(MP_QSTR_SERVO4), MP_ROM_PTR(&pin_GPIO6) },
31+
{ MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) },
32+
33+
// Audio
34+
{ MP_ROM_QSTR(MP_QSTR_AUDIO), MP_ROM_PTR(&pin_GPIO12) },
35+
{ MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) },
36+
{ MP_ROM_QSTR(MP_QSTR_AMP_EN), MP_ROM_PTR(&pin_GPIO13) },
37+
{ MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) },
38+
39+
// Buttons
40+
{ MP_ROM_QSTR(MP_QSTR_SW_C), MP_ROM_PTR(&pin_GPIO14) },
41+
{ MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) },
42+
{ MP_ROM_QSTR(MP_QSTR_SW_B), MP_ROM_PTR(&pin_GPIO15) },
43+
{ MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) },
44+
{ MP_ROM_QSTR(MP_QSTR_SW_A), MP_ROM_PTR(&pin_GPIO16) },
45+
{ MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) },
46+
{ MP_ROM_QSTR(MP_QSTR_SW_X), MP_ROM_PTR(&pin_GPIO17) },
47+
{ MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) },
48+
{ MP_ROM_QSTR(MP_QSTR_SW_Y), MP_ROM_PTR(&pin_GPIO18) },
49+
{ MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) },
50+
{ MP_ROM_QSTR(MP_QSTR_SW_Z), MP_ROM_PTR(&pin_GPIO19) },
51+
{ MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) },
52+
53+
// I2C
54+
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO20) },
55+
{ MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) },
56+
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO21) },
57+
{ MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) },
58+
59+
// User button
60+
{ MP_ROM_QSTR(MP_QSTR_SW_USER), MP_ROM_PTR(&pin_GPIO22) },
61+
{ MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) },
62+
63+
// LED?
64+
{ MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO25) },
65+
{ MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) },
66+
67+
// Display parallel bus pins (ST7789V 320x240)
68+
// Pins from Pimoroni: {cs=27, dc=28, wr=30, rd=31, d0=32, bl=26}
69+
{ MP_ROM_QSTR(MP_QSTR_LCD_BL), MP_ROM_PTR(&pin_GPIO26) },
70+
{ MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) },
71+
{ MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO27) },
72+
{ MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) },
73+
{ MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO28) },
74+
{ MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) },
75+
{ MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) },
76+
{ MP_ROM_QSTR(MP_QSTR_LCD_WR), MP_ROM_PTR(&pin_GPIO30) },
77+
{ MP_ROM_QSTR(MP_QSTR_GP30), MP_ROM_PTR(&pin_GPIO30) },
78+
{ MP_ROM_QSTR(MP_QSTR_LCD_RD), MP_ROM_PTR(&pin_GPIO31) },
79+
{ MP_ROM_QSTR(MP_QSTR_GP31), MP_ROM_PTR(&pin_GPIO31) },
80+
{ MP_ROM_QSTR(MP_QSTR_LCD_D0), MP_ROM_PTR(&pin_GPIO32) },
81+
{ MP_ROM_QSTR(MP_QSTR_GP32), MP_ROM_PTR(&pin_GPIO32) },
82+
{ MP_ROM_QSTR(MP_QSTR_LCD_D1), MP_ROM_PTR(&pin_GPIO33) },
83+
{ MP_ROM_QSTR(MP_QSTR_GP33), MP_ROM_PTR(&pin_GPIO33) },
84+
{ MP_ROM_QSTR(MP_QSTR_LCD_D2), MP_ROM_PTR(&pin_GPIO34) },
85+
{ MP_ROM_QSTR(MP_QSTR_GP34), MP_ROM_PTR(&pin_GPIO34) },
86+
{ MP_ROM_QSTR(MP_QSTR_LCD_D3), MP_ROM_PTR(&pin_GPIO35) },
87+
{ MP_ROM_QSTR(MP_QSTR_GP35), MP_ROM_PTR(&pin_GPIO35) },
88+
{ MP_ROM_QSTR(MP_QSTR_LCD_D4), MP_ROM_PTR(&pin_GPIO36) },
89+
{ MP_ROM_QSTR(MP_QSTR_GP36), MP_ROM_PTR(&pin_GPIO36) },
90+
{ MP_ROM_QSTR(MP_QSTR_LCD_D5), MP_ROM_PTR(&pin_GPIO37) },
91+
{ MP_ROM_QSTR(MP_QSTR_GP37), MP_ROM_PTR(&pin_GPIO37) },
92+
{ MP_ROM_QSTR(MP_QSTR_LCD_D6), MP_ROM_PTR(&pin_GPIO38) },
93+
{ MP_ROM_QSTR(MP_QSTR_GP38), MP_ROM_PTR(&pin_GPIO38) },
94+
{ MP_ROM_QSTR(MP_QSTR_LCD_D7), MP_ROM_PTR(&pin_GPIO39) },
95+
{ MP_ROM_QSTR(MP_QSTR_GP39), MP_ROM_PTR(&pin_GPIO39) },
96+
97+
// ADC pins (RP2350B extended GPIOs)
98+
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO40) },
99+
{ MP_ROM_QSTR(MP_QSTR_ADC0), MP_ROM_PTR(&pin_GPIO40) },
100+
{ MP_ROM_QSTR(MP_QSTR_GP40), MP_ROM_PTR(&pin_GPIO40) },
101+
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO41) },
102+
{ MP_ROM_QSTR(MP_QSTR_ADC1), MP_ROM_PTR(&pin_GPIO41) },
103+
{ MP_ROM_QSTR(MP_QSTR_GP41), MP_ROM_PTR(&pin_GPIO41) },
104+
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO42) },
105+
{ MP_ROM_QSTR(MP_QSTR_ADC2), MP_ROM_PTR(&pin_GPIO42) },
106+
{ MP_ROM_QSTR(MP_QSTR_GP42), MP_ROM_PTR(&pin_GPIO42) },
107+
{ MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO43) },
108+
{ MP_ROM_QSTR(MP_QSTR_ADC3), MP_ROM_PTR(&pin_GPIO43) },
109+
{ MP_ROM_QSTR(MP_QSTR_GP43), MP_ROM_PTR(&pin_GPIO43) },
110+
{ MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO44) },
111+
{ MP_ROM_QSTR(MP_QSTR_ADC4), MP_ROM_PTR(&pin_GPIO44) },
112+
{ MP_ROM_QSTR(MP_QSTR_GP44), MP_ROM_PTR(&pin_GPIO44) },
113+
{ MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO45) },
114+
{ MP_ROM_QSTR(MP_QSTR_ADC5), MP_ROM_PTR(&pin_GPIO45) },
115+
{ MP_ROM_QSTR(MP_QSTR_GP45), MP_ROM_PTR(&pin_GPIO45) },
116+
117+
// I2C object
118+
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
119+
{ MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) },
120+
121+
// Display object
122+
{ MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) },
123+
};
124+
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

0 commit comments

Comments
 (0)