Exemplo n.º 1
0
/*JSON{ "type":"method", "class": "Serial", "name" : "setup",
         "description" : ["Setup this Serial port with the given baud rate and options.",
                          "If not specified in options, the default pins are used (usually the lowest numbered pins on the lowest port that supports this peripheral)"],
         "generate" : "jswrap_serial_setup",
         "params" : [ [ "baudrate", "JsVar", "The baud rate - the default is 9600"],
                      [ "options", "JsVar", ["An optional structure containing extra information on initialising the serial port.",
                                             "```{rx:pin,tx:pin,bytesize:8,parity:null/'none'/'o'/'odd'/'e'/'even',stopbits:1}```",
                                             "You can find out which pins to use by looking at [your board's reference page](#boards) and searching for pins with the `UART`/`USART` markers.",
                                             "Note that even after changing the RX and TX pins, if you have called setup before then the previous RX and TX pins will still be connected to the Serial port as well - until you set them to something else using digitalWrite" ] ] ]
}*/
void jswrap_serial_setup(JsVar *parent, JsVar *baud, JsVar *options) {
  IOEventFlags device = jsiGetDeviceFromClass(parent);
  if (!DEVICE_IS_USART(device)) return;

  JshUSARTInfo inf;
  jshUSARTInitInfo(&inf);

  if (!jsvIsUndefined(baud)) {
    int b = (int)jsvGetInteger(baud);
    if (b<=100 || b > 10000000)
      jsExceptionHere(JSET_ERROR, "Invalid baud rate specified");
    else
      inf.baudRate = b;
  }


  if (jsvIsObject(options)) {
    inf.pinRX = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "rx", 0));
    inf.pinTX = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "tx", 0));    

    JsVar *v;
    v = jsvObjectGetChild(options, "bytesize", 0);
    if (jsvIsInt(v)) 
      inf.bytesize = (unsigned char)jsvGetInteger(v);
    jsvUnLock(v);
    
    inf.parity = 0;
    v = jsvObjectGetChild(options, "parity", 0);
    if(jsvIsString(v)) {
      if(jsvIsStringEqual(v, "o") || jsvIsStringEqual(v, "odd"))
        inf.parity = 1;
      else if(jsvIsStringEqual(v, "e") || jsvIsStringEqual(v, "even"))
        inf.parity = 2;
    } else if(jsvIsInt(v)) {
      inf.parity = (unsigned char)jsvGetInteger(v);
    }
    jsvUnLock(v);
    if (inf.parity>2) {
      jsExceptionHere(JSET_ERROR, "Invalid parity %d", inf.parity);
      return;
    }

    v = jsvObjectGetChild(options, "stopbits", 0);
    if (jsvIsInt(v)) 
      inf.stopbits = (unsigned char)jsvGetInteger(v);
    jsvUnLock(v);
  }

  jshUSARTSetup(device, &inf);
  // Set baud rate in object, so we can initialise it on startup
  if (inf.baudRate != DEFAULT_BAUD_RATE) {
    jsvUnLock(jsvObjectSetChild(parent, USART_BAUDRATE_NAME, jsvNewFromInteger(inf.baudRate)));
  } else
    jsvRemoveNamedChild(parent, USART_BAUDRATE_NAME);
  // Do the same for options
  if (options)
    jsvUnLock(jsvSetNamedChild(parent, options, DEVICE_OPTIONS_NAME));
  else
    jsvRemoveNamedChild(parent, DEVICE_OPTIONS_NAME);
}
Exemplo n.º 2
0
/*JSON{
  "type" : "staticmethod",
  "class" : "fs",
  "name" : "pipe",
  "ifndef" : "SAVE_ON_FLASH",
  "generate" : "jswrap_pipe",
  "params" : [
    ["source","JsVar","The source file/stream that will send content."],
    ["destination","JsVar","The destination file/stream that will receive content from the source."],
    ["options","JsVar",["An optional object `{ chunkSize : int=64, end : bool=true, complete : function }`","chunkSize : The amount of data to pipe from source to destination at a time","complete : a function to call when the pipe activity is complete","end : call the 'end' function on the destination when the source is finished"]]
  ]
}*/
void jswrap_pipe(JsVar* source, JsVar* dest, JsVar* options) {
  if (!source || !dest) return;
  JsVar *pipe = jspNewObject(0, "Pipe");
  JsVar *arr = pipeGetArray(true);
  JsVar* position = jsvNewFromInteger(0);
  if (pipe && arr && position) {// out of memory?
    JsVar *readFunc = jspGetNamedField(source, "read", false);
    JsVar *writeFunc = jspGetNamedField(dest, "write", false);
    if(jsvIsFunction(readFunc)) {
      if(jsvIsFunction(writeFunc)) {
        JsVarInt chunkSize = 64;
        bool callEnd = true;
        // parse Options Object
        if (jsvIsObject(options)) {
          JsVar *c;
          c = jsvObjectGetChild(options, "complete", false);
          if (c) {
            jsvObjectSetChild(pipe, "#oncomplete", c);
            jsvUnLock(c);
          }
          c = jsvObjectGetChild(options, "end", false);
          if (c) callEnd = jsvGetBoolAndUnLock(c);
          c = jsvObjectGetChild(options, "chunkSize", false);
          if (c) {
            if (jsvIsNumeric(c) && jsvGetInteger(c)>0)
              chunkSize = jsvGetInteger(c);
            else
              jsWarn("chunkSize must be an integer > 0");
            jsvUnLock(c);
          }
        } else if (!jsvIsUndefined(options)) {
          jsWarn("'options' must be an object, or undefined");
        }
        // set up our event listeners
        jswrap_object_addEventListener(source, "close", jswrap_pipe_src_close_listener, JSWAT_VOID | (JSWAT_JSVAR << (JSWAT_BITS*1)));
        jswrap_object_addEventListener(dest, "drain", jswrap_pipe_drain_listener, JSWAT_VOID | (JSWAT_JSVAR << (JSWAT_BITS*1)));
        jswrap_object_addEventListener(dest, "close", jswrap_pipe_dst_close_listener, JSWAT_VOID | (JSWAT_JSVAR << (JSWAT_BITS*1)));
        // set up the rest of the pipe
        jsvUnLock(jsvObjectSetChild(pipe, "chunkSize", jsvNewFromInteger(chunkSize)));
        jsvUnLock(jsvObjectSetChild(pipe, "end", jsvNewFromBool(callEnd)));
        jsvUnLock(jsvAddNamedChild(pipe, position, "position"));
        jsvUnLock(jsvAddNamedChild(pipe, source, "source"));
        jsvUnLock(jsvAddNamedChild(pipe, dest, "destination"));
        // add the pipe to our list
        jsvArrayPush(arr, pipe);
      } else {
        jsExceptionHere(JSET_ERROR, "Destination object does not implement the required write(buffer, length, position) method.");
      }
    } else {
      jsExceptionHere(JSET_ERROR, "Source object does not implement the required read(buffer, length, position) method.");
    }
    jsvUnLock(readFunc);
    jsvUnLock(writeFunc);
  }
  jsvUnLock(arr);
  jsvUnLock(pipe);
  jsvUnLock(position);
}
Exemplo n.º 3
0
/*JSON{ "type":"method", "class": "Serial", "name" : "setup",
         "description" : "Setup this Serial port with the given baud rate and options",
         "generate" : "jswrap_serial_setup",
         "params" : [ [ "baudrate", "int", "The baud rate - the default is 9600"],
                      [ "options", "JsVar", ["An optional structure containing extra information on initialising the serial port.",
                                             "```{rx:pin,tx:pin}```",
                                             "Note that even after changing the RX and TX pins, if you have called setup before then the previous RX and TX pins will still be connected to the Serial port as well - until you set them to something else using digitalWrite" ] ] ]
}*/
void jswrap_serial_setup(JsVar *parent, JsVarInt baud, JsVar *options) {
  IOEventFlags device = jsiGetDeviceFromClass(parent);
  JshUSARTInfo inf;
  jshUSARTInitInfo(&inf);

  if (baud>0) inf.baudRate = (int)baud;

  if (jsvIsObject(options)) {

    inf.pinRX = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "rx", 0));
    inf.pinTX = jshGetPinFromVarAndUnLock(jsvObjectGetChild(options, "tx", 0));
    inf.bytesize = (unsigned char)jsvGetIntegerAndUnLock(jsvObjectGetChild(options, "bytesize", 0));

    JsVar *v;
    v = jsvObjectGetChild(options, "parity", 0);
    
    if(jsvIsNull(v)) {
      inf.parity = 0;
    }
    else if(jsvIsString(v)) {
      inf.parity = 0xFF;
      char s[8] = "";

      jsvGetString(v, s, sizeof(s) - 1);

      if(!strcmp(s, "o") || !strcmp(s, "odd")) {
        inf.parity = 1;
      }
      else if(!strcmp(s, "e") || !strcmp(s, "even")) {
        inf.parity = 2;
      }
    }
    else if(jsvIsInt(v)) {
      inf.parity = (unsigned char)jsvGetInteger(v);
    }

    jsvUnLock(v);

    v = jsvObjectGetChild(options, "stopbits", 0);
    inf.stopbits = (unsigned char)jsvGetInteger(v);
    jsvUnLock(v);
  }

  jshUSARTSetup(device, &inf);
  // Set baud rate in object, so we can initialise it on startup
  if (baud != DEFAULT_BAUD_RATE) {
    JsVar *baudVar = jsvNewFromInteger(baud);
    jsvUnLock(jsvSetNamedChild(parent, baudVar, USART_BAUDRATE_NAME));
    jsvUnLock(baudVar);
  } else
    jsvRemoveNamedChild(parent, USART_BAUDRATE_NAME);
  // Do the same for options
  if (options)
    jsvUnLock(jsvSetNamedChild(parent, options, DEVICE_OPTIONS_NAME));
  else
    jsvRemoveNamedChild(parent, DEVICE_OPTIONS_NAME);
}
Exemplo n.º 4
0
JsVar *jswrap_typedarray_constructor(JsVarDataArrayBufferViewType type, JsVar *arr, JsVarInt byteOffset, JsVarInt length) {
  JsVar *arrayBuffer = 0;
  // Only allow use of byteOffset/length if we're passing an ArrayBuffer - NOT A VIEW.
  bool copyData = false;
  if (jsvIsArrayBuffer(arr) && arr->varData.arraybuffer.type==ARRAYBUFFERVIEW_ARRAYBUFFER) {
    arrayBuffer = jsvLockAgain(arr);
  } else if (jsvIsNumeric(arr)) {
    length = jsvGetInteger(arr);
    byteOffset = 0;
    arrayBuffer = jswrap_arraybuffer_constructor((int)JSV_ARRAYBUFFER_GET_SIZE(type)*length);
  } else if (jsvIsArray(arr) || jsvIsArrayBuffer(arr)) {
    length = (JsVarInt)jsvGetLength(arr);
    byteOffset = 0;
    arrayBuffer = jswrap_arraybuffer_constructor((int)JSV_ARRAYBUFFER_GET_SIZE(type)*length);
    copyData = true; // so later on we'll populate this
  }
  if (!arrayBuffer) {
    jsExceptionHere(JSET_ERROR, "Unsupported first argument of type %t\n", arr);
    return 0;
  }
  if (length==0) {
    length = ((JsVarInt)jsvGetArrayBufferLength(arrayBuffer)-byteOffset) / (JsVarInt)JSV_ARRAYBUFFER_GET_SIZE(type); 
    if (length<0) length=0;
  }
  JsVar *typedArr = jsvNewWithFlags(JSV_ARRAYBUFFER);
  if (typedArr) {
    typedArr->varData.arraybuffer.type = type;
    typedArr->varData.arraybuffer.byteOffset = (unsigned short)byteOffset;
    typedArr->varData.arraybuffer.length = (unsigned short)length;
    jsvSetFirstChild(typedArr, jsvGetRef(jsvRef(arrayBuffer)));

    if (copyData) {
      // if we were given an array, populate this ArrayBuffer
      JsvIterator it;
      jsvIteratorNew(&it, arr, JSIF_DEFINED_ARRAY_ElEMENTS);
      while (jsvIteratorHasElement(&it)) {
        JsVar *idx = jsvIteratorGetKey(&it);
        if (jsvIsInt(idx)) {
          JsVar *val = jsvIteratorGetValue(&it);
          // TODO: This is horrible! We need to try and iterate properly...
          jsvArrayBufferSet(typedArr, (size_t)jsvGetInteger(idx), val);
          jsvUnLock(val);
        }
        jsvUnLock(idx);
        jsvIteratorNext(&it);
      }
      jsvIteratorFree(&it);
    }
  }
  jsvUnLock(arrayBuffer);
  return typedArr;
}
Exemplo n.º 5
0
/*JSON{
  "type" : "method",
  "class" : "Object",
  "name" : "toString",
  "generate" : "jswrap_object_toString",
  "params" : [
    ["radix","JsVar","If the object is an integer, the radix (between 2 and 36) to use. NOTE: Setting a radix does not work on floating point numbers."]
  ],
  "return" : ["JsVar","A String representing the object"]
}
Convert the Object to a string
 */
JsVar *jswrap_object_toString(JsVar *parent, JsVar *arg0) {
  if (jsvIsInt(arg0) && jsvIsNumeric(parent)) {
    JsVarInt radix = jsvGetInteger(arg0);
    if (radix>=2 && radix<=36) {
      char buf[JS_NUMBER_BUFFER_SIZE];
      if (jsvIsInt(parent))
        itostr(jsvGetInteger(parent), buf, (unsigned int)radix);
      else
        ftoa_bounded_extra(jsvGetFloat(parent), buf, sizeof(buf), (int)radix, -1);
      return jsvNewFromString(buf);
    }
  }
  return jsvAsString(parent, false);
}
Exemplo n.º 6
0
/*JSON{
  "type" : "staticmethod",
  "class" : "Trig",
  "name" : "setup",
  "generate" : "jswrap_trig_setup",
  "params" : [
    ["pin","pin","The pin to use for triggering"],
    ["options","JsVar","Additional options as an object. defaults are: ```{teethTotal:60,teethMissing:2,minRPM:30,keyPosition:0}```"]
  ]
}
Initialise the trigger class
*/
void jswrap_trig_setup(Pin pin, JsVar *options) {
  if (!jshIsPinValid(pin)) {
    jsError("Invalid pin supplied as an argument to Trig.setup");
    return;
  }

  TriggerStruct *trig = &mainTrigger;
  // static info
  trig->teethMissing = 2;
  trig->teethTotal = 60;
  trig->keyPosition = 0;
  JsVarFloat minRPM = 30;
  if (jsvIsObject(options)) {
    JsVar *v;
    v = jsvObjectGetChild(options, "teethMissing", 0);
    if (!jsvIsUndefined(v)) trig->teethMissing = (unsigned char)jsvGetInteger(v);
    jsvUnLock(v);
    v = jsvObjectGetChild(options, "teethTotal", 0);
    if (!jsvIsUndefined(v)) trig->teethTotal = (unsigned char)jsvGetInteger(v);
    jsvUnLock(v);
    v = jsvObjectGetChild(options, "minRPM", 0);
    if (!jsvIsUndefined(v)) minRPM = jsvGetFloat(v);
    jsvUnLock(v);
    v = jsvObjectGetChild(options, "keyPosition", 0);
    if (!jsvIsUndefined(v)) trig->keyPosition = jsvGetFloat(v);
    jsvUnLock(v);
  }
  trig->maxTooth = (unsigned int)jshGetTimeFromMilliseconds(60000 / (JsVarFloat)(trig->teethTotal * minRPM));

  // semi-static info
  int i;
  for (i=0;i<TRIGGER_TRIGGERS_COUNT;i++) {
    trig->triggers[i].tooth = TRIGGERPOINT_TOOTH_DISABLE;
    trig->triggers[i].newTooth = TRIGGERPOINT_TOOTH_DISABLE;
  }
  // dynamic info
  trig->lastTime = jshGetSystemTime();
  trig->avrTrigger = (unsigned int)jshGetTimeFromMilliseconds(10); // average time for a trigger pulse
  trig->avrTooth = (unsigned int)jshGetTimeFromMilliseconds(10); // average time for a tooth
  trig->currTooth = 0;
  trig->teethSinceStart = 0;
  trig->wrongTriggerTeeth = 0;
  // finally set up the watch!
  if (jshIsPinValid(trig->sensorPin))
    jshPinWatch(trig->sensorPin, false);
  trig->sensorPin = pin;
  jshPinWatch(trig->sensorPin, true);
}
Exemplo n.º 7
0
/*JSON{
 "type"     : "method",
 "class"    : "Queue",
 "name"     : "read",
 "generate" : "jswrap_Queue_read"
}
reads one character from queue, if available
*/
void jswrap_Queue_read(JsVar *parent) {
  char data;
  JsVar *idx = jsvObjectGetChild(parent,"index",1);
  queue_read(jsvGetInteger(idx));
  jsvUnLock(idx);
  return;
}
Exemplo n.º 8
0
void   jsvArrayBufferIteratorSetValue(JsvArrayBufferIterator *it, JsVar *value) {
  if (it->type == ARRAYBUFFERVIEW_UNDEFINED) return;
  assert(!it->hasAccessedElement); // we just haven't implemented this case yet
  char data[8];
  unsigned int i,dataLen = JSV_ARRAYBUFFER_GET_SIZE(it->type);

  if (JSV_ARRAYBUFFER_IS_FLOAT(it->type)) {
    JsVarFloat v = jsvGetFloat(value);       ;
    if (dataLen==4) { float f = (float)v; memcpy(data,&f,dataLen); }
    else if (dataLen==8) { double f = (double)v; memcpy(data,&f,dataLen); }
    else assert(0);
  } else {
    JsVarInt v = jsvGetInteger(value);
    // we don't care about sign when writing - as it gets truncated
    if (dataLen==1) { char c = (char)v; memcpy(data,&c,dataLen); }
    else if (dataLen==2) { short c = (short)v; memcpy(data,&c,dataLen); }
    else if (dataLen==4) { int c = (int)v; memcpy(data,&c,dataLen); }
    else if (dataLen==8) { long long c = (long long)v; memcpy(data,&c,dataLen); }
    else assert(0);
  }

  for (i=0;i<dataLen;i++) {
    jsvStringIteratorSetChar(&it->it, data[i]);
    if (dataLen!=1) jsvStringIteratorNext(&it->it);
  }
  if (dataLen!=1) it->hasAccessedElement = true;
}
Exemplo n.º 9
0
/*JSON{ "type":"method", "class": "Array", "name" : "reduce",
         "description" : "Execute `previousValue=initialValue` and then `previousValue = callback(previousValue, currentValue, index, array)` for each element in the array, and finally return previousValue.",
         "generate" : "jswrap_array_reduce",
         "params" : [ [ "callback", "JsVar", "Function used to reduce the array"] ,
                      [ "initialValue", "JsVar", "if specified, the initial value to pass to the function"] ],
         "return" : ["JsVar", "The value returned by the last function called"]
}*/
JsVar *jswrap_array_reduce(JsVar *parent, JsVar *funcVar, JsVar *initialValue) {
  const char *name = "reduce";
  if (!jsvIsIterable(parent)) {
    jsError("Array.%s can only be called on something iterable", name);
    return 0;
  }
  if (!jsvIsFunction(funcVar)) {
    jsError("Array.%s's first argument should be a function", name);
    return 0;
  }
  JsVar *previousValue = initialValue ? jsvLockAgain(initialValue) : 0;
  JsvIterator it;
  jsvIteratorNew(&it, parent);
  while (jsvIteratorHasElement(&it)) {
    JsVar *index = jsvIteratorGetKey(&it);
    if (jsvIsInt(index)) {
      JsVarInt idxValue = jsvGetInteger(index);

      JsVar *args[4];
      args[0] = previousValue;
      args[1] = jsvIteratorGetValue(&it);
      args[2] = jsvNewFromInteger(idxValue); // child is a variable name, create a new variable for the index
      args[3] = parent;
      previousValue = jspeFunctionCall(funcVar, 0, 0, false, 4, args);
      jsvUnLock(args[0]);
      jsvUnLock(args[1]);
      jsvUnLock(args[2]);
    }
    jsvUnLock(index);
    jsvIteratorNext(&it);
  }
  jsvIteratorFree(&it);

  return previousValue;
}
Exemplo n.º 10
0
/*JSON{
  "type" : "function",
  "name" : "show",
  "generate" : "jswrap_microbit_show",
  "params" : [
     ["image","JsVar","The image to show"]
  ]
}
Show an image on the in-built 5x5 LED screen.

Image can be:

* A number where each bit represents a pixel (so 25 bits)

*/
void jswrap_microbit_show(JsVar *image) {
  if (!jsvIsInt(image)) {
    jsError("Expecting a number, got %t\n", image);
    return;
  }
  uint32_t newState = jsvGetInteger(image);

  if ((newState!=0) && (microbitLEDState==0)) {
    // we want to display something but we don't have an interval
    jstExecuteFn(jswrap_microbit_display_callback, jshGetTimeFromMilliseconds(5));
    // and also set pins to outputs
    nrf_gpio_cfg_output(MB_LED_COL1);
    nrf_gpio_cfg_output(MB_LED_COL2);
    nrf_gpio_cfg_output(MB_LED_COL3);
    nrf_gpio_cfg_output(MB_LED_COL4);
    nrf_gpio_cfg_output(MB_LED_COL5);
    nrf_gpio_cfg_output(MB_LED_COL6);
    nrf_gpio_cfg_output(MB_LED_COL7);
    nrf_gpio_cfg_output(MB_LED_COL8);
    nrf_gpio_cfg_output(MB_LED_COL9);
    nrf_gpio_cfg_output(MB_LED_ROW1);
    nrf_gpio_cfg_output(MB_LED_ROW2);
    nrf_gpio_cfg_output(MB_LED_ROW3);
  } else  if ((newState==0) && (microbitLEDState!=0)) {
    jswrap_microbit_stopDisplay();
  }
  microbitLEDState = newState;
}
Exemplo n.º 11
0
void jsvArrayBufferIteratorSetValue(JsvArrayBufferIterator *it, JsVar *value) {
  if (it->type == ARRAYBUFFERVIEW_UNDEFINED) return;
  assert(!it->hasAccessedElement); // we just haven't implemented this case yet
  char data[8];
  int i,dataLen = (int)JSV_ARRAYBUFFER_GET_SIZE(it->type);

  if (JSV_ARRAYBUFFER_IS_FLOAT(it->type)) {
    jsvArrayBufferIteratorFloatToData(data, (unsigned)dataLen, it->type, jsvGetFloat(value));
  } else {
    jsvArrayBufferIteratorIntToData(data, (unsigned)dataLen, it->type, jsvGetInteger(value));
  }

  if (it->type & ARRAYBUFFERVIEW_BIG_ENDIAN) {
    for (i=dataLen-1;i>=0;i--) {
      jsvStringIteratorSetChar(&it->it, data[i]);
      if (dataLen!=1) jsvStringIteratorNext(&it->it);
    }
  } else {
    for (i=0;i<dataLen;i++) {
      jsvStringIteratorSetChar(&it->it, data[i]);
      if (dataLen!=1) jsvStringIteratorNext(&it->it);
    }
  }
  if (dataLen!=1) it->hasAccessedElement = true;
}
Exemplo n.º 12
0
JsVar *jswrap_typedarray_constructor(JsVarDataArrayBufferViewType type, JsVar *arr, JsVarInt byteOffset, JsVarInt length) {
  JsVar *arrayBuffer = 0;
  if (jsvIsArrayBuffer(arr)) {
    arrayBuffer = jsvLockAgain(arr);
  } else if (jsvIsInt(arr)) {
    length = jsvGetInteger(arr);
    byteOffset = 0;
    arrayBuffer = jswrap_arraybuffer_constructor(JSV_ARRAYBUFFER_GET_SIZE(type)*length);
  } else if (jsvIsArray(arr)) {
    length = jsvGetArrayLength(arr);
    byteOffset = 0;
    arrayBuffer = jswrap_arraybuffer_constructor(JSV_ARRAYBUFFER_GET_SIZE(type)*length);
    // later on we'll populate this
  }
  if (!arrayBuffer) {
    jsError("Unsupported first argument\n");
    return 0;
  }
  if (length<=0) length = (JsVarInt)jsvGetArrayBufferLength(arrayBuffer) / JSV_ARRAYBUFFER_GET_SIZE(type);
  JsVar *typedArr = jsvNewWithFlags(JSV_ARRAYBUFFER);
  if (typedArr) {
    typedArr->varData.arraybuffer.type = type;
    typedArr->varData.arraybuffer.byteOffset = (unsigned short)byteOffset;
    typedArr->varData.arraybuffer.length = (unsigned short)length;
    typedArr->firstChild = jsvGetRef(jsvRef(arrayBuffer));

    if (jsvIsArray(arr)) {
      // if we were given an array, populate this ArrayBuffer
      JsvArrayIterator it;
      jsvArrayIteratorNew(&it, arr);
      while (jsvArrayIteratorHasElement(&it)) {
        JsVar *idx = jsvArrayIteratorGetIndex(&it);
        if (jsvIsInt(idx)) {
          JsVar *val = jsvArrayIteratorGetElement(&it);
          jsvArrayBufferSet(typedArr, jsvGetInteger(idx), val);
          jsvUnLock(val);
        }
        jsvUnLock(idx);
        jsvArrayIteratorNext(&it);
      }
      jsvArrayIteratorFree(&it);
    }
  }
  jsvUnLock(arrayBuffer);
  return typedArr;
}
Exemplo n.º 13
0
static NO_INLINE int i2c_get_address(JsVar *address, bool *sendStop) {
  *sendStop = true;
  if (jsvIsObject(address)) {
    JsVar *stopVar = jsvObjectGetChild(address, "stop", 0);
    if (stopVar) *sendStop = jsvGetBoolAndUnLock(stopVar);
    return jsvGetIntegerAndUnLock(jsvObjectGetChild(address, "address", 0));
  } else
    return jsvGetInteger(address);
}
Exemplo n.º 14
0
/*JSON{ "type":"method", "class": "String", "name" : "substr",
         "generate" : "jswrap_string_substr",
         "params" : [ [ "start", "int", "The start character index"],
                      [ "len", "JsVar", "The number of characters"] ],
         "return" : ["JsVar", "Part of this string from start for len characters"]
}*/
JsVar *jswrap_string_substr(JsVar *parent, JsVarInt pStart, JsVar *vLen) {
  JsVar *res;
  JsVarInt pLen = jsvIsUndefined(vLen) ? JSVAPPENDSTRINGVAR_MAXLENGTH : (int)jsvGetInteger(vLen);
  if (pLen<0) pLen=0;
  res = jsvNewWithFlags(JSV_STRING);
  if (!res) return 0; // out of memory
  jsvAppendStringVar(res, parent, (int)pStart, (int)pLen);
  return res;
}
Exemplo n.º 15
0
/*JSON{
  "type"     : "staticmethod",
  "class"    : "ESP8266WiFi",
  "name"     : "getAddressAsString",
  "generate" : "jswrap_ESP8266WiFi_getAddressAsString",
  "params"   : [
    ["address","JsVar","An integer value representing an IP address."]
  ],
  "return"   : ["JsVar","A String"]
}*/
JsVar *jswrap_ESP8266WiFi_getAddressAsString(
    JsVar *address //!< An integer value representing an IP address.
  ) {
  if (!jsvIsInt(address)) {
    jsExceptionHere(JSET_ERROR, "No SSID.");
    return NULL;
  }
  uint32 iAddress = (uint32)jsvGetInteger(address);
  return networkGetAddressAsString((uint8 *)&iAddress, 4, 10, '.');
}
Exemplo n.º 16
0
/*JSON{
  "type" : "constructor",
  "class" : "Array",
  "name" : "Array",
  "generate" : "jswrap_array_constructor",
  "params" : [
    ["args","JsVarArray","The length of the array OR any number of items to add to the array"]
  ],
  "return" : ["JsVar","An Array"]
}
Create an Array. Either give it one integer argument (>=0) which is the length of the array, or any number of arguments 
*/
JsVar *jswrap_array_constructor(JsVar *args) {
  assert(args);
  if (jsvGetArrayLength(args)==1) {
    JsVar *firstArg = jsvSkipNameAndUnLock(jsvGetArrayItem(args,0));
    if (jsvIsInt(firstArg) && jsvGetInteger(firstArg)>=0) {
      JsVarInt count = jsvGetInteger(firstArg);
      if (count>0) {
        JsVar *arr = jsvNewWithFlags(JSV_ARRAY);
        if (!arr) return 0; // out of memory
        jsvSetArrayLength(arr, count, false);
        jsvUnLock(firstArg);
        return arr;
      }
    }
    jsvUnLock(firstArg);
  }
  // Otherwise, we just return the array!
  return jsvLockAgain(args);
}
Exemplo n.º 17
0
/** Iterate over the contents of var, calling callback for each. Contents may be:
 *   * numeric -> output
 *   * a string -> output each character
 *   * array/arraybuffer -> call itself on each element
 *   * object -> call itself object.count times, on object.data
 */
