]> sigrok.org Git - libsigrok.git/blame - src/hardware/korad-kaxxxxp/api.c
drivers: Drop unneeded or duplicate comments.
[libsigrok.git] / src / hardware / korad-kaxxxxp / api.c
CommitLineData
e75ee7de
HV
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2015 Hannu Vuolasaho <vuokkosetae@gmail.com>
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#include <config.h>
21#include "protocol.h"
22
d7083042
HV
23static const uint32_t scanopts[] = {
24 SR_CONF_CONN,
25 SR_CONF_SERIALCOMM,
26};
27
55fb76b3 28static const uint32_t drvopts[] = {
55fb76b3
UH
29 SR_CONF_POWER_SUPPLY,
30};
31
d7083042 32static const uint32_t devopts[] = {
d7083042
HV
33 SR_CONF_CONTINUOUS,
34 SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
35 SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
d7083042
HV
36 SR_CONF_VOLTAGE | SR_CONF_GET,
37 SR_CONF_VOLTAGE_TARGET | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
38 SR_CONF_CURRENT | SR_CONF_GET,
39 SR_CONF_CURRENT_LIMIT | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
40 SR_CONF_ENABLED | SR_CONF_GET | SR_CONF_SET,
b16d975a 41 SR_CONF_REGULATION | SR_CONF_GET,
c40ed60f
HV
42 SR_CONF_OVER_CURRENT_PROTECTION_ENABLED | SR_CONF_GET | SR_CONF_SET,
43 SR_CONF_OVER_VOLTAGE_PROTECTION_ENABLED | SR_CONF_GET | SR_CONF_SET,
d7083042
HV
44};
45
16fc7ee2 46static const struct korad_kaxxxxp_model models[] = {
d7083042 47 /* Device enum, vendor, model, ID reply, channels, voltage, current */
ae9ca5b1
UH
48 {VELLEMAN_PS3005D, "Velleman", "PS3005D",
49 "VELLEMANPS3005DV2.0", 1, {0, 31, 0.01}, {0, 5, 0.001}},
50 {VELLEMAN_LABPS3005D, "Velleman", "LABPS3005D",
d7083042 51 "VELLEMANLABPS3005DV2.0", 1, {0, 31, 0.01}, {0, 5, 0.001}},
bcf9384d 52 {KORAD_KA3005P, "Korad", "KA3005P",
2c5bdf1b 53 "KORADKA3005PV2.0", 1, {0, 31, 0.01}, {0, 5, 0.001}},
a078d3ec
UH
54 /* Sometimes the KA3005P has an extra 0x01 after the ID. */
55 {KORAD_KA3005P_0X01, "Korad", "KA3005P",
56 "KORADKA3005PV2.0\x01", 1, {0, 31, 0.01}, {0, 5, 0.001}},
9e9dba7b 57 ALL_ZERO
d7083042
HV
58};
59
e75ee7de
HV
60static GSList *scan(struct sr_dev_driver *di, GSList *options)
61{
d7083042 62 struct dev_context *devc;
43376f33 63 GSList *l;
d7083042
HV
64 struct sr_dev_inst *sdi;
65 struct sr_config *src;
66 const char *conn, *serialcomm;
67 struct sr_serial_dev_inst *serial;
68 char reply[50];
69 int i, model_id;
70 unsigned int len;
e75ee7de 71
d7083042
HV
72 conn = NULL;
73 serialcomm = NULL;
e75ee7de 74
d7083042
HV
75 for (l = options; l; l = l->next) {
76 src = l->data;
77 switch (src->key) {
78 case SR_CONF_CONN:
79 conn = g_variant_get_string(src->data, NULL);
80 break;
81 case SR_CONF_SERIALCOMM:
82 serialcomm = g_variant_get_string(src->data, NULL);
83 break;
84 default:
85 sr_err("Unknown option %d, skipping.", src->key);
86 break;
87 }
88 }
89
90 if (!conn)
91 return NULL;
92 if (!serialcomm)
93 serialcomm = "9600/8n1";
94
95 serial = sr_serial_dev_inst_new(conn, serialcomm);
96 if (serial_open(serial, SERIAL_RDWR) != SR_OK)
97 return NULL;
98
99 serial_flush(serial);
100
101 /* Get the device model. */
102 len = 0;
103 for (i = 0; models[i].id; i++) {
104 if (strlen(models[i].id) > len)
105 len = strlen(models[i].id);
106 }
107 memset(&reply, 0, sizeof(reply));
108 sr_dbg("Want max %d bytes.", len);
16fc7ee2 109 if ((korad_kaxxxxp_send_cmd(serial, "*IDN?") < 0))
d7083042
HV
110 return NULL;
111
112 /* i is used here for debug purposes only. */
16fc7ee2 113 if ((i = korad_kaxxxxp_read_chars(serial, len, reply)) < 0)
d7083042
HV
114 return NULL;
115 sr_dbg("Received: %d, %s", i, reply);
116 model_id = -1;
117 for (i = 0; models[i].id; i++) {
118 if (!strcmp(models[i].id, reply))
119 model_id = i;
120 }
121 if (model_id < 0) {
122 sr_err("Unknown model ID '%s' detected, aborting.", reply);
123 return NULL;
124 }
a078d3ec
UH
125 sr_dbg("Found: %s %s (idx %d, ID '%s').", models[model_id].vendor,
126 models[model_id].name, model_id, models[model_id].id);
d7083042 127
d7083042
HV
128 sdi = g_malloc0(sizeof(struct sr_dev_inst));
129 sdi->status = SR_ST_INACTIVE;
130 sdi->vendor = g_strdup(models[model_id].vendor);
131 sdi->model = g_strdup(models[model_id].name);
132 sdi->inst_type = SR_INST_SERIAL;
133 sdi->conn = serial;
d7083042
HV
134
135 sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "CH1");
136
137 devc = g_malloc0(sizeof(struct dev_context));
597deef9 138 sr_sw_limits_init(&devc->limits);
d7083042
HV
139 devc->model = &models[model_id];
140 devc->reply[5] = 0;
141 devc->req_sent_at = 0;
142 sdi->priv = devc;
143
144 /* Get current status of device. */
16fc7ee2 145 if (korad_kaxxxxp_get_all_values(serial, devc) < 0)
d7083042 146 goto exit_err;
d7083042
HV
147
148 serial_close(serial);
e75ee7de 149
43376f33 150 return std_scan_complete(di, g_slist_append(NULL, sdi));
d7083042
HV
151
152exit_err:
153 sr_dev_inst_free(sdi);
154 g_free(devc);
155 sr_dbg("Scan failed.");
156
157 return NULL;
e75ee7de
HV
158}
159
e75ee7de
HV
160static int config_get(uint32_t key, GVariant **data,
161 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
162{
d7083042 163 struct dev_context *devc;
e75ee7de 164
e75ee7de
HV
165 (void)cg;
166
d7083042
HV
167 if (!sdi || !data)
168 return SR_ERR_ARG;
169
170 devc = sdi->priv;
171
e75ee7de 172 switch (key) {
cd04f641
UH
173 case SR_CONF_LIMIT_SAMPLES:
174 case SR_CONF_LIMIT_MSEC:
597deef9 175 return sr_sw_limits_config_get(&devc->limits, key, data);
d7083042
HV
176 case SR_CONF_VOLTAGE:
177 *data = g_variant_new_double(devc->voltage);
178 break;
179 case SR_CONF_VOLTAGE_TARGET:
180 *data = g_variant_new_double(devc->voltage_max);
181 break;
182 case SR_CONF_CURRENT:
183 *data = g_variant_new_double(devc->current);
184 break;
185 case SR_CONF_CURRENT_LIMIT:
186 *data = g_variant_new_double(devc->current_max);
187 break;
188 case SR_CONF_ENABLED:
189 *data = g_variant_new_boolean(devc->output_enabled);
190 break;
b16d975a
HV
191 case SR_CONF_REGULATION:
192 /* Dual channel not supported. */
9e5366df 193 *data = g_variant_new_string((devc->cc_mode[0]) ? "CC" : "CV");
b16d975a 194 break;
c40ed60f 195 case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED:
9e5366df 196 *data = g_variant_new_boolean(devc->ocp_enabled);
c40ed60f
HV
197 break;
198 case SR_CONF_OVER_VOLTAGE_PROTECTION_ENABLED:
9e5366df 199 *data = g_variant_new_boolean(devc->ovp_enabled);
c40ed60f 200 break;
e75ee7de
HV
201 default:
202 return SR_ERR_NA;
203 }
204
d7083042 205 return SR_OK;
e75ee7de
HV
206}
207
208static int config_set(uint32_t key, GVariant *data,
209 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
210{
d7083042
HV
211 struct dev_context *devc;
212 double dval;
213 gboolean bval;
e75ee7de 214
e75ee7de
HV
215 (void)cg;
216
d7083042
HV
217 devc = sdi->priv;
218
e75ee7de 219 switch (key) {
d7083042 220 case SR_CONF_LIMIT_MSEC:
d7083042 221 case SR_CONF_LIMIT_SAMPLES:
597deef9 222 return sr_sw_limits_config_set(&devc->limits, key, data);
d7083042
HV
223 case SR_CONF_VOLTAGE_TARGET:
224 dval = g_variant_get_double(data);
225 if (dval < devc->model->voltage[0] || dval > devc->model->voltage[1])
226 return SR_ERR_ARG;
227 devc->voltage_max = dval;
16fc7ee2
UH
228 devc->target = KAXXXXP_VOLTAGE_MAX;
229 if (korad_kaxxxxp_set_value(sdi->conn, devc) < 0)
d7083042
HV
230 return SR_ERR;
231 break;
232 case SR_CONF_CURRENT_LIMIT:
233 dval = g_variant_get_double(data);
234 if (dval < devc->model->current[0] || dval > devc->model->current[1])
235 return SR_ERR_ARG;
236 devc->current_max = dval;
16fc7ee2
UH
237 devc->target = KAXXXXP_CURRENT_MAX;
238 if (korad_kaxxxxp_set_value(sdi->conn, devc) < 0)
d7083042
HV
239 return SR_ERR;
240 break;
241 case SR_CONF_ENABLED:
242 bval = g_variant_get_boolean(data);
243 /* Set always so it is possible turn off with sigrok-cli. */
244 devc->output_enabled = bval;
16fc7ee2
UH
245 devc->target = KAXXXXP_OUTPUT;
246 if (korad_kaxxxxp_set_value(sdi->conn, devc) < 0)
d7083042 247 return SR_ERR;
c40ed60f
HV
248 break;
249 case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED:
250 bval = g_variant_get_boolean(data);
9e5366df 251 devc->ocp_enabled = bval;
16fc7ee2
UH
252 devc->target = KAXXXXP_OCP;
253 if (korad_kaxxxxp_set_value(sdi->conn, devc) < 0)
c40ed60f
HV
254 return SR_ERR;
255 break;
256 case SR_CONF_OVER_VOLTAGE_PROTECTION_ENABLED:
257 bval = g_variant_get_boolean(data);
9e5366df 258 devc->ovp_enabled = bval;
16fc7ee2
UH
259 devc->target = KAXXXXP_OVP;
260 if (korad_kaxxxxp_set_value(sdi->conn, devc) < 0)
c40ed60f 261 return SR_ERR;
d7083042 262 break;
e75ee7de 263 default:
d7083042 264 return SR_ERR_NA;
e75ee7de
HV
265 }
266
d7083042 267 return SR_OK;
e75ee7de
HV
268}
269
270static int config_list(uint32_t key, GVariant **data,
271 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
272{
d7083042
HV
273 struct dev_context *devc;
274 GVariant *gvar;
275 GVariantBuilder gvb;
276 double dval;
277 int idx;
278
e66d1892 279 devc = (sdi) ? sdi->priv : NULL;
d7083042 280
e75ee7de 281 switch (key) {
e66d1892 282 case SR_CONF_SCAN_OPTIONS:
d7083042 283 case SR_CONF_DEVICE_OPTIONS:
e66d1892 284 return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
d7083042
HV
285 case SR_CONF_VOLTAGE_TARGET:
286 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
287 /* Min, max, step. */
288 for (idx = 0; idx < 3; idx++) {
289 dval = devc->model->voltage[idx];
290 gvar = g_variant_new_double(dval);
291 g_variant_builder_add_value(&gvb, gvar);
292 }
293 *data = g_variant_builder_end(&gvb);
294 break;
295 case SR_CONF_CURRENT_LIMIT:
296 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
297 /* Min, max, step. */
298 for (idx = 0; idx < 3; idx++) {
299 dval = devc->model->current[idx];
300 gvar = g_variant_new_double(dval);
301 g_variant_builder_add_value(&gvb, gvar);
302 }
303 *data = g_variant_builder_end(&gvb);
304 break;
e75ee7de
HV
305 default:
306 return SR_ERR_NA;
307 }
308
d7083042 309 return SR_OK;
e75ee7de
HV
310}
311
695dc859 312static int dev_acquisition_start(const struct sr_dev_inst *sdi)
e75ee7de 313{
d7083042
HV
314 struct dev_context *devc;
315 struct sr_serial_dev_inst *serial;
e75ee7de 316
d7083042 317 devc = sdi->priv;
d7083042 318
597deef9 319 sr_sw_limits_acquisition_start(&devc->limits);
bee2b016 320 std_session_send_df_header(sdi);
d7083042 321
d7083042
HV
322 devc->reply_pending = FALSE;
323 devc->req_sent_at = 0;
324 serial = sdi->conn;
325 serial_source_add(sdi->session, serial, G_IO_IN,
16fc7ee2
UH
326 KAXXXXP_POLL_INTERVAL_MS,
327 korad_kaxxxxp_receive_data, (void *)sdi);
e75ee7de
HV
328
329 return SR_OK;
330}
331
dd5c48a6 332static struct sr_dev_driver korad_kaxxxxp_driver_info = {
16fc7ee2
UH
333 .name = "korad-kaxxxxp",
334 .longname = "Korad KAxxxxP",
e75ee7de 335 .api_version = 1,
c2fdcc25 336 .init = std_init,
700d6b64 337 .cleanup = std_cleanup,
e75ee7de 338 .scan = scan,
c01bf34c 339 .dev_list = std_dev_list,
f778bf02 340 .dev_clear = std_dev_clear,
e75ee7de
HV
341 .config_get = config_get,
342 .config_set = config_set,
343 .config_list = config_list,
d7083042
HV
344 .dev_open = std_serial_dev_open,
345 .dev_close = std_serial_dev_close,
e75ee7de 346 .dev_acquisition_start = dev_acquisition_start,
4b1a9d5d 347 .dev_acquisition_stop = std_serial_dev_acquisition_stop,
e75ee7de
HV
348 .context = NULL,
349};
dd5c48a6 350SR_REGISTER_DEV_DRIVER(korad_kaxxxxp_driver_info);