analog.c: sr_analog_to_float(): Support for receiving double values.
authorTimo Kokkonen <tjko@iki.fi>
Tue, 8 Sep 2020 00:33:07 +0000 (17:33 -0700)
committerGerhard Sittig <gerhard.sittig@gmx.net>
Fri, 18 Sep 2020 14:42:37 +0000 (16:42 +0200)
Unbreak the conversion of input data in the floating point format when
the input data's format does not match the host's internal presentation,
thus grabbing raw data cannot be done.

Also accept the input data in double precision format which was not
supported before. Check for unsupported unit size values and emit an
error message similar to the integer code path.

This is motivated by bug #779 but does not resolve it. Adjusts common
conversion support, but sticks with single precision return data type
for API compatibility.

src/analog.c

index 2a8e8d9054cfdd8bc691bb2e5e95534a0c50c0c7..4ec724cfde488a0ae4a37a5c2ab0f0b414264da8 100644 (file)
@@ -179,6 +179,9 @@ SR_API int sr_analog_to_float(const struct sr_datafeed_analog *analog,
 {
        unsigned int b, count;
        gboolean bigendian;
+       uint8_t conv_buf[sizeof(double)];
+       float *conv_f = (float*)conv_buf;
+       double *conv_d = (double*)conv_buf;
 
        if (!analog || !(analog->data) || !(analog->meaning)
                        || !(analog->encoding) || !outbuf)
@@ -277,20 +280,39 @@ SR_API int sr_analog_to_float(const struct sr_datafeed_analog *analog,
                /* The data is already in the right format. */
                memcpy(outbuf, analog->data, count * sizeof(float));
        } else {
-               for (unsigned int i = 0; i < count; i += analog->encoding->unitsize) {
+               for (unsigned int i = 0; i < count; i++) {
                        for (b = 0; b < analog->encoding->unitsize; b++) {
                                if (analog->encoding->is_bigendian == bigendian)
-                                       ((uint8_t *)outbuf)[i + b] =
+                                       conv_buf[b] =
                                                ((uint8_t *)analog->data)[i * analog->encoding->unitsize + b];
                                else
-                                       ((uint8_t *)outbuf)[i + (analog->encoding->unitsize - b)] =
+                                       conv_buf[analog->encoding->unitsize - b - 1] =
                                                ((uint8_t *)analog->data)[i * analog->encoding->unitsize + b];
                        }
-                       if (analog->encoding->scale.p != 1
-                                       || analog->encoding->scale.q != 1)
-                               outbuf[i] = (outbuf[i] * analog->encoding->scale.p) / analog->encoding->scale.q;
-                       float offset = ((float)analog->encoding->offset.p / (float)analog->encoding->offset.q);
-                       outbuf[i] += offset;
+
+                       if (analog->encoding->unitsize == sizeof(float)) {
+                               if (analog->encoding->scale.p != 1
+                                   || analog->encoding->scale.q != 1)
+                                       *conv_f = (*conv_f * analog->encoding->scale.p) / analog->encoding->scale.q;
+                               float offset = ((float)analog->encoding->offset.p / (float)analog->encoding->offset.q);
+                               *conv_f += offset;
+
+                               outbuf[i] = *conv_f;
+                       }
+                       else if (analog->encoding->unitsize == sizeof(double)) {
+                               if (analog->encoding->scale.p != 1
+                                   || analog->encoding->scale.q != 1)
+                                       *conv_d = (*conv_d * analog->encoding->scale.p) / analog->encoding->scale.q;
+                               double offset = ((double)analog->encoding->offset.p / (double)analog->encoding->offset.q);
+                               *conv_d += offset;
+
+                               outbuf[i] = *conv_d;
+                       }
+                       else {
+                               sr_err("Unsupported floating-point unit size '%d' for analog-to-float"
+                                      " conversion.", analog->encoding->unitsize);
+                               return SR_ERR;
+                       }
                }
        }