Merge pull request #6029 from jepler/pio-wrap
raspberry: StateMachine: Add support for wrap=, wrap_target=
This commit is contained in:
commit
1a329cfd11
@ -87,7 +87,10 @@
|
|||||||
//| auto_push: bool = False,
|
//| auto_push: bool = False,
|
||||||
//| push_threshold: int = 32,
|
//| push_threshold: int = 32,
|
||||||
//| in_shift_right: bool = True,
|
//| in_shift_right: bool = True,
|
||||||
//| user_interruptible: bool = True) -> None:
|
//| user_interruptible: bool = True,
|
||||||
|
//| wrap_target: int = 0,
|
||||||
|
//| wrap: int = -1,
|
||||||
|
//| ) -> None:
|
||||||
//|
|
//|
|
||||||
//| """Construct a StateMachine object on the given pins with the given program.
|
//| """Construct a StateMachine object on the given pins with the given program.
|
||||||
//|
|
//|
|
||||||
@ -136,6 +139,10 @@
|
|||||||
//| that causes an infinite loop, you will be able to interrupt the loop.
|
//| that causes an infinite loop, you will be able to interrupt the loop.
|
||||||
//| However, if you are writing to a device that can get into a bad state if a read or write
|
//| However, if you are writing to a device that can get into a bad state if a read or write
|
||||||
//| is interrupted, you may want to set this to False after your program has been vetted.
|
//| is interrupted, you may want to set this to False after your program has been vetted.
|
||||||
|
//| :param int wrap_target: The target instruction number of automatic wrap. Defaults to the first instruction of the program.
|
||||||
|
//| :param int wrap: The instruction after which to wrap to the ``wrap``
|
||||||
|
//| instruction. As a special case, -1 (the default) indicates the
|
||||||
|
//| last instruction of the program.
|
||||||
//| """
|
//| """
|
||||||
//| ...
|
//| ...
|
||||||
//|
|
//|
|
||||||
@ -155,7 +162,9 @@ STATIC mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
|
|||||||
ARG_auto_pull, ARG_pull_threshold, ARG_out_shift_right,
|
ARG_auto_pull, ARG_pull_threshold, ARG_out_shift_right,
|
||||||
ARG_wait_for_txstall,
|
ARG_wait_for_txstall,
|
||||||
ARG_auto_push, ARG_push_threshold, ARG_in_shift_right,
|
ARG_auto_push, ARG_push_threshold, ARG_in_shift_right,
|
||||||
ARG_user_interruptible,};
|
ARG_user_interruptible,
|
||||||
|
ARG_wrap_target,
|
||||||
|
ARG_wrap,};
|
||||||
static const mp_arg_t allowed_args[] = {
|
static const mp_arg_t allowed_args[] = {
|
||||||
{ MP_QSTR_program, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
{ MP_QSTR_program, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||||
{ MP_QSTR_frequency, MP_ARG_REQUIRED | MP_ARG_INT },
|
{ MP_QSTR_frequency, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||||
@ -194,6 +203,9 @@ STATIC mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
|
|||||||
{ MP_QSTR_push_threshold, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} },
|
{ MP_QSTR_push_threshold, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} },
|
||||||
{ MP_QSTR_in_shift_right, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
|
{ MP_QSTR_in_shift_right, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
|
||||||
{ MP_QSTR_user_interruptible, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
|
{ MP_QSTR_user_interruptible, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
|
||||||
|
|
||||||
|
{ MP_QSTR_wrap_target, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||||
|
{ MP_QSTR_wrap, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||||
};
|
};
|
||||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||||
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||||
@ -254,6 +266,9 @@ STATIC mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
|
|||||||
mp_raise_ValueError(translate("Init program size invalid"));
|
mp_raise_ValueError(translate("Init program size invalid"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int wrap = args[ARG_wrap].u_int;
|
||||||
|
int wrap_target = args[ARG_wrap_target].u_int;
|
||||||
|
|
||||||
common_hal_rp2pio_statemachine_construct(self,
|
common_hal_rp2pio_statemachine_construct(self,
|
||||||
bufinfo.buf, bufinfo.len / 2,
|
bufinfo.buf, bufinfo.len / 2,
|
||||||
args[ARG_frequency].u_int,
|
args[ARG_frequency].u_int,
|
||||||
@ -269,7 +284,8 @@ STATIC mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
|
|||||||
args[ARG_auto_pull].u_bool, pull_threshold, args[ARG_out_shift_right].u_bool,
|
args[ARG_auto_pull].u_bool, pull_threshold, args[ARG_out_shift_right].u_bool,
|
||||||
args[ARG_wait_for_txstall].u_bool,
|
args[ARG_wait_for_txstall].u_bool,
|
||||||
args[ARG_auto_push].u_bool, push_threshold, args[ARG_in_shift_right].u_bool,
|
args[ARG_auto_push].u_bool, push_threshold, args[ARG_in_shift_right].u_bool,
|
||||||
args[ARG_user_interruptible].u_bool);
|
args[ARG_user_interruptible].u_bool,
|
||||||
|
wrap_target, wrap);
|
||||||
return MP_OBJ_FROM_PTR(self);
|
return MP_OBJ_FROM_PTR(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,8 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
|
|||||||
bool auto_pull, uint8_t pull_threshold, bool out_shift_right,
|
bool auto_pull, uint8_t pull_threshold, bool out_shift_right,
|
||||||
bool wait_for_txstall,
|
bool wait_for_txstall,
|
||||||
bool auto_push, uint8_t push_threshold, bool in_shift_right,
|
bool auto_push, uint8_t push_threshold, bool in_shift_right,
|
||||||
bool user_interruptible);
|
bool user_interruptible,
|
||||||
|
int wrap_taget, int wrap);
|
||||||
|
|
||||||
void common_hal_rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self);
|
void common_hal_rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self);
|
||||||
bool common_hal_rp2pio_statemachine_deinited(rp2pio_statemachine_obj_t *self);
|
bool common_hal_rp2pio_statemachine_deinited(rp2pio_statemachine_obj_t *self);
|
||||||
|
@ -134,7 +134,8 @@ void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self,
|
|||||||
false, 32, false, // shift out left to start with MSB
|
false, 32, false, // shift out left to start with MSB
|
||||||
false, // Wait for txstall
|
false, // Wait for txstall
|
||||||
false, 32, false, // in settings
|
false, 32, false, // in settings
|
||||||
false); // Not user-interruptible.
|
false, // Not user-interruptible.
|
||||||
|
0, -1); // wrap settings
|
||||||
|
|
||||||
self->playing = false;
|
self->playing = false;
|
||||||
audio_dma_init(&self->dma);
|
audio_dma_init(&self->dma);
|
||||||
|
@ -63,7 +63,7 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t *self,
|
|||||||
|
|
||||||
// Use the state machine to manage pins.
|
// Use the state machine to manage pins.
|
||||||
common_hal_rp2pio_statemachine_construct(&self->state_machine,
|
common_hal_rp2pio_statemachine_construct(&self->state_machine,
|
||||||
pdmin, sizeof(pdmin) / sizeof(pdmin[0]),
|
pdmin, MP_ARRAY_SIZE(pdmin),
|
||||||
sample_rate * 32 * 2, // Frequency based on sample rate
|
sample_rate * 32 * 2, // Frequency based on sample rate
|
||||||
NULL, 0,
|
NULL, 0,
|
||||||
NULL, 1, 0, 0xffffffff, // out pin
|
NULL, 1, 0, 0xffffffff, // out pin
|
||||||
@ -78,7 +78,8 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t *self,
|
|||||||
false, 32, false, // out settings
|
false, 32, false, // out settings
|
||||||
false, // Wait for txstall
|
false, // Wait for txstall
|
||||||
false, 32, true, // in settings
|
false, 32, true, // in settings
|
||||||
false); // Not user-interruptible.
|
false, // Not user-interruptible.
|
||||||
|
0, -1); // wrap settings
|
||||||
|
|
||||||
uint32_t actual_frequency = common_hal_rp2pio_statemachine_get_frequency(&self->state_machine);
|
uint32_t actual_frequency = common_hal_rp2pio_statemachine_get_frequency(&self->state_machine);
|
||||||
if (actual_frequency < MIN_MIC_CLOCK) {
|
if (actual_frequency < MIN_MIC_CLOCK) {
|
||||||
|
@ -118,13 +118,13 @@ void common_hal_imagecapture_parallelimagecapture_construct(imagecapture_paralle
|
|||||||
false, 32, false, // out settings
|
false, 32, false, // out settings
|
||||||
false, // wait for txstall
|
false, // wait for txstall
|
||||||
true, 32, true, // in settings
|
true, 32, true, // in settings
|
||||||
false); // Not user-interruptible.
|
false, // Not user-interruptible.
|
||||||
|
2, 5); // wrap settings
|
||||||
|
|
||||||
|
|
||||||
PIO pio = self->state_machine.pio;
|
PIO pio = self->state_machine.pio;
|
||||||
uint8_t pio_index = pio_get_index(pio);
|
uint8_t pio_index = pio_get_index(pio);
|
||||||
uint sm = self->state_machine.state_machine;
|
uint sm = self->state_machine.state_machine;
|
||||||
rp2pio_statemachine_set_wrap(&self->state_machine, 2, 5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_imagecapture_parallelimagecapture_deinit(imagecapture_parallelimagecapture_obj_t *self) {
|
void common_hal_imagecapture_parallelimagecapture_deinit(imagecapture_parallelimagecapture_obj_t *self) {
|
||||||
|
@ -78,7 +78,8 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout,
|
|||||||
false, 32, true, // RX setting we don't use
|
false, 32, true, // RX setting we don't use
|
||||||
false, // claim pins
|
false, // claim pins
|
||||||
false, // Not user-interruptible.
|
false, // Not user-interruptible.
|
||||||
false); // No sideset enable
|
false, // No sideset enable
|
||||||
|
0, -1); // wrap
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
// Do nothing. Maybe bitbang?
|
// Do nothing. Maybe bitbang?
|
||||||
return;
|
return;
|
||||||
|
@ -95,7 +95,7 @@ void common_hal_paralleldisplay_parallelbus_construct(paralleldisplay_parallelbu
|
|||||||
}
|
}
|
||||||
|
|
||||||
common_hal_rp2pio_statemachine_construct(&self->state_machine,
|
common_hal_rp2pio_statemachine_construct(&self->state_machine,
|
||||||
parallel_program, sizeof(parallel_program) / sizeof(parallel_program[0]),
|
parallel_program, MP_ARRAY_SIZE(parallel_program),
|
||||||
frequency * 2, // frequency multiplied by 2 as 2 PIO instructions
|
frequency * 2, // frequency multiplied by 2 as 2 PIO instructions
|
||||||
NULL, 0, // init
|
NULL, 0, // init
|
||||||
data0, 8, 0, 255, // first out pin, # out pins
|
data0, 8, 0, 255, // first out pin, # out pins
|
||||||
@ -109,7 +109,8 @@ void common_hal_paralleldisplay_parallelbus_construct(paralleldisplay_parallelbu
|
|||||||
true, 8, true, // TX, auto pull every 8 bits. shift left to output msb first
|
true, 8, true, // TX, auto pull every 8 bits. shift left to output msb first
|
||||||
false, // wait for TX stall
|
false, // wait for TX stall
|
||||||
false, 32, true, // RX setting we don't use
|
false, 32, true, // RX setting we don't use
|
||||||
false); // Not user-interruptible.
|
false, // Not user-interruptible.
|
||||||
|
0, -1); // wrap settings
|
||||||
|
|
||||||
common_hal_rp2pio_statemachine_never_reset(&self->state_machine);
|
common_hal_rp2pio_statemachine_never_reset(&self->state_machine);
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,8 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self,
|
|||||||
true, 32, true, // RX auto-push every 32 bits
|
true, 32, true, // RX auto-push every 32 bits
|
||||||
false, // claim pins
|
false, // claim pins
|
||||||
false, // Not user-interruptible.
|
false, // Not user-interruptible.
|
||||||
false); // No sideset enable
|
false, // No sideset enable
|
||||||
|
0, -1); // wrap settings
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
mp_raise_RuntimeError(translate("All state machines in use"));
|
mp_raise_RuntimeError(translate("All state machines in use"));
|
||||||
|
@ -92,7 +92,9 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode
|
|||||||
false, 32, false, // out settings
|
false, 32, false, // out settings
|
||||||
false, // Wait for txstall
|
false, // Wait for txstall
|
||||||
false, 32, false, // in settings
|
false, 32, false, // in settings
|
||||||
false); // Not user-interruptible.
|
false, // Not user-interruptible.
|
||||||
|
0, MP_ARRAY_SIZE(encoder) - 1 // wrap settings
|
||||||
|
);
|
||||||
|
|
||||||
// We're guaranteed by the init code that some output will be available promptly
|
// We're guaranteed by the init code that some output will be available promptly
|
||||||
uint8_t quiescent_state;
|
uint8_t quiescent_state;
|
||||||
|
@ -165,7 +165,8 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
|
|||||||
bool auto_push, uint8_t push_threshold, bool in_shift_right,
|
bool auto_push, uint8_t push_threshold, bool in_shift_right,
|
||||||
bool claim_pins,
|
bool claim_pins,
|
||||||
bool user_interruptible,
|
bool user_interruptible,
|
||||||
bool sideset_enable
|
bool sideset_enable,
|
||||||
|
int wrap_target, int wrap
|
||||||
) {
|
) {
|
||||||
// Create a program id that isn't the pointer so we can store it without storing the original object.
|
// Create a program id that isn't the pointer so we can store it without storing the original object.
|
||||||
uint32_t program_id = ~((uint32_t)program);
|
uint32_t program_id = ~((uint32_t)program);
|
||||||
@ -289,7 +290,18 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
|
|||||||
if (jmp_pin != NULL) {
|
if (jmp_pin != NULL) {
|
||||||
sm_config_set_jmp_pin(&c, jmp_pin->number);
|
sm_config_set_jmp_pin(&c, jmp_pin->number);
|
||||||
}
|
}
|
||||||
sm_config_set_wrap(&c, program_offset, program_offset + program_len - 1);
|
|
||||||
|
mp_arg_validate_int_range(wrap, -1, program_len - 1, MP_QSTR_wrap);
|
||||||
|
if (wrap == -1) {
|
||||||
|
wrap = program_len - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_arg_validate_int_range(wrap_target, 0, program_len - 1, MP_QSTR_wrap_target);
|
||||||
|
|
||||||
|
wrap += program_offset;
|
||||||
|
wrap_target += program_offset;
|
||||||
|
|
||||||
|
sm_config_set_wrap(&c, wrap_target, wrap);
|
||||||
sm_config_set_in_shift(&c, in_shift_right, auto_push, push_threshold);
|
sm_config_set_in_shift(&c, in_shift_right, auto_push, push_threshold);
|
||||||
sm_config_set_out_shift(&c, out_shift_right, auto_pull, pull_threshold);
|
sm_config_set_out_shift(&c, out_shift_right, auto_pull, pull_threshold);
|
||||||
|
|
||||||
@ -348,7 +360,8 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
|
|||||||
bool auto_pull, uint8_t pull_threshold, bool out_shift_right,
|
bool auto_pull, uint8_t pull_threshold, bool out_shift_right,
|
||||||
bool wait_for_txstall,
|
bool wait_for_txstall,
|
||||||
bool auto_push, uint8_t push_threshold, bool in_shift_right,
|
bool auto_push, uint8_t push_threshold, bool in_shift_right,
|
||||||
bool user_interruptible) {
|
bool user_interruptible,
|
||||||
|
int wrap_target, int wrap) {
|
||||||
|
|
||||||
// First, check that all pins are free OR already in use by any PIO if exclusive_pin_use is false.
|
// First, check that all pins are free OR already in use by any PIO if exclusive_pin_use is false.
|
||||||
uint32_t pins_we_use = wait_gpio_mask;
|
uint32_t pins_we_use = wait_gpio_mask;
|
||||||
@ -510,7 +523,8 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
|
|||||||
auto_push, push_threshold, in_shift_right,
|
auto_push, push_threshold, in_shift_right,
|
||||||
true /* claim pins */,
|
true /* claim pins */,
|
||||||
user_interruptible,
|
user_interruptible,
|
||||||
sideset_enable);
|
sideset_enable,
|
||||||
|
wrap_target, wrap);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
mp_raise_RuntimeError(translate("All state machines in use"));
|
mp_raise_RuntimeError(translate("All state machines in use"));
|
||||||
}
|
}
|
||||||
@ -834,10 +848,3 @@ uint8_t rp2pio_statemachine_program_offset(rp2pio_statemachine_obj_t *self) {
|
|||||||
uint8_t sm = self->state_machine;
|
uint8_t sm = self->state_machine;
|
||||||
return _current_program_offset[pio_index][sm];
|
return _current_program_offset[pio_index][sm];
|
||||||
}
|
}
|
||||||
|
|
||||||
void rp2pio_statemachine_set_wrap(rp2pio_statemachine_obj_t *self, uint wrap_target, uint wrap) {
|
|
||||||
uint8_t sm = self->state_machine;
|
|
||||||
uint8_t offset = rp2pio_statemachine_program_offset(self);
|
|
||||||
|
|
||||||
pio_sm_set_wrap(self->pio, sm, offset + wrap_target, offset + wrap);
|
|
||||||
}
|
|
||||||
|
@ -76,10 +76,10 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
|
|||||||
bool auto_push, uint8_t push_threshold, bool in_shift_right,
|
bool auto_push, uint8_t push_threshold, bool in_shift_right,
|
||||||
bool claim_pins,
|
bool claim_pins,
|
||||||
bool interruptible,
|
bool interruptible,
|
||||||
bool sideset_enable);
|
bool sideset_enable,
|
||||||
|
int wrap_target, int wrap);
|
||||||
|
|
||||||
uint8_t rp2pio_statemachine_program_offset(rp2pio_statemachine_obj_t *self);
|
uint8_t rp2pio_statemachine_program_offset(rp2pio_statemachine_obj_t *self);
|
||||||
void rp2pio_statemachine_set_wrap(rp2pio_statemachine_obj_t *self, uint wrap_target, uint wrap);
|
|
||||||
|
|
||||||
void rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self, bool leave_pins);
|
void rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self, bool leave_pins);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user