• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright JS Foundation and other contributors, http://js.foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "jerryscript-mbed-util/logging.h"
16 #include "jerryscript-mbed-event-loop/EventLoop.h"
17 #include "jerryscript-mbed-library-registry/wrap_tools.h"
18 
19 #include "mbed.h"
20 
21 /**
22  * InterruptIn#destructor
23  *
24  * Called if/when the InterruptIn object is GC'ed.
25  */
NAME_FOR_CLASS_NATIVE_DESTRUCTOR(InterruptIn)26 void NAME_FOR_CLASS_NATIVE_DESTRUCTOR(InterruptIn) (void *void_ptr) {
27     InterruptIn *native_ptr = static_cast<InterruptIn*>(void_ptr);
28 
29     native_ptr->rise(0);
30     native_ptr->fall(0);
31     delete native_ptr;
32 }
33 
34 /**
35  * Type infomation of the native InterruptIn pointer
36  *
37  * Set InterruptIn#destructor as the free callback.
38  */
39 static const jerry_object_native_info_t native_obj_type_info = {
40     .free_cb = NAME_FOR_CLASS_NATIVE_DESTRUCTOR(InterruptIn)
41 };
42 
43 /**
44  * InterruptIn#rise (native JavaScript method)
45  *
46  * Register a rise callback for an InterruptIn
47  *
48  * @param cb Callback function, or null to detach previously attached callback.
49  */
DECLARE_CLASS_FUNCTION(InterruptIn,rise)50 DECLARE_CLASS_FUNCTION(InterruptIn, rise) {
51     CHECK_ARGUMENT_COUNT(InterruptIn, rise, (args_count == 1));
52 
53     // Detach the rise callback when InterruptIn::rise(null) is called
54     if (jerry_value_is_null(args[0])) {
55         void *void_ptr;
56         bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
57 
58         if (!has_ptr) {
59             return jerry_create_error(JERRY_ERROR_TYPE,
60                                       (const jerry_char_t *) "Failed to get native InterruptIn pointer");
61         }
62 
63         InterruptIn *native_ptr = static_cast<InterruptIn*>(void_ptr);
64 
65         jerry_value_t property_name = jerry_create_string((const jerry_char_t*)"cb_rise");
66         jerry_value_t cb_func = jerry_get_property(this_obj, property_name);
67         jerry_release_value(property_name);
68 
69         // Only drop the callback if it exists
70         if (jerry_value_is_function(cb_func)) {
71             // Ensure that the EventLoop frees memory used by the callback.
72             mbed::js::EventLoop::getInstance().dropCallback(cb_func);
73         }
74         jerry_release_value(cb_func);
75 
76         native_ptr->rise(0);
77 
78         return jerry_create_undefined();
79     }
80 
81     // Assuming we actually have a callback now...
82     CHECK_ARGUMENT_TYPE_ALWAYS(InterruptIn, rise, 0, function);
83 
84     void *void_ptr;
85     bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
86 
87     if (!has_ptr) {
88         return jerry_create_error(JERRY_ERROR_TYPE,
89                                   (const jerry_char_t *) "Failed to get native InterruptIn pointer");
90     }
91 
92     InterruptIn *native_ptr = static_cast<InterruptIn*>(void_ptr);
93 
94     jerry_value_t f = args[0];
95 
96     // Pass the function to EventLoop.
97     mbed::Callback<void()> cb = mbed::js::EventLoop::getInstance().wrapFunction(f);
98     native_ptr->rise(cb);
99 
100     // Keep track of our callback internally.
101     jerry_value_t property_name = jerry_create_string((const jerry_char_t*)"cb_rise");
102     jerry_release_value(jerry_set_property(this_obj, property_name, f));
103     jerry_release_value(property_name);
104 
105     return jerry_create_undefined();
106 }
107 
108 /**
109  * InterruptIn#fall (native JavaScript method)
110  *
111  * Register a fall callback for an InterruptIn
112  *
113  * @param cb Callback function, or null to detach previously attached callback.
114  */
DECLARE_CLASS_FUNCTION(InterruptIn,fall)115 DECLARE_CLASS_FUNCTION(InterruptIn, fall) {
116     CHECK_ARGUMENT_COUNT(InterruptIn, fall, (args_count == 1));
117 
118     // Detach the fall callback when InterruptIn::fall(null) is called
119     if (jerry_value_is_null(args[0])) {
120         void *void_ptr;
121         bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
122 
123         if (!has_ptr) {
124             return jerry_create_error(JERRY_ERROR_TYPE,
125                                       (const jerry_char_t *) "Failed to get native InterruptIn pointer");
126         }
127 
128         InterruptIn *native_ptr = static_cast<InterruptIn*>(void_ptr);
129 
130         jerry_value_t property_name = jerry_create_string((const jerry_char_t*)"cb_fall");
131         jerry_value_t cb_func = jerry_get_property(this_obj, property_name);
132         jerry_release_value(property_name);
133 
134         // Only drop the callback if it exists
135         if (jerry_value_is_function(cb_func)) {
136             // Ensure that the EventLoop frees memory used by the callback.
137             mbed::js::EventLoop::getInstance().dropCallback(cb_func);
138         }
139         jerry_release_value(cb_func);
140 
141         native_ptr->fall(0);
142 
143         return jerry_create_undefined();
144     }
145 
146     // Assuming we actually have a callback now...
147     CHECK_ARGUMENT_TYPE_ALWAYS(InterruptIn, fall, 0, function);
148 
149     void *void_ptr;
150     bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
151 
152     if (!has_ptr) {
153         return jerry_create_error(JERRY_ERROR_TYPE,
154                                   (const jerry_char_t *) "Failed to get native InterruptIn pointer");
155     }
156 
157     InterruptIn *native_ptr = static_cast<InterruptIn*>(void_ptr);
158 
159     jerry_value_t f = args[0];
160 
161     // Pass the function to EventLoop.
162     mbed::Callback<void()> cb = mbed::js::EventLoop::getInstance().wrapFunction(f);
163     native_ptr->fall(cb);
164 
165     // Keep track of our callback internally.
166     jerry_value_t property_name = jerry_create_string((const jerry_char_t*)"cb_fall");
167     jerry_release_value(jerry_set_property(this_obj, property_name, f));
168     jerry_release_value(property_name);
169 
170     return jerry_create_undefined();
171 }
172 
173 /**
174  * InterruptIn#mode (native JavaScript method)
175  *
176  * Set the mode of the InterruptIn pin.
177  *
178  * @param mode PullUp, PullDown, PullNone
179  */
DECLARE_CLASS_FUNCTION(InterruptIn,mode)180 DECLARE_CLASS_FUNCTION(InterruptIn, mode) {
181     CHECK_ARGUMENT_COUNT(InterruptIn, mode, (args_count == 1));
182     CHECK_ARGUMENT_TYPE_ALWAYS(InterruptIn, mode, 0, number);
183 
184     void *void_ptr;
185     bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
186 
187     if (!has_ptr) {
188         return jerry_create_error(JERRY_ERROR_TYPE,
189                                   (const jerry_char_t *) "Failed to get native InterruptIn pointer");
190     }
191 
192     InterruptIn *native_ptr = static_cast<InterruptIn*>(void_ptr);
193 
194     int pull = jerry_get_number_value(args[0]);
195     native_ptr->mode((PinMode)pull);
196 
197     return jerry_create_undefined();
198 }
199 
200 /**
201  * InterruptIn#disable_irq (native JavaScript method)
202  *
203  * Disable IRQ. See InterruptIn.h in mbed-os sources for more details.
204  */
DECLARE_CLASS_FUNCTION(InterruptIn,disable_irq)205 DECLARE_CLASS_FUNCTION(InterruptIn, disable_irq) {
206     CHECK_ARGUMENT_COUNT(InterruptIn, disable_irq, (args_count == 0));
207 
208     void *void_ptr;
209     bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
210 
211     if (!has_ptr) {
212         return jerry_create_error(JERRY_ERROR_TYPE,
213                                   (const jerry_char_t *) "Failed to get native InterruptIn pointer");
214     }
215 
216     InterruptIn *native_ptr = static_cast<InterruptIn*>(void_ptr);
217 
218     native_ptr->disable_irq();
219     return jerry_create_undefined();
220 }
221 
222 /**
223  * InterruptIn#enable_irq (native JavaScript method)
224  *
225  * Enable IRQ. See InterruptIn.h in mbed-os sources for more details.
226  */
DECLARE_CLASS_FUNCTION(InterruptIn,enable_irq)227 DECLARE_CLASS_FUNCTION(InterruptIn, enable_irq) {
228     CHECK_ARGUMENT_COUNT(InterruptIn, enable_irq, (args_count == 0));
229 
230     void *void_ptr;
231     bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &native_obj_type_info);
232 
233     if (!has_ptr) {
234         return jerry_create_error(JERRY_ERROR_TYPE,
235                                   (const jerry_char_t *) "Failed to get native InterruptIn pointer");
236     }
237 
238     InterruptIn *native_ptr = static_cast<InterruptIn*>(void_ptr);
239 
240     native_ptr->enable_irq();
241     return jerry_create_undefined();
242 }
243 
244 /**
245  * InterruptIn (native JavaScript constructor)
246  *
247  * @param pin PinName
248  *
249  * @returns JavaScript object wrapping InterruptIn native object
250  */
DECLARE_CLASS_CONSTRUCTOR(InterruptIn)251 DECLARE_CLASS_CONSTRUCTOR(InterruptIn) {
252     CHECK_ARGUMENT_COUNT(InterruptIn, __constructor, (args_count == 1));
253     CHECK_ARGUMENT_TYPE_ALWAYS(InterruptIn, __constructor, 0, number);
254     int pin = jerry_get_number_value(args[0]);
255 
256     InterruptIn *native_ptr = new InterruptIn((PinName)pin);
257     jerry_value_t js_object = jerry_create_object();
258 
259     jerry_set_object_native_pointer(js_object, native_ptr, &native_obj_type_info);
260 
261     ATTACH_CLASS_FUNCTION(js_object, InterruptIn, rise);
262     ATTACH_CLASS_FUNCTION(js_object, InterruptIn, fall);
263     ATTACH_CLASS_FUNCTION(js_object, InterruptIn, mode);
264     ATTACH_CLASS_FUNCTION(js_object, InterruptIn, enable_irq);
265     ATTACH_CLASS_FUNCTION(js_object, InterruptIn, disable_irq);
266 
267     return js_object;
268 }
269