/** Send data packets for current measurements. */ static void send_data(struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog_old analog; int i; float data[MAX_CHANNELS]; devc = sdi->priv; packet.type = SR_DF_ANALOG_OLD; packet.payload = &analog; analog.channels = sdi->channels; analog.num_samples = 1; analog.mq = SR_MQ_VOLTAGE; analog.unit = SR_UNIT_VOLT; analog.mqflags = SR_MQFLAG_DC; analog.data = data; for (i = 0; i < devc->model->num_channels; i++) analog.data[i] = devc->channel_status[i].output_voltage_last; /* Value always 3.3 or 5 for channel 3, if present! */ sr_session_send(sdi, &packet); analog.mq = SR_MQ_CURRENT; analog.unit = SR_UNIT_AMPERE; analog.mqflags = 0; analog.data = data; for (i = 0; i < devc->model->num_channels; i++) analog.data[i] = devc->channel_status[i].output_current_last; /* Value always 0 for channel 3, if present! */ sr_session_send(sdi, &packet); sr_sw_limits_update_samples_read(&devc->limits, 1); }
static void send_sample(struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; devc = sdi->priv; sr_analog_init(&analog, &encoding, &meaning, &spec, 2); packet.type = SR_DF_ANALOG; packet.payload = &analog; analog.meaning->channels = sdi->channels; analog.num_samples = 1; analog.meaning->mq = SR_MQ_VOLTAGE; analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags = SR_MQFLAG_DC; analog.data = &devc->voltage; sr_session_send(sdi, &packet); analog.meaning->mq = SR_MQ_CURRENT; analog.meaning->unit = SR_UNIT_AMPERE; analog.meaning->mqflags = 0; analog.data = &devc->current; sr_session_send(sdi, &packet); sr_sw_limits_update_samples_read(&devc->limits, 1); }
static void send_sample(struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog_old analog; devc = sdi->priv; packet.type = SR_DF_ANALOG_OLD; packet.payload = &analog; analog.channels = sdi->channels; analog.num_samples = 1; analog.mq = SR_MQ_VOLTAGE; analog.unit = SR_UNIT_VOLT; analog.mqflags = SR_MQFLAG_DC; analog.data = &devc->voltage; sr_session_send(sdi, &packet); analog.mq = SR_MQ_CURRENT; analog.unit = SR_UNIT_AMPERE; analog.mqflags = 0; analog.data = &devc->current; sr_session_send(sdi, &packet); sr_sw_limits_update_samples_read(&devc->limits, 1); }
static void handle_packet(const uint8_t *buf, struct sr_dev_inst *sdi) { float floatval; struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog_old analog; devc = sdi->priv; analog.num_samples = 1; analog.mq = -1; if (brymen_parse(buf, &floatval, &analog, NULL) != SR_OK) return; analog.data = &floatval; analog.channels = sdi->channels; if (analog.mq != -1) { /* Got a measurement. */ packet.type = SR_DF_ANALOG_OLD; packet.payload = &analog; sr_session_send(sdi, &packet); sr_sw_limits_update_samples_read(&devc->sw_limits, 1); } }
static void handle_packet(const uint8_t *buf, struct sr_dev_inst *sdi) { float floatval; struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; devc = sdi->priv; sr_analog_init(&analog, &encoding, &meaning, &spec, 0); analog.num_samples = 1; analog.meaning->mq = 0; if (brymen_parse(buf, &floatval, &analog, NULL) != SR_OK) return; analog.data = &floatval; analog.meaning->channels = sdi->channels; if (analog.meaning->mq != 0) { /* Got a measurement. */ packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); sr_sw_limits_update_samples_read(&devc->sw_limits, 1); } }
static void brymen_bm86x_handle_packet(const struct sr_dev_inst *sdi, unsigned char *buf) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog[2]; struct sr_analog_encoding encoding[2]; struct sr_analog_meaning meaning[2]; struct sr_analog_spec spec[2]; float floatval[2]; devc = sdi->priv; sr_analog_init(&analog[0], &encoding[0], &meaning[0], &spec[0], 0); sr_analog_init(&analog[1], &encoding[1], &meaning[1], &spec[1], 0); analog[0].meaning->mq = 0; analog[0].meaning->mqflags = 0; analog[1].meaning->mq = 0; analog[1].meaning->mqflags = 0; brymen_bm86x_parse(buf, floatval, analog); if (analog[0].meaning->mq != 0) { /* Got a measurement. */ analog[0].num_samples = 1; analog[0].data = &floatval[0]; analog[0].meaning->channels = g_slist_append(NULL, sdi->channels->data); packet.type = SR_DF_ANALOG; packet.payload = &analog[0]; sr_session_send(sdi, &packet); g_slist_free(analog[0].meaning->channels); } if (analog[1].meaning->mq != 0) { /* Got a measurement. */ analog[1].num_samples = 1; analog[1].data = &floatval[1]; analog[1].meaning->channels = g_slist_append(NULL, sdi->channels->next->data); packet.type = SR_DF_ANALOG; packet.payload = &analog[1]; sr_session_send(sdi, &packet); g_slist_free(analog[1].meaning->channels); } if (analog[0].meaning->mq != 0 || analog[1].meaning->mq != 0) sr_sw_limits_update_samples_read(&devc->sw_limits, 1); }
static void handle_qm_19x_data(const struct sr_dev_inst *sdi, char **tokens) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog_old analog; float fvalue; if (!strcmp(tokens[0], "9.9E+37")) { /* An invalid measurement shows up on the display as "OL", but * comes through like this. Since comparing 38-digit floats * is rather problematic, we'll cut through this here. */ fvalue = NAN; } else { if (sr_atof_ascii(tokens[0], &fvalue) != SR_OK || fvalue == 0.0) { sr_err("Invalid float '%s'.", tokens[0]); return; } } devc = sdi->priv; if (devc->mq == -1 || devc->unit == -1) /* Don't have valid metadata yet. */ return; if (devc->mq == SR_MQ_RESISTANCE && isnan(fvalue)) fvalue = INFINITY; else if (devc->mq == SR_MQ_CONTINUITY) { if (isnan(fvalue)) fvalue = 0.0; else fvalue = 1.0; } analog.channels = sdi->channels; analog.num_samples = 1; analog.data = &fvalue; analog.mq = devc->mq; analog.unit = devc->unit; analog.mqflags = 0; packet.type = SR_DF_ANALOG_OLD; packet.payload = &analog; sr_session_send(sdi, &packet); sr_sw_limits_update_samples_read(&devc->limits, 1); }
SR_PRIV int maynuo_m97_receive_data(int fd, int revents, void *cb_data) { struct sr_dev_inst *sdi; struct dev_context *devc; struct sr_modbus_dev_inst *modbus; struct sr_datafeed_packet packet; uint16_t registers[4]; (void)fd; (void)revents; if (!(sdi = cb_data)) return TRUE; modbus = sdi->conn; devc = sdi->priv; devc->expecting_registers = 0; if (sr_modbus_read_holding_registers(modbus, -1, 4, registers) == SR_OK) { packet.type = SR_DF_FRAME_BEGIN; sr_session_send(sdi, &packet); maynuo_m97_session_send_value(sdi, sdi->channels->data, RBFL(registers + 0), SR_MQ_VOLTAGE, SR_UNIT_VOLT); maynuo_m97_session_send_value(sdi, sdi->channels->next->data, RBFL(registers + 2), SR_MQ_CURRENT, SR_UNIT_AMPERE); packet.type = SR_DF_FRAME_END; sr_session_send(sdi, &packet); sr_sw_limits_update_samples_read(&devc->limits, 1); } if (sr_sw_limits_check(&devc->limits)) { sdi->driver->dev_acquisition_stop(sdi); return TRUE; } maynuo_m97_capture_start(sdi); return TRUE; }
static void teleinfo_handle_measurement(struct sr_dev_inst *sdi, const char *label, const char *data, char *optarif) { struct dev_context *devc; int v = atoi(data); if (!sdi || !(devc = sdi->priv)) { if (optarif && !strcmp(label, "OPTARIF")) strcpy(optarif, data); return; } if (!strcmp(label, "ADCO")) { sr_sw_limits_update_samples_read(&devc->sw_limits, 1); } else if (!strcmp(label, "BASE")) { teleinfo_send_value(sdi, "BASE", v, SR_MQ_POWER, SR_UNIT_WATT_HOUR); } else if (!strcmp(label, "HCHP")) { teleinfo_send_value(sdi, "HP" , v, SR_MQ_POWER, SR_UNIT_WATT_HOUR); } else if (!strcmp(label, "HCHC")) { teleinfo_send_value(sdi, "HC" , v, SR_MQ_POWER, SR_UNIT_WATT_HOUR); } else if (!strcmp(label, "EJPHN")) { teleinfo_send_value(sdi, "HN" , v, SR_MQ_POWER, SR_UNIT_WATT_HOUR); } else if (!strcmp(label, "EJPHPM")) { teleinfo_send_value(sdi, "HPM" , v, SR_MQ_POWER, SR_UNIT_WATT_HOUR); } else if (!strcmp(label, "BBRHPJB")) { teleinfo_send_value(sdi, "HPJB", v, SR_MQ_POWER, SR_UNIT_WATT_HOUR); } else if (!strcmp(label, "BBRHPJW")) { teleinfo_send_value(sdi, "HPJW", v, SR_MQ_POWER, SR_UNIT_WATT_HOUR); } else if (!strcmp(label, "BBRHPJR")) { teleinfo_send_value(sdi, "HPJR", v, SR_MQ_POWER, SR_UNIT_WATT_HOUR); } else if (!strcmp(label, "BBRHCJB")) { teleinfo_send_value(sdi, "HCJB", v, SR_MQ_POWER, SR_UNIT_WATT_HOUR); } else if (!strcmp(label, "BBRHCJW")) { teleinfo_send_value(sdi, "HCJW", v, SR_MQ_POWER, SR_UNIT_WATT_HOUR); } else if (!strcmp(label, "BBRHCJR")) { teleinfo_send_value(sdi, "HCJR", v, SR_MQ_POWER, SR_UNIT_WATT_HOUR); } else if (!strcmp(label, "IINST")) { teleinfo_send_value(sdi, "IINST", v, SR_MQ_CURRENT, SR_UNIT_AMPERE); } else if (!strcmp(label, "PAPP")) { teleinfo_send_value(sdi, "PAPP", v, SR_MQ_POWER, SR_UNIT_VOLT_AMPERE); } }
static void handle_packet(const uint8_t *buf, struct sr_dev_inst *sdi, void *info) { struct dmm_info *dmm; float floatval; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; struct dev_context *devc; dmm = (struct dmm_info *)sdi->driver; log_dmm_packet(buf); devc = sdi->priv; /* Note: digits/spec_digits will be overridden by the DMM parsers. */ sr_analog_init(&analog, &encoding, &meaning, &spec, 0); analog.meaning->channels = sdi->channels; analog.num_samples = 1; analog.meaning->mq = 0; dmm->packet_parse(buf, &floatval, &analog, info); analog.data = &floatval; /* If this DMM needs additional handling, call the resp. function. */ if (dmm->dmm_details) dmm->dmm_details(&analog, info); if (analog.meaning->mq != 0) { /* Got a measurement. */ packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); sr_sw_limits_update_samples_read(&devc->limits, 1); } }
/** * Process received line. It consists of 20 hex digits + \\r\\n, * e.g. '08100400018100400000'. */ static void nma_process_line(const struct sr_dev_inst *sdi) { struct dev_context *devc; int pos, flags; int vt, range; /* Measurement value type, range in device format */ int mmode, devstat; /* Measuring mode, device status */ float value; /* Measured value */ float scale; /* Scaling factor depending on range and function */ 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; devc->buf[LINE_LENGTH] = '\0'; sr_spew("Received line '%s'.", devc->buf); /* Check line. */ if (strlen((const char *)devc->buf) != LINE_LENGTH) { sr_err("line: Invalid status '%s', must be 20 hex digits.", devc->buf); devc->buflen = 0; return; } for (pos = 0; pos < LINE_LENGTH; pos++) { if (!isxdigit(devc->buf[pos])) { sr_err("line: Expected hex digit in '%s' at pos %d!", devc->buf, pos); devc->buflen = 0; return; } } /* Start decoding. */ value = 0.0; scale = 1.0; /* TODO: Use proper 'digits' value for this device (and its modes). */ sr_analog_init(&analog, &encoding, &meaning, &spec, 2); /* * The numbers are hex digits, starting from 0. * 0: Keyboard status, currently not interesting. * 1: Central switch status, currently not interesting. * 2: Type of measured value. */ vt = xgittoint(devc->buf[2]); switch (vt) { case 0: analog.meaning->mq = SR_MQ_VOLTAGE; break; case 1: analog.meaning->mq = SR_MQ_CURRENT; /* 2A */ break; case 2: analog.meaning->mq = SR_MQ_RESISTANCE; break; case 3: analog.meaning->mq = SR_MQ_CAPACITANCE; break; case 4: analog.meaning->mq = SR_MQ_TEMPERATURE; break; case 5: analog.meaning->mq = SR_MQ_FREQUENCY; break; case 6: analog.meaning->mq = SR_MQ_CURRENT; /* 10A */ break; case 7: analog.meaning->mq = SR_MQ_GAIN; /* TODO: Scale factor */ break; case 8: analog.meaning->mq = SR_MQ_GAIN; /* Percentage */ scale /= 100.0; break; case 9: analog.meaning->mq = SR_MQ_GAIN; /* dB */ scale /= 100.0; break; default: sr_err("Unknown value type: 0x%02x.", vt); break; } /* 3: Measurement range for measured value */ range = xgittoint(devc->buf[3]); switch (vt) { case 0: /* V */ scale *= pow(10.0, range - 5); break; case 1: /* A */ scale *= pow(10.0, range - 7); break; case 2: /* Ω */ scale *= pow(10.0, range - 2); break; case 3: /* F */ scale *= pow(10.0, range - 12); break; case 4: /* °C */ scale *= pow(10.0, range - 1); break; case 5: /* Hz */ scale *= pow(10.0, range - 2); break; // No default, other value types have fixed display format. } /* 5: Sign and 1st digit */ flags = xgittoint(devc->buf[5]); value = (flags & 0x03); if (flags & 0x04) scale *= -1; /* 6-9: 2nd-4th digit */ for (pos = 6; pos < 10; pos++) value = value * 10 + xgittoint(devc->buf[pos]); value *= scale; /* 10: Display counter */ mmode = xgittoint(devc->buf[10]); switch (mmode) { case 0: /* Frequency */ analog.meaning->unit = SR_UNIT_HERTZ; break; case 1: /* V TRMS, only type 5 */ analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS); break; case 2: /* V AC */ analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags |= SR_MQFLAG_AC; if (devc->type >= 3) analog.meaning->mqflags |= SR_MQFLAG_RMS; break; case 3: /* V DC */ analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags |= SR_MQFLAG_DC; break; case 4: /* Ohm */ analog.meaning->unit = SR_UNIT_OHM; break; case 5: /* Continuity */ analog.meaning->unit = SR_UNIT_BOOLEAN; analog.meaning->mq = SR_MQ_CONTINUITY; /* TODO: Continuity handling is a bit odd in libsigrok. */ break; case 6: /* Degree Celsius */ analog.meaning->unit = SR_UNIT_CELSIUS; break; case 7: /* Capacity */ analog.meaning->unit = SR_UNIT_FARAD; break; case 8: /* Current DC */ analog.meaning->unit = SR_UNIT_AMPERE; analog.meaning->mqflags |= SR_MQFLAG_DC; break; case 9: /* Current AC */ analog.meaning->unit = SR_UNIT_AMPERE; analog.meaning->mqflags |= SR_MQFLAG_AC; if (devc->type >= 3) analog.meaning->mqflags |= SR_MQFLAG_RMS; break; case 0xa: /* Current TRMS, only type 5 */ analog.meaning->unit = SR_UNIT_AMPERE; analog.meaning->mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS); break; case 0xb: /* Diode */ analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags |= (SR_MQFLAG_DIODE | SR_MQFLAG_DC); break; default: sr_err("Unknown mmode: 0x%02x.", mmode); break; } /* 11: Device status */ devstat = xgittoint(devc->buf[11]); switch (devstat) { case 1: /* Normal measurement */ break; case 2: /* Input loop (limit, reference values) */ break; case 3: /* TRANS/SENS */ break; case 4: /* Error */ sr_err("Device error. Fuse?"); /* TODO: Really abort? */ devc->buflen = 0; return; /* Cannot continue. */ default: sr_err("Unknown device status: 0x%02x", devstat); break; } /* 12-19: Flags and display symbols */ /* 12, 13 */ flags = (xgittoint(devc->buf[12]) << 8) | xgittoint(devc->buf[13]); /* 0x80: PRINT TODO: Stop polling when discovered? */ /* 0x40: EXTR */ if (analog.meaning->mq == SR_MQ_CONTINUITY) { if (flags & 0x20) value = 1.0; /* Beep */ else value = 0.0; } /* 0x10: AVG */ /* 0x08: Diode */ if (flags & 0x04) /* REL */ analog.meaning->mqflags |= SR_MQFLAG_RELATIVE; /* 0x02: SHIFT */ if (flags & 0x01) /* % */ analog.meaning->unit = SR_UNIT_PERCENTAGE; /* 14, 15 */ flags = (xgittoint(devc->buf[14]) << 8) | xgittoint(devc->buf[15]); if (!(flags & 0x80)) /* MAN: Manual range */ analog.meaning->mqflags |= SR_MQFLAG_AUTORANGE; if (flags & 0x40) /* LOBATT1: Low battery, measurement still within specs */ devc->lowbatt = 1; /* 0x20: PEAK */ /* 0x10: COUNT */ if (flags & 0x08) /* HOLD */ analog.meaning->mqflags |= SR_MQFLAG_HOLD; /* 0x04: LIMIT */ if (flags & 0x02) /* MAX */ analog.meaning->mqflags |= SR_MQFLAG_MAX; if (flags & 0x01) /* MIN */ analog.meaning->mqflags |= SR_MQFLAG_MIN; /* 16, 17 */ flags = (xgittoint(devc->buf[16]) << 8) | xgittoint(devc->buf[17]); /* 0xe0: undefined */ if (flags & 0x10) { /* LOBATT2: Low battery, measurement inaccurate */ devc->lowbatt = 2; sr_warn("Low battery, measurement quality degraded!"); } /* 0x08: SCALED */ /* 0x04: RATE (=lower resolution, allows higher data rate up to 10/s. */ /* 0x02: Current clamp */ if (flags & 0x01) { /* dB */ /* * TODO: The Norma has an adjustable dB reference value. If * changed from default, this is not correct. */ if (analog.meaning->unit == SR_UNIT_VOLT) analog.meaning->unit = SR_UNIT_DECIBEL_VOLT; else analog.meaning->unit = SR_UNIT_UNITLESS; } /* 18, 19 */ /* flags = (xgittoint(devc->buf[18]) << 8) | xgittoint(devc->buf[19]); */ /* 0x80: Undefined. */ /* 0x40: Remote mode, keyboard locked */ /* 0x38: Undefined. */ /* 0x04: MIN > MAX */ /* 0x02: Measured value < Min */ /* 0x01: Measured value > Max */ /* 4: Flags. Evaluating this after setting value! */ flags = xgittoint(devc->buf[4]); if (flags & 0x04) /* Invalid value */ value = NAN; else if (flags & 0x01) /* Overload */ value = INFINITY; if (flags & 0x02) { /* Duplicate value, has been sent before. */ sr_spew("Duplicate value, dismissing!"); devc->buflen = 0; return; } sr_spew("range=%d/scale=%f/value=%f", range, (double)scale, (double)value); /* Finish and send packet. */ analog.meaning->channels = sdi->channels; analog.num_samples = 1; analog.data = &value; memset(&packet, 0, sizeof(struct sr_datafeed_packet)); packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); /* Finish processing. */ sr_sw_limits_update_samples_read(&devc->limits, 1); devc->buflen = 0; }
static int recv_log(const struct sr_dev_inst *sdi, GMatchInfo *match, const int mqs[], const int units[], const int exponents[], unsigned int num_functions) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; char *mstr; unsigned function; int value, negative, overload, exponent, alternate_unit, mq, unit; int mqflags = 0; float fvalue; sr_spew("LOG response '%s'.", g_match_info_get_string(match)); devc = sdi->priv; mstr = g_match_info_fetch(match, 2); if (sr_atoi(mstr, (int*)&function) != SR_OK || function >= num_functions) { g_free(mstr); sr_dbg("Invalid function."); return SR_ERR; } g_free(mstr); mstr = g_match_info_fetch(match, 3); if (sr_atoi(mstr, &value) != SR_OK) { g_free(mstr); sr_dbg("Invalid value."); return SR_ERR; } g_free(mstr); mstr = g_match_info_fetch(match, 1); negative = mstr[7] & 2 ? -1 : 1; overload = mstr[8] & 4; exponent = (mstr[9] & 0xF) + exponents[function]; alternate_unit = mstr[10] & 1; if (mstr[ 8] & 1) mqflags |= SR_MQFLAG_DC; if (mstr[ 8] & 2) mqflags |= SR_MQFLAG_AC; if (mstr[11] & 4) mqflags |= SR_MQFLAG_RELATIVE; if (mstr[12] & 1) mqflags |= SR_MQFLAG_AVG; if (mstr[12] & 2) mqflags |= SR_MQFLAG_MIN; if (mstr[12] & 4) mqflags |= SR_MQFLAG_MAX; if (function == 5) mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC; g_free(mstr); mq = mqs[function]; unit = units[function]; if (alternate_unit) { if (mq == SR_MQ_RESISTANCE) mq = SR_MQ_CONTINUITY; if (unit == SR_UNIT_DECIBEL_MW) unit = SR_UNIT_DECIBEL_VOLT; if (unit == SR_UNIT_CELSIUS) { unit = SR_UNIT_FAHRENHEIT; if (devc->profile->model == KEYSIGHT_U1281 || devc->profile->model == KEYSIGHT_U1282) exponent--; } } if (overload) fvalue = NAN; else fvalue = negative * value * powf(10, exponent); sr_analog_init(&analog, &encoding, &meaning, &spec, -exponent); analog.meaning->mq = mq; analog.meaning->unit = unit; analog.meaning->mqflags = mqflags; analog.meaning->channels = g_slist_append(NULL, devc->cur_channel); analog.num_samples = 1; analog.data = &fvalue; packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); g_slist_free(analog.meaning->channels); sr_sw_limits_update_samples_read(&devc->limits, 1); devc->cur_sample++; return JOB_LOG; }
static int recv_fetc(const struct sr_dev_inst *sdi, GMatchInfo *match) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; struct sr_channel *prev_chan; float fvalue; const char *s; char *mstr; int i, exp; sr_spew("FETC reply '%s'.", g_match_info_get_string(match)); devc = sdi->priv; i = devc->cur_channel->index; if (devc->cur_mq[i] == -1) /* This detects when channel P2 is reporting TEMP as an identical * copy of channel P3. In this case, we just skip P2. */ goto skip_value; s = g_match_info_get_string(match); if (!strcmp(s, "-9.90000000E+37") || !strcmp(s, "+9.90000000E+37")) { /* An invalid measurement shows up on the display as "O.L", but * comes through like this. Since comparing 38-digit floats * is rather problematic, we'll cut through this here. */ fvalue = NAN; } else { mstr = g_match_info_fetch(match, 1); if (sr_atof_ascii(mstr, &fvalue) != SR_OK) { g_free(mstr); sr_dbg("Invalid float."); return SR_ERR; } g_free(mstr); if (devc->cur_exponent[i] != 0) fvalue *= powf(10, devc->cur_exponent[i]); } if (devc->cur_unit[i] == SR_UNIT_DECIBEL_MW || devc->cur_unit[i] == SR_UNIT_DECIBEL_VOLT || devc->cur_unit[i] == SR_UNIT_PERCENTAGE) { mstr = g_match_info_fetch(match, 2); if (mstr && sr_atoi(mstr, &exp) == SR_OK) { devc->cur_digits[i] = MIN(4 - exp, devc->cur_digits[i]); devc->cur_encoding[i] = MIN(5 - exp, devc->cur_encoding[i]); } g_free(mstr); } sr_analog_init(&analog, &encoding, &meaning, &spec, devc->cur_digits[i] - devc->cur_exponent[i]); analog.meaning->mq = devc->cur_mq[i]; analog.meaning->unit = devc->cur_unit[i]; analog.meaning->mqflags = devc->cur_mqflags[i]; analog.meaning->channels = g_slist_append(NULL, devc->cur_channel); analog.num_samples = 1; analog.data = &fvalue; encoding.digits = devc->cur_encoding[i] - devc->cur_exponent[i]; packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); g_slist_free(analog.meaning->channels); sr_sw_limits_update_samples_read(&devc->limits, 1); skip_value: prev_chan = devc->cur_channel; devc->cur_channel = sr_next_enabled_channel(sdi, devc->cur_channel); if (devc->cur_channel->index > prev_chan->index) return JOB_AGAIN; else return JOB_FETC; }
static void handle_line(const struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_serial_dev_inst *serial; struct sr_datafeed_packet packet; struct sr_datafeed_analog_old *analog; int num_tokens, n, i; char cmd[16], **tokens; devc = sdi->priv; serial = sdi->conn; sr_spew("Received line '%s' (%d).", devc->buf, devc->buflen); if (devc->buflen == 1) { if (devc->buf[0] != '0') { /* Not just a CMD_ACK from the query command. */ sr_dbg("Got CMD_ACK '%c'.", devc->buf[0]); devc->expect_response = FALSE; } devc->buflen = 0; return; } analog = NULL; tokens = g_strsplit(devc->buf, ",", 0); if (tokens[0]) { if (devc->profile->model == FLUKE_187 || devc->profile->model == FLUKE_189) { devc->expect_response = FALSE; analog = handle_qm_18x(sdi, tokens); } else if (devc->profile->model == FLUKE_287 || devc->profile->model == FLUKE_289) { devc->expect_response = FALSE; analog = handle_qm_28x(sdi, tokens); } else if (devc->profile->model == FLUKE_190) { devc->expect_response = FALSE; for (num_tokens = 0; tokens[num_tokens]; num_tokens++); if (num_tokens >= 7) { /* Response to QM: this is a comma-separated list of * fields with metadata about the measurement. This * format can return multiple sets of metadata, * split into sets of 7 tokens each. */ devc->meas_type = 0; for (i = 0; i < num_tokens; i += 7) handle_qm_19x_meta(sdi, tokens + i); if (devc->meas_type) { /* Slip the request in now, before the main * timer loop asks for metadata again. */ n = sprintf(cmd, "QM %d\r", devc->meas_type); if (serial_write_blocking(serial, cmd, n, SERIAL_WRITE_TIMEOUT_MS) < 0) sr_err("Unable to send QM (measurement)."); } } else { /* Response to QM <n> measurement request. */ handle_qm_19x_data(sdi, tokens); } } } g_strfreev(tokens); devc->buflen = 0; if (analog) { /* Got a measurement. */ packet.type = SR_DF_ANALOG_OLD; packet.payload = analog; sr_session_send(sdi, &packet); sr_sw_limits_update_samples_read(&devc->limits, 1); g_free(analog->data); g_free(analog); } }
static void decode_buf(struct sr_dev_inst *sdi, unsigned char *data) { struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; struct dev_context *devc; long factor, ivalue; uint8_t digits[4]; gboolean is_duty, is_continuity, is_diode, is_ac, is_dc, is_auto; gboolean is_hold, is_max, is_min, is_relative, minus; float fvalue; devc = sdi->priv; digits[0] = decode_digit(data[12]); digits[1] = decode_digit(data[11]); digits[2] = decode_digit(data[10]); digits[3] = decode_digit(data[9]); if (digits[0] == 0x0f && digits[1] == 0x00 && digits[2] == 0x0a && digits[3] == 0x0f) /* The "over limit" (OL) display comes through like this */ ivalue = -1; else if (digits[0] > 9 || digits[1] > 9 || digits[2] > 9 || digits[3] > 9) /* An invalid digit in any position denotes no value. */ ivalue = -2; else { ivalue = digits[0] * 1000; ivalue += digits[1] * 100; ivalue += digits[2] * 10; ivalue += digits[3]; } /* Decimal point position */ factor = 0; switch (data[7] >> 4) { case 0x00: factor = 0; break; case 0x02: factor = 1; break; case 0x04: factor = 2; break; case 0x08: factor = 3; break; default: sr_err("Unknown decimal point byte: 0x%.2x.", data[7]); break; } /* Minus flag */ minus = data[2] & 0x01; /* Mode detail symbols on the right side of the digits */ is_duty = is_continuity = is_diode = FALSE; switch (data[4]) { case 0x00: /* None. */ break; case 0x01: /* Micro */ factor += 6; break; case 0x02: /* Milli */ factor += 3; break; case 0x04: /* Kilo */ ivalue *= 1000; break; case 0x08: /* Mega */ ivalue *= 1000000; break; case 0x10: /* Continuity shows up as Ohm + this bit */ is_continuity = TRUE; break; case 0x20: /* Diode tester is Volt + this bit */ is_diode = TRUE; break; case 0x40: is_duty = TRUE; break; case 0x80: /* Never seen */ sr_dbg("Unknown mode right detail: 0x%.2x.", data[4]); break; default: sr_dbg("Unknown/invalid mode right detail: 0x%.2x.", data[4]); break; } /* Scale flags on the right, continued */ is_max = is_min = FALSE; if (data[5] & 0x04) is_max = TRUE; if (data[5] & 0x08) is_min = TRUE; if (data[5] & 0x40) /* Nano */ factor += 9; /* Mode detail symbols on the left side of the digits */ is_auto = is_dc = is_ac = is_hold = is_relative = FALSE; if (data[6] & 0x04) is_auto = TRUE; if (data[6] & 0x08) is_dc = TRUE; if (data[6] & 0x10) is_ac = TRUE; if (data[6] & 0x20) is_relative = TRUE; if (data[6] & 0x40) is_hold = TRUE; fvalue = (float)ivalue / pow(10, factor); if (minus) fvalue = -fvalue; sr_analog_init(&analog, &encoding, &meaning, &spec, 4); /* Measurement mode */ meaning.channels = sdi->channels; meaning.mq = 0; switch (data[3]) { case 0x00: if (is_duty) { meaning.mq = SR_MQ_DUTY_CYCLE; meaning.unit = SR_UNIT_PERCENTAGE; } else sr_dbg("Unknown measurement mode: %.2x.", data[3]); break; case 0x01: if (is_diode) { meaning.mq = SR_MQ_VOLTAGE; meaning.unit = SR_UNIT_VOLT; meaning.mqflags |= SR_MQFLAG_DIODE; if (ivalue < 0) fvalue = NAN; } else { if (ivalue < 0) break; meaning.mq = SR_MQ_VOLTAGE; meaning.unit = SR_UNIT_VOLT; if (is_ac) meaning.mqflags |= SR_MQFLAG_AC; if (is_dc) meaning.mqflags |= SR_MQFLAG_DC; } break; case 0x02: meaning.mq = SR_MQ_CURRENT; meaning.unit = SR_UNIT_AMPERE; if (is_ac) meaning.mqflags |= SR_MQFLAG_AC; if (is_dc) meaning.mqflags |= SR_MQFLAG_DC; break; case 0x04: if (is_continuity) { meaning.mq = SR_MQ_CONTINUITY; meaning.unit = SR_UNIT_BOOLEAN; fvalue = ivalue < 0 ? 0.0 : 1.0; } else { meaning.mq = SR_MQ_RESISTANCE; meaning.unit = SR_UNIT_OHM; if (ivalue < 0) fvalue = INFINITY; } break; case 0x08: /* Never seen */ sr_dbg("Unknown measurement mode: 0x%.2x.", data[3]); break; case 0x10: meaning.mq = SR_MQ_FREQUENCY; meaning.unit = SR_UNIT_HERTZ; break; case 0x20: meaning.mq = SR_MQ_CAPACITANCE; meaning.unit = SR_UNIT_FARAD; break; case 0x40: meaning.mq = SR_MQ_TEMPERATURE; meaning.unit = SR_UNIT_CELSIUS; break; case 0x80: meaning.mq = SR_MQ_TEMPERATURE; meaning.unit = SR_UNIT_FAHRENHEIT; break; default: sr_dbg("Unknown/invalid measurement mode: 0x%.2x.", data[3]); break; } if (meaning.mq == 0) return; if (is_auto) meaning.mqflags |= SR_MQFLAG_AUTORANGE; if (is_hold) meaning.mqflags |= SR_MQFLAG_HOLD; if (is_max) meaning.mqflags |= SR_MQFLAG_MAX; if (is_min) meaning.mqflags |= SR_MQFLAG_MIN; if (is_relative) meaning.mqflags |= SR_MQFLAG_RELATIVE; analog.data = &fvalue; analog.num_samples = 1; packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); sr_sw_limits_update_samples_read(&devc->limits, 1); }