Skip to content

Commit c523383

Browse files
committed
rp2: StateMachine: Allow loading programs at fixed offsets
1 parent c1a40bd commit c523383

File tree

11 files changed

+52
-18
lines changed

11 files changed

+52
-18
lines changed

ports/raspberrypi/bindings/rp2pio/StateMachine.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
//| user_interruptible: bool = True,
9595
//| wrap_target: int = 0,
9696
//| wrap: int = -1,
97+
//| offset: int = -1,
9798
//| ) -> None:
9899
//| """Construct a StateMachine object on the given pins with the given program.
99100
//|
@@ -151,6 +152,9 @@
151152
//| :param int wrap: The instruction after which to wrap to the ``wrap``
152153
//| instruction. As a special case, -1 (the default) indicates the
153154
//| last instruction of the program.
155+
//| :param int offset: A specific offset in the state machine's program memory where the program must be loaded.
156+
//| The default value, -1, allows the program to be loaded at any offset.
157+
//| This is appropriate for most programs.
154158
//| """
155159
//| ...
156160

@@ -171,7 +175,8 @@ STATIC mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
171175
ARG_auto_push, ARG_push_threshold, ARG_in_shift_right,
172176
ARG_user_interruptible,
173177
ARG_wrap_target,
174-
ARG_wrap,};
178+
ARG_wrap,
179+
ARG_offset,};
175180
static const mp_arg_t allowed_args[] = {
176181
{ MP_QSTR_program, MP_ARG_REQUIRED | MP_ARG_OBJ },
177182
{ MP_QSTR_frequency, MP_ARG_REQUIRED | MP_ARG_INT },
@@ -215,6 +220,7 @@ STATIC mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
215220

216221
{ MP_QSTR_wrap_target, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
217222
{ MP_QSTR_wrap, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
223+
{ MP_QSTR_offset, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
218224
};
219225
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
220226
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@@ -287,7 +293,7 @@ STATIC mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
287293
args[ARG_wait_for_txstall].u_bool,
288294
args[ARG_auto_push].u_bool, push_threshold, args[ARG_in_shift_right].u_bool,
289295
args[ARG_user_interruptible].u_bool,
290-
wrap_target, wrap);
296+
wrap_target, wrap, args[ARG_offset].u_int);
291297
return MP_OBJ_FROM_PTR(self);
292298
}
293299

ports/raspberrypi/bindings/rp2pio/StateMachine.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
5454
bool wait_for_txstall,
5555
bool auto_push, uint8_t push_threshold, bool in_shift_right,
5656
bool user_interruptible,
57-
int wrap_taget, int wrap);
57+
int wrap_taget, int wrap,
58+
int offset);
5859

5960
void common_hal_rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self);
6061
bool common_hal_rp2pio_statemachine_deinited(rp2pio_statemachine_obj_t *self);

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self,
136136
false, // Wait for txstall
137137
false, 32, false, // in settings
138138
false, // Not user-interruptible.
139-
0, -1); // wrap settings
139+
0, -1, // wrap settings
140+
PIO_ANY_OFFSET);
140141

141142
self->playing = false;
142143
audio_dma_init(&self->dma);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t *self,
8080
false, // Wait for txstall
8181
false, 32, true, // in settings
8282
false, // Not user-interruptible.
83-
0, -1); // wrap settings
84-
83+
0, -1, // wrap settings
84+
PIO_ANY_OFFSET);
8585
uint32_t actual_frequency = common_hal_rp2pio_statemachine_get_frequency(&self->state_machine);
8686
if (actual_frequency < MIN_MIC_CLOCK) {
8787
mp_raise_ValueError(translate("sampling rate out of range"));

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ void common_hal_imagecapture_parallelimagecapture_construct(imagecapture_paralle
120120
false, // wait for txstall
121121
true, 32, true, // in settings
122122
false, // Not user-interruptible.
123-
2, 5); // wrap settings
123+
2, 5, // wrap settings
124+
PIO_ANY_OFFSET);
124125
}
125126

126127
void common_hal_imagecapture_parallelimagecapture_deinit(imagecapture_parallelimagecapture_obj_t *self) {

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout,
7979
false, // claim pins
8080
false, // Not user-interruptible.
8181
false, // No sideset enable
82-
0, -1); // wrap
82+
0, -1, // wrap
83+
PIO_ANY_OFFSET // offset
84+
);
8385
if (!ok) {
8486
// Do nothing. Maybe bitbang?
8587
return;

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ void common_hal_paralleldisplay_parallelbus_construct(paralleldisplay_parallelbu
111111
false, // wait for TX stall
112112
false, 32, true, // RX setting we don't use
113113
false, // Not user-interruptible.
114-
0, -1); // wrap settings
114+
0, -1, // wrap settings
115+
PIO_ANY_OFFSET);
115116

