Skip to content
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

Added support for PCAN on Mac #365

Merged
merged 17 commits into from
Aug 9, 2018
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
6 changes: 5 additions & 1 deletion can/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,11 @@ def __new__(cls, channel=None, *args, **config):
channel = config['channel']
del config['channel']

return cls(channel, *args, **config)
if channel is None:
# Use the default channel for the backend
return cls(*args, **config)
else:
return cls(channel, *args, **config)


def detect_available_configs(interfaces=None):
Expand Down
84 changes: 43 additions & 41 deletions can/interfaces/pcan/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
PCAN_LANBUS15 = TPCANHandle(0x80F) # PCAN-LAN interface, channel 15
PCAN_LANBUS16 = TPCANHandle(0x810) # PCAN-LAN interface, channel 16

# Represent the PCAN error and status codes
# Represent the PCAN error and status codes
PCAN_ERROR_OK = TPCANStatus(0x00000) # No error
PCAN_ERROR_XMTFULL = TPCANStatus(0x00001) # Transmit buffer in CAN controller is full
PCAN_ERROR_OVERRUN = TPCANStatus(0x00002) # CAN controller was read too late
Expand Down Expand Up @@ -239,7 +239,7 @@

# Baud rate codes = BTR0/BTR1 register values for the CAN controller.
# You can define your own Baud rate with the BTROBTR1 register.
# Take a look at www.peak-system.com for our free software "BAUDTOOL"
# Take a look at www.peak-system.com for our free software "BAUDTOOL"
# to calculate the BTROBTR1 register for every bit rate and sample point.

