## ## This file is part of the libsigrokdecode project. ## ## Copyright (C) 2019 Benedikt Otto ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## import sigrokdecode as srd class ChannelError(Exception): pass # This table is sorted by ASCII code numbers, with the exception # of letters having their upper/lower case ignored. # # Traditional LED segment names and layout: # # A # F B # G # E C # D # # A B C D E F G digits = { (0, 0, 0, 0, 0, 0, 0): ' ', (0, 1, 0, 0, 0, 1, 0): '"', (1, 1, 0, 1, 1, 1, 1): "&", (0, 0, 0, 0, 0, 1, 0): "'", (0, 1, 0, 0, 0, 0, 0): "'", (0, 0, 1, 1, 0, 0, 0): ',', (0, 0, 0, 0, 0, 0, 1): '-', (0, 0, 0, 0, 1, 0, 0): '.', (1, 1, 1, 1, 1, 1, 0): '0', (0, 1, 1, 0, 0, 0, 0): '1', (1, 1, 0, 1, 1, 0, 1): '2', (1, 1, 1, 1, 0, 0, 1): '3', (0, 1, 1, 0, 0, 1, 1): '4', (1, 0, 1, 1, 0, 1, 1): '5', (1, 0, 1, 1, 1, 1, 1): '6', (1, 1, 1, 0, 0, 1, 0): '7', (1, 1, 1, 0, 0, 0, 0): '7', (1, 1, 1, 1, 1, 1, 1): '8', (1, 1, 1, 1, 0, 1, 1): '9', (1, 0, 0, 0, 0, 0, 1): '=', (0, 0, 0, 1, 0, 0, 1): '=', (1, 1, 0, 0, 1, 0, 1): '?', (1, 1, 1, 0, 1, 1, 1): 'A', (1, 1, 1, 1, 1, 0, 1): 'a', (0, 0, 1, 1, 1, 1, 1): 'b', (1, 0, 0, 1, 1, 1, 0): 'C', (0, 0, 0, 1, 1, 0, 1): 'c', (0, 1, 1, 1, 1, 0, 1): 'd', (1, 0, 0, 1, 1, 1, 1): 'E', (1, 0, 0, 0, 1, 1, 1): 'F', (1, 0, 1, 1, 1, 1, 0): 'G', (0, 1, 1, 0, 1, 1, 1): 'H', (0, 0, 1, 0, 1, 1, 1): 'h', (0, 0, 0, 0, 1, 1, 0): 'I', (1, 0, 0, 0, 1, 0, 0): 'i', (0, 0, 1, 0, 0, 0, 0): 'i', (0, 1, 1, 1, 1, 0, 0): 'J', (0, 1, 1, 1, 0, 0, 0): 'J', (1, 0, 1, 1, 0, 0, 0): 'j', (1, 0, 1, 0, 1, 1, 1): 'K', (0, 0 ,0, 1, 1, 1, 0): 'L', (1, 0, 1, 0, 1, 0, 0): 'M', (1, 0, 1, 0, 1, 0, 1): 'M', (1, 1, 1, 0, 1, 1, 0): 'N', (0, 0, 1, 0, 1, 0, 1): 'n', (0, 0, 1, 1, 1, 0, 1): 'o', (1, 1, 0, 0, 1, 1, 1): 'p', (1, 1, 1, 0, 0, 1, 1): 'q', (1, 1, 0, 0, 1, 1, 0): 'R', (0, 0, 0, 0, 1, 0, 1): 'r', (0, 0, 0, 1, 1, 1, 1): 't', (0, 0, 1, 1, 1, 0, 0): 'u', (0, 1, 0, 1, 0, 1, 0): 'V', (0, 1, 0, 0, 1, 1, 1): 'V', (0, 1, 1, 1, 1, 1, 0): 'V', (0, 1, 0, 0, 0, 1, 1): 'v', (0, 1, 0, 1, 0, 1, 1): 'W', (0, 0, 1, 0, 1, 0, 0): 'x', (0, 1, 1, 1, 0, 1, 1): 'y', (1, 1, 0, 1, 1, 0, 0): 'Z', (1, 1, 0, 0, 0, 1, 0): '^', (0, 0, 0, 1, 0, 0, 0): '_', } class Decoder(srd.Decoder): api_version = 3 id = 'seven_segment' name = '7-segment' longname = '7-segment display' desc = '7-segment display protocol.' license = 'gplv2+' inputs = ['logic'] outputs = [] tags = ['Display'] channels = ( {'id': 'a', 'name': 'A', 'desc': 'Segment A'}, {'id': 'b', 'name': 'B', 'desc': 'Segment B'}, {'id': 'c', 'name': 'C', 'desc': 'Segment C'}, {'id': 'd', 'name': 'D', 'desc': 'Segment D'}, {'id': 'e', 'name': 'E', 'desc': 'Segment E'}, {'id': 'f', 'name': 'F', 'desc': 'Segment F'}, {'id': 'g', 'name': 'G', 'desc': 'Segment G'}, ) optional_channels = ( {'id': 'dp', 'name': 'DP', 'desc': 'Decimal point'}, ) options = ( {'id': 'polarity', 'desc': 'Expected polarity', 'default': 'common-cathode', 'values': ('common-cathode', 'common-anode')}, {'id': 'show_unknown', 'desc': 'Display Unknown characters as #', 'default': 'no', 'values': ('yes', 'no')}, ) annotations = ( ('decoded-digit', 'Decoded digit'), ) annotation_rows = ( ('decoded-digits', 'Decoded digits', (0,)), ) def __init__(self): self.reset() def reset(self): pass def start(self): self.out_ann = self.register(srd.OUTPUT_ANN) def putb(self, ss_block, es_block, data): self.put(ss_block, es_block, self.out_ann, data) def pins_to_hex(self, pins): return digits.get(pins, None) def decode(self): oldpins = self.wait() lastpos = self.samplenum # Check mandatory and optional decoder input signals. if False in [p in (0, 1) for p in oldpins[:7]]: raise ChannelError('Need at least segments A-G.') self.have_dp = self.has_channel(7) seg_count = 8 if self.have_dp else 7 conditions = [{i: 'e'} for i in range(seg_count)] while True: # Wait for any change. pins = self.wait(conditions) # Invert all data lines if a common anode display is used. if self.options['polarity'] == 'common-anode': oldpins = tuple((1 - state for state in oldpins[:seg_count])) # Convert to character string. digit = self.pins_to_hex(oldpins[:7]) if digit is None and self.options['show_unknown'] == 'yes': digit = '#' # Emit annotation when conversion succeeded. # Optionally present the decimal point when active. if digit is not None: if self.have_dp: dp = oldpins[7] if dp == 1: digit += '.' self.putb(lastpos, self.samplenum, [0, [digit]]) oldpins = pins lastpos = self.samplenum