Open Channel
============

Once we have imported `canlib.canlib` to enumerate the connected Kvaser CAN
devices, the next call is likely to be a call to `~canlib.canlib.openChannel`,
which returns a `~canlib.canlib.Channel` object for the specific CAN
circuit. This object is then used for subsequent calls to the library. The
`~canlib.canlib.openChannel` function's first argument is the number of the
desired channel, the second argument is modifier flags `canlib.canlib.Open`.

`~canlib.canlib.openChannel` may raise several different exceptions, one of
which is `~canlib.canlib.CanNotFound`. This means that the channel specified in
the first parameter was not found, or that the flags passed to
`~canlib.canlib.openChannel` is not applicable to the specified channel.


Open as CAN
-----------

No special `canlib.canlib.Open` modifier flag is needed in the flags argument to `~canlib.canlib.openChannel` when opening a channel in CAN mode.

    >>> from canlib import canlib
    >>> canlib.openChannel(channel=0, flags=canlib.Open.EXCLUSIVE)
    <canlib.canlib.channel.Channel object at 0x0000015B787EDA90>


Open as CAN FD
--------------

To open a channel in CAN FD mode, either `~canlib.canlib.Open.CAN_FD` or
`~canlib.canlib.Open.CAN_FD_NONISO` needs to be given in the flags argument to
`~canlib.canlib.openChannel`.

This example opens channel 0 in CAN FD mode for exclusive usage by this application::

    >>> from canlib import canlib
    >>> ch = canlib.openChannel(
    ...     channel=0,
    ...     flags=canlib.Open.CAN_FD | canlib.Open.EXCLUSIVE,
    ... )
    >>> ch.close()


Close Channel
-------------

Closing a channel is done using `~canlib.canlib.Channel.close`. If no other
handles are referencing the same CANlib channel, the channel is taken off
bus.

The CAN channel can also be opened and closed using a context manager::

    >>> from canlib import canlib
    >>> with canlib.openChannel(channel=1) as ch:
    ...     ...


.. _set_can_bitrate:

Set CAN Bitrate
---------------

Use `~canlib.canlib.Channel.set_bus_params_tq` to set the CAN bus parameters. Bus parameters, 
including the total nominal bit time and individual phase segements in number of 
time quanta etc, must be stored as attributes of an object of type `~canlib.canlib.busparams.BusParamsTq`. 
The synchronization segment is excluded as it is always one time quantum. 
    
To set the bus speed to 500 kbit/s on a CAN device with an 80 MHz oscillator:

    >>> from canlib import canlib
    >>> ch = canlib.openChannel(channel=0)
    >>> params = canlib.busparams.BusParamsTq(
    ...     tq=8, 
    ...     phase1=2, 
    ...     phase2=2, 
    ...     sjw=1, 
    ...     prescaler=20, 
    ...     prop=3
    ... )
    >>> ch.set_bus_params_tq(params)
    >>> ch.close()

In the example a prescaler of 20 is used, resulting in each bit comprising of 160 time quanta (8 * 20). 
The nominal bus speed is given by 80*10^6/(8*20) = 500*10^3.

The device clock frequency can be obtained via `ChannelData.clock_info.frequency():`

    >>> from canlib import canlib
    >>> chd = canlib.ChannelData(channel_number=0)
    >>> clock_info = chd.clock_info
    >>> clock_info.frequency()
    80000000

If uncertain how to set a specific bus speed, one can use `~canlib.canlib.busparams.calc_busparamstq`,
which returns a `~canlib.canlib.busparams.BusParamsTq` object:

    >>> params = canlib.busparams.calc_busparamstq(
    ... target_bitrate=470_000,
    ... target_sample_point=82,
    ... target_sync_jump_width=33.5,
    ... clk_freq=clock_freq
    ... )
    >>> params
    BusParamsTq(tq=170, prop=107, phase1=31, phase2=31, sjw=57, prescaler=1)

CANlib also provides a few default set of parameters for the most common 
bus speeds through the `canlib.canlib.canBITRATE_xxx` constants.
The predefined bit rates may be set directly in the call to 
`~canlib.canlib.openChannel`::

    >>> ch = canlib.openChannel(channel=0, bitrate=canlib.canBITRATE_500K)

If you do not specify a bitrate, a default bus speed of 500 kbit/s will be used.


Set CAN FD Bitrate
------------------

After opening a channel in CAN FD mode (passing either `~canlib.canlib.Open.CAN_FD` or 
`~canlib.canlib.Open.CAN_FD_NONISO` to `~canlib.canlib.openChannel`), parameters for both the arbitration 
and data phases need to be set. This is done by a call to `~canlib.canlib.Channel.set_bus_params_tq`, with 
individual `~canlib.canlib.busparams.BusParamsTq` objects for the arbitration phase and data phase as 
arguemnts.

