]>
Commit | Line | Data |
---|---|---|
4d9f1640 TP |
1 | ## |
2 | ## This file is part of the libsigrokdecode project. | |
3 | ## | |
4 | ## Copyright (C) 2020 Analog Devices Inc. | |
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 3 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 | |
17 | ## along with this program; if not, see <http://www.gnu.org/licenses/>. | |
18 | ## | |
19 | ||
20 | import sigrokdecode as srd | |
21 | ||
22 | slave_address = { | |
23 | 0x00: ['GND', 'GND', 'GND', 'G'], | |
24 | 0x01: ['FLOAT', 'FLOAT', 'FLOAT', 'F'], | |
25 | 0x02: ['VCC', 'VCC', 'VCC', 'V'], | |
26 | } | |
27 | ||
28 | commands = { | |
29 | 0x00: ['Write Input Register', 'Write In Reg', 'Wr In Reg', 'WIR'], | |
30 | 0x01: ['Update DAC', 'Update', 'U'], | |
31 | 0x03: ['Write and Power Up DAC', 'Write & Power Up', 'W&PU'], | |
32 | 0x04: ['Power Down DAC', 'Power Down', 'PD'], | |
33 | 0x0F: ['No Operation', 'No Op', 'NO'], | |
34 | } | |
35 | ||
36 | addresses = { | |
37 | 0x00: ['DAC A', 'A'], | |
38 | 0x01: ['DAC B', 'B'], | |
39 | 0x0F: ['All DACs', 'All'], | |
40 | } | |
41 | ||
42 | input_voltage_format = ['%fV', '%fV', '%.6fV', '%.2fV'] | |
43 | ||
44 | class Decoder(srd.Decoder): | |
45 | api_version = 3 | |
46 | id = 'ltc26x7' | |
47 | name = 'LTC26x7' | |
48 | longname = 'Linear Technology LTC26x7' | |
49 | desc = 'Linear Technology LTC26x7 16-/14-/12-bit rail-to-rail DACs.' | |
50 | license = 'gplv2+' | |
51 | inputs = ['i2c'] | |
52 | outputs = [] | |
39770181 | 53 | tags = ['IC', 'Analog/digital'] |
4d9f1640 | 54 | options = ( |
c7c4c06c | 55 | {'id': 'chip', 'desc': 'Chip', 'default': 'ltc26x7', |
4d9f1640 | 56 | 'values': ('ltc2607', 'ltc2617', 'ltc2627')}, |
c7c4c06c | 57 | {'id': 'vref', 'desc': 'Reference voltage (V)', 'default': 1.5}, |
4d9f1640 TP |
58 | ) |
59 | annotations = ( | |
60 | ('slave_addr', 'Slave address'), | |
61 | ('command', 'Command'), | |
62 | ('address', 'Address'), | |
63 | ('data', '2 byte data'), | |
64 | ) | |
4d9f1640 TP |
65 | |
66 | def __init__(self): | |
67 | self.reset() | |
68 | ||
69 | def reset(self): | |
70 | self.state = 'IDLE' | |
71 | self.ss = -1 | |
72 | self.data = 0x00 | |
73 | ||
74 | def start(self): | |
75 | self.out_ann = self.register(srd.OUTPUT_ANN) | |
76 | ||
77 | def convert_ternary_str(self, n): | |
78 | if n == 0: | |
79 | return [0, 0, 0] | |
80 | nums = [] | |
81 | while n: | |
82 | n, r = divmod(n, 3) | |
83 | nums.append(r) | |
84 | while len(nums) < 3: | |
85 | nums.append(0) | |
86 | return list(reversed(nums)) | |
87 | ||
88 | def handle_slave_addr(self, data): | |
89 | if data == 0x73: | |
90 | ann = ['Global address', 'Global addr', 'Glob addr', 'GA'] | |
91 | self.put(self.ss, self.es, self.out_ann, [0, ann]) | |
92 | return | |
93 | ann = ['CA2=%s CA1=%s CA0=%s', '2=%s 1=%s 0=%s', '%s %s %s', '%s %s %s'] | |
94 | addr = 0 | |
95 | for i in range(7): | |
96 | if i in [2, 3]: | |
97 | continue | |
98 | offset = i | |
99 | if i > 3: | |
100 | offset -= 2 | |
101 | mask = 1 << i | |
102 | if data & mask: | |
103 | mask = 1 << offset | |
104 | addr |= mask | |
105 | ||
106 | addr -= 0x04 | |
107 | ternary_values = self.convert_ternary_str(addr) | |
108 | for i in range(len(ann)): | |
109 | ann[i] = ann[i] % (slave_address[ternary_values[0]][i], | |
110 | slave_address[ternary_values[1]][i], | |
111 | slave_address[ternary_values[2]][i]) | |
112 | self.put(self.ss, self.es, self.out_ann, [0, ann]) | |
113 | ||
114 | def handle_cmd_addr(self, data): | |
115 | cmd_val = (data >> 4) & 0x0F | |
116 | dac_val = (data & 0x0F) | |
117 | sm = (self.ss + self.es) // 2 | |
118 | ||
119 | self.put(self.ss, sm, self.out_ann, [1, commands[cmd_val]]) | |
120 | self.put(sm, self.es, self.out_ann, [2, addresses[dac_val]]) | |
121 | ||
122 | def handle_data(self, data): | |
123 | self.data = (self.data << 8) & 0xFF00 | |
124 | self.data += data | |
c7c4c06c | 125 | if self.options['chip'] == 'ltc2617': |
4d9f1640 | 126 | self.data = (self.data >> 2) |
c7c4c06c UH |
127 | self.data = (self.options['vref'] * self.data) / 0x3FFF |
128 | elif self.options['chip'] == 'ltc2627': | |
4d9f1640 | 129 | self.data = (self.data >> 4) |
c7c4c06c | 130 | self.data = (self.options['vref'] * self.data) / 0x0FFF |
4d9f1640 | 131 | else: |
c7c4c06c | 132 | self.data = (self.options['vref'] * self.data) / 0xFFFF |
4d9f1640 TP |
133 | ann = [] |
134 | for format in input_voltage_format: | |
135 | ann.append(format % self.data) | |
136 | self.data = 0 | |
137 | ||
138 | self.put(self.ss, self.es, self.out_ann, [3, ann]) | |
139 | ||
140 | def decode(self, ss, es, data): | |
141 | cmd, databyte = data | |
142 | self.es = es | |
143 | ||
144 | # State machine. | |
145 | if self.state == 'IDLE': | |
146 | # Wait for an I²C START condition. | |
147 | if cmd != 'START': | |
148 | return | |
149 | self.state = 'GET SLAVE ADDR' | |
150 | elif self.state == 'GET SLAVE ADDR': | |
151 | # Wait for an address write operation. | |
152 | if cmd != 'ADDRESS WRITE': | |
153 | return | |
154 | self.ss = ss | |
155 | self.handle_slave_addr(databyte) | |
156 | self.ss = -1 | |
157 | self.state = 'GET CMD ADDR' | |
158 | elif self.state == 'GET CMD ADDR': | |
159 | if cmd != 'DATA WRITE': | |
160 | return | |
161 | self.ss = ss | |
162 | self.handle_cmd_addr(databyte) | |
163 | self.ss = -1 | |
164 | self.state = 'WRITE DATA' | |
165 | elif self.state == 'WRITE DATA': | |
166 | if cmd == 'DATA WRITE': | |
167 | if self.ss == -1: | |
168 | self.ss = ss | |
169 | self.data = databyte | |
170 | return | |
171 | self.handle_data(databyte) | |
172 | self.ss = -1 | |
173 | elif cmd == 'STOP': | |
174 | self.state = 'IDLE' | |
175 | else: | |
176 | return |