Skip to content
Snippets Groups Projects
Commit 63f49f22 authored by Joakim Nohlgård's avatar Joakim Nohlgård
Browse files

sys/phydat: Add phydat_fit

Fits larger values into the 16 bit integers used by phydat and update
scale accordingly.
parent 0f19bdd8
No related branches found
No related tags found
No related merge requests found
...@@ -543,6 +543,10 @@ ifneq (,$(filter xtimer,$(USEMODULE))) ...@@ -543,6 +543,10 @@ ifneq (,$(filter xtimer,$(USEMODULE)))
USEMODULE += div USEMODULE += div
endif endif
ifneq (,$(filter saul,$(USEMODULE)))
USEMODULE += phydat
endif
ifneq (,$(filter saul_reg,$(USEMODULE))) ifneq (,$(filter saul_reg,$(USEMODULE)))
USEMODULE += saul USEMODULE += saul
endif endif
......
...@@ -178,6 +178,40 @@ const char *phydat_unit_to_str(uint8_t unit); ...@@ -178,6 +178,40 @@ const char *phydat_unit_to_str(uint8_t unit);
*/ */
char phydat_prefix_from_scale(int8_t scale); char phydat_prefix_from_scale(int8_t scale);
/**
* @brief Scale an integer value to fit into a @ref phydat_t
*
* Insert @p value at position @p index in the given @p dat while rescaling all
* numbers in @p dat->val so that @p value fits inside the limits of the data
* type, [@ref PHYDAT_MIN, @ref PHYDAT_MAX], and update the stored scale factor.
* The result will be rounded towards zero (the standard C99 integer division
* behaviour).
* The final parameter @p prescale can be used to chain multiple calls to
* this function in order to fit multidimensional values into the same phydat_t.
*
* The code example below shows how to chain multiple calls via the @p prescale parameter
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
* long val0 = 100000;
* long val1 = 2000000;
* long val2 = 30000000;
* phydat_t dat;
* dat.scale = 0;
* phydat_fit(&dat, val0, 0, phydat_fit(&dat, val1, 1, phydat_fit(&dat, val2, 2, 0)));
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* The prescale scaling is only applied to @p value, the existing values in
* @p dat are only scaled if the prescaled @p value does not fit in phydat_t::val
*
* @param[in, out] dat the value will be written into this data array
* @param[in] value value to rescale
* @param[in] index place the value at this position in the phydat_t::val array
* @param[in] prescale start by scaling the value by this exponent
*
* @return scaling offset that was applied
*/
uint8_t phydat_fit(phydat_t *dat, long value, unsigned int index, uint8_t prescale);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
/*
* Copyright (C) 2018 Eistec AB
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup sys_phydat
* @{
*
* @file
* @brief Generic sensor/actuator data handling
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
*
* @}
*/
#include <stdint.h>
#include "phydat.h"
#define ENABLE_DEBUG 0
#include "debug.h"
uint8_t phydat_fit(phydat_t *dat, long value, unsigned int index, uint8_t prescale)
{
assert(index < (sizeof(dat->val) / sizeof(dat->val[0])));
uint8_t ret = prescale;
while (prescale > 0) {
value /= 10;
--prescale;
}
int8_t scale_offset = 0;
while ((value > PHYDAT_MAX) || (value < PHYDAT_MIN)) {
value /= 10;
for (unsigned int k = 0; k < (sizeof(dat->val) / sizeof(dat->val[0])); ++k) {
dat->val[k] /= 10;
}
++scale_offset;
}
dat->val[index] = value;
dat->scale += scale_offset;
ret += scale_offset;
return ret;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment