]>
Commit | Line | Data |
---|---|---|
1 | ## | |
2 | ## This file is part of the libsigrokdecode project. | |
3 | ## | |
4 | ## Copyright (C) 2015 Paul Evans <leonerd@leonerd.org.uk> | |
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 | |
17 | ## along with this program; if not, write to the Free Software | |
18 | ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
19 | ## | |
20 | ||
21 | import re | |
22 | import sigrokdecode as srd | |
23 | ||
24 | def _decode_intensity(val): | |
25 | intensity = val & 0x0f | |
26 | if intensity == 0: | |
27 | return 'min' | |
28 | elif intensity == 15: | |
29 | return 'max' | |
30 | else: | |
31 | return intensity | |
32 | ||
33 | registers = { | |
34 | 0x00: ['No-op', lambda _: ''], | |
35 | 0x09: ['Decode', lambda v: '0b{:08b}'.format(v)], | |
36 | 0x0A: ['Intensity', _decode_intensity], | |
37 | 0x0B: ['Scan limit', lambda v: 1 + v], | |
38 | 0x0C: ['Shutdown', lambda v: 'off' if v else 'on'], | |
39 | 0x0F: ['Display test', lambda v: 'on' if v else 'off'] | |
40 | } | |
41 | ||
42 | ann_reg, ann_digit, ann_warning = range(3) | |
43 | ||
44 | class Decoder(srd.Decoder): | |
45 | api_version = 2 | |
46 | id = 'max7219' | |
47 | name = 'MAX7219' | |
48 | longname = 'Maxim MAX7219/MAX7221' | |
49 | desc = '8-digit LED display driver.' | |
50 | license = 'gplv2+' | |
51 | inputs = ['spi'] | |
52 | outputs = ['max7219'] | |
53 | annotations = ( | |
54 | ('register', 'Registers written to the device'), | |
55 | ('digit', 'Digits displayed on the device'), | |
56 | ('warnings', 'Human-readable warnings'), | |
57 | ) | |
58 | annotation_rows = ( | |
59 | ('commands', 'Commands', (ann_reg, ann_digit)), | |
60 | ('warnings', 'Warnings', (ann_warning,)), | |
61 | ) | |
62 | ||
63 | def start(self): | |
64 | self.out_ann = self.register(srd.OUTPUT_ANN) | |
65 | self.pos = 0 | |
66 | self.cs_start = 0 | |
67 | ||
68 | def putreg(self, ss, es, reg, value): | |
69 | self.put(ss, es, self.out_ann, [ann_reg, ['%s: %s' % (reg, value)]]) | |
70 | ||
71 | def putdigit(self, ss, es, digit, value): | |
72 | self.put(ss, es, self.out_ann, [ann_digit, ['Digit %d: %02X' % (digit, value)]]) | |
73 | ||
74 | def putwarn(self, ss, es, message): | |
75 | self.put(ss, es, self.out_ann, [ann_warning, [message]]) | |
76 | ||
77 | def decode(self, ss, es, data): | |
78 | ptype, mosi, _ = data | |
79 | ||
80 | if ptype == 'DATA': | |
81 | if not self.cs_asserted: | |
82 | return | |
83 | ||
84 | if self.pos == 0: | |
85 | self.addr = mosi | |
86 | self.addr_start = ss | |
87 | elif self.pos == 1: | |
88 | if self.addr >= 1 and self.addr <= 8: | |
89 | self.putdigit(self.addr_start, es, self.addr, mosi) | |
90 | elif self.addr in registers: | |
91 | name, decoder = registers[self.addr] | |
92 | self.putreg(self.addr_start, es, name, decoder(mosi)) | |
93 | else: | |
94 | self.putwarn(self.addr_start, es, | |
95 | 'Unknown register %02X' % (self.addr)) | |
96 | ||
97 | self.pos += 1 | |
98 | elif ptype == 'CS-CHANGE': | |
99 | self.cs_asserted = mosi | |
100 | if self.cs_asserted: | |
101 | self.pos = 0 | |
102 | self.cs_start = ss | |
103 | else: | |
104 | if self.pos == 1: | |
105 | # Don't warn if pos=0 so that CS# glitches don't appear | |
106 | # as spurious warnings. | |
107 | self.putwarn(self.cs_start, es, 'Short write') | |
108 | elif self.pos > 2: | |
109 | self.putwarn(self.cs_start, es, 'Overlong write') |