libsigrok  unreleased development snapshot
sigrok hardware access and backend library
analog.c
Go to the documentation of this file.
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2014 Bert Vermeulen <bert@biot.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 <stdio.h>
22 #include <stdint.h>
23 #include <string.h>
24 #include <ctype.h>
25 #include <math.h>
26 #include <libsigrok/libsigrok.h>
27 #include "libsigrok-internal.h"
28 
29 /** @cond PRIVATE */
30 #define LOG_PREFIX "analog"
31 /** @endcond */
32 
33 /**
34  * @file
35  *
36  * Handling and converting analog data.
37  */
38 
39 /**
40  * @defgroup grp_analog Analog data handling
41  *
42  * Handling and converting analog data.
43  *
44  * @{
45  */
46 
47 struct unit_mq_string {
48  uint64_t value;
49  const char *str;
50 };
51 
52 /* Please use the same order as in enum sr_unit (libsigrok.h). */
53 static struct unit_mq_string unit_strings[] = {
54  { SR_UNIT_VOLT, "V" },
55  { SR_UNIT_AMPERE, "A" },
56  { SR_UNIT_OHM, "\xe2\x84\xa6" },
57  { SR_UNIT_FARAD, "F" },
58  { SR_UNIT_KELVIN, "K" },
59  { SR_UNIT_CELSIUS, "\xc2\xb0""C" },
60  { SR_UNIT_FAHRENHEIT, "\xc2\xb0""F" },
61  { SR_UNIT_HERTZ, "Hz" },
62  { SR_UNIT_PERCENTAGE, "%" },
63  { SR_UNIT_BOOLEAN, "" },
64  { SR_UNIT_SECOND, "s" },
65  { SR_UNIT_SIEMENS, "S" },
66  { SR_UNIT_DECIBEL_MW, "dBm" },
67  { SR_UNIT_DECIBEL_VOLT, "dBV" },
68  { SR_UNIT_UNITLESS, "" },
69  { SR_UNIT_DECIBEL_SPL, "dB" },
70  { SR_UNIT_CONCENTRATION, "ppm" },
72  { SR_UNIT_VOLT_AMPERE, "VA" },
73  { SR_UNIT_WATT, "W" },
74  { SR_UNIT_WATT_HOUR, "Wh" },
75  { SR_UNIT_METER_SECOND, "m/s" },
76  { SR_UNIT_HECTOPASCAL, "hPa" },
77  { SR_UNIT_HUMIDITY_293K, "%rF" },
78  { SR_UNIT_DEGREE, "\xc2\xb0" },
79  { SR_UNIT_HENRY, "H" },
80  { SR_UNIT_GRAM, "g" },
81  { SR_UNIT_CARAT, "ct" },
82  { SR_UNIT_OUNCE, "oz" },
83  { SR_UNIT_TROY_OUNCE, "oz t" },
84  { SR_UNIT_POUND, "lb" },
85  { SR_UNIT_PENNYWEIGHT, "dwt" },
86  { SR_UNIT_GRAIN, "gr" },
87  { SR_UNIT_TAEL, "tael" },
88  { SR_UNIT_MOMME, "momme" },
89  { SR_UNIT_TOLA, "tola" },
90  { SR_UNIT_PIECE, "pcs" },
91  { SR_UNIT_JOULE, "J" },
92  { SR_UNIT_COULOMB, "C" },
93  { SR_UNIT_AMPERE_HOUR, "Ah" },
94  ALL_ZERO
95 };
96 
97 /* Please use the same order as in enum sr_mqflag (libsigrok.h). */
98 static struct unit_mq_string mq_strings[] = {
99  { SR_MQFLAG_AC, " AC" },
100  { SR_MQFLAG_DC, " DC" },
101  { SR_MQFLAG_RMS, " RMS" },
102  { SR_MQFLAG_DIODE, " DIODE" },
103  { SR_MQFLAG_HOLD, " HOLD" },
104  { SR_MQFLAG_MAX, " MAX" },
105  { SR_MQFLAG_MIN, " MIN" },
106  { SR_MQFLAG_AUTORANGE, " AUTO" },
107  { SR_MQFLAG_RELATIVE, " REL" },
108  { SR_MQFLAG_SPL_FREQ_WEIGHT_A, "(A)" },
109  { SR_MQFLAG_SPL_FREQ_WEIGHT_C, "(C)" },
110  { SR_MQFLAG_SPL_FREQ_WEIGHT_Z, "(Z)" },
111  { SR_MQFLAG_SPL_FREQ_WEIGHT_FLAT, "(SPL)" },
112  { SR_MQFLAG_SPL_TIME_WEIGHT_S, " S" },
113  { SR_MQFLAG_SPL_TIME_WEIGHT_F, " F" },
114  { SR_MQFLAG_SPL_LAT, " LAT" },
115  /* Not a standard function for SLMs, so this is a made-up notation. */
116  { SR_MQFLAG_SPL_PCT_OVER_ALARM, "%oA" },
117  { SR_MQFLAG_DURATION, " DURATION" },
118  { SR_MQFLAG_AVG, " AVG" },
119  { SR_MQFLAG_REFERENCE, " REF" },
120  { SR_MQFLAG_UNSTABLE, " UNSTABLE" },
121  { SR_MQFLAG_FOUR_WIRE, " 4-WIRE" },
122  ALL_ZERO
123 };
124 
125 /** @private */
126 SR_PRIV int sr_analog_init(struct sr_datafeed_analog *analog,
127  struct sr_analog_encoding *encoding,
128  struct sr_analog_meaning *meaning,
129  struct sr_analog_spec *spec,
130  int digits)
131 {
132  memset(analog, 0, sizeof(*analog));
133  memset(encoding, 0, sizeof(*encoding));
134  memset(meaning, 0, sizeof(*meaning));
135  memset(spec, 0, sizeof(*spec));
136 
137  analog->encoding = encoding;
138  analog->meaning = meaning;
139  analog->spec = spec;
140 
141  encoding->unitsize = sizeof(float);
142  encoding->is_float = TRUE;
143 #ifdef WORDS_BIGENDIAN
144  encoding->is_bigendian = TRUE;
145 #else
146  encoding->is_bigendian = FALSE;
147 #endif
148  encoding->digits = digits;
149  encoding->is_digits_decimal = TRUE;
150  encoding->scale.p = 1;
151  encoding->scale.q = 1;
152  encoding->offset.p = 0;
153  encoding->offset.q = 1;
154 
155  spec->spec_digits = digits;
156 
157  return SR_OK;
158 }
159 
160 /**
161  * Convert an analog datafeed payload to an array of floats.
162  *
163  * The caller must provide the #outbuf space for the conversion result,
164  * and is expected to free allocated space after use.
165  *
166  * @param[in] analog The analog payload to convert. Must not be NULL.
167  * analog->data, analog->meaning, and analog->encoding
168  * must not be NULL.
169  * @param[out] outbuf Memory where to store the result. Must not be NULL.
170  *
171  * @retval SR_OK Success.
172  * @retval SR_ERR Unsupported encoding.
173  * @retval SR_ERR_ARG Invalid argument.
174  *
175  * @since 0.4.0
176  */
178  float *outbuf)
179 {
180  size_t count;
181  gboolean host_bigendian;
182  gboolean input_float, input_signed, input_bigendian;
183  size_t input_unitsize;
184  double scale, offset, value;
185  const uint8_t *data8;
186  gboolean input_is_native;
187  char type_text[10];
188 
189  if (!analog || !analog->data || !analog->meaning || !analog->encoding)
190  return SR_ERR_ARG;
191  if (!outbuf)
192  return SR_ERR_ARG;
193 
194  count = analog->num_samples * g_slist_length(analog->meaning->channels);
195 
196  /*
197  * Determine properties of the input data's and the host's
198  * native formats, to simplify test conditions below.
199  * Error messages for unsupported input property combinations
200  * will only be seen by developers and maintainers of input
201  * formats or acquisition device drivers. Terse output is
202  * acceptable there, users shall never see them.
203  */
204 #ifdef WORDS_BIGENDIAN
205  host_bigendian = TRUE;
206 #else
207  host_bigendian = FALSE;
208 #endif
209  input_float = analog->encoding->is_float;
210  input_signed = analog->encoding->is_signed;
211  input_bigendian = analog->encoding->is_bigendian;
212  input_unitsize = analog->encoding->unitsize;
213 
214  /*
215  * Prepare the iteration over the sample data: Get the common
216  * scale/offset factors which apply to all individual values.
217  * Position the read pointer on the first byte of input data.
218  */
219  offset = analog->encoding->offset.p;
220  offset /= analog->encoding->offset.q;
221  scale = analog->encoding->scale.p;
222  scale /= analog->encoding->scale.q;
223  data8 = analog->data;
224 
225  /*
226  * Immediately handle the special case where input data needs
227  * no conversion because it already is in the application's
228  * native format. Do apply scale/offset though when applicable
229  * on our way out.
230  */
231  input_is_native = input_float &&
232  input_unitsize == sizeof(outbuf[0]) &&
233  input_bigendian == host_bigendian;
234  if (input_is_native) {
235  memcpy(outbuf, data8, count * sizeof(outbuf[0]));
236  if (scale != 1.0 || offset != 0.0) {
237  while (count--) {
238  *outbuf *= scale;
239  *outbuf += offset;
240  outbuf++;
241  }
242  }
243  return SR_OK;
244  }
245 
246  /*
247  * Accept sample values in different widths and data types and
248  * endianess formats (floating point or signed or unsigned
249  * integer, in either endianess, for a set of supported widths).
250  * Common scale/offset factors apply to all sample values.
251  *
252  * Do most internal calculations on double precision values.
253  * Only trim the result data to single precision, since that's
254  * the routine's result data type in its public API which needs
255  * to be kept for compatibility. It remains an option for later
256  * to add another public routine which returns double precision
257  * result data, call sites could migrate at their own pace.
258  */
259  if (input_float && input_unitsize == sizeof(float)) {
260  float (*reader)(const uint8_t **p);
261  if (input_bigendian)
262  reader = read_fltbe_inc;
263  else
264  reader = read_fltle_inc;
265  while (count--) {
266  value = reader(&data8);
267  value *= scale;
268  value += offset;
269  *outbuf++ = value;
270  }
271  return SR_OK;
272  }
273  if (input_float && input_unitsize == sizeof(double)) {
274  double (*reader)(const uint8_t **p);
275  if (input_bigendian)
276  reader = read_dblbe_inc;
277  else
278  reader = read_dblle_inc;
279  while (count--) {
280  value = reader(&data8);
281  value *= scale;
282  value += offset;
283  *outbuf++ = value;
284  }
285  return SR_OK;
286  }
287  if (input_float) {
288  snprintf(type_text, sizeof(type_text), "%c%zu%s",
289  'f', input_unitsize * 8, input_bigendian ? "be" : "le");
290  sr_err("Unsupported type for analog-to-float conversion: %s.",
291  type_text);
292  return SR_ERR;
293  }
294 
295  if (input_unitsize == sizeof(uint8_t) && input_signed) {
296  int8_t (*reader)(const uint8_t **p);
297  reader = read_i8_inc;
298  while (count--) {
299  value = reader(&data8);
300  value *= scale;
301  value += offset;
302  *outbuf++ = value;
303  }
304  return SR_OK;
305  }
306  if (input_unitsize == sizeof(uint8_t)) {
307  uint8_t (*reader)(const uint8_t **p);
308  reader = read_u8_inc;
309  while (count--) {
310  value = reader(&data8);
311  value *= scale;
312  value += offset;
313  *outbuf++ = value;
314  }
315  return SR_OK;
316  }
317  if (input_unitsize == sizeof(uint16_t) && input_signed) {
318  int16_t (*reader)(const uint8_t **p);
319  if (input_bigendian)
320  reader = read_i16be_inc;
321  else
322  reader = read_i16le_inc;
323  while (count--) {
324  value = reader(&data8);
325  value *= scale;
326  value += offset;
327  *outbuf++ = value;
328  }
329  return SR_OK;
330  }
331  if (input_unitsize == sizeof(uint16_t)) {
332  uint16_t (*reader)(const uint8_t **p);
333  if (input_bigendian)
334  reader = read_u16be_inc;
335  else
336  reader = read_u16le_inc;
337  while (count--) {
338  value = reader(&data8);
339  value *= scale;
340  value += offset;
341  *outbuf++ = value;
342  }
343  return SR_OK;
344  }
345  if (input_unitsize == sizeof(uint32_t) && input_signed) {
346  int32_t (*reader)(const uint8_t **p);
347  if (input_bigendian)
348  reader = read_i32be_inc;
349  else
350  reader = read_i32le_inc;
351  while (count--) {
352  value = reader(&data8);
353  value *= scale;
354  value += offset;
355  *outbuf++ = value;
356  }
357  return SR_OK;
358  }
359  if (input_unitsize == sizeof(uint32_t)) {
360  uint32_t (*reader)(const uint8_t **p);
361  if (input_bigendian)
362  reader = read_u32be_inc;
363  else
364  reader = read_u32le_inc;
365  while (count--) {
366  value = reader(&data8);
367  value *= scale;
368  value += offset;
369  *outbuf++ = value;
370  }
371  return SR_OK;
372  }
373  snprintf(type_text, sizeof(type_text), "%c%zu%s",
374  input_float ? 'f' : input_signed ? 'i' : 'u',
375  input_unitsize * 8, input_bigendian ? "be" : "le");
376  sr_err("Unsupported type for analog-to-float conversion: %s.",
377  type_text);
378  return SR_ERR;
379 }
380 
381 /**
382  * Scale a float value to the appropriate SI prefix.
383  *
384  * @param[in,out] value The float value to convert to appropriate SI prefix.
385  * @param[in,out] digits The number of significant decimal digits in value.
386  *
387  * @return The SI prefix to which value was scaled, as a printable string.
388  *
389  * @since 0.5.0
390  */
391 SR_API const char *sr_analog_si_prefix(float *value, int *digits)
392 {
393 /** @cond PRIVATE */
394 #define NEG_PREFIX_COUNT 5 /* number of prefixes below unity */
395 #define POS_PREFIX_COUNT (int)(ARRAY_SIZE(prefixes) - NEG_PREFIX_COUNT - 1)
396 /** @endcond */
397  static const char *prefixes[] = { "f", "p", "n", "µ", "m", "", "k", "M", "G", "T" };
398 
399  if (!value || !digits || isnan(*value))
400  return prefixes[NEG_PREFIX_COUNT];
401 
402  float logval = log10f(fabsf(*value));
403  int prefix = (logval / 3) - (logval < 1);
404 
405  if (prefix < -NEG_PREFIX_COUNT)
406  prefix = -NEG_PREFIX_COUNT;
407  if (3 * prefix < -*digits)
408  prefix = (-*digits + 2 * (*digits < 0)) / 3;
409  if (prefix > POS_PREFIX_COUNT)
410  prefix = POS_PREFIX_COUNT;
411 
412  *value *= powf(10, -3 * prefix);
413  *digits += 3 * prefix;
414 
415  return prefixes[prefix + NEG_PREFIX_COUNT];
416 }
417 
418 /**
419  * Check if a unit "accepts" an SI prefix.
420  *
421  * E.g. SR_UNIT_VOLT is SI prefix friendly while SR_UNIT_DECIBEL_MW or
422  * SR_UNIT_PERCENTAGE are not.
423  *
424  * @param[in] unit The unit to check for SI prefix "friendliness".
425  *
426  * @return TRUE if the unit "accept" an SI prefix.
427  *
428  * @since 0.5.0
429  */
431 {
432  static const enum sr_unit prefix_friendly_units[] = {
433  SR_UNIT_VOLT,
435  SR_UNIT_OHM,
442  SR_UNIT_WATT,
447  };
448  unsigned int i;
449 
450  for (i = 0; i < ARRAY_SIZE(prefix_friendly_units); i++)
451  if (unit == prefix_friendly_units[i])
452  return TRUE;
453 
454  return FALSE;
455 }
456 
457 /**
458  * Convert the unit/MQ/MQ flags in the analog struct to a string.
459  *
460  * The string is allocated by the function and must be freed by the caller
461  * after use by calling g_free().
462  *
463  * @param[in] analog Struct containing the unit, MQ and MQ flags.
464  * Must not be NULL. analog->meaning must not be NULL.
465  * @param[out] result Pointer to store result. Must not be NULL.
466  *
467  * @retval SR_OK Success.
468  * @retval SR_ERR_ARG Invalid argument.
469  *
470  * @since 0.4.0
471  */
473  char **result)
474 {
475  int i;
476  GString *buf;
477 
478  if (!analog || !(analog->meaning) || !result)
479  return SR_ERR_ARG;
480 
481  buf = g_string_new(NULL);
482 
483  for (i = 0; unit_strings[i].value; i++) {
484  if (analog->meaning->unit == unit_strings[i].value) {
485  g_string_assign(buf, unit_strings[i].str);
486  break;
487  }
488  }
489 
490  /* More than one MQ flag may apply. */
491  for (i = 0; mq_strings[i].value; i++)
492  if (analog->meaning->mqflags & mq_strings[i].value)
493  g_string_append(buf, mq_strings[i].str);
494 
495  *result = g_string_free(buf, FALSE);
496 
497  return SR_OK;
498 }
499 
500 /**
501  * Set sr_rational r to the given value.
502  *
503  * @param[out] r Rational number struct to set. Must not be NULL.
504  * @param[in] p Numerator.
505  * @param[in] q Denominator.
506  *
507  * @since 0.4.0
508  */
509 SR_API void sr_rational_set(struct sr_rational *r, int64_t p, uint64_t q)
510 {
511  if (!r)
512  return;
513 
514  r->p = p;
515  r->q = q;
516 }
517 
518 #ifndef HAVE___INT128_T
519 struct sr_int128_t {
520  int64_t high;
521  uint64_t low;
522 };
523 
524 struct sr_uint128_t {
525  uint64_t high;
526  uint64_t low;
527 };
528 
529 static void mult_int64(struct sr_int128_t *res, const int64_t a,
530  const int64_t b)
531 {
532  uint64_t t1, t2, t3, t4;
533 
534  t1 = (UINT32_MAX & a) * (UINT32_MAX & b);
535  t2 = (UINT32_MAX & a) * (b >> 32);
536  t3 = (a >> 32) * (UINT32_MAX & b);
537  t4 = (a >> 32) * (b >> 32);
538 
539  res->low = t1 + (t2 << 32) + (t3 << 32);
540  res->high = (t1 >> 32) + (uint64_t)((uint32_t)(t2)) + (uint64_t)((uint32_t)(t3));
541  res->high >>= 32;
542  res->high += ((int64_t)t2 >> 32) + ((int64_t)t3 >> 32) + t4;
543 }
544 
545 static void mult_uint64(struct sr_uint128_t *res, const uint64_t a,
546  const uint64_t b)
547 {
548  uint64_t t1, t2, t3, t4;
549 
550  // (x1 + x2) * (y1 + y2) = x1*y1 + x1*y2 + x2*y1 + x2*y2
551  t1 = (UINT32_MAX & a) * (UINT32_MAX & b);
552  t2 = (UINT32_MAX & a) * (b >> 32);
553  t3 = (a >> 32) * (UINT32_MAX & b);
554  t4 = (a >> 32) * (b >> 32);
555 
556  res->low = t1 + (t2 << 32) + (t3 << 32);
557  res->high = (t1 >> 32) + (uint64_t)((uint32_t)(t2)) + (uint64_t)((uint32_t)(t3));
558  res->high >>= 32;
559  res->high += ((int64_t)t2 >> 32) + ((int64_t)t3 >> 32) + t4;
560 }
561 #endif
562 
563 /**
564  * Compare two sr_rational for equality.
565  *
566  * The values are compared for numerical equality, i.e. 2/10 == 1/5.
567  *
568  * @param[in] a First value.
569  * @param[in] b Second value.
570  *
571  * @retval 1 if both values are equal.
572  * @retval 0 Otherwise.
573  *
574  * @since 0.5.0
575  */
576 SR_API int sr_rational_eq(const struct sr_rational *a, const struct sr_rational *b)
577 {
578 #ifdef HAVE___INT128_T
579  __int128_t m1, m2;
580 
581  /* p1/q1 = p2/q2 <=> p1*q2 = p2*q1 */
582  m1 = ((__int128_t)(b->p)) * ((__uint128_t)a->q);
583  m2 = ((__int128_t)(a->p)) * ((__uint128_t)b->q);
584 
585  return (m1 == m2);
586 
587 #else
588  struct sr_int128_t m1, m2;
589 
590  mult_int64(&m1, a->q, b->p);
591  mult_int64(&m2, a->p, b->q);
592 
593  return (m1.high == m2.high) && (m1.low == m2.low);
594 #endif
595 }
596 
597 /**
598  * Multiply two sr_rational.
599  *
600  * The resulting nominator/denominator are reduced if the result would not fit
601  * otherwise. If the resulting nominator/denominator are relatively prime,
602  * this may not be possible.
603  *
604  * It is safe to use the same variable for result and input values.
605  *
606  * @param[in] a First value.
607  * @param[in] b Second value.
608  * @param[out] res Result.
609  *
610  * @retval SR_OK Success.
611  * @retval SR_ERR_ARG Resulting value too large.
612  *
613  * @since 0.5.0
614  */
615 SR_API int sr_rational_mult(struct sr_rational *res, const struct sr_rational *a,
616  const struct sr_rational *b)
617 {
618 #ifdef HAVE___INT128_T
619  __int128_t p;
620  __uint128_t q;
621 
622  p = (__int128_t)(a->p) * (__int128_t)(b->p);
623  q = (__uint128_t)(a->q) * (__uint128_t)(b->q);
624 
625  if ((p > INT64_MAX) || (p < INT64_MIN) || (q > UINT64_MAX)) {
626  while (!((p & 1) || (q & 1))) {
627  p /= 2;
628  q /= 2;
629  }
630  }
631 
632  if ((p > INT64_MAX) || (p < INT64_MIN) || (q > UINT64_MAX)) {
633  // TODO: determine gcd to do further reduction
634  return SR_ERR_ARG;
635  }
636 
637  res->p = (int64_t)p;
638  res->q = (uint64_t)q;
639 
640  return SR_OK;
641 
642 #else
643  struct sr_int128_t p;
644  struct sr_uint128_t q;
645 
646  mult_int64(&p, a->p, b->p);
647  mult_uint64(&q, a->q, b->q);
648 
649  while (!(p.low & 1) && !(q.low & 1)) {
650  p.low /= 2;
651  if (p.high & 1)
652  p.low |= (1ll << 63);
653  p.high >>= 1;
654  q.low /= 2;
655  if (q.high & 1)
656  q.low |= (1ll << 63);
657  q.high >>= 1;
658  }
659 
660  if (q.high)
661  return SR_ERR_ARG;
662  if ((p.high >= 0) && (p.low > INT64_MAX))
663  return SR_ERR_ARG;
664  if (p.high < -1)
665  return SR_ERR_ARG;
666 
667  res->p = (int64_t)p.low;
668  res->q = q.low;
669 
670  return SR_OK;
671 #endif
672 }
673 
674 /**
675  * Divide rational a by rational b.
676  *
677  * The resulting nominator/denominator are reduced if the result would not fit
678  * otherwise. If the resulting nominator/denominator are relatively prime,
679  * this may not be possible.
680  *
681  * It is safe to use the same variable for result and input values.
682  *
683  * @param[in] num Numerator.
684  * @param[in] div Divisor.
685  * @param[out] res Result.
686  *
687  * @retval SR_OK Success.
688  * @retval SR_ERR_ARG Division by zero, denominator of divisor too large,
689  * or resulting value too large.
690  *
691  * @since 0.5.0
692  */
693 SR_API int sr_rational_div(struct sr_rational *res, const struct sr_rational *num,
694  const struct sr_rational *div)
695 {
696  struct sr_rational t;
697 
698  if (div->q > INT64_MAX)
699  return SR_ERR_ARG;
700  if (div->p == 0)
701  return SR_ERR_ARG;
702 
703  if (div->p > 0) {
704  t.p = div->q;
705  t.q = div->p;
706  } else {
707  t.p = -div->q;
708  t.q = -div->p;
709  }
710 
711  return sr_rational_mult(res, num, &t);
712 }
713 
714 /** @} */
Sound pressure level, in decibels, relative to 20 micropascals.
Definition: libsigrok.h:292
Pressure in hectopascal.
Definition: libsigrok.h:310
Device is in "min" mode, only updating upon a new min value.
Definition: libsigrok.h:367
Mass in tola.
Definition: libsigrok.h:336
Device is in "max" mode, only updating upon a new max value.
Definition: libsigrok.h:365
struct sr_analog_encoding * encoding
Definition: libsigrok.h:521
GSList * channels
Definition: libsigrok.h:559
Percent value.
Definition: libsigrok.h:271
int sr_analog_to_float(const struct sr_datafeed_analog *analog, float *outbuf)
Convert an analog datafeed payload to an array of floats.
Definition: analog.c:177
Ampere (current).
Definition: libsigrok.h:257
No error.
Definition: libsigrok.h:67
int8_t digits
Number of significant digits after the decimal point, if positive.
Definition: libsigrok.h:549
Mass in pound [lb].
Definition: libsigrok.h:326
Sound pressure level is time-averaged (LAT), also known as Equivalent Continuous A-weighted Sound Lev...
Definition: libsigrok.h:392
enum sr_unit unit
Definition: libsigrok.h:557
Volt.
Definition: libsigrok.h:255
Ohm (resistance).
Definition: libsigrok.h:259
Real power [W].
Definition: libsigrok.h:304
Device is in relative mode.
Definition: libsigrok.h:371
int sr_rational_div(struct sr_rational *res, const struct sr_rational *num, const struct sr_rational *div)
Divide rational a by rational b.
Definition: analog.c:693
Mass in grain [gr].
Definition: libsigrok.h:330
Sound pressure level represented as a percentage of measurements that were over a preset alarm level...
Definition: libsigrok.h:395
#define SR_API
Definition: libsigrok.h:128
struct sr_rational offset
Definition: libsigrok.h:552
Boolean value.
Definition: libsigrok.h:273
Voltage in decibel, referenced to 1 volt (dBV).
Definition: libsigrok.h:284
Mass in carat [ct].
Definition: libsigrok.h:320
int64_t p
Numerator of the rational number.
Definition: libsigrok.h:488
Measurements that intrinsically do not have units attached, such as ratios, gains, etc.
Definition: libsigrok.h:290
Device is in "avg" mode, averaging upon each new value.
Definition: libsigrok.h:399
Device is in autoranging mode.
Definition: libsigrok.h:369
struct sr_rational scale
Definition: libsigrok.h:551
int sr_analog_unit_to_string(const struct sr_datafeed_analog *analog, char **result)
Convert the unit/MQ/MQ flags in the analog struct to a string.
Definition: analog.c:472
gboolean sr_analog_si_prefix_friendly(enum sr_unit unit)
Check if a unit "accepts" an SI prefix.
Definition: analog.c:430
Mass in troy ounce [oz t].
Definition: libsigrok.h:324
Mass in pennyweight [dwt].
Definition: libsigrok.h:328
Normalized (0 to 1) concentration of a substance or compound with 0 representing a concentration of 0...
Definition: libsigrok.h:298
gboolean is_float
Definition: libsigrok.h:529
Measurement is four wire (e.g.
Definition: libsigrok.h:405
sr_unit
Unit of measured quantity, sr_analog_meaning.unit.
Definition: libsigrok.h:253
Revolutions per minute.
Definition: libsigrok.h:300
Plane angle in 1/360th of a full circle.
Definition: libsigrok.h:314
Mass in ounce [oz].
Definition: libsigrok.h:322
Analog datafeed payload for type SR_DF_ANALOG.
Definition: libsigrok.h:518
Electric charge in coulomb.
Definition: libsigrok.h:342
Sound pressure level is Z-weighted (i.e.
Definition: libsigrok.h:380
int sr_rational_mult(struct sr_rational *res, const struct sr_rational *a, const struct sr_rational *b)
Multiply two sr_rational.
Definition: analog.c:615
Generic/unspecified error.
Definition: libsigrok.h:68
gboolean is_bigendian
Definition: libsigrok.h:530
struct sr_analog_meaning * meaning
Definition: libsigrok.h:522
An absolute measurement of power, in decibels, referenced to 1 milliwatt (dBm).
Definition: libsigrok.h:282
Pieces (number of items).
Definition: libsigrok.h:338
gboolean is_digits_decimal
Definition: libsigrok.h:550
Reference value shown.
Definition: libsigrok.h:401
Sound pressure level is not weighted in the frequency domain, albeit without standards-defined low an...
Definition: libsigrok.h:383
Value is voltage drop across a diode, or NAN.
Definition: libsigrok.h:361
void sr_rational_set(struct sr_rational *r, int64_t p, uint64_t q)
Set sr_rational r to the given value.
Definition: analog.c:509
Unit of conductance, the inverse of resistance.
Definition: libsigrok.h:277
Apparent power [VA].
Definition: libsigrok.h:302
int8_t spec_digits
Number of significant digits after the decimal point, if positive.
Definition: libsigrok.h:581
struct sr_analog_spec * spec
Definition: libsigrok.h:523
Time in seconds.
Definition: libsigrok.h:275
Voltage measurement is alternating current (AC).
Definition: libsigrok.h:355
Sound pressure level measurement is S-weighted (1s) in the time domain.
Definition: libsigrok.h:386
Henry (inductance).
Definition: libsigrok.h:316
Electric charge in ampere hour [Ah].
Definition: libsigrok.h:344
gboolean is_signed
Definition: libsigrok.h:528
Mass in gram [g].
Definition: libsigrok.h:318
uint64_t q
Denominator of the rational number.
Definition: libsigrok.h:490
Unstable value (hasn&#39;t settled yet).
Definition: libsigrok.h:403
Device is in "hold" mode (repeating the last measurement).
Definition: libsigrok.h:363
Function argument error.
Definition: libsigrok.h:70
Sound pressure level is C-weighted in the frequency domain, according to IEC 61672:2003.
Definition: libsigrok.h:377
Time is duration (as opposed to epoch, ...).
Definition: libsigrok.h:397
Voltage measurement is direct current (DC).
Definition: libsigrok.h:357
const char * sr_analog_si_prefix(float *value, int *digits)
Scale a float value to the appropriate SI prefix.
Definition: analog.c:391
Sound pressure level is A-weighted in the frequency domain, according to IEC 61672:2003.
Definition: libsigrok.h:374
The public libsigrok header file to be used by frontends.
Mass in tael (variants: Hong Kong, Singapore/Malaysia, Taiwan)
Definition: libsigrok.h:332
Energy (consumption) in watt hour [Wh].
Definition: libsigrok.h:306
This is a true RMS measurement.
Definition: libsigrok.h:359
#define SR_PRIV
Definition: libsigrok.h:135
Hertz (frequency, 1/s, [Hz]).
Definition: libsigrok.h:269
Sound pressure level measurement is F-weighted (125ms) in the time domain.
Definition: libsigrok.h:389
Wind speed in meters per second.
Definition: libsigrok.h:308
Kelvin (temperature).
Definition: libsigrok.h:263
Farad (capacity).
Definition: libsigrok.h:261
Degrees Celsius (temperature).
Definition: libsigrok.h:265
Energy in joule.
Definition: libsigrok.h:340
Relative humidity assuming air temperature of 293 Kelvin (rF).
Definition: libsigrok.h:312
enum sr_mqflag mqflags
Definition: libsigrok.h:558
uint32_t num_samples
Definition: libsigrok.h:520
Mass in momme.
Definition: libsigrok.h:334
Degrees Fahrenheit (temperature).
Definition: libsigrok.h:267
int sr_rational_eq(const struct sr_rational *a, const struct sr_rational *b)
Compare two sr_rational for equality.
Definition: analog.c:576