2 ## This file is part of the libsigrokdecode project.
4 ## Copyright (C) 2019 Jiahao Li <reg@ljh.me>
6 ## Permission is hereby granted, free of charge, to any person obtaining a copy
7 ## of this software and associated documentation files (the "Software"), to deal
8 ## in the Software without restriction, including without limitation the rights
9 ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 ## copies of the Software, and to permit persons to whom the Software is
11 ## furnished to do so, subject to the following conditions:
13 ## The above copyright notice and this permission notice shall be included in all
14 ## copies or substantial portions of the Software.
16 ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 import sigrokdecode as srd
27 OPCODE_MASK = 0b11100000
28 REG_ADDR_MASK = 0b00011111
31 0b00000000: '_process_rcr',
32 0b00100000: '_process_rbm',
33 0b01000000: '_process_wcr',
34 0b01100000: '_process_wbm',
35 0b10000000: '_process_bfs',
36 0b10100000: '_process_bfc',
37 0b11100000: '_process_src',
40 (ANN_RCR, ANN_RBM, ANN_WCR, ANN_WBM, ANN_BFS, ANN_BFC, ANN_SRC, ANN_DATA,
41 ANN_REG_ADDR, ANN_WARNING) = range(10)
44 BIT_ECON1_BSEL0 = 0b00000001
45 BIT_ECON1_BSEL1 = 0b00000010
47 class Decoder(srd.Decoder):
51 longname = 'Microchip ENC28J60'
52 desc = 'Microchip ENC28J60 10Base-T Ethernet controller protocol.'
56 tags = ['Embedded/industrial', 'Networking']
58 ('rcr', 'Read Control Register'),
59 ('rbm', 'Read Buffer Memory'),
60 ('wcr', 'Write Control Register'),
61 ('wbm', 'Write Buffer Memory'),
62 ('bfs', 'Bit Field Set'),
63 ('bfc', 'Bit Field Clear'),
64 ('src', 'System Reset Command'),
66 ('reg-addr', 'Register Address'),
67 ('warning', 'Warning'),
70 ('commands', 'Commands',
71 (ANN_RCR, ANN_RBM, ANN_WCR, ANN_WBM, ANN_BFS, ANN_BFC, ANN_SRC)),
72 ('fields', 'Fields', (ANN_DATA, ANN_REG_ADDR)),
73 ('warnings', 'Warnings', (ANN_WARNING,)),
90 self.ann = self.register(srd.OUTPUT_ANN)
93 self.put(self.cmd_ss, self.cmd_es, self.ann, data)
95 def _process_command(self):
96 if len(self.mosi) == 0:
100 header = self.mosi[0]
101 opcode = header & OPCODE_MASK
103 if opcode not in OPCODE_HANDLERS:
104 self._put_command_warning("Unknown opcode.")
108 getattr(self, OPCODE_HANDLERS[opcode])()
112 def _get_register_name(self, reg_addr):
113 if (self.bsel0 is None) or (self.bsel1 is None):
114 # We don't know the bank we're in yet.
117 bank = (self.bsel1 << 1) + self.bsel0
118 return REGS[bank][reg_addr]
120 def _put_register_header(self):
121 reg_addr = self.mosi[0] & REG_ADDR_MASK
122 reg_name = self._get_register_name(reg_addr)
124 ss, es = self.cmd_ss, self.ranges[1][0]
127 # We don't know the bank we're in yet.
128 self.put(ss, es, self.ann, [
131 'Reg Bank ? Addr 0x{0:02X}'.format(reg_addr),
132 '?:{0:02X}'.format(reg_addr),
134 self.put(ss, es, self.ann, [
137 'Warning: Register bank not known yet.',
141 self.put(ss, es, self.ann, [
144 'Reg {0}'.format(reg_name),
145 '{0}'.format(reg_name),
148 if (reg_name == '-') or (reg_name == 'Reserved'):
149 self.put(ss, es, self.ann, [
152 'Warning: Invalid register accessed.',
156 def _put_data_byte(self, data, byte_index, binary=False):
157 ss = self.ranges[byte_index][0]
158 if byte_index == len(self.mosi) - 1:
161 es = self.ranges[byte_index + 1][0]
164 self.put(ss, es, self.ann, [
167 'Data 0b{0:08b}'.format(data),
168 '{0:08b}'.format(data),
171 self.put(ss, es, self.ann, [
174 'Data 0x{0:02X}'.format(data),
175 '{0:02X}'.format(data),
178 def _put_command_warning(self, reason):
182 'Warning: {0}'.format(reason),
186 def _process_rcr(self):
187 self.putc([ANN_RCR, ['Read Control Register', 'RCR']])
189 if (len(self.mosi) != 2) and (len(self.mosi) != 3):
190 self._put_command_warning('Invalid command length.')
193 self._put_register_header()
195 reg_name = self._get_register_name(self.mosi[0] & REG_ADDR_MASK)
197 # We can't tell if we're accessing MAC/MII registers or not
198 # Let's trust the user in this case.
201 if (reg_name[0] == 'M') and (len(self.mosi) != 3):
202 self._put_command_warning('Attempting to read a MAC/MII '
203 + 'register without using the dummy byte.')
206 if (reg_name[0] != 'M') and (len(self.mosi) != 2):
207 self._put_command_warning('Attempting to read a non-MAC/MII '
208 + 'register using the dummy byte.')
211 if len(self.mosi) == 2:
212 self._put_data_byte(self.miso[1], 1)
214 ss, es = self.ranges[1][0], self.ranges[2][0]
215 self.put(ss, es, self.ann, [
221 self._put_data_byte(self.miso[2], 2)
223 def _process_rbm(self):
224 if self.mosi[0] != 0b00111010:
225 self._put_command_warning('Invalid header byte.')
231 'Read Buffer Memory: Length {0}'.format(
236 for i in range(1, len(self.miso)):
237 self._put_data_byte(self.miso[i], i)
239 def _process_wcr(self):
240 self.putc([ANN_WCR, ['Write Control Register', 'WCR']])
242 if len(self.mosi) != 2:
243 self._put_command_warning('Invalid command length.')
246 self._put_register_header()
247 self._put_data_byte(self.mosi[1], 1)
249 if self.mosi[0] & REG_ADDR_MASK == REG_ADDR_ECON1:
250 self.bsel0 = (self.mosi[1] & BIT_ECON1_BSEL0) >> 0
251 self.bsel1 = (self.mosi[1] & BIT_ECON1_BSEL1) >> 1
253 def _process_wbm(self):
254 if self.mosi[0] != 0b01111010:
255 self._put_command_warning('Invalid header byte.')
261 'Write Buffer Memory: Length {0}'.format(
266 for i in range(1, len(self.mosi)):
267 self._put_data_byte(self.mosi[i], i)
269 def _process_bfc(self):
270 self.putc([ANN_BFC, ['Bit Field Clear', 'BFC']])
272 if len(self.mosi) != 2:
273 self._put_command_warning('Invalid command length.')
276 self._put_register_header()
277 self._put_data_byte(self.mosi[1], 1, True)
279 if self.mosi[0] & REG_ADDR_MASK == REG_ADDR_ECON1:
280 if self.mosi[1] & BIT_ECON1_BSEL0:
282 if self.mosi[1] & BIT_ECON1_BSEL1:
285 def _process_bfs(self):
286 self.putc([ANN_BFS, ['Bit Field Set', 'BFS']])
288 if len(self.mosi) != 2:
289 self._put_command_warning('Invalid command length.')
292 self._put_register_header()
293 self._put_data_byte(self.mosi[1], 1, True)
295 if self.mosi[0] & REG_ADDR_MASK == REG_ADDR_ECON1:
296 if self.mosi[1] & BIT_ECON1_BSEL0:
298 if self.mosi[1] & BIT_ECON1_BSEL1:
301 def _process_src(self):
302 self.putc([ANN_SRC, ['System Reset Command', 'SRC']])
304 if len(self.mosi) != 1:
305 self._put_command_warning('Invalid command length.')
311 def decode(self, ss, es, data):
312 ptype, data1, data2 = data
314 if ptype == 'CS-CHANGE':
326 self._process_command()
327 elif ptype == 'DATA':
328 mosi, miso = data1, data2
330 self.mosi.append(mosi)
331 self.miso.append(miso)
332 self.ranges.append((ss, es))