Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3929a84

Browse files
committed
adds lvgl c api
1 parent941a164 commit3929a84

File tree

11 files changed

+3729
-278
lines changed

11 files changed

+3729
-278
lines changed

‎ext_mod/lcd_bus/esp32_include/spi_bus.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,4 @@
3737

3838
externconstmp_obj_type_tmp_lcd_spi_bus_type;
3939
#endif/* _ESP32_SPI_BUS_H_ */
40+

‎ext_mod/lcd_bus/esp32_src/i2c_bus.c‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,9 @@ STATIC mp_obj_t mp_lcd_i2c_bus_make_new(const mp_obj_type_t *type, size_t n_args
9494
self->panel_io_config.flags.dc_low_on_data= (unsignedint)args[ARG_dc_low_on_data].u_bool;
9595
self->panel_io_config.flags.disable_control_phase= (unsignedint)args[ARG_disable_control_phase].u_bool;
9696

97-
self->panel_io_handle.del=i2c_del;
98-
self->panel_io_handle.init=i2c_init;
99-
self->panel_io_handle.get_lane_count=i2c_get_lane_count;
97+
self->panel_io_handle.del=&i2c_del;
98+
self->panel_io_handle.init=&i2c_init;
99+
self->panel_io_handle.get_lane_count=&i2c_get_lane_count;
100100

101101
returnMP_OBJ_FROM_PTR(self);
102102
}

‎ext_mod/lcd_bus/esp32_src/i80_bus.c‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@
142142
self->panel_io_config.cs_gpio_num= (int)args[ARG_cs].u_int;
143143
self->panel_io_config.pclk_hz= (uint32_t)args[ARG_freq].u_int;
144144
self->panel_io_config.trans_queue_depth=1;
145-
self->panel_io_config.on_color_trans_done=bus_trans_done_cb;
145+
self->panel_io_config.on_color_trans_done=&bus_trans_done_cb;
146146
self->panel_io_config.user_ctx=self;
147147
self->panel_io_config.lcd_cmd_bits= (int)args[ARG_cmd_bits].u_int;
148148
self->panel_io_config.lcd_param_bits= (int)args[ARG_param_bits].u_int;
@@ -156,9 +156,9 @@
156156
self->panel_io_config.flags.pclk_active_neg= (unsignedint)args[ARG_pclk_active_low].u_bool;
157157
self->panel_io_config.flags.pclk_idle_low= (unsignedint)args[ARG_pclk_idle_low].u_bool;
158158

159-
self->panel_io_handle.init=i80_init;
160-
self->panel_io_handle.del=i80_del;
161-
self->panel_io_handle.get_lane_count=i80_get_lane_count;
159+
self->panel_io_handle.init=&i80_init;
160+
self->panel_io_handle.del=&i80_del;
161+
self->panel_io_handle.get_lane_count=&i80_get_lane_count;
162162

163163
returnMP_OBJ_FROM_PTR(self);
164164
}

‎ext_mod/lcd_bus/esp32_src/rgb_bus.c‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,14 +210,14 @@
210210

211211
self->panel_io_config.data_width= (size_t)i;
212212

213-
self->panel_io_handle.get_lane_count=rgb_get_lane_count;
214-
self->panel_io_handle.del=rgb_del;
215-
self->panel_io_handle.rx_param=rgb_rx_param;
216-
self->panel_io_handle.tx_param=rgb_tx_param;
217-
self->panel_io_handle.tx_color=rgb_tx_color;
218-
self->panel_io_handle.allocate_framebuffer=rgb_allocate_framebuffer;
219-
self->panel_io_handle.free_framebuffer=rgb_free_framebuffer;
220-
self->panel_io_handle.init=rgb_init;
213+
self->panel_io_handle.get_lane_count=&rgb_get_lane_count;
214+
self->panel_io_handle.del=&rgb_del;
215+
self->panel_io_handle.rx_param=&rgb_rx_param;
216+
self->panel_io_handle.tx_param=&rgb_tx_param;
217+
self->panel_io_handle.tx_color=&rgb_tx_color;
218+
self->panel_io_handle.allocate_framebuffer=&rgb_allocate_framebuffer;
219+
self->panel_io_handle.free_framebuffer=&rgb_free_framebuffer;
220+
self->panel_io_handle.init=&rgb_init;
221221

