LIN Master - Schedule Table Processing and Read

The free LIN software API (Application Programming Interface) for Windows® (only for usage with the PCAN-USB Pro CAN/LIN interface)
Post Reply
Volker.Schilling
Posts: 2
Joined: Tue 17. Mar 2020, 06:50

LIN Master - Schedule Table Processing and Read

Post by Volker.Schilling » Tue 17. Mar 2020, 06:59

Hello,

I'm trying to develop a LIN Master that is implemented using the PLinApi with Python 3. I want the Master to
run a schedule table on the hardware (this part is working fine) and read the BUS from the same hardware.
What I see is as soon as I read from a parallel thread the timings from the schedule table will not process proper.

- So, is it possible using the API to run an schedule table and do reads (logging of the bus) on the same hardware?
- How can this be realized? I tried multible threads.

Thanks,
Volker Schilling

M.Heidemann
Sales & Support
Sales & Support
Posts: 222
Joined: Fri 20. Sep 2019, 13:31

Re: LIN Master - Schedule Table Processing and Read

Post by M.Heidemann » Tue 17. Mar 2020, 11:54

Hello,

Can you please send us the necessary code (your sheduler implementation) , so we can assess the issue further?

Best Regards

Marvin

Volker.Schilling
Posts: 2
Joined: Tue 17. Mar 2020, 06:50

Re: LIN Master - Schedule Table Processing and Read

Post by Volker.Schilling » Wed 18. Mar 2020, 05:40

Hello Marvin,

this is the code:

Code: Select all

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import time
from ctypes import *

import PLinApi


