1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
5  * Copyright (C) 2017 John Chajecki <subs@qcontinuum.plus.com>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #ifndef LIBSIGROK_HARDWARE_FLUKE_45_PROTOCOL_H
22 #define LIBSIGROK_HARDWARE_FLUKE_45_PROTOCOL_H
23 
24 #include <stdint.h>
25 #include <stdbool.h>
26 #include <scpi.h>
27 
28 #define LOG_PREFIX "fluke-45"
29 
30 #define FLUKEDMM_BUFSIZE 256
31 
32 /* Always USB-serial, 1ms is plenty. */
33 #define SERIAL_WRITE_TIMEOUT_MS 1
34 
35 enum data_format {
36 	/* Fluke 45 uses IEEE488v2. */
37 	FORMAT_IEEE488_2,
38 };
39 
40 enum dmm_scpi_cmds {
41 	SCPI_CMD_CLS,
42 	SCPI_CMD_RST,
43 	SCPI_CMD_REMS,
44 	SCPI_CMD_RWLS,
45 	SCPI_CMD_LOCS,
46 	SCPI_CMD_LWLS,
47 	SCPI_CMD_REMOTE,
48 	SCPI_CMD_LOCAL,
49 	SCPI_CMD_SET_ACVOLTAGE,
50 	SCPI_CMD_SET_ACDCVOLTAGE,
51 	SCPI_CMD_SET_DCVOLTAGE,
52 	SCPI_CMD_SET_ACCURRENT,
53 	SCPI_CMD_SET_ACDCCURRENT,
54 	SCPI_CMD_SET_DCCURRENT,
55 	SCPI_CMD_SET_FREQUENCY,
56 	SCPI_CMD_SET_RESISTANCE,
57 	SCPI_CMD_SET_CONTINUITY,
58 	SCPI_CMD_SET_DIODE,
59 	SCPI_CMD_SET_AUTO,
60 	SCPI_CMD_GET_AUTO,
61 	SCPI_CMD_SET_FIXED,
62 	SCPI_CMD_SET_RANGE,
63 	SCPI_CMD_GET_RANGE_D1,
64 	SCPI_CMD_GET_RANGE_D2,
65 	SCPI_CMD_SET_DB,
66 	SCPI_CMD_SET_DBCLR,
67 	SCPI_CMD_SET_DBPOWER,
68 	SCPI_CMD_SET_DBREF,
69 	SCPI_CMD_GET_DBREF,
70 	SCPI_CMD_SET_HOLD,
71 	SCPI_CMD_SET_HOLDCLR,
72 	SCPI_CMD_SET_MAX,
73 	SCPI_CMD_SET_MIN,
74 	SCPI_CMD_SET_MMCLR,
75 	SCPI_CMD_SET_REL,
76 	SCPI_CMD_SET_RELCLR,
77 	SCPI_CMD_GET_MEAS_DD,
78 	SCPI_CMD_GET_MEAS_D1,
79 	SCPI_CMD_GET_MEAS_D2,
80 	SCPI_CMD_GET_RATE,
81 	SCPI_CMD_SET_RATE,
82 	SCPI_CMD_SET_TRIGGER,
83 	SCPI_CMD_GET_TRIGGER,
84 };
85 
86 static const struct scpi_command fluke_45_cmdset[] = {
87 	{ SCPI_CMD_CLS, "*CLS" },
88 	{ SCPI_CMD_RST, "*RST" },
89 	{ SCPI_CMD_REMS, "*REMS" },
90 	{ SCPI_CMD_RWLS, "*RWLS" },
91 	{ SCPI_CMD_LOCS, "LOCS" },
92 	{ SCPI_CMD_LWLS, "LWLS" },
93 	{ SCPI_CMD_REMOTE, "REMS" },
94 	{ SCPI_CMD_LOCAL, "LOCS" },
95 	{ SCPI_CMD_SET_ACVOLTAGE, "VAC" },
96 	{ SCPI_CMD_SET_ACDCVOLTAGE, "VACDC" },
97 	{ SCPI_CMD_SET_DCVOLTAGE, "VDC" },
98 	{ SCPI_CMD_SET_ACCURRENT, "AAC" },
99 	{ SCPI_CMD_SET_ACDCCURRENT, "AACDC" },
100 	{ SCPI_CMD_SET_DCCURRENT, "ADC" },
101 	{ SCPI_CMD_SET_FREQUENCY, "FREQ" },
102 	{ SCPI_CMD_SET_RESISTANCE, "OHMS" },
103 	{ SCPI_CMD_SET_CONTINUITY, "CONT" },
104 	{ SCPI_CMD_SET_DIODE, "DIODE" },
105 	{ SCPI_CMD_SET_AUTO, "AUTO" },
106 	{ SCPI_CMD_GET_AUTO, "AUTO?" },
107 	{ SCPI_CMD_SET_FIXED, "FIXED" },
108 	{ SCPI_CMD_SET_RANGE, "RANGE" },
109 	{ SCPI_CMD_GET_RANGE_D1, "RANGE1?" },
110 	{ SCPI_CMD_GET_RANGE_D2, "RANGE2?" },
111 	{ SCPI_CMD_SET_DB, "DB" },
112 	{ SCPI_CMD_SET_DBCLR, "DBCLR" },
113 	{ SCPI_CMD_SET_DBPOWER, "DBPOWER" },
114 	{ SCPI_CMD_SET_DBREF, "DBREF" },
115 	{ SCPI_CMD_GET_DBREF, "DBREF?" },
116 	{ SCPI_CMD_SET_HOLD, "HOLD" },
117 	{ SCPI_CMD_SET_HOLDCLR, "HOLDCLR" },
118 	{ SCPI_CMD_SET_MAX, "MAX" },
119 	{ SCPI_CMD_SET_MIN, "MIN" },
120 	{ SCPI_CMD_SET_MMCLR, "MMCLR" },
121 	{ SCPI_CMD_SET_REL, "REL" },
122 	{ SCPI_CMD_SET_RELCLR, "RELCLR" },
123 	{ SCPI_CMD_GET_MEAS_DD, "MEAS?" },
124 	{ SCPI_CMD_GET_MEAS_D1, "MEAS1?" },
125 	{ SCPI_CMD_GET_MEAS_D2, "MEAS2?" },
126 	{ SCPI_CMD_SET_RATE, "RATE" },
127 	{ SCPI_CMD_GET_RATE, "RATE?" },
128 	{ SCPI_CMD_SET_TRIGGER, "TRIGGER" },
129 	{ SCPI_CMD_GET_TRIGGER, "TRIGGER?" },
130 	ALL_ZERO
131 };
132 
133 struct fluke_scpi_dmm_model {
134 	const char *vendor;
135 	const char *model;
136 	int num_channels;
137 	int poll_period; /* How often to poll, in ms. */
138 };
139 
140 struct channel_spec {
141 	const char *name;
142 	/* Min, max, programming resolution, spec digits, encoding digits. */
143 	double voltage[5];
144 	double current[5];
145 	double resistance[5];
146 	double capacitance[5];
147 	double conductance[5];
148 	double diode[5];
149 };
150 
151 struct channel_group_spec {
152 	const char *name;
153 	uint64_t channel_index_mask;
154 	uint64_t features;
155 };
156 
157 struct dmm_channel {
158 	enum sr_mq mq;
159 	unsigned int hw_output_idx;
160 	const char *hwname;
161 	int digits;
162 };
163 
164 struct dmm_channel_instance {
165 	enum sr_mq mq;
166 	int command;
167 	const char *prefix;
168 };
169 
170 struct dmm_channel_group {
171 	uint64_t features;
172 };
173 
174 struct dev_context {
175 	struct sr_sw_limits limits;
176 	unsigned int num_channels;
177 	const struct scpi_command *cmdset;
178 	char *response;
179 	const char *mode1;
180 	const char *mode2;
181 	long range1;
182 	long range2;
183 	long autorng;
184 	const char *rate;
185 	long modifiers;
186 	long trigmode;
187 };
188 
189 int get_reading_dd(char *reading, size_t size);
190 
191 SR_PRIV extern const struct fluke_scpi_dmm_model dmm_profiles[];
192 
193 SR_PRIV int fl45_scpi_receive_data(int fd, int revents, void *cb_data);
194 SR_PRIV int fl45_scpi_get_response(const struct sr_dev_inst *sdi,  char *cmd);
195 SR_PRIV int fl45_get_status(const struct sr_dev_inst *sdi,
196 		struct sr_datafeed_analog *analog, int idx);
197 SR_PRIV int fl45_get_modifiers(const struct sr_dev_inst *sdi,
198 		struct sr_datafeed_analog *analog, int idx);
199 
200 #endif
201