11#include " wiringPiISR.h"
22#include < wiringPi.h>
3- #include < iostream>
4- #include < map>
53#include < uv.h>
64
75using namespace v8 ;
86
9- typedef struct js_work_t {
10- uv_work_t req ;
11- int pin ;
12- unsigned int delta ;
13- } js_work_t ;
7+ typedef struct interrupt_t {
8+ int pin ;
9+ unsigned int delta ;
10+ unsigned long int previous_timestamp ;
11+ } interrupt_t ;
1412
13+ #if NODE_VERSION_AT_LEAST(0, 11, 0)
14+ typedef v8::Persistent<v8::Function, v8::CopyablePersistentTraits<v8::Function> > CopyablePersistentFunction;
15+ #else
16+ typedef v8::Persistent<v8::Function> CopyablePersistentFunction;
17+ #endif
1518typedef void (*NATIVE_INTERRUPT_HANDLER_T)(void );
1619
17- static NATIVE_INTERRUPT_HANDLER_T nativeInterruptHandlers [64 ];
18- static unsigned long int lastInterruptMicroseconds [64 ];
19- static std::map< int , v8::Persistent<v8::Function, v8::CopyablePersistentTraits<v8::Function> > > interruptCallbackMapping ;
20- static uv_async_t asyncHandlers [64 ];
20+ static uv_async_t async_handlers [64 ];
21+ static interrupt_t interrupt_data [64 ];
22+ static NATIVE_INTERRUPT_HANDLER_T interrupt_handlers[ 64 ] ;
23+ static CopyablePersistentFunction interrupt_callbacks [64 ];
2124
2225#define DEFINE_NATIVE_INTERRUPT_HANDLER (pin ) \
2326 static void nativeInterruptHandler##pin(void ) { \
2427 processNativeInterrupt (pin); \
2528 }
26-
27- #define REGISTER_NATIVE_INTERRUPT_HANDLER (pin ) nativeInterruptHandlers[pin] = &nativeInterruptHandler##pin
28-
29- #define GET_NATIVE_INTERRUPT_HANDLER (pin ) nativeInterruptHandlers[pin]
30-
31- static void processInterrupt (uv_work_t * req, int status) {
32- js_work_t * work = static_cast <js_work_t *>(req->data );
33-
34- #if NODE_VERSION_AT_LEAST(0, 11, 0)
35- v8::Isolate* isolate = v8::Isolate::GetCurrent ();
36- Local<Function> callback = Local<Function>::New (isolate, interruptCallbackMapping[work->pin ]);
37- #else
38- Persistent<Function> callback = interruptCallbackMapping[work->pin ];
39- #endif
40-
41- Local<Value> argv[] = {
42- #if NODE_VERSION_AT_LEAST(0, 11, 0)
43- Local<Value>::New (isolate, UINT32 (work->delta ))
44- #else
45- Local<Value>::New (UINT32 (work->delta ))
46- #endif
47- };
48-
49- #if NODE_VERSION_AT_LEAST(0, 11, 0)
50- callback->Call (isolate->GetCurrentContext ()->Global (), 1 , argv);
51- #else
52- callback->Call (Context::GetCurrent ()->Global (), 1 , argv);
53- #endif
54-
55- delete work;
56- }
5729
58- static void UV_NOP (uv_work_t *) {}
59- static void UV_ASYNC_NOP (uv_async_t * handler) {}
30+ #define REGISTER_NATIVE_INTERRUPT_HANDLER (pin ) interrupt_handlers[pin] = &nativeInterruptHandler##pin
6031
6132void processNativeInterrupt (int pin) {
6233 unsigned int now = ::micros ();
63-
64- js_work_t * work = new js_work_t ;
65- work->req .data = work;
66- work->pin = pin;
67- work->delta = now - lastInterruptMicroseconds[pin];
68-
69- int r = uv_queue_work (uv_default_loop (), &work->req , &UV_NOP, &processInterrupt);
70- if (r != 0 ) {
71- delete work;
72- }
73-
74- lastInterruptMicroseconds[pin] = now;
34+
35+ uv_async_t * handle = &async_handlers[pin];
36+ interrupt_t * data = &interrupt_data[pin];
37+ data->pin = pin;
38+ data->delta = now - data->previous_timestamp ;
39+ handle->data = (void *)data;
40+
41+ uv_async_send (handle);
42+
43+ data->previous_timestamp = now;
44+ }
45+
46+ #if NODE_VERSION_AT_LEAST(0, 11, 0)
47+ static void dispatchInterrupt (uv_async_t * handle) {
48+ #else
49+ static void dispatchInterrupt (uv_async_t * handle, int status) {
50+ #endif
51+ interrupt_t * data = (interrupt_t *)handle->data ;
52+
53+ #if NODE_VERSION_AT_LEAST(0, 11, 0)
54+ v8::Isolate* isolate = v8::Isolate::GetCurrent ();
55+ v8::Local<Function> callback = v8::Local<Function>::New (isolate, interrupt_callbacks[data->pin ]);
56+ #else
57+ v8::Local<Function> callback = v8::Local<Function>::New (interrupt_callbacks[data->pin ]);
58+ #endif
59+
60+ Local<Value> argv[] = {
61+ UINT32 (data->delta )
62+ };
63+
64+ #if NODE_VERSION_AT_LEAST(0, 11, 0)
65+ callback->Call (isolate->GetCurrentContext ()->Global (), 1 , argv);
66+ #else
67+ callback->Call (Context::GetCurrent ()->Global (), 1 , argv);
68+ #endif
7569}
7670
7771DEFINE_NATIVE_INTERRUPT_HANDLER (0 );
@@ -142,54 +136,54 @@ DEFINE_NATIVE_INTERRUPT_HANDLER(63);
142136DECLARE (wiringPiISR);
143137IMPLEMENT (wiringPiISR) {
144138 SCOPE_OPEN ();
145-
139+
146140 SET_ARGUMENT_NAME (0 , pin);
147141 SET_ARGUMENT_NAME (1 , edgeType);
148142 SET_ARGUMENT_NAME (2 , callback);
149-
143+
150144 CHECK_ARGUMENTS_LENGTH_EQUAL (3 );
151-
145+
152146 CHECK_ARGUMENT_TYPE_INT32 (0 );
153147 CHECK_ARGUMENT_TYPE_INT32 (1 );
154148 CHECK_ARGUMENT_TYPE_FUNCTION (2 );
155-
149+
156150 int pin = GET_ARGUMENT_AS_INT32 (0 );
157151 int edgeType = GET_ARGUMENT_AS_INT32 (1 );
158-
152+
159153 #if NODE_VERSION_AT_LEAST(0, 11, 0)
160154 Persistent<Function> callback (isolate, GET_ARGUMENT_AS_LOCAL_FUNCTION (2 ));
161155 #else
162156 Persistent<Function> callback = GET_ARGUMENT_AS_PERSISTENT_FUNCTION (2 );
163157 #endif
164-
158+
165159 CHECK_ARGUMENT_IN_INTS (1 , edgeType, (INT_EDGE_FALLING, INT_EDGE_RISING, INT_EDGE_BOTH, INT_EDGE_SETUP));
166-
167- interruptCallbackMapping. insert (std::pair< int , v8::Persistent<v8::Function, v8::CopyablePersistentTraits<v8::Function> > >( pin, callback)) ;
168- lastInterruptMicroseconds [pin] = ::micros ();
169-
170- ::wiringPiISR (pin, edgeType, GET_NATIVE_INTERRUPT_HANDLER( pin) );
171-
172- uv_async_init (uv_default_loop (), &asyncHandlers [pin], &UV_ASYNC_NOP );
173- uv_ref ((uv_handle_t *)&asyncHandlers [pin]);
174-
160+
161+ interrupt_callbacks[ pin] = callback;
162+ interrupt_data [pin]. previous_timestamp = ::micros ();
163+
164+ ::wiringPiISR (pin, edgeType, interrupt_handlers[ pin] );
165+
166+ uv_async_init (uv_default_loop (), &async_handlers [pin], &dispatchInterrupt );
167+ uv_ref ((uv_handle_t *)&async_handlers [pin]);
168+
175169 SCOPE_CLOSE (UNDEFINED ());
176170}
177171
178172DECLARE (wiringPiISRCancel);
179173IMPLEMENT (wiringPiISRCancel) {
180174 SCOPE_OPEN ();
181-
175+
182176 SET_ARGUMENT_NAME (0 , pin);
183-
177+
184178 CHECK_ARGUMENTS_LENGTH_EQUAL (1 );
185-
179+
186180 CHECK_ARGUMENT_TYPE_INT32 (0 );
187-
181+
188182 int pin = GET_ARGUMENT_AS_INT32 (0 );
189-
183+
190184 ::wiringPiISRCancel (pin);
191- uv_close ((uv_handle_t *)&asyncHandlers [pin], NULL );
192-
185+ uv_close ((uv_handle_t *)&async_handlers [pin], NULL );
186+
193187 SCOPE_CLOSE (UNDEFINED ());
194188}
195189
@@ -258,12 +252,12 @@ IMPLEMENT_EXPORT_INIT(wiringPiISR) {
258252 REGISTER_NATIVE_INTERRUPT_HANDLER (61 );
259253 REGISTER_NATIVE_INTERRUPT_HANDLER (62 );
260254 REGISTER_NATIVE_INTERRUPT_HANDLER (63 );
261-
255+
262256 EXPORT_FUNCTION (wiringPiISR);
263257 EXPORT_FUNCTION (wiringPiISRCancel);
264-
258+
265259 EXPORT_CONSTANT_INT (INT_EDGE_FALLING);
266260 EXPORT_CONSTANT_INT (INT_EDGE_RISING);
267261 EXPORT_CONSTANT_INT (INT_EDGE_BOTH);
268262 EXPORT_CONSTANT_INT (INT_EDGE_SETUP);
269- }
263+ }
0 commit comments