X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fgmc-mh-1x-2x%2Fprotocol.c;h=6ee986f1d7bcb870a367c5de9655ab5c7c69aa2e;hb=9ae544b6ce98097f9610a0adab8aa14da0d259c9;hp=dc1a683ed37d5453cab9c95cf668dc917dd14dad;hpb=155b680da482cea2381becb73c51cfb838bff31e;p=libsigrok.git diff --git a/src/hardware/gmc-mh-1x-2x/protocol.c b/src/hardware/gmc-mh-1x-2x/protocol.c index dc1a683e..6ee986f1 100644 --- a/src/hardware/gmc-mh-1x-2x/protocol.c +++ b/src/hardware/gmc-mh-1x-2x/protocol.c @@ -22,12 +22,13 @@ * @internal */ +#include #include #include #include "protocol.h" /* Internal Headers */ -static guchar calc_chksum_14(guchar* dta); +static guchar calc_chksum_14(guchar *dta); static int chk_msg14(struct sr_dev_inst *sdi); /** Set or clear flags in devc->mqflags. */ @@ -257,7 +258,7 @@ static void decode_ctmv_18(uint8_t ctmv, struct dev_context *devc) /** * Decode range/sign/acdc byte special chars, Metrahit 18. * - * @param[in] rs Rance/sign byte. + * @param[in] rs Range/sign byte. */ static void decode_rs_18(uint8_t rs, struct dev_context *devc) { @@ -282,8 +283,6 @@ static void decode_rs_18(uint8_t rs, struct dev_context *devc) * identify relative mode. */ } - else if (devc->vmains_29S) - devc->scale *= pow(10.0, range - 2); else devc->scale *= pow(10.0, range - 5); break; @@ -306,6 +305,9 @@ static void decode_rs_18(uint8_t rs, struct dev_context *devc) devc->scale *= pow(10.0, range - 13); break; /* TODO: 29S Mains measurements. */ + default: + /* Avoid certain compiler warnings due to (-Wswitch). */ + break; } } @@ -346,8 +348,8 @@ static void decode_spc_18(uint8_t spc, struct dev_context *devc) */ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc) { - if ((ctmv > 0x1c) || (!devc)) { - sr_err("decode_ctmv_2x(%d): invalid param(s)!", ctmv); + if ((ctmv > 0x20) || (!devc)) { + sr_err("decode_ctmv_2x(0x%x): invalid param(s)!", ctmv); return; } @@ -373,6 +375,7 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc) case 0x04: /* 00100 mA DC */ case 0x05: /* 00101 mA AC+DC */ devc->scale1000 = -1; + /* Fall through! */ case 0x06: /* 00110 A DC */ case 0x07: /* 00111 A AC+DC */ devc->mq = SR_MQ_CURRENT; @@ -409,11 +412,14 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc) devc->mqflags |= SR_MQFLAG_DC; break; case 0x0d: /* 01101 W on power, mA range (29S only) */ - devc->scale *= 0.001; + devc->scale *= 0.1; /* Fall through! */ case 0x0e: /* 01110 W on power, A range (29S only) */ + devc->scale *= 0.1; + devc->scale1000 = -1; devc->mq = SR_MQ_POWER; devc->unit = SR_UNIT_WATT; + devc->mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS); break; case 0x0f: /* 01111 Diode */ case 0x10: /* 10000 Diode with buzzer (actually cont. with voltage) */ @@ -437,7 +443,8 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc) devc->unit = SR_UNIT_CELSIUS; /* This can be Fahrenheit. That is detected by range=4 later. */ break; - /* 0x13 10011, 0x14 10100 unsed */ + /* 0x13 10011 unused */ + /* 0x14 10100 unused */ case 0x15: /* 10101 Press (29S only) */ /* TODO: What does that mean? Possibly phase shift? Then we need a unit/flag for it. */ @@ -452,8 +459,7 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc) case 0x17: /* 10111 TRMS V on mains (29S only) */ devc->mq = SR_MQ_VOLTAGE; devc->unit = SR_UNIT_VOLT; - devc->mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_RMS); - devc->vmains_29S = TRUE; + devc->mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS); break; case 0x18: /* 11000 Counter (zero crossings of a signal) */ devc->mq = SR_MQ_VOLTAGE; @@ -468,11 +474,11 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc) if (ctmv <= 0x19) devc->mqflags |= SR_MQFLAG_DC; break; - case 0x1b: /* 11011 pulse on mains (29S only) */ - /* TODO: No unit or flags for this yet! */ - devc->mq = SR_MQ_VOLTAGE; - devc->unit = SR_UNIT_UNITLESS; - devc->mqflags |= SR_MQFLAG_AC; + case 0x1b: /* 11011 Milliamperes in power mode (29S only); error in docs, "pulse on mains" */ + devc->mq = SR_MQ_CURRENT; + devc->unit = SR_UNIT_AMPERE; + devc->mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS); + devc->scale1000 = -1; break; case 0x1c: /* 11100 dropout on mains (29S only) */ /* TODO: No unit or flags for this yet! */ @@ -480,14 +486,20 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc) devc->unit = SR_UNIT_UNITLESS; devc->mqflags |= SR_MQFLAG_AC; break; - case 0x1f: /* 11111 Undocumented: 25S in stopwatch mode. + case 0x1d: /* 11101 Voltage in power mode (29S); undocumented! */ + devc->mq = SR_MQ_VOLTAGE; + devc->unit = SR_UNIT_VOLT; + devc->mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS); + break; + /* 0x1e: 11110 Undocumented */ + case 0x1f: /* 11111 25S in stopwatch mode; undocumented! The value is voltage, not time, so treat it such. */ devc->mq = SR_MQ_VOLTAGE; devc->unit = SR_UNIT_VOLT; devc->mqflags |= SR_MQFLAG_DC; break; - case 0x20: /* 100000 Undocumented: 25S in event count mode. - Value is 0 anyway. */ + case 0x20: /* 100000 25S in event count mode; undocumented! + Value is 0 anyway. */ devc->mq = SR_MQ_VOLTAGE; devc->unit = SR_UNIT_UNITLESS; break; @@ -517,8 +529,6 @@ static void decode_rs_2x(uint8_t rs, struct dev_context *devc) case SR_MQ_VOLTAGE: if (devc->unit == SR_UNIT_DECIBEL_VOLT) devc->scale *= pow(10.0, -3); - else if (devc->vmains_29S) - devc->scale *= pow(10.0, range - 2); else devc->scale *= pow(10.0, range - 6); break; @@ -544,6 +554,9 @@ static void decode_rs_2x(uint8_t rs, struct dev_context *devc) devc->scale *= pow(10.0, range - 13); break; /* TODO: 29S Mains measurements. */ + default: + /* Avoid certain compiler warnings due to (-Wswitch). */ + break; } } @@ -561,23 +574,28 @@ static void decode_rs_2x_TR2(uint8_t rs, struct dev_context *devc) switch (devc->mq) { case SR_MQ_CURRENT: if (devc->scale1000 == -1) /* mA */ - switch(range) { - case 0: case 1: /* 100, 300 µA */ + switch (range) { + case 0: + case 1: /* 100, 300 µA */ devc->scale *= pow(10.0, -6); break; - case 2: case 3: /* 1, 3 mA */ + case 2: + case 3: /* 1, 3 mA */ devc->scale *= pow(10.0, -5); break; - case 4: case 5: /* 10, 30 mA */ + case 4: + case 5: /* 10, 30 mA */ devc->scale *= pow(10.0, -4); break; - case 6: case 7: /* 100, 300 mA */ + case 6: + case 7: /* 100, 300 mA */ devc->scale *= pow(10.0, -3); break; } else /* A */ - switch(range) { - case 0: case 1: /* 1, 3 A */ + switch (range) { + case 0: + case 1: /* 1, 3 A */ devc->scale *= pow(10.0, -5); break; case 2: /* 10 A */ @@ -596,7 +614,6 @@ static void decode_rs_2x_TR2(uint8_t rs, struct dev_context *devc) devc->scale *= -1.0; } - /** * Decode special chars (Metrahit 2x). * @@ -634,7 +651,6 @@ static void clean_ctmv_rs_v(struct dev_context *devc) devc->unit = 0; devc->mqflags = 0; devc->scale1000 = 0; - devc->vmains_29S = FALSE; clean_rs_v(devc); } @@ -643,24 +659,27 @@ static void send_value(struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_datafeed_analog analog; + struct sr_analog_encoding encoding; + struct sr_analog_meaning meaning; + struct sr_analog_spec spec; struct sr_datafeed_packet packet; devc = sdi->priv; - memset(&analog, 0, sizeof(analog)); - analog.channels = sdi->channels; + sr_analog_init(&analog, &encoding, &meaning, &spec, 0); + analog.meaning->channels = sdi->channels; analog.num_samples = 1; - analog.mq = devc->mq; - analog.unit = devc->unit; - analog.mqflags = devc->mqflags; + analog.meaning->mq = devc->mq; + analog.meaning->unit = devc->unit; + analog.meaning->mqflags = devc->mqflags; analog.data = &devc->value; - memset(&packet, 0, sizeof(packet)); + memset(&packet, 0, sizeof(struct sr_datafeed_packet)); packet.type = SR_DF_ANALOG; packet.payload = &analog; - sr_session_send(devc->cb_data, &packet); + sr_session_send(sdi, &packet); - devc->num_samples++; + sr_sw_limits_update_samples_read(&devc->limits, 1); } /** Process 6-byte data message, Metrahit 1x/2x send mode. */ @@ -847,8 +866,8 @@ static void process_msg_inf_13(struct sr_dev_inst *sdi) devc->value += pow(10.0, cnt) * dgt; } sr_spew("process_msg_inf_13() value=%f scale=%f scale1000=%d mq=%d " - "unit=%d mqflags=0x%02llx", devc->value, devc->scale, - devc->scale1000, devc->mq, devc->unit, devc->mqflags); + "unit=%d mqflags=0x%02" PRIx64, devc->value, devc->scale, + devc->scale1000, devc->mq, devc->unit, (uint64_t)devc->mqflags); if (devc->value != NAN) devc->value *= devc->scale * pow(1000.0, devc->scale1000); @@ -863,7 +882,7 @@ static void process_msg_inf_13(struct sr_dev_inst *sdi) * @param buf Pointer to array of 14 data bytes. * @param[in] raw Write only data bytes, no interpretation. */ -void dump_msg14(guchar* buf, gboolean raw) +static void dump_msg14(guchar *buf, gboolean raw) { if (!buf) return; @@ -887,11 +906,11 @@ void dump_msg14(guchar* buf, gboolean raw) * @param[in] dta Pointer to array of 13 data bytes. * @return Checksum. */ -static guchar calc_chksum_14(guchar* dta) +static guchar calc_chksum_14(guchar *dta) { guchar cnt, chs; - for (chs = 0, cnt = 0; cnt < 13; cnt++) + for (chs = 0, cnt = 0; cnt < (GMC_REPLY_SIZE - 1); cnt++) chs += dta[cnt]; return (64 - chs) & MASK_6BITS; @@ -928,7 +947,6 @@ static int chk_msg14(struct sr_dev_inst *sdi) } if (devc->buf[1] == 0) { /* Error msg from device! */ - retc = SR_ERR_ARG; switch (devc->buf[2]) { case 1: /* Not used */ sr_err("Device: Illegal error code!"); @@ -993,7 +1011,7 @@ SR_PRIV int process_msg14(struct sr_dev_inst *sdi) sr_spew("Cmd %d unimplemented!", devc->buf[3]); break; case 3: /* Read firmware version and status */ - sr_spew("Cmd 3, Read firmware and status", devc->buf[3]); + sr_spew("Cmd 3, Read firmware and status"); switch (devc->cmd_idx) { case 0: devc->fw_ver_maj = devc->buf[5]; @@ -1064,8 +1082,8 @@ SR_PRIV int process_msg14(struct sr_dev_inst *sdi) devc->value += pow(10.0, cnt) * dgt; } sr_spew("process_msg14() value=%f scale=%f scale1000=%d mq=%d " - "unit=%d mqflags=0x%02llx", devc->value, devc->scale, - devc->scale1000, devc->mq, devc->unit, devc->mqflags); + "unit=%d mqflags=0x%02" PRIx64, devc->value, devc->scale, + devc->scale1000, devc->mq, devc->unit, (uint64_t)devc->mqflags); if (devc->value != NAN) devc->value *= devc->scale * pow(1000.0, devc->scale1000); @@ -1088,7 +1106,6 @@ SR_PRIV int gmc_mh_1x_2x_receive_data(int fd, int revents, void *cb_data) struct sr_serial_dev_inst *serial; uint8_t buf, msgt; int len; - gdouble elapsed_s; (void)fd; @@ -1102,7 +1119,7 @@ SR_PRIV int gmc_mh_1x_2x_receive_data(int fd, int revents, void *cb_data) if (revents == G_IO_IN) { /* Serial data arrived. */ while (GMC_BUFSIZE - devc->buflen - 1 > 0) { - len = serial_read(serial, devc->buf + devc->buflen, 1); + len = serial_read_nonblocking(serial, devc->buf + devc->buflen, 1); if (len < 1) break; buf = *(devc->buf + devc->buflen); @@ -1162,15 +1179,8 @@ SR_PRIV int gmc_mh_1x_2x_receive_data(int fd, int revents, void *cb_data) } } - /* If number of samples or time limit reached, stop acquisition. */ - if (devc->limit_samples && (devc->num_samples >= devc->limit_samples)) - sdi->driver->dev_acquisition_stop(sdi, cb_data); - - if (devc->limit_msec) { - elapsed_s = g_timer_elapsed(devc->elapsed_msec, NULL); - if ((elapsed_s * 1000) >= devc->limit_msec) - sdi->driver->dev_acquisition_stop(sdi, cb_data); - } + if (sr_sw_limits_check(&devc->limits)) + sdi->driver->dev_acquisition_stop(sdi); return TRUE; } @@ -1182,7 +1192,6 @@ SR_PRIV int gmc_mh_2x_receive_data(int fd, int revents, void *cb_data) struct sr_serial_dev_inst *serial; uint8_t buf; int len; - gdouble elapsed_s; (void)fd; @@ -1196,7 +1205,7 @@ SR_PRIV int gmc_mh_2x_receive_data(int fd, int revents, void *cb_data) if (revents == G_IO_IN) { /* Serial data arrived. */ while (GMC_BUFSIZE - devc->buflen - 1 > 0) { - len = serial_read(serial, devc->buf + devc->buflen, 1); + len = serial_read_nonblocking(serial, devc->buf + devc->buflen, 1); if (len < 1) break; buf = *(devc->buf + devc->buflen); @@ -1213,21 +1222,14 @@ SR_PRIV int gmc_mh_2x_receive_data(int fd, int revents, void *cb_data) } } - /* If number of samples or time limit reached, stop acquisition. */ - if (devc->limit_samples && (devc->num_samples >= devc->limit_samples)) - sdi->driver->dev_acquisition_stop(sdi, cb_data); - - if (devc->limit_msec) { - elapsed_s = g_timer_elapsed(devc->elapsed_msec, NULL); - if ((elapsed_s * 1000) >= devc->limit_msec) - sdi->driver->dev_acquisition_stop(sdi, cb_data); - } + if (sr_sw_limits_check(&devc->limits)) + sdi->driver->dev_acquisition_stop(sdi); /* Request next data set, if required */ if (sdi->status == SR_ST_ACTIVE) { if (devc->response_pending) { gint64 elapsed_us = g_get_monotonic_time() - devc->req_sent_at; - if (elapsed_us > 1*1000*1000) /* Timeout! */ + if (elapsed_us > (1 * 1000 * 1000)) /* Timeout! */ devc->response_pending = FALSE; } if (!devc->response_pending) { @@ -1252,9 +1254,9 @@ SR_PRIV int gmc_mh_2x_receive_data(int fd, int revents, void *cb_data) * @param[in] params Further parameters (9 bytes) * @param[out] buf Buffer to create msg in (42 bytes). */ -void create_cmd_14(guchar addr, guchar func, guchar* params, guchar* buf) +static void create_cmd_14(guchar addr, guchar func, guchar *params, guchar *buf) { - uint8_t dta[14]; /* Unencoded message */ + uint8_t dta[GMC_REPLY_SIZE]; /* Unencoded message */ int cnt; if (!params || !buf) @@ -1270,17 +1272,17 @@ void create_cmd_14(guchar addr, guchar func, guchar* params, guchar* buf) /* 4-12: Copy further parameters */ for (cnt = 0; cnt < 9; cnt++) - dta[cnt+4] = (params[cnt] & MASK_6BITS); + dta[cnt + 4] = (params[cnt] & MASK_6BITS); /* 13: Checksum (b complement) */ dta[13] = calc_chksum_14(dta); /* The whole message is packed into 3 bytes per byte now (lower 6 bits only) the most * peculiar way I have ever seen. Possibly to improve IR communication? */ - for (cnt = 0; cnt < 14; cnt++) { - buf[3*cnt] = (dta[cnt] & 0x01 ? 0x0f : 0) | (dta[cnt] & 0x02 ? 0xf0 : 0); - buf[3*cnt + 1] = (dta[cnt] & 0x04 ? 0x0f : 0) | (dta[cnt] & 0x08 ? 0xf0 : 0); - buf[3*cnt + 2] = (dta[cnt] & 0x10 ? 0x0f : 0) | (dta[cnt] & 0x20 ? 0xf0 : 0); + for (cnt = 0; cnt < GMC_REPLY_SIZE; cnt++) { + buf[(3 * cnt) + 0] = (dta[cnt] & 0x01 ? 0x0f : 0) | (dta[cnt] & 0x02 ? 0xf0 : 0); + buf[(3 * cnt) + 1] = (dta[cnt] & 0x04 ? 0x0f : 0) | (dta[cnt] & 0x08 ? 0xf0 : 0); + buf[(3 * cnt) + 2] = (dta[cnt] & 0x10 ? 0x0f : 0) | (dta[cnt] & 0x20 ? 0xf0 : 0); } } @@ -1302,7 +1304,8 @@ int req_meas14(const struct sr_dev_inst *sdi) devc->cmd_idx = 0; create_cmd_14(devc->addr, 8, params, msg); devc->req_sent_at = g_get_monotonic_time(); - if (serial_write(serial, msg, sizeof(msg)) == -1) { + if (serial_write_blocking(serial, msg, sizeof(msg), + serial_timeout(serial, sizeof(msg))) < (int)sizeof(msg)) { return SR_ERR; } @@ -1331,21 +1334,25 @@ int req_stat14(const struct sr_dev_inst *sdi, gboolean power_on) if (power_on) { sr_info("Write some data and wait 3s to turn on powered off device..."); - if (serial_write(serial, msg, sizeof(msg)) < 0) + if (serial_write_blocking(serial, msg, sizeof(msg), + serial_timeout(serial, sizeof(msg))) < 0) return SR_ERR; - g_usleep(1*1000*1000); - if (serial_write(serial, msg, sizeof(msg)) < 0) + g_usleep(1 * 1000 * 1000); + if (serial_write_blocking(serial, msg, sizeof(msg), + serial_timeout(serial, sizeof(msg))) < 0) return SR_ERR; - g_usleep(1*1000*1000); - if (serial_write(serial, msg, sizeof(msg)) < 0) + g_usleep(1 * 1000 * 1000); + if (serial_write_blocking(serial, msg, sizeof(msg), + serial_timeout(serial, sizeof(msg))) < 0) return SR_ERR; - g_usleep(1*1000*1000); + g_usleep(1 * 1000 * 1000); serial_flush(serial); } /* Write message and wait for reply */ devc->req_sent_at = g_get_monotonic_time(); - if (serial_write(serial, msg, sizeof(msg)) == -1) { + if (serial_write_blocking(serial, msg, sizeof(msg), + serial_timeout(serial, sizeof(msg))) < (int)sizeof(msg)) { return SR_ERR; } @@ -1366,7 +1373,7 @@ SR_PRIV int gmc_decode_model_sm(uint8_t mcode) return METRAHIT_NONE; } - switch(mcode) { + switch (mcode) { case 0x04: /* 0100b */ return METRAHIT_12S; case 0x08: /* 1000b */ @@ -1492,11 +1499,9 @@ SR_PRIV const char *gmc_model_str(enum model mcode) } } - -/** @copydoc sr_dev_driver.config_set - */ -SR_PRIV int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) +/** @copydoc sr_dev_driver.config_set */ +SR_PRIV int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi, + const struct sr_channel_group *cg) { struct dev_context *devc; uint8_t params[9]; @@ -1507,10 +1512,7 @@ SR_PRIV int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi, if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; - if (!(devc = sdi->priv)) { - sr_err("sdi->priv was NULL."); - return SR_ERR_BUG; - } + devc = sdi->priv; switch (key) { case SR_CONF_POWER_OFF: @@ -1524,25 +1526,15 @@ SR_PRIV int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi, params[0] = 5; params[1] = 5; create_cmd_14(devc->addr, 6, params, msg); - if (serial_write(sdi->conn, msg, sizeof(msg)) == -1) + if (serial_write_blocking(sdi->conn, msg, sizeof(msg), + serial_timeout(sdi->conn, sizeof(msg))) < 0) return SR_ERR; else - g_usleep(2000000); /* Wait to ensure transfer before interface switched off. */ - break; - case SR_CONF_LIMIT_MSEC: - if (g_variant_get_uint64(data) == 0) { - sr_err("LIMIT_MSEC can't be 0."); - return SR_ERR; - } - devc->limit_msec = g_variant_get_uint64(data); - sr_dbg("Setting time limit to %" PRIu64 "ms.", - devc->limit_msec); + g_usleep(2 * 1000 * 1000); /* Wait to ensure transfer before interface switched off. */ break; case SR_CONF_LIMIT_SAMPLES: - devc->limit_samples = g_variant_get_uint64(data); - sr_dbg("Setting sample limit to %" PRIu64 ".", - devc->limit_samples); - break; + case SR_CONF_LIMIT_MSEC: + return sr_sw_limits_config_set(&devc->limits, key, data); default: return SR_ERR_NA; }