]> sigrok.org Git - libsigrokdecode.git/blame - decoders/avr_isp/pd.py
Mark all stacked decoders as being PD API version 3.
[libsigrokdecode.git] / decoders / avr_isp / pd.py
CommitLineData
3bd76451 1##
50bd5d25 2## This file is part of the libsigrokdecode project.
3bd76451 3##
ad30cb46 4## Copyright (C) 2012-2014 Uwe Hermann <uwe@hermann-uwe.de>
3bd76451
UH
5##
6## This program is free software; you can redistribute it and/or modify
7## it under the terms of the GNU General Public License as published by
8## the Free Software Foundation; either version 2 of the License, or
9## (at your option) any later version.
10##
11## This program is distributed in the hope that it will be useful,
12## but WITHOUT ANY WARRANTY; without even the implied warranty of
13## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14## GNU General Public License for more details.
15##
16## You should have received a copy of the GNU General Public License
4539e9ca 17## along with this program; if not, see <http://www.gnu.org/licenses/>.
3bd76451
UH
18##
19
3bd76451 20import sigrokdecode as srd
77adad94 21from .parts import *
3bd76451
UH
22
23VENDOR_CODE_ATMEL = 0x1e
24
25class Decoder(srd.Decoder):
b197383c 26 api_version = 3
3bd76451
UH
27 id = 'avr_isp'
28 name = 'AVR ISP'
d523eae6 29 longname = 'AVR In-System Programming'
3bd76451
UH
30 desc = 'Protocol for in-system programming Atmel AVR MCUs.'
31 license = 'gplv2+'
4e4f8527 32 inputs = ['spi']
3bd76451 33 outputs = ['avr_isp']
da9bcbd9
BV
34 annotations = (
35 ('pe', 'Programming enable'),
36 ('rsb0', 'Read signature byte 0'),
37 ('rsb1', 'Read signature byte 1'),
38 ('rsb2', 'Read signature byte 2'),
39 ('ce', 'Chip erase'),
40 ('rfb', 'Read fuse bits'),
41 ('rhfb', 'Read high fuse bits'),
42 ('refb', 'Read extended fuse bits'),
43 ('warnings', 'Warnings'),
44 ('dev', 'Device'),
45 )
3b001341
UH
46 annotation_rows = (
47 ('bits', 'Bits', ()),
48 ('commands', 'Commands', tuple(range(7 + 1))),
49 ('warnings', 'Warnings', (8,)),
38ab4ed0 50 ('dev', 'Device', (9,)),
3b001341 51 )
3bd76451 52
92b7b49f 53 def __init__(self):
3bd76451
UH
54 self.state = 'IDLE'
55 self.mosi_bytes, self.miso_bytes = [], []
486b19ce 56 self.ss_cmd, self.es_cmd = 0, 0
3bd76451 57 self.xx, self.yy, self.zz, self.mm = 0, 0, 0, 0
486b19ce 58 self.ss_device = None
3bd76451 59
8915b346 60 def start(self):
be465111 61 self.out_ann = self.register(srd.OUTPUT_ANN)
3bd76451 62
3bd76451 63 def putx(self, data):
486b19ce 64 self.put(self.ss_cmd, self.es_cmd, self.out_ann, data)
3bd76451
UH
65
66 def handle_cmd_programming_enable(self, cmd, ret):
67 # Programming enable.
68 # Note: The chip doesn't send any ACK for 'Programming enable'.
69 self.putx([0, ['Programming enable']])
70
71 # Sanity check on reply.
72 if ret[1:4] != [0xac, 0x53, cmd[2]]:
ad30cb46 73 self.putx([8, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
74
75 def handle_cmd_read_signature_byte_0x00(self, cmd, ret):
76 # Signature byte 0x00: vendor code.
77 self.vendor_code = ret[3]
78 v = vendor_code[self.vendor_code]
ad30cb46 79 self.putx([1, ['Vendor code: 0x%02x (%s)' % (ret[3], v)]])
3bd76451
UH
80
81 # Store for later.
82 self.xx = cmd[1] # Same as ret[2].
83 self.yy = cmd[3]
84 self.zz = ret[0]
85
86 # Sanity check on reply.
87 if ret[1] != 0x30 or ret[2] != cmd[1]:
ad30cb46 88 self.putx([8, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
89
90 # Sanity check for the vendor code.
91 if self.vendor_code != VENDOR_CODE_ATMEL:
ad30cb46 92 self.putx([8, ['Warning: Vendor code was not 0x1e (Atmel)!']])
3bd76451
UH
93
94 def handle_cmd_read_signature_byte_0x01(self, cmd, ret):
95 # Signature byte 0x01: part family and memory size.
96 self.part_fam_flash_size = ret[3]
ad30cb46 97 self.putx([2, ['Part family / memory size: 0x%02x' % ret[3]]])
3bd76451
UH
98
99 # Store for later.
100 self.mm = cmd[3]
486b19ce 101 self.ss_device = self.ss_cmd
3bd76451
UH
102
103 # Sanity check on reply.
104 if ret[1] != 0x30 or ret[2] != cmd[1] or ret[0] != self.yy:
ad30cb46 105 self.putx([8, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
106
107 def handle_cmd_read_signature_byte_0x02(self, cmd, ret):
108 # Signature byte 0x02: part number.
109 self.part_number = ret[3]
ad30cb46 110 self.putx([3, ['Part number: 0x%02x' % ret[3]]])
3bd76451 111
3bd76451 112 p = part[(self.part_fam_flash_size, self.part_number)]
38ab4ed0 113 data = [9, ['Device: Atmel %s' % p]]
486b19ce 114 self.put(self.ss_device, self.es_cmd, self.out_ann, data)
3bd76451
UH
115
116 # Sanity check on reply.
117 if ret[1] != 0x30 or ret[2] != self.xx or ret[0] != self.mm:
ad30cb46 118 self.putx([8, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
119
120 self.xx, self.yy, self.zz, self.mm = 0, 0, 0, 0
121
122 def handle_cmd_chip_erase(self, cmd, ret):
1fd698dc
UH
123 # Chip erase (erases both flash an EEPROM).
124 # Upon successful chip erase, the lock bits will also be erased.
125 # The only way to end a Chip Erase cycle is to release RESET#.
ad30cb46 126 self.putx([4, ['Chip erase']])
3bd76451 127
1fd698dc
UH
128 # TODO: Check/handle RESET#.
129
130 # Sanity check on reply.
131 bit = (ret[2] & (1 << 7)) >> 7
132 if ret[1] != 0xac or bit != 1 or ret[3] != cmd[2]:
ad30cb46 133 self.putx([8, ['Warning: Unexpected bytes in reply!']])
1fd698dc 134
3bd76451
UH
135 def handle_cmd_read_fuse_bits(self, cmd, ret):
136 # Read fuse bits.
ad30cb46 137 self.putx([5, ['Read fuse bits: 0x%02x' % ret[3]]])
3bd76451
UH
138
139 # TODO: Decode fuse bits.
140 # TODO: Sanity check on reply.
141
142 def handle_cmd_read_fuse_high_bits(self, cmd, ret):
143 # Read fuse high bits.
ad30cb46 144 self.putx([6, ['Read fuse high bits: 0x%02x' % ret[3]]])
3bd76451
UH
145
146 # TODO: Decode fuse bits.
147 # TODO: Sanity check on reply.
148
149 def handle_cmd_read_extended_fuse_bits(self, cmd, ret):
150 # Read extended fuse bits.
ad30cb46 151 self.putx([7, ['Read extended fuse bits: 0x%02x' % ret[3]]])
3bd76451
UH
152
153 # TODO: Decode fuse bits.
154 # TODO: Sanity check on reply.
155
156 def handle_command(self, cmd, ret):
157 if cmd[:2] == [0xac, 0x53]:
158 self.handle_cmd_programming_enable(cmd, ret)
159 elif cmd[0] == 0xac and (cmd[1] & (1 << 7)) == (1 << 7):
160 self.handle_cmd_chip_erase(cmd, ret)
161 elif cmd[:3] == [0x50, 0x00, 0x00]:
162 self.handle_cmd_read_fuse_bits(cmd, ret)
163 elif cmd[:3] == [0x58, 0x08, 0x00]:
164 self.handle_cmd_read_fuse_high_bits(cmd, ret)
165 elif cmd[:3] == [0x50, 0x08, 0x00]:
166 self.handle_cmd_read_extended_fuse_bits(cmd, ret)
167 elif cmd[0] == 0x30 and cmd[2] == 0x00:
168 self.handle_cmd_read_signature_byte_0x00(cmd, ret)
169 elif cmd[0] == 0x30 and cmd[2] == 0x01:
170 self.handle_cmd_read_signature_byte_0x01(cmd, ret)
171 elif cmd[0] == 0x30 and cmd[2] == 0x02:
172 self.handle_cmd_read_signature_byte_0x02(cmd, ret)
173 else:
174 c = '%02x %02x %02x %02x' % tuple(cmd)
175 r = '%02x %02x %02x %02x' % tuple(ret)
176 self.putx([0, ['Unknown command: %s (reply: %s)!' % (c, r)]])
177
178 def decode(self, ss, es, data):
179 ptype, mosi, miso = data
180
ad30cb46
UH
181 # For now, only use DATA and BITS packets.
182 if ptype not in ('DATA', 'BITS'):
3bd76451
UH
183 return
184
ad30cb46
UH
185 # Store the individual bit values and ss/es numbers. The next packet
186 # is guaranteed to be a 'DATA' packet belonging to this 'BITS' one.
187 if ptype == 'BITS':
188 self.miso_bits, self.mosi_bits = miso, mosi
189 return
3bd76451
UH
190
191 self.ss, self.es = ss, es
192
011ed1a3 193 if len(self.mosi_bytes) == 0:
486b19ce 194 self.ss_cmd = ss
011ed1a3 195
3bd76451
UH
196 # Append new bytes.
197 self.mosi_bytes.append(mosi)
198 self.miso_bytes.append(miso)
199
3bd76451
UH
200 # All commands consist of 4 bytes.
201 if len(self.mosi_bytes) < 4:
202 return
203
486b19ce 204 self.es_cmd = es
3bd76451
UH
205
206 self.handle_command(self.mosi_bytes, self.miso_bytes)
207
208 self.mosi_bytes = []
209 self.miso_bytes = []