Initial release
Fork of nrf51-sdk by
Embed:
(wiki syntax)
Show/hide line numbers
app_util.h
Go to the documentation of this file.
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 11:17:14 by 1.7.2