Skip to content

When available, use core Message and RemoteTransmissionRequest #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 20 additions & 28 deletions adafruit_mcp2515/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,8 @@
_SEND_TIMEOUT_MS = const(5) # 500ms
_MAX_CAN_MSG_LEN = 8 # ?!
# perhaps this will be stateful later?
TransmitBuffer = namedtuple(
"TransmitBuffer",
["CTRL_REG", "STD_ID_REG", "INT_FLAG_MASK", "LOAD_CMD", "SEND_CMD"],
)

# perhaps this will be stateful later? #TODO : dedup with above
ReceiveBuffer = namedtuple(
"TransmitBuffer",
_TransmitBuffer = namedtuple(
"_TransmitBuffer",
["CTRL_REG", "STD_ID_REG", "INT_FLAG_MASK", "LOAD_CMD", "SEND_CMD"],
)

Expand Down Expand Up @@ -266,25 +260,11 @@ def _tx_buffer_status_decode(status_byte):


class MCP2515: # pylint:disable=too-many-instance-attributes
"""A common shared-bus protocol."""

def __init__(
self,
spi_bus,
cs_pin,
*,
baudrate: int = 250000,
crystal_freq: Literal[8000000, 10000000, 16000000] = 16000000,
loopback: bool = False,
silent: bool = False,
auto_restart: bool = False,
debug: bool = False,
):
"""A common shared-bus protocol.
"""A common shared-bus protocol.

:param ~busio.SPI spi: The SPI bus used to communicate with the MCP2515
:param ~digitalio.DigitalInOut cs_pin: SPI bus enable pin
:param int baudrate: The bit rate of the bus in Hz, using a 16Mhz crystal. All devices on\
:param int baudrate: The bit rate of the bus in Hz. All devices on\
the bus must agree on this value. Defaults to 250000.
:param Literal crystal_freq: MCP2515 crystal frequency. Valid values are:\
16000000, 10000000 and 8000000. Defaults to 16000000 (16MHz).\
Expand All @@ -297,10 +277,22 @@ def __init__(
:param bool auto_restart: **Not supported by hardware. An `AttributeError` will be raised\
if `auto_restart` is set to `True`** If `True`, will restart communications after entering\
bus-off state. Defaults to `False`.

:param bool debug: If `True`, will enable printing debug information. Defaults to `False`.
"""

def __init__(
self,
spi_bus,
cs_pin,
*,
baudrate: int = 250000,
crystal_freq: Literal[8000000, 10000000, 16000000] = 16000000,
loopback: bool = False,
silent: bool = False,
auto_restart: bool = False,
debug: bool = False,
):

if loopback and not silent:
raise AttributeError("Loopback mode requires silent to be set")
if auto_restart:
Expand Down Expand Up @@ -332,21 +324,21 @@ def __init__(
def _init_buffers(self):

self._tx_buffers = [
TransmitBuffer(
_TransmitBuffer(
CTRL_REG=_TXB0CTRL,
STD_ID_REG=_TXB0SIDH,
INT_FLAG_MASK=_TX0IF,
LOAD_CMD=_LOAD_TX0,
SEND_CMD=_SEND_TX0,
),
TransmitBuffer(
_TransmitBuffer(
CTRL_REG=_TXB1CTRL,
STD_ID_REG=_TXB1SIDH,
INT_FLAG_MASK=_TX1IF,
LOAD_CMD=_LOAD_TX1,
SEND_CMD=_SEND_TX1,
),
TransmitBuffer(
_TransmitBuffer(
CTRL_REG=_TXB2CTRL,
STD_ID_REG=_TXB2SIDH,
INT_FLAG_MASK=_TX2IF,
Expand Down
68 changes: 41 additions & 27 deletions adafruit_mcp2515/canio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,30 @@


class Message:
"""A class representing a CANbus data frame"""
"""A class representing a CANbus data frame

:param int id: The numeric ID of the message
:param bytes data: The content of the message, from 0 to 8 bytes of data
:param bool extended: True if the message has an extended identifier,
False if it has a standard identifier
"""

# pylint:disable=too-many-arguments,invalid-name,redefined-builtin
def __init__(self, id, data, extended=False):
"""Create a `Message` to send

Args:
id (int): The numeric ID of the message
data (bytes): The content of the message
extended (bool): True if the
Raises:
AttributeError: If `data` of type `bytes` is not provided for a non-RTR message
AttributeError: If `data` is larger than 8 bytes
"""

self._data = None
self.id = id
self.data = data
self.extended = extended

id: int
"""The numeric ID of the message"""

extended: bool
"""Indicates whether the the message has an extended identifier"""

@property
def data(self):
"""The content of the message, or dummy content in the case of an rtr"""
"""The content of the message"""
return self._data

@data.setter
Expand All @@ -50,28 +51,41 @@ def data(self, new_data):


class RemoteTransmissionRequest:
"""A class representing a CANbus remote frame"""

def __init__(self, id: int, length: int, *, extended: bool = False):
"""Construct a RemoteTransmissionRequest to send on a CAN bus
"""A class representing a CANbus remote frame

Args:
id (int): The numeric ID of the requested message
length (int): The length of the requested message
extended (bool, optional): True if the message has an extended identifier, False if it\
has a standard identifier. Defaults to False.
:param int id: The numeric ID of the message
:param length int: The length of the requested message
:param bool extended: True if the message has an extended identifier,
False if it has a standard identifier
"""

"""
def __init__(self, id: int, length: int, *, extended: bool = False):
self.id = id
self.length = length
self.extended = extended

id: int
"""The numeric ID of the message"""

extended: bool
"""Indicates whether the the message has an extended identifier"""

length: int
"""The length of the requested message, from 0 to 8"""


# Replace the above implementation with core canio implementation if it is available
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about moving the above into a separate file and then importing it if canio fails? That'd simplify this file and make it faster to load when canio is available.

try:
from canio import Message, RemoteTransmissionRequest
except ImportError:
pass


class Listener:
"""Listens for a CAN message

canio.Listener is not constructed directly, but instead by calling the `listen` method of a\
canio.CAN object.
canio.Listener is not constructed directly, but instead by calling the
``listen`` method of a canio.CAN object.
"""

def __init__(self, can_bus_obj, timeout=1.0):
Expand All @@ -82,8 +96,8 @@ def __init__(self, can_bus_obj, timeout=1.0):

@property
def timeout(self):
"""The maximum amount of time in seconds that `read` or `readinto` will wait before giving\
up"""
"""The maximum amount of time in seconds that ``read`` or ``readinto``
will wait before giving up"""
return self._timeout

@timeout.setter
Expand Down
2 changes: 2 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@

.. automodule:: adafruit_mcp2515
:members:
.. automodule:: adafruit_mcp2515.canio
:members: