2 ## This file is part of the libsigrokdecode project.
4 ## Copyright (C) 2020 Tomas Mudrunka <harvie@github>
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
25 from common.srdhelper import bitpack
27 # Millimeters per inch.
30 class Decoder(srd.Decoder):
34 longname = 'Digital calipers'
35 desc = 'Protocol of cheap generic digital calipers.'
40 {'id': 'clk', 'name': 'CLK', 'desc': 'Serial clock line'},
41 {'id': 'data', 'name': 'DATA', 'desc': 'Serial data line'},
44 {'id': 'timeout_ms', 'desc': 'Packet timeout in ms, 0 to disable',
46 {'id': 'unit', 'desc': 'Convert units', 'default': 'keep',
47 'values': ('keep', 'mm', 'inch')},
48 {'id': 'changes', 'desc': 'Changes only', 'default': 'no',
49 'values': ('no', 'yes')},
51 tags = ['Analog/digital', 'Sensor']
53 ('measurement', 'Measurement'),
54 ('warning', 'Warning'),
57 ('measurements', 'Measurements', (0,)),
58 ('warnings', 'Warnings', (1,)),
61 def metadata(self, key, value):
62 if key == srd.SRD_CONF_SAMPLERATE:
63 self.samplerate = value
69 self.ss, self.es = 0, 0
74 self.out_ann = self.register(srd.OUTPUT_ANN)
76 def putg(self, ss, es, cls, data):
77 self.put(ss, es, self.out_ann, [cls, data])
81 timeout_ms = self.options['timeout_ms']
82 want_unit = self.options['unit']
83 show_all = self.options['changes'] == 'no'
84 wait_cond = [{0: 'r'}]
86 snum_per_ms = self.samplerate / 1000
87 timeout_snum = timeout_ms * snum_per_ms
88 wait_cond.append({'skip': round(timeout_snum)})
90 # Sample data at the rising clock edge. Optionally timeout
91 # after inactivity for a user specified period. Present the
92 # number of unprocessed bits to the user for diagnostics.
93 clk, data = self.wait(wait_cond)
94 if timeout_ms and not self.matched[0]:
95 if self.number_bits or self.flags_bits:
96 count = len(self.number_bits) + len(self.flags_bits)
97 self.putg(self.ss, self.samplenum, 1, [
98 'timeout with {} bits in buffer'.format(count),
99 'timeout ({} bits)'.format(count),
105 # Store position of first bit and last activity.
106 # Shift in measured number and flag bits.
108 self.ss = self.samplenum
109 self.es = self.samplenum
110 if len(self.number_bits) < 16:
111 self.number_bits.append(data)
113 if len(self.flags_bits) < 8:
114 self.flags_bits.append(data)
115 if len(self.flags_bits) < 8:
118 # Get raw values from received data bits. Run the number
119 # conversion, controlled by flags and/or user specs.
120 negative = bool(self.flags_bits[4])
121 is_inch = bool(self.flags_bits[7])
122 number = bitpack(self.number_bits)
127 if want_unit == 'mm':
128 number *= mm_per_inch
132 if want_unit == 'inch':
133 number = round(number / mm_per_inch, 4)
135 unit = 'in' if is_inch else 'mm'
137 # Construct and emit an annotation.
138 if show_all or (number, unit) != last_sent:
139 self.putg(self.ss, self.es, 0, [
140 '{number}{unit}'.format(**locals()),
141 '{number}'.format(**locals()),
143 last_sent = (number, unit)
145 # Reset internal state for the start of the next packet.