Example #1
0
/*JSON{
  "type" : "method",
  "class" : "I2C",
  "name" : "readFrom",
  "generate" : "jswrap_i2c_readFrom",
  "params" : [
    ["address","JsVar","The 7 bit address of the device to request bytes from, or an object of the form `{address:12, stop:false}` to send this data without a STOP signal."],
    ["quantity","int32","The number of bytes to request"]
  ],
  "return" : ["JsVar","The data that was returned - as a Uint8Array"],
  "return_object" : "Uint8Array"
}
Request bytes from the given slave device, and return them as a Uint8Array (packed array of bytes). This is like using Arduino Wire's requestFrom, available and read functions.  Sends a STOP
 */
JsVar *jswrap_i2c_readFrom(JsVar *parent, JsVar *addressVar, int nBytes) {
  IOEventFlags device = jsiGetDeviceFromClass(parent);
  if (!DEVICE_IS_I2C(device)) return 0;

  bool sendStop = true;
  int address = i2c_get_address(addressVar, &sendStop);

  if (nBytes<=0)
    return 0;
  if ((unsigned int)nBytes+256 > jsuGetFreeStack()) {
    jsExceptionHere(JSET_ERROR, "Not enough free stack to receive this amount of data");
    return 0;
  }
  unsigned char *buf = (unsigned char *)alloca((size_t)nBytes);

  jshI2CRead(device, (unsigned char)address, nBytes, buf, sendStop);

  JsVar *array = jsvNewTypedArray(ARRAYBUFFERVIEW_UINT8, nBytes);
  if (array) {
    JsvArrayBufferIterator it;
    jsvArrayBufferIteratorNew(&it, array, 0);
    unsigned int i;
    for (i=0;i<(unsigned)nBytes;i++) {
      jsvArrayBufferIteratorSetByteValue(&it, (char)buf[i]);
      jsvArrayBufferIteratorNext(&it);
    }
    jsvArrayBufferIteratorFree(&it);
  }
  return array;
}
Example #2
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.map`, eg. `[].map.call(myArray, x=>x+1)`
 */
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 *array = jsvNewTypedArray(arrayBufferType, (JsVarInt)jsvGetArrayBufferLength(parent));
  if (!array) return 0;

  // now iterate
  JsvIterator it; // TODO: if we really are limited to ArrayBuffers, this could be an ArrayBufferIterator.
  jsvIteratorNew(&it, parent, JSIF_EVERY_ARRAY_ELEMENT);
  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);
      jsvUnLockMany(2,args);
      if (mapped) {
        jsvArrayBufferIteratorSetValue(&itdst, mapped);
        jsvUnLock(mapped);
      }
    }
    jsvUnLock(index);
    jsvIteratorNext(&it);
    jsvArrayBufferIteratorNext(&itdst);
  }
  jsvIteratorFree(&it);
  jsvArrayBufferIteratorFree(&itdst);

  return array;
}
Example #3
0
/*JSON{
  "type" : "constructor",
  "class" : "Waveform",
  "name" : "Waveform",
  "ifndef" : "SAVE_ON_FLASH",
  "generate" : "jswrap_waveform_constructor",
  "params" : [
    ["samples","int32","The number of samples"],
    ["options","JsVar","Optional options struct `{doubleBuffer:bool, bits : 8/16}` where: `doubleBuffer` is whether to allocate two buffers or not (default false), and bits is the amount of bits to use (default 8)."]
  ],
  "return" : ["JsVar","An Waveform object"]
}
Create a waveform class. This allows high speed input and output of waveforms. It has an internal variable called `buffer` (as well as `buffer2` when double-buffered - see `options` below) which contains the data to input/output.

When double-buffered, a 'buffer' event will be emitted each time a buffer is finished with (the argument is that buffer). When the recording stops, a 'finish' event will be emitted (with the first argument as the buffer).
 */
JsVar *jswrap_waveform_constructor(int samples, JsVar *options) {
  if (samples<=0) {
    jsExceptionHere(JSET_ERROR, "Samples must be greater than 0");
    return 0;
  }

  bool doubleBuffer = false;
  bool use16bit = false;
  if (jsvIsObject(options)) {
    doubleBuffer = jsvGetBoolAndUnLock(jsvObjectGetChild(options, "doubleBuffer", 0));

    int bits = (int)jsvGetIntegerAndUnLock(jsvObjectGetChild(options, "bits", 0));
    if (bits!=0 && bits!=8 && bits!=16) {
      jsExceptionHere(JSET_ERROR, "Invalid number of bits");
      return 0;
    } else if (bits==16) use16bit = true;

  } else if (!jsvIsUndefined(options)) {
    jsExceptionHere(JSET_ERROR, "Expecting options to be undefined or an Object, not %t", options);
  }

  JsVarDataArrayBufferViewType bufferType = use16bit ? ARRAYBUFFERVIEW_UINT16 : ARRAYBUFFERVIEW_UINT8;
  JsVar *arrayBuffer = jsvNewTypedArray(bufferType, samples);
  JsVar *arrayBuffer2 = 0;
  if (doubleBuffer) arrayBuffer2 = jsvNewTypedArray(bufferType, samples);
  JsVar *waveform = jspNewObject(0, "Waveform");


  if (!waveform || !arrayBuffer || (doubleBuffer && !arrayBuffer2)) {
    jsvUnLock3(waveform,arrayBuffer,arrayBuffer2); // out of memory
    return 0;
  }
  jsvObjectSetChildAndUnLock(waveform, "buffer", arrayBuffer);
  if (arrayBuffer2) jsvObjectSetChildAndUnLock(waveform, "buffer2", arrayBuffer2);

  return waveform;
}
Example #4
0
/*JSON{
  "type" : "method",
  "class" : "OneWire",
  "name" : "read",
  "generate" : "jswrap_onewire_read",
  "params" : [["count","JsVar","(optional) The amount of bytes to read"]],
  "return" : ["JsVar","The byte that was read, or a Uint8Array if count was specified and >=0"]
}
Read a byte
 */
JsVar *jswrap_onewire_read(JsVar *parent, JsVar *count) {
  Pin pin = onewire_getpin(parent);
  if (!jshIsPinValid(pin)) return 0;
  if (jsvIsNumeric(count)) {
    JsVarInt c = jsvGetInteger(count);
    JsVar *arr = jsvNewTypedArray(ARRAYBUFFERVIEW_UINT8, c);
    if (!arr) return 0;
    JsvArrayBufferIterator it;
    jsvArrayBufferIteratorNew(&it, arr, 0);
    while (c--) {
      jsvArrayBufferIteratorSetByteValue(&it, (char)OneWireRead(pin, 8));
      jsvArrayBufferIteratorNext(&it);
    }
    jsvArrayBufferIteratorFree(&it);
    return arr;
  } else {
    return jsvNewFromInteger(OneWireRead(pin, 8));
  }
}
Example #5
0
JsVar *jswrap_io_peek(JsVarInt addr, JsVarInt count, int wordSize) {
  if (count<=1) {
    return jsvNewFromLongInteger((long long)_jswrap_io_peek(addr, wordSize));
  } else {
    JsVarDataArrayBufferViewType aType;
    if (wordSize==1) aType=ARRAYBUFFERVIEW_UINT8;
    if (wordSize==2) aType=ARRAYBUFFERVIEW_UINT16;
    if (wordSize==4) aType=ARRAYBUFFERVIEW_UINT32;
    JsVar *arr = jsvNewTypedArray(aType, count);
    if (!arr) return 0;
    JsvArrayBufferIterator it;
    jsvArrayBufferIteratorNew(&it, arr, 0);
    while (jsvArrayBufferIteratorHasElement(&it)) {
      jsvArrayBufferIteratorSetIntegerValue(&it, (JsVarInt)_jswrap_io_peek(addr, wordSize));
      addr += wordSize;
      jsvArrayBufferIteratorNext(&it);
    }
    jsvArrayBufferIteratorFree(&it);
    return arr;
  }
}
Example #6
0
/**
 * Send data through SPI.
 * The data can be in a variety of formats including:
 * * `numeric` - A single byte is transmitted.
 * * `string` - Each character in the string is transmitted.
 * * `iterable` - An iterable object is transmitted.
 * \return the Received bytes (MISO).  This is byte array.
 */
JsVar *jswrap_spi_send(
    JsVar *parent,  //!< A description of the SPI device to send data through.
    JsVar *srcdata, //!< The data to send through SPI.
    Pin    nss_pin  //!< The pin to toggle low then high (CS)
  ) {
  // Debug
  // jsiConsolePrintf("jswrap_spi_send called: parent=%j, srcdata=%j, nss_pin=%p\n", parent, srcdata, nss_pin);
  NOT_USED(parent);
  IOEventFlags device = jsiGetDeviceFromClass(parent);

  jswrap_spi_send_data data;
  if (!jsspiGetSendFunction(parent, &data.spiSend, &data.spiSendData))
    return 0;

  JsVar *dst = 0;

  // we're sending and receiving
  if (DEVICE_IS_SPI(device)) jshSPISetReceive(device, true);

  // assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, false);

  // Now that we are setup, we can send the data.

  // Handle the data being a single byte value
  if (jsvIsNumeric(srcdata)) {
    int r = data.spiSend((unsigned char)jsvGetInteger(srcdata), &data.spiSendData);
    if (r<0) r = data.spiSend(-1, &data.spiSendData);
    dst = jsvNewFromInteger(r); // retrieve the byte (no send!)
  }
  // Handle the data being a string
  else if (jsvIsString(srcdata)) {
    dst = jsvNewFromEmptyString();
    JsvStringIterator it;
    jsvStringIteratorNew(&it, srcdata, 0);
    int incount = 0, outcount = 0;
    while (jsvStringIteratorHasChar(&it) && !jspIsInterrupted()) {
      unsigned char in = (unsigned char)jsvStringIteratorGetChar(&it);
      incount++;
      int out = data.spiSend(in, &data.spiSendData);
      if (out>=0) {
        outcount++;
        char outc = (char)out;
        jsvAppendStringBuf(dst, (char*)&outc, 1);
      }
      jsvStringIteratorNext(&it);
    }
    jsvStringIteratorFree(&it);
    // finally add the remaining bytes  (no send!)
    while (outcount < incount && !jspIsInterrupted()) {
      outcount++;
      unsigned char out = (unsigned char)data.spiSend(-1, &data.spiSendData);
      jsvAppendStringBuf(dst, (char*)&out, 1);
    }
  }
  // Handle the data being an iterable.
  else {
    int nBytes = jsvIterateCallbackCount(srcdata);
    dst = jsvNewTypedArray(ARRAYBUFFERVIEW_UINT8, nBytes);
    if (dst) {
      data.rxAmt = data.txAmt = 0;
      jsvArrayBufferIteratorNew(&data.it, dst, 0);
      // Write data
      jsvIterateCallback(srcdata, (void (*)(int,  void *))jswrap_spi_send_cb, &data);
      // Wait until SPI send is finished, and flush data
      while (data.rxAmt < data.txAmt && !jspIsInterrupted())
        jswrap_spi_send_cb(-1, &data);
      jsvArrayBufferIteratorFree(&data.it);
    }
  }

  // de-assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, true);
  return dst;
}
Example #7
0
JsVar *jswrap_spi_send(JsVar *parent, JsVar *srcdata, Pin nss_pin) {
  NOT_USED(parent);
  IOEventFlags device = jsiGetDeviceFromClass(parent);

  jswrap_spi_send_data data;
  if (!jsspiGetSendFunction(parent, &data.spiSend, &data.spiSendData))
    return 0;

  JsVar *dst = 0;

  // we're sending and receiving
  if (DEVICE_IS_SPI(device)) jshSPISetReceive(device, true);

  // assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, false);

  // send data
  if (jsvIsNumeric(srcdata)) {
    int r = data.spiSend((unsigned char)jsvGetInteger(srcdata), &data.spiSendData);
    if (r<0) r = data.spiSend(-1, &data.spiSendData);
    dst = jsvNewFromInteger(r); // retrieve the byte (no send!)
  } else if (jsvIsString(srcdata)) {
    dst = jsvNewFromEmptyString();
    JsvStringIterator it;
    jsvStringIteratorNew(&it, srcdata, 0);
    int incount = 0, outcount = 0;
    while (jsvStringIteratorHasChar(&it) && !jspIsInterrupted()) {
      unsigned char in = (unsigned char)jsvStringIteratorGetChar(&it);
      incount++;
      int out = data.spiSend(in, &data.spiSendData);
      if (out>=0) {
        outcount++;
        char outc = (char)out;
        jsvAppendStringBuf(dst, (char*)&outc, 1);
      }
      jsvStringIteratorNext(&it);
    }
    jsvStringIteratorFree(&it);
    // finally add the remaining bytes  (no send!)
    while (outcount < incount && !jspIsInterrupted()) {
      outcount++;
      unsigned char out = (unsigned char)data.spiSend(-1, &data.spiSendData);
      jsvAppendStringBuf(dst, (char*)&out, 1);
    }
  } else {
    int nBytes = jsvIterateCallbackCount(srcdata);
    dst = jsvNewTypedArray(ARRAYBUFFERVIEW_UINT8, nBytes);
    if (dst) {
      data.rxAmt = data.txAmt = 0;
      jsvArrayBufferIteratorNew(&data.it, dst, 0);
      // Write data
      jsvIterateCallback(srcdata, (void (*)(int,  void *))jswrap_spi_send_cb, &data);
      // Wait until SPI send is finished, and flush data
      while (data.rxAmt < data.txAmt && !jspIsInterrupted())
        jswrap_spi_send_cb(-1, &data);
      jsvArrayBufferIteratorFree(&data.it);
    }
  }

  // de-assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, true);
  return dst;
}