From 1c81c2e07521b014039873a67588cc9172bc16bf Mon Sep 17 00:00:00 2001 From: chenyue Date: Thu, 18 Jun 2026 10:45:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0counter=EF=BC=8C=E5=92=8Cpara?= =?UTF-8?q?llel=E8=A7=A3=E7=A0=81=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- counter/__init__.py | 28 ++ counter/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 430 bytes counter/__pycache__/pd.cpython-36.pyc | Bin 0 -> 3586 bytes counter/pd.py | 145 +++++++++++ parallel/__init__.py | 34 +++ parallel/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 810 bytes parallel/__pycache__/pd.cpython-36.pyc | Bin 0 -> 5776 bytes parallel/pd.py | 260 +++++++++++++++++++ 8 files changed, 467 insertions(+) create mode 100644 counter/__init__.py create mode 100644 counter/__pycache__/__init__.cpython-36.pyc create mode 100644 counter/__pycache__/pd.cpython-36.pyc create mode 100644 counter/pd.py create mode 100644 parallel/__init__.py create mode 100644 parallel/__pycache__/__init__.cpython-36.pyc create mode 100644 parallel/__pycache__/pd.cpython-36.pyc create mode 100644 parallel/pd.py diff --git a/counter/__init__.py b/counter/__init__.py new file mode 100644 index 0000000..505148d --- /dev/null +++ b/counter/__init__.py @@ -0,0 +1,28 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2018 Stefan Brüns +## +## 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 . +## + +''' +This decoder is a simple edge counter. + +It can count rising and/or falling edges, provides an optional reset +signal. It can also divide the count to e.g. count the number of +fixed-length words (where a word corresponds to e.g. 9 clock edges). +''' + +from .pd import Decoder diff --git a/counter/__pycache__/__init__.cpython-36.pyc b/counter/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e5162b92b482074b1d196a0a47df383f0d5f9527 GIT binary patch literal 430 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 E0gw~1S^xk5 literal 0 HcmV?d00001 diff --git a/counter/pd.py b/counter/pd.py new file mode 100644 index 0000000..a9f3536 --- /dev/null +++ b/counter/pd.py @@ -0,0 +1,145 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2018 Stefan Brüns +## +## 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 + +PIN_DATA, PIN_RESET = range(2) +ROW_EDGE, ROW_WORD, ROW_RESET = range(3) + +class Decoder(srd.Decoder): + api_version = 3 + id = 'counter' + name = 'Counter' + longname = 'Edge counter' + desc = 'Count the number of edges in a signal.' + license = 'gplv2+' + inputs = ['logic'] + outputs = [] + tags = ['Util'] + channels = ( + {'id': 'data', 'name': 'Data', 'desc': 'Data line', 'idn':'dec_counter_chan_data'}, + ) + optional_channels = ( + {'id': 'reset', 'name': 'Reset', 'desc': 'Reset line', 'idn':'dec_counter_opt_chan_reset'}, + ) + annotations = ( + ('edge_count', 'Edge count'), + ('word_count', 'Word count'), + ('word_reset', 'Word reset'), + ) + annotation_rows = ( + ('edge_counts', 'Edges', (ROW_EDGE,)), + ('word_counts', 'Words', (ROW_WORD,)), + ('word_resets', 'Word resets', (ROW_RESET,)), + ) + options = ( + {'id': 'data_edge', 'desc': 'Edges to count (data)', 'default': 'any', + 'values': ('any', 'rising', 'falling'), 'idn':'dec_counter_opt_data_edge'}, + {'id': 'divider', 'desc': 'Count divider (word width)', 'default': 0, 'idn':'dec_counter_opt_divider'}, + {'id': 'reset_edge', 'desc': 'Edge which clears counters (reset)', + 'default': 'falling', 'values': ('rising', 'falling'), 'idn':'dec_counter_opt_reset_edge'}, + {'id': 'edge_off', 'desc': 'Edge counter value after start/reset', 'default': 0, 'idn':'dec_counter_opt_edge_off'}, + {'id': 'word_off', 'desc': 'Word counter value after start/reset', 'default': 0, 'idn':'dec_counter_opt_word_off'}, + {'id': 'dead_cycles', 'desc': 'Ignore this many edges after reset', 'default': 0, 'idn':'dec_counter_opt_dead_cycles'}, + {'id': 'start_with_reset', 'desc': 'Assume decode starts with reset', + 'default': 'no', 'values': ('no', 'yes'), 'idn':'dec_counter_opt_start_with_reset'}, + ) + + def __init__(self): + self.reset() + + def reset(self): + pass + + def metadata(self, key, value): + if key == srd.SRD_CONF_SAMPLERATE: + self.samplerate = value + + def start(self): + self.out_ann = self.register(srd.OUTPUT_ANN) + + def putc(self, cls, ss, annlist): + self.put(ss, self.samplenum, self.out_ann, [cls, annlist]) + + def decode(self): + opt_edge_map = {'rising': 'r', 'falling': 'f', 'any': 'e'} + + data_edge = self.options['data_edge'] + divider = self.options['divider'] + if divider < 0: + divider = 0 + reset_edge = self.options['reset_edge'] + + condition = [{PIN_DATA: opt_edge_map[data_edge]}] + have_reset = self.has_channel(PIN_RESET) + if have_reset: + cond_reset = len(condition) + condition.append({PIN_RESET: opt_edge_map[reset_edge]}) + + edge_count = int(self.options['edge_off']) + edge_start = None + word_count = int(self.options['word_off']) + word_start = None + + if self.options['start_with_reset'] == 'yes': + dead_count = int(self.options['dead_cycles']) + else: + dead_count = 0 + + while True: + self.wait(condition) + now = self.samplenum + + if have_reset and (self.matched & (0b1 < +## +## 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 . +## + +''' +This protocol decoder can decode synchronous parallel buses with various +number of data bits/channels and one (optional) clock line. + +If no clock line is supplied, the decoder works slightly differently in +that it interprets every transition on any of the supplied data channels +like there had been a clock transition. + +It is required to use the lowest data channels, and use consecutive ones. +For example, for a 4-bit sync parallel bus, channels D0/D1/D2/D3 (and CLK) +should be used. Using combinations like D7/D12/D3/D15 is not supported. +For an 8-bit bus you should use D0-D7, for a 16-bit bus use D0-D15 and so on. +''' + +from .pd import Decoder diff --git a/parallel/__pycache__/__init__.cpython-36.pyc b/parallel/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..83ff4aba24ee33ea733fe20858594697c3b070fa GIT binary patch literal 810 zcmY+C-D=c86vwk^r4s0!4{$EKu-&xQS`iVUp&%6zs$SGWm}E{i!%pVJnaOVR3ci6a zQ1F%Z)+=AZE6?n1Y8#TtB^dXuK;lJ0+iM<)F3XsU!^&OOj}z6lS{z*PF7oWT<05VTIPHq39esSSnw` zLRiJN#B@!;kyL>cUO=I|OUqgqgW7>G638GNQ0o;Lp~p~aD(9e;!D*7bufWiQU%*hV zYg?^QPQcfAPqrjGXPZ{D+Up*qsw%W-!d{ug*TRG1+jz9CMehI?XnXKh7^gyQ=3tyY zfQGz7l@0X(oM<)2V7CahkWe6U)E4l6u0YPk99aC`DT@+30ZX&atZ9kPKh8T@D-k?O zG7ihms|5yS+%&l$3wSG5&n1<4zKUCE!_fYU zEYI?0`Fnc)I{jp6W<>)RN~24&tFH=|>2^-t%`lNSd9IA|c|L9X)zdc($xh>2;7l%L H-HrbN@FNBO literal 0 HcmV?d00001 diff --git a/parallel/__pycache__/pd.cpython-36.pyc b/parallel/__pycache__/pd.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a8b8bd3818d739b1e759e31070636face5f106c GIT binary patch literal 5776 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 LQ8znm+2(%%1t1$0 literal 0 HcmV?d00001 diff --git a/parallel/pd.py b/parallel/pd.py new file mode 100644 index 0000000..5649f0f --- /dev/null +++ b/parallel/pd.py @@ -0,0 +1,260 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2013-2016 Uwe Hermann +## +## 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 +from common.srdhelper import bitpack + +''' +OUTPUT_PYTHON format: + +Packet: +[, ] + +, + - 'ITEM', [, ] + - 'WORD', [, , ] + +: + - A single item (a number). It can be of arbitrary size. The max. number + of bits in this item is specified in . + +: + - The size of an item (in bits). For a 4-bit parallel bus this is 4, + for a 16-bit parallel bus this is 16, and so on. + +: + - A single word (a number). It can be of arbitrary size. The max. number + of bits in this word is specified in . The (exact) number + of items in this word is specified in . + +: + - The size of a word (in bits). For a 2-item word with 8-bit items + is 16, for a 3-item word with 4-bit items + is 12, and so on. + +: + - The size of a word (in number of items). For a 4-item word (no matter + how many bits each item consists of) is 4, for a 7-item + word is 7, and so on. +''' + +def channel_list(num_channels): + l = [{'id': 'clk', 'name': 'CLK', 'desc': 'Clock line'}] + for i in range(num_channels): + d = {'id': 'd%d' % i, 'name': 'D%d' % i, 'desc': 'Data line %d' % i} + l.append(d) + return tuple(l) + +class ChannelError(Exception): + pass + +NUM_CHANNELS = 32 + +class Decoder(srd.Decoder): + api_version = 3 + id = 'parallel' + name = 'Parallel' + longname = 'Parallel sync bus' + desc = 'Generic parallel synchronous bus.' + license = 'gplv2+' + inputs = ['logic'] + outputs = ['parallel'] + tags = ['Util'] + optional_channels = channel_list(NUM_CHANNELS) + options = ( + {'id': 'clock_edge', 'desc': 'Clock edge to sample on', + 'default': 'rising', 'values': ('rising', 'falling'), 'idn':'dec_parallel_opt_clock_edge'}, + {'id': 'wordsize', 'desc': 'Data wordsize (# bus cycles)', + 'default': 0, 'idn':'dec_parallel_opt_wordsize'}, + {'id': 'endianness', 'desc': 'Data endianness', + 'default': 'little', 'values': ('little', 'big'), 'idn':'dec_parallel_opt_endianness'}, + ) + annotations = ( + ('items', 'Items'), + ('words', 'Words'), + ) + annotation_rows = ( + ('items', 'Items', (0,)), + ('words', 'Words', (1,)), + ) + + def __init__(self): + self.reset() + + def reset(self): + self.items = [] + self.saved_item = None + self.saved_word = None + self.ss_word = self.es_word = None + self.first = True + self.have_clock = True + self.prv_dex = 0 + self.num_item_bits = None + + def start(self): + self.out_python = self.register(srd.OUTPUT_PYTHON) + self.out_ann = self.register(srd.OUTPUT_ANN) + + def putpw(self, data): + self.put(self.ss_word, self.es_word, self.out_python, data) + + def putw(self, data): + self.put(self.ss_word, self.es_word, self.out_ann, data) + + def put_ann(self, s, e, data): + self.put(s, e, self.out_ann, data) + + def put_py(self, s, e, data): + self.put(s, e, self.out_python, data) + + def handle_bits(self, item): + # If a word was previously accumulated, then emit its annotation + # now after its end samplenumber became available. + cur_dex = self.samplenum + + # Defer annotations for individual items until the next sample + # is taken, and the previous sample's end samplenumber has + # become available. + if self.first: + # Save the start sample and item for later (no output yet). + if not self.have_clock: + self.put_py(self.prv_dex, cur_dex, ['ITEM', self.saved_item]) + self.put_ann(self.prv_dex, cur_dex, [0, [self.fmt_item.format(self.saved_item)]]) + + self.first = False + self.saved_item = item + else: + # Output the saved item (from the last CLK edge to the current). + self.put_py(self.prv_dex, cur_dex, ['ITEM', self.saved_item]) + self.put_ann(self.prv_dex, cur_dex, [0, [self.fmt_item.format(self.saved_item)]]) + self.saved_item = item + + self.prv_dex = cur_dex + self.handel_word(item, cur_dex) + + #word + def handel_word(self, item, cur_dex): + if self.saved_word is not None: + if self.options['wordsize'] > 0: + self.es_word = cur_dex + self.putw([1, [self.fmt_word.format(self.saved_word)]]) + self.putpw(['WORD', self.saved_word]) + self.saved_word = None + + if item is None: + return + + # Get as many items as the configured wordsize specifies. + if not self.items: + self.ss_word = cur_dex + + self.items.append(item) + ws = self.options['wordsize'] + + if len(self.items) < ws: + return + + # Collect words and prepare annotation details, but defer emission + # until the end samplenumber becomes available. + endian = self.options['endianness'] + + if endian == 'big': + self.items.reverse() + + word = sum([self.items[i] << (i * self.num_item_bits) for i in range(ws)]) + self.saved_word = word + self.items = [] + + def end(self): + cur_dex = self.last_samplenum + #the last annotation + if self.saved_item != None: + self.put_py(self.prv_dex, cur_dex, ['ITEM', self.saved_item]) + self.put_ann(self.prv_dex, cur_dex, [0, [self.fmt_item.format(self.saved_item)]]) + self.handel_word(None, cur_dex) + + def decode(self): + # Determine which (optional) channels have input data. Insist in + # a non-empty input data set. Cope with sparse connection maps. + # Store enough state to later "compress" sampled input data. + max_possible = len(self.optional_channels) + + idx_channels = [ + idx if self.has_channel(idx) else None + for idx in range(max_possible) + ] + + has_channels = [idx for idx in idx_channels if idx is not None] + if not has_channels: + raise ChannelError('At least one channel has to be supplied.') + max_connected = max(has_channels) + + self.have_clock = self.has_channel(0) + self.prv_dex = self.samplenum + have_clock = self.have_clock + + # Determine .wait() conditions, depending on the presence of a + # clock signal. Either inspect samples on the configured edge of + # the clock, or inspect samples upon ANY edge of ANY of the pins + # which provide input data. + if have_clock: + edge = self.options['clock_edge'][0] + conds = {0: edge} #'f' or 'r' + else: + conds = [{idx: 'e'} for idx in has_channels] + + # Pre-determine which input data to strip off, the width of + # individual items and multiplexed words, as well as format + # strings here. This simplifies call sites which run in tight + # loops later. + idx_strip = max_connected + 1 + num_item_bits = idx_strip - 1 + num_word_items = self.options['wordsize'] + num_word_bits = num_item_bits * num_word_items + num_digits = (num_item_bits + 3) // 4 + self.fmt_item = "@{{:0{}X}}".format(num_digits) + num_digits = (num_word_bits + 3) // 4 + self.fmt_word = "@{{:0{}X}}".format(num_digits) + self.num_item_bits = num_item_bits + + # Keep processing the input stream. Assume "always zero" for + # not-connected input lines. Pass data bits (all inputs except + # clock) to the handle_bits() method. + + is_first = True + the_conds = conds + + while True: + if not have_clock and is_first: + #get the value at sample 0 + conds = None + else: + conds = the_conds + + (clk, d0, d1, d2, d3, d4, d5, d6, d7,d8, d9,d10 ,d11 ,d12 ,d13 ,d14 ,d15 ,d16 ,d17 ,d18 ,d19 ,d20 ,d21 ,d22 ,d23 ,d24 ,d25 ,d26 ,d27 ,d28 ,d29 ,d30 ,d31 ) = self.wait(conds) + pins = (clk, d0, d1, d2, d3, d4, d5, d6, d7,d8, d9, d10, d11, d12,d13 ,d14 ,d15 ,d16 ,d17 ,d18 ,d19 ,d20 ,d21 ,d22 ,d23 ,d24 ,d25 ,d26 ,d27 ,d28 ,d29 ,d30 ,d31 ) + bits = [0 if idx is None else pins[idx] for idx in idx_channels] + item = bitpack(bits[1:idx_strip]) + + if not have_clock and is_first: + is_first = False + self.saved_item = item + continue + + self.handle_bits(item)