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