222222
returnMP_OBJ_FROM_PTR(self);
223223
}

‎ext_mod/lcd_bus/esp32_src/spi_bus.c‎

Lines changed: 27 additions & 255 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ STATIC mp_obj_t mp_lcd_spi_bus_make_new(const mp_obj_type_t *type, size_t n_args
3939
ARG_cs,
4040
ARG_wp,
4141
ARG_hd,
42-
ARG_quad_spi,
43-
ARG_tx_only,
4442
ARG_cmd_bits,
4543
ARG_param_bits,
4644
ARG_dc_low_on_data,
@@ -50,28 +48,16 @@ STATIC mp_obj_t mp_lcd_spi_bus_make_new(const mp_obj_type_t *type, size_t n_args
5048
ARG_spi_mode
5149
};
5250

53-
/*
54-
* The required parameters are required to keep the API consistant.
55-
* This is done for portability reasons.
56-
* You can set the required values in a manner that will ttrigger
57-
* an automatic setup procedure
58-
* host: -1 if mosi != -1 and sclk != -1
59-
* mosi -1 & sclk -1: if host != -1
60-
* freq: -1
61-
*/
62-
6351
constmp_arg_tmake_new_args[]= {
6452
{MP_QSTR_dc,MP_ARG_OBJ |MP_ARG_KW_ONLY |MP_ARG_REQUIRED },
6553
{MP_QSTR_host,MP_ARG_INT |MP_ARG_KW_ONLY |MP_ARG_REQUIRED },
6654
{MP_QSTR_sclk,MP_ARG_INT |MP_ARG_KW_ONLY |MP_ARG_REQUIRED },
6755
{MP_QSTR_freq,MP_ARG_INT |MP_ARG_KW_ONLY |MP_ARG_REQUIRED },
6856
{MP_QSTR_mosi,MP_ARG_INT |MP_ARG_KW_ONLY |MP_ARG_REQUIRED },
69-
{MP_QSTR_miso,MP_ARG_INT |MP_ARG_KW_ONLY, { .u_int=-1 } },
57+
{MP_QSTR_miso,MP_ARG_INT |MP_ARG_KW_ONLY |MP_ARG_REQUIRED },
7058
{MP_QSTR_cs,MP_ARG_INT |MP_ARG_KW_ONLY, { .u_int=-1 } },
7159
{MP_QSTR_wp,MP_ARG_INT |MP_ARG_KW_ONLY, { .u_int=-1 } },
7260
{MP_QSTR_hd,MP_ARG_INT |MP_ARG_KW_ONLY, { .u_int=-1 } },
73-
{MP_QSTR_quad_spi,MP_ARG_BOOL |MP_ARG_KW_ONLY, { .u_bool= false } },
74-
{MP_QSTR_tx_only,MP_ARG_BOOL |MP_ARG_KW_ONLY, { .u_bool= false } },
7561
{MP_QSTR_cmd_bits,MP_ARG_INT |MP_ARG_KW_ONLY, { .u_int=8 } },
7662
{MP_QSTR_param_bits,MP_ARG_INT |MP_ARG_KW_ONLY, { .u_int=8 } },
7763
{MP_QSTR_dc_low_on_data,MP_ARG_BOOL |MP_ARG_KW_ONLY, { .u_bool= false } },
@@ -95,244 +81,30 @@ STATIC mp_obj_t mp_lcd_spi_bus_make_new(const mp_obj_type_t *type, size_t n_args
9581
mp_lcd_spi_bus_obj_t*self=m_new_obj(mp_lcd_spi_bus_obj_t);
9682
self->base.type=&mp_lcd_spi_bus_type;
9783

98-
uint32_tflags=SPICOMMON_BUSFLAG_MASTER;
99-
intdc= (int)args[ARG_dc].u_int;
100-
inthost= (int)args[ARG_host].u_int;
101-
intmosi= (int)args[ARG_mosi].u_int;
102-
intmiso= (int)args[ARG_miso].u_int;
103-
intsclk= (int)args[ARG_sclk].u_int;
104-
intcs= (int)args[ARG_cs].u_int;
105-
intfreq= (int)args[ARG_freq].u_int;
106-
intwp= (int)args[ARG_wp].u_int;
107-
inthd= (int)args[ARG_hd].u_int;
108-
10984
if ((args[ARG_spi_mode].u_int>3)|| (args[ARG_spi_mode].u_int<0)) {
11085
mp_raise_msg_varg(&mp_type_ValueError,MP_ERROR_TEXT("invalid spi mode (%d)"),args[ARG_spi_mode].u_int);
11186
}
11287

113-
if ((mosi==-1)&& (miso==-1)&& (sclk==-1)) {
114-
if (host==0) {
115-
#ifdefSPI_IOMUX_PIN_NUM_MISO
116-
sclk=SPI_IOMUX_PIN_NUM_CLK;
117-
mosi=SPI_IOMUX_PIN_NUM_MOSI;
118-
119-
if (!args[ARG_tx_only].u_bool) {
120-
miso=SPI_IOMUX_PIN_NUM_MISO;
121-
}
122-
if (cs==-1) {
123-
cs=SPI_IOMUX_PIN_NUM_CS;
124-
}
125-
if (args[ARG_quad_spi].u_bool) {
126-
if (wp==-1) {
127-
wp=SPI_IOMUX_PIN_NUM_WP;
128-
}
129-
if (hd==-1) {
130-
hd=SPI_IOMUX_PIN_NUM_HD;
131-
}
132-
}
133-
#else
134-
mp_raise_msg(&mp_type_ValueError,MP_ERROR_TEXT("host 0 is not available for this board"));
135-
#endif
136-
}elseif (host==1) {
137-
#ifdefSPI2_IOMUX_PIN_NUM_MISO
138-
sclk=SPI2_IOMUX_PIN_NUM_CLK;
139-
mosi=SPI2_IOMUX_PIN_NUM_MOSI;
140-
141-
if (!args[ARG_tx_only].u_bool) {
142-
miso=SPI2_IOMUX_PIN_NUM_MISO;
143-
}
144-
if (cs==-1) {
145-
cs=SPI2_IOMUX_PIN_NUM_CS;
146-
}
147-
if (args[ARG_quad_spi].u_bool) {
148-
if (wp==-1) {
149-
wp=SPI2_IOMUX_PIN_NUM_WP;
150-
}
151-
if (hd==-1) {
152-
hd=SPI2_IOMUX_PIN_NUM_HD;
153-
}
154-
}
155-
#else
156-
mp_raise_msg(&mp_type_ValueError,MP_ERROR_TEXT("host 1 is not available for this board"));
157-
#endif
158-
159-
}elseif (host==2) {
160-
#ifdefSPI3_IOMUX_PIN_NUM_MISO
161-
sclk=SPI3_IOMUX_PIN_NUM_CLK;
162-
mosi=SPI3_IOMUX_PIN_NUM_MOSI;
163-
164-
if (!args[ARG_tx_only].u_bool) {
165-
miso=SPI3_IOMUX_PIN_NUM_MISO;
166-
}
167-
if (cs==-1) {
168-
cs=SPI3_IOMUX_PIN_NUM_CS;
169-
}
170-
if (args[ARG_quad_spi].u_bool) {
171-
if (wp==-1) {
172-
wp=SPI3_IOMUX_PIN_NUM_WP;
173-
}
174-
if (hd==-1) {
175-
hd=SPI3_IOMUX_PIN_NUM_HD;
176-
}
177-
}
178-
#else
179-
mp_raise_msg(&mp_type_ValueError,MP_ERROR_TEXT("host 2 is not available for this board"));
180-
#endif
181-
}else {
182-
mp_raise_msg_varg(&mp_type_ValueError,MP_ERROR_TEXT("invalid spi host (%d)"),host);
183-
}
184-
}elseif (host==-1) {
185-
#ifdefSPI_IOMUX_PIN_NUM_MISO
186-
if (
187-
(mosi==SPI_IOMUX_PIN_NUM_MOSI)&&
188-
(sclk==SPI_IOMUX_PIN_NUM_CLK)&&
189-
(((args[ARG_tx_only].u_bool)&& (miso==-1))|| ((!args[ARG_tx_only].u_bool)&& (miso==SPI_IOMUX_PIN_NUM_MISO)))&&
190-
(
191-
((args[ARG_quad_spi].u_bool)&& (wp==SPI_IOMUX_PIN_NUM_WP)&& (hd==SPI_IOMUX_PIN_NUM_HD))||
192-
((!args[ARG_quad_spi].u_bool)&& (wp==-1)&& (hd==-1))
193-
)&&
194-
((cs==-1)|| (cs==SPI_IOMUX_PIN_NUM_CS))
195-
) {
196-
host=0;
197-
}else {
198-
mp_raise_msg(&mp_type_ValueError,MP_ERROR_TEXT("unable to set host"));
199-
}
200-
#endif
201-
202-
#ifdefSPI2_IOMUX_PIN_NUM_MISO
203-
if (
204-
(mosi==SPI2_IOMUX_PIN_NUM_MOSI)&&
205-
(sclk==SPI2_IOMUX_PIN_NUM_CLK)&&
206-
(((args[ARG_tx_only].u_bool)&& (miso==-1))|| ((!args[ARG_tx_only].u_bool)&& (miso==SPI2_IOMUX_PIN_NUM_MISO)))&&
207-
(
208-
((args[ARG_quad_spi].u_bool)&& (wp==SPI2_IOMUX_PIN_NUM_WP)&& (hd==SPI2_IOMUX_PIN_NUM_HD))||
209-
((!args[ARG_quad_spi].u_bool)&& (wp==-1)&& (hd==-1))
210-
)&&
211-
((cs==-1)|| (cs==SPI2_IOMUX_PIN_NUM_CS))
212-
) {
213-
host=1;
214-
}else {
215-
mp_raise_msg(&mp_type_ValueError,MP_ERROR_TEXT("unable to set host"));
216-
}
217-
#endif
218-
219-
#ifdefSPI3_IOMUX_PIN_NUM_MISO
220-
if (
221-
(mosi==SPI3_IOMUX_PIN_NUM_MOSI)&&
222-
(sclk==SPI3_IOMUX_PIN_NUM_CLK)&&
223-
(((args[ARG_tx_only].u_bool)&& (miso==-1))|| ((!args[ARG_tx_only].u_bool)&& (miso==SPI3_IOMUX_PIN_NUM_MISO)))&&
224-
(
225-
((args[ARG_quad_spi].u_bool)&& (wp==SPI3_IOMUX_PIN_NUM_WP)&& (hd==SPI3_IOMUX_PIN_NUM_HD))||
226-
((!args[ARG_quad_spi].u_bool)&& (wp==-1)&& (hd==-1))
227-
)&&
228-
((cs==-1)|| (cs==SPI3_IOMUX_PIN_NUM_CS))
229-
) {
230-
host=2;
231-
}else {
232-
mp_raise_msg(&mp_type_ValueError,MP_ERROR_TEXT("unable to set host"));
233-
}
234-
#endif
88+
uint32_tflags=SPICOMMON_BUSFLAG_MASTER;
23589

236-
}
90+
intwp= (int)args[ARG_wp].u_int;
91+
inthd= (int)args[ARG_hd].u_int;
23792

238-
if (!args[ARG_quad_spi].u_bool) {
239-
wp=-1;
240-
hd=-1;
241-
}else {
93+
if (wp!=-1&&hd!=-1) {
24294
flags |=SPICOMMON_BUSFLAG_QUAD;
243-
}
244-
245-
if (args[ARG_tx_only].u_bool) {
246-
miso=-1;
247-
}
248-
249-
if (host==0) {
250-
#ifdefSPI_IOMUX_PIN_NUM_MISO
251-
if (
252-
(mosi==SPI_IOMUX_PIN_NUM_MOSI)&&
253-
(sclk==SPI_IOMUX_PIN_NUM_CLK)&&
254-
(((args[ARG_tx_only].u_bool)&& (miso==-1))|| ((!args[ARG_tx_only].u_bool)&& (miso==SPI_IOMUX_PIN_NUM_MISO)))&&
255-
(
256-
((args[ARG_quad_spi].u_bool)&& (wp==SPI_IOMUX_PIN_NUM_WP)&& (hd==SPI_IOMUX_PIN_NUM_HD))||
257-
((!args[ARG_quad_spi].u_bool)&& (wp==-1)&& (hd==-1))
258-
)&&
259-
((cs==-1)|| (cs==SPI_IOMUX_PIN_NUM_CS))
260-
) {
261-
if (freq==-1) {
262-
freq=80000000;
263-
}
264-
flags |=SPICOMMON_BUSFLAG_IOMUX_PINS;
265-
}else {
266-
if (freq==-1) {
267-
freq=26600000;
268-
}
269-
flags |=SPICOMMON_BUSFLAG_GPIO_PINS;
270-
}
271-
#else
272-
mp_raise_msg(&mp_type_ValueError,MP_ERROR_TEXT("spi host 0 is not supported by this board"));
273-
#endif
274-
}elseif (host==1) {
275-
#ifdefSPI2_IOMUX_PIN_NUM_MISO
276-
if (
277-
(mosi==SPI2_IOMUX_PIN_NUM_MOSI)&&
278-
(sclk==SPI2_IOMUX_PIN_NUM_CLK)&&
279-
(((args[ARG_tx_only].u_bool)&& (miso==-1))|| ((!args[ARG_tx_only].u_bool)&& (miso==SPI2_IOMUX_PIN_NUM_MISO)))&&
280-
(
281-
((args[ARG_quad_spi].u_bool)&& (wp==SPI2_IOMUX_PIN_NUM_WP)&& (hd==SPI2_IOMUX_PIN_NUM_HD))||
282-
((!args[ARG_quad_spi].u_bool)&& (wp==-1)&& (hd==-1))
283-
)&&
284-
((cs==-1)|| (cs==SPI2_IOMUX_PIN_NUM_CS))
285-
) {
286-
if (freq==-1) {
287-
freq=80000000;
288-
}
289-
flags |=SPICOMMON_BUSFLAG_IOMUX_PINS;
290-
}else {
291-
if (freq==-1) {
292-
freq=26600000;
293-
}
294-
flags |=SPICOMMON_BUSFLAG_GPIO_PINS;
295-
}
296-
#else
297-
mp_raise_msg(&mp_type_ValueError,MP_ERROR_TEXT("spi host 1 is not supported by this board"));
298-
#endif
299-
}elseif (host==2) {
300-
#ifdefSPI3_IOMUX_PIN_NUM_MISO
301-
if (
302-
(mosi==SPI3_IOMUX_PIN_NUM_MOSI)&&
303-
(sclk==SPI3_IOMUX_PIN_NUM_CLK)&&
304-
(((args[ARG_tx_only].u_bool)&& (miso==-1))|| ((!args[ARG_tx_only].u_bool)&& (miso==SPI3_IOMUX_PIN_NUM_MISO)))&&
305-
(
306-
((args[ARG_quad_spi].u_bool)&& (wp==SPI3_IOMUX_PIN_NUM_WP)&& (hd==SPI3_IOMUX_PIN_NUM_HD))||
307-
((!args[ARG_quad_spi].u_bool)&& (wp==-1)&& (hd==-1))
308-
)&&
309-
((cs==-1)|| (cs==SPI3_IOMUX_PIN_NUM_CS))
310-
) {
311-
if (freq==-1) {
312-
freq=80000000;
313-
}
314-
flags |=SPICOMMON_BUSFLAG_IOMUX_PINS;
315-
}else {
316-
if (freq==-1) {
317-
freq=26600000;
318-
}
319-
flags |=SPICOMMON_BUSFLAG_GPIO_PINS;
320-
}
321-
#else
322-
mp_raise_msg(&mp_type_ValueError,MP_ERROR_TEXT("spi host 2 is not supported by this board"));
323-
#endif
32495
}else {
325-
mp_raise_msg_varg(&mp_type_ValueError,MP_ERROR_TEXT("invalid spi host (%d)"),host);
96+
wp=-1;
97+
hd=-1;
32698
}
32799

328100
self->callback=mp_const_none;
329101

330-
self->host=host;
331-
self->bus_handle= (esp_lcd_spi_bus_handle_t)((uint32_t)host);
102+
self->host=(int)args[ARG_host].u_int;
103+
self->bus_handle= (esp_lcd_spi_bus_handle_t)((uint32_t)self->host);
332104

333-
self->bus_config.sclk_io_num=sclk;
334-
self->bus_config.mosi_io_num=mosi;
335-
self->bus_config.miso_io_num=miso;
105+
self->bus_config.sclk_io_num=(int)args[ARG_sclk].u_int;
106+
self->bus_config.mosi_io_num=(int)args[ARG_mosi].u_int;
107+
self->bus_config.miso_io_num=(int)args[ARG_miso].u_int;
336108
self->bus_config.quadwp_io_num=wp;
337109
self->bus_config.quadhd_io_num=hd;
338110
self->bus_config.data4_io_num=-1;
@@ -341,24 +113,24 @@ STATIC mp_obj_t mp_lcd_spi_bus_make_new(const mp_obj_type_t *type, size_t n_args
341113
self->bus_config.data7_io_num=-1;
342114
self->bus_config.flags=flags;
343115

344-
self->panel_io_config.cs_gpio_num=cs;
345-
self->panel_io_config.dc_gpio_num=dc;
346-
self->panel_io_config.spi_mode=args[ARG_spi_mode].u_int;
347-
self->panel_io_config.pclk_hz=freq;
348-
self->panel_io_config.trans_queue_depth=1;
349-
self->panel_io_config.on_color_trans_done=bus_trans_done_cb;
116+
self->panel_io_config.cs_gpio_num=(int)args[ARG_cs].u_int;
117+
self->panel_io_config.dc_gpio_num=(int)args[ARG_dc].u_int;
118+
self->panel_io_config.spi_mode=(int)args[ARG_spi_mode].u_int;
119+
self->panel_io_config.pclk_hz=(unsignedint)args[ARG_freq].u_int;
120+
self->panel_io_config.trans_queue_depth=10;
121+
self->panel_io_config.on_color_trans_done=&bus_trans_done_cb;
350122
self->panel_io_config.user_ctx=self;
351-
self->panel_io_config.lcd_cmd_bits=args[ARG_cmd_bits].u_int;
352-
self->panel_io_config.lcd_param_bits=args[ARG_param_bits].u_int;
353-
self->panel_io_config.flags.dc_low_on_data=args[ARG_dc_low_on_data].u_bool;
354-
self->panel_io_config.flags.sio_mode=args[ARG_sio_mode].u_bool;
355-
self->panel_io_config.flags.lsb_first=args[ARG_lsb_first].u_bool;
356-
self->panel_io_config.flags.cs_high_active=args[ARG_cs_high_active].u_bool;
123+
self->panel_io_config.lcd_cmd_bits=(int)args[ARG_cmd_bits].u_int;
124+
self->panel_io_config.lcd_param_bits=(int)args[ARG_param_bits].u_int;
125+
self->panel_io_config.flags.dc_low_on_data=(unsignedint)args[ARG_dc_low_on_data].u_bool;
126+
self->panel_io_config.flags.sio_mode=(unsignedint)args[ARG_sio_mode].u_bool;
127+
self->panel_io_config.flags.lsb_first=(unsignedint)args[ARG_lsb_first].u_bool;
128+
self->panel_io_config.flags.cs_high_active=(unsignedint)args[ARG_cs_high_active].u_bool;
357129
self->panel_io_config.flags.octal_mode=0;
358130

359-
self->panel_io_handle.del=spi_del;
360-
self->panel_io_handle.init=spi_init;
361-
self->panel_io_handle.get_lane_count=spi_get_lane_count;
131+
self->panel_io_handle.del=&spi_del;
132+
self->panel_io_handle.init=&spi_init;
133+
self->panel_io_handle.get_lane_count=&spi_get_lane_count;
362134

363135
returnMP_OBJ_FROM_PTR(self);
364136
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp