Browse Source

Merge pull request #4668 from haukepetersen/add_phydat_ffp

sys/phydat: dump function can handle fixed floating points
pr/gpio
Cenk Gündoğan 7 years ago
parent
commit
ed208c2da8
  1. 76
      sys/fmt/fmt.c
  2. 55
      sys/include/fmt.h
  3. 4
      sys/include/phydat.h
  4. 54
      sys/phydat/phydat_str.c
  5. 91
      tests/unittests/tests-fmt/tests-fmt.c

76
sys/fmt/fmt.c

@ -1,15 +1,20 @@
/**
/*
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
*
* 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_fmt
*/
/**
* @ingroup sys_fmt
* @{
*
* @file
* @brief String formatting library implementation
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @brief String formatting library implementation
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*
* @}
*/
@ -34,6 +39,17 @@ static inline int _is_digit(char c)
return (c >= '0' && c <= '9');
}
static inline unsigned pwr(unsigned val, unsigned exp)
{
unsigned res = 1;
for (unsigned i = 0; i < exp; i++) {
res *= val;
}
return res;
}
size_t fmt_byte_hex(char *out, uint8_t byte)
{
if (out) {
@ -122,6 +138,56 @@ size_t fmt_s32_dec(char *out, int32_t val)
return fmt_u32_dec(out, val) + negative;
}
size_t fmt_s16_dec(char *out, int16_t val)
{
return fmt_s32_dec(out, val);
}
size_t fmt_s16_dfp(char *out, int16_t val, unsigned fp_digits)
{
int16_t absolute, divider;
size_t pos = 0;
size_t div_len, len;
unsigned e;
char tmp[4];
if (fp_digits > 4) {
return 0;
}
if (fp_digits == 0) {
return fmt_s16_dec(out, val);
}
if (val < 0) {
if (out) {
out[pos++] = '-';
}
val *= -1;
}
e = pwr(10, fp_digits);
absolute = (val / (int)e);
divider = val - (absolute * e);
pos += fmt_s16_dec(&out[pos], absolute);
if (!out) {
return pos + 1 + fp_digits; /* abs len + decimal point + divider */
}
out[pos++] = '.';
len = pos + fp_digits;
div_len = fmt_s16_dec(tmp, divider);
while (pos < (len - div_len)) {
out[pos++] = '0';
}
for (size_t i = 0; i < div_len; i++) {
out[pos++] = tmp[i];
}
return pos;
}
uint32_t scn_u32_dec(const char *str, size_t n)
{
uint32_t res = 0;

55
sys/include/fmt.h

@ -7,14 +7,16 @@
*/
/**
* @defgroup sys_fmt string formatting
* @ingroup sys
* @brief Provides simple string formatting functions
* @defgroup sys_fmt string formatting
* @ingroup sys
* @brief Provides simple string formatting functions
*
* @{
*
* @file
* @brief string formatting API
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @brief String formatting API
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
#ifndef FMT_H_
@ -127,6 +129,49 @@ size_t fmt_u16_dec(char *out, uint16_t val);
*/
size_t fmt_s32_dec(char *out, int32_t val);
/**
* @brief Convert a int16 value to decimal string.
*
* Will add a leading "-" if @p val is negative.
*
* If @p out is NULL, will only return the number of bytes that would have
* been written.
*
* @param[out] out Pointer to output buffer, or NULL
* @param[in] val Value to convert
*
* @return nr of characters written to (or needed in) @p out
*/
size_t fmt_s16_dec(char *out, int16_t val);
/**
* @brief Convert 16-bit fixed point number to a decimal string
*
* The input for this function is a signed 16-bit integer holding the fixed
* point value as well as an unsigned integer defining the position of the
* decimal point, so this value defines the number of decimal digits after the
* decimal point.
*
* The resulting string will always be patted with zeros after the decimal point.
*
* For example: if @p val is -3548 and @p fp_digits is 2, the resulting string
* will be "-35.48". For @p val := 12010 and @p fp_digits := 3 the result will
* be "12.010".
*
* Will add a leading "-" if @p val is negative.
*
* If @p out is NULL, will only return the number of bytes that would have
* been written.
*
* @param[out] out Pointer to the output buffer, or NULL
* @param[in] val Fixed point value, MUST be <= 4
* @param[in] fp_digits Number of digits after the decimal point
*
* @return Length of the resulting string
* @return 0 if @p fp_digits is > 4
*/
size_t fmt_s16_dfp(char *out, int16_t val, unsigned fp_digits);
/**
* @brief Count characters until '\0' (exclusive) in @p str
*

4
sys/include/phydat.h

@ -162,10 +162,8 @@ const char *phydat_unit_to_str(uint8_t unit);
* etc) otherwise.
*
* @param[in] scale scale factor to convert
* @param[in] str buffer to write the result into, MUST be at least of
* length @p PHYDAT_SCALE_STR_MAXLEN
*/
void phydat_scale_to_str(int8_t scale, char *str);
char phydat_scale_to_str(int8_t scale);
#ifdef __cplusplus
}

54
sys/phydat/phydat_str.c

@ -32,10 +32,27 @@ void phydat_dump(phydat_t *data, uint8_t dim)
}
printf("Data:");
for (uint8_t i = 0; i < dim; i++) {
char tmp[PHYDAT_SCALE_STR_MAXLEN];
phydat_scale_to_str(data->scale, tmp);
printf("\t[%i] %i%s%s\n", (int)i, (int)data->val[i], tmp,
phydat_unit_to_str(data->unit));
char scale_str = phydat_scale_to_str(data->scale);
printf("\t[%i] ", (int)i);
if (scale_str) {
printf("%i%c", (int)data->val[i], scale_str);
}
else if (data->scale == 0) {
printf("%i", (int)data->val[i]);
}
else if ((data->scale > -5) && (data->scale < 0)) {
char num[8];
size_t len = fmt_s16_dfp(num, data->val[i], data->scale * -1);
num[len] = '\0';
printf("%s", num);
}
else {
printf("%iE%i", (int)data->val[i], (int)data->scale);
}
printf("%s\n", phydat_unit_to_str(data->unit));
}
}
@ -55,27 +72,24 @@ const char *phydat_unit_to_str(uint8_t unit)
case UNIT_BAR: return "Bar";
case UNIT_PA: return "Pa";
case UNIT_CD: return "cd";
case UNIT_PERCENT: return "%";
default: return "";
}
}
void phydat_scale_to_str(int8_t scale, char *str)
char phydat_scale_to_str(int8_t scale)
{
switch (scale) {
case 0: *str = '\0'; return;
case -3: *str = 'm'; break;
case -6: *str = 'u'; break;
case -9: *str = 'n'; break;
case -12: *str = 'p'; break;
case -15: *str = 'f'; break;
case 3: *str = 'k'; break;
case 6: *str = 'M'; break;
case 9: *str = 'G'; break;
case 12: *str = 'T'; break;
case 15: *str = 'P'; break;
default:
*str++ = 'E';
str += fmt_s32_dec(str, scale) -1;
case -3: return 'm';
case -6: return 'u';
case -9: return 'n';
case -12: return 'p';
case -15: return 'f';
case 3: return 'k';
case 6: return 'M';
case 9: return 'G';
case 12: return 'T';
case 15: return 'P';
default: return '\0';
}
*++str = '\0';
}

