chiark / gitweb /
Merge branch 'master' of github.com:daid/Cura
[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 = 'COM3', speed = 115200):\r
15                 if self.serial != None:\r
16                         self.close()\r
17                 try:\r
18                         self.serial = Serial(port, speed, timeout=1)\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         def isConnected(self):\r
42                 return self.serial != None\r
43         \r
44         def sendISP(self, data):\r
45                 recv = self.sendMessage([0x1D, 4, 4, 0, data[0], data[1], data[2], data[3]])\r
46                 return recv[2:6]\r
47         \r
48         def writeFlash(self, flashData):\r
49                 #Set load addr to 0, in case we have more then 64k flash we need to enable the address extension\r
50                 flashSize = self.chip['pageSize'] * 2 * self.chip['pageCount']\r
51                 if flashSize > 0xFFFF:\r
52                         self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])\r
53                 else:\r
54                         self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00])\r
55                 \r
56                 loadCount = (len(flashData) + 0xFF) / 0x100\r
57                 for i in xrange(0, loadCount):\r
58                         recv = self.sendMessage([0x13, 0x01, 0x00, 0xc1, 0x0a, 0x40, 0x4c, 0x20, 0x00, 0x00] + flashData[(i * 0x100):(i * 0x100 + 0x100)])\r
59                         if self.progressCallback != None:\r
60                                 self.progressCallback(i + 1, loadCount*2)\r
61         \r
62         def verifyFlash(self, flashData):\r
63                 #Set load addr to 0, in case we have more then 64k flash we need to enable the address extension\r
64                 flashSize = self.chip['pageSize'] * 2 * self.chip['pageCount']\r
65                 if flashSize > 0xFFFF:\r
66                         self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])\r
67                 else:\r
68                         self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00])\r
69                 \r
70                 loadCount = (len(flashData) + 0xFF) / 0x100\r
71                 for i in xrange(0, loadCount):\r
72                         recv = self.sendMessage([0x14, 0x01, 0x00, 0x20])[2:0x102]\r
73                         if self.progressCallback != None:\r
74                                 self.progressCallback(loadCount + i + 1, loadCount*2)\r
75                         for j in xrange(0, 0x100):\r
76                                 if i * 0x100 + j < len(flashData) and flashData[i * 0x100 + j] != recv[j]:\r
77                                         raise ispBase.IspError('Verify error at: 0x%x' % (i * 0x100 + j))\r
78 \r
79         def sendMessage(self, data):\r
80                 message = struct.pack(">BBHB", 0x1B, self.seq, len(data), 0x0E)\r
81                 for c in data:\r
82                         message += struct.pack(">B", c)\r
83                 checksum = 0\r
84                 for c in message:\r
85                         checksum ^= ord(c)\r
86                 message += struct.pack(">B", checksum)\r
87                 try:\r
88                         self.serial.write(message)\r
89                         self.serial.flush()\r
90                 except SerialTimeoutException:\r
91                         raise ispBase.IspError('Serial send timeout')\r
92                 self.seq = (self.seq + 1) & 0xFF\r
93                 return self.recvMessage()\r
94         \r
95         def recvMessage(self):\r
96                 state = 'Start'\r
97                 checksum = 0\r
98                 while True:\r
99                         s = self.serial.read()\r
100                         if len(s) < 1:\r
101                                 raise ispBase.IspError("Timeout")\r
102                         b = struct.unpack(">B", s)[0]\r
103                         checksum ^= b\r
104                         #print hex(b)\r
105                         if state == 'Start':\r
106                                 if b == 0x1B:\r
107                                         state = 'GetSeq'\r
108                                         checksum = 0x1B\r
109                         elif state == 'GetSeq':\r
110                                 state = 'MsgSize1'\r
111                         elif state == 'MsgSize1':\r
112                                 msgSize = b << 8\r
113                                 state = 'MsgSize2'\r
114                         elif state == 'MsgSize2':\r
115                                 msgSize |= b\r
116                                 state = 'Token'\r
117                         elif state == 'Token':\r
118                                 if b != 0x0E:\r
119                                         state = 'Start'\r
120                                 else:\r
121                                         state = 'Data'\r
122                                         data = []\r
123                         elif state == 'Data':\r
124                                 data.append(b)\r
125                                 if len(data) == msgSize:\r
126                                         state = 'Checksum'\r
127                         elif state == 'Checksum':\r
128                                 if checksum != 0:\r
129                                         state = 'Start'\r
130                                 else:\r
131                                         return data\r
132 \r
133 \r
134 def main():\r
135         programmer = Stk500v2()\r
136         programmer.connect()\r
137         programmer.programChip(intelHex.readHex("cfg_4f55234def059.hex"))\r
138         sys.exit(1)\r
139 \r
140 if __name__ == '__main__':\r
141         main()\r