class LinFuzzer(object):
    """
    """

    FRAME_FILTER_MASK = c_uint64(0xFFFFFFFFFFFFFFFF)

    GLOBAL_FRAME_TABLE = {        
        0x00: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x01: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x02: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x03: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x04: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x05: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x06: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x07: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x08: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x09: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x0A: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x0B: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x0C: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x0D: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x0E: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x0F: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},

        0x10: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x11: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x12: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x13: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x14: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x15: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x16: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x17: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x18: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x19: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x1A: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x1B: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x1C: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x1D: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x1E: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},
        0x1F: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},

        # 0x20: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},
        0x20: {"dir": PLinApi.TLIN_DIRECTION_PUBLISHER, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 2},

        0x21: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},
        0x22: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},
        0x23: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},
        0x24: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},
        0x25: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},
        0x26: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},
        0x27: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},
        0x28: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},
        0x29: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},

        # 0x2A: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},
        0x2A: {"dir": PLinApi.TLIN_DIRECTION_SUBSCRIBER, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},

        # 0x2B: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},
        0x2B: {"dir": PLinApi.TLIN_DIRECTION_PUBLISHER, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},

        0x2C: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},
        0x2D: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},
        0x2E: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},
        0x2F: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},

        # 0x30: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},
        0x30: {"dir": PLinApi.TLIN_DIRECTION_PUBLISHER, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},

        # 0x31: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},
        0x31: {"dir": PLinApi.TLIN_DIRECTION_PUBLISHER, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 4},

        # 0x32: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},
        0x32: {"dir": PLinApi.TLIN_DIRECTION_PUBLISHER, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 1},

        # 0x33: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},
        0x33: {"dir": PLinApi.TLIN_DIRECTION_SUBSCRIBER, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 1},

        0x34: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},
        0x35: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},
        0x36: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},

        # 0x37: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},
        0x37: {"dir": PLinApi.TLIN_DIRECTION_PUBLISHER, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},

        0x38: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},
        0x39: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},
        0x3A: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},
        0x3B: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},

        # 0x3C: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},
        0x3C: {"dir": PLinApi.TLIN_DIRECTION_PUBLISHER, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},

        # 0x3D: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},
        0x3D: {"dir": PLinApi.TLIN_DIRECTION_SUBSCRIBER, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},

        0x3E: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},
        0x3F: {"dir": PLinApi.TLIN_DIRECTION_DISABLED, "cst": PLinApi.TLIN_CHECKSUMTYPE_CLASSIC, "len": 8},
    }

    SCHEDULE_TABLE = [
        {"id": [0x37], "delay": 20, "type": PLinApi.TLIN_SLOTTYPE_UNCONDITIONAL},
        {"id": [0x33], "delay": 10, "type": PLinApi.TLIN_SLOTTYPE_UNCONDITIONAL},
        {"id": [0x32], "delay": 10, "type": PLinApi.TLIN_SLOTTYPE_UNCONDITIONAL},
        {"id": [0x2A], "delay": 20, "type": PLinApi.TLIN_SLOTTYPE_UNCONDITIONAL},
        {"id": [0x2B], "delay": 20, "type": PLinApi.TLIN_SLOTTYPE_UNCONDITIONAL},
        {"id": [0x30], "delay": 15, "type": PLinApi.TLIN_SLOTTYPE_UNCONDITIONAL},
        {"id": [0x31], "delay": 15, "type": PLinApi.TLIN_SLOTTYPE_UNCONDITIONAL},
        {"id": [0x20], "delay": 10, "type": PLinApi.TLIN_SLOTTYPE_UNCONDITIONAL},
        {"id": [0x2A], "delay": 20, "type": PLinApi.TLIN_SLOTTYPE_UNCONDITIONAL},
        {"id": [0x2B], "delay": 20, "type": PLinApi.TLIN_SLOTTYPE_UNCONDITIONAL},
    ]

    def __init__(self):
        """
        """
        self.m_objPLinApi = PLinApi.PLinApi()
        self.m_hClient = PLinApi.HLINCLIENT(0)
        self.m_hHw = PLinApi.HLINHW(0)
        self.m_HwMode = PLinApi.TLIN_HARDWAREMODE_MASTER
        self.m_HwBaudrate = c_ushort(9600)
        self.m_lMask = self.FRAME_FILTER_MASK

        if not self.m_objPLinApi.isLoaded():
            raise Exception("PLin-API could not be loaded ! Exiting...")

    def connect(self, name, device_number, channel_number):
        """
        :param name:
        :param device_number:
        :param channel_number:
        :return:
        """
        if self.m_objPLinApi.RegisterClient(name, None, self.m_hClient) != PLinApi.TLIN_ERROR_OK:
            raise Exception("Connect Failed")

        self.m_objPLinApi.ResetClient(self.m_hClient)

        self.m_hHw = PLinApi.HLINHW(device_number)

        if self.m_objPLinApi.ConnectClient(self.m_hClient, self.m_hHw) != PLinApi.TLIN_ERROR_OK:
            raise Exception("Connect Failed")

        mode = c_int(0)
        baudrate = c_int(0)

        if self.m_objPLinApi.GetHardwareParam(
                self.m_hHw, PLinApi.TLIN_HARDWAREPARAM_MODE, mode, 0) != PLinApi.TLIN_ERROR_OK:
            raise Exception("Connect Failed")
        if self.m_objPLinApi.GetHardwareParam(
                self.m_hHw, PLinApi.TLIN_HARDWAREPARAM_BAUDRATE, baudrate, 0) != PLinApi.TLIN_ERROR_OK:
            raise Exception("Connect Failed")

        self.m_objPLinApi.ResetHardware(self.m_hClient, self.m_hHw)

        if mode.value == PLinApi.TLIN_HARDWAREMODE_NONE.value or baudrate.value != self.m_HwBaudrate.value:
            if self.m_objPLinApi.InitializeHardware(
                    self.m_hClient, self.m_hHw, self.m_HwMode, self.m_HwBaudrate) != PLinApi.TLIN_ERROR_OK:
                raise Exception("Connect Failed")
            if self.m_objPLinApi.SetClientFilter(
                    self.m_hClient, self.m_hHw, self.m_lMask) != PLinApi.TLIN_ERROR_OK:
                raise Exception("Connect Failed")

    def disconnect(self):
        """
        :return:
        """

        if self.m_objPLinApi.DisconnectClient(self.m_hClient, self.m_hHw) == PLinApi.TLIN_ERROR_OK:
            self.m_hHw = PLinApi.HLINHW(0)
            self.m_objPLinApi.RemoveClient(self.m_hClient)

    def set_frame_entry(self, frameId, direction, cst, length):
        """
        :param frameId:
        :param direction:
        :param cst:
        :param length:
        :return:
        """
        frame_entry = PLinApi.TLINFrameEntry()
        frame_entry.FrameId = c_ubyte(frameId)
        frame_entry.ChecksumType = cst
        frame_entry.Direction = direction
        frame_entry.Length = c_ubyte(length)
        frame_entry.Flags = PLinApi.FRAME_FLAG_RESPONSE_ENABLE

        if self.m_objPLinApi.SetFrameEntry(self.m_hClient, self.m_hHw, frame_entry) == PLinApi.TLIN_ERROR_OK:
            mask = c_uint64(1 << frameId)
            self.m_lMask = c_uint64(self.m_lMask.value | mask.value)
            if self.m_objPLinApi.SetClientFilter(self.m_hClient, self.m_hHw, self.m_lMask) != PLinApi.TLIN_ERROR_OK:
                raise Exception("Connect Failed")

    def set_global_frame_table(self):
        """
        :return:
        """
        for frame_id in self.GLOBAL_FRAME_TABLE:
            entry = self.GLOBAL_FRAME_TABLE[frame_id]
            self.set_frame_entry(
                frameId=frame_id, direction=entry['dir'], cst=entry['cst'], length=entry['len'])

    def get_global_frame_table(self):
        """
        :return:
        """

        table = {}

        self.m_lMask = c_uint64(0x0)
        mask = c_uint64(0x0)

        for index in range(64):
            frame_entry = PLinApi.TLINFrameEntry()
            frame_entry.FrameId = c_ubyte(index)
            frame_entry.ChecksumType = PLinApi.TLIN_CHECKSUMTYPE_AUTO
            frame_entry.Direction = PLinApi.TLIN_DIRECTION_SUBSCRIBER_AUTOLENGTH

            if (index >= 0x00) and (index <= 0x1F):
                frame_entry.Length = c_ubyte(2)
            elif (index >= 0x20) and (index <= 0x2F):
                frame_entry.Length = c_ubyte(4)
            elif (index >= 0x30) and (index <= 0x3F):
                frame_entry.Length = c_ubyte(8)

            if self.m_objPLinApi.GetFrameEntry(self.m_hHw, frame_entry) == PLinApi.TLIN_ERROR_OK:

                table[frame_entry.FrameId] = {
                    "dir": frame_entry.Direction,
                    "cst": frame_entry.ChecksumType,
                    "len": frame_entry.Length
                }

                if frame_entry.Direction != PLinApi.TLIN_DIRECTION_DISABLED.value:
                    mask = c_uint64((1 << index) & self.FRAME_FILTER_MASK.value)
                    self.m_lMask = c_uint64(self.m_lMask.value | mask.value)

            if (self.m_hClient.value != 0) and (self.m_hHw.value != 0):
                self.m_objPLinApi.SetClientFilter(self.m_hClient, self.m_hHw, self.m_lMask)

        return table

    def set_schedule_table(self, tyble_id):
        """
        :param tyble_id:
        :return:
        """
        schedule_slot_array = (PLinApi.TLINScheduleSlot * len(self.SCHEDULE_TABLE))
        schedule_table = schedule_slot_array()

        for index, entry in enumerate(self.SCHEDULE_TABLE):
            schedule_entry = PLinApi.TLINScheduleSlot()

            for pos, frameId in enumerate(entry["id"]):
                schedule_entry.FrameId[pos] = c_ubyte(frameId)
            schedule_entry.Type = entry["type"]
            schedule_entry.Delay = c_ushort(entry["delay"])
            schedule_entry.CountResolve = c_ubyte(0)

            schedule_table[index] = schedule_entry

        self.m_objPLinApi.SetSchedule(self.m_hClient, self.m_hHw, tyble_id, schedule_table, len(self.SCHEDULE_TABLE))

    def get_schedule_table(self, tyble_id):
        """
        :param tyble_id:
        :return:
        """
        schedule_slot_array = (PLinApi.TLINScheduleSlot * 256)
        schedule_table = schedule_slot_array()

        count = c_int(0)
        self.m_objPLinApi.GetSchedule(self.m_hHw, tyble_id, schedule_table, c_int(256), count)

        for index in range(count.value):
            schedule_entry = schedule_table[index]
            print(
                schedule_entry.Type,
                schedule_entry.Delay,
                schedule_entry.FrameId[0],
                schedule_entry.CountResolve,
                schedule_entry.Handle
            )

    def delete_schedule_table(self, table_id):
        """
        :param table_id:
        :return:
        """
        self.m_objPLinApi.DeleteSchedule(self.m_hClient, self.m_hHw, table_id)

    def start_schedule_table(self, table_id):
        """
        :param table_id:
        :return:
        """
        self.m_objPLinApi.StartSchedule(self.m_hClient, self.m_hHw, table_id)

    def resume_schedule_table(self):
        """
        :return:
        """
        self.m_objPLinApi.ResumeSchedule(self.m_hClient, self.m_hHw)

    def suspend_schedule_table(self):
        """
        :return:
        """
        self.m_objPLinApi.SuspendSchedule(self.m_hClient, self.m_hHw)

    def update_schedule_data(self, frame_id, data=[]):
        """
        :param frame_id:
        :param data:
        :return:
        """

        raw_data = (c_ubyte * len(data))()
        for index, byte in enumerate(data):
            raw_data[index] = c_ubyte(byte)

        self.m_objPLinApi.UpdateByteArray(self.m_hClient, self.m_hHw, c_ubyte(frame_id), 0, c_ubyte(len(data)), raw_data)

    def write_frame(self, frame_id, data=[]):
        """
        :param frame_id:
        :param data:
        :return:
        """

        frame_entry = PLinApi.TLINFrameEntry()
        frame_entry.FrameId = c_ubyte(frame_id)
        self.m_objPLinApi.GetFrameEntry(self.m_hHw, frame_entry)

        msg = PLinApi.TLINMsg()
        msg.Direction = PLinApi.TLINDirection(frame_entry.Direction)
        msg.ChecksumType = PLinApi.TLINChecksumType(frame_entry.ChecksumType)
        msg.Length = c_ubyte(frame_entry.Length)

        for index in range(frame_entry.Length):
            msg.Data[index] = c_ubyte(data[index])

        private_id = c_ubyte(frame_id)
        self.m_objPLinApi.GetPID(private_id)
        msg.FrameId = c_ubyte(private_id.value)
        self.m_objPLinApi.CalculateChecksum(msg)
        self.m_objPLinApi.Write(self.m_hClient, self.m_hHw, msg)

    def read(self):
        """
        :return:
        """
        msg_buffer = {}

        while True:
            msg = PLinApi.TLINRcvMsg()
            if self.m_objPLinApi.Read(self.m_hClient, msg) == PLinApi.TLIN_ERROR_OK:
                delta = ((msg.TimeStamp - msg_buffer.setdefault(msg.FrameId, msg.TimeStamp)) / 1000.0)
                msg_buffer[msg.FrameId] = msg.TimeStamp

                if msg.Length == 1:
                    print("{} ({:>14}) : 0x{:02X} {} - {:02X} [{}]".format(
                        msg.TimeStamp, delta, msg.FrameId, msg.Length,
                        msg.Data[0], msg.ErrorFlags)
                    )
                elif msg.Length == 2:
                    print("{} ({:>14}) : 0x{:02X} {} - {:02X} {:02X} [{}]".format(
                        msg.TimeStamp, delta, msg.FrameId, msg.Length,
                        msg.Data[0],
                        msg.Data[1], msg.ErrorFlags)
                    )
                elif msg.Length == 3:
                    print("{} ({:>14}) : 0x{:02X} {} - {:02X} {:02X} {:02X} [{}]".format(
                        msg.TimeStamp, delta, msg.FrameId, msg.Length,
                        msg.Data[0],
                        msg.Data[1],
                        msg.Data[2], msg.ErrorFlags)
                    )
                elif msg.Length == 4:
                    print("{} ({:>14}) : 0x{:02X} {} - {:02X} {:02X} {:02X} {:02X} [{}]".format(
                        msg.TimeStamp, delta, msg.FrameId, msg.Length,
                        msg.Data[0],
                        msg.Data[1],
                        msg.Data[2],
                        msg.Data[3], msg.ErrorFlags)
                    )
                elif msg.Length == 5:
                    print("{} ({:>14}) : 0x{:02X} {} - {:02X} {:02X} {:02X} {:02X} {:02X} [{}]".format(
                        msg.TimeStamp, delta, msg.FrameId, msg.Length,
                        msg.Data[0],
                        msg.Data[1],
                        msg.Data[2],
                        msg.Data[3],
                        msg.Data[4], msg.ErrorFlags)
                    )
                elif msg.Length == 6:
                    print("{} ({:>14}) : 0x{:02X} {} - {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} [{}]".format(
                        msg.TimeStamp, delta, msg.FrameId, msg.Length,
                        msg.Data[0],
                        msg.Data[1],
                        msg.Data[2],
                        msg.Data[3],
                        msg.Data[4],
                        msg.Data[5], msg.ErrorFlags)
                    )
                elif msg.Length == 7:
                    print("{} ({:>14}) : 0x{:02X} {} - {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} [{}]".format(
                        msg.TimeStamp, delta, msg.FrameId, msg.Length,
                        msg.Data[0],
                        msg.Data[1],
                        msg.Data[2],
                        msg.Data[3],
                        msg.Data[4],
                        msg.Data[5],
                        msg.Data[6], msg.ErrorFlags)
                    )
                elif msg.Length == 8:
                    print("{} ({:>14}) : 0x{:02X} {} - {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} [{}]".format(
                        msg.TimeStamp, delta, msg.FrameId, msg.Length,
                        msg.Data[0],
                        msg.Data[1],
                        msg.Data[2],
                        msg.Data[3],
                        msg.Data[4],
                        msg.Data[5],
                        msg.Data[6],
                        msg.Data[7], msg.ErrorFlags)
                    )

            time.sleep(0.000001)


