Skip to content

Commit 2796fe8

Browse files
committed
rp2pio: Support PIOv1 features
This is needed to fully support the .mov_status and .fifo directives, as well as checking for PIO version compatibility between program & runtime hardware.
1 parent 561578f commit 2796fe8

File tree

12 files changed

+134
-26
lines changed

12 files changed

+134
-26
lines changed

ports/raspberrypi/bindings/rp2pio/StateMachine.c

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
#include "py/runtime.h"
2323

2424

25+
//| FifoType = Literal["auto", "txrx", "tx", "rx", "txput", "txget", "putget"]
26+
//| FifoType_piov0 = Literal["auto", "txrx", "tx", "rx"]
27+
//| MovStatusType = Literal["txfifo", "rxfifo", "irq"]
28+
//| MovStatusType_piov0 = Literal["txfifo"]
29+
//|
2530
//| class StateMachine:
2631
//| """A single PIO StateMachine
2732
//|
@@ -41,6 +46,7 @@
4146
//| program: ReadableBuffer,
4247
//| frequency: int,
4348
//| *,
49+
//| pio_version: int = 0,
4450
//| may_exec: Optional[ReadableBuffer] = None,
4551
//| init: Optional[ReadableBuffer] = None,
4652
//| first_out_pin: Optional[microcontroller.Pin] = None,
@@ -74,13 +80,17 @@
7480
//| wrap_target: int = 0,
7581
//| wrap: int = -1,
7682
//| offset: int = -1,
83+
//| fifo_type: FifoType = "auto",
84+
//| mov_status_type: MovStatusType = "txfifo",
85+
//| mov_status_n: int = 0,
7786
//| ) -> None:
7887
//| """Construct a StateMachine object on the given pins with the given program.
7988
//|
8089
//| :param ReadableBuffer program: the program to run with the state machine
8190
//| :param int frequency: the target clock frequency of the state machine. Actual may be less. Use 0 for system clock speed.
8291
//| :param ReadableBuffer init: a program to run once at start up. This is run after program
8392
//| is started so instructions may be intermingled
93+
//| :param int pio_version: The version of the PIO peripheral required by the program. The constructor will raise an error if the actual hardware is not compatible with this program version.
8494
//| :param ReadableBuffer may_exec: Instructions that may be executed via `StateMachine.run` calls.
8595
//| Some elements of the `StateMachine`'s configuration are inferred from the instructions used;
8696
//| for instance, if there is no ``in`` or ``push`` instruction, then the `StateMachine` is configured without a receive FIFO.
@@ -134,12 +144,25 @@
134144
//| :param int offset: A specific offset in the state machine's program memory where the program must be loaded.
135145
//| The default value, -1, allows the program to be loaded at any offset.
136146
//| This is appropriate for most programs.
147+
//| :param FifoType fifo_type: How the program accessess the FIFOs. PIO version 0 only supports a subset of values.
148+
//| :param MovStatusType mov_status_type: What condition the ``mov status`` instruction checks. PIO version 0 only supports a subset of values.
149+
//| :param MovStatusType mov_status_n: The FIFO depth or IRQ the ``mov status`` instruction checks for. For ``mov_status irq`` this includes the encoding of the ``next``/``prev`` selection bits.
137150
//| """
138151
//| ...
139152