116117
common_hal_rp2pio_statemachine_never_reset(&self->state_machine);
117118
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self,
7474
false, // wait for TX stall
7575
true, 32, true, // RX auto pull every 32 bits. shift left to output msb first
7676
false, // Not user-interruptible.
77-
0, -1); // wrap settings
77+
0, -1, // wrap settings
78+
PIO_ANY_OFFSET);
7879

7980
common_hal_pulseio_pulsein_pause(self);
8081

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode
9595
false, // Wait for txstall
9696
false, 32, false, // in settings
9797
false, // Not user-interruptible.
98-
0, MP_ARRAY_SIZE(encoder) - 1 // wrap settings
98+
0, MP_ARRAY_SIZE(encoder) - 1, // wrap settings
99+
PIO_ANY_OFFSET
99100
);
100101

101102
// We're guaranteed by the init code that some output will be available promptly

ports/raspberrypi/common-hal/rp2pio/StateMachine.c

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,21 @@ STATIC uint32_t _check_pins_free(const mcu_pin_obj_t *first_pin, uint8_t pin_cou
178178
return pins_we_use;
179179
}
180180

181+
static bool can_add_program(PIO pio, const pio_program_t *program, int offset) {
182+
if (offset == -1) {
183+
return pio_can_add_program(pio, program);
184+
}
185+
return pio_can_add_program_at_offset(pio, program, offset);
186+
}
187+
188+
static uint add_program(PIO pio, const pio_program_t *program, int offset) {
189+
if (offset == -1) {
190+
return pio_add_program(pio, program);
191+
} else {
192+
pio_add_program_at_offset(pio, program, offset);
193+
return offset;
194+
}
195+
}
181196

182197
bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
183198
const uint16_t *program, size_t program_len,
@@ -197,7 +212,8 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
197212
bool claim_pins,
198213
bool user_interruptible,
199214
bool sideset_enable,
200-
int wrap_target, int wrap
215+
int wrap_target, int wrap,
216+
int offset
201217
) {
202218
// Create a program id that isn't the pointer so we can store it without storing the original object.
203219
uint32_t program_id = ~((uint32_t)program);
@@ -215,14 +231,15 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
215231
uint8_t free_count = 0;
216232
for (size_t j = 0; j < NUM_PIO_STATE_MACHINES; j++) {
217233
if (_current_program_id[i][j] == program_id &&
218-
_current_program_len[i][j] == program_len) {
234+
_current_program_len[i][j] == program_len &&
235+
(offset == -1 || offset == _current_program_offset[i][j])) {
219236
program_offset = _current_program_offset[i][j];
220237
}
221238
if (!pio_sm_is_claimed(pio, j)) {
222239
free_count++;
223240
}
224241
}
225-
if (free_count > 0 && (program_offset < 32 || pio_can_add_program(pio, &program_struct))) {
242+
if (free_count > 0 && (program_offset < 32 || can_add_program(pio, &program_struct, offset))) {
226243
pio_index = i;
227244
if (program_offset < 32) {
228245
break;
@@ -254,7 +271,7 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
254271
self->pio = pio_instances[pio_index];
255272
self->state_machine = state_machine;
256273
if (program_offset == 32) {
257-
program_offset = pio_add_program(self->pio, &program_struct);
274+
program_offset = add_program(self->pio, &program_struct, offset);
258275
}
259276
self->offset = program_offset;
260277
_current_program_id[pio_index][state_machine] = program_id;
@@ -509,7 +526,8 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
509526
bool wait_for_txstall,
510527
bool auto_push, uint8_t push_threshold, bool in_shift_right,
511528
bool user_interruptible,
512-
int wrap_target, int wrap) {
529+
int wrap_target, int wrap,
530+
int offset) {
513531

514532
// First, check that all pins are free OR already in use by any PIO if exclusive_pin_use is false.
515533
uint32_t pins_we_use = wait_gpio_mask;
@@ -598,7 +616,7 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
598616
true /* claim pins */,
599617
user_interruptible,
600618
sideset_enable,
601-
wrap_target, wrap);
619+
wrap_target, wrap, offset);
602620
if (!ok) {
603621
mp_raise_RuntimeError(translate("All state machines in use"));
604622
}

ports/raspberrypi/common-hal/rp2pio/StateMachine.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#include "common-hal/microcontroller/Pin.h"
3333
#include "src/rp2_common/hardware_pio/include/hardware/pio.h"
3434

35+
enum { PIO_ANY_OFFSET = -1 };
36+
3537
typedef struct sm_buf_info {
3638
mp_obj_t obj;
3739
mp_buffer_info_t info;
@@ -88,7 +90,7 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
8890
bool claim_pins,
8991
bool interruptible,
9092
bool sideset_enable,
91-
int wrap_target, int wrap);
93+
int wrap_target, int wrap, int offset);
9294

9395
uint8_t rp2pio_statemachine_program_offset(rp2pio_statemachine_obj_t *self);
9496

0 commit comments

Comments
 (0)