if __name__ == '__main__':

    import threading

    fuzzer = LinFuzzer()
    fuzzer.connect("Fuzzer", 1, 1)
    fuzzer.set_global_frame_table()

    fuzzer.delete_schedule_table(0)
    fuzzer.set_schedule_table(0)
    fuzzer.get_schedule_table(0)

    fuzzer.update_schedule_data(0x32, [0x00])
    fuzzer.update_schedule_data(0x2B, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
    fuzzer.update_schedule_data(0x30, [0x00, 0x00, 0x00, 0x00])
    fuzzer.update_schedule_data(0x31, [0x00, 0x00, 0x00, 0x00])
    fuzzer.update_schedule_data(0x20, [0x00, 0x00])
    fuzzer.update_schedule_data(0x37, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])

[b]    readThread = threading.Thread(target=fuzzer.read, args=(,))
    readThread.start()[/b]

    fuzzer.start_schedule_table(0)
    time.sleep(5)
    fuzzer.suspend_schedule_table()
    
[b]    readThread.join()[/b]
    
    fuzzer.delete_schedule_table(0)

    fuzzer.disconnect()
    
If I add the readThread part, then the timings (Interval ov the Frames) are not correct.
Whats wrong with this approach?

Thanks,
Volker
Last edited by M.Heidemann on Wed 18. Mar 2020, 07:55, edited 1 time in total.
Reason: Used the "Code"-Tag on the code posted for improved readability, please use the code-tags when posting code-snippets.

M.Heidemann
Sales & Support
Sales & Support
Posts: 222
Joined: Fri 20. Sep 2019, 13:31

Re: LIN Master - Schedule Table Processing and Read

Post by M.Heidemann » Wed 18. Mar 2020, 13:51

Hello Volker,

To quote:
If I add the readThread part, then the timings (Interval ov the Frames) are not correct.
Do you mean the delays between the messages of the shedule table?

As an additional info:

Once the shedule-table is started, it runs independently on the hardware.


Best Regards

Marvin

Post Reply