153+
static int one_of(qstr_short_t what, mp_obj_t arg, size_t n_options, const qstr_short_t options[], const int values[]) {
154+
for (size_t i = 0; i < n_options; i++) {
155+
mp_obj_t option_str = MP_OBJ_NEW_QSTR(options[i]);
156+
if (mp_obj_equal(arg, option_str)) {
157+
return values[i];
158+
}
159+
}
160+
mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), what);
161+
}
162+
140163
static mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
141164
rp2pio_statemachine_obj_t *self = mp_obj_malloc(rp2pio_statemachine_obj_t, &rp2pio_statemachine_type);
142-
enum { ARG_program, ARG_frequency, ARG_init, ARG_may_exec,
165+
enum { ARG_program, ARG_frequency, ARG_init, ARG_pio_version, ARG_may_exec,
143166
ARG_first_out_pin, ARG_out_pin_count, ARG_initial_out_pin_state, ARG_initial_out_pin_direction,
144167
ARG_first_in_pin, ARG_in_pin_count,
145168
ARG_pull_in_pin_up, ARG_pull_in_pin_down,
@@ -154,11 +177,15 @@ static mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
154177
ARG_user_interruptible,
155178
ARG_wrap_target,
156179
ARG_wrap,
157-
ARG_offset, };
180+
ARG_offset,
181+
ARG_fifo_type,
182+
ARG_mov_status_type,
183+
ARG_mov_status_n, };
158184
static const mp_arg_t allowed_args[] = {
159185
{ MP_QSTR_program, MP_ARG_REQUIRED | MP_ARG_OBJ },
160186
{ MP_QSTR_frequency, MP_ARG_REQUIRED | MP_ARG_INT },
161187
{ MP_QSTR_init, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
188+
{ MP_QSTR_pio_version, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
162189
{ MP_QSTR_may_exec, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
163190

164191
{ MP_QSTR_first_out_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
@@ -198,11 +225,18 @@ static mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
198225

199226
{ MP_QSTR_wrap_target, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
200227
{ MP_QSTR_wrap, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
201-
{ MP_QSTR_offset, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
228+
229+
{ MP_QSTR_offset, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PIO_ANY_OFFSET} },
230+
231+
{ MP_QSTR_fifo_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_obj = MP_ROM_QSTR(MP_QSTR_rxtx) } },
232+
{ MP_QSTR_mov_status_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_obj = MP_ROM_QSTR(MP_QSTR_txfifo) } },
233+
{ MP_QSTR_mov_status_n, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
202234
};
203235
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
204236
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
205237

238+
(void)mp_arg_validate_int_max(args[ARG_pio_version].u_int, PICO_PIO_VERSION, MP_QSTR_out_pin_count);
239+
206240
mp_buffer_info_t bufinfo;
207241
mp_get_buffer_raise(args[ARG_program].u_obj, &bufinfo, MP_BUFFER_READ);
208242

@@ -254,6 +288,30 @@ static mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
254288
int wrap = args[ARG_wrap].u_int;
255289
int wrap_target = args[ARG_wrap_target].u_int;
256290

291+
const qstr_short_t fifo_alternatives[] = { MP_QSTR_auto, MP_QSTR_txrx, MP_QSTR_tx, MP_QSTR_rx,
292+
#if PICO_PIO_VERSION > 0
293+
MP_QSTR_txput, MP_QSTR_txget, MP_QSTR_putget
294+
#endif
295+
};
296+
const int fifo_values[] = { PIO_FIFO_JOIN_AUTO, PIO_FIFO_JOIN_NONE, PIO_FIFO_JOIN_TX, PIO_FIFO_JOIN_RX,
297+
#if PICO_PIO_VERSION > 0
298+
PIO_FIFO_JOIN_TXPUT, PIO_FIFO_JOIN_PUTGET
299+
#endif
300+
};
301+
int fifo_type = one_of(MP_QSTR_fifo_type, args[ARG_fifo_type].u_obj, MP_ARRAY_SIZE(fifo_alternatives), fifo_alternatives, fifo_values);
302+
303+
const qstr_short_t mov_status_alternatives[] = { MP_QSTR_txfifo, MP_QSTR_rxfifo,
304+
#if PICO_PIO_VERSION > 0
305+
MP_QSTR_IRQ
306+
#endif
307+
};
308+
const int mov_status_values[] = { STATUS_TX_LESSTHAN, STATUS_RX_LESSTHAN,
309+
#if PICO_PIO_VERSION > 0
310+
STATUS_IRQ_SET
311+
#endif
312+
};
313+
int mov_status_type = one_of(MP_QSTR_mov_status_type, args[ARG_mov_status_type].u_obj, MP_ARRAY_SIZE(mov_status_alternatives), mov_status_alternatives, mov_status_values);
314+
257315
common_hal_rp2pio_statemachine_construct(self,
258316
bufinfo.buf, bufinfo.len / 2,
259317
args[ARG_frequency].u_int,
@@ -271,7 +329,10 @@ static mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
271329
args[ARG_wait_for_txstall].u_bool,
272330
args[ARG_auto_push].u_bool, push_threshold, args[ARG_in_shift_right].u_bool,
273331
args[ARG_user_interruptible].u_bool,
274-
wrap_target, wrap, args[ARG_offset].u_int);
332+
wrap_target, wrap, args[ARG_offset].u_int,
333+
fifo_type,
334+
mov_status_type, args[ARG_mov_status_n].u_int
335+
);
275336
return MP_OBJ_FROM_PTR(self);
276337
}
277338

ports/raspberrypi/bindings/rp2pio/StateMachine.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
3434
bool auto_push, uint8_t push_threshold, bool in_shift_right,
3535
bool user_interruptible,
3636
int wrap_taget, int wrap,
37-
int offset);
37+
int offset,
38+
int fifo_type,
39+
int mov_status_type,
40+
int mov_status_n);
3841

3942
void common_hal_rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self);
4043
bool common_hal_rp2pio_statemachine_deinited(rp2pio_statemachine_obj_t *self);