bool jsvIterateCallback(JsVar *data, void (*callback)(int item, void *callbackData), void *callbackData) {
  bool ok = true;
  if (jsvIsNumeric(data)) {
    callback((int)jsvGetInteger(data), callbackData);
  } else if (jsvIsObject(data)) {
    JsVar *countVar = jsvObjectGetChild(data, "count", 0);
    JsVar *dataVar = jsvObjectGetChild(data, "data", 0);
    if (countVar && dataVar && jsvIsNumeric(countVar)) {
      int n = (int)jsvGetInteger(countVar);
      while (ok && n-- > 0) {
        ok = jsvIterateCallback(dataVar, callback, callbackData);
      }
    } else {
      jsWarn("If specifying an object, it must be of the form {data : ..., count : N}");
    }
    jsvUnLock(countVar);
    jsvUnLock(dataVar);
  } else if (jsvIsString(data)) {
    JsvStringIterator it;
    jsvStringIteratorNew(&it, data, 0);
    while (jsvStringIteratorHasChar(&it) && ok) {
      char ch = jsvStringIteratorGetChar(&it);
      callback(ch, callbackData);
      jsvStringIteratorNext(&it);
    }
    jsvStringIteratorFree(&it);
  } else if (jsvIsIterable(data)) {
    JsvIterator it;
    jsvIteratorNew(&it, data);
    while (jsvIteratorHasElement(&it) && ok) {
      JsVar *el = jsvIteratorGetValue(&it);
      ok = jsvIterateCallback(el, callback, callbackData);
      jsvUnLock(el);
      jsvIteratorNext(&it);
    }
    jsvIteratorFree(&it);
  } else {
    jsWarn("Expecting a number or something iterable, got %t", data);
    ok = false;
  }
  return ok;
}
Exemplo n.º 18
0
/*JSON{
  "type" : "method",
  "class" : "String",
  "name" : "lastIndexOf",
  "generate_full" : "jswrap_string_indexOf(parent, substring, fromIndex, true)",
  "params" : [
    ["substring","JsVar","The string to search for"],
    ["fromIndex","JsVar","Index to search from"]
  ],
  "return" : ["int32","The index of the string, or -1 if not found"]
}
Return the last index of substring in this string, or -1 if not found
*/
int jswrap_string_indexOf(JsVar *parent, JsVar *substring, JsVar *fromIndex, bool lastIndexOf) {
  if (!jsvIsString(parent)) return 0;
  // slow, but simple!
  substring = jsvAsString(substring, false);
  if (!substring) return 0; // out of memory
  int parentLength = (int)jsvGetStringLength(parent);
  int subStringLength = (int)jsvGetStringLength(substring);
  if (subStringLength > parentLength) {
    jsvUnLock(substring);
    return -1;
  }
  int lastPossibleSearch = parentLength - subStringLength;
  int idx, dir, end;
  if (!lastIndexOf) { // normal indexOf
    dir = 1;
    end = lastPossibleSearch+1;
    idx = 0;
    if (jsvIsNumeric(fromIndex)) {
      idx = (int)jsvGetInteger(fromIndex);
      if (idx<0) idx=0;
      if (idx>end) idx=end;
    }
  } else {
    dir = -1;
    end = -1;
    idx = lastPossibleSearch;
    if (jsvIsNumeric(fromIndex)) {
      idx = (int)jsvGetInteger(fromIndex);
      if (idx<0) idx=0;
      if (idx>lastPossibleSearch) idx=lastPossibleSearch;
    }
  }

  for (;idx!=end;idx+=dir) {
    if (jsvCompareString(parent, substring, (size_t)idx, 0, true)==0) {
      jsvUnLock(substring);
      return idx;
    }
  }
  jsvUnLock(substring);
  return -1;
}
Exemplo n.º 19
0
/*JSON{ "type":"method", "class": "Object", "name" : "toString",
         "description" : "Convert the Object to a string",
         "generate" : "jswrap_object_toString",
         "params" : [ [ "radix", "JsVar", "If the object is an integer, the radix (between 2 and 36) to use. NOTE: Setting a radix does not work on floating point numbers."] ],
         "return" : ["JsVar", "A String representing the object"]
}*/
JsVar *jswrap_object_toString(JsVar *parent, JsVar *arg0) {
  if (jsvIsInt(arg0) && jsvIsInt(parent)) {
    JsVarInt radix = jsvGetInteger(arg0);
    if (radix>=2 && radix<=36) {
      char buf[JS_NUMBER_BUFFER_SIZE];
      itoa(parent->varData.integer, buf, (unsigned int)radix);
      return jsvNewFromString(buf);
    }
  }
  return jsvAsString(parent, false);
}
Exemplo n.º 20
0
/*JSON{
  "type" : "method",
  "class" : "String",
  "name" : "substr",
  "generate" : "jswrap_string_substr",
  "params" : [
    ["start","int","The start character index"],
    ["len","JsVar","The number of characters"]
  ],
  "return" : ["JsVar","Part of this string from start for len characters"]
}*/
JsVar *jswrap_string_substr(JsVar *parent, JsVarInt pStart, JsVar *vLen) {
  JsVar *res;
  JsVarInt pLen = jsvIsUndefined(vLen) ? JSVAPPENDSTRINGVAR_MAXLENGTH : (int)jsvGetInteger(vLen);
  if (pLen<0) pLen = 0;
  if (pStart<0) pStart += (JsVarInt)jsvGetStringLength(parent);
  if (pStart<0) pStart = 0;
  res = jsvNewFromEmptyString();
  if (!res) return 0; // out of memory
  jsvAppendStringVar(res, parent, (size_t)pStart, (size_t)pLen);
  return res;
}
Exemplo n.º 21
0
JsVar *jsvIteratorGetValue(JsvIterator *it) {
  switch (it->type) {
  case JSVI_FULLARRAY: if (jsvIsIntegerish(it->it.obj.it.var) &&
                           jsvGetInteger(it->it.obj.it.var) == it->it.obj.index)
                         return jsvObjectIteratorGetValue(&it->it.obj.it);
                       return 0;
  case JSVI_OBJECT : return jsvObjectIteratorGetValue(&it->it.obj.it);
  case JSVI_STRING : { char buf[2] = {jsvStringIteratorGetChar(&it->it.str),0}; return jsvNewFromString(buf); }
  case JSVI_ARRAYBUFFER : return jsvArrayBufferIteratorGetValueAndRewind(&it->it.buf);
  default: assert(0); return 0;
  }
}
Exemplo n.º 22
0
JsVarFloat jsvIteratorGetFloatValue(JsvIterator *it) {
  switch (it->type) {
  case JSVI_FULLARRAY: if (jsvIsIntegerish(it->it.obj.it.var) &&
                           jsvGetInteger(it->it.obj.it.var) == it->it.obj.index)
                         return jsvGetFloatAndUnLock(jsvObjectIteratorGetValue(&it->it.obj.it));
                       return NAN;
  case JSVI_OBJECT : return jsvGetFloatAndUnLock(jsvObjectIteratorGetValue(&it->it.obj.it));
  case JSVI_STRING : return (JsVarFloat)jsvStringIteratorGetChar(&it->it.str);
  case JSVI_ARRAYBUFFER : return jsvArrayBufferIteratorGetFloatValue(&it->it.buf);
  default: assert(0); return NAN;
  }
}
Exemplo n.º 23
0
/*JSON{
  "type" : "method",
  "class" : "ArrayBufferView",
  "name" : "map",
  "generate" : "jswrap_arraybufferview_map",
  "params" : [
    ["function","JsVar","Function used to map one item to another"],
    ["thisArg","JsVar","if specified, the function is called with 'this' set to thisArg (optional)"]
  ],
  "return" : ["JsVar","An array containing the results"],
  "return_object" : "ArrayBufferView"
}
Return an array which is made from the following: ```A.map(function) = [function(A[0]), function(A[1]), ...]```

**Note:** This returns an ArrayBuffer of the same type it was called on. To get an Array, use `Array.prototype.map`
*/
JsVar *jswrap_arraybufferview_map(JsVar *parent, JsVar *funcVar, JsVar *thisVar) {
  if (!jsvIsArrayBuffer(parent)) {
    jsExceptionHere(JSET_ERROR, "ArrayBufferView.map can only be called on an ArrayBufferView");
    return 0;
  }
  if (!jsvIsFunction(funcVar)) {
    jsExceptionHere(JSET_ERROR, "ArrayBufferView.map's first argument should be a function");
    return 0;
  }
  if (!jsvIsUndefined(thisVar) && !jsvIsObject(thisVar)) {
    jsExceptionHere(JSET_ERROR, "ArrayBufferView.map's second argument should be undefined, or an object");
    return 0;
  }

  // create ArrayBuffer result
  JsVarDataArrayBufferViewType arrayBufferType = parent->varData.arraybuffer.type;
  JsVar *arrayBufferLength = jsvNewFromInteger((JsVarInt)jsvGetArrayBufferLength(parent));
  JsVar *array = jswrap_typedarray_constructor(arrayBufferType, arrayBufferLength, 0, 0);
  jsvUnLock(arrayBufferLength);
  if (!array) return 0;

  // now iterate
  JsvIterator it; // TODO: if we really are limited to ArrayBuffers, this could be an ArrayBufferIterator.
  jsvIteratorNew(&it, parent);
  JsvArrayBufferIterator itdst;
  jsvArrayBufferIteratorNew(&itdst, array, 0);

  while (jsvIteratorHasElement(&it)) {
    JsVar *index = jsvIteratorGetKey(&it);
    if (jsvIsInt(index)) {
      JsVarInt idxValue = jsvGetInteger(index);

      JsVar *args[3], *mapped;
      args[0] = jsvIteratorGetValue(&it);
      args[1] = jsvNewFromInteger(idxValue); // child is a variable name, create a new variable for the index
      args[2] = parent;
      mapped = jspeFunctionCall(funcVar, 0, thisVar, false, 3, args);
      jsvUnLock(args[0]);
      jsvUnLock(args[1]);
      if (mapped) {
        jsvArrayBufferIteratorSetValue(&itdst, mapped);
        jsvUnLock(mapped);
      }
    }
    jsvUnLock(index);
    jsvIteratorNext(&it);
    jsvArrayBufferIteratorNext(&itdst);
  }
  jsvIteratorFree(&it);
  jsvArrayBufferIteratorFree(&itdst);

  return array;
}
Exemplo n.º 24
0
/*JSON{
  "type" : "method",
  "class" : "String",
  "name" : "endsWith",
  "ifndef" : "SAVE_ON_FLASH",
  "generate" : "jswrap_string_endsWith",
  "params" : [
    ["searchString","JsVar","The string to search for"],
    ["length","JsVar","The 'end' of the string - if left off the actual length of the string is used"]
  ],
  "return" : ["bool","`true` if the given characters are found at the end of the string, otherwise, `false`."]
}
*/
bool jswrap_string_endsWith(JsVar *parent, JsVar *search, JsVar *length) {
  if (!jsvIsString(parent)) return false;
  int position = jsvIsNumeric(length) ? jsvGetInteger(length) : (int)jsvGetStringLength(parent);
  JsVar *searchStr = jsvAsString(search);
  position -= jsvGetStringLength(searchStr);
  bool match = false;
  if (position >= 0 &&
      jsvGetStringLength(searchStr)+position <= jsvGetStringLength(parent))
    match = jsvCompareString(parent, searchStr, position,0,true)==0;
  jsvUnLock(searchStr);
  return match;
}
Exemplo n.º 25
0
/*JSON{ "type":"function", "name" : "parseInt",
         "description" : "Convert a string representing a number into an integer",
         "generate" : "jswrap_parseInt",
         "params" :  [ [ "string", "JsVar", ""],
                       [ "radix", "JsVar", "The Radix of the string (optional)"] ],
         "return" : ["JsVar", "The integer value of the string (or NaN)"]
}*/
JsVar *jswrap_parseInt(JsVar *v, JsVar *radixVar) {
  int radix = 0/*don't force radix*/;
  if (jsvIsNumeric(radixVar))
    radix = (int)jsvGetInteger(radixVar);

  char buffer[JS_NUMBER_BUFFER_SIZE];
  jsvGetString(v, buffer, JS_NUMBER_BUFFER_SIZE);
  bool hasError;
  JsVarInt i = stringToIntWithRadix(buffer, radix, &hasError);
  if (hasError) return jsvNewFromFloat(NAN);
  return jsvNewFromInteger(i);
}
Exemplo n.º 26
0
int jswrap_E_flashFatFS(JsVar* options) {
  uint32_t addr = FS_FLASH_BASE;
  uint16_t sectors = FS_SECTOR_COUNT;
  uint8_t format = 0;
  if (jsvIsObject(options)) {
    JsVar *a = jsvObjectGetChild(options, "addr", false);
    if (a) {
      if (jsvIsNumeric(a) && jsvGetInteger(a)>0x100000)
        addr = (uint32_t)jsvGetInteger(a);
    }
    JsVar *s = jsvObjectGetChild(options, "sectors", false);
    if (s) {
      if (jsvIsNumeric(s) && jsvGetInteger(s)>0)
        sectors = (uint16_t)jsvGetInteger(s);
    }
    JsVar *f = jsvObjectGetChild(options, "format", false);
    if (f) {
      if (jsvIsBoolean(f))
        format = jsvGetBool(f);
    }
  }
  else if (!jsvIsUndefined(options)) {
    jsExceptionHere(JSET_TYPEERROR, "'options' must be an object, or undefined");
  }
  
  uint8_t init=flashFatFsInit(addr, sectors);
  if (init) {
    if ( format ) {
      uint8_t res = f_mount(&jsfsFAT, "", 0);
      jsDebug("Formatting Flash");
      res = f_mkfs("", 1, 0);  // Super Floppy format, using all space (not partition table)
      if (res != FR_OK) {
        jsExceptionHere(JSET_INTERNALERROR, "Flash Formatting error:",res);
        return false;
     }
   }    
  }
  jsfsInit();
  return true;
}
Exemplo n.º 27
0
/*JSON{
  "type" : "method",
  "class" : "SPI",
  "name" : "send4bit",
  "generate" : "jswrap_spi_send4bit",
  "params" : [
    ["data","JsVar","The data to send - either an integer, array, or string"],
    ["bit0","int32","The 4 bits to send for a 0 (MSB first)"],
    ["bit1","int32","The 4 bits to send for a 1 (MSB first)"],
    ["nss_pin","pin","An nSS pin - this will be lowered before SPI output and raised afterwards (optional). There will be a small delay between when this is lowered and when sending starts, and also between sending finishing and it being raised."]
  ]
}
Send data down SPI, using 4 bits for each 'real' bit (MSB first). This can be useful for faking one-wire style protocols

Sending multiple bytes in one call to send is preferable as they can then be transmitted end to end. Using multiple calls to send() will result in significantly slower transmission speeds.
 */
