StateMachine: add swap flag
Always use DMA if swap flag is enabled. Improve docs a bit
This commit is contained in:
parent
23c0fc8354
commit
b482a732c6
@ -1540,6 +1540,10 @@ msgstr ""
|
||||
msgid "Mismatched data size"
|
||||
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
|
||||
msgid "Missing MISO or MOSI Pin"
|
||||
msgstr ""
|
||||
@ -2033,7 +2037,7 @@ msgstr ""
|
||||
msgid "RNG Init Error"
|
||||
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"
|
||||
msgstr ""
|
||||
|
||||
|
@ -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);
|
||||
|
||||
//| 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.
|
||||
//|
|
||||
//| 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 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 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) {
|
||||
enum { ARG_buffer, ARG_start, ARG_end };
|
||||
enum { ARG_buffer, ARG_start, ARG_end, ARG_swap };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ 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_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]);
|
||||
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"));
|
||||
}
|
||||
|
||||
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()) {
|
||||
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);
|
||||
|
||||
//| 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.
|
||||
//|
|
||||
//| 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
|
||||
//| 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] 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) {
|
||||
enum { ARG_once, ARG_loop };
|
||||
enum { ARG_once, ARG_loop, ARG_swap };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ 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_swap, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
||||
};
|
||||
rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
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;
|
||||
}
|
||||
|
||||
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()) {
|
||||
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);
|
||||
|
||||
//| 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) {
|
||||
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},
|
||||
};
|
||||
|
||||
//| 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
|
||||
//| 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 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) {
|
||||
enum { ARG_buffer, ARG_start, ARG_end };
|
||||
enum { ARG_buffer, ARG_start, ARG_end, ARG_swap };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ 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_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]);
|
||||
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"));
|
||||
}
|
||||
|
||||
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) {
|
||||
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 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 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) {
|
||||
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[] = {
|
||||
{ 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} },
|
||||
@ -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_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_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]);
|
||||
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,
|
||||
((uint8_t *)buf_in_info.buf) + in_start,
|
||||
in_length,
|
||||
in_stride_in_bytes);
|
||||
in_stride_in_bytes, args[ARG_swap_out].u_bool, args[ARG_swap_in].u_bool);
|
||||
if (!ok) {
|
||||
mp_raise_OSError(MP_EIO);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
// 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_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_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 swap);
|
||||
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);
|
||||
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,
|
||||
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.
|
||||
uint32_t common_hal_rp2pio_statemachine_get_frequency(rp2pio_statemachine_obj_t *self);
|
||||
|
@ -157,9 +157,9 @@ uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t *se
|
||||
size_t output_count = 0;
|
||||
common_hal_rp2pio_statemachine_clear_rxfifo(&self->state_machine);
|
||||
// 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)) {
|
||||
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.
|
||||
uint16_t value = filter_sample(samples);
|
||||
if (self->bit_depth == 8) {
|
||||
|
@ -153,7 +153,7 @@ void common_hal_imagecapture_parallelimagecapture_singleshot_capture(imagecaptur
|
||||
pio_sm_exec(pio, sm, pio_encode_jmp(offset));
|
||||
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);
|
||||
}
|
||||
|
@ -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) {
|
||||
}
|
||||
|
||||
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.
|
||||
rp2pio_statemachine_deinit(&state_machine, true);
|
||||
|
@ -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);
|
||||
|
||||
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) {
|
||||
|
@ -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
|
||||
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);
|
||||
common_hal_rp2pio_statemachine_set_interrupt_handler(&self->state_machine, incrementalencoder_interrupt_handler, self, PIO_IRQ0_INTF_SM0_RXNEMPTY_BITS);
|
||||
|
@ -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,
|
||||
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
|
||||
// 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);
|
||||
bool tx = data_out != 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
|
||||
if (tx) {
|
||||
chan_tx = dma_claim_unused_channel(false);
|
||||
// DMA allocation failed...
|
||||
if (chan_tx < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (rx) {
|
||||
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;
|
||||
@ -698,7 +711,6 @@ static bool _transfer(rp2pio_statemachine_obj_t *self,
|
||||
}
|
||||
}
|
||||
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) {
|
||||
dma_channel_config c;
|
||||
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_read_increment(&c, true);
|
||||
channel_config_set_write_increment(&c, false);
|
||||
channel_config_set_bswap(&c, swap_out);
|
||||
dma_channel_configure(chan_tx, &c,
|
||||
tx_destination,
|
||||
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_read_increment(&c, false);
|
||||
channel_config_set_write_increment(&c, true);
|
||||
channel_config_set_bswap(&c, swap_in);
|
||||
dma_channel_configure(chan_rx, &c,
|
||||
data_in,
|
||||
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
|
||||
// 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) {
|
||||
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) {
|
||||
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,
|
||||
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) {
|
||||
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) {
|
||||
@ -902,7 +916,7 @@ uint8_t rp2pio_statemachine_program_offset(rp2pio_statemachine_obj_t *self) {
|
||||
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 sm = self->state_machine;
|
||||
|
||||
@ -911,11 +925,13 @@ bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t *
|
||||
once = loop;
|
||||
}
|
||||
|
||||
|
||||
if (SM_DMA_ALLOCATED(pio_index, sm)) {
|
||||
if (stride_in_bytes != self->background_stride_in_bytes) {
|
||||
mp_raise_ValueError(translate("Mismatched data size"));
|
||||
}
|
||||
if (swap != self->byteswap) {
|
||||
mp_raise_ValueError(translate("Mismatched swap flag"));
|
||||
}
|
||||
|
||||
while (self->pending_buffers) {
|
||||
RUN_BACKGROUND_TASKS;
|
||||
@ -958,12 +974,14 @@ bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t *
|
||||
self->pending_buffers = pending_buffers;
|
||||
self->dma_completed = false;
|
||||
self->background_stride_in_bytes = stride_in_bytes;
|
||||
self->byteswap = swap;
|
||||
|
||||
c = dma_channel_get_default_config(channel);
|
||||
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_read_increment(&c, true);
|
||||
channel_config_set_write_increment(&c, false);
|
||||
channel_config_set_bswap(&c, swap);
|
||||
dma_channel_configure(channel, &c,
|
||||
tx_destination,
|
||||
once->info.buf,
|
||||
|
@ -64,7 +64,7 @@ typedef struct {
|
||||
volatile int pending_buffers;
|
||||
sm_buf_info current, once, loop;
|
||||
int background_stride_in_bytes;
|
||||
bool dma_completed;
|
||||
bool dma_completed, byteswap;
|
||||
} rp2pio_statemachine_obj_t;
|
||||
|
||||
void reset_rp2pio_statemachine(void);
|
||||
|
Loading…
Reference in New Issue
Block a user