diff --git a/src/hardware/korad-kaxxxxp/api.c b/src/hardware/korad-kaxxxxp/api.c index 82e437974..c6b9b1f67 100644 --- a/src/hardware/korad-kaxxxxp/api.c +++ b/src/hardware/korad-kaxxxxp/api.c @@ -57,6 +57,8 @@ static const double amps_5[] = { 0, 5.1, 0.001, }; static const struct korad_kaxxxxp_model models[] = { /* Vendor, model name, ID reply, channels, voltage, current, quirks. */ + {"Korad", "KA3005PS", "", 1, volts_30, amps_5, + KORAD_QUIRK_NEWLINE}, {"Korad", "KA3005P", "", 1, volts_30, amps_5, KORAD_QUIRK_ID_TRAILING}, {"Korad", "KD3005P", "", 1, volts_30, amps_5, 0}, @@ -278,11 +280,14 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) len = sizeof(reply) - 1; sr_dbg("Want max %zu bytes.", len); - ret = korad_kaxxxxp_send_cmd(serial, "*IDN?"); + // TODO: check if adding the newline breaks some other devices - I cannot do so + // This is required for the KA3005PS + ret = korad_kaxxxxp_send_cmd(serial, "*IDN?", true); if (ret < 0) return NULL; - ret = korad_kaxxxxp_read_chars(serial, len, reply); + // Newline stripping enabled by default - doesn't matter for devices that don't add one + ret = korad_kaxxxxp_read_chars(serial, len, reply, true); if (ret < 0) return NULL; sr_dbg("Received: %d, %s", ret, reply); diff --git a/src/hardware/korad-kaxxxxp/protocol.c b/src/hardware/korad-kaxxxxp/protocol.c index bac8c8ef7..0ce7206e7 100644 --- a/src/hardware/korad-kaxxxxp/protocol.c +++ b/src/hardware/korad-kaxxxxp/protocol.c @@ -25,12 +25,26 @@ #define EXTRA_PROCESSING_TIME_MS 450 SR_PRIV int korad_kaxxxxp_send_cmd(struct sr_serial_dev_inst *serial, - const char *cmd) + const char *cmd, bool add_newline) { int ret; + char* addition = ""; + if (add_newline) + addition = "\n"; + + // 21 was chosen here because 20 is chosen in korad_kaxxxxp_set_value + char newcmd[21]; + ret = sr_snprintf_ascii(newcmd, 21, "%s%s", cmd, addition); + if (ret < 0 || ret >= 21) { + sr_err("Error creating command: %d.", ret); + if (ret > 0) + ret = -ret; // make errors always return negative numbers + return ret; + } + sr_dbg("Sending '%s'.", cmd); - if ((ret = serial_write_blocking(serial, cmd, strlen(cmd), 0)) < 0) { + if ((ret = serial_write_blocking(serial, newcmd, strlen(newcmd), 0)) < 0) { sr_err("Error sending command: %d.", ret); return ret; } @@ -71,7 +85,7 @@ SR_PRIV int korad_kaxxxxp_send_cmd(struct sr_serial_dev_inst *serial, * larger initial timeout period before receive data is seen. */ SR_PRIV int korad_kaxxxxp_read_chars(struct sr_serial_dev_inst *serial, - size_t count, char *buf) + size_t count, char *buf, bool strip_newline) { int timeout_first, timeout_later, timeout; size_t retries_first, retries_later, retries; @@ -146,6 +160,10 @@ SR_PRIV int korad_kaxxxxp_read_chars(struct sr_serial_dev_inst *serial, timeout = timeout_later; retries = retries_later; } + + if (strip_newline && buf[received-1] == 0x0a) + buf[--received] = 0x00; + /* TODO Escape non-printables? Seen those with status queries. */ sr_dbg("got %zu bytes, received: '%s'.", received, buf); @@ -259,7 +277,7 @@ SR_PRIV int korad_kaxxxxp_set_value(struct sr_serial_dev_inst *serial, } if (ret == SR_OK && msg[0]) { - ret = korad_kaxxxxp_send_cmd(serial, msg); + ret = korad_kaxxxxp_send_cmd(serial, msg, devc->model->quirks & KORAD_QUIRK_NEWLINE); devc->next_req_time = next_req_time(devc, TRUE, target); } @@ -272,7 +290,7 @@ SR_PRIV int korad_kaxxxxp_get_value(struct sr_serial_dev_inst *serial, int target, struct dev_context *devc) { int ret, count; - char reply[6]; + char reply[7]; float *value; char status_byte; gboolean needs_ovp_quirk; @@ -282,27 +300,29 @@ SR_PRIV int korad_kaxxxxp_get_value(struct sr_serial_dev_inst *serial, give_device_time_to_process(devc); value = NULL; - count = 5; + count = 6; + + bool newline_quirk = devc->model->quirks & KORAD_QUIRK_NEWLINE; switch (target) { case KAXXXXP_CURRENT: /* Read current from device. */ - ret = korad_kaxxxxp_send_cmd(serial, "IOUT1?"); + ret = korad_kaxxxxp_send_cmd(serial, "IOUT1?", newline_quirk); value = &(devc->current); break; case KAXXXXP_CURRENT_LIMIT: /* Read set current from device. */ - ret = korad_kaxxxxp_send_cmd(serial, "ISET1?"); + ret = korad_kaxxxxp_send_cmd(serial, "ISET1?", newline_quirk); value = &(devc->current_limit); break; case KAXXXXP_VOLTAGE: /* Read voltage from device. */ - ret = korad_kaxxxxp_send_cmd(serial, "VOUT1?"); + ret = korad_kaxxxxp_send_cmd(serial, "VOUT1?", newline_quirk); value = &(devc->voltage); break; case KAXXXXP_VOLTAGE_TARGET: /* Read set voltage from device. */ - ret = korad_kaxxxxp_send_cmd(serial, "VSET1?"); + ret = korad_kaxxxxp_send_cmd(serial, "VSET1?", newline_quirk); value = &(devc->voltage_target); break; case KAXXXXP_STATUS: @@ -310,8 +330,10 @@ SR_PRIV int korad_kaxxxxp_get_value(struct sr_serial_dev_inst *serial, case KAXXXXP_OCP: case KAXXXXP_OVP: /* Read status from device. */ - ret = korad_kaxxxxp_send_cmd(serial, "STATUS?"); + ret = korad_kaxxxxp_send_cmd(serial, "STATUS?", newline_quirk); count = 1; + if (newline_quirk) + count = 2; break; default: sr_err("Don't know how to query %d.", target); @@ -324,7 +346,7 @@ SR_PRIV int korad_kaxxxxp_get_value(struct sr_serial_dev_inst *serial, devc->next_req_time = next_req_time(devc, FALSE, target); - if ((ret = korad_kaxxxxp_read_chars(serial, count, reply)) < 0) { + if ((ret = korad_kaxxxxp_read_chars(serial, count, reply, newline_quirk)) < 0) { g_mutex_unlock(&devc->rw_mutex); return ret; } diff --git a/src/hardware/korad-kaxxxxp/protocol.h b/src/hardware/korad-kaxxxxp/protocol.h index 005d94ab1..43653d148 100644 --- a/src/hardware/korad-kaxxxxp/protocol.h +++ b/src/hardware/korad-kaxxxxp/protocol.h @@ -21,6 +21,7 @@ #ifndef LIBSIGROK_HARDWARE_KORAD_KAXXXXP_PROTOCOL_H #define LIBSIGROK_HARDWARE_KORAD_KAXXXXP_PROTOCOL_H +#include #include #include #include @@ -38,7 +39,8 @@ enum korad_quirks_flag { KORAD_QUIRK_ID_TRAILING = 1UL << 2, KORAD_QUIRK_ID_OPT_VERSION = 1UL << 3, KORAD_QUIRK_SLOW_PROCESSING = 1UL << 4, - KORAD_QUIRK_ALL = (1UL << 5) - 1, + KORAD_QUIRK_NEWLINE = 1UL << 5, + KORAD_QUIRK_ALL = (1UL << 6) - 1, }; /* Information on single model */ @@ -103,9 +105,9 @@ struct dev_context { }; SR_PRIV int korad_kaxxxxp_send_cmd(struct sr_serial_dev_inst *serial, - const char *cmd); + const char *cmd, bool add_newline); SR_PRIV int korad_kaxxxxp_read_chars(struct sr_serial_dev_inst *serial, - size_t count, char *buf); + size_t count, char *buf, bool strip_newline); SR_PRIV int korad_kaxxxxp_set_value(struct sr_serial_dev_inst *serial, int target, struct dev_context *devc); SR_PRIV int korad_kaxxxxp_get_value(struct sr_serial_dev_inst *serial,