The RP2040 is new microcontroller from Raspberry Pi that features two Cortex M0s and eight PIO state machines that are good for crunching lots of data. It has 264k RAM and a built in UF2 bootloader too. Datasheet: https://pico.raspberrypi.org/files/rp2040_datasheet.pdf
449 lines
22 KiB
C
449 lines
22 KiB
C
/*
|
|
* This file is part of the MicroPython project, http://micropython.org/
|
|
*
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2021 Scott Shawcroft for Adafruit Industries
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
|
|
// This file contains all of the Python API definitions for the
|
|
// rp2pio.StateMachine class.
|
|
|
|
#include <string.h>
|
|
|
|
#include "shared-bindings/microcontroller/Pin.h"
|
|
#include "bindings/rp2pio/StateMachine.h"
|
|
#include "shared-bindings/util.h"
|
|
|
|
#include "lib/utils/buffer_helper.h"
|
|
#include "lib/utils/context_manager_helpers.h"
|
|
#include "lib/utils/interrupt_char.h"
|
|
#include "py/mperrno.h"
|
|
#include "py/objproperty.h"
|
|
#include "py/runtime.h"
|
|
#include "supervisor/shared/translate.h"
|
|
|
|
|
|
//| class StateMachine:
|
|
//| """A single PIO StateMachine
|
|
//|
|
|
//| The programmable I/O peripheral on the RP2 series of microcontrollers is
|
|
//| unique. It is a collection of generic state machines that can be
|
|
//| used for a variety of protocols. State machines may be independent or
|
|
//| coordinated. Program memory and IRQs are shared between the state machines
|
|
//| in a particular PIO instance. They are independent otherwise.
|
|
//|
|
|
//| This class is designed to facilitate sharing of PIO resources. By default,
|
|
//| it is assumed that the state machine is used on it's own and can be placed
|
|
//| in either PIO. State machines with the same program will be placed in the
|
|
//| same PIO if possible. To ensure multiple state machines share a PIO use
|
|
//| the ``colocate`` kwarg during construction and create them one after another."""
|
|
//|
|
|
//| def __init__(self,
|
|
//| program: ReadableBuffer,
|
|
//| frequency: int,
|
|
//| *,
|
|
//| init: Optional[ReadableBuffer] = None,
|
|
//| first_out_pin: Optional[microcontroller.Pin] = None,
|
|
//| out_pin_count: int = 1,
|
|
//| first_in_pin: Optional[microcontroller.Pin] = None,
|
|
//| in_pin_count: int = 1,
|
|
//| first_set_pin: Optional[microcontroller.Pin] = None,
|
|
//| set_pin_count: int = 1,
|
|
//| first_sideset_pin: Optional[microcontroller.Pin] = None,
|
|
//| sideset_pin_count: int = 1,
|
|
//| exclusive_pin_use: bool = True,
|
|
//| auto_pull: bool = False,
|
|
//| pull_threshold : int = 32,
|
|
//| out_shift_right : bool = True,
|
|
//| auto_push: bool = False,
|
|
//| push_threshold : int = 32,
|
|
//| in_shift_right : bool = True) -> None:
|
|
// //| colocate: Union[int, StateMachine, None] = None
|
|
//|
|
|
//| """Construct a StateMachine object on the given pins with the given program.
|
|
//|
|
|
//| :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.
|
|
//| :param ReadableBuffer init: a program to run once at start up. This is run after program
|
|
//| is started so instructions may be intermingled
|
|
//| :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 ~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 ~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 ~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
|
|
//| :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 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)."""
|
|
//| ...
|
|
//|
|
|
|
|
STATIC mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
|
rp2pio_statemachine_obj_t *self = m_new_obj(rp2pio_statemachine_obj_t);
|
|
self->base.type = &rp2pio_statemachine_type;
|
|
enum { ARG_program, ARG_frequency, ARG_init,
|
|
ARG_first_out_pin, ARG_out_pin_count,
|
|
ARG_first_in_pin, ARG_in_pin_count,
|
|
ARG_first_set_pin, ARG_set_pin_count,
|
|
ARG_first_sideset_pin, ARG_sideset_pin_count,
|
|
ARG_exclusive_pin_use,
|
|
ARG_auto_pull, ARG_pull_threshold, ARG_out_shift_right,
|
|
ARG_auto_push, ARG_push_threshold, ARG_in_shift_right};
|
|
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_first_out_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
|
{ MP_QSTR_out_pin_count, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
|
|
{ MP_QSTR_first_in_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
|
{ MP_QSTR_in_pin_count, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
|
|
{ MP_QSTR_first_set_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
|
{ MP_QSTR_set_pin_count, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
|
|
{ MP_QSTR_first_sideset_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
|
{ MP_QSTR_sideset_pin_count, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
|
|
{ MP_QSTR_exclusive_pin_use, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
|
|
{ MP_QSTR_auto_pull, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
|
{ MP_QSTR_pull_threshold, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} },
|
|
{ MP_QSTR_out_shift_right, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
|
|
{ MP_QSTR_auto_push, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
|
{ 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_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
|
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
|
|
|
mp_buffer_info_t bufinfo;
|
|
mp_get_buffer_raise(args[ARG_program].u_obj, &bufinfo, MP_BUFFER_READ);
|
|
|
|
mp_buffer_info_t init_bufinfo;
|
|
init_bufinfo.len = 0;
|
|
mp_get_buffer(args[ARG_init].u_obj, &init_bufinfo, MP_BUFFER_READ);
|
|
|
|
// We don't validate pin in use here because we may be ok sharing them within a PIO.
|
|
mcu_pin_obj_t *first_out_pin = validate_obj_is_pin_or_none(args[ARG_first_out_pin].u_obj);
|
|
if (args[ARG_out_pin_count].u_int < 1) {
|
|
mp_raise_ValueError(translate("Pin count must be at least 1"));
|
|
}
|
|
mcu_pin_obj_t *first_in_pin = validate_obj_is_pin_or_none(args[ARG_first_in_pin].u_obj);
|
|
if (args[ARG_in_pin_count].u_int < 1) {
|
|
mp_raise_ValueError(translate("Pin count must be at least 1"));
|
|
}
|
|
mcu_pin_obj_t *first_set_pin = validate_obj_is_pin_or_none(args[ARG_first_set_pin].u_obj);
|
|
if (args[ARG_set_pin_count].u_int < 1) {
|
|
mp_raise_ValueError(translate("Pin count must be at least 1"));
|
|
}
|
|
if (args[ARG_set_pin_count].u_int > 5) {
|
|
mp_raise_ValueError(translate("Set pin count must be between 1 and 5"));
|
|
}
|
|
mcu_pin_obj_t *first_sideset_pin = validate_obj_is_pin_or_none(args[ARG_first_sideset_pin].u_obj);
|
|
if (args[ARG_sideset_pin_count].u_int < 1) {
|
|
mp_raise_ValueError(translate("Pin count must be at least 1"));
|
|
}
|
|
if (args[ARG_sideset_pin_count].u_int > 5) {
|
|
mp_raise_ValueError(translate("Side set pin count must be between 1 and 5"));
|
|
}
|
|
|
|
mp_int_t pull_threshold = args[ARG_pull_threshold].u_int;
|
|
mp_int_t push_threshold = args[ARG_push_threshold].u_int;
|
|
if (pull_threshold < 1 || pull_threshold > 32) {
|
|
mp_raise_ValueError(translate("pull_threshold must be between 1 and 32"));
|
|
}
|
|
if (push_threshold < 1 || push_threshold > 32) {
|
|
mp_raise_ValueError(translate("push_threshold must be between 1 and 32"));
|
|
}
|
|
|
|
if (bufinfo.len < 2) {
|
|
mp_raise_ValueError(translate("Program must contain at least one 16-bit instruction."));
|
|
}
|
|
if (bufinfo.len % 2 != 0) {
|
|
mp_raise_ValueError(translate("Program size invalid"));
|
|
}
|
|
if (bufinfo.len > 32) {
|
|
mp_raise_ValueError(translate("Program too large"));
|
|
}
|
|
|
|
if (init_bufinfo.len % 2 != 0) {
|
|
mp_raise_ValueError(translate("Init program size invalid"));
|
|
}
|
|
|
|
common_hal_rp2pio_statemachine_construct(self,
|
|
bufinfo.buf, bufinfo.len / 2,
|
|
args[ARG_frequency].u_int,
|
|
init_bufinfo.buf, init_bufinfo.len / 2,
|
|
first_out_pin, args[ARG_out_pin_count].u_int,
|
|
first_in_pin, args[ARG_in_pin_count].u_int,
|
|
first_set_pin, args[ARG_set_pin_count].u_int,
|
|
first_sideset_pin, args[ARG_sideset_pin_count].u_int,
|
|
args[ARG_exclusive_pin_use].u_bool,
|
|
args[ARG_auto_pull].u_bool, pull_threshold, args[ARG_out_shift_right].u_bool,
|
|
args[ARG_auto_push].u_bool, push_threshold, args[ARG_in_shift_right].u_bool);
|
|
return MP_OBJ_FROM_PTR(self);
|
|
}
|
|
|
|
//| def deinit(self) -> None:
|
|
//| """Turn off the state machine and release it's resources."""
|
|
//| ...
|
|
//|
|
|
STATIC mp_obj_t rp2pio_statemachine_obj_deinit(mp_obj_t self_in) {
|
|
rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
|
common_hal_rp2pio_statemachine_deinit(self);
|
|
return mp_const_none;
|
|
}
|
|
MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_deinit_obj, rp2pio_statemachine_obj_deinit);
|
|
|
|
//| def __enter__(self) -> SPI:
|
|
//| """No-op used by Context Managers.
|
|
//| Provided by context manager helper."""
|
|
//| ...
|
|
//|
|
|
|
|
//| def __exit__(self) -> None:
|
|
//| """Automatically deinitializes the hardware when exiting a context. See
|
|
//| :ref:`lifetime-and-contextmanagers` for more info."""
|
|
//| ...
|
|
//|
|
|
STATIC mp_obj_t rp2pio_statemachine_obj___exit__(size_t n_args, const mp_obj_t *args) {
|
|
(void)n_args;
|
|
common_hal_rp2pio_statemachine_deinit(args[0]);
|
|
return mp_const_none;
|
|
}
|
|
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rp2pio_statemachine_obj___exit___obj, 4, 4, rp2pio_statemachine_obj___exit__);
|
|
|
|
|
|
STATIC void check_for_deinit(rp2pio_statemachine_obj_t *self) {
|
|
if (common_hal_rp2pio_statemachine_deinited(self)) {
|
|
raise_deinited_error();
|
|
}
|
|
}
|
|
|
|
// // | def restart(self, *other_state_machines) -> None:
|
|
// // | """Restarts this state machine and any others given. They must share
|
|
// // | an underlying PIO. An exception will be raised otherwise."""
|
|
// // | ...
|
|
// // |
|
|
|
|
//| def write(self, buffer: ReadableBuffer, *, start: int = 0, end: Optional[int] = None) -> None:
|
|
//| """Write the data contained in ``buffer`` to the state machine. If the buffer is empty, nothing happens.
|
|
//|
|
|
//| :param ~_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)``"""
|
|
//| ...
|
|
//|
|
|
|
|
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 };
|
|
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} },
|
|
};
|
|
rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
|
check_for_deinit(self);
|
|
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
|
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
|
|
|
mp_buffer_info_t bufinfo;
|
|
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ);
|
|
int32_t start = args[ARG_start].u_int;
|
|
size_t length = bufinfo.len;
|
|
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
|
|
|
|
if (length == 0) {
|
|
return mp_const_none;
|
|
}
|
|
|
|
bool ok = common_hal_rp2pio_statemachine_write(self, ((uint8_t*)bufinfo.buf) + start, length);
|
|
if (mp_hal_is_interrupted()) {
|
|
return mp_const_none;
|
|
}
|
|
if (!ok) {
|
|
mp_raise_OSError(MP_EIO);
|
|
}
|
|
return mp_const_none;
|
|
}
|
|
MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_obj, 2, rp2pio_statemachine_write);
|
|
|
|
|
|
// // | def readinto(self, buffer: WriteableBuffer, *, start: int = 0, end: Optional[int] = None) -> None:
|
|
// // | """Read into ``buffer``. If the number of bytes to read is 0, nothing happens.
|
|
// // |
|
|
// // | :param ~_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 write_value: Value to write while reading. (Usually ignored.)"""
|
|
// // | ...
|
|
// // |
|
|
|
|
// 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, ARG_write_value };
|
|
// 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_write_value,MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
|
// };
|
|
// rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
|
// check_for_deinit(self);
|
|
// check_lock(self);
|
|
// mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
|
// mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
|
|
|
// mp_buffer_info_t bufinfo;
|
|
// mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE);
|
|
// int32_t start = args[ARG_start].u_int;
|
|
// size_t length = bufinfo.len;
|
|
// normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
|
|
|
|
// if (length == 0) {
|
|
// return mp_const_none;
|
|
// }
|
|
|
|
// bool ok = common_hal_rp2pio_statemachine_read(self, ((uint8_t*)bufinfo.buf) + start, length, args[ARG_write_value].u_int);
|
|
// if (!ok) {
|
|
// mp_raise_OSError(MP_EIO);
|
|
// }
|
|
// return mp_const_none;
|
|
// }
|
|
// MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_readinto_obj, 2, rp2pio_statemachine_readinto);
|
|
|
|
// //| def write_readinto(self, buffer_out: ReadableBuffer, buffer_in: WriteableBuffer, *, out_start: int = 0, out_end: Optional[int] = None, in_start: int = 0, in_end: Optional[int] = None) -> None:
|
|
// //| """Write out the data in ``buffer_out`` while simultaneously reading data into ``buffer_in``.
|
|
// //| The SPI object must be locked.
|
|
// //| The lengths of the slices defined by ``buffer_out[out_start:out_end]`` and ``buffer_in[in_start:in_end]``
|
|
// //| must be equal.
|
|
// //| If buffer slice lengths are both 0, nothing happens.
|
|
// //|
|
|
// //| :param ~_typing.ReadableBuffer buffer_out: Write out the data in this buffer
|
|
// //| :param ~_typing.WriteableBuffer buffer_in: Read data into this buffer
|
|
// //| :param int out_start: Start of the slice of buffer_out to write out: ``buffer_out[out_start:out_end]``
|
|
// //| :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)``"""
|
|
// //| ...
|
|
// //|
|
|
|
|
// 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 };
|
|
// 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} },
|
|
// { MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
|
// { 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} },
|
|
// };
|
|
// rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
|
// check_for_deinit(self);
|
|
// check_lock(self);
|
|
// mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
|
// mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
|
|
|
// mp_buffer_info_t buf_out_info;
|
|
// mp_get_buffer_raise(args[ARG_buffer_out].u_obj, &buf_out_info, MP_BUFFER_READ);
|
|
// int32_t out_start = args[ARG_out_start].u_int;
|
|
// size_t out_length = buf_out_info.len;
|
|
// normalize_buffer_bounds(&out_start, args[ARG_out_end].u_int, &out_length);
|
|
|
|
// mp_buffer_info_t buf_in_info;
|
|
// mp_get_buffer_raise(args[ARG_buffer_in].u_obj, &buf_in_info, MP_BUFFER_WRITE);
|
|
// int32_t in_start = args[ARG_in_start].u_int;
|
|
// size_t in_length = buf_in_info.len;
|
|
// normalize_buffer_bounds(&in_start, args[ARG_in_end].u_int, &in_length);
|
|
|
|
// if (out_length != in_length) {
|
|
// mp_raise_ValueError(translate("buffer slices must be of equal length"));
|
|
// }
|
|
|
|
// if (out_length == 0) {
|
|
// return mp_const_none;
|
|
// }
|
|
|
|
// bool ok = common_hal_rp2pio_statemachine_transfer(self,
|
|
// ((uint8_t*)buf_out_info.buf) + out_start,
|
|
// ((uint8_t*)buf_in_info.buf) + in_start,
|
|
// out_length);
|
|
// if (!ok) {
|
|
// mp_raise_OSError(MP_EIO);
|
|
// }
|
|
// return mp_const_none;
|
|
// }
|
|
// MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_readinto_obj, 2, rp2pio_statemachine_write_readinto);
|
|
|
|
//| frequency: int
|
|
//| """The actual state machine frequency. This may not match the frequency requested
|
|
//| due to internal limitations."""
|
|
//|
|
|
|
|
STATIC mp_obj_t rp2pio_statemachine_obj_get_frequency(mp_obj_t self_in) {
|
|
rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
|
check_for_deinit(self);
|
|
return MP_OBJ_NEW_SMALL_INT(common_hal_rp2pio_statemachine_get_frequency(self));
|
|
}
|
|
MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_frequency_obj, rp2pio_statemachine_obj_get_frequency);
|
|
|
|
const mp_obj_property_t rp2pio_statemachine_frequency_obj = {
|
|
.base.type = &mp_type_property,
|
|
.proxy = {(mp_obj_t)&rp2pio_statemachine_get_frequency_obj,
|
|
(mp_obj_t)&mp_const_none_obj,
|
|
(mp_obj_t)&mp_const_none_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) },
|
|
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
|
|
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&rp2pio_statemachine_obj___exit___obj) },
|
|
|
|
// { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&rp2pio_statemachine_configure_obj) },
|
|
|
|
// { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&rp2pio_statemachine_readinto_obj) },
|
|
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&rp2pio_statemachine_write_obj) },
|
|
// { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&rp2pio_statemachine_write_readinto_obj) },
|
|
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&rp2pio_statemachine_frequency_obj) }
|
|
};
|
|
STATIC MP_DEFINE_CONST_DICT(rp2pio_statemachine_locals_dict, rp2pio_statemachine_locals_dict_table);
|
|
|
|
const mp_obj_type_t rp2pio_statemachine_type = {
|
|
{ &mp_type_type },
|
|
.name = MP_QSTR_StateMachine,
|
|
.make_new = rp2pio_statemachine_make_new,
|
|
.locals_dict = (mp_obj_dict_t*)&rp2pio_statemachine_locals_dict,
|
|
};
|
|
|
|
rp2pio_statemachine_obj_t *validate_obj_is_statemachine(mp_obj_t obj) {
|
|
if (!MP_OBJ_IS_TYPE(obj, &rp2pio_statemachine_type)) {
|
|
mp_raise_TypeError_varg(translate("Expected a %q"), rp2pio_statemachine_type.name);
|
|
}
|
|
return MP_OBJ_TO_PTR(obj);
|
|
}
|