mbed os with nrf51 internal bandgap enabled to read battery level

Dependents:   BLE_file_test BLE_Blink ExternalEncoder

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 /* mbed Microcontroller Library
elessair 0:f269e3021894 2 * Copyright (c) 2006-2013 ARM Limited
elessair 0:f269e3021894 3 *
elessair 0:f269e3021894 4 * Licensed under the Apache License, Version 2.0 (the "License");
elessair 0:f269e3021894 5 * you may not use this file except in compliance with the License.
elessair 0:f269e3021894 6 * You may obtain a copy of the License at
elessair 0:f269e3021894 7 *
elessair 0:f269e3021894 8 * http://www.apache.org/licenses/LICENSE-2.0
elessair 0:f269e3021894 9 *
elessair 0:f269e3021894 10 * Unless required by applicable law or agreed to in writing, software
elessair 0:f269e3021894 11 * distributed under the License is distributed on an "AS IS" BASIS,
elessair 0:f269e3021894 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
elessair 0:f269e3021894 13 * See the License for the specific language governing permissions and
elessair 0:f269e3021894 14 * limitations under the License.
elessair 0:f269e3021894 15 */
elessair 0:f269e3021894 16 #ifndef MBED_CALLCHAIN_OF_FUNCTION_POINTERS_WITH_CONTEXT_H
elessair 0:f269e3021894 17 #define MBED_CALLCHAIN_OF_FUNCTION_POINTERS_WITH_CONTEXT_H
elessair 0:f269e3021894 18
elessair 0:f269e3021894 19 #include <string.h>
elessair 0:f269e3021894 20 #include "FunctionPointerWithContext.h"
elessair 0:f269e3021894 21 #include "SafeBool.h"
elessair 0:f269e3021894 22
elessair 0:f269e3021894 23
elessair 0:f269e3021894 24 /** Group one or more functions in an instance of a CallChainOfFunctionPointersWithContext, then call them in
elessair 0:f269e3021894 25 * sequence using CallChainOfFunctionPointersWithContext::call(). Used mostly by the interrupt chaining code,
elessair 0:f269e3021894 26 * but can be used for other purposes.
elessair 0:f269e3021894 27 *
elessair 0:f269e3021894 28 * Example:
elessair 0:f269e3021894 29 * @code
elessair 0:f269e3021894 30 *
elessair 0:f269e3021894 31 * CallChainOfFunctionPointersWithContext<void *> chain;
elessair 0:f269e3021894 32 *
elessair 0:f269e3021894 33 * void first(void *context) {
elessair 0:f269e3021894 34 * printf("'first' function.\n");
elessair 0:f269e3021894 35 * }
elessair 0:f269e3021894 36 *
elessair 0:f269e3021894 37 * void second(void *context) {
elessair 0:f269e3021894 38 * printf("'second' function.\n");
elessair 0:f269e3021894 39 * }
elessair 0:f269e3021894 40 *
elessair 0:f269e3021894 41 * class Test {
elessair 0:f269e3021894 42 * public:
elessair 0:f269e3021894 43 * void f(void *context) {
elessair 0:f269e3021894 44 * printf("A::f (class member).\n");
elessair 0:f269e3021894 45 * }
elessair 0:f269e3021894 46 * };
elessair 0:f269e3021894 47 *
elessair 0:f269e3021894 48 * int main() {
elessair 0:f269e3021894 49 * Test test;
elessair 0:f269e3021894 50 *
elessair 0:f269e3021894 51 * chain.add(second);
elessair 0:f269e3021894 52 * chain.add_front(first);
elessair 0:f269e3021894 53 * chain.add(&test, &Test::f);
elessair 0:f269e3021894 54 * chain.call();
elessair 0:f269e3021894 55 * }
elessair 0:f269e3021894 56 * @endcode
elessair 0:f269e3021894 57 */
elessair 0:f269e3021894 58 template <typename ContextType>
elessair 0:f269e3021894 59 class CallChainOfFunctionPointersWithContext : public SafeBool<CallChainOfFunctionPointersWithContext<ContextType> > {
elessair 0:f269e3021894 60 public:
elessair 0:f269e3021894 61 /**
elessair 0:f269e3021894 62 * The type of each callback in the callchain.
elessair 0:f269e3021894 63 */
elessair 0:f269e3021894 64 typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t;
elessair 0:f269e3021894 65
elessair 0:f269e3021894 66 public:
elessair 0:f269e3021894 67 /**
elessair 0:f269e3021894 68 * Create an empty chain.
elessair 0:f269e3021894 69 */
elessair 0:f269e3021894 70 CallChainOfFunctionPointersWithContext() : chainHead(NULL) {
elessair 0:f269e3021894 71 /* empty */
elessair 0:f269e3021894 72 }
elessair 0:f269e3021894 73
elessair 0:f269e3021894 74 virtual ~CallChainOfFunctionPointersWithContext() {
elessair 0:f269e3021894 75 clear();
elessair 0:f269e3021894 76 }
elessair 0:f269e3021894 77
elessair 0:f269e3021894 78 /**
elessair 0:f269e3021894 79 * Add a function at the front of the chain.
elessair 0:f269e3021894 80 *
elessair 0:f269e3021894 81 * @param[in] function
elessair 0:f269e3021894 82 * A pointer to a void function.
elessair 0:f269e3021894 83 *
elessair 0:f269e3021894 84 * @return The function object created for @p function.
elessair 0:f269e3021894 85 */
elessair 0:f269e3021894 86 pFunctionPointerWithContext_t add(void (*function)(ContextType context)) {
elessair 0:f269e3021894 87 return common_add(new FunctionPointerWithContext<ContextType>(function));
elessair 0:f269e3021894 88 }
elessair 0:f269e3021894 89
elessair 0:f269e3021894 90 /**
elessair 0:f269e3021894 91 * Add a function at the front of the chain.
elessair 0:f269e3021894 92 *
elessair 0:f269e3021894 93 * @param[in] tptr
elessair 0:f269e3021894 94 * Pointer to the object to call the member function on.
elessair 0:f269e3021894 95 * @param[in] mptr
elessair 0:f269e3021894 96 * Pointer to the member function to be called.
elessair 0:f269e3021894 97 *
elessair 0:f269e3021894 98 * @return The function object created for @p tptr and @p mptr.
elessair 0:f269e3021894 99 */
elessair 0:f269e3021894 100 template<typename T>
elessair 0:f269e3021894 101 pFunctionPointerWithContext_t add(T *tptr, void (T::*mptr)(ContextType context)) {
elessair 0:f269e3021894 102 return common_add(new FunctionPointerWithContext<ContextType>(tptr, mptr));
elessair 0:f269e3021894 103 }
elessair 0:f269e3021894 104
elessair 0:f269e3021894 105 /**
elessair 0:f269e3021894 106 * Add a function at the front of the chain.
elessair 0:f269e3021894 107 *
elessair 0:f269e3021894 108 * @param[in] func
elessair 0:f269e3021894 109 * The FunctionPointerWithContext to add.
elessair 0:f269e3021894 110 *
elessair 0:f269e3021894 111 * @return The function object created for @p func.
elessair 0:f269e3021894 112 */
elessair 0:f269e3021894 113 pFunctionPointerWithContext_t add(const FunctionPointerWithContext<ContextType>& func) {
elessair 0:f269e3021894 114 return common_add(new FunctionPointerWithContext<ContextType>(func));
elessair 0:f269e3021894 115 }
elessair 0:f269e3021894 116
elessair 0:f269e3021894 117 /**
elessair 0:f269e3021894 118 * Detach a function pointer from a callchain.
elessair 0:f269e3021894 119 *
elessair 0:f269e3021894 120 * @param[in] toDetach
elessair 0:f269e3021894 121 * FunctionPointerWithContext to detach from this callchain.
elessair 0:f269e3021894 122 *
elessair 0:f269e3021894 123 * @return true if a function pointer has been detached and false otherwise.
elessair 0:f269e3021894 124 *
elessair 0:f269e3021894 125 * @note It is safe to remove a function pointer while the chain is
elessair 0:f269e3021894 126 * traversed by call(ContextType).
elessair 0:f269e3021894 127 */
elessair 0:f269e3021894 128 bool detach(const FunctionPointerWithContext<ContextType>& toDetach) {
elessair 0:f269e3021894 129 pFunctionPointerWithContext_t current = chainHead;
elessair 0:f269e3021894 130 pFunctionPointerWithContext_t previous = NULL;
elessair 0:f269e3021894 131
elessair 0:f269e3021894 132 while (current) {
elessair 0:f269e3021894 133 if(*current == toDetach) {
elessair 0:f269e3021894 134 if(previous == NULL) {
elessair 0:f269e3021894 135 if(currentCalled == current) {
elessair 0:f269e3021894 136 currentCalled = NULL;
elessair 0:f269e3021894 137 }
elessair 0:f269e3021894 138 chainHead = current->getNext();
elessair 0:f269e3021894 139 } else {
elessair 0:f269e3021894 140 if(currentCalled == current) {
elessair 0:f269e3021894 141 currentCalled = previous;
elessair 0:f269e3021894 142 }
elessair 0:f269e3021894 143 previous->chainAsNext(current->getNext());
elessair 0:f269e3021894 144 }
elessair 0:f269e3021894 145 delete current;
elessair 0:f269e3021894 146 return true;
elessair 0:f269e3021894 147 }
elessair 0:f269e3021894 148
elessair 0:f269e3021894 149 previous = current;
elessair 0:f269e3021894 150 current = current->getNext();
elessair 0:f269e3021894 151 }
elessair 0:f269e3021894 152
elessair 0:f269e3021894 153 return false;
elessair 0:f269e3021894 154 }
elessair 0:f269e3021894 155
elessair 0:f269e3021894 156 /**
elessair 0:f269e3021894 157 * Clear the call chain (remove all functions in the chain).
elessair 0:f269e3021894 158 */
elessair 0:f269e3021894 159 void clear(void) {
elessair 0:f269e3021894 160 pFunctionPointerWithContext_t fptr = chainHead;
elessair 0:f269e3021894 161 while (fptr) {
elessair 0:f269e3021894 162 pFunctionPointerWithContext_t deadPtr = fptr;
elessair 0:f269e3021894 163 fptr = deadPtr->getNext();
elessair 0:f269e3021894 164 delete deadPtr;
elessair 0:f269e3021894 165 }
elessair 0:f269e3021894 166
elessair 0:f269e3021894 167 chainHead = NULL;
elessair 0:f269e3021894 168 }
elessair 0:f269e3021894 169
elessair 0:f269e3021894 170 /**
elessair 0:f269e3021894 171 * Check whether the callchain contains any callbacks.
elessair 0:f269e3021894 172 *
elessair 0:f269e3021894 173 * @return true if the callchain is not empty and false otherwise.
elessair 0:f269e3021894 174 */
elessair 0:f269e3021894 175 bool hasCallbacksAttached(void) const {
elessair 0:f269e3021894 176 return (chainHead != NULL);
elessair 0:f269e3021894 177 }
elessair 0:f269e3021894 178
elessair 0:f269e3021894 179 /**
elessair 0:f269e3021894 180 * Call all the functions in the chain in sequence.
elessair 0:f269e3021894 181 */
elessair 0:f269e3021894 182 void call(ContextType context) {
elessair 0:f269e3021894 183 ((const CallChainOfFunctionPointersWithContext*) this)->call(context);
elessair 0:f269e3021894 184 }
elessair 0:f269e3021894 185
elessair 0:f269e3021894 186 /**
elessair 0:f269e3021894 187 * Same as call() above, but const.
elessair 0:f269e3021894 188 */
elessair 0:f269e3021894 189 void call(ContextType context) const {
elessair 0:f269e3021894 190 currentCalled = chainHead;
elessair 0:f269e3021894 191
elessair 0:f269e3021894 192 while(currentCalled) {
elessair 0:f269e3021894 193 currentCalled->call(context);
elessair 0:f269e3021894 194 // if this was the head and the call removed the head
elessair 0:f269e3021894 195 if(currentCalled == NULL) {
elessair 0:f269e3021894 196 currentCalled = chainHead;
elessair 0:f269e3021894 197 } else {
elessair 0:f269e3021894 198 currentCalled = currentCalled->getNext();
elessair 0:f269e3021894 199 }
elessair 0:f269e3021894 200 }
elessair 0:f269e3021894 201 }
elessair 0:f269e3021894 202
elessair 0:f269e3021894 203 /**
elessair 0:f269e3021894 204 * Same as call(), but with function call operator.
elessair 0:f269e3021894 205 * @code
elessair 0:f269e3021894 206 *
elessair 0:f269e3021894 207 * void first(bool);
elessair 0:f269e3021894 208 * void second(bool);
elessair 0:f269e3021894 209 *
elessair 0:f269e3021894 210 * CallChainOfFunctionPointerWithContext<bool> foo;
elessair 0:f269e3021894 211 *
elessair 0:f269e3021894 212 * foo.attach(first);
elessair 0:f269e3021894 213 * foo.attach(second);
elessair 0:f269e3021894 214 *
elessair 0:f269e3021894 215 * // call the callchain like a function
elessair 0:f269e3021894 216 * foo(true);
elessair 0:f269e3021894 217 *
elessair 0:f269e3021894 218 * @endcode
elessair 0:f269e3021894 219 */
elessair 0:f269e3021894 220 void operator()(ContextType context) const {
elessair 0:f269e3021894 221 call(context);
elessair 0:f269e3021894 222 }
elessair 0:f269e3021894 223
elessair 0:f269e3021894 224 /**
elessair 0:f269e3021894 225 * Bool conversion operation.
elessair 0:f269e3021894 226 *
elessair 0:f269e3021894 227 * @return true if the callchain is not empty and false otherwise.
elessair 0:f269e3021894 228 */
elessair 0:f269e3021894 229 bool toBool() const {
elessair 0:f269e3021894 230 return chainHead != NULL;
elessair 0:f269e3021894 231 }
elessair 0:f269e3021894 232
elessair 0:f269e3021894 233 private:
elessair 0:f269e3021894 234 /**
elessair 0:f269e3021894 235 * Add a callback to the head of the callchain.
elessair 0:f269e3021894 236 *
elessair 0:f269e3021894 237 * @return A pointer to the head of the callchain.
elessair 0:f269e3021894 238 */
elessair 0:f269e3021894 239 pFunctionPointerWithContext_t common_add(pFunctionPointerWithContext_t pf) {
elessair 0:f269e3021894 240 if (chainHead == NULL) {
elessair 0:f269e3021894 241 chainHead = pf;
elessair 0:f269e3021894 242 } else {
elessair 0:f269e3021894 243 pf->chainAsNext(chainHead);
elessair 0:f269e3021894 244 chainHead = pf;
elessair 0:f269e3021894 245 }
elessair 0:f269e3021894 246
elessair 0:f269e3021894 247 return chainHead;
elessair 0:f269e3021894 248 }
elessair 0:f269e3021894 249
elessair 0:f269e3021894 250 private:
elessair 0:f269e3021894 251 /**
elessair 0:f269e3021894 252 * A pointer to the first callback in the callchain or NULL if the callchain is empty.
elessair 0:f269e3021894 253 */
elessair 0:f269e3021894 254 pFunctionPointerWithContext_t chainHead;
elessair 0:f269e3021894 255
elessair 0:f269e3021894 256 /**
elessair 0:f269e3021894 257 * Iterator during a function call, this has to be mutable because the call function is const.
elessair 0:f269e3021894 258 *
elessair 0:f269e3021894 259 * @note Mutable is the correct behaviour here, the iterator never leaks outside the object.
elessair 0:f269e3021894 260 * so the object can still be seen as logically const even if it is modified.
elessair 0:f269e3021894 261 */
elessair 0:f269e3021894 262 mutable pFunctionPointerWithContext_t currentCalled;
elessair 0:f269e3021894 263
elessair 0:f269e3021894 264
elessair 0:f269e3021894 265 /* Disallow copy constructor and assignment operators. */
elessair 0:f269e3021894 266 private:
elessair 0:f269e3021894 267 CallChainOfFunctionPointersWithContext(const CallChainOfFunctionPointersWithContext &);
elessair 0:f269e3021894 268 CallChainOfFunctionPointersWithContext & operator = (const CallChainOfFunctionPointersWithContext &);
elessair 0:f269e3021894 269 };
elessair 0:f269e3021894 270
elessair 0:f269e3021894 271 #endif