ports/raspberrypi/common-hal/audiobusio/I2SOut.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,11 @@ void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self,
198198
false, 32, false, // in settings
199199
false, // Not user-interruptible.
200200
0, -1, // wrap settings
201-
PIO_ANY_OFFSET);
201+
PIO_ANY_OFFSET,
202+
PIO_FIFO_TYPE_DEFAULT,
203+
PIO_MOV_STATUS_DEFAULT,
204+
PIO_MOV_N_DEFAULT
205+
);
202206

203207
self->playing = false;
204208
audio_dma_init(&self->dma);

ports/raspberrypi/common-hal/audiobusio/PDMIn.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t *self,
6060
false, 32, true, // in settings
6161
false, // Not user-interruptible.
6262
0, -1, // wrap settings
63-
PIO_ANY_OFFSET);
63+
PIO_ANY_OFFSET,
64+
PIO_FIFO_TYPE_DEFAULT,
65+
PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT);
6466
uint32_t actual_frequency = common_hal_rp2pio_statemachine_get_frequency(&self->state_machine);
6567
if (actual_frequency < MIN_MIC_CLOCK) {
6668
mp_raise_ValueError(MP_ERROR_TEXT("sampling rate out of range"));

ports/raspberrypi/common-hal/floppyio/__init__.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ int common_hal_floppyio_flux_readinto(void *buf, size_t len, digitalio_digitalin
9999
false, // Not user-interruptible.
100100
false, // No sideset enable
101101
0, -1, // wrap
102-
PIO_ANY_OFFSET // offset
102+
PIO_ANY_OFFSET, // offset
103+
PIO_FIFO_TYPE_DEFAULT,
104+
PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT
103105
);
104106
if (!ok) {
105107
mp_raise_RuntimeError(MP_ERROR_TEXT("All state machines in use"));

ports/raspberrypi/common-hal/imagecapture/ParallelImageCapture.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,9 @@ void common_hal_imagecapture_parallelimagecapture_construct(imagecapture_paralle
101101
true, 32, true, // in settings
102102
false, // Not user-interruptible.
103103
2, 5, // wrap settings
104-
PIO_ANY_OFFSET);
104+
PIO_ANY_OFFSET,
105+
PIO_FIFO_TYPE_DEFAULT,
106+
PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT);
105107
}
106108

107109
void common_hal_imagecapture_parallelimagecapture_deinit(imagecapture_parallelimagecapture_obj_t *self) {

ports/raspberrypi/common-hal/neopixel_write/__init__.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout,
6060
false, // Not user-interruptible.
6161
false, // No sideset enable
6262
0, -1, // wrap
63-
PIO_ANY_OFFSET // offset
64-
);
63+
PIO_ANY_OFFSET, // offset
64+
PIO_FIFO_TYPE_DEFAULT,
65+
PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT);
6566
if (!ok) {
6667
// Do nothing. Maybe bitbang?
6768
return;

ports/raspberrypi/common-hal/paralleldisplaybus/ParallelBus.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,9 @@ void common_hal_paralleldisplaybus_parallelbus_construct(paralleldisplaybus_para
9292
false, 32, true, // RX setting we don't use
9393
false, // Not user-interruptible.
9494
0, -1, // wrap settings
95-
PIO_ANY_OFFSET);
95+
PIO_ANY_OFFSET,
96+
PIO_FIFO_TYPE_DEFAULT,
97+
PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT);
9698

9799
common_hal_rp2pio_statemachine_never_reset(&self->state_machine);
98100
}

ports/raspberrypi/common-hal/pulseio/PulseIn.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self,
5454
true, 32, true, // RX auto pull every 32 bits. shift left to output msb first
5555
false, // Not user-interruptible.
5656
0, -1, // wrap settings
57-
PIO_ANY_OFFSET);
57+
PIO_ANY_OFFSET,
58+
PIO_FIFO_TYPE_DEFAULT,
59+
PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT);
5860

5961
common_hal_pulseio_pulsein_pause(self);
6062

ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode
7676
false, 32, false, // in settings
7777
false, // Not user-interruptible.
7878
0, MP_ARRAY_SIZE(encoder) - 1, // wrap settings
79-
PIO_ANY_OFFSET
80-
);
79+
PIO_ANY_OFFSET,
80+
PIO_FIFO_TYPE_DEFAULT,
81+
PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT);
8182

8283
// We're guaranteed by the init code that some output will be available promptly
8384
uint8_t quiescent_state;

0 commit comments

Comments
 (0)