]>
Commit | Line | Data |
---|---|---|
5ed5cea5 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 | ||
24 | import sigrokdecode as srd | |
25 | ||
26 | class Decoder(srd.Decoder): | |
27 | api_version = 3 | |
28 | id = 'caliper' | |
29 | name = 'Caliper' | |
30 | longname = 'Digital calipers' | |
4afcb4d0 | 31 | desc = 'Protocol of cheap generic digital calipers.' |
5ed5cea5 TM |
32 | license = 'mit' |
33 | inputs = ['logic'] | |
34 | outputs = [] | |
35 | channels = ( | |
4afcb4d0 GS |
36 | {'id': 'clk', 'name': 'CLK', 'desc': 'Serial clock line'}, |
37 | {'id': 'data', 'name': 'DATA', 'desc': 'Serial data line'}, | |
5ed5cea5 TM |
38 | ) |
39 | options = ( | |
4afcb4d0 GS |
40 | {'id': 'timeout_ms', 'desc': 'Packet timeout in ms, 0 to disable', |
41 | 'default': 10}, | |
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')}, | |
5ed5cea5 | 46 | ) |
4afcb4d0 | 47 | tags = ['Analog/digital', 'Sensor'] |
5ed5cea5 | 48 | annotations = ( |
4afcb4d0 GS |
49 | ('measurement', 'Measurement'), |
50 | ('warning', 'Warning'), | |
5ed5cea5 TM |
51 | ) |
52 | annotation_rows = ( | |
53 | ('measurements', 'Measurements', (0,)), | |
54 | ('warnings', 'Warnings', (1,)), | |
55 | ) | |
56 | ||
5ed5cea5 TM |
57 | def metadata(self, key, value): |
58 | if key == srd.SRD_CONF_SAMPLERATE: | |
59 | self.samplerate = value | |
60 | ||
61 | def __init__(self): | |
62 | self.reset() | |
63 | ||
64 | def reset(self): | |
65 | self.ss_cmd, self.es_cmd = 0, 0 | |
b3fafeb4 GS |
66 | self.bits = 0 |
67 | self.number = 0 | |
68 | self.flags = 0 | |
5ed5cea5 TM |
69 | |
70 | def start(self): | |
71 | self.out_ann = self.register(srd.OUTPUT_ANN) | |
72 | ||
b3fafeb4 GS |
73 | def putg(self, ss, es, cls, data): |
74 | self.put(ss, es, self.out_ann, [cls, data]) | |
75 | ||
4afcb4d0 GS |
76 | # Switch bit order of variable x, which is l bit long. |
77 | def bitr(self, x, l): | |
5ed5cea5 TM |
78 | return int(bin(x)[2:].zfill(l)[::-1], 2) |
79 | ||
80 | def decode(self): | |
b3fafeb4 GS |
81 | last_measurement = None |
82 | timeout_ms = self.options['timeout_ms'] | |
83 | want_unit = self.options['unit'] | |
84 | show_all = self.options['changes'] == 'no' | |
b213c046 GS |
85 | snum_per_ms = self.samplerate / 1000 |
86 | timeout_snum = timeout_ms * snum_per_ms | |
5ed5cea5 | 87 | while True: |
b213c046 | 88 | clk, data = self.wait([{0: 'r'}, {'skip': round(snum_per_ms)}]) |
5ed5cea5 | 89 | |
4afcb4d0 | 90 | # Timeout after inactivity. |
b3fafeb4 | 91 | if timeout_ms > 0: |
b213c046 | 92 | if self.samplenum > self.es_cmd + timeout_snum: |
5ed5cea5 | 93 | if self.bits > 0: |
b3fafeb4 GS |
94 | self.putg(self.ss_cmd, self.samplenum, 1, [ |
95 | 'timeout with %s bits in buffer' % (self.bits), | |
96 | 'timeout', | |
97 | ]) | |
5ed5cea5 TM |
98 | self.reset() |
99 | ||
4afcb4d0 | 100 | # Do nothing if there was timeout without rising clock edge. |
5ed5cea5 TM |
101 | if self.matched == (False, True): |
102 | continue | |
103 | ||
4afcb4d0 | 104 | # Store position of last activity. |
5ed5cea5 TM |
105 | self.es_cmd = self.samplenum |
106 | ||
4afcb4d0 | 107 | # Store position of first bit. |
5ed5cea5 TM |
108 | if self.ss_cmd == 0: |
109 | self.ss_cmd = self.samplenum | |
110 | ||
4afcb4d0 | 111 | # Shift in measured number. |
5ed5cea5 TM |
112 | if self.bits < 16: |
113 | self.number = (self.number << 1) | (data & 0b1) | |
4afcb4d0 | 114 | self.bits += 1 |
5ed5cea5 TM |
115 | continue |
116 | ||
4afcb4d0 | 117 | # Shift in flag bits. |
5ed5cea5 TM |
118 | if self.bits < 24: |
119 | self.flags = (self.flags << 1) | (data & 0b1) | |
4afcb4d0 | 120 | self.bits += 1 |
5ed5cea5 TM |
121 | if self.bits < 24: |
122 | continue | |
4afcb4d0 | 123 | # We got last bit of data. |
5ed5cea5 TM |
124 | self.es_cmd = self.samplenum |
125 | ||
4afcb4d0 | 126 | # Do actual decoding. |
5ed5cea5 TM |
127 | |
128 | negative = ((self.flags & 0b00001000) >> 3) | |
129 | inch = (self.flags & 0b00000001) | |
130 | ||
131 | number = self.bitr(self.number, 16) | |
132 | ||
5ed5cea5 TM |
133 | if negative > 0: |
134 | number = -number | |
135 | ||
136 | inchmm = 25.4 #how many mms in inch | |
137 | ||
138 | if inch: | |
4afcb4d0 | 139 | number = number / 2000 |
b3fafeb4 | 140 | if want_unit == 'mm': |
5ed5cea5 TM |
141 | number *= inchmm |
142 | inch = 0 | |
143 | else: | |
4afcb4d0 | 144 | number = number / 100 |
b3fafeb4 | 145 | if want_unit == 'inch': |
4afcb4d0 | 146 | number = round(number / inchmm, 4) |
5ed5cea5 TM |
147 | inch = 1 |
148 | ||
149 | units = "in" if inch else "mm" | |
150 | ||
4afcb4d0 | 151 | measurement = (str(number) + units) |
5ed5cea5 | 152 | |
b3fafeb4 GS |
153 | if show_all or measurement != last_measurement: |
154 | self.putg(self.ss_cmd, self.es_cmd, 0, [ | |
155 | measurement, | |
156 | str(number), | |
157 | ]) | |
158 | last_measurement = measurement | |
5ed5cea5 | 159 | |
4afcb4d0 | 160 | # Prepare for next packet. |
5ed5cea5 | 161 | self.reset() |