DevI2C wrappers for Javascript.

Dependents:   ST_SENSOR_JS MQTT_JS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DevI2C-js.cpp Source File

DevI2C-js.cpp

Go to the documentation of this file.
00001 /**
00002  ******************************************************************************
00003  * @file    DevI2C-js.cpp
00004  * @author  ST
00005  * @version V1.0.0
00006  * @date    25 October 2017
00007  * @brief   Implementation of DevI2C for Javascript.
00008  ******************************************************************************
00009  * @attention
00010  *
00011  * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
00012  *
00013  * Redistribution and use in source and binary forms, with or without modification,
00014  * are permitted provided that the following conditions are met:
00015  *   1. Redistributions of source code must retain the above copyright notice,
00016  *      this list of conditions and the following disclaimer.
00017  *   2. Redistributions in binary form must reproduce the above copyright notice,
00018  *      this list of conditions and the following disclaimer in the documentation
00019  *      and/or other materials provided with the distribution.
00020  *   3. Neither the name of STMicroelectronics nor the names of its contributors
00021  *      may be used to endorse or promote products derived from this software
00022  *      without specific prior written permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00027  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00028  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00029  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00030  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00032  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  ******************************************************************************
00036  */
00037 
00038 
00039 /* Includes ------------------------------------------------------------------*/
00040 
00041 #include "jerryscript-mbed-util/logging.h"
00042 #include "jerryscript-mbed-library-registry/wrap_tools.h"
00043 
00044 // Load the library that we'll wrap
00045 #include "DevI2C.h"
00046 
00047 #include "mbed.h"
00048 
00049 /* Class Implementation ------------------------------------------------------*/
00050 
00051 /**
00052  * DevI2C#destructor
00053  * @brief   Called if/when the DevI2C object is GC'ed.
00054  */
00055 void NAME_FOR_CLASS_NATIVE_DESTRUCTOR(DevI2C) (void *void_ptr) {
00056     delete static_cast<DevI2C*>(void_ptr);
00057 }
00058 
00059 /**
00060  * Type infomation of the native DevI2C pointer
00061  * @brief   Set DevI2C#destructor as the free callback.
00062  */
00063 static const jerry_object_native_info_t native_obj_type_info = {
00064     .free_cb = NAME_FOR_CLASS_NATIVE_DESTRUCTOR(DevI2C)
00065 };
00066 
00067 /**
00068  * DevI2C#frequency (native JavaScript method)
00069  * @brief   Set the frequency of the DevI2C bus.
00070  *
00071  * @param frequency New DevI2C Frequency
00072  */
00073 DECLARE_CLASS_FUNCTION(DevI2C, frequency) {
00074     CHECK_ARGUMENT_COUNT(DevI2C, frequency, (args_count == 1));
00075     CHECK_ARGUMENT_TYPE_ALWAYS(DevI2C, frequency, 0, number);
00076 
00077     // Unwrap native DevI2C object
00078     void *void_ptr;
00079     const jerry_object_native_info_t *type_ptr;
00080     bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
00081 
00082     if (!has_ptr || type_ptr != &native_obj_type_info) {
00083         return jerry_create_error(JERRY_ERROR_TYPE,
00084                                   (const jerry_char_t *) "Failed to get native DevI2C pointer");
00085     }
00086 
00087     I2C *native_ptr = static_cast<I2C*>(void_ptr);
00088 
00089     int hz = jerry_get_number_value(args[0]);
00090     native_ptr->frequency(hz);
00091 
00092     return jerry_create_undefined();
00093 }
00094 
00095 /**
00096  * DevI2C#read (native JavaScript method)
00097  * @brief   Read data from the DevI2C bus.
00098  *
00099  * @overload DevI2C#read(int)
00100  * Read a single byte from the DevI2C bus
00101  *
00102  * @param ack indicates if the byte is to be acknowledged (1 => acknowledge)
00103  *
00104  * @returns array: Data read from the DevI2C bus
00105  *
00106  * @overload DevI2C#read(int, array, int)
00107  * Read a series of bytes from the DevI2C bus
00108  *
00109  * @param address DevI2C address to read from
00110  * @param data Array to read into
00111  * @param length Length of data to read
00112  *
00113  * @returns array: Data read from the DevI2C bus
00114  */
00115 DECLARE_CLASS_FUNCTION(DevI2C, read) {
00116     CHECK_ARGUMENT_COUNT(DevI2C, read, (args_count == 1 || args_count == 3 || args_count == 4));
00117 
00118     if (args_count == 1) {
00119         CHECK_ARGUMENT_TYPE_ALWAYS(DevI2C, read, 0, number);
00120         void *void_ptr;
00121         const jerry_object_native_info_t *type_ptr;
00122         bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
00123 
00124         if (!has_ptr || type_ptr != &native_obj_type_info) {
00125             return jerry_create_error(JERRY_ERROR_TYPE,
00126                                       (const jerry_char_t *) "Failed to get native DevI2C pointer");
00127         }
00128 
00129         I2C *native_ptr = static_cast<I2C*>(void_ptr);
00130 
00131         int data = jerry_get_number_value(args[0]);
00132         int result = native_ptr->read(data);
00133 
00134         return jerry_create_number(result);
00135     } else {
00136         CHECK_ARGUMENT_TYPE_ALWAYS(DevI2C, read, 0, number);
00137         CHECK_ARGUMENT_TYPE_ALWAYS(DevI2C, read, 1, array);
00138         CHECK_ARGUMENT_TYPE_ALWAYS(DevI2C, read, 2, number);
00139 
00140         CHECK_ARGUMENT_TYPE_ON_CONDITION(DevI2C, read, 3, boolean, (args_count == 4));
00141 
00142         void *void_ptr;
00143         const jerry_object_native_info_t *type_ptr;
00144         bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
00145 
00146         if (!has_ptr || type_ptr != &native_obj_type_info) {
00147             return jerry_create_error(JERRY_ERROR_TYPE,
00148                                       (const jerry_char_t *) "Failed to get native DevI2C pointer");
00149         }
00150 
00151         I2C *native_ptr = static_cast<I2C*>(void_ptr);
00152 
00153         const uint32_t data_len = jerry_get_array_length(args[1]);
00154 
00155         int address = jerry_get_number_value(args[0]);
00156         int length = jerry_get_number_value(args[2]);
00157 
00158         char *data = new char[data_len];
00159 
00160         bool repeated = false;
00161         if (args_count == 4) {
00162             repeated = jerry_get_boolean_value(args[3]);
00163         }
00164 
00165         int result = native_ptr->read(address, data, length, repeated);
00166 
00167         jerry_value_t out_array = jerry_create_array(data_len);
00168 
00169         for (uint32_t i = 0; i < data_len; i++) {
00170             jerry_value_t val = jerry_create_number(double(data[i]));
00171             jerry_set_property_by_index(out_array, i, val);
00172             jerry_release_value(val);
00173         }
00174 
00175         delete[] data;
00176 
00177         if (result == 0) {
00178             // ACK
00179             return out_array;
00180         } else {
00181             // NACK
00182             const char *error_msg = "NACK received from DevI2C bus";
00183 
00184             jerry_release_value(out_array);
00185             return jerry_create_error(JERRY_ERROR_COMMON, reinterpret_cast<const jerry_char_t *>(error_msg));
00186         }
00187     }
00188 }
00189 
00190 /**
00191  * DevI2C#write (native JavaScript method)
00192  * @brief   Writes to DevI2C bus
00193  * 
00194  * @overload DevI2C#write(int)
00195  * Write a single byte to the DevI2C bus
00196  *
00197  * @param data Data byte to write to the DevI2C bus
00198  *
00199  * @returns 1 on success, 0 on failure
00200  *
00201  * @overload DevI2C#write(int, array, int, bool)
00202  * Write an array of data to a certain address on the DevI2C bus
00203  *
00204  * @param address 8-bit DevI2C slave address
00205  * @param data Array of bytes to send
00206  * @param length Length of data to write
00207  * @param repeated (optional) If true, do not send stop at end.
00208  *
00209  * @returns 0 on success, non-0 on failure
00210  */
00211 DECLARE_CLASS_FUNCTION(DevI2C, write) {
00212     CHECK_ARGUMENT_COUNT(DevI2C, write, (args_count == 1 || args_count == 3 || args_count == 4));
00213 
00214     if (args_count == 1) {
00215         CHECK_ARGUMENT_TYPE_ALWAYS(DevI2C, write, 0, number);
00216 
00217         // Extract native DevI2C object
00218         void *void_ptr;
00219         const jerry_object_native_info_t *type_ptr;
00220         bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
00221 
00222         if (!has_ptr || type_ptr != &native_obj_type_info) {
00223             return jerry_create_error(JERRY_ERROR_TYPE,
00224                                       (const jerry_char_t *) "Failed to get native DevI2C pointer");
00225         }
00226 
00227         I2C *native_ptr = static_cast<I2C*>(void_ptr);
00228 
00229         // Unwrap arguments
00230         int data = jerry_get_number_value(args[0]);
00231 
00232         int result = native_ptr->write(data);
00233         return jerry_create_number(result);
00234     } else {
00235         // 3 or 4
00236         CHECK_ARGUMENT_TYPE_ALWAYS(DevI2C, write, 0, number);
00237         CHECK_ARGUMENT_TYPE_ALWAYS(DevI2C, write, 1, array);
00238         CHECK_ARGUMENT_TYPE_ALWAYS(DevI2C, write, 2, number);
00239         CHECK_ARGUMENT_TYPE_ON_CONDITION(DevI2C, write, 3, boolean, (args_count == 4));
00240 
00241         // Extract native DevI2C object
00242         void *void_ptr;
00243         const jerry_object_native_info_t *type_ptr;
00244         bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
00245 
00246         if (!has_ptr || type_ptr != &native_obj_type_info) {
00247             return jerry_create_error(JERRY_ERROR_TYPE,
00248                                       (const jerry_char_t *) "Failed to get native DevI2C pointer");
00249         }
00250 
00251         I2C *native_ptr = static_cast<I2C*>(void_ptr);
00252 
00253         // Unwrap arguments
00254         int address = jerry_get_number_value(args[0]);
00255         const uint32_t data_len = jerry_get_array_length(args[1]);
00256         int length = jerry_get_number_value(args[2]);
00257         bool repeated = args_count == 4 && jerry_get_boolean_value(args[3]);
00258 
00259         // Construct data byte array
00260         char *data = new char[data_len];
00261         for (uint32_t i = 0; i < data_len; i++) {
00262             data[i] = jerry_get_number_value(jerry_get_property_by_index(args[1], i));
00263         }
00264 
00265         int result = native_ptr->write(address, data, length, repeated);
00266 
00267         // free dynamically allocated resources
00268         delete[] data;
00269 
00270         return jerry_create_number(result);
00271     }
00272 }
00273 
00274 /**
00275  * DevI2C#start (native JavaScript method)
00276  * @brief   Creates a start condition on the DevI2C bus.
00277  */
00278 DECLARE_CLASS_FUNCTION(DevI2C, start) {
00279     CHECK_ARGUMENT_COUNT(DevI2C, start, (args_count == 0));
00280 
00281     // Extract native DevI2C object
00282     void *void_ptr;
00283     const jerry_object_native_info_t *type_ptr;
00284     bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
00285 
00286     if (!has_ptr || type_ptr != &native_obj_type_info) {
00287         return jerry_create_error(JERRY_ERROR_TYPE,
00288                                   (const jerry_char_t *) "Failed to get native DevI2C pointer");
00289     }
00290 
00291     I2C *native_ptr = static_cast<I2C*>(void_ptr);
00292 
00293     native_ptr->start();
00294     return jerry_create_undefined();
00295 }
00296 
00297 /**
00298  * DevI2C#stop (native JavaScript method)
00299  * @brief   Creates a stop condition on the DevI2C bus.
00300  */
00301 DECLARE_CLASS_FUNCTION(DevI2C, stop) {
00302     CHECK_ARGUMENT_COUNT(DevI2C, stop, (args_count == 0));
00303 
00304     // Extract native DevI2C object
00305     void *void_ptr;
00306     const jerry_object_native_info_t *type_ptr;
00307     bool has_ptr = jerry_get_object_native_pointer(this_obj, &void_ptr, &type_ptr);
00308 
00309     if (!has_ptr || type_ptr != &native_obj_type_info) {
00310         return jerry_create_error(JERRY_ERROR_TYPE,
00311                                   (const jerry_char_t *) "Failed to get native DevI2C pointer");
00312     }
00313 
00314     I2C *native_ptr = static_cast<I2C*>(void_ptr);
00315 
00316     native_ptr->stop();
00317     return jerry_create_undefined();
00318 }
00319 
00320 /**
00321  * DevI2C (native JavaScript constructor)
00322  * @brief   Constructor
00323  * @param sda mbed pin for DevI2C data
00324  * @param scl mbed pin for DevI2C clock
00325  * @returns a JavaScript object representing the DevI2C bus.
00326  */
00327 DECLARE_CLASS_CONSTRUCTOR(DevI2C) {
00328     CHECK_ARGUMENT_COUNT(DevI2C, __constructor, (args_count == 2));
00329     CHECK_ARGUMENT_TYPE_ALWAYS(DevI2C, __constructor, 0, number);
00330     CHECK_ARGUMENT_TYPE_ALWAYS(DevI2C, __constructor, 1, number);
00331 
00332     int sda = jerry_get_number_value(args[0]);
00333     int scl = jerry_get_number_value(args[1]);
00334 
00335     DevI2C *native_ptr = new DevI2C((PinName)sda, (PinName)scl);
00336 
00337     jerry_value_t js_object = jerry_create_object();
00338     jerry_set_object_native_pointer(js_object, native_ptr, &native_obj_type_info);
00339 
00340     ATTACH_CLASS_FUNCTION(js_object, DevI2C, frequency);
00341     ATTACH_CLASS_FUNCTION(js_object, DevI2C, read);
00342     ATTACH_CLASS_FUNCTION(js_object, DevI2C, write);
00343     ATTACH_CLASS_FUNCTION(js_object, DevI2C, start);
00344     ATTACH_CLASS_FUNCTION(js_object, DevI2C, stop);
00345 
00346     return js_object;
00347 }