91
tests/unittests/tests-fmt/tests-fmt.c

@ -120,6 +120,95 @@ static void test_fmt_s32_dec(void)
TEST_ASSERT_EQUAL_STRING("-9876", (char *) out);
}
static void test_rmt_s16_dec(void)
{
char out[7] = "-------";
int16_t val;
size_t len;
val = 0;
len = fmt_s16_dec(out, val);
out[len] = '\0';
TEST_ASSERT_EQUAL_INT(1, len);
TEST_ASSERT_EQUAL_STRING("0", (char *)out);
val = -32000;
len = fmt_s16_dec(out, val);
out[len] = '\0';
TEST_ASSERT_EQUAL_INT(6, len);
TEST_ASSERT_EQUAL_STRING("-32000", (char *)out);
val = 12345;
len = fmt_s16_dec(out, val);
out[len] = '\0';
TEST_ASSERT_EQUAL_INT(5, len);
TEST_ASSERT_EQUAL_STRING("12345", (char *)out);
}
static void test_rmt_s16_dfp(void)
{
char out[8] = "--------";
int16_t val;
unsigned fpp;
size_t len;
val = 0;
fpp = 3;
len = fmt_s16_dfp(out, val, fpp);
out[len] = '\0';
TEST_ASSERT_EQUAL_INT(5, len);
TEST_ASSERT_EQUAL_STRING("0.000", (char *)out);
val = 12345;
fpp = 4;
len = fmt_s16_dfp(out, val, fpp);
out[len] = '\0';
TEST_ASSERT_EQUAL_INT(6, len);
TEST_ASSERT_EQUAL_STRING("1.2345", (char *)out);
val = 12030;
fpp = 3;
len = fmt_s16_dfp(out, val, fpp);
out[len] = '\0';
TEST_ASSERT_EQUAL_INT(6, len);
TEST_ASSERT_EQUAL_STRING("12.030", (char *)out);
val = -3548;
fpp = 2;
len = fmt_s16_dfp(out, val, fpp);
out[len] = '\0';
TEST_ASSERT_EQUAL_INT(6, len);
TEST_ASSERT_EQUAL_STRING("-35.48", (char *)out);
val = -23;
fpp = 4;
len = fmt_s16_dfp(out, val, fpp);
out[len] = '\0';
TEST_ASSERT_EQUAL_INT(7, len);
TEST_ASSERT_EQUAL_STRING("-0.0023", (char *)out);
val = 50;
fpp = 3;
len = fmt_s16_dfp(out, val, fpp);
out[len] = '\0';
TEST_ASSERT_EQUAL_INT(5, len);
TEST_ASSERT_EQUAL_STRING("0.050", (char *)out);
val = -12345;
fpp = 0;
len = fmt_s16_dfp(out, val, fpp);
out[len] = '\0';
TEST_ASSERT_EQUAL_INT(6, len);
TEST_ASSERT_EQUAL_STRING("-12345", (char *)out);
val = 31987;
fpp = 5;
len = fmt_s16_dfp(out, val, fpp);
out[len] = '\0';
TEST_ASSERT_EQUAL_INT(0, len);
TEST_ASSERT_EQUAL_STRING("", (char *)out);
}
static void test_fmt_strlen(void)
{
const char *empty_str = "";
@ -160,6 +249,8 @@ Test *tests_fmt_tests(void)
new_TestFixture(test_fmt_u32_dec),
new_TestFixture(test_fmt_u16_dec),
new_TestFixture(test_fmt_s32_dec),
new_TestFixture(test_rmt_s16_dec),
new_TestFixture(test_rmt_s16_dfp),
new_TestFixture(test_fmt_strlen),
new_TestFixture(test_fmt_str),
new_TestFixture(test_scn_u32_dec),

Loading…
Cancel
Save