void jswrap_spi_send4bit(JsVar *parent, JsVar *srcdata, int bit0, int bit1, Pin nss_pin) {
  NOT_USED(parent);
  IOEventFlags device = jsiGetDeviceFromClass(parent);
  if (!DEVICE_IS_SPI(device)) {
    jsExceptionHere(JSET_ERROR, "SPI.send4bit only works on hardware SPI");
    return;
  }

  jshSPISet16(device, true); // 16 bit output

  if (bit0==0 && bit1==0) {
    bit0 = 0x01;
    bit1 = 0x03;
  }
  bit0 = bit0 & 0x0F;
  bit1 = bit1 & 0x0F;

  if (!jshIsDeviceInitialised(device)) {
    JshSPIInfo inf;
    jshSPIInitInfo(&inf);
    jshSPISetup(device, &inf);
  }

  // we're just sending (no receive)
  jshSPISetReceive(device, false);
  // assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, false);

  // send data
  if (jsvIsNumeric(srcdata)) {
    jsspiSend4bit(device, (unsigned char)jsvGetInteger(srcdata), bit0, bit1);
  } else if (jsvIsIterable(srcdata)) {
    jshInterruptOff();
    JsvIterator it;
    jsvIteratorNew(&it, srcdata);
    while (jsvIteratorHasElement(&it)) {
      unsigned char in = (unsigned char)jsvIteratorGetIntegerValue(&it);
      jsspiSend4bit(device, in, bit0, bit1);
      jsvIteratorNext(&it);
    }
    jsvIteratorFree(&it);
    jshInterruptOn();
  } else {
    jsExceptionHere(JSET_ERROR, "Variable type %t not suited to transmit operation", srcdata);
  }

  jshSPIWait(device); // wait until SPI send finished and clear the RX buffer

  // de-assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, true);
  jshSPISet16(device, false); // back to 8 bit
}
Exemplo n.º 28
0
/*JSON{ "type":"method", "class": "Array", "name" : "slice",
         "description" : "Return a copy of a portion of the calling array",
         "generate" : "jswrap_array_slice",
         "params" : [ [ "start", "JsVar", "Start index"],
                      [ "end", "JsVar", "End index (optional)"] ],
         "return" : ["JsVar", "A new array"]
}*/
JsVar *jswrap_array_slice(JsVar *parent, JsVar *startVar, JsVar *endVar) {
  JsVarInt len = jsvGetLength(parent);
  JsVarInt start = 0;
  JsVarInt end = len;

  if (!jsvIsUndefined(startVar))
    start = jsvGetInteger(startVar);

  if (!jsvIsUndefined(endVar))
    end = jsvGetInteger(endVar);

  JsVarInt k = 0;
  JsVarInt final = len;
  JsVar *array = jsvNewWithFlags(JSV_ARRAY);

  if (!array) return 0;

  if (start<0) k = max((len + start), 0);
  else k = min(start, len);

  if (end<0) final = max((len + end), 0);
  else final = min(end, len);
Exemplo n.º 29
0
void jsvIteratorNext(JsvIterator *it) {
  switch (it->type) {
  case JSVI_FULLARRAY: it->it.obj.index++;
                       if (jsvIsIntegerish(it->it.obj.it.var) &&
                           jsvGetInteger(it->it.obj.it.var)<it->it.obj.index)
                         jsvObjectIteratorNext(&it->it.obj.it);
                       break;
  case JSVI_OBJECT : jsvObjectIteratorNext(&it->it.obj.it); break;
  case JSVI_STRING : jsvStringIteratorNext(&it->it.str); break;
  case JSVI_ARRAYBUFFER : jsvArrayBufferIteratorNext(&it->it.buf); break;
  default: assert(0); break;
  }
}
Exemplo n.º 30
0
/*JSON{
  "type" : "method",
  "class" : "String",
  "name" : "slice",
  "generate" : "jswrap_string_slice",
  "params" : [
    ["start","int","The start character index, if negative it is from the end of the string"],
    ["end","JsVar","The end character index, if negative it is from the end of the string, and if omitted it is the end of the string"]
  ],
  "return" : ["JsVar","Part of this string from start for len characters"]
}*/
JsVar *jswrap_string_slice(JsVar *parent, JsVarInt pStart, JsVar *vEnd) {
  JsVar *res;
  JsVarInt pEnd = jsvIsUndefined(vEnd) ? JSVAPPENDSTRINGVAR_MAXLENGTH : (int)jsvGetInteger(vEnd);
  if (pStart<0) pStart += (JsVarInt)jsvGetStringLength(parent);
  if (pEnd<0) pEnd += (JsVarInt)jsvGetStringLength(parent);
  if (pStart<0) pStart = 0;
  if (pEnd<0) pEnd = 0;
  res = jsvNewFromEmptyString();
  if (!res) return 0; // out of memory
  if (pEnd>pStart)
    jsvAppendStringVar(res, parent, (size_t)pStart, (size_t)(pEnd-pStart));
  return res;
}