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 nRF51822 by
nordic/nrf-sdk/app_common/app_util.h@0:eff01767de02, 2014-03-26 (annotated)
- Committer:
- bogdanm
- Date:
- Wed Mar 26 14:38:17 2014 +0000
- Revision:
- 0:eff01767de02
- Child:
- 5:b11766b636aa
Initial import of the nRF51822 code
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
bogdanm | 0:eff01767de02 | 1 | /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. |
bogdanm | 0:eff01767de02 | 2 | * |
bogdanm | 0:eff01767de02 | 3 | * The information contained herein is property of Nordic Semiconductor ASA. |
bogdanm | 0:eff01767de02 | 4 | * Terms and conditions of usage are described in detail in NORDIC |
bogdanm | 0:eff01767de02 | 5 | * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. |
bogdanm | 0:eff01767de02 | 6 | * |
bogdanm | 0:eff01767de02 | 7 | * Licensees are granted free, non-transferable use of the information. NO |
bogdanm | 0:eff01767de02 | 8 | * WARRANTY of ANY KIND is provided. This heading must NOT be removed from |
bogdanm | 0:eff01767de02 | 9 | * the file. |
bogdanm | 0:eff01767de02 | 10 | * |
bogdanm | 0:eff01767de02 | 11 | */ |
bogdanm | 0:eff01767de02 | 12 | |
bogdanm | 0:eff01767de02 | 13 | /** @file |
bogdanm | 0:eff01767de02 | 14 | * |
bogdanm | 0:eff01767de02 | 15 | * @defgroup app_util Utility Functions and Definitions |
bogdanm | 0:eff01767de02 | 16 | * @{ |
bogdanm | 0:eff01767de02 | 17 | * @ingroup app_common |
bogdanm | 0:eff01767de02 | 18 | * |
bogdanm | 0:eff01767de02 | 19 | * @brief Various types and definitions available to all applications. |
bogdanm | 0:eff01767de02 | 20 | */ |
bogdanm | 0:eff01767de02 | 21 | |
bogdanm | 0:eff01767de02 | 22 | #ifndef APP_UTIL_H__ |
bogdanm | 0:eff01767de02 | 23 | #define APP_UTIL_H__ |
bogdanm | 0:eff01767de02 | 24 | |
bogdanm | 0:eff01767de02 | 25 | #include <stdint.h> |
bogdanm | 0:eff01767de02 | 26 | #include "nordic_global.h" |
bogdanm | 0:eff01767de02 | 27 | #include "compiler_abstraction.h" |
bogdanm | 0:eff01767de02 | 28 | #include "nrf51.h" |
bogdanm | 0:eff01767de02 | 29 | #include "app_error.h" |
bogdanm | 0:eff01767de02 | 30 | |
bogdanm | 0:eff01767de02 | 31 | /**@brief The interrupt priorities available to the application while the softdevice is active. */ |
bogdanm | 0:eff01767de02 | 32 | typedef enum |
bogdanm | 0:eff01767de02 | 33 | { |
bogdanm | 0:eff01767de02 | 34 | APP_IRQ_PRIORITY_HIGH = 1, |
bogdanm | 0:eff01767de02 | 35 | APP_IRQ_PRIORITY_LOW = 3 |
bogdanm | 0:eff01767de02 | 36 | } app_irq_priority_t; |
bogdanm | 0:eff01767de02 | 37 | |
bogdanm | 0:eff01767de02 | 38 | enum |
bogdanm | 0:eff01767de02 | 39 | { |
bogdanm | 0:eff01767de02 | 40 | UNIT_0_625_MS = 625, /**< Number of microseconds in 0.625 milliseconds. */ |
bogdanm | 0:eff01767de02 | 41 | UNIT_1_25_MS = 1250, /**< Number of microseconds in 1.25 milliseconds. */ |
bogdanm | 0:eff01767de02 | 42 | UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */ |
bogdanm | 0:eff01767de02 | 43 | }; |
bogdanm | 0:eff01767de02 | 44 | |
bogdanm | 0:eff01767de02 | 45 | #define NRF_APP_PRIORITY_THREAD 4 /**< "Interrupt level" when running in Thread Mode. */ |
bogdanm | 0:eff01767de02 | 46 | |
bogdanm | 0:eff01767de02 | 47 | /**@cond NO_DOXYGEN */ |
bogdanm | 0:eff01767de02 | 48 | #define EXTERNAL_INT_VECTOR_OFFSET 16 |
bogdanm | 0:eff01767de02 | 49 | /**@endcond */ |
bogdanm | 0:eff01767de02 | 50 | |
bogdanm | 0:eff01767de02 | 51 | #define PACKED(TYPE) __packed TYPE |
bogdanm | 0:eff01767de02 | 52 | |
bogdanm | 0:eff01767de02 | 53 | /**@brief Macro for doing static (i.e. compile time) assertion. |
bogdanm | 0:eff01767de02 | 54 | * |
bogdanm | 0:eff01767de02 | 55 | * @note If the assertion fails when compiling using Keil, the compiler will report error message |
bogdanm | 0:eff01767de02 | 56 | * "error: #94: the size of an array must be greater than zero" (while gcc will list the |
bogdanm | 0:eff01767de02 | 57 | * symbol static_assert_failed, making the error message more readable). |
bogdanm | 0:eff01767de02 | 58 | * If the supplied expression can not be evaluated at compile time, Keil will report |
bogdanm | 0:eff01767de02 | 59 | * "error: #28: expression must have a constant value". |
bogdanm | 0:eff01767de02 | 60 | * |
bogdanm | 0:eff01767de02 | 61 | * @note The macro is intentionally implemented not using do while(0), allowing it to be used |
bogdanm | 0:eff01767de02 | 62 | * outside function blocks (e.g. close to global type- and variable declarations). |
bogdanm | 0:eff01767de02 | 63 | * If used in a code block, it must be used before any executable code in this block. |
bogdanm | 0:eff01767de02 | 64 | * |
bogdanm | 0:eff01767de02 | 65 | * @param[in] EXPR Constant expression to be verified. |
bogdanm | 0:eff01767de02 | 66 | */ |
bogdanm | 0:eff01767de02 | 67 | |
bogdanm | 0:eff01767de02 | 68 | #define STATIC_ASSERT(EXPR) typedef char static_assert_failed[(EXPR) ? 1 : -1] |
bogdanm | 0:eff01767de02 | 69 | |
bogdanm | 0:eff01767de02 | 70 | /**@brief type for holding an encoded (i.e. little endian) 16 bit unsigned integer. */ |
bogdanm | 0:eff01767de02 | 71 | typedef uint8_t uint16_le_t[2]; |
bogdanm | 0:eff01767de02 | 72 | |
bogdanm | 0:eff01767de02 | 73 | /**@brief type for holding an encoded (i.e. little endian) 32 bit unsigned integer. */ |
bogdanm | 0:eff01767de02 | 74 | typedef uint8_t uint32_le_t[4]; |
bogdanm | 0:eff01767de02 | 75 | |
bogdanm | 0:eff01767de02 | 76 | /**@brief Byte array type. */ |
bogdanm | 0:eff01767de02 | 77 | typedef struct |
bogdanm | 0:eff01767de02 | 78 | { |
bogdanm | 0:eff01767de02 | 79 | uint16_t size; /**< Number of array entries. */ |
bogdanm | 0:eff01767de02 | 80 | uint8_t * p_data; /**< Pointer to array entries. */ |
bogdanm | 0:eff01767de02 | 81 | } uint8_array_t; |
bogdanm | 0:eff01767de02 | 82 | |
bogdanm | 0:eff01767de02 | 83 | /**@brief Macro for entering a critical region. |
bogdanm | 0:eff01767de02 | 84 | * |
bogdanm | 0:eff01767de02 | 85 | * @note Due to implementation details, there must exist one and only one call to |
bogdanm | 0:eff01767de02 | 86 | * CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located |
bogdanm | 0:eff01767de02 | 87 | * in the same scope. |
bogdanm | 0:eff01767de02 | 88 | */ |
bogdanm | 0:eff01767de02 | 89 | #define CRITICAL_REGION_ENTER() \ |
bogdanm | 0:eff01767de02 | 90 | { \ |
bogdanm | 0:eff01767de02 | 91 | uint8_t IS_NESTED_CRITICAL_REGION = 0; \ |
bogdanm | 0:eff01767de02 | 92 | uint32_t CURRENT_INT_PRI = current_int_priority_get(); \ |
bogdanm | 0:eff01767de02 | 93 | if (CURRENT_INT_PRI != APP_IRQ_PRIORITY_HIGH) \ |
bogdanm | 0:eff01767de02 | 94 | { \ |
bogdanm | 0:eff01767de02 | 95 | uint32_t ERR_CODE = sd_nvic_critical_region_enter(&IS_NESTED_CRITICAL_REGION); \ |
bogdanm | 0:eff01767de02 | 96 | if (ERR_CODE == NRF_ERROR_SOFTDEVICE_NOT_ENABLED) \ |
bogdanm | 0:eff01767de02 | 97 | { \ |
bogdanm | 0:eff01767de02 | 98 | __disable_irq(); \ |
bogdanm | 0:eff01767de02 | 99 | } \ |
bogdanm | 0:eff01767de02 | 100 | else \ |
bogdanm | 0:eff01767de02 | 101 | { \ |
bogdanm | 0:eff01767de02 | 102 | APP_ERROR_CHECK(ERR_CODE); \ |
bogdanm | 0:eff01767de02 | 103 | } \ |
bogdanm | 0:eff01767de02 | 104 | } |
bogdanm | 0:eff01767de02 | 105 | |
bogdanm | 0:eff01767de02 | 106 | /**@brief Macro for leaving a critical region. |
bogdanm | 0:eff01767de02 | 107 | * |
bogdanm | 0:eff01767de02 | 108 | * @note Due to implementation details, there must exist one and only one call to |
bogdanm | 0:eff01767de02 | 109 | * CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located |
bogdanm | 0:eff01767de02 | 110 | * in the same scope. |
bogdanm | 0:eff01767de02 | 111 | */ |
bogdanm | 0:eff01767de02 | 112 | #define CRITICAL_REGION_EXIT() \ |
bogdanm | 0:eff01767de02 | 113 | if (CURRENT_INT_PRI != APP_IRQ_PRIORITY_HIGH) \ |
bogdanm | 0:eff01767de02 | 114 | { \ |
bogdanm | 0:eff01767de02 | 115 | uint32_t ERR_CODE; \ |
bogdanm | 0:eff01767de02 | 116 | __enable_irq(); \ |
bogdanm | 0:eff01767de02 | 117 | ERR_CODE = sd_nvic_critical_region_exit(IS_NESTED_CRITICAL_REGION); \ |
bogdanm | 0:eff01767de02 | 118 | if (ERR_CODE != NRF_ERROR_SOFTDEVICE_NOT_ENABLED) \ |
bogdanm | 0:eff01767de02 | 119 | { \ |
bogdanm | 0:eff01767de02 | 120 | APP_ERROR_CHECK(ERR_CODE); \ |
bogdanm | 0:eff01767de02 | 121 | } \ |
bogdanm | 0:eff01767de02 | 122 | } \ |
bogdanm | 0:eff01767de02 | 123 | } |
bogdanm | 0:eff01767de02 | 124 | |
bogdanm | 0:eff01767de02 | 125 | /**@brief Perform rounded integer division (as opposed to truncating the result). |
bogdanm | 0:eff01767de02 | 126 | * |
bogdanm | 0:eff01767de02 | 127 | * @param[in] A Numerator. |
bogdanm | 0:eff01767de02 | 128 | * @param[in] B Denominator. |
bogdanm | 0:eff01767de02 | 129 | * |
bogdanm | 0:eff01767de02 | 130 | * @return Rounded (integer) result of dividing A by B. |
bogdanm | 0:eff01767de02 | 131 | */ |
bogdanm | 0:eff01767de02 | 132 | #define ROUNDED_DIV(A, B) (((A) + ((B) / 2)) / (B)) |
bogdanm | 0:eff01767de02 | 133 | |
bogdanm | 0:eff01767de02 | 134 | /**@brief Check if the integer provided is a power of two. |
bogdanm | 0:eff01767de02 | 135 | * |
bogdanm | 0:eff01767de02 | 136 | * @param[in] A Number to be tested. |
bogdanm | 0:eff01767de02 | 137 | * |
bogdanm | 0:eff01767de02 | 138 | * @return true if value is power of two. |
bogdanm | 0:eff01767de02 | 139 | * @return false if value not power of two. |
bogdanm | 0:eff01767de02 | 140 | */ |
bogdanm | 0:eff01767de02 | 141 | #define IS_POWER_OF_TWO(A) ( ((A) != 0) && ((((A) - 1) & (A)) == 0) ) |
bogdanm | 0:eff01767de02 | 142 | |
bogdanm | 0:eff01767de02 | 143 | /**@brief To convert ticks to millisecond |
bogdanm | 0:eff01767de02 | 144 | * @param[in] time Number of millseconds that needs to be converted. |
bogdanm | 0:eff01767de02 | 145 | * @param[in] resolution Units to be converted. |
bogdanm | 0:eff01767de02 | 146 | */ |
bogdanm | 0:eff01767de02 | 147 | #define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) |
bogdanm | 0:eff01767de02 | 148 | |
bogdanm | 0:eff01767de02 | 149 | |
bogdanm | 0:eff01767de02 | 150 | /**@brief Perform integer division, making sure the result is rounded up. |
bogdanm | 0:eff01767de02 | 151 | * |
bogdanm | 0:eff01767de02 | 152 | * @details One typical use for this is to compute the number of objects with size B is needed to |
bogdanm | 0:eff01767de02 | 153 | * hold A number of bytes. |
bogdanm | 0:eff01767de02 | 154 | * |
bogdanm | 0:eff01767de02 | 155 | * @param[in] A Numerator. |
bogdanm | 0:eff01767de02 | 156 | * @param[in] B Denominator. |
bogdanm | 0:eff01767de02 | 157 | * |
bogdanm | 0:eff01767de02 | 158 | * @return Integer result of dividing A by B, rounded up. |
bogdanm | 0:eff01767de02 | 159 | */ |
bogdanm | 0:eff01767de02 | 160 | #define CEIL_DIV(A, B) \ |
bogdanm | 0:eff01767de02 | 161 | /*lint -save -e573 */ \ |
bogdanm | 0:eff01767de02 | 162 | ((((A) - 1) / (B)) + 1) \ |
bogdanm | 0:eff01767de02 | 163 | /*lint -restore */ |
bogdanm | 0:eff01767de02 | 164 | |
bogdanm | 0:eff01767de02 | 165 | /**@brief Function for encoding a uint16 value. |
bogdanm | 0:eff01767de02 | 166 | * |
bogdanm | 0:eff01767de02 | 167 | * @param[in] value Value to be encoded. |
bogdanm | 0:eff01767de02 | 168 | * @param[out] p_encoded_data Buffer where the encoded data is to be written. |
bogdanm | 0:eff01767de02 | 169 | * |
bogdanm | 0:eff01767de02 | 170 | * @return Number of bytes written. |
bogdanm | 0:eff01767de02 | 171 | */ |
bogdanm | 0:eff01767de02 | 172 | static __INLINE uint8_t uint16_encode(uint16_t value, uint8_t * p_encoded_data) |
bogdanm | 0:eff01767de02 | 173 | { |
bogdanm | 0:eff01767de02 | 174 | p_encoded_data[0] = (uint8_t) ((value & 0x00FF) >> 0); |
bogdanm | 0:eff01767de02 | 175 | p_encoded_data[1] = (uint8_t) ((value & 0xFF00) >> 8); |
bogdanm | 0:eff01767de02 | 176 | return sizeof(uint16_t); |
bogdanm | 0:eff01767de02 | 177 | } |
bogdanm | 0:eff01767de02 | 178 | |
bogdanm | 0:eff01767de02 | 179 | /**@brief Function for encoding a uint32 value. |
bogdanm | 0:eff01767de02 | 180 | * |
bogdanm | 0:eff01767de02 | 181 | * @param[in] value Value to be encoded. |
bogdanm | 0:eff01767de02 | 182 | * @param[out] p_encoded_data Buffer where the encoded data is to be written. |
bogdanm | 0:eff01767de02 | 183 | * |
bogdanm | 0:eff01767de02 | 184 | * @return Number of bytes written. |
bogdanm | 0:eff01767de02 | 185 | */ |
bogdanm | 0:eff01767de02 | 186 | static __INLINE uint8_t uint32_encode(uint32_t value, uint8_t * p_encoded_data) |
bogdanm | 0:eff01767de02 | 187 | { |
bogdanm | 0:eff01767de02 | 188 | p_encoded_data[0] = (uint8_t) ((value & 0x000000FF) >> 0); |
bogdanm | 0:eff01767de02 | 189 | p_encoded_data[1] = (uint8_t) ((value & 0x0000FF00) >> 8); |
bogdanm | 0:eff01767de02 | 190 | p_encoded_data[2] = (uint8_t) ((value & 0x00FF0000) >> 16); |
bogdanm | 0:eff01767de02 | 191 | p_encoded_data[3] = (uint8_t) ((value & 0xFF000000) >> 24); |
bogdanm | 0:eff01767de02 | 192 | return sizeof(uint32_t); |
bogdanm | 0:eff01767de02 | 193 | } |
bogdanm | 0:eff01767de02 | 194 | |
bogdanm | 0:eff01767de02 | 195 | /**@brief Function for decoding a uint16 value. |
bogdanm | 0:eff01767de02 | 196 | * |
bogdanm | 0:eff01767de02 | 197 | * @param[in] p_encoded_data Buffer where the encoded data is stored. |
bogdanm | 0:eff01767de02 | 198 | * |
bogdanm | 0:eff01767de02 | 199 | * @return Decoded value. |
bogdanm | 0:eff01767de02 | 200 | */ |
bogdanm | 0:eff01767de02 | 201 | static __INLINE uint16_t uint16_decode(const uint8_t * p_encoded_data) |
bogdanm | 0:eff01767de02 | 202 | { |
bogdanm | 0:eff01767de02 | 203 | return ( (((uint16_t)((uint8_t *)p_encoded_data)[0])) | |
bogdanm | 0:eff01767de02 | 204 | (((uint16_t)((uint8_t *)p_encoded_data)[1]) << 8 )); |
bogdanm | 0:eff01767de02 | 205 | } |
bogdanm | 0:eff01767de02 | 206 | |
bogdanm | 0:eff01767de02 | 207 | /**@brief Function for decoding a uint32 value. |
bogdanm | 0:eff01767de02 | 208 | * |
bogdanm | 0:eff01767de02 | 209 | * @param[in] p_encoded_data Buffer where the encoded data is stored. |
bogdanm | 0:eff01767de02 | 210 | * |
bogdanm | 0:eff01767de02 | 211 | * @return Decoded value. |
bogdanm | 0:eff01767de02 | 212 | */ |
bogdanm | 0:eff01767de02 | 213 | static __INLINE uint32_t uint32_decode(const uint8_t * p_encoded_data) |
bogdanm | 0:eff01767de02 | 214 | { |
bogdanm | 0:eff01767de02 | 215 | return ( (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) | |
bogdanm | 0:eff01767de02 | 216 | (((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) | |
bogdanm | 0:eff01767de02 | 217 | (((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16) | |
bogdanm | 0:eff01767de02 | 218 | (((uint32_t)((uint8_t *)p_encoded_data)[3]) << 24 )); |
bogdanm | 0:eff01767de02 | 219 | } |
bogdanm | 0:eff01767de02 | 220 | |
bogdanm | 0:eff01767de02 | 221 | |
bogdanm | 0:eff01767de02 | 222 | /**@brief Function for finding the current interrupt level. |
bogdanm | 0:eff01767de02 | 223 | * |
bogdanm | 0:eff01767de02 | 224 | * @return Current interrupt level. |
bogdanm | 0:eff01767de02 | 225 | * @retval APP_IRQ_PRIORITY_HIGH We are running in Application High interrupt level. |
bogdanm | 0:eff01767de02 | 226 | * @retval APP_IRQ_PRIORITY_LOW We are running in Application Low interrupt level. |
bogdanm | 0:eff01767de02 | 227 | * @retval APP_IRQ_PRIORITY_THREAD We are running in Thread Mode. |
bogdanm | 0:eff01767de02 | 228 | */ |
bogdanm | 0:eff01767de02 | 229 | static __INLINE uint8_t current_int_priority_get(void) |
bogdanm | 0:eff01767de02 | 230 | { |
bogdanm | 0:eff01767de02 | 231 | uint32_t isr_vector_num = (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk); |
bogdanm | 0:eff01767de02 | 232 | if (isr_vector_num > 0) |
bogdanm | 0:eff01767de02 | 233 | { |
bogdanm | 0:eff01767de02 | 234 | int32_t irq_type = ((int32_t)isr_vector_num - EXTERNAL_INT_VECTOR_OFFSET); |
bogdanm | 0:eff01767de02 | 235 | return (NVIC_GetPriority((IRQn_Type)irq_type) & 0xFF); |
bogdanm | 0:eff01767de02 | 236 | } |
bogdanm | 0:eff01767de02 | 237 | else |
bogdanm | 0:eff01767de02 | 238 | { |
bogdanm | 0:eff01767de02 | 239 | return NRF_APP_PRIORITY_THREAD; |
bogdanm | 0:eff01767de02 | 240 | } |
bogdanm | 0:eff01767de02 | 241 | } |
bogdanm | 0:eff01767de02 | 242 | |
bogdanm | 0:eff01767de02 | 243 | /** @brief Function for converting the input voltage (in milli volts) into percentage of 3.0 Volts. |
bogdanm | 0:eff01767de02 | 244 | * |
bogdanm | 0:eff01767de02 | 245 | * @details The calculation is based on a linearized version of the battery's discharge |
bogdanm | 0:eff01767de02 | 246 | * curve. 3.0V returns 100% battery level. The limit for power failure is 2.1V and |
bogdanm | 0:eff01767de02 | 247 | * is considered to be the lower boundary. |
bogdanm | 0:eff01767de02 | 248 | * |
bogdanm | 0:eff01767de02 | 249 | * The discharge curve for CR2032 is non-linear. In this model it is split into |
bogdanm | 0:eff01767de02 | 250 | * 4 linear sections: |
bogdanm | 0:eff01767de02 | 251 | * - Section 1: 3.0V - 2.9V = 100% - 42% (58% drop on 100 mV) |
bogdanm | 0:eff01767de02 | 252 | * - Section 2: 2.9V - 2.74V = 42% - 18% (24% drop on 160 mV) |
bogdanm | 0:eff01767de02 | 253 | * - Section 3: 2.74V - 2.44V = 18% - 6% (12% drop on 300 mV) |
bogdanm | 0:eff01767de02 | 254 | * - Section 4: 2.44V - 2.1V = 6% - 0% (6% drop on 340 mV) |
bogdanm | 0:eff01767de02 | 255 | * |
bogdanm | 0:eff01767de02 | 256 | * These numbers are by no means accurate. Temperature and |
bogdanm | 0:eff01767de02 | 257 | * load in the actual application is not accounted for! |
bogdanm | 0:eff01767de02 | 258 | * |
bogdanm | 0:eff01767de02 | 259 | * @param[in] mvolts The voltage in mV |
bogdanm | 0:eff01767de02 | 260 | * |
bogdanm | 0:eff01767de02 | 261 | * @return Battery level in percent. |
bogdanm | 0:eff01767de02 | 262 | */ |
bogdanm | 0:eff01767de02 | 263 | static __INLINE uint8_t battery_level_in_percent(const uint16_t mvolts) |
bogdanm | 0:eff01767de02 | 264 | { |
bogdanm | 0:eff01767de02 | 265 | uint8_t battery_level; |
bogdanm | 0:eff01767de02 | 266 | |
bogdanm | 0:eff01767de02 | 267 | if (mvolts >= 3000) |
bogdanm | 0:eff01767de02 | 268 | { |
bogdanm | 0:eff01767de02 | 269 | battery_level = 100; |
bogdanm | 0:eff01767de02 | 270 | } |
bogdanm | 0:eff01767de02 | 271 | else if (mvolts > 2900) |
bogdanm | 0:eff01767de02 | 272 | { |
bogdanm | 0:eff01767de02 | 273 | battery_level = 100 - ((3000 - mvolts) * 58) / 100; |
bogdanm | 0:eff01767de02 | 274 | } |
bogdanm | 0:eff01767de02 | 275 | else if (mvolts > 2740) |
bogdanm | 0:eff01767de02 | 276 | { |
bogdanm | 0:eff01767de02 | 277 | battery_level = 42 - ((2900 - mvolts) * 24) / 160; |
bogdanm | 0:eff01767de02 | 278 | } |
bogdanm | 0:eff01767de02 | 279 | else if (mvolts > 2440) |
bogdanm | 0:eff01767de02 | 280 | { |
bogdanm | 0:eff01767de02 | 281 | battery_level = 18 - ((2740 - mvolts) * 12) / 300; |
bogdanm | 0:eff01767de02 | 282 | } |
bogdanm | 0:eff01767de02 | 283 | else if (mvolts > 2100) |
bogdanm | 0:eff01767de02 | 284 | { |
bogdanm | 0:eff01767de02 | 285 | battery_level = 6 - ((2440 - mvolts) * 6) / 340; |
bogdanm | 0:eff01767de02 | 286 | } |
bogdanm | 0:eff01767de02 | 287 | else |
bogdanm | 0:eff01767de02 | 288 | { |
bogdanm | 0:eff01767de02 | 289 | battery_level = 0; |
bogdanm | 0:eff01767de02 | 290 | } |
bogdanm | 0:eff01767de02 | 291 | |
bogdanm | 0:eff01767de02 | 292 | return battery_level; |
bogdanm | 0:eff01767de02 | 293 | } |
bogdanm | 0:eff01767de02 | 294 | |
bogdanm | 0:eff01767de02 | 295 | /**@brief Function for checking if a pointer value is aligned to a 4 byte boundary. |
bogdanm | 0:eff01767de02 | 296 | * |
bogdanm | 0:eff01767de02 | 297 | * @param[in] p Pointer value to be checked. |
bogdanm | 0:eff01767de02 | 298 | * |
bogdanm | 0:eff01767de02 | 299 | * @return TRUE if pointer is aligned to a 4 byte boundary, FALSE otherwise. |
bogdanm | 0:eff01767de02 | 300 | */ |
bogdanm | 0:eff01767de02 | 301 | static __INLINE bool is_word_aligned(void * p) |
bogdanm | 0:eff01767de02 | 302 | { |
bogdanm | 0:eff01767de02 | 303 | return (((uint32_t)p & 0x00000003) == 0); |
bogdanm | 0:eff01767de02 | 304 | } |
bogdanm | 0:eff01767de02 | 305 | |
bogdanm | 0:eff01767de02 | 306 | #endif // APP_UTIL_H__ |
bogdanm | 0:eff01767de02 | 307 | |
bogdanm | 0:eff01767de02 | 308 | /** @} */ |