diff --git a/sys/bcd/Makefile b/sys/bcd/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/sys/bcd/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/sys/bcd/bcd.c b/sys/bcd/bcd.c new file mode 100644 index 0000000000..3355cc1708 --- /dev/null +++ b/sys/bcd/bcd.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2025 ML!PA Consulting GmbH + * + * 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_bcd + * @{ + * + * @file + * @brief Library to de- and encode binary coded decimals + * + * @author Benjamin Valentin + * + * @} + */ + +#include "bcd.h" +#include +#include + +static inline uint8_t swap_nibbles(uint8_t b) +{ + return (b << 4) | (b >> 4); +} + +int bcd_buf_from_u32(uint32_t val, void *dst, size_t len) +{ + uint8_t *tgt = dst; + uint8_t hex = 0; + uint8_t idx = 0; + + memset(dst, 0, len); + len *= 2; + + do { + hex <<= 4; + hex += val % 10; + val /= 10; + if (++idx % 2 == 0) { + *tgt++ = swap_nibbles(hex); + hex = 0; + } + } while (val && idx <= len); + + if (idx > len) { + return -ENOBUFS; + } + + if (idx % 2) { + *tgt++ = hex; + } + + return (uintptr_t)tgt - (uintptr_t)dst; +} diff --git a/sys/include/bcd.h b/sys/include/bcd.h index 67b65f3a0a..5195c36d83 100644 --- a/sys/include/bcd.h +++ b/sys/include/bcd.h @@ -20,6 +20,7 @@ #ifndef BCD_H #define BCD_H +#include #include #ifdef __cplusplus @@ -52,6 +53,22 @@ static inline uint8_t bcd_to_byte(uint8_t bcd) return bcd - (6 * (bcd >> 4)); } +/** + * @brief Convert a decimal value into a BCD buffer. + * (This looks like the decimal integer value when printed as hex) + * + * This will e.g. turn the value 123 -> 0x123 (decimal: 291) + * + * @param[in] val Decimal value to print + * @param[out] dst Destination buffer + * @param[in] len Size of the destination buffer + * + * @return number of bytes written + * @return -ENOBUFS if @p dst is not large enough + * In that case the state of @p dst is undefined. + */ +int bcd_buf_from_u32(uint32_t val, void *dst, size_t len); + #ifdef __cplusplus } #endif