]> sigrok.org Git - libsigrokdecode.git/blame - decoders/qi/pd.py
avr_isp: Add more parts
[libsigrokdecode.git] / decoders / qi / pd.py
CommitLineData
d574715e
JG
1##
2## This file is part of the libsigrokdecode project.
3##
4## Copyright (C) 2015 Josef Gajdusek <atx@atx.name>
5##
6## This program is free software; you can redistribute it and/or modify
7## it under the terms of the GNU General Public License as published by
8## the Free Software Foundation; either version 2 of the License, or
9## (at your option) any later version.
10##
11## This program is distributed in the hope that it will be useful,
12## but WITHOUT ANY WARRANTY; without even the implied warranty of
13## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14## GNU General Public License for more details.
15##
16## You should have received a copy of the GNU General Public License
4539e9ca 17## along with this program; if not, see <http://www.gnu.org/licenses/>.
d574715e
JG
18##
19
20import sigrokdecode as srd
21import operator
22import collections
23from functools import reduce
24
25end_codes = (
26 'Unknown',
27 'Charge Complete',
28 'Internal Fault',
29 'Over Temperature',
30 'Over Voltage',
31 'Over Current',
32 'Battery Failure',
33 'Reconfigure',
34 'No Response',
35)
36
37class SamplerateError(Exception):
38 pass
39
40def calc_checksum(packet):
41 return reduce(operator.xor, packet[:-1])
42
43def bits_to_uint(bits):
44 # LSB first
45 return reduce(lambda i, v: (i >> 1) | (v << (len(bits) - 1)), bits, 0)
46
47class Decoder(srd.Decoder):
d9135fe1 48 api_version = 3
d574715e
JG
49 id = 'qi'
50 name = 'Qi'
51 longname = 'Qi charger protocol'
c14ef8e3 52 desc = 'Protocol used by Qi receiver.'
d574715e
JG
53 license = 'gplv2+'
54 inputs = ['logic']
6cbba91f 55 outputs = []
d6d8a8a4 56 tags = ['Embedded/industrial', 'Wireless/RF']
d574715e
JG
57 channels = (
58 {'id': 'qi', 'name': 'Qi', 'desc': 'Demodulated Qi data line'},
59 )
60 annotations = (
e144452b
UH
61 ('bit', 'Bit'),
62 ('byte-error', 'Bit error'),
63 ('byte-start', 'Start bit'),
64 ('byte-info', 'Info bit'),
65 ('byte-data', 'Data byte'),
66 ('packet-data', 'Packet data'),
67 ('packet-checksum-ok', 'Packet checksum OK'),
68 ('packet-checksum-err', 'Packet checksum error'),
d574715e
JG
69 )
70 annotation_rows = (
71 ('bits', 'Bits', (0,)),
72 ('bytes', 'Bytes', (1, 2, 3, 4)),
73 ('packets', 'Packets', (5, 6, 7)),
74 )
75
92b7b49f 76 def __init__(self):
10aeb8ea
GS
77 self.reset()
78
79 def reset(self):
d574715e
JG
80 self.samplerate = None
81 self.reset_variables()
82
83 def reset_variables(self):
84 self.counter = 0
85 self.prev = None
86 self.state = 'IDLE'
87 self.lastbit = 0
88 self.bytestart = 0
89 self.deq = collections.deque(maxlen = 2)
90 self.bits = []
91 self.bitsi = [0]
92 self.bytesi = []
93 self.packet = []
94
95 def metadata(self, key, value):
96 if key == srd.SRD_CONF_SAMPLERATE:
97 self.samplerate = value
98 self.bit_width = float(self.samplerate) / 2e3
99
100 def start(self):
101 self.out_ann = self.register(srd.OUTPUT_ANN)
102 self.reset_variables()
103
104 def packet_len(self, byte):
105 if 0x00 <= byte <= 0x1f:
106 return int(1 + (byte - 0) / 32)
107 if 0x20 <= byte <= 0x7f:
108 return int(2 + (byte - 32) / 16)
109 if 0x80 <= byte <= 0xdf:
110 return int(8 + (byte - 128) / 8)
111 if 0xe0 <= byte <= 0xff:
112 return int(20 + (byte - 224) / 4)
113
114 def in_tolerance(self, l):
115 return (0.75 * self.bit_width) < l < (1.25 * self.bit_width)
116
117 def putp(self, data):
118 self.put(self.bytesi[0], self.bytesi[-1], self.out_ann, [5, data])
119
120 def process_packet(self):
121 if self.packet[0] == 0x01: # Signal Strength
122 self.putp(['Signal Strength: %d' % self.packet[1],
123 'SS: %d' % self.packet[1], 'SS'])
124 elif self.packet[0] == 0x02: # End Power Transfer
125 reason = end_codes[self.packet[1]] if self.packet[1] < len(end_codes) else 'Reserved'
126 self.putp(['End Power Transfer: %s' % reason,
127 'EPT: %s' % reason, 'EPT'])
128 elif self.packet[0] == 0x03: # Control Error
129 val = self.packet[1] if self.packet[1] < 128 else (self.packet[1] & 0x7f) - 128
130 self.putp(['Control Error: %d' % val, 'CE: %d' % val, 'CE'])
131 elif self.packet[0] == 0x04: # Received Power
132 self.putp(['Received Power: %d' % self.packet[1],
133 'RP: %d' % self.packet[1], 'RP'])
134 elif self.packet[0] == 0x05: # Charge Status
135 self.putp(['Charge Status: %d' % self.packet[1],
136 'CS: %d' % self.packet[1], 'CS'])
137 elif self.packet[0] == 0x06: # Power Control Hold-off
138 self.putp(['Power Control Hold-off: %dms' % self.packet[1],
139 'PCH: %d' % self.packet[1]], 'PCH')
140 elif self.packet[0] == 0x51: # Configuration
141 powerclass = (self.packet[1] & 0xc0) >> 7
142 maxpower = self.packet[1] & 0x3f
143 prop = (self.packet[3] & 0x80) >> 7
144 count = self.packet[3] & 0x07
145 winsize = (self.packet[4] & 0xf8) >> 3
146 winoff = self.packet[4] & 0x07
147 self.putp(['Configuration: Power Class = %d, Maximum Power = %d, Prop = %d,'
148 'Count = %d, Window Size = %d, Window Offset = %d' %
149 (powerclass, maxpower, prop, count, winsize, winoff),
150 'C: PC = %d MP = %d P = %d C = %d WS = %d WO = %d' %
151 (powerclass, maxpower, prop, count, winsize, winoff),
152 'Configuration', 'C'])
18101a31 153 elif self.packet[0] == 0x71: # Identification
d574715e
JG
154 version = '%d.%d' % ((self.packet[1] & 0xf0) >> 4, self.packet[1] & 0x0f)
155 mancode = '%02x%02x' % (self.packet[2], self.packet[3])
156 devid = '%02x%02x%02x%02x' % (self.packet[4] & ~0x80,
157 self.packet[5], self.packet[6], self.packet[7])
158 self.putp(['Identification: Version = %s, Manufacturer = %s, ' \
159 'Device = %s' % (version, mancode, devid),
160 'ID: %s %s %s' % (version, mancode, devid), 'ID'])
161 elif self.packet[0] == 0x81: # Extended Identification
162 edevid = '%02x%02x%02x%02x%02x%02x%02x%02x' % self.packet[1:-1]
163 self.putp(['Extended Identification: %s' % edevid,
164 'EI: %s' % edevid, 'EI'])
165 elif self.packet[0] in (0x18, 0x19, 0x28, 0x29, 0x38, 0x48, 0x58, 0x68,
166 0x78, 0x85, 0xa4, 0xc4, 0xe2): # Proprietary
167 self.putp(['Proprietary', 'P'])
168 else: # Unknown
169 self.putp(['Unknown', '?'])
170 self.put(self.bytesi[-1], self.samplenum, self.out_ann,
171 [6, ['Checksum OK', 'OK']] if \
172 calc_checksum(self.packet) == self.packet[-1]
173 else [6, ['Checksum error', 'ERR']])
174
175 def process_byte(self):
176 self.put(self.bytestart, self.bitsi[0], self.out_ann,
177 ([2, ['Start bit', 'Start', 'S']]) if self.bits[0] == 0 else
178 ([1, ['Start error', 'Start err', 'SE']]))
179 databits = self.bits[1:9]
180 data = bits_to_uint(databits)
181 parity = reduce(lambda i, v: (i + v) % 2, databits, 1)
182 self.put(self.bitsi[0], self.bitsi[8], self.out_ann, [4, ['%02x' % data]])
183 self.put(self.bitsi[8], self.bitsi[9], self.out_ann,
184 ([3, ['Parity bit', 'Parity', 'P']]) if self.bits[9] == parity else
185 ([1, ['Parity error', 'Parity err', 'PE']]))
186 self.put(self.bitsi[9], self.bitsi[10], self.out_ann,
187 ([3, ['Stop bit', 'Stop', 'S']]) if self.bits[10] == 1 else
188 ([1, ['Stop error', 'Stop err', 'SE']]))
189
190 self.bytesi.append(self.bytestart)
191 self.packet.append(data)
192 if self.packet_len(self.packet[0]) + 2 == len(self.packet):
193 self.process_packet()
194 self.bytesi.clear()
195 self.packet.clear()
196
197 def add_bit(self, bit):
198 self.bits.append(bit)
199 self.bitsi.append(self.samplenum)
200
201 if self.state == 'IDLE' and len(self.bits) >= 5 and \
202 self.bits[-5:] == [1, 1, 1, 1, 0]:
203 self.state = 'DATA'
204 self.bytestart = self.bitsi[-2]
205 self.bits = [0]
206 self.bitsi = [self.samplenum]
207 self.packet.clear()
208 elif self.state == 'DATA' and len(self.bits) == 11:
209 self.process_byte()
210 self.bytestart = self.samplenum
211 self.bits.clear()
212 self.bitsi.clear()
213 if self.state != 'IDLE':
214 self.put(self.lastbit, self.samplenum, self.out_ann, [0, ['%d' % bit]])
215 self.lastbit = self.samplenum
216
217 def handle_transition(self, l, htl):
218 self.deq.append(l)
219 if len(self.deq) >= 2 and \
220 (self.in_tolerance(self.deq[-1] + self.deq[-2]) or \
221 htl and self.in_tolerance(l * 2) and \
222 self.deq[-2] > 1.25 * self.bit_width):
223 self.add_bit(1)
224 self.deq.clear()
225 elif self.in_tolerance(l):
226 self.add_bit(0)
227 self.deq.clear()
228 elif l > (1.25 * self.bit_width):
229 self.state = 'IDLE'
230 self.bytesi.clear()
231 self.packet.clear()
232 self.bits.clear()
233 self.bitsi.clear()
234
d9135fe1 235 def decode(self):
d574715e
JG
236 if not self.samplerate:
237 raise SamplerateError('Cannot decode without samplerate.')
d9135fe1 238
1b9ef18b 239 (qi,) = self.wait()
d9135fe1
GS
240 self.handle_transition(self.samplenum, qi == 0)
241 while True:
242 prev = self.samplenum
243 (qi,) = self.wait({0: 'e'})
244 self.handle_transition(self.samplenum - prev, qi == 0)