]> sigrok.org Git - libsigrokdecode.git/blob - decoders/seven_segment/pd.py
avr_isp: Add more parts
[libsigrokdecode.git] / decoders / seven_segment / pd.py
1 ##
2 ## This file is part of the libsigrokdecode project.
3 ##
4 ## Copyright (C) 2019 Benedikt Otto <benedikt_o@web.de>
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, see <http://www.gnu.org/licenses/>.
18 ##
19
20 import sigrokdecode as srd
21
22 class ChannelError(Exception):
23     pass
24
25 # This table is sorted by ASCII code numbers, with the exception
26 # of letters having their upper/lower case ignored.
27 #
28 # Traditional LED segment names and layout:
29 #
30 #      A
31 #    F   B
32 #      G
33 #    E   C
34 #      D
35 #
36 #    A  B  C  D  E  F  G
37 digits = {
38     (0, 0, 0, 0, 0, 0, 0): ' ',
39     (0, 1, 0, 0, 0, 1, 0): '"',
40     (1, 1, 0, 1, 1, 1, 1): "&",
41     (0, 0, 0, 0, 0, 1, 0): "'",
42     (0, 1, 0, 0, 0, 0, 0): "'",
43     (0, 0, 1, 1, 0, 0, 0): ',',
44     (0, 0, 0, 0, 0, 0, 1): '-',
45     (0, 0, 0, 0, 1, 0, 0): '.',
46     (1, 1, 1, 1, 1, 1, 0): '0',
47     (0, 1, 1, 0, 0, 0, 0): '1',
48     (1, 1, 0, 1, 1, 0, 1): '2',
49     (1, 1, 1, 1, 0, 0, 1): '3',
50     (0, 1, 1, 0, 0, 1, 1): '4',
51     (1, 0, 1, 1, 0, 1, 1): '5',
52     (1, 0, 1, 1, 1, 1, 1): '6',
53     (1, 1, 1, 0, 0, 1, 0): '7',
54     (1, 1, 1, 0, 0, 0, 0): '7',
55     (1, 1, 1, 1, 1, 1, 1): '8',
56     (1, 1, 1, 1, 0, 1, 1): '9',
57     (1, 0, 0, 0, 0, 0, 1): '=',
58     (0, 0, 0, 1, 0, 0, 1): '=',
59     (1, 1, 0, 0, 1, 0, 1): '?',
60     (1, 1, 1, 0, 1, 1, 1): 'A',
61     (1, 1, 1, 1, 1, 0, 1): 'a',
62     (0, 0, 1, 1, 1, 1, 1): 'b',
63     (1, 0, 0, 1, 1, 1, 0): 'C',
64     (0, 0, 0, 1, 1, 0, 1): 'c',
65     (0, 1, 1, 1, 1, 0, 1): 'd',
66     (1, 0, 0, 1, 1, 1, 1): 'E',
67     (1, 0, 0, 0, 1, 1, 1): 'F',
68     (1, 0, 1, 1, 1, 1, 0): 'G',
69     (0, 1, 1, 0, 1, 1, 1): 'H',
70     (0, 0, 1, 0, 1, 1, 1): 'h',
71     (0, 0, 0, 0, 1, 1, 0): 'I',
72     (1, 0, 0, 0, 1, 0, 0): 'i',
73     (0, 0, 1, 0, 0, 0, 0): 'i',
74     (0, 1, 1, 1, 1, 0, 0): 'J',
75     (0, 1, 1, 1, 0, 0, 0): 'J',
76     (1, 0, 1, 1, 0, 0, 0): 'j',
77     (1, 0, 1, 0, 1, 1, 1): 'K',
78     (0, 0 ,0, 1, 1, 1, 0): 'L',
79     (1, 0, 1, 0, 1, 0, 0): 'M',
80     (1, 0, 1, 0, 1, 0, 1): 'M',
81     (1, 1, 1, 0, 1, 1, 0): 'N',
82     (0, 0, 1, 0, 1, 0, 1): 'n',
83     (0, 0, 1, 1, 1, 0, 1): 'o',
84     (1, 1, 0, 0, 1, 1, 1): 'p',
85     (1, 1, 1, 0, 0, 1, 1): 'q',
86     (1, 1, 0, 0, 1, 1, 0): 'R',
87     (0, 0, 0, 0, 1, 0, 1): 'r',
88     (0, 0, 0, 1, 1, 1, 1): 't',
89     (0, 0, 1, 1, 1, 0, 0): 'u',
90     (0, 1, 0, 1, 0, 1, 0): 'V',
91     (0, 1, 0, 0, 1, 1, 1): 'V',
92     (0, 1, 1, 1, 1, 1, 0): 'V',
93     (0, 1, 0, 0, 0, 1, 1): 'v',
94     (0, 1, 0, 1, 0, 1, 1): 'W',
95     (0, 0, 1, 0, 1, 0, 0): 'x',
96     (0, 1, 1, 1, 0, 1, 1): 'y',
97     (1, 1, 0, 1, 1, 0, 0): 'Z',
98     (1, 1, 0, 0, 0, 1, 0): '^',
99     (0, 0, 0, 1, 0, 0, 0): '_',
100 }
101
102 class Decoder(srd.Decoder):
103     api_version = 3
104     id = 'seven_segment'
105     name = '7-segment'
106     longname = '7-segment display'
107     desc = '7-segment display protocol.'
108     license = 'gplv2+'
109     inputs = ['logic']
110     outputs = []
111     tags = ['Display']
112     channels = (
113         {'id': 'a', 'name': 'A', 'desc': 'Segment A'},
114         {'id': 'b', 'name': 'B', 'desc': 'Segment B'},
115         {'id': 'c', 'name': 'C', 'desc': 'Segment C'},
116         {'id': 'd', 'name': 'D', 'desc': 'Segment D'},
117         {'id': 'e', 'name': 'E', 'desc': 'Segment E'},
118         {'id': 'f', 'name': 'F', 'desc': 'Segment F'},
119         {'id': 'g', 'name': 'G', 'desc': 'Segment G'},
120     )
121     optional_channels = (
122         {'id': 'dp', 'name': 'DP', 'desc': 'Decimal point'},
123     )
124     options = (
125         {'id': 'polarity', 'desc': 'Expected polarity',
126             'default': 'common-cathode', 'values': ('common-cathode', 'common-anode')},
127         {'id': 'show_unknown', 'desc': 'Display Unknown characters as #',
128             'default': 'no', 'values': ('yes', 'no')},
129     )
130     annotations = (
131         ('decoded-digit', 'Decoded digit'),
132     )
133     annotation_rows = (
134         ('decoded-digits', 'Decoded digits', (0,)),
135     )
136
137     def __init__(self):
138         self.reset()
139
140     def reset(self):
141         pass
142
143     def start(self):
144         self.out_ann = self.register(srd.OUTPUT_ANN)
145
146     def putb(self, ss_block, es_block, data):
147         self.put(ss_block, es_block, self.out_ann, data)
148
149     def pins_to_hex(self, pins):
150         return digits.get(pins, None)
151
152     def decode(self):
153         oldpins = self.wait()
154         lastpos = self.samplenum
155
156         # Check mandatory and optional decoder input signals.
157         if False in [p in (0, 1) for p in oldpins[:7]]:
158             raise ChannelError('Need at least segments A-G.')
159         self.have_dp = self.has_channel(7)
160         seg_count = 8 if self.have_dp else 7
161
162         conditions = [{i: 'e'} for i in range(seg_count)]
163         while True:
164             # Wait for any change.
165             pins = self.wait(conditions)
166
167             # Invert all data lines if a common anode display is used.
168             if self.options['polarity'] == 'common-anode':
169                 oldpins = tuple((1 - state for state in oldpins[:seg_count]))
170
171             # Convert to character string.
172             digit = self.pins_to_hex(oldpins[:7])
173             if digit is None and self.options['show_unknown'] == 'yes':
174                 digit = '#'
175
176             # Emit annotation when conversion succeeded.
177             # Optionally present the decimal point when active.
178             if digit is not None:
179                 if self.have_dp:
180                     dp = oldpins[7]
181                     if dp == 1:
182                         digit += '.'
183                 self.putb(lastpos, self.samplenum, [0, [digit]])
184
185             oldpins = pins
186             lastpos = self.samplenum