PCAN_BAUD_1M = TPCANBaudrate(0x0014) # 1 MBit/s
Expand All @@ -260,7 +260,7 @@
# Represents the configuration for a CAN bit rate
# Note:
# * Each parameter and its value must be separated with a '='.
# * Each pair of parameter/value must be separated using ','.
# * Each pair of parameter/value must be separated using ','.
#
# Example:
# f_clock=80000000,nom_brp=10,nom_tseg1=5,nom_tseg2=2,nom_sjw=1,data_brp=4,data_tseg1=7,data_tseg2=2,data_sjw=1
Expand Down Expand Up @@ -292,7 +292,7 @@ class TPCANMsg (Structure):
"""
Represents a PCAN message
"""
_fields_ = [ ("ID", c_uint), # 11/29-bit message identifier
_fields_ = [ ("ID", c_ulong), # 11/29-bit message identifier - was changed from u_uint to c_ulong, so it is compatible with the PCAN-USB Driver for macOS
("MSGTYPE", TPCANMessageType), # Type of the message
("LEN", c_ubyte), # Data Length Code of the message (0..8)
("DATA", c_ubyte * 8) ] # Data of the message (DATA[0]..DATA[7])
Expand All @@ -303,7 +303,7 @@ class TPCANTimestamp (Structure):
Represents a timestamp of a received PCAN message
Total Microseconds = micros + 1000 * millis + 0x100000000 * 1000 * millis_overflow
"""
_fields_ = [ ("millis", c_uint), # Base-value: milliseconds: 0.. 2^32-1
_fields_ = [ ("millis", c_ulong), # Base-value: milliseconds: 0.. 2^32-1 - was changed from u_uint to c_ulong, so it is compatible with the PCAN-USB Driver for macOS
("millis_overflow", c_ushort), # Roll-arounds of millis
("micros", c_ushort) ] # Microseconds: 0..999

Expand All @@ -312,7 +312,7 @@ class TPCANMsgFD (Structure):
"""
Represents a PCAN message
"""
_fields_ = [ ("ID", c_uint), # 11/29-bit message identifier
_fields_ = [ ("ID", c_ulong), # 11/29-bit message identifier - was changed from u_uint to c_ulong, so it is compatible with the PCAN-USB Driver for macOS
("MSGTYPE", TPCANMessageType), # Type of the message
("DLC", c_ubyte), # Data Length Code of the message (0..15)
("DATA", c_ubyte * 64) ] # Data of the message (DATA[0]..DATA[63])
Expand All @@ -329,6 +329,8 @@ def __init__(self):
# Loads the PCANBasic.dll
if platform.system() == 'Windows':
self.__m_dllBasic = windll.LoadLibrary("PCANBasic")
elif platform.system() == 'Darwin':
self.__m_dllBasic = cdll.LoadLibrary('libPCBUSB.dylib')
else:
self.__m_dllBasic = cdll.LoadLibrary("libpcanbasic.so")
if self.__m_dllBasic == None:
Expand All @@ -351,7 +353,7 @@ def Initialize(
HwType : NON PLUG&PLAY: The type of hardware and operation mode
IOPort : NON PLUG&PLAY: The I/O address for the parallel port
Interrupt: NON PLUG&PLAY: Interrupt number of the parallel port

Returns:
A TPCANStatus error code
"""
Expand All @@ -368,7 +370,7 @@ def InitializeFD(
BitrateFD):

"""
Initializes a FD capable PCAN Channel
Initializes a FD capable PCAN Channel

Parameters:
Channel : The handle of a FD capable PCAN Channel
Expand Down Expand Up @@ -401,13 +403,13 @@ def Uninitialize(

"""
Uninitializes one or all PCAN Channels initialized by CAN_Initialize

Remarks:
Giving the TPCANHandle value "PCAN_NONEBUS", uninitialize all initialized channels

Parameters:
Channel : A TPCANHandle representing a PCAN Channel

Returns:
A TPCANStatus error code
"""
Expand All @@ -424,13 +426,13 @@ def Reset(

"""
Resets the receive and transmit queues of the PCAN Channel

Remarks:
A reset of the CAN controller is not performed

Parameters:
Channel : A TPCANHandle representing a PCAN Channel

Returns:
A TPCANStatus error code
"""
Expand All @@ -447,10 +449,10 @@ def GetStatus(

"""
Gets the current status of a PCAN Channel

Parameters:
Channel : A TPCANHandle representing a PCAN Channel

Returns:
A TPCANStatus error code
"""
Expand All @@ -469,16 +471,16 @@ def Read(
Reads a CAN message from the receive queue of a PCAN Channel

Remarks:
The return value of this method is a 3-touple, where
The return value of this method is a 3-touple, where
the first value is the result (TPCANStatus) of the method.
The order of the values are:
[0]: A TPCANStatus error code
[1]: A TPCANMsg structure with the CAN message read
[2]: A TPCANTimestamp structure with the time when a message was read

Parameters:
Channel : A TPCANHandle representing a PCAN Channel

Returns:
A touple with three values
"""
Expand All @@ -499,16 +501,16 @@ def ReadFD(
Reads a CAN message from the receive queue of a FD capable PCAN Channel

Remarks:
The return value of this method is a 3-touple, where
The return value of this method is a 3-touple, where
the first value is the result (TPCANStatus) of the method.
The order of the values are:
[0]: A TPCANStatus error code
[1]: A TPCANMsgFD structure with the CAN message read
[2]: A TPCANTimestampFD that is the time when a message was read

Parameters:
Channel : The handle of a FD capable PCAN Channel

Returns:
A touple with three values
"""
Expand All @@ -527,12 +529,12 @@ def Write(
MessageBuffer):

"""
Transmits a CAN message
Transmits a CAN message

Parameters:
Channel : A TPCANHandle representing a PCAN Channel
MessageBuffer: A TPCANMsg representing the CAN message to be sent

Returns:
A TPCANStatus error code
"""
Expand All @@ -549,12 +551,12 @@ def WriteFD(
MessageBuffer):

"""
Transmits a CAN message over a FD capable PCAN Channel
Transmits a CAN message over a FD capable PCAN Channel

Parameters:
Channel : The handle of a FD capable PCAN Channel
MessageBuffer: A TPCANMsgFD buffer with the message to be sent

Returns:
A TPCANStatus error code
"""
Expand All @@ -578,14 +580,14 @@ def FilterMessages(
Remarks:
The message filter will be expanded with every call to this function.
If it is desired to reset the filter, please use the 'SetValue' function.

Parameters:
Channel : A TPCANHandle representing a PCAN Channel
FromID : A c_uint value with the lowest CAN ID to be received
ToID : A c_uint value with the highest CAN ID to be received
Mode : A TPCANMode representing the message type (Standard, 11-bit
Mode : A TPCANMode representing the message type (Standard, 11-bit
identifier, or Extended, 29-bit identifier)

Returns:
A TPCANStatus error code
"""
Expand All @@ -608,15 +610,15 @@ def GetValue(
Parameters can be present or not according with the kind
of Hardware (PCAN Channel) being used. If a parameter is not available,
a PCAN_ERROR_ILLPARAMTYPE error will be returned.
The return value of this method is a 2-touple, where

The return value of this method is a 2-touple, where
the first value is the result (TPCANStatus) of the method and
the second one, the asked value
the second one, the asked value

Parameters:
Channel : A TPCANHandle representing a PCAN Channel
Parameter : The TPCANParameter parameter to get

Returns:
A touple with 2 values
"""
Expand Down Expand Up @@ -646,13 +648,13 @@ def SetValue(
Parameters can be present or not according with the kind
of Hardware (PCAN Channel) being used. If a parameter is not available,
a PCAN_ERROR_ILLPARAMTYPE error will be returned.

Parameters:
Channel : A TPCANHandle representing a PCAN Channel
Parameter : The TPCANParameter parameter to set
Buffer : Buffer with the value to be set
BufferLength : Size in bytes of the buffer

Returns:
A TPCANStatus error code
"""
Expand Down Expand Up @@ -681,16 +683,16 @@ def GetErrorText(

The current languages available for translation are:
Neutral (0x00), German (0x07), English (0x09), Spanish (0x0A),
Italian (0x10) and French (0x0C)
Italian (0x10) and French (0x0C)

The return value of this method is a 2-touple, where
the first value is the result (TPCANStatus) of the method and
the second one, the error text

Parameters:
Error : A TPCANStatus error code
Language : Indicates a 'Primary language ID' (Default is Neutral(0))

Returns:
A touple with 2 values
"""
Expand Down
14 changes: 5 additions & 9 deletions can/interfaces/pcan/pcan.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@

class PcanBus(BusABC):

def __init__(self, channel, state=BusState.ACTIVE, *args, **kwargs):
def __init__(self, channel='PCAN_USBBUS1', state=BusState.ACTIVE, bitrate=500000, *args, **kwargs):
"""A PCAN USB interface to CAN.

On top of the usual :class:`~can.Bus` methods provided,
Expand All @@ -77,6 +77,7 @@ def __init__(self, channel, state=BusState.ACTIVE, *args, **kwargs):

:param str channel:
The can interface name. An example would be 'PCAN_USBBUS1'
Default is 'PCAN_USBBUS1'

:param can.bus.BusState state:
BusState of the channel.
Expand All @@ -87,12 +88,7 @@ def __init__(self, channel, state=BusState.ACTIVE, *args, **kwargs):
Default is 500 kbit/s.

"""
if not channel:
raise ArgumentError("Must specify a PCAN channel")
else:
self.channel_info = channel

bitrate = kwargs.get('bitrate', 500000)
self.channel_info = channel
pcan_bitrate = pcan_bitrate_objs.get(bitrate, PCAN_BAUD_500K)

hwtype = PCAN_TYPE_ISA
Expand All @@ -119,7 +115,7 @@ def __init__(self, channel, state=BusState.ACTIVE, *args, **kwargs):
if result != PCAN_ERROR_OK:
raise PcanError(self._get_formatted_error(result))

super(PcanBus, self).__init__(channel=channel, *args, **kwargs)
super(PcanBus, self).__init__(channel=channel, state=state, bitrate=bitrate, *args, **kwargs)

def _get_formatted_error(self, error):
"""
Expand Down Expand Up @@ -219,7 +215,7 @@ def _recv_internal(self, timeout):
bIsExt = (theMsg.MSGTYPE & PCAN_MESSAGE_EXTENDED.value) == PCAN_MESSAGE_EXTENDED.value

dlc = theMsg.LEN
timestamp = boottimeEpoch + ((itsTimeStamp.micros + (1000 * itsTimeStamp.millis)) / (1000.0 * 1000.0))
timestamp = boottimeEpoch + ((itsTimeStamp.micros + 1000 * itsTimeStamp.millis + 0x100000000 * 1000 * itsTimeStamp.millis_overflow) / (1000.0 * 1000.0))

rx_msg = Message(timestamp=timestamp,
arbitration_id=theMsg.ID,
Expand Down
35 changes: 30 additions & 5 deletions doc/interfaces/pcan.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,52 @@
PCAN Basic API
==============

.. warning::
Interface to `Peak-System <https://www.peak-system.com/?&L=1/>`__'s PCAN-Basic API.

This ``PCAN`` documentation is a work in progress. Feedback and revisions are most welcome!
Windows driver: https://www.peak-system.com/Downloads.76.0.html?&L=1

Linux driver: https://www.peak-system.com/fileadmin/media/linux/index.htm#download and https://www.peak-system.com/Downloads.76.0.html?&L=1 (PCAN-Basic API (Linux))

Interface to `Peak-System <http://www.peak-system.com/>`__'s PCAN-Basic API.
Mac driver: http://www.mac-can.com

Configuration
-------------

An example `can.ini` file for windows 7:
Here is an example configuration file for using `PCAN-USB <https://www.peak-system.com/PCAN-USB.199.0.html?&L=1>`_:

::

[default]
interface = pcan
channel = PCAN_USBBUS1
state = can.bus.BusState.PASSIVE
bitrate = 500000

``channel``: (default PCAN_USBBUS1) CAN interface name

``state``: (default can.bus.BusState.ACTIVE) BusState of the channel

``bitrate``: (default 500000) Channel bitrate

Valid ``channel`` values:

::

PCAN_ISABUSx
PCAN_DNGBUSx
PCAN_PCIBUSx
PCAN_USBBUSx
PCAN_PCCBUSx
PCAN_LANBUSx

Where ``x`` should be replaced with the desired channel number starting at 1.

Linux installation
------------------

Kernels >= 3.4 supports the PCAN adapters natively via :doc:`/interfaces/socketcan`, refer to: :ref:`socketcan-pcan`.

Bus
---

.. autoclass:: can.interfaces.pcan.PcanBus

Loading