Merge pull request #9610 from jepler/piov2
rp2pio: Support PIOv1 (rp2350) features
This commit is contained in:
commit
345a8294e1
12 changed files with 238 additions and 47 deletions
|
|
@ -21,7 +21,13 @@
|
|||
#include "py/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
|
||||
//| import memorymap
|
||||
//|
|
||||
//| FifoType = Literal["auto", "txrx", "tx", "rx", "txput", "txget", "putget"]
|
||||
//| FifoType_piov0 = Literal["auto", "txrx", "tx", "rx"]
|
||||
//| MovStatusType = Literal["txfifo", "rxfifo", "irq"]
|
||||
//| MovStatusType_piov0 = Literal["txfifo"]
|
||||
//|
|
||||
//| class StateMachine:
|
||||
//| """A single PIO StateMachine
|
||||
//|
|
||||
|
|
@ -41,6 +47,7 @@
|
|||
//| program: ReadableBuffer,
|
||||
//| frequency: int,
|
||||
//| *,
|
||||
//| pio_version: int = 0,
|
||||
//| may_exec: Optional[ReadableBuffer] = None,
|
||||
//| init: Optional[ReadableBuffer] = None,
|
||||
//| first_out_pin: Optional[microcontroller.Pin] = None,
|
||||
|
|
@ -74,9 +81,14 @@
|
|||
//| wrap_target: int = 0,
|
||||
//| wrap: int = -1,
|
||||
//| offset: int = -1,
|
||||
//| fifo_type: FifoType = "auto",
|
||||
//| mov_status_type: MovStatusType = "txfifo",
|
||||
//| mov_status_n: int = 0,
|
||||
//| ) -> None:
|
||||
//| """Construct a StateMachine object on the given pins with the given program.
|
||||
//|
|
||||
//| The following parameters are usually supplied directly:
|
||||
//|
|
||||
//| :param ReadableBuffer program: the program to run with the state machine
|
||||
//| :param int frequency: the target clock frequency of the state machine. Actual may be less. Use 0 for system clock speed.
|
||||
//| :param ReadableBuffer init: a program to run once at start up. This is run after program
|
||||
|
|
@ -86,60 +98,77 @@
|
|||
//| for instance, if there is no ``in`` or ``push`` instruction, then the `StateMachine` is configured without a receive FIFO.
|
||||
//| In this case, passing a ``may_exec`` program containing an ``in`` instruction such as ``in x``, a receive FIFO will be configured.
|
||||
//| :param ~microcontroller.Pin first_out_pin: the first pin to use with the OUT instruction
|
||||
//| :param int out_pin_count: the count of consecutive pins to use with OUT starting at first_out_pin
|
||||
//| :param int initial_out_pin_state: the initial output value for out pins starting at first_out_pin
|
||||
//| :param int initial_out_pin_direction: the initial output direction for out pins starting at first_out_pin
|
||||
//| :param ~microcontroller.Pin first_in_pin: the first pin to use with the IN instruction
|
||||
//| :param int in_pin_count: the count of consecutive pins to use with IN starting at first_in_pin
|
||||
//| :param int pull_in_pin_up: a 1-bit in this mask sets pull up on the corresponding in pin
|
||||
//| :param int pull_in_pin_down: a 1-bit in this mask sets pull down on the corresponding in pin. Setting both pulls enables a "bus keep" function, i.e. a weak pull to whatever is current high/low state of GPIO.
|
||||
//| :param ~microcontroller.Pin first_set_pin: the first pin to use with the SET instruction
|
||||
//| :param int set_pin_count: the count of consecutive pins to use with SET starting at first_set_pin
|
||||
//| :param int initial_set_pin_state: the initial output value for set pins starting at first_set_pin
|
||||
//| :param int initial_set_pin_direction: the initial output direction for set pins starting at first_set_pin
|
||||
//| :param ~microcontroller.Pin first_sideset_pin: the first pin to use with a side set
|
||||
//| :param int sideset_pin_count: the count of consecutive pins to use with a side set starting at first_sideset_pin. Does not include sideset enable
|
||||
//| :param int initial_sideset_pin_state: the initial output value for sideset pins starting at first_sideset_pin
|
||||
//| :param int initial_sideset_pin_direction: the initial output direction for sideset pins starting at first_sideset_pin
|
||||
//| :param bool sideset_enable: True when the top sideset bit is to enable. This should be used with the ".side_set # opt" directive
|
||||
//| :param ~microcontroller.Pin jmp_pin: the pin which determines the branch taken by JMP PIN instructions
|
||||
//| :param ~digitalio.Pull jmp_pin_pull: The pull value for the jmp pin, default is no pull.
|
||||
//| :param bool exclusive_pin_use: When True, do not share any pins with other state machines. Pins are never shared with other peripherals
|
||||
//| :param bool auto_pull: When True, automatically load data from the tx FIFO into the
|
||||
//| output shift register (OSR) when an OUT instruction shifts more than pull_threshold bits
|
||||
//| :param int pull_threshold: Number of bits to shift before loading a new value into the OSR from the tx FIFO
|
||||
//| :param bool out_shift_right: When True, data is shifted out the right side (LSB) of the
|
||||
//| OSR. It is shifted out the left (MSB) otherwise. NOTE! This impacts data alignment
|
||||
//| when the number of bytes is not a power of two (1, 2 or 4 bytes).
|
||||
//| :param bool wait_for_txstall: When True, writing data out will block until the TX FIFO and OSR are empty
|
||||
//| and an instruction is stalled waiting for more data. When False, data writes won't
|
||||
//| wait for the OSR to empty (only the TX FIFO) so make sure you give enough time before
|
||||
//| deiniting or stopping the state machine.
|
||||
//| :param bool auto_push: When True, automatically save data from input shift register
|
||||
//| (ISR) into the rx FIFO when an IN instruction shifts more than push_threshold bits
|
||||
//| :param int push_threshold: Number of bits to shift before saving the ISR value to the RX FIFO
|
||||
//| :param bool in_shift_right: When True, data is shifted into the right side (LSB) of the
|
||||
//| ISR. It is shifted into the left (MSB) otherwise. NOTE! This impacts data alignment
|
||||
//| when the number of bytes is not a power of two (1, 2 or 4 bytes).
|
||||
//| :param bool user_interruptible: When True (the default),
|
||||
//| `write()`, `readinto()`, and `write_readinto()` can be interrupted by a ctrl-C.
|
||||
//| This is useful when developing a PIO program: if there is an error in the program
|
||||
//| 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
|
||||
//| is interrupted, you may want to set this to False after your program has been vetted.
|
||||
//| :param int offset: A specific offset in the state machine's program memory where the program must be loaded.
|
||||
//| The default value, -1, allows the program to be loaded at any offset.
|
||||
//| This is appropriate for most programs.
|
||||
//|
|
||||
//| The following parameters are usually set via assembler directives and passed using a ``**program.pio_kwargs`` argument but may also be specified directly:
|
||||
//|
|
||||
//| :param int out_pin_count: the count of consecutive pins to use with OUT starting at first_out_pin
|
||||
//| :param int in_pin_count: the count of consecutive pins to use with IN starting at first_in_pin
|
||||
//| :param int set_pin_count: the count of consecutive pins to use with SET starting at first_set_pin
|
||||
//| :param int sideset_pin_count: the count of consecutive pins to use with a side set starting at first_sideset_pin. Does not include sideset enable
|
||||
//| :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.
|
||||
//| :param bool auto_push: When True, automatically save data from input shift register
|
||||
//| (ISR) into the rx FIFO when an IN instruction shifts more than push_threshold bits
|
||||
//| :param int push_threshold: Number of bits to shift before saving the ISR value to the RX FIFO
|
||||
//| :param bool in_shift_right: When True, data is shifted into the right side (LSB) of the
|
||||
//| ISR. It is shifted into the left (MSB) otherwise. NOTE! This impacts data alignment
|
||||
//| when the number of bytes is not a power of two (1, 2 or 4 bytes).
|
||||
//| :param bool auto_pull: When True, automatically load data from the tx FIFO into the
|
||||
//| output shift register (OSR) when an OUT instruction shifts more than pull_threshold bits
|
||||
//| :param int pull_threshold: Number of bits to shift before loading a new value into the OSR from the tx FIFO
|
||||
//| :param bool out_shift_right: When True, data is shifted out the right side (LSB) of the
|
||||
//| OSR. It is shifted out the left (MSB) otherwise. NOTE! This impacts data alignment
|
||||
//| when the number of bytes is not a power of two (1, 2 or 4 bytes).
|
||||
//| :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.
|
||||
//| :param int offset: A specific offset in the state machine's program memory where the program must be loaded.
|
||||
//| The default value, -1, allows the program to be loaded at any offset.
|
||||
//| This is appropriate for most programs.
|
||||
//| :param FifoType fifo_type: How the program accessess the FIFOs. PIO version 0 only supports a subset of values.
|
||||
//| :param MovStatusType mov_status_type: What condition the ``mov status`` instruction checks. PIO version 0 only supports a subset of values.
|
||||
//| :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.
|
||||
//| """
|
||||
//| ...
|
||||
|
||||
static int one_of(qstr_short_t what, mp_obj_t arg, size_t n_options, const qstr_short_t options[], const int values[]) {
|
||||
for (size_t i = 0; i < n_options; i++) {
|
||||
mp_obj_t option_str = MP_OBJ_NEW_QSTR(options[i]);
|
||||
if (mp_obj_equal(arg, option_str)) {
|
||||
return values[i];
|
||||
}
|
||||
}
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), what);
|
||||
}
|
||||
|
||||
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) {
|
||||
rp2pio_statemachine_obj_t *self = mp_obj_malloc(rp2pio_statemachine_obj_t, &rp2pio_statemachine_type);
|
||||
enum { ARG_program, ARG_frequency, ARG_init, ARG_may_exec,
|
||||
enum { ARG_program, ARG_frequency, ARG_init, ARG_pio_version, ARG_may_exec,
|
||||
ARG_first_out_pin, ARG_out_pin_count, ARG_initial_out_pin_state, ARG_initial_out_pin_direction,
|
||||
ARG_first_in_pin, ARG_in_pin_count,
|
||||
ARG_pull_in_pin_up, ARG_pull_in_pin_down,
|
||||
|
|
@ -154,11 +183,15 @@ static mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
|
|||
ARG_user_interruptible,
|
||||
ARG_wrap_target,
|
||||
ARG_wrap,
|
||||
ARG_offset, };
|
||||
ARG_offset,
|
||||
ARG_fifo_type,
|
||||
ARG_mov_status_type,
|
||||
ARG_mov_status_n, };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_program, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_frequency, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_init, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_pio_version, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_may_exec, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
|
||||
{ MP_QSTR_first_out_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
|
|
@ -198,11 +231,18 @@ static mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
|
|||
|
||||
{ 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_QSTR_offset, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||
|
||||
{ MP_QSTR_offset, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PIO_ANY_OFFSET} },
|
||||
|
||||
{ MP_QSTR_fifo_type, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_ROM_QSTR(MP_QSTR_auto) } },
|
||||
{ MP_QSTR_mov_status_type, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_ROM_QSTR(MP_QSTR_txfifo) } },
|
||||
{ MP_QSTR_mov_status_n, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
};
|
||||
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);
|
||||
|
||||
(void)mp_arg_validate_int_max(args[ARG_pio_version].u_int, PICO_PIO_VERSION, MP_QSTR_out_pin_count);
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[ARG_program].u_obj, &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
|
|
@ -254,6 +294,33 @@ static mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
|
|||
int wrap = args[ARG_wrap].u_int;
|
||||
int wrap_target = args[ARG_wrap_target].u_int;
|
||||
|
||||
const qstr_short_t fifo_alternatives[] = { MP_QSTR_auto, MP_QSTR_txrx, MP_QSTR_tx, MP_QSTR_rx,
|
||||
#if PICO_PIO_VERSION > 0
|
||||
MP_QSTR_txput, MP_QSTR_txget, MP_QSTR_putget
|
||||
#endif
|
||||
};
|
||||
const int fifo_values[] = { PIO_FIFO_JOIN_AUTO, PIO_FIFO_JOIN_NONE, PIO_FIFO_JOIN_TX, PIO_FIFO_JOIN_RX,
|
||||
#if PICO_PIO_VERSION > 0
|
||||
PIO_FIFO_JOIN_TXPUT, PIO_FIFO_JOIN_TXGET, PIO_FIFO_JOIN_PUTGET
|
||||
#endif
|
||||
};
|
||||
MP_STATIC_ASSERT(MP_ARRAY_SIZE(fifo_alternatives) == MP_ARRAY_SIZE(fifo_values));
|
||||
|
||||
int fifo_type = one_of(MP_QSTR_fifo_type, args[ARG_fifo_type].u_obj, MP_ARRAY_SIZE(fifo_alternatives), fifo_alternatives, fifo_values);
|
||||
|
||||
const qstr_short_t mov_status_alternatives[] = { MP_QSTR_txfifo, MP_QSTR_rxfifo,
|
||||
#if PICO_PIO_VERSION > 0
|
||||
MP_QSTR_IRQ
|
||||
#endif
|
||||
};
|
||||
const int mov_status_values[] = { STATUS_TX_LESSTHAN, STATUS_RX_LESSTHAN,
|
||||
#if PICO_PIO_VERSION > 0
|
||||
STATUS_IRQ_SET
|
||||
#endif
|
||||
};
|
||||
MP_STATIC_ASSERT(MP_ARRAY_SIZE(mov_status_alternatives) == MP_ARRAY_SIZE(mov_status_values));
|
||||
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);
|
||||
|
||||
common_hal_rp2pio_statemachine_construct(self,
|
||||
bufinfo.buf, bufinfo.len / 2,
|
||||
args[ARG_frequency].u_int,
|
||||
|
|
@ -271,7 +338,10 @@ static mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n
|
|||
args[ARG_wait_for_txstall].u_bool,
|
||||
args[ARG_auto_push].u_bool, push_threshold, args[ARG_in_shift_right].u_bool,
|
||||
args[ARG_user_interruptible].u_bool,
|
||||
wrap_target, wrap, args[ARG_offset].u_int);
|
||||
wrap_target, wrap, args[ARG_offset].u_int,
|
||||
fifo_type,
|
||||
mov_status_type, args[ARG_mov_status_n].u_int
|
||||
);
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
|
|
@ -841,6 +911,32 @@ MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_pc_obj, rp2pio_statemachine_ob
|
|||
MP_PROPERTY_GETTER(rp2pio_statemachine_pc_obj,
|
||||
(mp_obj_t)&rp2pio_statemachine_get_pc_obj);
|
||||
|
||||
//| rxfifo: memorymap.AddressRange
|
||||
//| """Access the state machine's rxfifo directly
|
||||
//|
|
||||
//| If the state machine's fifo mode is ``txput`` then accessing this object
|
||||
//| reads values stored by the ``mov rxfifo[], isr`` PIO instruction, and the
|
||||
//| result of modifying it is undefined.
|
||||
//|
|
||||
//| If the state machine's fifo mode is ``txget`` then modifying this object
|
||||
//| writes values accessed by the ``mov osr, rxfifo[]`` PIO instruction, and
|
||||
//| the result of accessing it is undefined.
|
||||
//|
|
||||
//| If this state machine's mode is something else, then the property's value is `None`.
|
||||
//|
|
||||
//| Note: Since the ``txput`` and ``txget`` fifo mode does not exist on RP2040, this property will always be `None`."""
|
||||
//|
|
||||
|
||||
static mp_obj_t rp2pio_statemachine_obj_get_rxfifo(mp_obj_t self_in) {
|
||||
rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return common_hal_rp2pio_statemachine_get_rxfifo(self);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_rxfifo_obj, rp2pio_statemachine_obj_get_rxfifo);
|
||||
|
||||
MP_PROPERTY_GETTER(rp2pio_statemachine_rxfifo_obj,
|
||||
(mp_obj_t)&rp2pio_statemachine_get_rxfifo_obj);
|
||||
|
||||
|
||||
static const mp_rom_map_elem_t rp2pio_statemachine_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&rp2pio_statemachine_deinit_obj) },
|
||||
|
|
@ -868,6 +964,8 @@ static const mp_rom_map_elem_t rp2pio_statemachine_locals_dict_table[] = {
|
|||
|
||||
{ MP_ROM_QSTR(MP_QSTR_offset), MP_ROM_PTR(&rp2pio_statemachine_offset_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pc), MP_ROM_PTR(&rp2pio_statemachine_pc_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_rxfifo), MP_ROM_PTR(&rp2pio_statemachine_rxfifo_obj) },
|
||||
};
|
||||
static MP_DEFINE_CONST_DICT(rp2pio_statemachine_locals_dict, rp2pio_statemachine_locals_dict_table);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,10 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
|
|||
bool auto_push, uint8_t push_threshold, bool in_shift_right,
|
||||
bool user_interruptible,
|
||||
int wrap_taget, int wrap,
|
||||
int offset);
|
||||
int offset,
|
||||
int fifo_type,
|
||||
int mov_status_type,
|
||||
int mov_status_n);
|
||||
|
||||
void common_hal_rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self);
|
||||
bool common_hal_rp2pio_statemachine_deinited(rp2pio_statemachine_obj_t *self);
|
||||
|
|
@ -70,3 +73,5 @@ int common_hal_rp2pio_statemachine_get_offset(rp2pio_statemachine_obj_t *self);
|
|||
int common_hal_rp2pio_statemachine_get_pc(rp2pio_statemachine_obj_t *self);
|
||||
|
||||
void common_hal_rp2pio_statemachine_set_interrupt_handler(rp2pio_statemachine_obj_t *self, void (*handler)(void *), void *arg, int mask);
|
||||
|
||||
mp_obj_t common_hal_rp2pio_statemachine_get_rxfifo(rp2pio_statemachine_obj_t *self);
|
||||
|
|
|
|||
|
|
@ -198,7 +198,11 @@ void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self,
|
|||
false, 32, false, // in settings
|
||||
false, // Not user-interruptible.
|
||||
0, -1, // wrap settings
|
||||
PIO_ANY_OFFSET);
|
||||
PIO_ANY_OFFSET,
|
||||
PIO_FIFO_TYPE_DEFAULT,
|
||||
PIO_MOV_STATUS_DEFAULT,
|
||||
PIO_MOV_N_DEFAULT
|
||||
);
|
||||
|
||||
self->playing = false;
|
||||
audio_dma_init(&self->dma);
|
||||
|
|
|
|||
|
|
@ -60,7 +60,9 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t *self,
|
|||
false, 32, true, // in settings
|
||||
false, // Not user-interruptible.
|
||||
0, -1, // wrap settings
|
||||
PIO_ANY_OFFSET);
|
||||
PIO_ANY_OFFSET,
|
||||
PIO_FIFO_TYPE_DEFAULT,
|
||||
PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT);
|
||||
uint32_t actual_frequency = common_hal_rp2pio_statemachine_get_frequency(&self->state_machine);
|
||||
if (actual_frequency < MIN_MIC_CLOCK) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("sampling rate out of range"));
|
||||
|
|
|
|||
|
|
@ -99,7 +99,9 @@ int common_hal_floppyio_flux_readinto(void *buf, size_t len, digitalio_digitalin
|
|||
false, // Not user-interruptible.
|
||||
false, // No sideset enable
|
||||
0, -1, // wrap
|
||||
PIO_ANY_OFFSET // offset
|
||||
PIO_ANY_OFFSET, // offset
|
||||
PIO_FIFO_TYPE_DEFAULT,
|
||||
PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT
|
||||
);
|
||||
if (!ok) {
|
||||
mp_raise_RuntimeError(MP_ERROR_TEXT("All state machines in use"));
|
||||
|
|
|
|||
|
|
@ -101,7 +101,9 @@ void common_hal_imagecapture_parallelimagecapture_construct(imagecapture_paralle
|
|||
true, 32, true, // in settings
|
||||
false, // Not user-interruptible.
|
||||
2, 5, // wrap settings
|
||||
PIO_ANY_OFFSET);
|
||||
PIO_ANY_OFFSET,
|
||||
PIO_FIFO_TYPE_DEFAULT,
|
||||
PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT);
|
||||
}
|
||||
|
||||
void common_hal_imagecapture_parallelimagecapture_deinit(imagecapture_parallelimagecapture_obj_t *self) {
|
||||
|
|
|
|||
|
|
@ -60,8 +60,9 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout,
|
|||
false, // Not user-interruptible.
|
||||
false, // No sideset enable
|
||||
0, -1, // wrap
|
||||
PIO_ANY_OFFSET // offset
|
||||
);
|
||||
PIO_ANY_OFFSET, // offset
|
||||
PIO_FIFO_TYPE_DEFAULT,
|
||||
PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT);
|
||||
if (!ok) {
|
||||
// Do nothing. Maybe bitbang?
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -92,7 +92,9 @@ void common_hal_paralleldisplaybus_parallelbus_construct(paralleldisplaybus_para
|
|||
false, 32, true, // RX setting we don't use
|
||||
false, // Not user-interruptible.
|
||||
0, -1, // wrap settings
|
||||
PIO_ANY_OFFSET);
|
||||
PIO_ANY_OFFSET,
|
||||
PIO_FIFO_TYPE_DEFAULT,
|
||||
PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT);
|
||||
|
||||
common_hal_rp2pio_statemachine_never_reset(&self->state_machine);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,9 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self,
|
|||
true, 32, true, // RX auto pull every 32 bits. shift left to output msb first
|
||||
false, // Not user-interruptible.
|
||||
0, -1, // wrap settings
|
||||
PIO_ANY_OFFSET);
|
||||
PIO_ANY_OFFSET,
|
||||
PIO_FIFO_TYPE_DEFAULT,
|
||||
PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT);
|
||||
|
||||
common_hal_pulseio_pulsein_pause(self);
|
||||
|
||||
|
|
|
|||
|
|
@ -76,8 +76,9 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode
|
|||
false, 32, false, // in settings
|
||||
false, // Not user-interruptible.
|
||||
0, MP_ARRAY_SIZE(encoder) - 1, // wrap settings
|
||||
PIO_ANY_OFFSET
|
||||
);
|
||||
PIO_ANY_OFFSET,
|
||||
PIO_FIFO_TYPE_DEFAULT,
|
||||
PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT);
|
||||
|
||||
// We're guaranteed by the init code that some output will be available promptly
|
||||
uint8_t quiescent_state;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "shared-bindings/digitalio/Pull.h"
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "shared-bindings/memorymap/AddressRange.h"
|
||||
|
||||
#include "src/rp2040/hardware_regs/include/hardware/platform_defs.h"
|
||||
#include "src/rp2_common/hardware_clocks/include/hardware/clocks.h"
|
||||
|
|
@ -180,6 +181,33 @@ static uint add_program(PIO pio, const pio_program_t *program, int offset) {
|
|||
}
|
||||
}
|
||||
|
||||
static enum pio_fifo_join compute_fifo_type(int fifo_type_in, bool rx_fifo, bool tx_fifo) {
|
||||
if (fifo_type_in != PIO_FIFO_JOIN_AUTO) {
|
||||
return fifo_type_in;
|
||||
}
|
||||
if (!rx_fifo) {
|
||||
return PIO_FIFO_JOIN_TX;
|
||||
}
|
||||
if (!tx_fifo) {
|
||||
return PIO_FIFO_JOIN_RX;
|
||||
}
|
||||
return PIO_FIFO_JOIN_NONE;
|
||||
}
|
||||
|
||||
static int compute_fifo_depth(enum pio_fifo_join join) {
|
||||
if (join == PIO_FIFO_JOIN_TX || join == PIO_FIFO_JOIN_RX) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
#if PICO_PIO_VERSION > 0
|
||||
if (join == PIO_FIFO_JOIN_PUTGET) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
|
||||
const uint16_t *program, size_t program_len,
|
||||
size_t frequency,
|
||||
|
|
@ -199,7 +227,9 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
|
|||
bool user_interruptible,
|
||||
bool sideset_enable,
|
||||
int wrap_target, int wrap,
|
||||
int offset
|
||||
int offset,
|
||||
int fifo_type,
|
||||
int mov_status_type, int mov_status_n
|
||||
) {
|
||||
// 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);
|
||||
|
|
@ -343,15 +373,27 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
|
|||
|
||||
sm_config_set_wrap(&c, wrap_target, wrap);
|
||||
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);
|
||||
#if PICO_PIO_VERSION > 0
|
||||
sm_config_set_in_pin_count(&c, in_pin_count);
|
||||
#endif
|
||||
|
||||
enum pio_fifo_join join = PIO_FIFO_JOIN_NONE;
|
||||
if (!rx_fifo) {
|
||||
join = PIO_FIFO_JOIN_TX;
|
||||
} else if (!tx_fifo) {
|
||||
join = PIO_FIFO_JOIN_RX;
|
||||
sm_config_set_out_shift(&c, out_shift_right, auto_pull, pull_threshold);
|
||||
sm_config_set_out_pin_count(&c, out_pin_count);
|
||||
|
||||
sm_config_set_set_pin_count(&c, set_pin_count);
|
||||
|
||||
enum pio_fifo_join join = compute_fifo_type(fifo_type, rx_fifo, tx_fifo);
|
||||
|
||||
self->fifo_depth = compute_fifo_depth(join);
|
||||
|
||||
#if PICO_PIO_VERSION > 0
|
||||
if (fifo_type == PIO_FIFO_JOIN_TXPUT || fifo_type == PIO_FIFO_JOIN_TXGET) {
|
||||
self->rxfifo_obj.base.type = &memorymap_addressrange_type;
|
||||
common_hal_memorymap_addressrange_construct(&self->rxfifo_obj, (uint8_t *)self->pio->rxf_putget[self->state_machine], 4 * sizeof(uint32_t));
|
||||
} else {
|
||||
self->rxfifo_obj.base.type = NULL;
|
||||
}
|
||||
self->fifo_depth = (join == PIO_FIFO_JOIN_NONE) ? 4 : 8;
|
||||
#endif
|
||||
|
||||
if (rx_fifo) {
|
||||
self->rx_dreq = pio_get_dreq(self->pio, self->state_machine, false);
|
||||
|
|
@ -370,6 +412,11 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
|
|||
self->init_len = init_len;
|
||||
|
||||
sm_config_set_fifo_join(&c, join);
|
||||
|
||||
// TODO: these arguments
|
||||
// int mov_status_type, int mov_status_n,
|
||||
// int set_count, int out_count
|
||||
|
||||
self->sm_config = c;
|
||||
|
||||
// no DMA allocated
|
||||
|
|
@ -519,7 +566,10 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
|
|||
bool auto_push, uint8_t push_threshold, bool in_shift_right,
|
||||
bool user_interruptible,
|
||||
int wrap_target, int wrap,
|
||||
int offset) {
|
||||
int offset,
|
||||
int fifo_type,
|
||||
int mov_status_type,
|
||||
int mov_status_n) {
|
||||
|
||||
// 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;
|
||||
|
|
@ -585,7 +635,7 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
|
|||
pull_up |= jmp_mask;
|
||||
}
|
||||
if (jmp_pull == PULL_DOWN) {
|
||||
pull_up |= jmp_mask;
|
||||
pull_down |= jmp_mask;
|
||||
}
|
||||
}
|
||||
if (initial_pin_direction & (pull_up | pull_down)) {
|
||||
|
|
@ -610,7 +660,9 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
|
|||
true /* claim pins */,
|
||||
user_interruptible,
|
||||
sideset_enable,
|
||||
wrap_target, wrap, offset);
|
||||
wrap_target, wrap, offset,
|
||||
fifo_type,
|
||||
mov_status_type, mov_status_n);
|
||||
if (!ok) {
|
||||
mp_raise_RuntimeError(MP_ERROR_TEXT("All state machines in use"));
|
||||
}
|
||||
|
|
@ -1102,6 +1154,16 @@ int common_hal_rp2pio_statemachine_get_pc(rp2pio_statemachine_obj_t *self) {
|
|||
return pio_sm_get_pc(pio, sm);
|
||||
}
|
||||
|
||||
mp_obj_t common_hal_rp2pio_statemachine_get_rxfifo(rp2pio_statemachine_obj_t *self) {
|
||||
#if PICO_PIO_VERSION > 0
|
||||
if (self->rxfifo_obj.base.type) {
|
||||
return MP_OBJ_FROM_PTR(&self->rxfifo_obj);
|
||||
}
|
||||
#endif
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
|
||||
// Use a compile-time constant for MP_REGISTER_POINTER so the preprocessor will
|
||||
// not split the expansion across multiple lines.
|
||||
MP_REGISTER_ROOT_POINTER(mp_obj_t background_pio[enum_NUM_DMA_CHANNELS]);
|
||||
|
|
|
|||
|
|
@ -9,9 +9,13 @@
|
|||
#include "py/obj.h"
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
#include "common-hal/memorymap/AddressRange.h"
|
||||
#include "src/rp2_common/hardware_pio/include/hardware/pio.h"
|
||||
|
||||
enum { PIO_ANY_OFFSET = -1 };
|
||||
enum { PIO_FIFO_JOIN_AUTO = -1, PIO_FIFO_TYPE_DEFAULT = PIO_FIFO_JOIN_AUTO };
|
||||
enum { PIO_MOV_STATUS_DEFAULT = STATUS_TX_LESSTHAN };
|
||||
enum { PIO_MOV_N_DEFAULT = 0 };
|
||||
|
||||
typedef struct sm_buf_info {
|
||||
mp_obj_t obj;
|
||||
|
|
@ -47,6 +51,9 @@ typedef struct {
|
|||
sm_buf_info current, once, loop;
|
||||
int background_stride_in_bytes;
|
||||
bool dma_completed, byteswap;
|
||||
#if PICO_PIO_VERSION > 0
|
||||
memorymap_addressrange_obj_t rxfifo_obj;
|
||||
#endif
|
||||
} rp2pio_statemachine_obj_t;
|
||||
|
||||
void reset_rp2pio_statemachine(void);
|
||||
|
|
@ -70,7 +77,10 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
|
|||
bool claim_pins,
|
||||
bool interruptible,
|
||||
bool sideset_enable,
|
||||
int wrap_target, int wrap, int offset);
|
||||
int wrap_target, int wrap, int offset,
|
||||
int fifo_type,
|
||||
int mov_status_type, int mov_status_n
|
||||
);
|
||||
|
||||
uint8_t rp2pio_statemachine_program_offset(rp2pio_statemachine_obj_t *self);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue