Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of nrf51-sdk by
app_util.h
00001 /* 00002 * Copyright (c) Nordic Semiconductor ASA 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without modification, 00006 * are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright notice, this 00009 * list of conditions and the following disclaimer. 00010 * 00011 * 2. Redistributions in binary form must reproduce the above copyright notice, this 00012 * list of conditions and the following disclaimer in the documentation and/or 00013 * other materials provided with the distribution. 00014 * 00015 * 3. Neither the name of Nordic Semiconductor ASA nor the names of other 00016 * contributors to this software may be used to endorse or promote products 00017 * derived from this software without specific prior written permission. 00018 * 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00021 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00023 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00024 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 00027 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 * 00031 */ 00032 00033 /** @file 00034 * 00035 * @defgroup app_util Utility Functions and Definitions 00036 * @{ 00037 * @ingroup app_common 00038 * 00039 * @brief Various types and definitions available to all applications. 00040 */ 00041 00042 #ifndef APP_UTIL_H__ 00043 #define APP_UTIL_H__ 00044 00045 #include <stdint.h> 00046 #include <stdbool.h> 00047 #include "compiler_abstraction.h" 00048 00049 enum 00050 { 00051 UNIT_0_625_MS = 625, /**< Number of microseconds in 0.625 milliseconds. */ 00052 UNIT_1_25_MS = 1250, /**< Number of microseconds in 1.25 milliseconds. */ 00053 UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */ 00054 }; 00055 00056 00057 /**@brief Implementation specific macro for delayed macro expansion used in string concatenation 00058 * 00059 * @param[in] lhs Left hand side in concatenation 00060 * @param[in] rhs Right hand side in concatenation 00061 */ 00062 #define STRING_CONCATENATE_IMPL(lhs, rhs) lhs ## rhs 00063 00064 00065 /**@brief Macro used to concatenate string using delayed macro expansion 00066 * 00067 * @note This macro will delay concatenation until the expressions have been resolved 00068 * 00069 * @param[in] lhs Left hand side in concatenation 00070 * @param[in] rhs Right hand side in concatenation 00071 */ 00072 #define STRING_CONCATENATE(lhs, rhs) STRING_CONCATENATE_IMPL(lhs, rhs) 00073 00074 00075 // Disable lint-warnings/errors for STATIC_ASSERT 00076 //lint --emacro(10,STATIC_ASSERT) 00077 //lint --emacro(18,STATIC_ASSERT) 00078 //lint --emacro(19,STATIC_ASSERT) 00079 //lint --emacro(30,STATIC_ASSERT) 00080 //lint --emacro(37,STATIC_ASSERT) 00081 //lint --emacro(42,STATIC_ASSERT) 00082 //lint --emacro(26,STATIC_ASSERT) 00083 //lint --emacro(102,STATIC_ASSERT) 00084 //lint --emacro(533,STATIC_ASSERT) 00085 //lint --emacro(534,STATIC_ASSERT) 00086 //lint --emacro(132,STATIC_ASSERT) 00087 //lint --emacro(414,STATIC_ASSERT) 00088 //lint --emacro(578,STATIC_ASSERT) 00089 //lint --emacro(628,STATIC_ASSERT) 00090 //lint --emacro(648,STATIC_ASSERT) 00091 //lint --emacro(830,STATIC_ASSERT) 00092 00093 00094 /**@brief Macro for doing static (i.e. compile time) assertion. 00095 * 00096 * @note If the EXPR isn't resolvable, then the error message won't be shown. 00097 * 00098 * @note The output of STATIC_ASSERT_MSG will be different across different compilers. 00099 * 00100 * @param[in] EXPR Constant expression to be verified. 00101 */ 00102 #if defined ( __COUNTER__ ) 00103 00104 #define STATIC_ASSERT(EXPR) \ 00105 ;enum { STRING_CONCATENATE(static_assert_, __COUNTER__) = 1/(!!(EXPR)) } 00106 00107 #else 00108 00109 #define STATIC_ASSERT(EXPR) \ 00110 ;enum { STRING_CONCATENATE(assert_line_, __LINE__) = 1/(!!(EXPR)) } 00111 00112 #endif 00113 00114 00115 00116 /**@brief type for holding an encoded (i.e. little endian) 16 bit unsigned integer. */ 00117 typedef uint8_t uint16_le_t[2]; 00118 00119 /**@brief type for holding an encoded (i.e. little endian) 32 bit unsigned integer. */ 00120 typedef uint8_t uint32_le_t[4]; 00121 00122 /**@brief Byte array type. */ 00123 typedef struct 00124 { 00125 uint16_t size; /**< Number of array entries. */ 00126 uint8_t * p_data; /**< Pointer to array entries. */ 00127 } uint8_array_t; 00128 00129 /**@brief Perform rounded integer division (as opposed to truncating the result). 00130 * 00131 * @param[in] A Numerator. 00132 * @param[in] B Denominator. 00133 * 00134 * @return Rounded (integer) result of dividing A by B. 00135 */ 00136 #define ROUNDED_DIV(A, B) (((A) + ((B) / 2)) / (B)) 00137 00138 /**@brief Check if the integer provided is a power of two. 00139 * 00140 * @param[in] A Number to be tested. 00141 * 00142 * @return true if value is power of two. 00143 * @return false if value not power of two. 00144 */ 00145 #define IS_POWER_OF_TWO(A) ( ((A) != 0) && ((((A) - 1) & (A)) == 0) ) 00146 00147 /**@brief To convert milliseconds to ticks. 00148 * @param[in] TIME Number of milliseconds to convert. 00149 * @param[in] RESOLUTION Unit to be converted to in [us/ticks]. 00150 */ 00151 #define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) 00152 00153 /**@brief Perform integer division, making sure the result is rounded up. 00154 * 00155 * @details One typical use for this is to compute the number of objects with size B is needed to 00156 * hold A number of bytes. 00157 * 00158 * @param[in] A Numerator. 00159 * @param[in] B Denominator. 00160 * 00161 * @return Integer result of dividing A by B, rounded up. 00162 */ 00163 #define CEIL_DIV(A, B) \ 00164 (((A) + (B) - 1) / (B)) 00165 00166 /**@brief Function for creating a buffer aligned to 4 bytes. 00167 * 00168 * @param[in] NAME Name of the buffor. 00169 * @param[in] MIN_SIZE Size of this buffor (it will be rounded up to multiples of 4 bytes). 00170 */ 00171 #define WORD_ALIGNED_MEM_BUFF(NAME, MIN_SIZE) static uint32_t NAME[CEIL_DIV(MIN_SIZE, sizeof(uint32_t))] 00172 00173 /**@brief Function for changing the value unit. 00174 * 00175 * @param[in] value Value to be rescaled. 00176 * @param[in] old_unit_reversal Reversal of the incoming unit. 00177 * @param[in] new_unit_reversal Reversal of the desired unit. 00178 * 00179 * @return Number of bytes written. 00180 */ 00181 static __INLINE uint64_t value_rescale(uint32_t value, uint32_t old_unit_reversal, uint16_t new_unit_reversal) 00182 { 00183 return (uint64_t)ROUNDED_DIV((uint64_t)value * new_unit_reversal, old_unit_reversal); 00184 } 00185 00186 /**@brief Function for encoding a uint16 value. 00187 * 00188 * @param[in] value Value to be encoded. 00189 * @param[out] p_encoded_data Buffer where the encoded data is to be written. 00190 * 00191 * @return Number of bytes written. 00192 */ 00193 static __INLINE uint8_t uint16_encode(uint16_t value, uint8_t * p_encoded_data) 00194 { 00195 p_encoded_data[0] = (uint8_t) ((value & 0x00FF) >> 0); 00196 p_encoded_data[1] = (uint8_t) ((value & 0xFF00) >> 8); 00197 return sizeof(uint16_t); 00198 } 00199 00200 /**@brief Function for encoding a three-byte value. 00201 * 00202 * @param[in] value Value to be encoded. 00203 * @param[out] p_encoded_data Buffer where the encoded data is to be written. 00204 * 00205 * @return Number of bytes written. 00206 */ 00207 static __INLINE uint8_t uint24_encode(uint32_t value, uint8_t * p_encoded_data) 00208 { 00209 p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0); 00210 p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8); 00211 p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16); 00212 return 3; 00213 } 00214 00215 /**@brief Function for encoding a uint32 value. 00216 * 00217 * @param[in] value Value to be encoded. 00218 * @param[out] p_encoded_data Buffer where the encoded data is to be written. 00219 * 00220 * @return Number of bytes written. 00221 */ 00222 static __INLINE uint8_t uint32_encode(uint32_t value, uint8_t * p_encoded_data) 00223 { 00224 p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0); 00225 p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8); 00226 p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16); 00227 p_encoded_data[3] = (uint8_t) ((value & 0xFF000000) >> 24); 00228 return sizeof(uint32_t); 00229 } 00230 00231 /**@brief Function for decoding a uint16 value. 00232 * 00233 * @param[in] p_encoded_data Buffer where the encoded data is stored. 00234 * 00235 * @return Decoded value. 00236 */ 00237 static __INLINE uint16_t uint16_decode(const uint8_t * p_encoded_data) 00238 { 00239 return ( (((uint16_t)((uint8_t *)p_encoded_data)[0])) | 00240 (((uint16_t)((uint8_t *)p_encoded_data)[1]) << 8 )); 00241 } 00242 00243 /**@brief Function for decoding a three-byte value. 00244 * 00245 * @param[in] p_encoded_data Buffer where the encoded data is stored. 00246 * 00247 * @return Decoded value (uint32_t). 00248 */ 00249 static __INLINE uint32_t uint24_decode(const uint8_t * p_encoded_data) 00250 { 00251 return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | 00252 (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | 00253 (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16)); 00254 } 00255 00256 /**@brief Function for decoding a uint32 value. 00257 * 00258 * @param[in] p_encoded_data Buffer where the encoded data is stored. 00259 * 00260 * @return Decoded value. 00261 */ 00262 static __INLINE uint32_t uint32_decode(const uint8_t * p_encoded_data) 00263 { 00264 return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | 00265 (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | 00266 (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16) | 00267 (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 24 )); 00268 } 00269 00270 /** @brief Function for converting the input voltage (in milli volts) into percentage of 3.0 Volts. 00271 * 00272 * @details The calculation is based on a linearized version of the battery's discharge 00273 * curve. 3.0V returns 100% battery level. The limit for power failure is 2.1V and 00274 * is considered to be the lower boundary. 00275 * 00276 * The discharge curve for CR2032 is non-linear. In this model it is split into 00277 * 4 linear sections: 00278 * - Section 1: 3.0V - 2.9V = 100% - 42% (58% drop on 100 mV) 00279 * - Section 2: 2.9V - 2.74V = 42% - 18% (24% drop on 160 mV) 00280 * - Section 3: 2.74V - 2.44V = 18% - 6% (12% drop on 300 mV) 00281 * - Section 4: 2.44V - 2.1V = 6% - 0% (6% drop on 340 mV) 00282 * 00283 * These numbers are by no means accurate. Temperature and 00284 * load in the actual application is not accounted for! 00285 * 00286 * @param[in] mvolts The voltage in mV 00287 * 00288 * @return Battery level in percent. 00289 */ 00290 static __INLINE uint8_t battery_level_in_percent(const uint16_t mvolts) 00291 { 00292 uint8_t battery_level; 00293 00294 if (mvolts >= 3000) 00295 { 00296 battery_level = 100; 00297 } 00298 else if (mvolts > 2900) 00299 { 00300 battery_level = 100 - ((3000 - mvolts) * 58) / 100; 00301 } 00302 else if (mvolts > 2740) 00303 { 00304 battery_level = 42 - ((2900 - mvolts) * 24) / 160; 00305 } 00306 else if (mvolts > 2440) 00307 { 00308 battery_level = 18 - ((2740 - mvolts) * 12) / 300; 00309 } 00310 else if (mvolts > 2100) 00311 { 00312 battery_level = 6 - ((2440 - mvolts) * 6) / 340; 00313 } 00314 else 00315 { 00316 battery_level = 0; 00317 } 00318 00319 return battery_level; 00320 } 00321 00322 /**@brief Function for checking if a pointer value is aligned to a 4 byte boundary. 00323 * 00324 * @param[in] p Pointer value to be checked. 00325 * 00326 * @return TRUE if pointer is aligned to a 4 byte boundary, FALSE otherwise. 00327 */ 00328 static __INLINE bool is_word_aligned(void const* p) 00329 { 00330 return (((uintptr_t)p & 0x03) == 0); 00331 } 00332 00333 #endif // APP_UTIL_H__ 00334 00335 /** @} */
Generated on Tue Jul 12 2022 14:11:18 by
