27 #include "libsigrok-internal.h"
30 #define LOG_PREFIX "analog"
47 struct unit_mq_string {
53 static struct unit_mq_string unit_strings[] = {
95 static struct unit_mq_string mq_strings[] = {
129 memset(analog, 0,
sizeof(*analog));
130 memset(encoding, 0,
sizeof(*encoding));
131 memset(meaning, 0,
sizeof(*meaning));
132 memset(spec, 0,
sizeof(*spec));
140 #ifdef WORDS_BIGENDIAN
145 encoding->
digits = digits;
178 unsigned int b, i, count;
181 if (!analog || !(analog->
data) || !(analog->
meaning)
187 #ifdef WORDS_BIGENDIAN
198 int8_t *data8 = (int8_t *)(analog->
data);
199 int16_t *data16 = (int16_t *)(analog->
data);
200 int32_t *data32 = (int32_t *)(analog->
data);
205 for (
unsigned int i = 0; i < count; i++) {
206 outbuf[i] = scale * data8[i];
210 for (
unsigned int i = 0; i < count; i++) {
211 outbuf[i] = scale * R8(data8 + i);
217 if (is_signed && is_bigendian) {
218 for (
unsigned int i = 0; i < count; i++) {
219 outbuf[i] = scale * RB16S(&data16[i]);
222 }
else if (is_bigendian) {
223 for (
unsigned int i = 0; i < count; i++) {
224 outbuf[i] = scale * RB16(&data16[i]);
227 }
else if (is_signed) {
228 for (
unsigned int i = 0; i < count; i++) {
229 outbuf[i] = scale * RL16S(&data16[i]);
233 for (
unsigned int i = 0; i < count; i++) {
234 outbuf[i] = scale * RL16(&data16[i]);
240 if (is_signed && is_bigendian) {
241 for (
unsigned int i = 0; i < count; i++) {
242 outbuf[i] = scale * RB32S(&data32[i]);
245 }
else if (is_bigendian) {
246 for (
unsigned int i = 0; i < count; i++) {
247 outbuf[i] = scale * RB32(&data32[i]);
250 }
else if (is_signed) {
251 for (
unsigned int i = 0; i < count; i++) {
252 outbuf[i] = scale * RL32S(&data32[i]);
256 for (
unsigned int i = 0; i < count; i++) {
257 outbuf[i] = scale * RL32(&data32[i]);
263 sr_err(
"Unsupported unit size '%d' for analog-to-float"
276 memcpy(outbuf, analog->
data, count *
sizeof(
float));
281 ((uint8_t *)outbuf)[i + b] =
311 #define NEG_PREFIX_COUNT 5
312 #define POS_PREFIX_COUNT (int)(ARRAY_SIZE(prefixes) - NEG_PREFIX_COUNT - 1)
314 static const char *prefixes[] = {
"f",
"p",
"n",
"µ",
"m",
"",
"k",
"M",
"G",
"T" };
316 if (!value || !digits || isnan(*value))
317 return prefixes[NEG_PREFIX_COUNT];
319 float logval = log10f(fabsf(*value));
320 int prefix = (logval / 3) - (logval < 1);
322 if (prefix < -NEG_PREFIX_COUNT)
323 prefix = -NEG_PREFIX_COUNT;
324 if (3 * prefix < -*digits)
325 prefix = (-*digits + 2 * (*digits < 0)) / 3;
326 if (prefix > POS_PREFIX_COUNT)
327 prefix = POS_PREFIX_COUNT;
329 *value *= powf(10, -3 * prefix);
330 *digits += 3 * prefix;
332 return prefixes[prefix + NEG_PREFIX_COUNT];
349 static const enum sr_unit prefix_friendly_units[] = {
367 for (i = 0; i < ARRAY_SIZE(prefix_friendly_units); i++)
368 if (unit == prefix_friendly_units[i])
371 if (unit != prefix_friendly_units[i])
398 if (!analog || !(analog->
meaning) || !result)
401 buf = g_string_new(NULL);
403 for (i = 0; unit_strings[i].value; i++) {
404 if (analog->
meaning->
unit == unit_strings[i].value) {
405 g_string_assign(buf, unit_strings[i].str);
411 for (i = 0; mq_strings[i].value; i++)
413 g_string_append(buf, mq_strings[i].str);
416 g_string_free(buf, FALSE);
439 #ifndef HAVE___INT128_T
445 struct sr_uint128_t {
450 static void mult_int64(
struct sr_int128_t *res,
const int64_t a,
453 uint64_t t1, t2, t3, t4;
455 t1 = (UINT32_MAX & a) * (UINT32_MAX & b);
456 t2 = (UINT32_MAX & a) * (b >> 32);
457 t3 = (a >> 32) * (UINT32_MAX & b);
458 t4 = (a >> 32) * (b >> 32);
460 res->low = t1 + (t2 << 32) + (t3 << 32);
461 res->high = (t1 >> 32) + (uint64_t)((uint32_t)(t2)) + (uint64_t)((uint32_t)(t3));
463 res->high += ((int64_t)t2 >> 32) + ((int64_t)t3 >> 32) + t4;
466 static void mult_uint64(
struct sr_uint128_t *res,
const uint64_t a,
469 uint64_t t1, t2, t3, t4;
472 t1 = (UINT32_MAX & a) * (UINT32_MAX & b);
473 t2 = (UINT32_MAX & a) * (b >> 32);
474 t3 = (a >> 32) * (UINT32_MAX & b);
475 t4 = (a >> 32) * (b >> 32);
477 res->low = t1 + (t2 << 32) + (t3 << 32);
478 res->high = (t1 >> 32) + (uint64_t)((uint32_t)(t2)) + (uint64_t)((uint32_t)(t3));
480 res->high += ((int64_t)t2 >> 32) + ((int64_t)t3 >> 32) + t4;
499 #ifdef HAVE___INT128_T
503 m1 = ((__int128_t)(b->
p)) * ((__uint128_t)a->
q);
504 m2 = ((__int128_t)(a->
p)) * ((__uint128_t)b->
q);
509 struct sr_int128_t m1, m2;
511 mult_int64(&m1, a->
q, b->
p);
512 mult_int64(&m2, a->
p, b->
q);
514 return (m1.high == m2.high) && (m1.low == m2.low);
539 #ifdef HAVE___INT128_T
543 p = (__int128_t)(a->
p) * (__int128_t)(b->
p);
544 q = (__uint128_t)(a->
q) * (__uint128_t)(b->
q);
546 if ((p > INT64_MAX) || (p < INT64_MIN) || (q > UINT64_MAX)) {
547 while (!((p & 1) || (q & 1))) {
553 if ((p > INT64_MAX) || (p < INT64_MIN) || (q > UINT64_MAX)) {
558 res->
p = (int64_t)(p);
559 res->
q = (uint64_t)(q);
564 struct sr_int128_t p;
565 struct sr_uint128_t q;
567 mult_int64(&p, a->
p, b->
p);
568 mult_uint64(&q, a->
q, b->
q);
570 while (!(p.low & 1) && !(q.low & 1)) {
573 p.low |= (1ll << 63);
577 q.low |= (1ll << 63);
583 if ((p.high >= 0) && (p.low > INT64_MAX))
588 res->
p = (int64_t)p.low;
620 if (div->
q > INT64_MAX)
Generic/unspecified error.
Time is duration (as opposed to epoch, ...).
Sound pressure level is not weighted in the frequency domain, albeit without standards-defined low an...
int sr_rational_eq(const struct sr_rational *a, const struct sr_rational *b)
Compare two sr_rational for equality.
Sound pressure level is A-weighted in the frequency domain, according to IEC 61672:2003.
const char * sr_analog_si_prefix(float *value, int *digits)
Scale a float value to the appropriate SI prefix.
Measurement is four wire (e.g.
Degrees Fahrenheit (temperature).
void sr_rational_set(struct sr_rational *r, int64_t p, uint64_t q)
Set sr_rational r to the given value.
This is a true RMS measurement.
Normalized (0 to 1) concentration of a substance or compound with 0 representing a concentration of 0...
Plane angle in 1/360th of a full circle.
Sound pressure level measurement is S-weighted (1s) in the time domain.
Unit of conductance, the inverse of resistance.
Sound pressure level measurement is F-weighted (125ms) in the time domain.
Degrees Celsius (temperature).
The public libsigrok header file to be used by frontends.
An absolute measurement of power, in decibels, referenced to 1 milliwatt (dBm).
Sound pressure level is time-averaged (LAT), also known as Equivalent Continuous A-weighted Sound Lev...
Device is in autoranging mode.
Pieces (number of items).
Sound pressure level is C-weighted in the frequency domain, according to IEC 61672:2003.
Mass in tael (variants: Hong Kong, Singapore/Malaysia, Taiwan)
struct sr_analog_encoding * encoding
Device is in "min" mode, only updating upon a new min value.
Sound pressure level represented as a percentage of measurements that were over a preset alarm level...
Voltage measurement is alternating current (AC).
int sr_analog_to_float(const struct sr_datafeed_analog *analog, float *outbuf)
Convert an analog datafeed payload to an array of floats.
Device is in "hold" mode (repeating the last measurement).
gboolean sr_analog_si_prefix_friendly(enum sr_unit unit)
Check if a unit "accepts" an SI prefix.
int8_t spec_digits
Number of significant digits after the decimal point if positive, or number of non-significant digits...
sr_unit
Unit of measured quantity, sr_analog_meaning.unit.
struct sr_analog_meaning * meaning
Hertz (frequency, 1/s, [Hz]).
gboolean is_digits_decimal
Device is in "avg" mode, averaging upon each new value.
Voltage measurement is direct current (DC).
struct sr_analog_spec * spec
uint64_t q
Denominator of the rational number.
int sr_rational_mult(struct sr_rational *res, const struct sr_rational *a, const struct sr_rational *b)
Multiply two sr_rational.
int sr_rational_div(struct sr_rational *res, const struct sr_rational *num, const struct sr_rational *div)
Divide rational a by rational b.
Mass in troy ounce [oz t].
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.
int64_t p
Numerator of the rational number.
Voltage in decibel, referenced to 1 volt (dBV).
Analog datafeed payload for type SR_DF_ANALOG.
struct sr_rational offset
Sound pressure level is Z-weighted (i.e.
Relative humidity assuming air temperature of 293 Kelvin (rF).
Value is voltage drop across a diode, or NAN.
Sound pressure level, in decibels, relative to 20 micropascals.
Mass in pennyweight [dwt].
Device is in "max" mode, only updating upon a new max value.
Device is in relative mode.
Wind speed in meters per second.
int8_t digits
Number of significant digits after the decimal point if positive, or number of non-significant digits...
Measurements that intrinsically do not have units attached, such as ratios, gains, etc.
Unstable value (hasn't settled yet).