allow changes-only mode
[mirrors/Programs.git] / plugins / sigrok-decoders / caliper / pd.py
CommitLineData
63efb482
TM
1##
2## This file is part of the libsigrokdecode project.
3##
4## Copyright (C) 2020 Tomas Mudrunka <harvie@github>
5##
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:
12##
13## The above copyright notice and this permission notice shall be included in all
14## copies or substantial portions of the Software.
15##
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
22## SOFTWARE.
23
24import sigrokdecode as srd
25
26class Decoder(srd.Decoder):
27 api_version = 3
28 id = 'caliper'
29 name = 'Caliper'
30 longname = 'Digital calipers'
31 desc = 'Protocol of cheap generic digital calipers'
32 license = 'mit'
33 inputs = ['logic']
34 outputs = []
35 channels = (
36 {'id': 'clk', 'name': 'CLK', 'desc': 'Serial clock line'},
37 {'id': 'data', 'name': 'DATA', 'desc': 'Serial data line'},
38 )
39 options = (
40 {'id': 'timeout_ms', 'desc': 'Timeout packet after X ms, 0 to disable', 'default': 10},
41 {'id': 'unit', 'desc': 'Convert units', 'default': 'keep', 'values': ('keep', 'mm', 'inch')},
487a386c 42 {'id': 'changes', 'desc': 'Changes only', 'default': 'no', 'values': ('no', 'yes')},
63efb482
TM
43 )
44 tags = ['Analog/digital', 'IC', 'Sensor']
45 annotations = (
46 ('measurements', 'Measurements'),
47 ('warning', 'Warnings'),
48 )
49 annotation_rows = (
50 ('measurements', 'Measurements', (0,)),
51 ('warnings', 'Warnings', (1,)),
52 )
53
54 def reset_data(self):
55 self.bits = 0
56 self.number = 0
57 self.flags = 0
58
59 def metadata(self, key, value):
60 if key == srd.SRD_CONF_SAMPLERATE:
61 self.samplerate = value
62
63 def __init__(self):
64 self.reset()
65
66 def reset(self):
67 self.ss_cmd, self.es_cmd = 0, 0
68 self.reset_data()
69
70 def start(self):
71 self.out_ann = self.register(srd.OUTPUT_ANN)
72
73 #Switch bit order of variable x, which is l bit long
74 def bitr(self,x,l):
75 return int(bin(x)[2:].zfill(l)[::-1], 2)
76
77 def decode(self):
487a386c 78 self.last_measurement = None
63efb482
TM
79 while True:
80 clk, data = self.wait([{0: 'r'},{'skip': round(self.samplerate/1000)}])
81 #print([clk,data])
82
83 #Timeout after inactivity
84 if(self.options['timeout_ms'] > 0):
85 if self.samplenum > self.es_cmd + (self.samplerate/(1000/self.options['timeout_ms'])):
86 if self.bits > 0:
87 self.put(self.ss_cmd, self.samplenum, self.out_ann, [1, ['timeout with %s bits in buffer'%(self.bits),'timeout']])
88 self.reset()
89
90 #Do nothing if there was timeout without rising clock edge
91 if self.matched == (False, True):
92 continue
93
94 #Store position of last activity
95 self.es_cmd = self.samplenum
96
97 #Store position of first bit
98 if self.ss_cmd == 0:
99 self.ss_cmd = self.samplenum
100
101 #Shift in measured number
102 if self.bits < 16:
103 self.number = (self.number << 1) | (data & 0b1)
104 self.bits+=1
105 continue
106
107 #Shift in flag bits
108 if self.bits < 24:
109 self.flags = (self.flags << 1) | (data & 0b1)
110 self.bits+=1
111 if self.bits < 24:
112 continue
113 #Hooray! We got last bit of data
114 self.es_cmd = self.samplenum
115
116 #Do actual decoding
117
118 #print(format(self.flags, '08b'));
119
120 negative = ((self.flags & 0b00001000) >> 3)
121 inch = (self.flags & 0b00000001)
122
123 number = self.bitr(self.number, 16)
124
125 #print(format(number, '016b'))
126
127 if negative > 0:
128 number = -number
129
130 inchmm = 25.4 #how many mms in inch
131
132 if inch:
133 number = number/2000
134 if self.options['unit'] == 'mm':
135 number *= inchmm
136 inch = 0
137 else:
138 number = number/100
139 if self.options['unit'] == 'inch':
140 number = round(number/inchmm,4)
141 inch = 1
142
143 units = "in" if inch else "mm"
144
145 measurement = (str(number)+units)
146 #print(measurement)
147
487a386c
TM
148 if ((self.options['changes'] == 'no') or (self.last_measurement != measurement)):
149 self.put(self.ss_cmd, self.es_cmd, self.out_ann, [0, [measurement, str(number)]])
150 self.last_measurement = measurement
63efb482
TM
151
152 #Prepare for next packet
153 self.reset()
This page took 0.223616 seconds and 4 git commands to generate.