Commit 69237751 authored by Michael Buesch's avatar Michael Buesch
Browse files

phy_serial: Some simple speed optimizations

Signed-off-by: default avatarMichael Buesch <m@bues.ch>
parent 4914b589
......@@ -3,7 +3,7 @@
#
# PROFIBUS - Telegram sniffer
#
# Copyright (c) 2016 Michael Buesch <m@bues.ch>
# Copyright (c) 2016-2020 Michael Buesch <m@bues.ch>
#
# Licensed under the terms of the GNU General Public License version 2,
# or (at your option) any later version.
......@@ -12,6 +12,7 @@
from pyprofibus.phy_serial import *
from pyprofibus.fdl import *
from pyprofibus import *
import sys
import getopt
......@@ -55,7 +56,7 @@ def main():
try:
while True:
try:
ok, telegram = xceiv.poll(-1)
ok, telegram = xceiv.poll(-1.0)
if not ok or not telegram:
continue
print(telegram)
......
......@@ -44,7 +44,7 @@ class DpTransceiver(object):
self.fdlTrans = fdlTrans
self.thisIsMaster = thisIsMaster
def poll(self, timeout = 0):
def poll(self, timeout=0.0):
retTelegram = None
ok, fdlTelegram = self.fdlTrans.poll(timeout)
if ok and fdlTelegram:
......
......@@ -107,7 +107,7 @@ class FdlTransceiver(object):
# Accept the packet, if it's in the RX filter.
return (telegram.da & FdlTelegram.ADDRESS_MASK) in self.__rxFilter
def poll(self, timeout=0):
def poll(self, timeout=0.0):
ok, telegram = False, None
reply = self.phy.poll(timeout)
if reply is not None:
......@@ -205,6 +205,14 @@ class FdlTelegram(object):
FC_MRDY = 0x20 # Master, ready to enter token ring
FC_MTR = 0x30 # Master, in token ring
# Delimiter to size converstion table.
delim2size = {
SD1 : 6,
SD3 : 14,
SD4 : 3,
SC : 1,
}
__slots__ = (
"sd",
"haveLE",
......@@ -220,27 +228,22 @@ class FdlTelegram(object):
@classmethod
def getSizeFromRaw(cls, data):
try:
sd = data[0]
try:
return {
cls.SD1 : 6,
cls.SD3 : 14,
cls.SD4 : 3,
cls.SC : 1,
}[sd]
except KeyError:
pass
if sd == cls.SD2:
le = data[1]
if data[2] != le:
raise FdlError("Repeated length field mismatch")
if le < 3 or le > 249:
raise FdlError("Invalid LE field")
return le + 6
raise FdlError("Unknown start delimiter: %02X" % sd)
except IndexError:
raise FdlError("Invalid FDL packet format")
dataLen = len(data)
if dataLen < 1:
return None # Telegram too short.
sd = data[0]
if sd in cls.delim2size:
return cls.delim2size[sd]
if sd == cls.SD2:
if dataLen < 3:
return None # Telegram too short.
le = data[1]
if data[2] != le:
return None # Repeated length field mismatch.
if le < 3 or le > 249:
return None # Invalid length field.
return le + 6
return None # Unknown start delimiter.
def __init__(self, sd, haveLE=False, da=None, sa=None,
fc=None, dae=b"", sae=b"", du=None,
......
......@@ -83,15 +83,15 @@ class CpPhy(object):
def pollData(self, timeout):
"""Poll received data from the physical line.
timeout => timeout in seconds.
0 = no timeout, return immediately.
0.0 = no timeout, return immediately.
negative = unlimited.
Reimplement this method in the PHY driver.
"""
raise NotImplementedError
def poll(self, timeout = 0):
def poll(self, timeout=0.0):
"""timeout => timeout in seconds.
0 = no timeout, return immediately.
0.0 = no timeout, return immediately.
negative = unlimited.
"""
if self.__txQueueDAs:
......
......@@ -50,10 +50,10 @@ class CpPhyDummySlave(CpPhy):
bytesToHex(telegramData)))
self.__mockSend(telegramData, srd = srd)
def pollData(self, timeout = 0):
def pollData(self, timeout=0.0):
"""Poll received data from the physical line.
timeout => timeout in seconds.
0 = no timeout, return immediately.
0.0 = no timeout, return immediately.
negative = unlimited.
"""
try:
......
......@@ -87,7 +87,7 @@ class CpPhyFPGA(CpPhy):
if self.__rxDeque:
telegramData = self.__rxDeque.popleft()
else:
timeoutStamp = monotonic_time() + timeout
timeoutStamp = monotonic_time() + timeout#TODO
telegramDataList = self.__driver.telegramReceive()
count = len(telegramDataList)
if count >= 1:
......
......@@ -107,49 +107,52 @@ class CpPhySerial(CpPhy):
self.__discardTimeout = monotonic_time() + 0.01
# Poll for received packet.
# timeout => In seconds. 0 = none, Negative = unlimited.
def pollData(self, timeout = 0):
timeoutStamp = monotonic_time() + timeout
ret, rxBuf, s, size = None, self.__rxBuf, self.__serial, -1
# timeout => In seconds. 0.0 = none, Negative = unlimited.
def pollData(self, timeout=0.0):
if timeout > 0.0:
timeoutStamp = monotonic_time() + timeout
ret = None
rxBuf = self.__rxBuf
ser = self.__serial
size = -1
getSize = FdlTelegram.getSizeFromRaw
if self.__discardTimeout is not None:
while self.__discardTimeout is not None:
self.__discard()
if timeout >= 0 and\
monotonic_time() >= timeoutStamp:
if (timeout == 0.0 or
(timeout > 0.0 and monotonic_time() >= timeoutStamp)):
return None
try:
rxBufLen = len(rxBuf)
while True:
if len(rxBuf) < 1:
rxBuf += s.read(1)
elif len(rxBuf) < 3:
try:
size = getSize(rxBuf)
readLen = size
except ProfibusError:
readLen = 3
rxBuf += s.read(readLen - len(rxBuf))
elif len(rxBuf) >= 3:
try:
size = getSize(rxBuf)
except ProfibusError:
if rxBufLen < 1:
rxBuf.extend(ser.read(1))
elif rxBufLen < 3:
size = getSize(rxBuf)
readLen = 3 if size is None else size
rxBuf.extend(ser.read(readLen - rxBufLen))
elif rxBufLen >= 3:
size = getSize(rxBuf)
if size is None:
rxBuf = bytearray()
self.__startDiscard()
raise PhyError("PHY-serial: "
"Failed to get received "
"telegram size:\n"
"Failed to get received telegram size: "
"Invalid telegram format.")
if len(rxBuf) < size:
rxBuf += s.read(size - len(rxBuf))
if len(rxBuf) == size:
ret, rxBuf = rxBuf, bytearray()
if rxBufLen < size:
rxBuf.extend(ser.read(size - rxBufLen))
rxBufLen = len(rxBuf)
if rxBufLen == size:
ret = rxBuf
rxBuf = bytearray()
rxBufLen = 0
break
if timeout >= 0 and\
monotonic_time() >= timeoutStamp:
if (timeout == 0.0 or
(timeout > 0.0 and monotonic_time() >= timeoutStamp)):
break
except serial.SerialException as e:
rxBuf = bytearray()
......@@ -166,7 +169,6 @@ class CpPhySerial(CpPhy):
if self.__discardTimeout is not None:
return
try:
telegramData = bytearray(telegramData)
if self.debug:
print("PHY-serial: TX %s" % bytesToHex(telegramData))
self.__serial.write(telegramData)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment