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,)),
92 self.ann = self.register(srd.OUTPUT_ANN)
95 self.put(self.cmd_ss, self.cmd_es, self.ann, data)
98 self.put(self.range_ss, self.range_es, self.ann, data)
100 def _process_command(self):
101 if len(self.mosi) == 0:
105 header = self.mosi[0]
106 opcode = header & OPCODE_MASK
108 if opcode not in OPCODE_HANDLERS:
109 self._put_command_warning("Unknown opcode.")
113 getattr(self, OPCODE_HANDLERS[opcode])()
117 def _get_register_name(self, reg_addr):
118 if (self.bsel0 is None) or (self.bsel1 is None):
119 # We don't know the bank we're in yet.
122 bank = (self.bsel1 << 1) + self.bsel0
123 return REGS[bank][reg_addr]
125 def _put_register_header(self):
126 reg_addr = self.mosi[0] & REG_ADDR_MASK
127 reg_name = self._get_register_name(reg_addr)
129 self.range_ss, self.range_es = self.cmd_ss, self.ranges[1][0]
132 # We don't know the bank we're in yet.
136 'Reg Bank ? Addr 0x{0:02X}'.format(reg_addr),
137 '?:{0:02X}'.format(reg_addr),
142 'Warning: Register bank not known yet.',
149 'Reg {0}'.format(reg_name),
150 '{0}'.format(reg_name),
153 if (reg_name == '-') or (reg_name == 'Reserved'):
157 'Warning: Invalid register accessed.',
161 def _put_data_byte(self, data, byte_index, binary=False):
162 self.range_ss = self.ranges[byte_index][0]
163 if byte_index == len(self.mosi) - 1:
164 self.range_es = self.cmd_es
166 self.range_es = self.ranges[byte_index + 1][0]
172 'Data 0b{0:08b}'.format(data),
173 '{0:08b}'.format(data),
179 'Data 0x{0:02X}'.format(data),
180 '{0:02X}'.format(data),
183 def _put_command_warning(self, reason):
187 'Warning: {0}'.format(reason),
191 def _process_rcr(self):
192 self.putc([ANN_RCR, ['Read Control Register', 'RCR']])
194 if (len(self.mosi) != 2) and (len(self.mosi) != 3):
195 self._put_command_warning('Invalid command length.')
198 self._put_register_header()
200 reg_name = self._get_register_name(self.mosi[0] & REG_ADDR_MASK)
202 # We can't tell if we're accessing MAC/MII registers or not
203 # Let's trust the user in this case.
206 if (reg_name[0] == 'M') and (len(self.mosi) != 3):
207 self._put_command_warning('Attempting to read a MAC/MII '
208 + 'register without using the dummy byte.')
211 if (reg_name[0] != 'M') and (len(self.mosi) != 2):
212 self._put_command_warning('Attempting to read a non-MAC/MII '
213 + 'register using the dummy byte.')
216 if len(self.mosi) == 2:
217 self._put_data_byte(self.miso[1], 1)
219 self.range_ss, self.range_es = self.ranges[1][0], self.ranges[2][0]
226 self._put_data_byte(self.miso[2], 2)
228 def _process_rbm(self):
229 if self.mosi[0] != 0b00111010:
230 self._put_command_warning('Invalid header byte.')
236 'Read Buffer Memory: Length {0}'.format(
241 for i in range(1, len(self.miso)):
242 self._put_data_byte(self.miso[i], i)
244 def _process_wcr(self):
245 self.putc([ANN_WCR, ['Write Control Register', 'WCR']])
247 if len(self.mosi) != 2:
248 self._put_command_warning('Invalid command length.')
251 self._put_register_header()
252 self._put_data_byte(self.mosi[1], 1)
254 if self.mosi[0] & REG_ADDR_MASK == REG_ADDR_ECON1:
255 self.bsel0 = (self.mosi[1] & BIT_ECON1_BSEL0) >> 0
256 self.bsel1 = (self.mosi[1] & BIT_ECON1_BSEL1) >> 1
258 def _process_wbm(self):
259 if self.mosi[0] != 0b01111010:
260 self._put_command_warning('Invalid header byte.')
266 'Write Buffer Memory: Length {0}'.format(
271 for i in range(1, len(self.mosi)):
272 self._put_data_byte(self.mosi[i], i)
274 def _process_bfc(self):
275 self.putc([ANN_BFC, ['Bit Field Clear', 'BFC']])
277 if len(self.mosi) != 2:
278 self._put_command_warning('Invalid command length.')
281 self._put_register_header()
282 self._put_data_byte(self.mosi[1], 1, True)
284 if self.mosi[0] & REG_ADDR_MASK == REG_ADDR_ECON1:
285 if self.mosi[1] & BIT_ECON1_BSEL0:
287 if self.mosi[1] & BIT_ECON1_BSEL1:
290 def _process_bfs(self):
291 self.putc([ANN_BFS, ['Bit Field Set', 'BFS']])
293 if len(self.mosi) != 2:
294 self._put_command_warning('Invalid command length.')
297 self._put_register_header()
298 self._put_data_byte(self.mosi[1], 1, True)
300 if self.mosi[0] & REG_ADDR_MASK == REG_ADDR_ECON1:
301 if self.mosi[1] & BIT_ECON1_BSEL0:
303 if self.mosi[1] & BIT_ECON1_BSEL1:
306 def _process_src(self):
307 self.putc([ANN_SRC, ['System Reset Command', 'SRC']])
309 if len(self.mosi) != 1:
310 self._put_command_warning('Invalid command length.')
316 def decode(self, ss, es, data):
317 ptype, data1, data2 = data
319 if ptype == 'CS-CHANGE':
331 self._process_command()
332 elif ptype == 'DATA':
333 mosi, miso = data1, data2
335 self.mosi.append(mosi)
336 self.miso.append(miso)
337 self.ranges.append((ss, es))