analog.c: sr_analog_to_float(): Support for receiving double values.

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.
This commit is contained in:
Timo Kokkonen 2020-09-07 17:33:07 -07:00 committed by Gerhard Sittig
parent 505a55f789
commit f37f11ec6b
1 changed files with 30 additions and 8 deletions

View 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->unitsize == sizeof(float)) {
if (analog->encoding->scale.p != 1
|| analog->encoding->scale.q != 1)
outbuf[i] = (outbuf[i] * analog->encoding->scale.p) / analog->encoding->scale.q;
*conv_f = (*conv_f * analog->encoding->scale.p) / analog->encoding->scale.q;
float offset = ((float)analog->encoding->offset.p / (float)analog->encoding->offset.q);
outbuf[i] += offset;
*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;
}
}
}