27 #include "libsigrok-internal.h" 30 #define LOG_PREFIX "analog" 47 struct unit_mq_string {
53 static struct unit_mq_string unit_strings[] = {
98 static struct unit_mq_string mq_strings[] = {
132 memset(analog, 0,
sizeof(*analog));
133 memset(encoding, 0,
sizeof(*encoding));
134 memset(meaning, 0,
sizeof(*meaning));
135 memset(spec, 0,
sizeof(*spec));
143 #ifdef WORDS_BIGENDIAN 148 encoding->
digits = digits;
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;
204 #ifdef WORDS_BIGENDIAN 205 host_bigendian = TRUE;
207 host_bigendian = FALSE;
223 data8 = analog->
data;
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) {
259 if (input_float && input_unitsize ==
sizeof(
float)) {
260 float (*reader)(
const uint8_t **p);
262 reader = read_fltbe_inc;
264 reader = read_fltle_inc;
266 value = reader(&data8);
273 if (input_float && input_unitsize ==
sizeof(
double)) {
274 double (*reader)(
const uint8_t **p);
276 reader = read_dblbe_inc;
278 reader = read_dblle_inc;
280 value = reader(&data8);
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.",
295 if (input_unitsize ==
sizeof(uint8_t) && input_signed) {
296 int8_t (*reader)(
const uint8_t **p);
297 reader = read_i8_inc;
299 value = reader(&data8);
306 if (input_unitsize ==
sizeof(uint8_t)) {
307 uint8_t (*reader)(
const uint8_t **p);
308 reader = read_u8_inc;
310 value = reader(&data8);
317 if (input_unitsize ==
sizeof(uint16_t) && input_signed) {
318 int16_t (*reader)(
const uint8_t **p);
320 reader = read_i16be_inc;
322 reader = read_i16le_inc;
324 value = reader(&data8);
331 if (input_unitsize ==
sizeof(uint16_t)) {
332 uint16_t (*reader)(
const uint8_t **p);
334 reader = read_u16be_inc;
336 reader = read_u16le_inc;
338 value = reader(&data8);
345 if (input_unitsize ==
sizeof(uint32_t) && input_signed) {
346 int32_t (*reader)(
const uint8_t **p);
348 reader = read_i32be_inc;
350 reader = read_i32le_inc;
352 value = reader(&data8);
359 if (input_unitsize ==
sizeof(uint32_t)) {
360 uint32_t (*reader)(
const uint8_t **p);
362 reader = read_u32be_inc;
364 reader = read_u32le_inc;
366 value = reader(&data8);
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.",
394 #define NEG_PREFIX_COUNT 5 395 #define POS_PREFIX_COUNT (int)(ARRAY_SIZE(prefixes) - NEG_PREFIX_COUNT - 1) 397 static const char *prefixes[] = {
"f",
"p",
"n",
"µ",
"m",
"",
"k",
"M",
"G",
"T" };
399 if (!value || !digits || isnan(*value))
400 return prefixes[NEG_PREFIX_COUNT];
402 float logval = log10f(fabsf(*value));
403 int prefix = (logval / 3) - (logval < 1);
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;
412 *value *= powf(10, -3 * prefix);
413 *digits += 3 * prefix;
415 return prefixes[prefix + NEG_PREFIX_COUNT];
432 static const enum sr_unit prefix_friendly_units[] = {
450 for (i = 0; i < ARRAY_SIZE(prefix_friendly_units); i++)
451 if (unit == prefix_friendly_units[i])
478 if (!analog || !(analog->
meaning) || !result)
481 buf = g_string_new(NULL);
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);
491 for (i = 0; mq_strings[i].value; i++)
493 g_string_append(buf, mq_strings[i].str);
495 *result = g_string_free(buf, FALSE);
518 #ifndef HAVE___INT128_T 524 struct sr_uint128_t {
529 static void mult_int64(
struct sr_int128_t *res,
const int64_t a,
532 uint64_t t1, t2, t3, t4;
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);
539 res->low = t1 + (t2 << 32) + (t3 << 32);
540 res->high = (t1 >> 32) + (uint64_t)((uint32_t)(t2)) + (uint64_t)((uint32_t)(t3));
542 res->high += ((int64_t)t2 >> 32) + ((int64_t)t3 >> 32) + t4;
545 static void mult_uint64(
struct sr_uint128_t *res,
const uint64_t a,
548 uint64_t t1, t2, t3, t4;
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);
556 res->low = t1 + (t2 << 32) + (t3 << 32);
557 res->high = (t1 >> 32) + (uint64_t)((uint32_t)(t2)) + (uint64_t)((uint32_t)(t3));
559 res->high += ((int64_t)t2 >> 32) + ((int64_t)t3 >> 32) + t4;
578 #ifdef HAVE___INT128_T 582 m1 = ((__int128_t)(b->
p)) * ((__uint128_t)a->
q);
583 m2 = ((__int128_t)(a->
p)) * ((__uint128_t)b->
q);
588 struct sr_int128_t m1, m2;
590 mult_int64(&m1, a->
q, b->
p);
591 mult_int64(&m2, a->
p, b->
q);
593 return (m1.high == m2.high) && (m1.low == m2.low);
618 #ifdef HAVE___INT128_T 622 p = (__int128_t)(a->
p) * (__int128_t)(b->
p);
623 q = (__uint128_t)(a->
q) * (__uint128_t)(b->
q);
625 if ((p > INT64_MAX) || (p < INT64_MIN) || (q > UINT64_MAX)) {
626 while (!((p & 1) || (q & 1))) {
632 if ((p > INT64_MAX) || (p < INT64_MIN) || (q > UINT64_MAX)) {
638 res->
q = (uint64_t)q;
643 struct sr_int128_t p;
644 struct sr_uint128_t q;
646 mult_int64(&p, a->
p, b->
p);
647 mult_uint64(&q, a->
q, b->
q);
649 while (!(p.low & 1) && !(q.low & 1)) {
652 p.low |= (1ll << 63);
656 q.low |= (1ll << 63);
662 if ((p.high >= 0) && (p.low > INT64_MAX))
667 res->
p = (int64_t)p.low;
698 if (div->
q > INT64_MAX)
Sound pressure level, in decibels, relative to 20 micropascals.
Device is in "min" mode, only updating upon a new min value.
Device is in "max" mode, only updating upon a new max value.
struct sr_analog_encoding * encoding
int sr_analog_to_float(const struct sr_datafeed_analog *analog, float *outbuf)
Convert an analog datafeed payload to an array of floats.
int8_t digits
Number of significant digits after the decimal point, if positive.
Sound pressure level is time-averaged (LAT), also known as Equivalent Continuous A-weighted Sound Lev...
Device is in relative mode.
int sr_rational_div(struct sr_rational *res, const struct sr_rational *num, const struct sr_rational *div)
Divide rational a by rational b.
Sound pressure level represented as a percentage of measurements that were over a preset alarm level...
struct sr_rational offset
Voltage in decibel, referenced to 1 volt (dBV).
int64_t p
Numerator of the rational number.
Measurements that intrinsically do not have units attached, such as ratios, gains, etc.
Device is in "avg" mode, averaging upon each new value.
Device is in autoranging mode.
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.
gboolean sr_analog_si_prefix_friendly(enum sr_unit unit)
Check if a unit "accepts" an SI prefix.
Mass in troy ounce [oz t].
Mass in pennyweight [dwt].
Normalized (0 to 1) concentration of a substance or compound with 0 representing a concentration of 0...
Measurement is four wire (e.g.
sr_unit
Unit of measured quantity, sr_analog_meaning.unit.
Plane angle in 1/360th of a full circle.
Analog datafeed payload for type SR_DF_ANALOG.
Electric charge in coulomb.
Sound pressure level is Z-weighted (i.e.
int sr_rational_mult(struct sr_rational *res, const struct sr_rational *a, const struct sr_rational *b)
Multiply two sr_rational.
Generic/unspecified error.
struct sr_analog_meaning * meaning
An absolute measurement of power, in decibels, referenced to 1 milliwatt (dBm).
Pieces (number of items).
gboolean is_digits_decimal
Sound pressure level is not weighted in the frequency domain, albeit without standards-defined low an...
Value is voltage drop across a diode, or NAN.
void sr_rational_set(struct sr_rational *r, int64_t p, uint64_t q)
Set sr_rational r to the given value.
Unit of conductance, the inverse of resistance.
int8_t spec_digits
Number of significant digits after the decimal point, if positive.
struct sr_analog_spec * spec
Voltage measurement is alternating current (AC).
Sound pressure level measurement is S-weighted (1s) in the time domain.
Electric charge in ampere hour [Ah].
uint64_t q
Denominator of the rational number.
Unstable value (hasn't settled yet).
Device is in "hold" mode (repeating the last measurement).
Sound pressure level is C-weighted in the frequency domain, according to IEC 61672:2003.
Time is duration (as opposed to epoch, ...).
Voltage measurement is direct current (DC).
const char * sr_analog_si_prefix(float *value, int *digits)
Scale a float value to the appropriate SI prefix.
Sound pressure level is A-weighted in the frequency domain, according to IEC 61672:2003.
The public libsigrok header file to be used by frontends.
Mass in tael (variants: Hong Kong, Singapore/Malaysia, Taiwan)
Energy (consumption) in watt hour [Wh].
This is a true RMS measurement.
Hertz (frequency, 1/s, [Hz]).
Sound pressure level measurement is F-weighted (125ms) in the time domain.
Wind speed in meters per second.
Degrees Celsius (temperature).
Relative humidity assuming air temperature of 293 Kelvin (rF).
Degrees Fahrenheit (temperature).
int sr_rational_eq(const struct sr_rational *a, const struct sr_rational *b)
Compare two sr_rational for equality.