**Example:** Set the arbitration phase bitrate to 500 kbit/s, with sampling point at 80% and the data phase bitrate to 
1000 kbit/s, with sampling point at 80%. Note that only prescaler values of 1 or 2 are valid as input for CAN FD. 
Also, identical prescaler values must be used for the arbitration and data bus parameter settings

    >>> from canlib import canlib
    >>> ch = canlib.openChannel(channel=0, flags=canlib.Open.CAN_FD)
    >>> params_arbitration = canlib.busparams.BusParamsTq(
    ...     tq=80, 
    ...     phase1=16, 
    ...     phase2=16, 
    ...     sjw=16, 
    ...     prescaler=2, 
    ...     prop=47
    ... )
    >>> params_data = canlib.busparams.BusParamsTq(
    ...     tq=40, 
    ...     phase1=31, 
    ...     phase2=8, 
    ...     sjw=8, 
    ...     prescaler=2, 
    ...     prop=0
    ... )
    >>> ch.set_bus_params_tq(params_arbitration, params_data)
    >>> ch.close()

CANlib also provides a few default set of parameters for the most common 
bus speeds through the `canlib.canlib.canFD_BITRATE_xxx` constants.
The predefined bit rates may be set directly in the call to 
`~canlib.canlib.openChannel`::

    >>> ch = canlib.openChannel(
    ...     channel=0,
    ...     flags=canlib.Open.CAN_FD,
    ...     bitrate=canlib.canlib.canFD_BITRATE_500K_80P,
    ...     data_bitrate=canlib.canFD_BITRATE_1M_80P,
    ... )

If you do not specify a bitrate, a default arbitration phase bitrate of 500 kbit/s 
and a data phase bitrate of 1 Mbit/s will be used.

For more copmplex settings of CAN FD bitrates, use the `Bit Timing Calculator
for CAN FD
<https://www.kvaser.com/support/calculators/can-fd-bit-timing-calculator/>`_
available on the Kvaser web site.

.. _can-driver-modes:

CAN Driver Modes
----------------

Use `~canlib.canlib.Channel.setBusOutputControl` to set the bus driver
mode. This is usually set to `canlib.canlib.Driver.NORMAL` to obtain the
standard push-pull type of driver. Some controllers also support
`canlib.canlib.Driver.SILENT` which makes the controller receive only, not
transmit anything, not even ACK bits. This might be handy for e.g. when
listening to a CAN bus without interfering.


    >>> from canlib import canlib
    >>> with canlib.openChannel(channel=1) as ch:
    ...     ch.setBusOutputControl(canlib.Driver.SILENT)
    ...     ...

`canlib.canlib.Driver.NORMAL` is set by default.


Legacy Functions
----------------

The following functions are still supported by canlib. It is, however, 
recomended to use later implementations instead, see `~canlib.canlib.Channel.set_bus_params_tq`.


Set CAN Bitrate
_______________

Use `~canlib.canlib.Channel.setBusParams` to set the CAN bus parameters. The bus parameters include the bit rate, the position of the sampling point etc, they are also described in most CAN controller data sheets. CANlib provides a few default set of parameters for the most common bus speeds through the `canlib.canlib.canBITRATE_xxx` constants.

To set the bus speed to 500 kbit/s::

    >>> from canlib import canlib
    >>> ch = canlib.openChannel(channel=1)
    >>> ch.setBusParams(canlib.canBITRATE_500K)
    >>> ch.close()

To set a bit rate that is not predefined, you have to calculate the appropriate
bus parameters yourself.

Set the speed to 125 kbit/s, each bit comprising 8 (= 1 + 4 + 3) quanta, the
sampling point occurs at 5/8 of a bit; SJW = 1; one sampling point::

   >>> ch.setBusParams(freq=125000, tseg1=4, tseg2=3, sjw=1, noSamp=1)


Set the speed to 111111 kbit/s, the sampling point to 75%, the SJW to 2 and the
number of samples to 1::

   >>> ch.setBusParams(freq=111111, tseg1=5, tseg2=2, sjw=2, noSamp=1)


Set CAN FD Bitrate
__________________

In CAN FD we need to set both the arbitration/nominal bitrate, using
`~canlib.canlib.Channel.setBusParams`, and the data phase bitrate, using
`~canlib.canlib.Channel.setBusParamsFd`. CANlib provides a few default set of
parameters for the most common CAN FD bus speeds through the
`canlib.canlib.canFD_BITRATE_xxx` constants.

Set the nominal bitrate to 500 kbit/s, with sampling point at 80% and the data phase bitrate to 1000 kbit/s, with sampling point at 80%::

    >>> with canlib.openChannel(channel=1, flags=canlib.Open.CAN_FD) as ch:
    ...     ch.setBusParams(canlib.canFD_BITRATE_500K_80P)
    ...     ch.setBusParamsFd(canlib.canFD_BITRATE_1M_80P)
    ...     ...


For more copmplex settings of CAN FD bitrates, use the `Bit Timing Calculator
for CAN FD
<https://www.kvaser.com/support/calculators/can-fd-bit-timing-calculator/>`_
available on the Kvaser web site.