canio: Make both tx and rx (but not both) optional
.. loopback and silent come from the (optional) constructor parameters not guessing based on the pin specification .. docstring & comment improvements
This commit is contained in:
parent
09f8a83a75
commit
7fd6cab2ac
|
@ -51,9 +51,10 @@ __attribute__((optimize("O0"), noinline))
|
|||
void common_hal_canio_can_construct(canio_can_obj_t *self, mcu_pin_obj_t *rx, mcu_pin_obj_t *tx, int baudrate, bool loopback, bool silent)
|
||||
{
|
||||
mcu_pin_function_t *tx_function = mcu_find_pin_function(can_tx, tx, -1, MP_QSTR_tx);
|
||||
int instance = tx_function->instance;
|
||||
int instance = tx_function ? tx_function->instance : -1;
|
||||
|
||||
mcu_pin_function_t *rx_function = mcu_find_pin_function(can_rx, rx, instance, MP_QSTR_rx);
|
||||
instance = rx_function->instance;
|
||||
|
||||
const uint32_t can_frequency = CONF_CAN0_FREQUENCY;
|
||||
|
||||
|
@ -68,9 +69,11 @@ void common_hal_canio_can_construct(canio_can_obj_t *self, mcu_pin_obj_t *rx, mc
|
|||
mp_raise_OSError(MP_EINVAL); // baudrate cannot be attained (16kHz or something is lower bound, should never happen)
|
||||
}
|
||||
|
||||
gpio_set_pin_direction(tx_function->pin, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_function(tx_function->pin, tx_function->function);
|
||||
common_hal_never_reset_pin(tx_function->obj);
|
||||
if (tx_function) {
|
||||
gpio_set_pin_direction(tx_function->pin, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_function(tx_function->pin, tx_function->function);
|
||||
common_hal_never_reset_pin(tx_function->obj);
|
||||
}
|
||||
|
||||
if (rx_function) {
|
||||
gpio_set_pin_direction(rx_function->pin, GPIO_DIRECTION_IN);
|
||||
|
@ -78,12 +81,13 @@ void common_hal_canio_can_construct(canio_can_obj_t *self, mcu_pin_obj_t *rx, mc
|
|||
common_hal_never_reset_pin(rx_function->obj);
|
||||
}
|
||||
|
||||
self->tx_pin_number = common_hal_mcu_pin_number(tx);
|
||||
self->tx_pin_number = tx ? common_hal_mcu_pin_number(tx) : COMMON_HAL_MCU_NO_PIN;
|
||||
self->rx_pin_number = rx ? common_hal_mcu_pin_number(rx) : COMMON_HAL_MCU_NO_PIN;
|
||||
self->hw = can_insts[instance];
|
||||
self->state = &can_state[instance];
|
||||
|
||||
self->loopback = loopback;
|
||||
self->silent = silent;
|
||||
|
||||
// Allow configuration change
|
||||
hri_can_set_CCCR_INIT_bit(self->hw);
|
||||
|
@ -129,11 +133,9 @@ void common_hal_canio_can_construct(canio_can_obj_t *self, mcu_pin_obj_t *rx, mc
|
|||
hri_can_write_NBTP_reg(self->hw, btp.reg);
|
||||
}
|
||||
|
||||
// we don't do the high bit rate yet, so do we need to set this register?
|
||||
// hri_can_write_DBTP_reg(self->hw, ???);
|
||||
// A "data bit" is a data bit :) with dul rate CAN FD, this is a higher
|
||||
// rate. However, CAN FD is not implemented in CircuitPython, and this is the same rate as
|
||||
// the "nominal rate".
|
||||
// A "data bit" is a data bit :) with dula rate CAN FD, this is a higher
|
||||
// rate. However, CAN FD is not implemented in CircuitPython, and this is
|
||||
// the same rate as the "nominal rate".
|
||||
{
|
||||
CAN_DBTP_Type btp = {
|
||||
.bit.DTSEG1 = DIV_ROUND(clocks_to_sample, divisor) - 1,
|
||||
|
@ -259,7 +261,7 @@ void common_hal_canio_can_construct(canio_can_obj_t *self, mcu_pin_obj_t *rx, mc
|
|||
can_objs[instance] = self;
|
||||
}
|
||||
|
||||
int common_hal_canio_can_loopback_get(canio_can_obj_t *self)
|
||||
bool common_hal_canio_can_loopback_get(canio_can_obj_t *self)
|
||||
{
|
||||
return self->loopback;
|
||||
}
|
||||
|
@ -368,6 +370,10 @@ void common_hal_canio_can_send(canio_can_obj_t *self, canio_message_obj_t *messa
|
|||
}
|
||||
}
|
||||
|
||||
bool common_hal_canio_can_silent_get(canio_can_obj_t *self) {
|
||||
return self->silent;
|
||||
}
|
||||
|
||||
bool common_hal_canio_can_deinited(canio_can_obj_t *self) {
|
||||
return !self->hw;
|
||||
}
|
||||
|
|
|
@ -60,8 +60,10 @@ int common_hal_canio_can_baudrate_get(canio_can_obj_t *self);
|
|||
int common_hal_canio_can_bus_off_state_count_get(canio_can_obj_t *self);
|
||||
int common_hal_canio_can_error_passive_state_count_get(canio_can_obj_t *self);
|
||||
int common_hal_canio_can_error_warning_state_count_get(canio_can_obj_t *self);
|
||||
bool common_hal_canio_can_loopback_get(canio_can_obj_t *self);
|
||||
int common_hal_canio_can_receive_error_count_get(canio_can_obj_t *self);
|
||||
canio_bus_state_t common_hal_canio_can_state_get(canio_can_obj_t *self);
|
||||
bool common_hal_canio_can_silent_get(canio_can_obj_t *self);
|
||||
int common_hal_canio_can_transmit_error_count_get(canio_can_obj_t *self);
|
||||
void common_hal_canio_can_auto_restart_set(canio_can_obj_t *self, bool auto_restart);
|
||||
void common_hal_canio_can_check_for_deinit(canio_can_obj_t *self);
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
//| """CAN bus protocol"""
|
||||
//|
|
||||
//| def __init__(self,
|
||||
//| rx: microcontroller.Pin,
|
||||
//| rx: Optional[microcontroller.Pin]=None,
|
||||
//| tx: Optional[microcontroller.Pin]=None,
|
||||
//| *,
|
||||
//| baudrate: int = 250000,
|
||||
|
@ -50,13 +50,18 @@
|
|||
//| auto_restart: bool = False,
|
||||
//| ):
|
||||
//| """A common shared-bus protocol. The rx and tx pins are generally
|
||||
//| connected to a transceiver which controls the H and L pins on a shared
|
||||
//| bus.
|
||||
//| connected to a transceiver which controls the H and L pins on a
|
||||
//| shared bus.
|
||||
//|
|
||||
//| :param ~microcontroller.Pin rx: the pin to receive with.
|
||||
//| :param ~microcontroller.Pin tx: the pin to transmit with, or None if the peripheral should operate in "silent" mode.
|
||||
//| Normally, both ``tx`` and ``rx`` pins will be specified. However,
|
||||
//| in silent and loopback modes, the other pin may not be required and
|
||||
//| can be used for other purposes.
|
||||
//|
|
||||
//| :param ~microcontroller.Pin rx: the pin to receive with, or None.
|
||||
//| :param ~microcontroller.Pin tx: the pin to transmit with, or None.
|
||||
//| :param int baudrate: The bit rate of the bus in Hz. All devices on the bus must agree on this value.
|
||||
//| :param bool loopback: True if the peripheral will be operated in loopback mode.
|
||||
//| :param bool loopback: True if the peripheral will be operated in loopback mode. In loopback mode, the ``rx`` pin's value is ignored, and the device receives the packets it sends.
|
||||
//| :param bool silent: True if the peripheral will be operated in silent mode. In silent mode, the ``tx`` pin is always driven to the high logic level. This mode can be used to "sniff" a CAN bus without interfering.
|
||||
//| :param bool auto_restart: If True, will restart communications after entering bus-off state
|
||||
//| """
|
||||
//| ...
|
||||
|
@ -64,8 +69,8 @@
|
|||
STATIC mp_obj_t canio_can_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_rx, ARG_tx, ARG_baudrate, ARG_loopback, ARG_silent, ARG_auto_restart, NUM_ARGS };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_rx, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = 0} },
|
||||
{ MP_QSTR_tx, MP_ARG_OBJ, {.u_obj = 0} },
|
||||
{ MP_QSTR_rx, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_tx, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 250000} },
|
||||
{ MP_QSTR_loopback, MP_ARG_BOOL, {.u_bool = false} },
|
||||
{ MP_QSTR_silent, MP_ARG_BOOL, {.u_bool = false} },
|
||||
|
@ -76,8 +81,11 @@ STATIC mp_obj_t canio_can_make_new(const mp_obj_type_t *type, size_t n_args, con
|
|||
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
mcu_pin_obj_t *rx_pin = validate_obj_is_free_pin(args[ARG_rx].u_obj);
|
||||
mcu_pin_obj_t *rx_pin = validate_obj_is_free_pin_or_none(args[ARG_rx].u_obj);
|
||||
mcu_pin_obj_t *tx_pin = validate_obj_is_free_pin_or_none(args[ARG_tx].u_obj);
|
||||
if (!rx_pin && !tx_pin) {
|
||||
mp_raise_ValueError(translate("tx and rx cannot both be None"));
|
||||
}
|
||||
|
||||
canio_can_obj_t *self = m_new_obj(canio_can_obj_t);
|
||||
self->base.type = &canio_can_type;
|
||||
|
@ -301,6 +309,24 @@ STATIC mp_obj_t canio_can_listen(size_t n_args, const mp_obj_t *pos_args, mp_map
|
|||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(canio_can_listen_obj, 1, canio_can_listen);
|
||||
|
||||
//| loopback: bool
|
||||
//| """True if the device was created in loopback mode, False otherwise"""
|
||||
//|
|
||||
STATIC mp_obj_t canio_can_loopback_get(mp_obj_t self_in) {
|
||||
canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
common_hal_canio_can_check_for_deinit(self);
|
||||
return mp_obj_new_bool(common_hal_canio_can_loopback_get(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(canio_can_loopback_get_obj, canio_can_loopback_get);
|
||||
|
||||
STATIC const mp_obj_property_t canio_can_loopback_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&canio_can_loopback_get_obj,
|
||||
(mp_obj_t)mp_const_none,
|
||||
(mp_obj_t)mp_const_none},
|
||||
};
|
||||
|
||||
|
||||
//| def send(message: Message) -> None:
|
||||
//| """Send a message on the bus with the given data and id.
|
||||
//| If the message could not be sent due to a full fifo or a bus error condition, RuntimeError is raised.
|
||||
|
@ -321,6 +347,24 @@ STATIC mp_obj_t canio_can_send(mp_obj_t self_in, mp_obj_t message_in) {
|
|||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(canio_can_send_obj, canio_can_send);
|
||||
|
||||
//| silent: bool
|
||||
//| """True if the device was created in silent mode, False otherwise"""
|
||||
//|
|
||||
STATIC mp_obj_t canio_can_silent_get(mp_obj_t self_in) {
|
||||
canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
common_hal_canio_can_check_for_deinit(self);
|
||||
return mp_obj_new_bool(common_hal_canio_can_silent_get(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(canio_can_silent_get_obj, canio_can_silent_get);
|
||||
|
||||
STATIC const mp_obj_property_t canio_can_silent_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&canio_can_silent_get_obj,
|
||||
(mp_obj_t)mp_const_none,
|
||||
(mp_obj_t)mp_const_none},
|
||||
};
|
||||
|
||||
|
||||
//| def deinit(self) -> None:
|
||||
//| """Deinitialize this object, freeing its hardware resources"""
|
||||
//| ...
|
||||
|
@ -363,9 +407,11 @@ STATIC const mp_rom_map_elem_t canio_can_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_error_passive_state_count), MP_ROM_PTR(&canio_can_error_passive_state_count_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_error_warning_state_count), MP_ROM_PTR(&canio_can_error_warning_state_count_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&canio_can_listen_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_loopback), MP_ROM_PTR(&canio_can_loopback_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_receive_error_count), MP_ROM_PTR(&canio_can_receive_error_count_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&canio_can_restart_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&canio_can_send_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_silent), MP_ROM_PTR(&canio_can_silent_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&canio_can_state_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_transmit_error_count), MP_ROM_PTR(&canio_can_transmit_error_count_obj) },
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue