]> sigrok.org Git - libsigrokdecode.git/blame - decoders/avr_isp/pd.py
avr_isp: Use symbolic names for annotation classes.
[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 22
f5250c60
HK
23class Ann:
24 PE, RSB0, RSB1, RSB2, CE, RFB, RHFB, REFB, \
25 WARN, DEV, = range(10)
26
3bd76451
UH
27VENDOR_CODE_ATMEL = 0x1e
28
29class Decoder(srd.Decoder):
b197383c 30 api_version = 3
3bd76451
UH
31 id = 'avr_isp'
32 name = 'AVR ISP'
d523eae6 33 longname = 'AVR In-System Programming'
2787cf2a 34 desc = 'Atmel AVR In-System Programming (ISP) protocol.'
3bd76451 35 license = 'gplv2+'
4e4f8527 36 inputs = ['spi']
6cbba91f 37 outputs = []
d6d8a8a4 38 tags = ['Debug/trace']
da9bcbd9
BV
39 annotations = (
40 ('pe', 'Programming enable'),
41 ('rsb0', 'Read signature byte 0'),
42 ('rsb1', 'Read signature byte 1'),
43 ('rsb2', 'Read signature byte 2'),
44 ('ce', 'Chip erase'),
45 ('rfb', 'Read fuse bits'),
46 ('rhfb', 'Read high fuse bits'),
47 ('refb', 'Read extended fuse bits'),
e144452b 48 ('warning', 'Warning'),
da9bcbd9
BV
49 ('dev', 'Device'),
50 )
3b001341
UH
51 annotation_rows = (
52 ('bits', 'Bits', ()),
f5250c60
HK
53 ('commands', 'Commands', (Ann.PE, Ann.RSB0, Ann.RSB1, Ann.RSB2,
54 Ann.CE, Ann.RFB, Ann.RHFB, Ann.REFB,)),
55 ('warnings', 'Warnings', (Ann.WARN,)),
56 ('devs', 'Devices', (Ann.DEV,)),
3b001341 57 )
3bd76451 58
92b7b49f 59 def __init__(self):
10aeb8ea
GS
60 self.reset()
61
62 def reset(self):
3bd76451
UH
63 self.state = 'IDLE'
64 self.mosi_bytes, self.miso_bytes = [], []
486b19ce 65 self.ss_cmd, self.es_cmd = 0, 0
3bd76451 66 self.xx, self.yy, self.zz, self.mm = 0, 0, 0, 0
486b19ce 67 self.ss_device = None
3bd76451 68
8915b346 69 def start(self):
be465111 70 self.out_ann = self.register(srd.OUTPUT_ANN)
3bd76451 71
3bd76451 72 def putx(self, data):
486b19ce 73 self.put(self.ss_cmd, self.es_cmd, self.out_ann, data)
3bd76451
UH
74
75 def handle_cmd_programming_enable(self, cmd, ret):
76 # Programming enable.
77 # Note: The chip doesn't send any ACK for 'Programming enable'.
f5250c60 78 self.putx([Ann.PE, ['Programming enable']])
3bd76451
UH
79
80 # Sanity check on reply.
81 if ret[1:4] != [0xac, 0x53, cmd[2]]:
f5250c60 82 self.putx([Ann.WARN, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
83
84 def handle_cmd_read_signature_byte_0x00(self, cmd, ret):
85 # Signature byte 0x00: vendor code.
86 self.vendor_code = ret[3]
87 v = vendor_code[self.vendor_code]
f5250c60 88 self.putx([Ann.RSB0, ['Vendor code: 0x%02x (%s)' % (ret[3], v)]])
3bd76451
UH
89
90 # Store for later.
91 self.xx = cmd[1] # Same as ret[2].
92 self.yy = cmd[3]
93 self.zz = ret[0]
94
95 # Sanity check on reply.
96 if ret[1] != 0x30 or ret[2] != cmd[1]:
f5250c60 97 self.putx([Ann.WARN, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
98
99 # Sanity check for the vendor code.
100 if self.vendor_code != VENDOR_CODE_ATMEL:
f5250c60 101 self.putx([Ann.WARN, ['Warning: Vendor code was not 0x1e (Atmel)!']])
3bd76451
UH
102
103 def handle_cmd_read_signature_byte_0x01(self, cmd, ret):
104 # Signature byte 0x01: part family and memory size.
105 self.part_fam_flash_size = ret[3]
f5250c60 106 self.putx([Ann.RSB1, ['Part family / memory size: 0x%02x' % ret[3]]])
3bd76451
UH
107
108 # Store for later.
109 self.mm = cmd[3]
486b19ce 110 self.ss_device = self.ss_cmd
3bd76451
UH
111
112 # Sanity check on reply.
113 if ret[1] != 0x30 or ret[2] != cmd[1] or ret[0] != self.yy:
f5250c60 114 self.putx([Ann.WARN, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
115
116 def handle_cmd_read_signature_byte_0x02(self, cmd, ret):
117 # Signature byte 0x02: part number.
118 self.part_number = ret[3]
f5250c60 119 self.putx([Ann.RSB2, ['Part number: 0x%02x' % ret[3]]])
3bd76451 120
3bd76451 121 p = part[(self.part_fam_flash_size, self.part_number)]
f5250c60 122 data = [Ann.DEV, ['Device: Atmel %s' % p]]
486b19ce 123 self.put(self.ss_device, self.es_cmd, self.out_ann, data)
3bd76451
UH
124
125 # Sanity check on reply.
126 if ret[1] != 0x30 or ret[2] != self.xx or ret[0] != self.mm:
f5250c60 127 self.putx([Ann.WARN, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
128
129 self.xx, self.yy, self.zz, self.mm = 0, 0, 0, 0
130
131 def handle_cmd_chip_erase(self, cmd, ret):
1fd698dc
UH
132 # Chip erase (erases both flash an EEPROM).
133 # Upon successful chip erase, the lock bits will also be erased.
134 # The only way to end a Chip Erase cycle is to release RESET#.
f5250c60 135 self.putx([Ann.CE, ['Chip erase']])
3bd76451 136
1fd698dc
UH
137 # TODO: Check/handle RESET#.
138
139 # Sanity check on reply.
140 bit = (ret[2] & (1 << 7)) >> 7
141 if ret[1] != 0xac or bit != 1 or ret[3] != cmd[2]:
f5250c60 142 self.putx([Ann.WARN, ['Warning: Unexpected bytes in reply!']])
1fd698dc 143
3bd76451
UH
144 def handle_cmd_read_fuse_bits(self, cmd, ret):
145 # Read fuse bits.
f5250c60 146 self.putx([Ann.RFB, ['Read fuse bits: 0x%02x' % ret[3]]])
3bd76451
UH
147
148 # TODO: Decode fuse bits.
149 # TODO: Sanity check on reply.
150
151 def handle_cmd_read_fuse_high_bits(self, cmd, ret):
152 # Read fuse high bits.
f5250c60 153 self.putx([Ann.RHFB, ['Read fuse high bits: 0x%02x' % ret[3]]])
3bd76451
UH
154
155 # TODO: Decode fuse bits.
156 # TODO: Sanity check on reply.
157
158 def handle_cmd_read_extended_fuse_bits(self, cmd, ret):
159 # Read extended fuse bits.
f5250c60 160 self.putx([Ann.REFB, ['Read extended fuse bits: 0x%02x' % ret[3]]])
3bd76451
UH
161
162 # TODO: Decode fuse bits.
163 # TODO: Sanity check on reply.
164
165 def handle_command(self, cmd, ret):
166 if cmd[:2] == [0xac, 0x53]:
167 self.handle_cmd_programming_enable(cmd, ret)
168 elif cmd[0] == 0xac and (cmd[1] & (1 << 7)) == (1 << 7):
169 self.handle_cmd_chip_erase(cmd, ret)
170 elif cmd[:3] == [0x50, 0x00, 0x00]:
171 self.handle_cmd_read_fuse_bits(cmd, ret)
172 elif cmd[:3] == [0x58, 0x08, 0x00]:
173 self.handle_cmd_read_fuse_high_bits(cmd, ret)
174 elif cmd[:3] == [0x50, 0x08, 0x00]:
175 self.handle_cmd_read_extended_fuse_bits(cmd, ret)
176 elif cmd[0] == 0x30 and cmd[2] == 0x00:
177 self.handle_cmd_read_signature_byte_0x00(cmd, ret)
178 elif cmd[0] == 0x30 and cmd[2] == 0x01:
179 self.handle_cmd_read_signature_byte_0x01(cmd, ret)
180 elif cmd[0] == 0x30 and cmd[2] == 0x02:
181 self.handle_cmd_read_signature_byte_0x02(cmd, ret)
182 else:
183 c = '%02x %02x %02x %02x' % tuple(cmd)
184 r = '%02x %02x %02x %02x' % tuple(ret)
f5250c60 185 self.putx([Ann.PE, ['Unknown command: %s (reply: %s)!' % (c, r)]])
3bd76451
UH
186
187 def decode(self, ss, es, data):
188 ptype, mosi, miso = data
189
ad30cb46
UH
190 # For now, only use DATA and BITS packets.
191 if ptype not in ('DATA', 'BITS'):
3bd76451
UH
192 return
193
ad30cb46
UH
194 # Store the individual bit values and ss/es numbers. The next packet
195 # is guaranteed to be a 'DATA' packet belonging to this 'BITS' one.
196 if ptype == 'BITS':
197 self.miso_bits, self.mosi_bits = miso, mosi
198 return
3bd76451
UH
199
200 self.ss, self.es = ss, es
201
011ed1a3 202 if len(self.mosi_bytes) == 0:
486b19ce 203 self.ss_cmd = ss
011ed1a3 204
3bd76451
UH
205 # Append new bytes.
206 self.mosi_bytes.append(mosi)
207 self.miso_bytes.append(miso)
208
3bd76451
UH
209 # All commands consist of 4 bytes.
210 if len(self.mosi_bytes) < 4:
211 return
212
486b19ce 213 self.es_cmd = es
3bd76451
UH
214
215 self.handle_command(self.mosi_bytes, self.miso_bytes)
216
217 self.mosi_bytes = []
218 self.miso_bytes = []