StateMachine: add swap flag

Always use DMA if swap flag is enabled.

Improve docs a bit
This commit is contained in:
Jeff Epler 2022-05-06 15:18:59 -05:00
parent 23c0fc8354
commit b482a732c6
No known key found for this signature in database
GPG Key ID: D5BF15AB975AB4DE
10 changed files with 74 additions and 36 deletions

View File

@ -1540,6 +1540,10 @@ msgstr ""
msgid "Mismatched data size" msgid "Mismatched data size"
msgstr "" msgstr ""
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
msgid "Mismatched swap flag"
msgstr ""
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/SPI.c #: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/SPI.c
msgid "Missing MISO or MOSI Pin" msgid "Missing MISO or MOSI Pin"
msgstr "" msgstr ""
@ -2033,7 +2037,7 @@ msgstr ""
msgid "RNG Init Error" msgid "RNG Init Error"
msgstr "" msgstr ""
#: ports/nrf/common-hal/busio/UART.c ports/raspberrypi/common-hal/busio/UART.c #: ports/nrf/common-hal/busio/UART.c
msgid "RS485 Not yet supported on this device" msgid "RS485 Not yet supported on this device"
msgstr "" msgstr ""

View File

@ -378,7 +378,7 @@ STATIC mp_obj_t rp2pio_statemachine_stop(mp_obj_t self_obj) {
} }
MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_stop_obj, rp2pio_statemachine_stop); MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_stop_obj, rp2pio_statemachine_stop);
//| def write(self, buffer: ReadableBuffer, *, start: int = 0, end: Optional[int] = None) -> None: //| def write(self, buffer: ReadableBuffer, *, start: int = 0, end: Optional[int] = None, swap bool = False) -> None:
//| """Write the data contained in ``buffer`` to the state machine. If the buffer is empty, nothing happens. //| """Write the data contained in ``buffer`` to the state machine. If the buffer is empty, nothing happens.
//| //|
//| Writes to the FIFO will match the input buffer's element size. For example, bytearray elements //| Writes to the FIFO will match the input buffer's element size. For example, bytearray elements
@ -391,14 +391,16 @@ MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_stop_obj, rp2pio_statemachine_stop
//| :param ~circuitpython_typing.ReadableBuffer buffer: Write out the data in this buffer //| :param ~circuitpython_typing.ReadableBuffer buffer: Write out the data in this buffer
//| :param int start: Start of the slice of ``buffer`` to write out: ``buffer[start:end]`` //| :param int start: Start of the slice of ``buffer`` to write out: ``buffer[start:end]``
//| :param int end: End of the slice; this index is not included. Defaults to ``len(buffer)``""" //| :param int end: End of the slice; this index is not included. Defaults to ``len(buffer)``"""
//| :param bool swap: For 2- and 4-byte elements, swap the byte order"""
//| ... //| ...
//| //|
STATIC mp_obj_t rp2pio_statemachine_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC mp_obj_t rp2pio_statemachine_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_buffer, ARG_start, ARG_end }; enum { ARG_buffer, ARG_start, ARG_end, ARG_swap };
static const mp_arg_t allowed_args[] = { static const mp_arg_t allowed_args[] = {
{ MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
{ MP_QSTR_swap, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
}; };
rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
check_for_deinit(self); check_for_deinit(self);
@ -420,7 +422,7 @@ STATIC mp_obj_t rp2pio_statemachine_write(size_t n_args, const mp_obj_t *pos_arg
mp_raise_ValueError(translate("Buffer elements must be 4 bytes long or less")); mp_raise_ValueError(translate("Buffer elements must be 4 bytes long or less"));
} }
bool ok = common_hal_rp2pio_statemachine_write(self, ((uint8_t *)bufinfo.buf) + start, length, stride_in_bytes); bool ok = common_hal_rp2pio_statemachine_write(self, ((uint8_t *)bufinfo.buf) + start, length, stride_in_bytes, args[ARG_swap].u_bool);
if (mp_hal_is_interrupted()) { if (mp_hal_is_interrupted()) {
return mp_const_none; return mp_const_none;
} }
@ -431,7 +433,7 @@ STATIC mp_obj_t rp2pio_statemachine_write(size_t n_args, const mp_obj_t *pos_arg
} }
MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_obj, 2, rp2pio_statemachine_write); MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_obj, 2, rp2pio_statemachine_write);
//| def background_write(self, once: Optional[ReadableBuffer]=None, *, loop: Optional[ReadableBuffer]=None) -> None: //| def background_write(self, once: Optional[ReadableBuffer]=None, *, loop: Optional[ReadableBuffer]=None, swap: bool=False) -> None:
//| """Write data to the TX fifo in the background, with optional looping. //| """Write data to the TX fifo in the background, with optional looping.
//| //|
//| First, if any previous ``once`` or ``loop`` buffer has not been started, this function blocks until they have. //| First, if any previous ``once`` or ``loop`` buffer has not been started, this function blocks until they have.
@ -459,8 +461,13 @@ MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_obj, 2, rp2pio_statemachine
//| where a change in duty cycle requires a special transitional buffer to be used exactly once. Most //| where a change in duty cycle requires a special transitional buffer to be used exactly once. Most
//| use cases will probably only use one of ``once`` or ``loop``. //| use cases will probably only use one of ``once`` or ``loop``.
//| //|
//| Having neither ``once`` nor ``loop`` terminates an existing
//| background looping write after exactly a whole loop. This is in contrast to
//| `stop_background_write, which interrupts an ongoing DMA operation.
//|
//| :param ~Optional[circuitpython_typing.ReadableBuffer] once: Data to be written once //| :param ~Optional[circuitpython_typing.ReadableBuffer] once: Data to be written once
//| :param ~Optional[circuitpython_typing.ReadableBuffer] loop: Data to be written repeatedly //| :param ~Optional[circuitpython_typing.ReadableBuffer] loop: Data to be written repeatedly
//| :param bool swap: For 2- and 4-byte elements, swap the byte order"""
//| """ //| """
//| ... //| ...
//| //|
@ -483,10 +490,11 @@ STATIC void fill_buf_info(sm_buf_info *info, mp_obj_t obj, size_t *stride_in_byt
} }
STATIC mp_obj_t rp2pio_statemachine_background_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC mp_obj_t rp2pio_statemachine_background_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_once, ARG_loop }; enum { ARG_once, ARG_loop, ARG_swap };
static const mp_arg_t allowed_args[] = { static const mp_arg_t allowed_args[] = {
{ MP_QSTR_once, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_once, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_loop, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} }, { MP_QSTR_loop, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} },
{ MP_QSTR_swap, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
}; };
rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
check_for_deinit(self); check_for_deinit(self);
@ -502,7 +510,7 @@ STATIC mp_obj_t rp2pio_statemachine_background_write(size_t n_args, const mp_obj
return mp_const_none; return mp_const_none;
} }
bool ok = common_hal_rp2pio_statemachine_background_write(self, &once_info, &loop_info, stride_in_bytes); bool ok = common_hal_rp2pio_statemachine_background_write(self, &once_info, &loop_info, stride_in_bytes, args[ARG_swap].u_bool);
if (mp_hal_is_interrupted()) { if (mp_hal_is_interrupted()) {
return mp_const_none; return mp_const_none;
@ -515,7 +523,9 @@ STATIC mp_obj_t rp2pio_statemachine_background_write(size_t n_args, const mp_obj
MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_background_write_obj, 1, rp2pio_statemachine_background_write); MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_background_write_obj, 1, rp2pio_statemachine_background_write);
//| def stop_background_write(self) -> None: //| def stop_background_write(self) -> None:
//| """Immediately stop a background write, if one is in progress. Items already in the TX FIFO are not affected.""" //| """Immediately stop a background write, if one is in progress. Any
//| DMA in progress is halted, but items already in the TX FIFO are not
//| affected."""
//| //|
STATIC mp_obj_t rp2pio_statemachine_obj_stop_background_write(mp_obj_t self_in) { STATIC mp_obj_t rp2pio_statemachine_obj_stop_background_write(mp_obj_t self_in) {
rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in); rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in);
@ -567,7 +577,7 @@ const mp_obj_property_t rp2pio_statemachine_pending_obj = {
MP_ROM_NONE}, MP_ROM_NONE},
}; };
//| def readinto(self, buffer: WriteableBuffer, *, start: int = 0, end: Optional[int] = None) -> None: //| def readinto(self, buffer: WriteableBuffer, *, start: int = 0, end: Optional[int] = None, bool swap) -> None:
//| """Read into ``buffer``. If the number of bytes to read is 0, nothing happens. The buffer //| """Read into ``buffer``. If the number of bytes to read is 0, nothing happens. The buffer
//| includes any data added to the fifo even if it was added before this was called. //| includes any data added to the fifo even if it was added before this was called.
//| //|
@ -581,16 +591,18 @@ const mp_obj_property_t rp2pio_statemachine_pending_obj = {
//| //|
//| :param ~circuitpython_typing.WriteableBuffer buffer: Read data into this buffer //| :param ~circuitpython_typing.WriteableBuffer buffer: Read data into this buffer
//| :param int start: Start of the slice of ``buffer`` to read into: ``buffer[start:end]`` //| :param int start: Start of the slice of ``buffer`` to read into: ``buffer[start:end]``
//| :param int end: End of the slice; this index is not included. Defaults to ``len(buffer)``""" //| :param int end: End of the slice; this index is not included. Defaults to ``len(buffer)``
//| :param bool swap: For 2- and 4-byte elements, swap the byte order"""
//| ... //| ...
//| //|
STATIC mp_obj_t rp2pio_statemachine_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC mp_obj_t rp2pio_statemachine_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_buffer, ARG_start, ARG_end }; enum { ARG_buffer, ARG_start, ARG_end, ARG_swap };
static const mp_arg_t allowed_args[] = { static const mp_arg_t allowed_args[] = {
{ MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
{ MP_QSTR_swap, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
}; };
rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
check_for_deinit(self); check_for_deinit(self);
@ -613,7 +625,7 @@ STATIC mp_obj_t rp2pio_statemachine_readinto(size_t n_args, const mp_obj_t *pos_
mp_raise_ValueError(translate("Buffer elements must be 4 bytes long or less")); mp_raise_ValueError(translate("Buffer elements must be 4 bytes long or less"));
} }
bool ok = common_hal_rp2pio_statemachine_readinto(self, ((uint8_t *)bufinfo.buf) + start, length, stride_in_bytes); bool ok = common_hal_rp2pio_statemachine_readinto(self, ((uint8_t *)bufinfo.buf) + start, length, stride_in_bytes, args[ARG_swap].u_bool);
if (!ok) { if (!ok) {
mp_raise_OSError(MP_EIO); mp_raise_OSError(MP_EIO);
} }
@ -639,11 +651,13 @@ MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_readinto_obj, 2, rp2pio_statemach
//| :param int out_end: End of the slice; this index is not included. Defaults to ``len(buffer_out)`` //| :param int out_end: End of the slice; this index is not included. Defaults to ``len(buffer_out)``
//| :param int in_start: Start of the slice of ``buffer_in`` to read into: ``buffer_in[in_start:in_end]`` //| :param int in_start: Start of the slice of ``buffer_in`` to read into: ``buffer_in[in_start:in_end]``
//| :param int in_end: End of the slice; this index is not included. Defaults to ``len(buffer_in)``""" //| :param int in_end: End of the slice; this index is not included. Defaults to ``len(buffer_in)``"""
//| :param bool swap_out: For 2- and 4-byte elements, swap the byte order for the buffer being transmitted (written)"""
//| :param bool swap_in: For 2- and 4-rx elements, swap the byte order for the buffer being received (read)"""
//| ... //| ...
//| //|
STATIC mp_obj_t rp2pio_statemachine_write_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC mp_obj_t rp2pio_statemachine_write_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_buffer_out, ARG_buffer_in, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end }; enum { ARG_buffer_out, ARG_buffer_in, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end, ARG_swap_out, ARG_swap_in };
static const mp_arg_t allowed_args[] = { static const mp_arg_t allowed_args[] = {
{ MP_QSTR_buffer_out, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_buffer_out, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_buffer_in, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_buffer_in, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
@ -651,6 +665,8 @@ STATIC mp_obj_t rp2pio_statemachine_write_readinto(size_t n_args, const mp_obj_t
{ MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, { MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
{ MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} }, { MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
{ MP_QSTR_swap_out, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_swap_in, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
}; };
rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
check_for_deinit(self); check_for_deinit(self);
@ -689,7 +705,7 @@ STATIC mp_obj_t rp2pio_statemachine_write_readinto(size_t n_args, const mp_obj_t
out_stride_in_bytes, out_stride_in_bytes,
((uint8_t *)buf_in_info.buf) + in_start, ((uint8_t *)buf_in_info.buf) + in_start,
in_length, in_length,
in_stride_in_bytes); in_stride_in_bytes, args[ARG_swap_out].u_bool, args[ARG_swap_in].u_bool);
if (!ok) { if (!ok) {
mp_raise_OSError(MP_EIO); mp_raise_OSError(MP_EIO);
} }

View File

@ -65,15 +65,15 @@ void common_hal_rp2pio_statemachine_stop(rp2pio_statemachine_obj_t *self);
void common_hal_rp2pio_statemachine_run(rp2pio_statemachine_obj_t *self, const uint16_t *instructions, size_t len); void common_hal_rp2pio_statemachine_run(rp2pio_statemachine_obj_t *self, const uint16_t *instructions, size_t len);
// Writes out the given data. // Writes out the given data.
bool common_hal_rp2pio_statemachine_write(rp2pio_statemachine_obj_t *self, const uint8_t *data, size_t len, uint8_t stride_in_bytes); bool common_hal_rp2pio_statemachine_write(rp2pio_statemachine_obj_t *self, const uint8_t *data, size_t len, uint8_t stride_in_bytes, bool swap);
bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t *self, const sm_buf_info *once_obj, const sm_buf_info *loop_obj, uint8_t stride_in_bytes); bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t *self, const sm_buf_info *once_obj, const sm_buf_info *loop_obj, uint8_t stride_in_bytes, bool swap);
bool common_hal_rp2pio_statemachine_stop_background_write(rp2pio_statemachine_obj_t *self); bool common_hal_rp2pio_statemachine_stop_background_write(rp2pio_statemachine_obj_t *self);
mp_int_t common_hal_rp2pio_statemachine_get_pending(rp2pio_statemachine_obj_t *self); mp_int_t common_hal_rp2pio_statemachine_get_pending(rp2pio_statemachine_obj_t *self);
bool common_hal_rp2pio_statemachine_get_writing(rp2pio_statemachine_obj_t *self); bool common_hal_rp2pio_statemachine_get_writing(rp2pio_statemachine_obj_t *self);
bool common_hal_rp2pio_statemachine_readinto(rp2pio_statemachine_obj_t *self, uint8_t *data, size_t len, uint8_t stride_in_bytes); bool common_hal_rp2pio_statemachine_readinto(rp2pio_statemachine_obj_t *self, uint8_t *data, size_t len, uint8_t stride_in_bytes, bool swap);
bool common_hal_rp2pio_statemachine_write_readinto(rp2pio_statemachine_obj_t *self, bool common_hal_rp2pio_statemachine_write_readinto(rp2pio_statemachine_obj_t *self,
const uint8_t *data_out, size_t out_len, uint8_t out_stride_in_bytes, const uint8_t *data_out, size_t out_len, uint8_t out_stride_in_bytes,
uint8_t *data_in, size_t in_len, uint8_t in_stride_in_bytes); uint8_t *data_in, size_t in_len, uint8_t in_stride_in_bytes, bool swap_out, bool swap_in);
// Return actual state machine frequency. // Return actual state machine frequency.
uint32_t common_hal_rp2pio_statemachine_get_frequency(rp2pio_statemachine_obj_t *self); uint32_t common_hal_rp2pio_statemachine_get_frequency(rp2pio_statemachine_obj_t *self);

View File

@ -157,9 +157,9 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t *se
size_t output_count = 0; size_t output_count = 0;
common_hal_rp2pio_statemachine_clear_rxfifo(&self->state_machine); common_hal_rp2pio_statemachine_clear_rxfifo(&self->state_machine);
// Do one read to get the mic going and throw it away. // Do one read to get the mic going and throw it away.
common_hal_rp2pio_statemachine_readinto(&self->state_machine, (uint8_t *)samples, 2 * sizeof(uint32_t), sizeof(uint32_t)); common_hal_rp2pio_statemachine_readinto(&self->state_machine, (uint8_t *)samples, 2 * sizeof(uint32_t), sizeof(uint32_t), false);
while (output_count < output_buffer_length && !common_hal_rp2pio_statemachine_get_rxstall(&self->state_machine)) { while (output_count < output_buffer_length && !common_hal_rp2pio_statemachine_get_rxstall(&self->state_machine)) {
common_hal_rp2pio_statemachine_readinto(&self->state_machine, (uint8_t *)samples, 2 * sizeof(uint32_t), sizeof(uint32_t)); common_hal_rp2pio_statemachine_readinto(&self->state_machine, (uint8_t *)samples, 2 * sizeof(uint32_t), sizeof(uint32_t), false);
// Call filter_sample just one place so it can be inlined. // Call filter_sample just one place so it can be inlined.
uint16_t value = filter_sample(samples); uint16_t value = filter_sample(samples);
if (self->bit_depth == 8) { if (self->bit_depth == 8) {

View File

@ -153,7 +153,7 @@ void common_hal_imagecapture_parallelimagecapture_singleshot_capture(imagecaptur
pio_sm_exec(pio, sm, pio_encode_jmp(offset)); pio_sm_exec(pio, sm, pio_encode_jmp(offset));
pio_sm_set_enabled(pio, sm, true); pio_sm_set_enabled(pio, sm, true);
common_hal_rp2pio_statemachine_readinto(&self->state_machine, bufinfo.buf, bufinfo.len, 4); common_hal_rp2pio_statemachine_readinto(&self->state_machine, bufinfo.buf, bufinfo.len, 4, false);
pio_sm_set_enabled(pio, sm, false); pio_sm_set_enabled(pio, sm, false);
} }

View File

@ -90,7 +90,7 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout,
while (port_get_raw_ticks(NULL) < next_start_raw_ticks) { while (port_get_raw_ticks(NULL) < next_start_raw_ticks) {
} }
common_hal_rp2pio_statemachine_write(&state_machine, pixels, num_bytes, 1 /* stride in bytes */); common_hal_rp2pio_statemachine_write(&state_machine, pixels, num_bytes, 1 /* stride in bytes */, false);
// Use a private deinit of the state machine that doesn't reset the pin. // Use a private deinit of the state machine that doesn't reset the pin.
rp2pio_statemachine_deinit(&state_machine, true); rp2pio_statemachine_deinit(&state_machine, true);

View File

@ -161,7 +161,7 @@ void common_hal_paralleldisplay_parallelbus_send(mp_obj_t obj, display_byte_type
paralleldisplay_parallelbus_obj_t *self = MP_OBJ_TO_PTR(obj); paralleldisplay_parallelbus_obj_t *self = MP_OBJ_TO_PTR(obj);
common_hal_digitalio_digitalinout_set_value(&self->command, byte_type == DISPLAY_DATA); common_hal_digitalio_digitalinout_set_value(&self->command, byte_type == DISPLAY_DATA);
common_hal_rp2pio_statemachine_write(&self->state_machine, data, data_length, 1); common_hal_rp2pio_statemachine_write(&self->state_machine, data, data_length, 1, false);
} }
void common_hal_paralleldisplay_parallelbus_end_transaction(mp_obj_t obj) { void common_hal_paralleldisplay_parallelbus_end_transaction(mp_obj_t obj) {

View File

@ -98,7 +98,7 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode
// 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;
common_hal_rp2pio_statemachine_readinto(&self->state_machine, &quiescent_state, 1, 1); common_hal_rp2pio_statemachine_readinto(&self->state_machine, &quiescent_state, 1, 1, false);
shared_module_softencoder_state_init(self, quiescent_state & 3); shared_module_softencoder_state_init(self, quiescent_state & 3);
common_hal_rp2pio_statemachine_set_interrupt_handler(&self->state_machine, incrementalencoder_interrupt_handler, self, PIO_IRQ0_INTF_SM0_RXNEMPTY_BITS); common_hal_rp2pio_statemachine_set_interrupt_handler(&self->state_machine, incrementalencoder_interrupt_handler, self, PIO_IRQ0_INTF_SM0_RXNEMPTY_BITS);

View File

@ -663,7 +663,7 @@ STATIC enum dma_channel_transfer_size _stride_to_dma_size(uint8_t stride) {
static bool _transfer(rp2pio_statemachine_obj_t *self, static bool _transfer(rp2pio_statemachine_obj_t *self,
const uint8_t *data_out, size_t out_len, uint8_t out_stride_in_bytes, const uint8_t *data_out, size_t out_len, uint8_t out_stride_in_bytes,
uint8_t *data_in, size_t in_len, uint8_t in_stride_in_bytes) { uint8_t *data_in, size_t in_len, uint8_t in_stride_in_bytes, bool swap_out, bool swap_in) {
// This implementation is based on SPI but varies because the tx and rx buffers // This implementation is based on SPI but varies because the tx and rx buffers
// may be different lengths and occur at different times or speeds. // may be different lengths and occur at different times or speeds.
@ -674,13 +674,26 @@ static bool _transfer(rp2pio_statemachine_obj_t *self,
size_t len = MAX(out_len, in_len); size_t len = MAX(out_len, in_len);
bool tx = data_out != NULL; bool tx = data_out != NULL;
bool rx = data_in != NULL; bool rx = data_in != NULL;
if (len >= dma_min_size_threshold) { bool use_dma = len >= dma_min_size_threshold || swap_out || swap_in;
if (use_dma) {
// Use DMA channels to service the two FIFOs // Use DMA channels to service the two FIFOs
if (tx) { if (tx) {
chan_tx = dma_claim_unused_channel(false); chan_tx = dma_claim_unused_channel(false);
// DMA allocation failed...
if (chan_tx < 0) {
return false;
}
} }
if (rx) { if (rx) {
chan_rx = dma_claim_unused_channel(false); chan_rx = dma_claim_unused_channel(false);
// DMA allocation failed...
if (chan_rx < 0) {
// may need to free tx channel
if (chan_tx >= 0) {
dma_channel_unclaim(chan_tx);
}
return false;
}
} }
} }
volatile uint8_t *tx_destination = NULL; volatile uint8_t *tx_destination = NULL;
@ -698,7 +711,6 @@ static bool _transfer(rp2pio_statemachine_obj_t *self,
} }
} }
uint32_t stall_mask = 1 << (PIO_FDEBUG_TXSTALL_LSB + self->state_machine); uint32_t stall_mask = 1 << (PIO_FDEBUG_TXSTALL_LSB + self->state_machine);
bool use_dma = (!rx || chan_rx >= 0) && (!tx || chan_tx >= 0);
if (use_dma) { if (use_dma) {
dma_channel_config c; dma_channel_config c;
uint32_t channel_mask = 0; uint32_t channel_mask = 0;
@ -708,6 +720,7 @@ static bool _transfer(rp2pio_statemachine_obj_t *self,
channel_config_set_dreq(&c, self->tx_dreq); channel_config_set_dreq(&c, self->tx_dreq);
channel_config_set_read_increment(&c, true); channel_config_set_read_increment(&c, true);
channel_config_set_write_increment(&c, false); channel_config_set_write_increment(&c, false);
channel_config_set_bswap(&c, swap_out);
dma_channel_configure(chan_tx, &c, dma_channel_configure(chan_tx, &c,
tx_destination, tx_destination,
data_out, data_out,
@ -721,6 +734,7 @@ static bool _transfer(rp2pio_statemachine_obj_t *self,
channel_config_set_dreq(&c, self->rx_dreq); channel_config_set_dreq(&c, self->rx_dreq);
channel_config_set_read_increment(&c, false); channel_config_set_read_increment(&c, false);
channel_config_set_write_increment(&c, true); channel_config_set_write_increment(&c, true);
channel_config_set_bswap(&c, swap_in);
dma_channel_configure(chan_rx, &c, dma_channel_configure(chan_rx, &c,
data_in, data_in,
rx_source, rx_source,
@ -811,27 +825,27 @@ static bool _transfer(rp2pio_statemachine_obj_t *self,
// TODO: Provide a way around these checks in case someone wants to use the FIFO // TODO: Provide a way around these checks in case someone wants to use the FIFO
// with manually run code. // with manually run code.
bool common_hal_rp2pio_statemachine_write(rp2pio_statemachine_obj_t *self, const uint8_t *data, size_t len, uint8_t stride_in_bytes) { bool common_hal_rp2pio_statemachine_write(rp2pio_statemachine_obj_t *self, const uint8_t *data, size_t len, uint8_t stride_in_bytes, bool swap) {
if (!self->out) { if (!self->out) {
mp_raise_RuntimeError(translate("No out in program")); mp_raise_RuntimeError(translate("No out in program"));
} }
return _transfer(self, data, len, stride_in_bytes, NULL, 0, 0); return _transfer(self, data, len, stride_in_bytes, NULL, 0, 0, swap, false);
} }
bool common_hal_rp2pio_statemachine_readinto(rp2pio_statemachine_obj_t *self, uint8_t *data, size_t len, uint8_t stride_in_bytes) { bool common_hal_rp2pio_statemachine_readinto(rp2pio_statemachine_obj_t *self, uint8_t *data, size_t len, uint8_t stride_in_bytes, bool swap) {
if (!self->in) { if (!self->in) {
mp_raise_RuntimeError(translate("No in in program")); mp_raise_RuntimeError(translate("No in in program"));
} }
return _transfer(self, NULL, 0, 0, data, len, stride_in_bytes); return _transfer(self, NULL, 0, 0, data, len, stride_in_bytes, false, swap);
} }
bool common_hal_rp2pio_statemachine_write_readinto(rp2pio_statemachine_obj_t *self, bool common_hal_rp2pio_statemachine_write_readinto(rp2pio_statemachine_obj_t *self,
const uint8_t *data_out, size_t out_len, uint8_t out_stride_in_bytes, const uint8_t *data_out, size_t out_len, uint8_t out_stride_in_bytes,
uint8_t *data_in, size_t in_len, uint8_t in_stride_in_bytes) { uint8_t *data_in, size_t in_len, uint8_t in_stride_in_bytes, bool swap_out, bool swap_in) {
if (!self->in || !self->out) { if (!self->in || !self->out) {
mp_raise_RuntimeError(translate("No in or out in program")); mp_raise_RuntimeError(translate("No in or out in program"));
} }
return _transfer(self, data_out, out_len, out_stride_in_bytes, data_in, in_len, in_stride_in_bytes); return _transfer(self, data_out, out_len, out_stride_in_bytes, data_in, in_len, in_stride_in_bytes, swap_out, swap_in);
} }
bool common_hal_rp2pio_statemachine_get_rxstall(rp2pio_statemachine_obj_t *self) { bool common_hal_rp2pio_statemachine_get_rxstall(rp2pio_statemachine_obj_t *self) {
@ -902,7 +916,7 @@ uint8_t rp2pio_statemachine_program_offset(rp2pio_statemachine_obj_t *self) {
return _current_program_offset[pio_index][sm]; return _current_program_offset[pio_index][sm];
} }
bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t *self, const sm_buf_info *once, const sm_buf_info *loop, uint8_t stride_in_bytes) { bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t *self, const sm_buf_info *once, const sm_buf_info *loop, uint8_t stride_in_bytes, bool swap) {
uint8_t pio_index = pio_get_index(self->pio); uint8_t pio_index = pio_get_index(self->pio);
uint8_t sm = self->state_machine; uint8_t sm = self->state_machine;
@ -911,11 +925,13 @@ bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t *
once = loop; once = loop;
} }
if (SM_DMA_ALLOCATED(pio_index, sm)) { if (SM_DMA_ALLOCATED(pio_index, sm)) {
if (stride_in_bytes != self->background_stride_in_bytes) { if (stride_in_bytes != self->background_stride_in_bytes) {
mp_raise_ValueError(translate("Mismatched data size")); mp_raise_ValueError(translate("Mismatched data size"));
} }
if (swap != self->byteswap) {
mp_raise_ValueError(translate("Mismatched swap flag"));
}
while (self->pending_buffers) { while (self->pending_buffers) {
RUN_BACKGROUND_TASKS; RUN_BACKGROUND_TASKS;
@ -958,12 +974,14 @@ bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t *
self->pending_buffers = pending_buffers; self->pending_buffers = pending_buffers;
self->dma_completed = false; self->dma_completed = false;
self->background_stride_in_bytes = stride_in_bytes; self->background_stride_in_bytes = stride_in_bytes;
self->byteswap = swap;
c = dma_channel_get_default_config(channel); c = dma_channel_get_default_config(channel);
channel_config_set_transfer_data_size(&c, _stride_to_dma_size(stride_in_bytes)); channel_config_set_transfer_data_size(&c, _stride_to_dma_size(stride_in_bytes));
channel_config_set_dreq(&c, self->tx_dreq); channel_config_set_dreq(&c, self->tx_dreq);
channel_config_set_read_increment(&c, true); channel_config_set_read_increment(&c, true);
channel_config_set_write_increment(&c, false); channel_config_set_write_increment(&c, false);
channel_config_set_bswap(&c, swap);
dma_channel_configure(channel, &c, dma_channel_configure(channel, &c,
tx_destination, tx_destination,
once->info.buf, once->info.buf,

View File

@ -64,7 +64,7 @@ typedef struct {
volatile int pending_buffers; volatile int pending_buffers;
sm_buf_info current, once, loop; sm_buf_info current, once, loop;
int background_stride_in_bytes; int background_stride_in_bytes;
bool dma_completed; bool dma_completed, byteswap;
} rp2pio_statemachine_obj_t; } rp2pio_statemachine_obj_t;
void reset_rp2pio_statemachine(void); void reset_rp2pio_statemachine(void);