Includes library modifications to allow access to AIN_4 (AIN_0 / 5)

Committer:
bryantaylor
Date:
Tue Sep 20 21:26:12 2016 +0000
Revision:
0:eafc3fd41f75
hackathon

Who changed what in which revision?

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