/* ################################################################### ** This component module is generated by Processor Expert. Do not modify it. ** Filename : McuUtility.h ** Project : FRDM-K64F_Generator ** Processor : MK64FN1M0VLL12 ** Component : Utility ** Version : Component 01.171, Driver 01.00, CPU db: 3.00.000 ** Compiler : GNU C Compiler ** Date/Time : 2022-07-06, 11:44, # CodeGen: 778 ** Abstract : ** Contains various utility functions. ** Settings : ** Component name : McuUtility ** Contents : ** SkipSpaces - void McuUtility_SkipSpaces(const unsigned char **str); ** strcpy - void McuUtility_strcpy(uint8_t *dst, size_t dstSize, const unsigned char *src); ** strcat - void McuUtility_strcat(uint8_t *dst, size_t dstSize, const unsigned char *src); ** strcatPad - void McuUtility_strcatPad(uint8_t *dst, size_t dstSize, const unsigned char... ** chcat - void McuUtility_chcat(uint8_t *dst, size_t dstSize, uint8_t ch); ** Num8sToStr - void McuUtility_Num8sToStr(uint8_t *dst, size_t dstSize, signed char val); ** Num8uToStr - void McuUtility_Num8uToStr(uint8_t *dst, size_t dstSize, uint8_t val); ** Num16sToStr - void McuUtility_Num16sToStr(uint8_t *dst, size_t dstSize, int16_t val); ** Num16uToStr - void McuUtility_Num16uToStr(uint8_t *dst, size_t dstSize, uint16_t val); ** Num32uToStr - void McuUtility_Num32uToStr(uint8_t *dst, size_t dstSize, uint32_t val); ** Num32sToStr - void McuUtility_Num32sToStr(uint8_t *dst, size_t dstSize, int32_t val); ** NumFloatToStr - void McuUtility_NumFloatToStr(uint8_t *dst, size_t dstSize, float val,... ** Num16sToStrFormatted - void McuUtility_Num16sToStrFormatted(uint8_t *dst, size_t dstSize, int16_t... ** Num16uToStrFormatted - void McuUtility_Num16uToStrFormatted(uint8_t *dst, size_t dstSize, uint16_t... ** Num32uToStrFormatted - void McuUtility_Num32uToStrFormatted(uint8_t *dst, size_t dstSize, uint32_t... ** Num32sToStrFormatted - void McuUtility_Num32sToStrFormatted(uint8_t *dst, size_t dstSize, int32_t... ** strcatNum8u - void McuUtility_strcatNum8u(uint8_t *dst, size_t dstSize, uint8_t val); ** strcatNum8s - void McuUtility_strcatNum8s(uint8_t *dst, size_t dstSize, signed char val); ** strcatNum16u - void McuUtility_strcatNum16u(uint8_t *dst, size_t dstSize, uint16_t val); ** strcatNum16s - void McuUtility_strcatNum16s(uint8_t *dst, size_t dstSize, int16_t val); ** strcatNum32u - void McuUtility_strcatNum32u(uint8_t *dst, size_t dstSize, uint32_t val); ** strcatNum32s - void McuUtility_strcatNum32s(uint8_t *dst, size_t dstSize, int32_t val); ** strcatNum16uFormatted - void McuUtility_strcatNum16uFormatted(uint8_t *dst, size_t dstSize, uint16_t... ** strcatNum16sFormatted - void McuUtility_strcatNum16sFormatted(uint8_t *dst, size_t dstSize, int16_t... ** strcatNum32uFormatted - void McuUtility_strcatNum32uFormatted(uint8_t *dst, size_t dstSize, uint32_t... ** strcatNum32sFormatted - void McuUtility_strcatNum32sFormatted(uint8_t *dst, size_t dstSize, int32_t... ** strcatNumHex - void McuUtility_strcatNumHex(uint8_t *dst, size_t dstSize, uint32_t num,... ** strcatNum8Hex - void McuUtility_strcatNum8Hex(uint8_t *dst, size_t dstSize, uint8_t num); ** strcatNum16Hex - void McuUtility_strcatNum16Hex(uint8_t *dst, size_t dstSize, uint16_t num); ** strcatNum24Hex - void McuUtility_strcatNum24Hex(uint8_t *dst, size_t dstSize, uint32_t num); ** strcatNum32Hex - void McuUtility_strcatNum32Hex(uint8_t *dst, size_t dstSize, uint32_t num); ** strcatNum32sDotValue100 - void McuUtility_strcatNum32sDotValue100(uint8_t *dst, size_t dstSize, int32_t... ** strcatNumFloat - void McuUtility_strcatNumFloat(uint8_t *dst, size_t dstSize, float val,... ** IsLeapYear - bool McuUtility_IsLeapYear(uint16_t year); ** WeekDay - uint8_t McuUtility_WeekDay(uint16_t year, uint8_t month, uint8_t day); ** ReadEscapedName - uint8_t McuUtility_ReadEscapedName(const unsigned char *filename, uint8_t... ** xatoi - uint8_t McuUtility_xatoi(const unsigned char **str, int32_t *res); ** ScanDate - uint8_t McuUtility_ScanDate(const unsigned char **str, uint8_t *day, uint8_t... ** ScanTime - uint8_t McuUtility_ScanTime(const unsigned char **str, uint8_t *hour, uint8_t... ** ScanDecimal8uNumber - uint8_t McuUtility_ScanDecimal8uNumber(const unsigned char **str, uint8_t *val); ** ScanDecimal8sNumber - uint8_t McuUtility_ScanDecimal8sNumber(const unsigned char **str, signed char... ** ScanDecimal16uNumber - uint8_t McuUtility_ScanDecimal16uNumber(const unsigned char **str, uint16_t... ** ScanDecimal16sNumber - uint8_t McuUtility_ScanDecimal16sNumber(const unsigned char **str, int16_t... ** ScanDecimal32uNumber - uint8_t McuUtility_ScanDecimal32uNumber(const unsigned char **str, uint32_t... ** ScanDecimal32sNumber - uint8_t McuUtility_ScanDecimal32sNumber(const unsigned char **str, int32_t... ** ScanDecimal32sDotNumber - uint8_t McuUtility_ScanDecimal32sDotNumber(const unsigned char **str, int32_t... ** ScanHex8uNumber - uint8_t McuUtility_ScanHex8uNumber(const unsigned char **str, uint8_t *val); ** ScanHex8uNumberNoPrefix - uint8_t McuUtility_ScanHex8uNumberNoPrefix(const unsigned char **str, uint8_t... ** ScanHex16uNumber - uint8_t McuUtility_ScanHex16uNumber(const unsigned char **str, uint16_t *val); ** ScanHex32uNumber - uint8_t McuUtility_ScanHex32uNumber(const unsigned char **str, uint32_t *val); ** ScanSeparatedNumbers - uint8_t McuUtility_ScanSeparatedNumbers(const unsigned char **str, uint8_t... ** ScanDoubleQuotedString - uint8_t McuUtility_ScanDoubleQuotedString(const uint8_t **cmd, uint8_t *buf,... ** ScanRGB - uint8_t McuUtility_ScanRGB(const unsigned char **str, uint8_t *r, uint8_t *g,... ** ScanWRGB - uint8_t McuUtility_ScanWRGB(const unsigned char **str, uint8_t *w, uint8_t... ** ScanRGB32 - uint8_t McuUtility_ScanRGB32(const unsigned char **str, uint32_t *rgb); ** ScanWRGB32 - uint8_t McuUtility_ScanWRGB32(const unsigned char **str, uint32_t *rgbw); ** strcmp - int16_t McuUtility_strcmp(const char *, const char *); ** strncmp - int16_t McuUtility_strncmp(const char *, const char *, size_t size); ** strFind - int16_t McuUtility_strFind(uint8_t *str, uint8_t *subStr); ** strtailcmp - uint8_t McuUtility_strtailcmp(const uint8_t *str, const uint8_t *tail); ** strlen - uint16_t McuUtility_strlen(const char *); ** strCutTail - uint8_t McuUtility_strCutTail(uint8_t *str, uint8_t *tail); ** GetValue16LE - uint16_t McuUtility_GetValue16LE(uint8_t *dataP); ** GetValue24LE - uint32_t McuUtility_GetValue24LE(uint8_t *dataP); ** GetValue32LE - uint32_t McuUtility_GetValue32LE(uint8_t *dataP); ** SetValue16LE - void McuUtility_SetValue16LE(uint16_t data, uint8_t *dataP); ** SetValue24LE - void McuUtility_SetValue24LE(uint32_t data, uint8_t *dataP); ** SetValue32LE - void McuUtility_SetValue32LE(uint32_t data, uint8_t *dataP); ** map - int32_t McuUtility_map(int32_t x, int32_t in_min, int32_t in_max, int32_t... ** map64 - int64_t McuUtility_map64(int64_t x, int64_t in_min, int64_t in_max, int64_t... ** constrain - int32_t McuUtility_constrain(int32_t val, int32_t min, int32_t max); ** random - int32_t McuUtility_random(int32_t min, int32_t max); ** randomSetSeed - void McuUtility_randomSetSeed(unsigned int seed); ** Deinit - void McuUtility_Deinit(void); ** Init - void McuUtility_Init(void); ** ** * Copyright (c) 2014-2022, Erich Styger ** * Web: https://mcuoneclipse.com ** * SourceForge: https://sourceforge.net/projects/mcuoneclipse ** * Git: https://github.com/ErichStyger/McuOnEclipse_PEx ** * All rights reserved. ** * ** * Redistribution and use in source and binary forms, with or without modification, ** * are permitted provided that the following conditions are met: ** * ** * - Redistributions of source code must retain the above copyright notice, this list ** * of conditions and the following disclaimer. ** * ** * - Redistributions in binary form must reproduce the above copyright notice, this ** * list of conditions and the following disclaimer in the documentation and/or ** * other materials provided with the distribution. ** * ** * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ** * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ** * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ** * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ** * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ** * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ** * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ** * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** ###################################################################*/ /*! ** @file McuUtility.h ** @version 01.00 ** @brief ** Contains various utility functions. */ /*! ** @addtogroup McuUtility_module McuUtility module documentation ** @{ */ /* MODULE McuUtility. */ #include "McuUtility.h" #include /* for rand() */ #include /* Internal method prototypes */ static void ShiftRightAndFill(uint8_t *dst, uint8_t fill, uint8_t nofFill); /* ** =================================================================== ** Method : strcpy (component Utility) ** ** Description : ** Same as normal strcpy, but safe as it does not write beyond ** the buffer. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** * src - Pointer to source string. ** Returns : Nothing ** =================================================================== */ /*! \brief copy the string src into dst. It performs the same task as strncpy, except - always terminates the result string. - does not zero out the remaining part in dst. Note: dstSize is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] src The source string to copy */ void McuUtility_strcpy(uint8_t *dst, size_t dstSize, const unsigned char *src) { dstSize--; /* for zero byte */ while (dstSize > 0 && *src != '\0') { *dst++ = *src++; dstSize--; } *dst = '\0'; } /* ** =================================================================== ** Method : strcat (component Utility) ** ** Description : ** Same as normal strcat, but safe as it does not write beyond ** the buffer. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** * src - Pointer to source string. ** Returns : Nothing ** =================================================================== */ /*! \brief Concat the string src into dst. Always terminates the result string. Note: count is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] src The source string to add */ void McuUtility_strcat(uint8_t *dst, size_t dstSize, const unsigned char *src) { dstSize--; /* for zero byte */ /* point to the end of the source */ while (dstSize > 0 && *dst != '\0') { dst++; dstSize--; } /* copy the src in the destination */ while (dstSize > 0 && *src != '\0') { *dst++ = *src++; dstSize--; } /* terminate the string */ *dst = '\0'; } /* ** =================================================================== ** Method : chcat (component Utility) ** ** Description : ** Adds a single character to a zero byte terminated string ** buffer. It cares about buffer overflow. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** ch - character to append ** Returns : Nothing ** =================================================================== */ void McuUtility_chcat(uint8_t *dst, size_t dstSize, uint8_t ch) { dstSize--; /* for zero byte */ /* point to the end of the source */ while (dstSize > 0 && *dst != '\0') { dst++; dstSize--; } /* copy the ch in the destination */ if (dstSize > 0) { *dst++ = ch; } /* terminate the string */ *dst = '\0'; } /* ** =================================================================== ** Method : Num8uToStr (component Utility) ** ** Description : ** Converts an unsigned 8bit value into a string. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to be converted. ** Returns : Nothing ** =================================================================== */ /*! \brief Converts an 8bit unsigned number into a string. \param[in,out] dst String buffer to store the number. \param[in] dstSize Size of the destination buffer in uint8_ts. \param[in] val 8bit unsigned number to convert. */ void McuUtility_Num8uToStr(uint8_t *dst, size_t dstSize, uint8_t val) { McuUtility_Num16uToStr(dst, dstSize, (uint16_t)val); } /* ** =================================================================== ** Method : Num8sToStr (component Utility) ** ** Description : ** Converts a signed 8bit value into a string. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to be converted. ** Returns : Nothing ** =================================================================== */ /*! \brief Converts an 8bit signed number into a string. \param[in,out] dst String buffer to store the number. \param[in] dstSize Size of the destination buffer in uint8_ts. \param[in] val 8bit signed number to convert. */ void McuUtility_Num8sToStr(uint8_t *dst, size_t dstSize, signed char val) { McuUtility_Num16sToStr(dst, dstSize, (int16_t)val); } /* ** =================================================================== ** Method : Num16uToStr (component Utility) ** ** Description : ** Converts a signed 16bit value into a string. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to be converted. ** Returns : Nothing ** =================================================================== */ /*! \brief Converts a 16bit unsigned number into a string. \param[in,out] dst String buffer to store the number. \param[in] dstSize Size of the destination buffer in uint8_ts. \param[in] val 16bit unsigned number to convert. */ void McuUtility_Num16uToStr(uint8_t *dst, size_t dstSize, uint16_t val) { unsigned char *ptr = ((unsigned char *)dst); unsigned char i=0, j; unsigned char tmp; dstSize--; /* for zero byte */ if (val == 0 && dstSize > 0){ ptr[i++] = '0'; dstSize--; } while (val > 0 && dstSize > 0) { ptr[i++] = (unsigned char)((val % 10) + '0'); dstSize--; val /= 10; } for(j=0; j<(i/2); j++) { /* swap buffer */ tmp = ptr[j]; ptr[j] = ptr[(i-j)-1]; ptr[(i-j)-1] = tmp; } ptr[i] = '\0'; } /* ** =================================================================== ** Method : Num16sToStr (component Utility) ** ** Description : ** Converts a signed 16bit value into a string. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to be converted. ** Returns : Nothing ** =================================================================== */ /*! \brief Converts a 16bit signed number into a string. \param[in,out] dst String buffer to store the number. \param[in] dstSize Size of the destination buffer in uint8_ts. \param[in] val 16bit signed number to convert. */ void McuUtility_Num16sToStr(uint8_t *dst, size_t dstSize, int16_t val) { unsigned char *ptr = ((unsigned char *)dst); unsigned char i=0, j; unsigned char tmp; unsigned char sign = (unsigned char)(val < 0); if (val==(int16_t)(0x8000)) { /* special case 0x8000/-32768: prevent overflow below. */ McuUtility_strcpy(dst, dstSize, (unsigned char*)"-32768"); return; } dstSize--; /* for zero byte */ if (sign) { val = (int16_t)(-val); } if (val == 0 && dstSize > 0){ ptr[i++] = '0'; dstSize--; } while (val > 0 && dstSize > 0) { ptr[i++] = (unsigned char)((val % 10) + '0'); dstSize--; val /= 10; } if (sign && dstSize > 0){ ptr[i++] = '-'; } for(j=0; j<(i/2); j++) { /* swap buffer */ tmp = ptr[j]; ptr[j] = ptr[(i-j)-1]; ptr[(i-j)-1] = tmp; } ptr[i] = '\0'; } /* ** =================================================================== ** Method : ShiftRightAndFill (component Utility) ** ** Description : ** This method is internal. It is used by Processor Expert only. ** =================================================================== */ static void ShiftRightAndFill(uint8_t *dst, uint8_t fill, uint8_t nofFill) { signed char i, j; j = 0; while(dst[j] != '\0') { j++; } i = (signed char)nofFill; if (i==j) { /* nothing to do, we are done */ } else if (i>j) { while (j>=0) { dst[i] = dst[j]; i--; j--; } while(i>=0) { dst[i] = fill; i--; } } else { /* hmmm, not enough space, return what we have, do nothing */ } } /* ** =================================================================== ** Method : Num16sToStrFormatted (component Utility) ** ** Description : ** Converts a 16bit signed value to string. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to convert. ** fill - Fill character ** nofFill - Number of fill characters ** Returns : Nothing ** =================================================================== */ /*! \brief Converts a 16bit signed number to a string, in a formatted way (like printf with "%0d"). Always terminates the result string. Note: count is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize Size of the destination buffer, in uint8_ts. \param[in] val The 16bit signed number to add \param[in] fill Fill character, typically ' ' (like for "%2d" or '0' (for "%02d") \param[in] nofFill Size for the format (right aligned) string, e.g. '2' for "%2d" */ void McuUtility_Num16sToStrFormatted(uint8_t *dst, size_t dstSize, int16_t val, char fill, uint8_t nofFill) { McuUtility_Num16sToStr(dst, dstSize, val); ShiftRightAndFill(dst, fill, nofFill); } /* ** =================================================================== ** Method : Num16uToStrFormatted (component Utility) ** ** Description : ** Converts a 16bit unsigned value to string. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to convert. ** fill - Fill character ** nofFill - Number of fill characters ** Returns : Nothing ** =================================================================== */ /*! \brief Converts a 16bit unsigned number to a string, in a formatted way (like printf with "%0d"). Always terminates the result string. Note: count is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize Size of the destination buffer, in uint8_ts. \param[in] val The 16bit unsigned number to add \param[in] fill Fill character, typically ' ' (like for "%2d" or '0' (for "%02d") \param[in] nofFill Size for the format (right aligned) string, e.g. '2' for "%2d" */ void McuUtility_Num16uToStrFormatted(uint8_t *dst, size_t dstSize, uint16_t val, char fill, uint8_t nofFill) { McuUtility_Num16uToStr(dst, dstSize, val); ShiftRightAndFill(dst, fill, nofFill); } /* ** =================================================================== ** Method : Num32uToStrFormatted (component Utility) ** ** Description : ** Converts a 32bit unsigned value to string. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to convert. ** fill - Fill character ** nofFill - Number of fill characters ** Returns : Nothing ** =================================================================== */ /*! \brief Converts a 32bit unsigned number to a string, in a formatted way (like printf with "%0d"). Always terminates the result string. Note: count is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize Size of the destination buffer, in uint8_ts. \param[in] val The 32bit unsigned number to add \param[in] fill Fill character, typically ' ' (like for "%2d" or '0' (for "%02d") \param[in] nofFill Size for the format (right aligned) string, e.g. '2' for "%2d" */ void McuUtility_Num32uToStrFormatted(uint8_t *dst, size_t dstSize, uint32_t val, char fill, uint8_t nofFill) { McuUtility_Num32uToStr(dst, dstSize, val); ShiftRightAndFill(dst, fill, nofFill); } /* ** =================================================================== ** Method : Num32sToStrFormatted (component Utility) ** ** Description : ** Converts a 32bit signed value to string. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to convert. ** fill - Fill character ** nofFill - Number of fill characters ** Returns : Nothing ** =================================================================== */ /*! \brief Converts a 32bit signed number to a string, in a formatted way (like printf with "%0d"). Always terminates the result string. Note: count is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize Size of the destination buffer, in uint8_ts. \param[in] val The 32bit signed number to add \param[in] fill Fill character, typically ' ' (like for "%2d" or '0' (for "%02d") \param[in] nofFill Size for the format (right aligned) string, e.g. '2' for "%2d" */ void McuUtility_Num32sToStrFormatted(uint8_t *dst, size_t dstSize, int32_t val, char fill, uint8_t nofFill) { McuUtility_Num32sToStr(dst, dstSize, val); ShiftRightAndFill(dst, fill, nofFill); } /* ** =================================================================== ** Method : strcatNum8u (component Utility) ** ** Description : ** Appends a 8bit unsigned value to a string buffer. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to convert. ** Returns : Nothing ** =================================================================== */ /*! \brief appends a 8bit unsigned number to a string. Always terminates the result string. Note: count is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] val The 8bit unsigned number to add */ void McuUtility_strcatNum8u(uint8_t *dst, size_t dstSize, uint8_t val) { unsigned char buf[sizeof("256")]; /* maximum buffer size we need */ McuUtility_Num8uToStr(buf, sizeof(buf), val); McuUtility_strcat(dst, dstSize, buf); } /* ** =================================================================== ** Method : strcatNum8s (component Utility) ** ** Description : ** Appends a 8bit signed value to a string buffer. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to convert. ** Returns : Nothing ** =================================================================== */ /*! \brief appends a 8bit signed number to a string. Always terminates the result string. Note: count is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] val The 8bit signed number to add */ void McuUtility_strcatNum8s(uint8_t *dst, size_t dstSize, signed char val) { unsigned char buf[sizeof("-128")]; /* maximum buffer size we need */ McuUtility_Num8sToStr(buf, sizeof(buf), val); McuUtility_strcat(dst, dstSize, buf); } /* ** =================================================================== ** Method : strcatNum16u (component Utility) ** ** Description : ** Appends a 16bit unsigned value to a string buffer. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to convert. ** Returns : Nothing ** =================================================================== */ /*! \brief appends a 16bit unsigned number to a string. Always terminates the result string. Note: count is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] val The 16bit unsigned number to add */ void McuUtility_strcatNum16u(uint8_t *dst, size_t dstSize, uint16_t val) { unsigned char buf[sizeof("32768")]; /* maximum buffer size we need */ McuUtility_Num16uToStr(buf, sizeof(buf), val); McuUtility_strcat(dst, dstSize, buf); } /* ** =================================================================== ** Method : strcatNum16s (component Utility) ** ** Description : ** Appends a 16bit signed value to a string buffer. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to convert. ** Returns : Nothing ** =================================================================== */ /*! \brief appends a 16bit signed number to a string. Always terminates the result string. Note: count is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] val The 16bit signed number to add */ void McuUtility_strcatNum16s(uint8_t *dst, size_t dstSize, int16_t val) { unsigned char buf[sizeof("-32768")]; /* maximum buffer size we need */ McuUtility_Num16sToStr(buf, sizeof(buf), val); McuUtility_strcat(dst, dstSize, buf); } /* ** =================================================================== ** Method : strcatNum16uFormatted (component Utility) ** ** Description : ** Appends a 16bit unsigned value to a string buffer in a ** formatted way. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to convert. ** fill - Fill character ** nofFill - Number of fill characters ** Returns : Nothing ** =================================================================== */ /*! \brief appends a 16bit unsigned number to a string, in a formatted way (like printf with "%0d". Always terminates the result string. Note: count is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] val The 16bit unsigned number to add \param[in] fill Fill character \param[in] nofFill Number of fill characters */ void McuUtility_strcatNum16uFormatted(uint8_t *dst, size_t dstSize, uint16_t val, char fill, uint8_t nofFill) { unsigned char buf[sizeof("32768")]; /* maximum buffer size we need */ McuUtility_Num16uToStrFormatted(buf, dstSize, val, fill, nofFill); McuUtility_strcat(dst, dstSize, buf); } /* ** =================================================================== ** Method : strcatNum16sFormatted (component Utility) ** ** Description : ** Appends a 16bit signed value to a string buffer in a ** formatted way. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to convert. ** fill - Fill character ** nofFill - Number of fill characters ** Returns : Nothing ** =================================================================== */ /*! \brief appends a 16bit signed number to a string, in a formatted way (like printf with "%0d". Always terminates the result string. Note: count is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] val The 16bit signed number to add \param[in] fill Fill character \param[in] nofFill Number of fill characters */ void McuUtility_strcatNum16sFormatted(uint8_t *dst, size_t dstSize, int16_t val, char fill, uint8_t nofFill) { unsigned char buf[sizeof("-32768")]; /* maximum buffer size we need */ McuUtility_Num16sToStrFormatted(buf, dstSize, val, fill, nofFill); McuUtility_strcat(dst, dstSize, buf); } /* ** =================================================================== ** Method : strcatNum32uFormatted (component Utility) ** ** Description : ** Appends a 32bit unsigned value to a string buffer in a ** formatted way. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to convert. ** fill - Fill character ** nofFill - Number of fill characters ** Returns : Nothing ** =================================================================== */ /*! \brief appends a 32bit unsigned number to a string, in a formatted way (like printf with "%0d". Always terminates the result string. Note: count is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] val The 32bit unsigned number to add \param[in] fill Fill character \param[in] nofFill Number of fill characters */ void McuUtility_strcatNum32uFormatted(uint8_t *dst, size_t dstSize, uint32_t val, char fill, uint8_t nofFill) { unsigned char buf[sizeof("4294967295")]; /* maximum buffer size we need */ McuUtility_Num32uToStrFormatted(buf, dstSize, val, fill, nofFill); McuUtility_strcat(dst, dstSize, buf); } /* ** =================================================================== ** Method : strcatNum32sFormatted (component Utility) ** ** Description : ** Appends a 32bit signed value to a string buffer in a ** formatted way. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to convert. ** fill - Fill character ** nofFill - Number of fill characters ** Returns : Nothing ** =================================================================== */ /*! \brief appends a 32bit signed number to a string, in a formatted way (like printf with "%0d". Always terminates the result string. Note: count is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] val The 32bit signed number to add \param[in] fill Fill character \param[in] nofFill Number of fill characters */ void McuUtility_strcatNum32sFormatted(uint8_t *dst, size_t dstSize, int32_t val, char fill, uint8_t nofFill) { unsigned char buf[sizeof("-4294967295")]; /* maximum buffer size we need */ McuUtility_Num32sToStrFormatted(buf, dstSize, val, fill, nofFill); McuUtility_strcat(dst, dstSize, buf); } /* ** =================================================================== ** Method : strcatNum8Hex (component Utility) ** ** Description : ** Appends a 8bit unsigned value to a string buffer as hex ** number (without a 0x prefix). ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** num - Value to convert. ** Returns : Nothing ** =================================================================== */ /*! \brief Adds a 8bit number as hex value to a string. \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] num The 8bit number to add */ void McuUtility_strcatNum8Hex(uint8_t *dst, size_t dstSize, uint8_t num) { unsigned char buf[sizeof("FF")]; /* maximum buffer size we need */ unsigned char hex; buf[2] = '\0'; hex = (char)(num & 0x0F); buf[1] = (char)(hex + ((hex <= 9) ? '0' : ('A'-10))); hex = (char)((num>>4) & 0x0F); buf[0] = (char)(hex + ((hex <= 9) ? '0' : ('A'-10))); McuUtility_strcat(dst, dstSize, buf); } /* ** =================================================================== ** Method : strcatNum16Hex (component Utility) ** ** Description : ** Appends a 16bit unsigned value to a string buffer as hex ** number (without a 0x prefix). ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** num - Value to convert. ** Returns : Nothing ** =================================================================== */ /*! \brief Adds a 16bit number as hex value to a string. \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] num The 16bit number to add */ void McuUtility_strcatNum16Hex(uint8_t *dst, size_t dstSize, uint16_t num) { unsigned char buf[sizeof("FFFF")]; /* maximum buffer size we need */ unsigned char hex; int8_t i; buf[4] = '\0'; i = 3; do { hex = (char)(num & 0x0F); buf[i] = (char)(hex + ((hex <= 9) ? '0' : ('A'-10))); num >>= 4; /* next nibble */ i--; } while (i>=0); McuUtility_strcat(dst, dstSize, buf); } /* ** =================================================================== ** Method : strcatNum24Hex (component Utility) ** ** Description : ** Appends a 32bit unsigned value to a string buffer as hex ** number (without a 0x prefix). Only 24bits are used. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** num - Value to convert. ** Returns : Nothing ** =================================================================== */ /*! \brief Adds a 24bit number as hex value to a string. \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] num The 24bit number to add */ void McuUtility_strcatNum24Hex(uint8_t *dst, size_t dstSize, uint32_t num) { unsigned char buf[sizeof("FFFFFF")]; /* maximum buffer size we need */ unsigned char hex; int8_t i; buf[6] = '\0'; i = 5; do { hex = (char)(num & 0x0F); buf[i] = (char)(hex + ((hex <= 9) ? '0' : ('A'-10))); num >>= 4; /* next nibble */ i--; } while (i>=0); McuUtility_strcat(dst, dstSize, buf); } /* ** =================================================================== ** Method : strcatNum32Hex (component Utility) ** ** Description : ** Appends a 32bit unsigned value to a string buffer as hex ** number (without a 0x prefix). ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** num - Value to convert. ** Returns : Nothing ** =================================================================== */ /*! \brief Adds a 32bit number as hex value to a string. \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] num The 32bit number to add */ void McuUtility_strcatNum32Hex(uint8_t *dst, size_t dstSize, uint32_t num) { unsigned char buf[sizeof("FFFFFFFF")]; /* maximum buffer size we need */ unsigned char hex; int8_t i; buf[8] = '\0'; i = 7; do { hex = (char)(num & 0x0F); buf[i] = (char)(hex + ((hex <= 9) ? '0' : ('A'-10))); num >>= 4; /* next nibble */ i--; } while (i>=0); McuUtility_strcat(dst, dstSize, buf); } /* ** =================================================================== ** Method : strcatNum32s (component Utility) ** ** Description : ** Appends a 32bit signed value to a string buffer. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to convert. ** Returns : Nothing ** =================================================================== */ /*! \brief appends a 32bit (long) number to a string. Always terminates the result string. Note: count is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] val The 32bit number to add */ void McuUtility_strcatNum32s(uint8_t *dst, size_t dstSize, int32_t val) { unsigned char buf[sizeof("-4294967295")]; /* maximum buffer size we need */ McuUtility_Num32sToStr(buf, sizeof(buf), val); McuUtility_strcat(dst, dstSize, buf); } /* ** =================================================================== ** Method : strcatNum32u (component Utility) ** ** Description : ** Appends a 32bit signed value to a string buffer. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to convert. ** Returns : Nothing ** =================================================================== */ /*! \brief appends a 32bit (unsigned long) number to a string. Always terminates the result string. Note: count is the size of dst INCLUDING zero byte. Precondition: src, dst != NULL \param[in,out] dst Start of string buffer, where to append the number string \param[in] dstSize The size of the buffer, including the zero byte \param[in] val The 32bit unsigned number to add */ void McuUtility_strcatNum32u(uint8_t *dst, size_t dstSize, uint32_t val) { unsigned char buf[sizeof("4294967295")]; /* maximum buffer size we need */ McuUtility_Num32uToStr(buf, sizeof(buf), val); McuUtility_strcat(dst, dstSize, buf); } /* ** =================================================================== ** Method : Num32sToStr (component Utility) ** ** Description : ** Converts a signed 32bit value into a string. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to be converted. ** Returns : Nothing ** =================================================================== */ /*! \brief Converts a 32bit number to a string. \param[in,out] dst String buffer to store the number. \param[in] dstSize Size of the destination buffer in uint8_ts. \param[in] val 32bit signed number to convert. */ void McuUtility_Num32sToStr(uint8_t *dst, size_t dstSize, int32_t val) { unsigned char *ptr = ((unsigned char *)dst); unsigned char i=0, j; unsigned char tmp; unsigned char sign = (unsigned char)(val < 0); if (val==(int32_t)(0x80000000)) { /* special case 0x80000000/-2147483648: prevent overflow below. */ McuUtility_strcpy(dst, dstSize, (unsigned char*)"-2147483648"); return; } dstSize--; /* for zero byte */ if (sign) { val = -val; } if (val == 0 && dstSize > 0){ ptr[i++] = '0'; dstSize--; } while (val > 0 && dstSize > 0) { ptr[i++] = (unsigned char)((val % 10) + '0'); dstSize--; val /= 10; } if (sign && dstSize > 0){ ptr[i++] = '-'; } for(j=0; j<(i/2); j++) { /* swap buffer */ tmp = ptr[j]; ptr[j] = ptr[(i-j)-1]; ptr[(i-j)-1] = tmp; } ptr[i] = '\0'; } /* ** =================================================================== ** Method : Num32uToStr (component Utility) ** ** Description : ** Converts an unsigned 32bit value into a string. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to be converted. ** Returns : Nothing ** =================================================================== */ /*! \brief Converts a 32bit signed number to a string. \param[in,out] dst String buffer to store the number. \param[in] dstSize Size of the destination buffer in uint8_ts. \param[in] val 32bit unsigned number to convert. */ void McuUtility_Num32uToStr(uint8_t *dst, size_t dstSize, uint32_t val) { unsigned char *ptr = ((unsigned char *)dst); unsigned char i=0, j; unsigned char tmp; dstSize--; /* for zero byte */ if (val == 0 && dstSize > 0){ ptr[i++] = '0'; dstSize--; } while (val > 0 && dstSize > 0) { ptr[i++] = (unsigned char)((val % 10) + '0'); dstSize--; val /= 10; } for(j=0; j<(i/2); j++) { /* swap buffer */ tmp = ptr[j]; ptr[j] = ptr[(i-j)-1]; ptr[(i-j)-1] = tmp; } ptr[i] = '\0'; } /* ** =================================================================== ** Method : IsLeapYear (component Utility) ** ** Description : ** Returns true if a given year is a leap year ** Parameters : ** NAME - DESCRIPTION ** year - Year, in the YYYY format. ** Returns : ** --- - If the year is a leap year or not. ** =================================================================== */ bool McuUtility_IsLeapYear(uint16_t year) { return ((((year%4)==0) && (year%100)!=0) || (year%400)==0); } /* ** =================================================================== ** Method : WeekDay (component Utility) ** ** Description : ** Returns the weekday for a given date >= 1.Jan.1900 ** Parameters : ** NAME - DESCRIPTION ** year - year in YYYY format ** month - month of the year (1: January, 2: ** February, etc) ** day - day of the moth (starting with 1) ** Returns : ** --- - Returns the weekday, 0 for Sunday, 1 for ** Monday, 2 for Tuesday, etc. ** =================================================================== */ uint8_t McuUtility_WeekDay(uint16_t year, uint8_t month, uint8_t day) { /* see http://klausler.com/new-dayofweek.html */ static const uint8_t skew[12] = {0,3,3,6,1,4,6,2,5,0,3,5}; uint16_t sum; sum = (uint16_t)(year-1900); sum += sum/4; sum %= 7; if (McuUtility_IsLeapYear(year) && (month==1 || month==2)) { sum--; } sum += day; sum %= 7; sum += skew[month-1]; sum %= 7; return (uint8_t)sum; /* 0: Sunday, 1: Monday, 2: Tuesday, 3: Wednesday, ... */ } /* ** =================================================================== ** Method : ReadEscapedName (component Utility) ** ** Description : ** Scans an escaped name from a string. This is useful e.g. for ** double quoted file names. ** Parameters : ** NAME - DESCRIPTION ** * filename - the name to be copied. Names may ** be in quoted format ** * destname - the destination of the copy. ** Names are not in quoted format. destname ** may be NULL to get the other return values ** only ** maxlen - length allocated for destname ** * lenRead - length read in filename to copy ** the whole name. Note that filenames maybe ** space terminated, so *lenRead < ** strlen(filename) ** lenWritten - the size written in destname. ** In case of overflows in destname, ** lenWritten is still increased but destname ** no longer written. The have the string ** length in these cases use strlen(destname) ** terminators - additional characters ** where a name should terminate. May be NULL ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ReadEscapedName(const unsigned char *filename, uint8_t *destname, size_t maxlen, size_t *lenRead, size_t *lenWritten, const char *terminators) { size_t lenCopied = 0, lenOverread = 0; bool quoteMode = FALSE; /* quoteMode means the name is surrounded by ". In this mode, only a second single quote " terminates the string. In !quoteMode a space or a '\0' may also terminate it correctly */ bool res = ERR_OK; #define IS_SPACE(ch) ((ch)==' '||(ch)=='\t'||(ch)=='\n'||(ch)=='\v'||(ch)=='\f'||(ch)=='\r') if (filename==NULL || (destname!=NULL && maxlen==0)) { return ERR_FAILED; } if (filename[0] == '"') { /* translated mode */ filename++; /* overread '"' */ lenOverread++; quoteMode=TRUE; } if (terminators == NULL) { terminators = ""; } for (;;) { if (quoteMode) { if (filename[0] == '"') { filename++; /* overread '"' */ lenOverread++; if (filename[0] != '"') { /* quoteMode is terminated by a single quote. A double quote is treated like a single quote and does not terminate it ! */ break; /* successfully finished with this name */ } /* else we copy the second quote " */ } if (filename[0] == '\0') { /* unexpected 0. stop */ res = ERR_FAILED; break; /* error case: no terminating double quote (") was found */ } } else { /* copy mode */ if (IS_SPACE(filename[0]) || filename[0] == '\0' || strchr(terminators, filename[0]) != NULL) { /* !quoteMode is terminated by space, '\0' or by any char in terminators */ break; } } if (destname != NULL) { if (lenCopied + 1 < maxlen) { destname[0] = filename[0]; destname++; } else { destname[0] = '\0'; /* terminate string */ destname = NULL; /* avoid it to overwrite not allocated space */ } } lenCopied++; filename++; } if (destname != NULL) { destname[0] = '\0'; } if (lenRead != NULL) { *lenRead = lenCopied+lenOverread; } if (lenWritten != NULL) { *lenWritten = lenCopied + 1; /* additionally a zero byte written */ } return res; } /* ** =================================================================== ** Method : xatoi (component Utility) ** ** Description : ** Custom atoi() (ascii to int) implementation by Elm Chan ** Parameters : ** NAME - DESCRIPTION ** * str - Pointer to string to scan. Returns until ** where it has scanned. ** * res - Pointer to where to store the result ** Returns : ** --- - Error code ** =================================================================== */ /*------------------------------------------------------------------------/ / Universal string handler for user console interface /-------------------------------------------------------------------------/ / / Copyright (C) 2010, ChaN, all right reserved. / / * This software is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for / personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. / * Redistributions of source code must retain the above copyright notice. / /-------------------------------------------------------------------------*/ #ifdef __HC12__ #pragma MESSAGE DISABLE C12056 /* message about SP debug info */ #endif uint8_t McuUtility_xatoi(const unsigned char **str, int32_t *res) { /* 123 -5 0x3ff 0b1111 0377 3.25 w " ^ 1st call returns 123 and next ptr ^ 2nd call returns -5 and next ptr ^ 3rd call returns 1023 and next ptr ^ 4th call returns 15 and next ptr ^ 5th call returns 255 and next ptr ^ 6th call returns 3 and next ptr, caller needs to read '.' ^ 7th call returns 25 and next ptr ^ 8th call fails and returns ERR_FAILED */ uint32_t val; uint8_t c, r, s = 0; *res = 0; while (**str==' ') { (*str)++; /* Skip leading spaces */ } c = **str; if (c == '-') { /* negative? */ s = 1; c = *(++(*str)); } if (c == '0') { c = *(++(*str)); switch (c) { case 'x': /* hexadecimal */ r = 16; c = *(++(*str)); break; case 'b': /* binary */ r = 2; c = *(++(*str)); break; default: if (c <= ' ' || c == '.') { return ERR_OK; /* single zero */ } if (c < '0' || c > '9') { return ERR_FAILED; /* invalid char */ } r = 8; /* octal */ break; } /* switch */ } else { if (c < '0' || c > '9') { return ERR_FAILED; /* EOL or invalid char */ } r = 10; /* decimal */ } val = 0; while (c > ' ' && c != '.') { if (c >= 'a') c -= 0x20; c -= '0'; if (c >= 17) { c -= 7; if (c <= 9) return ERR_FAILED; /* invalid char */ } if (c >= r) return ERR_FAILED; /* invalid char for current radix */ val = val * r + c; c = *(++(*str)); } /* while */ if (s) val = 0 - val; /* apply sign if needed */ *res = (long)val; return ERR_OK; } #ifdef __HC12__ #pragma MESSAGE DEFAULT C12056 /* message about SP debug info */ #endif /* ** =================================================================== ** Method : ScanDate (component Utility) ** ** Description : ** Scans a date in the format "dd.mm.yyyy" or "dd-mm-yyyy". For ** yy it will expand it to 20yy. ** Parameters : ** NAME - DESCRIPTION ** * str - Pointer to the string to be scanned. The ** function advances the pointer. ** * day - Pointer to where to store the day value ** * month - Pointer to where to store the month ** value ** * year - Pointer to where to store the year value ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanDate(const unsigned char **str, uint8_t *day, uint8_t *month, uint16_t *year) { /* precondition: string points to starting of date, e.g. "01.01.10" or "12.5.2010", and date is in format dd.mm.yy or dd.mm.yyyy */ const unsigned char *p; p = *str; while(*p==' ') { p++; /* skip leading spaces */ } if ( McuUtility_ScanDecimal8uNumber(&p, day)==ERR_OK && *day > 0 && *day <= 31 && (*p=='.' || *p=='-') ) { p++; if ( McuUtility_ScanDecimal8uNumber(&p, month)==ERR_OK && *month > 0 && *month <= 12 && (*p=='.' || *p=='-') ) { p++; if ( McuUtility_ScanDecimal16uNumber(&p, year)==ERR_OK && *year > 0 && *year <= 3000 /* hopefully this is enough :-) */ ) { if (*year < 100) { *year += 2000; /* transform '10' into '2010' */ } *str = p; /* advance pointer for caller */ return ERR_OK; } } } *day = 0; *month = 0; *year = 0; return ERR_FAILED; /* wrong format */ } /* ** =================================================================== ** Method : ScanTime (component Utility) ** ** Description : ** Scans a time string in the format "hh:mm:ss,hh" with the ** part for the ",hh" is optional. ** Parameters : ** NAME - DESCRIPTION ** str - Pointer to the string to be scanned. The ** function advances the pointer. ** * hour - Pointer to where to store the hour value ** * minute - Pointer to where to store the minute ** value ** * second - Pointer to where to store the second ** value ** * hSecond - Pointer to scans the hundreds of ** second part. If not present in string, zero ** is stored ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanTime(const unsigned char **str, uint8_t *hour, uint8_t *minute, uint8_t *second, uint8_t *hSecond) { /* precondition: string points to starting of time string, e.g. "03:15:05" or "03:15:05,3" or "03:15:05,17", and time is in format hh:mm:ss[,hh] */ const unsigned char *p; #define SCAN_IS_DIGIT(ch) ((ch)>='0'&&(ch)<='9') *hour = 0; *minute = 0; *second = 0; *hSecond = 0; p = *str; while(*p==' ') { p++; /* skip leading spaces */ } if ( McuUtility_ScanDecimal8uNumber(&p, hour)==ERR_OK && *hour <= 24 && *p==':' ) { p++; /* skip ':' */ if ( McuUtility_ScanDecimal8uNumber(&p, minute)==ERR_OK && *minute <= 60 ) { if (*p==':') { /* there is more after the minute */ p++; /* skip ':' */ if ( McuUtility_ScanDecimal8uNumber(&p, second)==ERR_OK && *second <= 60 ) { if (*p==',') { /* we do have either ",z" or ",hh" */ p++; /* skip ',' */ if (SCAN_IS_DIGIT(*p)) { if (SCAN_IS_DIGIT(*(p+1))) { /* ,hh format */ *hSecond = (uint8_t)((*p-'0')*10 + *(p+1)-'0'); return ERR_OK; } else { /* ,z format */ *hSecond = (uint8_t)((*p-'0')*10); p++; *str = p; /* advance pointer for caller */ return ERR_OK; } } else { return ERR_FAILED; /* illegal format, not a number, e.g. ",x" */ } } *str = p; /* advance pointer for caller */ return ERR_OK; } } else if (*p==' ' || *p=='\0') { /* nothing more after the minute? Assume zero seconds */ *str = p; /* advance pointer for caller */ return ERR_OK; } } } return ERR_FAILED; /* wrong format */ } /* ** =================================================================== ** Method : ScanDecimal8uNumber (component Utility) ** ** Description : ** Scans a decimal 8bit unsigned number ** Parameters : ** NAME - DESCRIPTION ** str - String to scan. It returns as well until ** where it has scanned ** * val - Pointer to value ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanDecimal8uNumber(const unsigned char **str, uint8_t *val) { /* scans a decimal number, and stops at any non-number. Number can have any preceding zeros or spaces. */ #define _8_NOF_DIGITS (3+1) uint8_t nofDigits = _8_NOF_DIGITS; /* maximum number of digits to avoid overflow */ const unsigned char *p = *str; while(*p==' ') { /* skip leading spaces */ p++; } *val = 0; while(*p>='0' && *p<='9' && nofDigits > 0) { *val = (uint8_t)((*val)*10 + *p-'0'); nofDigits--; p++; } /* while */ if (nofDigits==0) { return ERR_OVERFLOW; } if (nofDigits==_8_NOF_DIGITS) { /* no digits at all? */ return ERR_FAILED; } *str = p; return ERR_OK; } /* ** =================================================================== ** Method : ScanDecimal8sNumber (component Utility) ** ** Description : ** Scans a decimal 8bit signed number ** Parameters : ** NAME - DESCRIPTION ** str - String to scan. It returns as well until ** where it has scanned ** * val - Pointer to value ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanDecimal8sNumber(const unsigned char **str, signed char *val) { /* Scans a decimal number, and stops at any non-number. Number can have any preceding spaces. */ const unsigned char *p = *str; bool isNeg; uint8_t val8u; uint8_t res; while(*p==' ') { /* skip leading spaces */ p++; } *val = 0; if (*p=='-') { isNeg = TRUE; p++; /* skip minus */ } else { isNeg = FALSE; } res = McuUtility_ScanDecimal8uNumber(&p, &val8u); if (res != ERR_OK) { return res; } if (isNeg) { *val = (int8_t)(-(int8_t)val8u); } else { *val = (int8_t)val8u; } *str = p; return ERR_OK; } /* ** =================================================================== ** Method : ScanDecimal16uNumber (component Utility) ** ** Description : ** Scans a decimal 16bit unsigned number ** Parameters : ** NAME - DESCRIPTION ** str - String to scan. It returns as well until ** where it has scanned ** * val - Pointer to value ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanDecimal16uNumber(const unsigned char **str, uint16_t *val) { /* scans a decimal number, and stops at any non-number. Number can have any preceding zeros or spaces. */ #define _16_NOF_DIGITS (5+1) uint8_t nofDigits = _16_NOF_DIGITS; /* maximum number of digits to avoid overflow */ const unsigned char *p = *str; while(*p==' ') { /* skip leading spaces */ p++; } *val = 0; while(*p>='0' && *p<='9' && nofDigits > 0) { *val = (uint16_t)((*val)*10 + *p-'0'); nofDigits--; p++; } /* while */ if (nofDigits==0) { return ERR_OVERFLOW; } if (nofDigits==_16_NOF_DIGITS) { /* no digits at all? */ return ERR_FAILED; } *str = p; return ERR_OK; } /* ** =================================================================== ** Method : ScanDecimal16sNumber (component Utility) ** ** Description : ** Scans a decimal 16bit signed number ** Parameters : ** NAME - DESCRIPTION ** str - String to scan. It returns as well until ** where it has scanned ** * val - Pointer to value ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanDecimal16sNumber(const unsigned char **str, int16_t *val) { /* Scans a decimal number, and stops at any non-number. Number can have any preceding spaces. */ const unsigned char *p = *str; bool isNeg; uint16_t val16u; uint8_t res; while(*p==' ') { /* skip leading spaces */ p++; } *val = 0; if (*p=='-') { isNeg = TRUE; p++; /* skip minus */ } else { isNeg = FALSE; } res = McuUtility_ScanDecimal16uNumber(&p, (uint16_t*)&val16u); if (res != ERR_OK) { return res; } if (isNeg) { *val = (int16_t)(-(int16_t)val16u); } else { *val = (int16_t)val16u; } *str = p; return ERR_OK; } /* ** =================================================================== ** Method : ScanDecimal32uNumber (component Utility) ** ** Description : ** Scans a decimal 32bit unsigned number ** Parameters : ** NAME - DESCRIPTION ** str - string to scan. It returns as well until ** where it has scanned ** * val - Pointer to value ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanDecimal32uNumber(const unsigned char **str, uint32_t *val) { /* scans a decimal number, and stops at any non-number. Number can have any preceding zeros or spaces. */ #define _32_NOF_DIGITS (10+1) uint8_t nofDigits = _32_NOF_DIGITS; /* maximum number of digits to avoid overflow */ const unsigned char *p = *str; while(*p==' ') { /* skip leading spaces */ p++; } *val = 0; while(*p>='0' && *p<='9' && nofDigits > 0) { *val = (uint32_t)((*val)*10 + *p-'0'); nofDigits--; p++; } /* while */ if (nofDigits==0) { return ERR_OVERFLOW; } if (nofDigits==_32_NOF_DIGITS) { /* no digits at all? */ return ERR_FAILED; } *str = p; return ERR_OK; } /* ** =================================================================== ** Method : ScanDecimal32sNumber (component Utility) ** ** Description : ** Scans a decimal 32bit signed number ** Parameters : ** NAME - DESCRIPTION ** str - string to scan. It returns as well until ** where it has scanned ** * val - Pointer to value ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanDecimal32sNumber(const unsigned char **str, int32_t *val) { /* Scans a decimal number, and stops at any non-number. Number can have any preceding spaces. */ const unsigned char *p = *str; bool isNeg; uint32_t val32u; uint8_t res; while(*p==' ') { /* skip leading spaces */ p++; } *val = 0; if (*p=='-') { isNeg = TRUE; p++; /* skip minus */ } else { isNeg = FALSE; } res = McuUtility_ScanDecimal32uNumber(&p, &val32u); if (res != ERR_OK) { return res; } if (isNeg) { *val = (int32_t)(-(int32_t)val32u); } else { *val = (int32_t)val32u; } *str = p; return ERR_OK; } /* ** =================================================================== ** Method : ScanDecimal32sDotNumber (component Utility) ** ** Description : ** Scans a decimal 32bit signed number with a following dot ** (fractional part), e.g. "-34587.0248", it will return the ** (signed) integral and fractional part with number of ** fractional zeros. The function accepts as well numbers like ** "17" (no fractional part" or "17.0" ** Parameters : ** NAME - DESCRIPTION ** str - string to scan. It returns as well until ** where it has scanned ** * integral - Pointer to value before the dot ** * fractional - Pointer to value after the ** dot, e.g. 32 for "-134.0032" ** nofFractionalZeros - Number of ** fractional leading zeros, e.g. 2 for "-134. ** 0032" ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanDecimal32sDotNumber(const unsigned char **str, int32_t *integral, uint32_t *fractional, uint8_t *nofFractionalZeros) { /* scans e.g. "-3445.071" and returns -3445 in integral part, and 71 in fractional part */ uint8_t res; const unsigned char *p = *str; *integral = 0; *fractional = 0; *nofFractionalZeros = 0; res = McuUtility_ScanDecimal32sNumber(&p, integral); if (res != ERR_OK) { return res; } if (*p=='.') { p++; /* skip '.' */ while (*p=='0') { /* count leading zeros */ (*nofFractionalZeros)++; p++; /* skip leading zero */ } if (*p>='0' && *p<='9') { /* number */ res = McuUtility_ScanDecimal32uNumber(&p, fractional); if (res != ERR_OK) { return res; } } } *str = p; /* store parsing pointer */ return ERR_OK; } /* ** =================================================================== ** Method : strcmp (component Utility) ** ** Description : ** Wrapper to the standard strcmp() routine ** Parameters : ** NAME - DESCRIPTION ** * str1 - Pointer to string ** * str2 - Pointer to string ** Returns : ** --- - Returns zero if the two strings are the ** same ** =================================================================== */ /*** int16_t McuUtility_strcmp(const char *, const char *) { Method is implemented as macro in the header file as wrapper to the standard strcmp() function } */ /* ** =================================================================== ** Method : strncmp (component Utility) ** ** Description : ** Wrapper to the standard strncmp() routine ** Parameters : ** NAME - DESCRIPTION ** * str1 - Pointer to string ** * str2 - Pointer to string ** size - ** Returns : ** --- - Returns zero if the two strings are the ** same ** =================================================================== */ /*** int16_t McuUtility_strncmp(const char *, const char *, size_t size) { /Method is implemented as macro in the header file as wrapper to the standard strncmp() function } */ /* ** =================================================================== ** Method : strlen (component Utility) ** ** Description : ** Wrapper to the standard strlen() function. ** Parameters : ** NAME - DESCRIPTION ** str - ** Returns : ** --- - size of strinig ** =================================================================== */ /*** uint16_t McuUtility_strlen(const char *) { Method is implemented as macro in the header file as wrapper to the standard strlen() function } */ static bool isHexCharacter(unsigned char ch) { /* returns TRUE if character is a hexadecimal character */ return (ch>='0' && ch<='9') || (ch>='a' && ch<='f') || (ch>='A' && ch<='F'); } static uint8_t PreScanHexNumber(const unsigned char **str) { const unsigned char *p = *str; while(*p==' ') { /* skip leading spaces */ p++; /* skip space */ } if (*p!='0') { /* must start with 0x */ return ERR_FAILED; } p++; /* skip '0' */ if (*p!='x') { /* must start with 0x */ return ERR_FAILED; } p++; /* skip 'x' */ *str = p; return ERR_OK; } static uint8_t HexToDec(const unsigned char **p, unsigned char *val) { /* convert a hexadecimal character into a decimal value */ unsigned char ch = **p; if (ch>='0' && ch<='9') { *val = (unsigned char)(ch-'0'); (*p)++; return ERR_OK; } else if (ch>='a' && ch<='f') { *val = (unsigned char)(ch-'a'+10); (*p)++; return ERR_OK; } else if (ch>='A' && ch<='F') { *val = (unsigned char)(ch-'A'+10); (*p)++; return ERR_OK; } return ERR_FAILED; } /* ** =================================================================== ** Method : ScanHex32uNumber (component Utility) ** ** Description : ** Scans a hexadecimal 32bit number, starting with 0x ** Parameters : ** NAME - DESCRIPTION ** str - String to scan, starting with 0x. It ** returns as well until where it has scanned ** * val - Pointer to value ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanHex32uNumber(const unsigned char **str, uint32_t *val) { /* scans a decimal number, and stops at any non-number. Number can have any preceding zeros or spaces. */ uint8_t nofDigits = 8; /* maximum number of digits to avoid overflow */ const unsigned char *p = *str; uint8_t v; *val = 0; if (PreScanHexNumber(&p)!=ERR_OK) { /* skip leading spaces, and scan '0x' */ return ERR_FAILED; } if (!isHexCharacter(*p)) { /* not a valid hex number sequence */ return ERR_FAILED; } while (nofDigits>0 && HexToDec(&p, &v)==ERR_OK) { *val = (uint32_t)((*val)*16 + v); nofDigits--; } /* while */ *str = p; return ERR_OK; } /* ** =================================================================== ** Method : ScanHex16uNumber (component Utility) ** ** Description : ** Scans a hexadecimal 16bit number, starting with 0x ** Parameters : ** NAME - DESCRIPTION ** str - String to scan, starting with 0x.. It ** returns as well until where it has scanned ** * val - Pointer to value ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanHex16uNumber(const unsigned char **str, uint16_t *val) { /* scans a decimal number, and stops at any non-number. Number can have any preceding zeros or spaces. */ uint8_t nofDigits = 4; /* maximum number of digits to read */ const unsigned char *p = *str; uint8_t v; *val = 0; if (PreScanHexNumber(&p)!=ERR_OK) { /* skip leading spaces, and scan '0x' */ return ERR_FAILED; } if (!isHexCharacter(*p)) { /* not a valid hex number sequence */ return ERR_FAILED; } while (nofDigits>0 && HexToDec(&p, &v)==ERR_OK) { *val = (uint16_t)((*val)*16 + v); nofDigits--; } /* while */ *str = p; return ERR_OK; } /* ** =================================================================== ** Method : ScanHex8uNumber (component Utility) ** ** Description : ** Scans a hexadecimal 8bit number, starting with 0x ** Parameters : ** NAME - DESCRIPTION ** str - String to scan, starting with 0x. It ** returns as well until where it has scanned ** * val - Pointer to value ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanHex8uNumber(const unsigned char **str, uint8_t *val) { /* scans a hex number with 0x, and stops at any non-number. Number can have any preceding zeros or spaces. */ uint8_t nofDigits = 2; /* maximum number of digits to read */ const unsigned char *p = *str; uint8_t v; *val = 0; if (PreScanHexNumber(&p)!=ERR_OK) { /* skip leading spaces, and scan '0x' */ return ERR_FAILED; } if (!isHexCharacter(*p)) { /* not a valid hex number sequence */ return ERR_FAILED; } while (nofDigits>0 && HexToDec(&p, &v)==ERR_OK) { *val = (uint8_t)((*val)*16 + v); nofDigits--; } /* while */ *str = p; return ERR_OK; } /* ** =================================================================== ** Method : ScanHex8uNumberNoPrefix (component Utility) ** ** Description : ** Scans a hexadecimal 8bit number, without 0x ** Parameters : ** NAME - DESCRIPTION ** str - String to scan, starting with 0x. It ** returns as well until where it has scanned ** * val - Pointer to value ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanHex8uNumberNoPrefix(const unsigned char **str, uint8_t *val) { /* scans a hex number without 0x, and stops at any non-number. Number can have any preceding zeros or spaces. */ uint8_t nofDigits = 2; /* maximum number of digits to read */ const unsigned char *p = *str; uint8_t v; *val = 0; while(*p==' ') { /* skip leading spaces */ p++; /* skip space */ } if (!isHexCharacter(*p)) { /* not a valid hex number sequence */ return ERR_FAILED; } while (nofDigits>0 && HexToDec(&p, &v)==ERR_OK) { *val = (uint8_t)((*val)*16 + v); nofDigits--; } /* while */ *str = p; return ERR_OK; } /* ** =================================================================== ** Method : strtailcmp (component Utility) ** ** Description : ** Compares the tail of a string and returns 0 if it matches, 1 ** otherwise ** Parameters : ** NAME - DESCRIPTION ** * str - Pointer to string. This string is compared ** if it contains the tail. ** * tail - Pointer to tail string. ** Returns : ** --- - returns 0 if tail matches, -1 otherwise ** =================================================================== */ uint8_t McuUtility_strtailcmp(const uint8_t *str, const uint8_t *tail) { int i, j; i = (int)McuUtility_strlen((char*)str); j = (int)McuUtility_strlen((char*)tail); if (j>i) { /* str is smaller than tail */ return 1; /* cannot match */ } /* compare strings */ while(str[i]==tail[j]) { i--; j--; if (j<0) { return 0; /* match */ } } return 1; /* !=0 means no match */ } /* ** =================================================================== ** Method : strCutTail (component Utility) ** ** Description : ** Removes a tailing substring from a string. The string passed ** will be modified (the tail is cut by writing a zero byte to ** the string!) ** Parameters : ** NAME - DESCRIPTION ** * str - Pointer to string where to remove the tail ** * tail - Pointer to substring to remove ** Returns : ** --- - Error code, ERR_OK if no error, otherwise ** ERR_FAIL if tail is not found ** =================================================================== */ uint8_t McuUtility_strCutTail(uint8_t *str, uint8_t *tail) { /* cut the tail from the string */ size_t strLen, tailLen; if (McuUtility_strtailcmp(str, tail)!=0) { /* check if tail is present */ return ERR_FAILED; /* tail not found */ } tailLen = McuUtility_strlen((char*)tail); strLen = McuUtility_strlen((char*)str); /* write \0 to cut the tail */ str[strLen-tailLen] = '\0'; return ERR_OK; } /* ** =================================================================== ** Method : strcatNum32sDotValue100 (component Utility) ** ** Description : ** Appends a 32bit signed value to a string buffer. The value ** is in 1/100 units. For example for the value -13456 it will ** append the string "-134.56" ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** num - Value to convert. ** Returns : Nothing ** =================================================================== */ void McuUtility_strcatNum32sDotValue100(uint8_t *dst, size_t dstSize, int32_t num) { if (num<0 && (num/100)==0) { /* e.g. -53 ==> write sign, as strcatNum32() below will not know that it is negative */ McuUtility_chcat(dst, dstSize, '-'); } McuUtility_strcatNum32s(dst, dstSize, num/100); McuUtility_chcat(dst, dstSize, '.'); if (num<0) { num = -num; } McuUtility_strcatNum16uFormatted(dst, dstSize, (uint16_t)((unsigned)num%100U), '0', 2); } /* ** =================================================================== ** Method : strFind (component Utility) ** ** Description : ** Searches a substring inside a string and returns the ** position. ** Parameters : ** NAME - DESCRIPTION ** * str - Pointer to string which will be searched ** * subStr - Pointer to substring to search ** inside str ** Returns : ** --- - -1 if not found, otherwise the character ** index. ** =================================================================== */ int16_t McuUtility_strFind(uint8_t *str, uint8_t *subStr) { int16_t i, len; len = (int16_t)McuUtility_strlen((char*)subStr); for (i=0; *str!='\0'; i++, str++) { if (McuUtility_strncmp((char*)str, (char*)subStr, len)==0) { return i; /* found */ } } return -1; /* not found */ } /* ** =================================================================== ** Method : ScanSeparatedNumbers (component Utility) ** ** Description : ** Scans multiple numbers separated by character, e.g. "123.68. ** 5.3" ** Parameters : ** NAME - DESCRIPTION ** str - String to scan. It returns as well until ** where it has scanned ** * values - Pointer to array where to store the ** values ** nofValues - Number of values in the array ** separator - Character separator, e.g. '.' ** numberType - type of number to scan ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanSeparatedNumbers(const unsigned char **str, uint8_t *values, uint8_t nofValues, char separator, McuUtility_SeparatedNumberType numberType) { int i; uint8_t res; const unsigned char *p; if (nofValues<=1) { return ERR_FAILED; /* need at least two values */ } p = *str; for(i=0;i0) { *buf++ = *p++; bufSize--; } if (*p!='\"') { return ERR_FAILED; /* no terminating double quote */ } else { p++; /* skip double quote */ *buf = '\0'; /* terminate buffer */ } *cmd = p; /* advance pointer */ return ERR_OK; } /* ** =================================================================== ** Method : strcatPad (component Utility) ** ** Description : ** Same as normal strcat, but safe as it does not write beyond ** the buffer. The buffer will be filled with a pad character ** for a given length. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** * src - Pointer to source string. ** padChar - Character to be used for padding ** srcPadSize - To which size the src string ** has to be padded. ** Returns : Nothing ** =================================================================== */ void McuUtility_strcatPad(uint8_t *dst, size_t dstSize, const unsigned char *src, char padChar, uint8_t srcPadSize) { uint8_t *p; size_t nof = 0; if (dstSize<2) { return; /* hmm, really to small for anything than the zero byte? */ } p = dst; while(*p != '\0') { /* find end of string */ p++; nof++; } McuUtility_strcat(dst+nof, dstSize-nof, src); /* add string */ dstSize -= nof; while(*p != '\0' && srcPadSize>0 && dstSize>1) { p++; srcPadSize--; dstSize--; } while(srcPadSize>0 && dstSize>1) { *p++ = padChar; /* add padding char */ srcPadSize--; dstSize--; } *p = '\0'; /* terminate string */ } /* ** =================================================================== ** Method : NumFloatToStr (component Utility) ** ** Description : ** Converts a float value into a string. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to be converted. ** nofFracDigits - Number of fractional ** digits to print ** Returns : Nothing ** =================================================================== */ void McuUtility_NumFloatToStr(uint8_t *dst, size_t dstSize, float val, uint8_t nofFracDigits) { uint32_t integral; uint32_t fractional, shift; int i; bool isNeg; isNeg = (bool)(val<0); if (isNeg) { val = -val; /* make it positive */ } integral = (uint32_t)(int32_t)val; val = val-(float)integral; /* get rid of integral part */ shift = 1; for(i=0;i0) { McuUtility_chcat(dst, dstSize, '.'); McuUtility_strcatNum32uFormatted(dst, dstSize, fractional, '0', nofFracDigits); } } /* ** =================================================================== ** Method : strcatNumFloat (component Utility) ** ** Description : ** Converts a float value into a string. ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** val - Value to be converted. ** nofFracDigits - Number of factional ** digits to print ** Returns : Nothing ** =================================================================== */ void McuUtility_strcatNumFloat(uint8_t *dst, size_t dstSize, float val, uint8_t nofFracDigits) { uint8_t buf[32]; McuUtility_NumFloatToStr(buf, sizeof(buf), val, nofFracDigits); McuUtility_strcat(dst, dstSize, buf); } /* ** =================================================================== ** Method : GetValue16LE (component Utility) ** ** Description : ** Returns a 16bit Little Endian value from memory ** Parameters : ** NAME - DESCRIPTION ** * dataP - Pointer to memory ** Returns : ** --- - Error code ** =================================================================== */ uint16_t McuUtility_GetValue16LE(uint8_t *dataP) { return (uint16_t)((dataP[1]<<8)+(dataP[0])); } /* ** =================================================================== ** Method : GetValue24LE (component Utility) ** ** Description : ** Returns a 24bit Little Endian value from memory ** Parameters : ** NAME - DESCRIPTION ** * dataP - Pointer to memory ** Returns : ** --- - Error code ** =================================================================== */ uint32_t McuUtility_GetValue24LE(uint8_t *dataP) { return (uint32_t)(((uint32_t)dataP[2])<<16)+(dataP[1]<<8)+(dataP[0]); } /* ** =================================================================== ** Method : GetValue32LE (component Utility) ** ** Description : ** Returns a 32bit Little Endian value from memory ** Parameters : ** NAME - DESCRIPTION ** * dataP - Pointer to memory ** Returns : ** --- - Error code ** =================================================================== */ uint32_t McuUtility_GetValue32LE(uint8_t *dataP) { return (uint32_t)(((uint32_t)dataP[3])<<24)+(((uint32_t)dataP[2])<<16)+(dataP[1]<<8)+(dataP[0]); } /* ** =================================================================== ** Method : SetValue16LE (component Utility) ** ** Description : ** Stores a 16bit value in memory as Little Endian ** Parameters : ** NAME - DESCRIPTION ** data - Value to store ** * dataP - Pointer to memory ** Returns : Nothing ** =================================================================== */ void McuUtility_SetValue16LE(uint16_t data, uint8_t *dataP) { dataP[0] = (uint8_t)(data&0xff); /* LSB */ dataP[1] = (uint8_t)((data>>8)&0xff); /* MSB */ } /* ** =================================================================== ** Method : SetValue24LE (component Utility) ** ** Description : ** Stores a 24bit value in memory as Little Endian ** Parameters : ** NAME - DESCRIPTION ** data - Value to store ** * dataP - Pointer to memory ** Returns : Nothing ** =================================================================== */ void McuUtility_SetValue24LE(uint32_t data, uint8_t *dataP) { dataP[0] = (uint8_t)(data&0xff); /* LSB */ dataP[1] = (uint8_t)((data>>8)&0xff); dataP[2] = (uint8_t)((data>>16)&0xff); } /* ** =================================================================== ** Method : SetValue32LE (component Utility) ** ** Description : ** Stores a 32bit value in memory as Little Endian ** Parameters : ** NAME - DESCRIPTION ** data - Value to store ** * dataP - Pointer to memory ** Returns : Nothing ** =================================================================== */ void McuUtility_SetValue32LE(uint32_t data, uint8_t *dataP) { dataP[0] = (uint8_t)(data&0xff); /* LSB */ dataP[1] = (uint8_t)((data>>8)&0xff); dataP[2] = (uint8_t)((data>>16)&0xff); dataP[3] = (uint8_t)((data>>24)&0xff); } /* ** =================================================================== ** Method : Deinit (component Utility) ** ** Description : ** Driver De-Initialization ** Parameters : None ** Returns : Nothing ** =================================================================== */ void McuUtility_Deinit(void) { /* nothing needed */ } /* ** =================================================================== ** Method : Init (component Utility) ** ** Description : ** Driver Initialization ** Parameters : None ** Returns : Nothing ** =================================================================== */ void McuUtility_Init(void) { /* nothing needed */ } /* ** =================================================================== ** Method : map (component Utility) ** ** Description : ** Maps a value from one range to another ** Parameters : ** NAME - DESCRIPTION ** x - value to be mapped ** in_min - input range minimum value ** in_max - input range maximum value ** out_min - output range minimum value ** out_max - output range maximum value ** Returns : ** --- - remapped value ** =================================================================== */ int32_t McuUtility_map(int32_t x, int32_t in_min, int32_t in_max, int32_t out_min, int32_t out_max) { #if 0 /* original Arduino implementation */ return (x-in_min)*(out_max-out_min)/(in_max-in_min)+out_min; #else /* improved version, see https://github.com/arduino/Arduino/issues/2466 */ if ((in_max - in_min) > (out_max - out_min)) { return (x - in_min) * (out_max - out_min+1) / (in_max - in_min+1) + out_min; } else { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } #endif } /* ** =================================================================== ** Method : constrain (component Utility) ** ** Description : ** Makes sure that a given input value is inside a given range. ** Parameters : ** NAME - DESCRIPTION ** val - input value ** min - range minimum value ** max - range maximum value ** Returns : ** --- - the constrained value ** =================================================================== */ int32_t McuUtility_constrain(int32_t val, int32_t min, int32_t max) { if (valmax) { return max; } return val; } /* ** =================================================================== ** Method : random (component Utility) ** ** Description : ** Provides a random value. You have to call intialize the ** random number generator with randomSetSeed() first! ** Parameters : ** NAME - DESCRIPTION ** min - range minimum value ** max - range maximum value ** Returns : ** --- - random value between min and max ** =================================================================== */ int32_t McuUtility_random(int32_t min, int32_t max) { int32_t val; val = rand()%(max-min+1)+min; return McuUtility_constrain(val, min, max); } /* ** =================================================================== ** Method : randomSetSeed (component Utility) ** ** Description : ** Sets a seed for the random number generator ** Parameters : ** NAME - DESCRIPTION ** seed - seed to be used for random number ** generator ** Returns : Nothing ** =================================================================== */ void McuUtility_randomSetSeed(unsigned int seed) { srand(seed); /* set random number generator seed */ } /* ** =================================================================== ** Method : map64 (component Utility) ** ** Description : ** Maps a value from one range to another, using 64bit math ** Parameters : ** NAME - DESCRIPTION ** x - value to be mapped ** in_min - input range minimum value ** in_max - input range maximum value ** out_min - output range maximum value ** out_max - ** Returns : ** --- - remapped value ** =================================================================== */ #ifdef __GNUC__ /* HIWARE compiler does not support 64bit data types */ int64_t McuUtility_map64(int64_t x, int64_t in_min, int64_t in_max, int64_t out_min, int64_t out_max) { if ((in_max - in_min) > (out_max - out_min)) { return (x - in_min) * (out_max - out_min+1) / (in_max - in_min+1) + out_min; } else { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } } #endif /* ** =================================================================== ** Method : strcatNumHex (component Utility) ** ** Description : ** Appends a value as hex valalue to a string buffer as hex ** number (without a 0x prefix), with variable number of digits ** Parameters : ** NAME - DESCRIPTION ** * dst - Pointer to destination string ** dstSize - Size of the destination buffer (in ** bytes). ** num - Value to convert. ** nofBytes - Number of bytes to write ** Returns : Nothing ** =================================================================== */ void McuUtility_strcatNumHex(uint8_t *dst, size_t dstSize, uint32_t num, uint8_t nofBytes) { if (nofBytes==1) { McuUtility_strcatNum8Hex(dst, dstSize, (uint8_t)num); } else if (nofBytes==2) { McuUtility_strcatNum16Hex(dst, dstSize, (uint16_t)num); } else if (nofBytes==3) { McuUtility_strcatNum24Hex(dst, dstSize, num); } else { /* nofBytes==4 */ McuUtility_strcatNum32Hex(dst, dstSize, num); } } /* ** =================================================================== ** Method : ScanRGB (component Utility) ** ** Description : ** Scans a RGB value and stores it in r, g and b. String can be ** a single hex number (0x120506) or three decimal values (18 5 ** 6) ** Parameters : ** NAME - DESCRIPTION ** str - String to scan ** * r - Pointer to red value ** * g - Pointer to green value ** * b - Pointer to blue value ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanRGB(const unsigned char **str, uint8_t *r, uint8_t *g, uint8_t *b) { const unsigned char *p; int32_t val32; int32_t rv, gv, bv; p = *str; while(*p==' ') { p++; /* skip leading spaces */ } if ( *p=='0' && *(p+1)=='x' /* hexadecimal, read single number */ && McuUtility_xatoi(&p, &val32)==ERR_OK && val32 <= 0xffffff ) { *r = (uint8_t)((val32>>16)&0xff); *g = (uint8_t)((val32>>8)&0xff); *b = (uint8_t)(val32&0xff); *str = p; return ERR_OK; } else { /* not starting with 0x (hex): read three values */ if ( McuUtility_xatoi(&p, &rv)==ERR_OK && rv>=0 && rv<=0xff && McuUtility_xatoi(&p, &gv)==ERR_OK && gv>=0 && gv<=0xff && McuUtility_xatoi(&p, &bv)==ERR_OK && bv>=0 && bv<=0xff ) { *r = (uint8_t)rv; *g = (uint8_t)gv; *b = (uint8_t)bv; *str = p; return ERR_OK; } } return ERR_FAILED; } /* ** =================================================================== ** Method : ScanWRGB (component Utility) ** ** Description : ** Scans a WRGB value and stores it in r, g, b and w. String ** can be a single hex number (0x12050608) or three decimal ** values (18 5 6 8) ** Parameters : ** NAME - DESCRIPTION ** str - String to scan ** * w - Pointer to white value ** * r - Pointer to red value ** * g - Pointer to green value ** * b - Pointer to blue value ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanWRGB(const unsigned char **str, uint8_t *w, uint8_t *r, uint8_t *g, uint8_t *b) { const unsigned char *p; int32_t val32; int32_t rv, gv, bv, wv; p = *str; while(*p==' ') { p++; /* skip leading spaces */ } if ( *p=='0' && *(p+1)=='x' /* hexadecimal, read single number */ && McuUtility_xatoi(&p, &val32)==ERR_OK ) { *w = (uint8_t)((val32>>24)&0xff); *r = (uint8_t)((val32>>16)&0xff); *g = (uint8_t)((val32>>8)&0xff); *b = (uint8_t)(val32&0xff); *str = p; return ERR_OK; } else { /* not starting with 0x (hex): read three values */ if ( McuUtility_xatoi(&p, &rv)==ERR_OK && rv>=0 && rv<=0xff && McuUtility_xatoi(&p, &gv)==ERR_OK && gv>=0 && gv<=0xff && McuUtility_xatoi(&p, &bv)==ERR_OK && bv>=0 && bv<=0xff && McuUtility_xatoi(&p, &wv)==ERR_OK && wv>=0 && wv<=0xff ) { *w = (uint8_t)wv; *r = (uint8_t)rv; *g = (uint8_t)gv; *b = (uint8_t)bv; *str = p; return ERR_OK; } } return ERR_FAILED; } /* ** =================================================================== ** Method : ScanRGB32 (component Utility) ** ** Description : ** Scans a RGB value and stores it in a single 32bit value. ** String can be a single hex number (0x120506) or three ** decimal values (18 5 6) ** Parameters : ** NAME - DESCRIPTION ** str - String to scan ** * rgb - Pointer to rgb value ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanRGB32(const unsigned char **str, uint32_t *rgb) { uint8_t res, r, g, b; res = McuUtility_ScanRGB(str, &r, &g, &b); if (res==ERR_OK) { *rgb = ((uint32_t)r<<16)|((uint32_t)g<<8)|b; return ERR_OK; } return ERR_FAILED; } /* ** =================================================================== ** Method : ScanWRGB32 (component Utility) ** ** Description : ** Scans a WRGB value and stores it in a single 32bit value. ** String can be a single hex number (0x12050608) or three ** decimal values (18 5 6 8) ** Parameters : ** NAME - DESCRIPTION ** str - String to scan ** * rgbw - Pointer to wrgb value ** Returns : ** --- - Error code ** =================================================================== */ uint8_t McuUtility_ScanWRGB32(const unsigned char **str, uint32_t *rgbw) { uint8_t res, r, g, b, w; res = McuUtility_ScanWRGB(str, &w, &r, &g, &b); if (res==ERR_OK) { *rgbw = ((uint32_t)w<<24)|((uint32_t)r<<16)|((uint32_t)g<<8)|b; return ERR_OK; } return ERR_FAILED; } /* ** =================================================================== ** Method : SkipSpaces (component Utility) ** ** Description : ** Skips spaces ** Parameters : ** NAME - DESCRIPTION ** * str - Pointer to string to scan. Returns until ** where it has scanned. ** Returns : Nothing ** =================================================================== */ void McuUtility_SkipSpaces(const unsigned char **str) { while(**str == ' ') { (*str)++; /* skip space */ } } /* END McuUtility. */ /*! ** @} */