448
|
1 |
import serial
|
453
|
2 |
import exceptions
|
|
3 |
import ctypes
|
|
4 |
import time
|
448
|
5 |
from threading import Lock
|
|
6 |
|
|
7 |
LPC_STATUS=dict(STARTED = 0x01,
|
|
8 |
STOPPED = 0x02,
|
|
9 |
DEBUG = 0x03)
|
|
10 |
|
|
11 |
class LPCError(exceptions.Exception):
|
|
12 |
"""Exception class"""
|
|
13 |
def __init__(self, msg):
|
|
14 |
self.msg = msg
|
|
15 |
return
|
|
16 |
|
|
17 |
def __str__(self):
|
|
18 |
return "LPC communication error ! " + str(self.msg)
|
|
19 |
|
|
20 |
class LPCProto:
|
|
21 |
def __init__(self, port, rate, timeout):
|
453
|
22 |
# serialize access lock
|
|
23 |
self.TransactionLock = Lock()
|
448
|
24 |
# open serial port
|
453
|
25 |
# self.serialPort = serial.Serial( port, rate, timeout = timeout )
|
|
26 |
# Debugging serial stuff
|
|
27 |
self._serialPort = serial.Serial( port, rate, timeout = timeout )
|
|
28 |
class myser:
|
|
29 |
def read(self_,cnt):
|
|
30 |
res = self._serialPort.read(cnt)
|
|
31 |
print "Recv :", map(hex,map(ord,res))
|
|
32 |
return res
|
|
33 |
def write(self_, str):
|
|
34 |
print "Send :", map(hex,map(ord,str))
|
|
35 |
self._serialPort.write(str)
|
|
36 |
def flush(self_):
|
|
37 |
self._serialPort.flush()
|
|
38 |
self.serialPort = myser()
|
|
39 |
# start with empty
|
448
|
40 |
self.serialPort.flush()
|
|
41 |
# handshake
|
453
|
42 |
self.HandleTransaction(IDLETransaction())
|
448
|
43 |
|
|
44 |
def HandleTransaction(self, transaction):
|
|
45 |
self.TransactionLock.acquire()
|
|
46 |
try:
|
|
47 |
transaction.SetPseudoFile(self.serialPort)
|
|
48 |
# send command, wait ack (timeout)
|
|
49 |
transaction.SendCommand()
|
|
50 |
current_plc_status = transaction.GetCommandAck()
|
|
51 |
if current_plc_status is not None:
|
|
52 |
res = transaction.ExchangeData()
|
|
53 |
else:
|
|
54 |
raise LPCError("LPC transaction error - controller did not answer as expected")
|
|
55 |
finally:
|
|
56 |
self.TransactionLock.release()
|
|
57 |
return current_plc_status, res
|
|
58 |
|
|
59 |
class LPCTransaction:
|
453
|
60 |
def __init__(self, command, optdata = ""):
|
|
61 |
self.Command = command
|
|
62 |
self.OptData = optdata
|
|
63 |
self.pseudofile = None
|
448
|
64 |
|
453
|
65 |
def SetPseudoFile(self, pseudofile):
|
448
|
66 |
self.pseudofile = pseudofile
|
|
67 |
|
|
68 |
def SendCommand(self):
|
|
69 |
# send command thread
|
|
70 |
self.pseudofile.write(chr(self.Command))
|
|
71 |
|
|
72 |
def GetCommandAck(self):
|
453
|
73 |
res = self.pseudofile.read(2)
|
|
74 |
if len(res) == 2:
|
|
75 |
comm_status, current_plc_status = map(ord, res)
|
|
76 |
else:
|
|
77 |
raise LPCError("LPC transaction error - controller did not ack order")
|
448
|
78 |
# LPC returns command itself as an ack for command
|
|
79 |
if(comm_status == self.Command):
|
|
80 |
return current_plc_status
|
|
81 |
return None
|
|
82 |
|
453
|
83 |
def SendData(self):
|
|
84 |
length = len(self.OptData)
|
|
85 |
# transform length into a byte string
|
|
86 |
# we presuppose endianess of LPC same as PC
|
|
87 |
lengthstr = ctypes.string_at(ctypes.pointer(ctypes.c_int(length)),4)
|
|
88 |
self.pseudofile.write(lengthstr + self.OptData)
|
|
89 |
|
|
90 |
def GetData(self):
|
|
91 |
lengthstr = self.pseudofile.read(4)
|
|
92 |
# transform a byte string into length
|
|
93 |
length = ctypes.cast(ctypes.c_char_p(lengthstr), ctypes.POINTER(ctypes.c_int)).contents.value
|
|
94 |
return self.pseudofile.read(length)
|
|
95 |
|
|
96 |
def ExchangeData(self):
|
|
97 |
pass
|
|
98 |
|
|
99 |
class IDLETransaction(LPCTransaction):
|
|
100 |
def __init__(self):
|
|
101 |
LPCTransaction.__init__(self, 0x00)
|
|
102 |
|
|
103 |
class STARTTransaction(LPCTransaction):
|
|
104 |
def __init__(self):
|
|
105 |
LPCTransaction.__init__(self, 0x01)
|
|
106 |
|
|
107 |
class STOPTransaction(LPCTransaction):
|
|
108 |
def __init__(self):
|
|
109 |
LPCTransaction.__init__(self, 0x02)
|
|
110 |
|
|
111 |
class SET_TRACE_VARIABLETransaction(LPCTransaction):
|
|
112 |
def __init__(self, data):
|
|
113 |
LPCTransaction.__init__(self, 0x04, data)
|
|
114 |
ExchangeData = LPCTransaction.SendData
|
|
115 |
|
|
116 |
class GET_TRACE_VARIABLETransaction(LPCTransaction):
|
|
117 |
def __init__(self):
|
|
118 |
LPCTransaction.__init__(self, 0x05)
|
|
119 |
ExchangeData = LPCTransaction.GetData
|
|
120 |
|
|
121 |
class SET_FORCED_VARIABLETransaction(LPCTransaction):
|
|
122 |
def __init__(self, data):
|
|
123 |
LPCTransaction.__init__(self, 0x06, data)
|
|
124 |
ExchangeData = LPCTransaction.SendData
|
|
125 |
|
|
126 |
class GET_PLCIDTransaction(LPCTransaction):
|
|
127 |
def __init__(self):
|
|
128 |
LPCTransaction.__init__(self, 0x07)
|
|
129 |
ExchangeData = LPCTransaction.GetData
|
|
130 |
|
448
|
131 |
if __name__ == "__main__":
|
453
|
132 |
TestConnection = LPCProto(6,115200,2)
|
|
133 |
#TestConnection.HandleTransaction(GET_PLCIDTransaction())
|
|
134 |
TestConnection.HandleTransaction(STARTTransaction())
|
|
135 |
TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction(
|
|
136 |
"\x03\x00\x00\x00"))
|
|
137 |
TestConnection.HandleTransaction(STARTTransaction())
|
|
138 |
while True:
|
|
139 |
time.sleep(0.5)
|
|
140 |
TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction(
|
|
141 |
"\x01\x00\x00\x00"*31))
|
|
142 |
#print map(hex,map(ord,TestConnection.HandleTransaction(GET_TRACE_VARIABLETransaction())))
|
|
143 |
#TestConnection.HandleTransaction(STOPTransaction())
|