chiark / gitweb /
Enable support cross hatch when printing with dual-extrusion support.
[cura.git] / Cura / avr_isp / stk500v2.py
1 import os, struct, sys, time\r
2 \r
3 from serial import Serial\r
4 from serial import SerialException\r
5 \r
6 import ispBase, intelHex\r
7 \r
8 class Stk500v2(ispBase.IspBase):\r
9         def __init__(self):\r
10                 self.serial = None\r
11                 self.seq = 1\r
12                 self.lastAddr = -1\r
13         \r
14         def connect(self, port = 'COM31', speed = 115200):\r
15                 if self.serial != None:\r
16                         self.close()\r
17                 try:\r
18                         self.serial = Serial(port, speed, timeout=1, writeTimeout=10000)\r
19                 except SerialException as e:\r
20                         raise ispBase.IspError("Failed to open serial port")\r
21                 except:\r
22                         raise ispBase.IspError("Unexpected error while connecting to serial port:" + port + ":" + str(sys.exc_info()[0]))\r
23                 self.seq = 1\r
24                 \r
25                 #Reset the controller\r
26                 self.serial.setDTR(1)\r
27                 time.sleep(0.1)\r
28                 self.serial.setDTR(0)\r
29                 time.sleep(0.2)\r
30                 \r
31                 self.sendMessage([1])\r
32                 if self.sendMessage([0x10, 0xc8, 0x64, 0x19, 0x20, 0x00, 0x53, 0x03, 0xac, 0x53, 0x00, 0x00]) != [0x10, 0x00]:\r
33                         self.close()\r
34                         raise ispBase.IspError("Failed to enter programming mode")\r
35 \r
36         def close(self):\r
37                 if self.serial != None:\r
38                         self.serial.close()\r
39                         self.serial = None\r
40 \r
41         #Leave ISP does not reset the serial port, only resets the device, and returns the serial port after disconnecting it from the programming interface.\r
42         #       This allows you to use the serial port without opening it again.\r
43         def leaveISP(self):\r
44                 if self.serial != None:\r
45                         if self.sendMessage([0x11]) != [0x11, 0x00]:\r
46                                 raise ispBase.IspError("Failed to leave programming mode")\r
47                         ret = self.serial\r
48                         self.serial = None\r
49                         return ret\r
50                 return None\r
51         \r
52         def isConnected(self):\r
53                 return self.serial != None\r
54         \r
55         def sendISP(self, data):\r
56                 recv = self.sendMessage([0x1D, 4, 4, 0, data[0], data[1], data[2], data[3]])\r
57                 return recv[2:6]\r
58         \r
59         def writeFlash(self, flashData):\r
60                 #Set load addr to 0, in case we have more then 64k flash we need to enable the address extension\r
61                 pageSize = self.chip['pageSize'] * 2\r
62                 flashSize = pageSize * self.chip['pageCount']\r
63                 if flashSize > 0xFFFF:\r
64                         self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])\r
65                 else:\r
66                         self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00])\r
67                 \r
68                 loadCount = (len(flashData) + pageSize - 1) / pageSize\r
69                 for i in xrange(0, loadCount):\r
70                         recv = self.sendMessage([0x13, pageSize >> 8, pageSize & 0xFF, 0xc1, 0x0a, 0x40, 0x4c, 0x20, 0x00, 0x00] + flashData[(i * pageSize):(i * pageSize + pageSize)])\r
71                         if self.progressCallback != None:\r
72                                 self.progressCallback(i + 1, loadCount*2)\r
73         \r
74         def verifyFlash(self, flashData):\r
75                 #Set load addr to 0, in case we have more then 64k flash we need to enable the address extension\r
76                 flashSize = self.chip['pageSize'] * 2 * self.chip['pageCount']\r
77                 if flashSize > 0xFFFF:\r
78                         self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])\r
79                 else:\r
80                         self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00])\r
81                 \r
82                 loadCount = (len(flashData) + 0xFF) / 0x100\r
83                 for i in xrange(0, loadCount):\r
84                         recv = self.sendMessage([0x14, 0x01, 0x00, 0x20])[2:0x102]\r
85                         if self.progressCallback != None:\r
86                                 self.progressCallback(loadCount + i + 1, loadCount*2)\r
87                         for j in xrange(0, 0x100):\r
88                                 if i * 0x100 + j < len(flashData) and flashData[i * 0x100 + j] != recv[j]:\r
89                                         raise ispBase.IspError('Verify error at: 0x%x' % (i * 0x100 + j))\r
90 \r
91         def sendMessage(self, data):\r
92                 message = struct.pack(">BBHB", 0x1B, self.seq, len(data), 0x0E)\r
93                 for c in data:\r
94                         message += struct.pack(">B", c)\r
95                 checksum = 0\r
96                 for c in message:\r
97                         checksum ^= ord(c)\r
98                 message += struct.pack(">B", checksum)\r
99                 try:\r
100                         self.serial.write(message)\r
101                         self.serial.flush()\r
102                 except SerialTimeoutException:\r
103                         raise ispBase.IspError('Serial send timeout')\r
104                 self.seq = (self.seq + 1) & 0xFF\r
105                 return self.recvMessage()\r
106         \r
107         def recvMessage(self):\r
108                 state = 'Start'\r
109                 checksum = 0\r
110                 while True:\r
111                         s = self.serial.read()\r
112                         if len(s) < 1:\r
113                                 raise ispBase.IspError("Timeout")\r
114                         b = struct.unpack(">B", s)[0]\r
115                         checksum ^= b\r
116                         #print(hex(b))\r
117                         if state == 'Start':\r
118                                 if b == 0x1B:\r
119                                         state = 'GetSeq'\r
120                                         checksum = 0x1B\r
121                         elif state == 'GetSeq':\r
122                                 state = 'MsgSize1'\r
123                         elif state == 'MsgSize1':\r
124                                 msgSize = b << 8\r
125                                 state = 'MsgSize2'\r
126                         elif state == 'MsgSize2':\r
127                                 msgSize |= b\r
128                                 state = 'Token'\r
129                         elif state == 'Token':\r
130                                 if b != 0x0E:\r
131                                         state = 'Start'\r
132                                 else:\r
133                                         state = 'Data'\r
134                                         data = []\r
135                         elif state == 'Data':\r
136                                 data.append(b)\r
137                                 if len(data) == msgSize:\r
138                                         state = 'Checksum'\r
139                         elif state == 'Checksum':\r
140                                 if checksum != 0:\r
141                                         state = 'Start'\r
142                                 else:\r
143                                         return data\r
144 \r
145 \r
146 def main():\r
147         programmer = Stk500v2()\r
148         programmer.connect()\r
149         programmer.programChip(intelHex.readHex("cfg_4f55234def059.hex"))\r
150         sys.exit(1)\r
151 \r
152 if __name__ == '__main__':\r
153         main()\r