69#include <avr/interrupt.h>
75#define FIX_BASE_POINTER(_ptr) __asm__ __volatile__("" : "=b"(_ptr) : "0"(_ptr))
91 template<
typename Handler>
class HandlerHolder
94 static Handler* handler()
99 using Holder = HandlerHolder<Handler>;
101 template<
typename Ret,
typename... Args>
struct ArgsHolder
103 template<Ret (Handler::*Callback)(Args...)>
struct CallbackHolder
105 static Ret handle(Args... args)
107 Handler* handler_instance = Holder::handler();
108 FIX_BASE_POINTER(handler_instance);
109 return (handler_instance->*Callback)(args...);
111 static Ret safe_handle(Args... args)
113 Handler* handler_instance = Holder::handler();
114 if (handler_instance ==
nullptr)
116 FIX_BASE_POINTER(handler_instance);
117 return (handler_instance->*Callback)(args...);
123 static Handler* handler_;
124 friend void register_handler<Handler>(Handler&);
125 friend void unregister_handler<Handler>(Handler&);
128 template<
typename Handler> Handler* HandlerHolder<Handler>::handler_ =
nullptr;
133 template<
typename T, T>
struct CallbackHandler;
134 template<
typename HANDLER,
typename RET,
typename... ARGS, RET (HANDLER::*CALLBACK)(ARGS...)>
135 struct CallbackHandler<RET (HANDLER::*)(ARGS...), CALLBACK>
137 static RET call(ARGS... args)
141 using HOLDER = HandlerHolder<HANDLER>;
142 using ARGS_HOLDER =
typename HOLDER::template ArgsHolder<RET, ARGS...>;
143 using CALLBACK_HOLDER =
typename ARGS_HOLDER::template CallbackHolder<CALLBACK>;
144 return CALLBACK_HOLDER::handle(args...);
146 static RET safe_call(ARGS... args)
150 using HOLDER = HandlerHolder<HANDLER>;
151 using ARGS_HOLDER =
typename HOLDER::template ArgsHolder<RET, ARGS...>;
152 using CALLBACK_HOLDER =
typename ARGS_HOLDER::template CallbackHolder<CALLBACK>;
153 return CALLBACK_HOLDER::safe_handle(args...);
156 template<
typename RET,
typename... ARGS, RET (*CALLBACK)(ARGS...)>
157 struct CallbackHandler<RET (*)(ARGS...), CALLBACK>
159 static RET call(ARGS... args)
161 return CALLBACK(args...);
163 static RET safe_call(ARGS... args)
165 return CALLBACK(args...);
187 HandlerHolder<Handler>::handler_ = &handler;
209 if (HandlerHolder<Handler>::handler_ == &handler)
210 HandlerHolder<Handler>::handler_ =
nullptr;
217#define CAT3(X, Y, Z) X##Y##Z
Defines API to handle AVR interruptions.
void register_handler(Handler &handler)
Register a class instance containing methods that shall be called back by an ISR.
void unregister_handler(Handler &handler)
Unregister a class instance that was previously registered with interrupt::register_handler.