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
26 class Decoder(srd.Decoder):
30 longname = 'Digital calipers'
31 desc = 'Protocol of cheap generic digital calipers.'
36 {'id': 'clk', 'name': 'CLK', 'desc': 'Serial clock line'},
37 {'id': 'data', 'name': 'DATA', 'desc': 'Serial data line'},
40 {'id': 'timeout_ms', 'desc': 'Packet timeout in ms, 0 to disable',
42 {'id': 'unit', 'desc': 'Convert units', 'default': 'keep',
43 'values': ('keep', 'mm', 'inch')},
44 {'id': 'changes', 'desc': 'Changes only', 'default': 'no',
45 'values': ('no', 'yes')},
47 tags = ['Analog/digital', 'Sensor']
49 ('measurement', 'Measurement'),
50 ('warning', 'Warning'),
53 ('measurements', 'Measurements', (0,)),
54 ('warnings', 'Warnings', (1,)),
57 def metadata(self, key, value):
58 if key == srd.SRD_CONF_SAMPLERATE:
59 self.samplerate = value
65 self.ss_cmd, self.es_cmd = 0, 0
71 self.out_ann = self.register(srd.OUTPUT_ANN)
73 def putg(self, ss, es, cls, data):
74 self.put(ss, es, self.out_ann, [cls, data])
76 # Switch bit order of variable x, which is l bit long.
78 return int(bin(x)[2:].zfill(l)[::-1], 2)
81 last_measurement = None
82 timeout_ms = self.options['timeout_ms']
83 want_unit = self.options['unit']
84 show_all = self.options['changes'] == 'no'
85 snum_per_ms = self.samplerate / 1000
86 timeout_snum = timeout_ms * snum_per_ms
88 clk, data = self.wait([{0: 'r'}, {'skip': round(snum_per_ms)}])
90 # Timeout after inactivity.
92 if self.samplenum > self.es_cmd + timeout_snum:
94 self.putg(self.ss_cmd, self.samplenum, 1, [
95 'timeout with %s bits in buffer' % (self.bits),
100 # Do nothing if there was timeout without rising clock edge.
101 if self.matched == (False, True):
104 # Store position of last activity.
105 self.es_cmd = self.samplenum
107 # Store position of first bit.
109 self.ss_cmd = self.samplenum
111 # Shift in measured number.
113 self.number = (self.number << 1) | (data & 0b1)
117 # Shift in flag bits.
119 self.flags = (self.flags << 1) | (data & 0b1)
123 # We got last bit of data.
124 self.es_cmd = self.samplenum
126 # Do actual decoding.
128 negative = ((self.flags & 0b00001000) >> 3)
129 inch = (self.flags & 0b00000001)
131 number = self.bitr(self.number, 16)
136 inchmm = 25.4 #how many mms in inch
139 number = number / 2000
140 if want_unit == 'mm':
144 number = number / 100
145 if want_unit == 'inch':
146 number = round(number / inchmm, 4)
149 units = "in" if inch else "mm"
151 measurement = (str(number) + units)
153 if show_all or measurement != last_measurement:
154 self.putg(self.ss_cmd, self.es_cmd, 0, [
158 last_measurement = measurement
160 # Prepare for next packet.