Exemple #1
0
/*JSON{
  "type" : "function",
  "name" : "setBusyIndicator",
  "generate" : "jswrap_interface_setBusyIndicator",
  "params" : [
    ["pin","JsVar",""]
  ]
}
When Espruino is busy, set the pin specified here high. Set this to undefined to disable the feature.
*/
void jswrap_interface_setBusyIndicator(JsVar *pinVar) {
  Pin oldPin = pinBusyIndicator;
  pinBusyIndicator = jshGetPinFromVar(pinVar);
  // we should be busy right now anyway, so set stuff up right
  if (pinBusyIndicator!=oldPin) {
    if (oldPin!=NC) jshPinOutput(oldPin, 0);
    if (pinBusyIndicator!=NC) jshPinOutput(pinBusyIndicator, 1);
  }
}
Exemple #2
0
/*JSON{ "type":"function", "name" : "digitalWrite",
         "description" : ["Set the digital value of the given pin",
                          "If pin is an array of pins, eg. ```[A2,A1,A0]``` the value will be treated as an integer where the first array element is the MSB" ],
         "generate" : "jswrap_io_digitalWrite",
         "params" : [ [ "pin", "JsVar", "The pin to use"],
                      [ "value", "int", "Whether to pulse high (true) or low (false)"] ]
}*/
void jswrap_io_digitalWrite(JsVar *pinVar, JsVarInt value) {
  if (jsvIsArray(pinVar)) {
    JsVarRef pinName = pinVar->lastChild; // NOTE: start at end and work back!
    while (pinName) {
      JsVar *pinNamePtr = jsvLock(pinName);
      JsVar *pinPtr = jsvSkipName(pinNamePtr);
      jshPinOutput(jshGetPinFromVar(pinPtr), value&1);
      jsvUnLock(pinPtr);
      pinName = pinNamePtr->prevSibling;
      jsvUnLock(pinNamePtr);
      value = value>>1; // next bit down
    }
  } else {
Exemple #3
0
/**
 * \brief
 */
JsVar *jswrap_pin_getInfo(
    JsVar *parent //!< The class instance representing the pin.
  ) {
  Pin pin = jshGetPinFromVar(parent);
  if (!jshIsPinValid(pin)) return 0;
  const JshPinInfo *inf = &pinInfo[pin];
  JsVar *obj = jsvNewWithFlags(JSV_OBJECT);
  if (!obj) return 0;

  char buf[2];
  buf[0] = (char)('A'+(inf->port-JSH_PORTA));
  buf[1] = 0;
  jsvObjectSetChildAndUnLock(obj, "port", jsvNewFromString(buf));
  jsvObjectSetChildAndUnLock(obj, "num", jsvNewFromInteger(inf->pin-JSH_PIN0));
  // ADC
  if (inf->analog) {
    JsVar *an = jsvNewWithFlags(JSV_OBJECT);
    if (an) {
      JsVar *arr = jsvNewWithFlags(JSV_ARRAY);
      if (arr) {
        int i;
        for (i=0;i<ADC_COUNT;i++)
          if (inf->analog&(JSH_ANALOG1<<i))
            jsvArrayPushAndUnLock(arr, jsvNewFromInteger(1+i));
        jsvObjectSetChildAndUnLock(an, "ADCs", arr);
      }
      jsvObjectSetChildAndUnLock(obj, "channel", jsvNewFromInteger(inf->analog & JSH_MASK_ANALOG_CH));
    }
  }
  JsVar *funcs = jsvNewWithFlags(JSV_OBJECT);
  if (funcs) {
    int i;
    for (i=0;i<JSH_PININFO_FUNCTIONS;i++) {
      if (inf->functions[i]) {
        JsVar *func = jsvNewWithFlags(JSV_OBJECT);
        if (func) {
          char buf[16];
          jshPinFunctionToString(inf->functions[i], JSPFTS_TYPE, buf, sizeof(buf));
          jsvObjectSetChildAndUnLock(func, "type", jsvNewFromString(buf));
          jsvObjectSetChildAndUnLock(func, "af", jsvNewFromInteger(inf->functions[i] & JSH_MASK_AF));

          jshPinFunctionToString(inf->functions[i], JSPFTS_DEVICE|JSPFTS_DEVICE_NUMBER, buf, sizeof(buf));
          jsvObjectSetChildAndUnLock(funcs, buf, func);
        }
      }
    }
    jsvObjectSetChildAndUnLock(obj, "functions", funcs);
  }

  return obj;
}
Exemple #4
0
/*JSON{
  "type"     : "function",
  "name"     : "digitalWrite",
  "generate" : "jswrap_io_digitalWrite",
  "params"   : [
    ["pin",   "JsVar","The pin to use"],
    ["value", "int","Whether to pulse high (true) or low (false)"]
  ]
}
Set the digital value of the given pin.

 **Note:** if you didn't call `pinMode` beforehand then this function will also reset pin's state to `"output"`

If pin argument is an array of pins (eg. `[A2,A1,A0]`) the value argument will be treated
as an array of bits where the last array element is the least significant bit.

In this case, pin values are set least significant bit first (from the right-hand side
of the array of pins). This means you can use the same pin multiple times, for
example `digitalWrite([A1,A1,A0,A0],0b0101)` would pulse A0 followed by A1.

If the pin argument is an object with a `write` method, the `write` method will
be called with the value passed through.
*/
void jswrap_io_digitalWrite(
    JsVar *pinVar, //!< A pin or pins.
    JsVarInt value //!< The value of the output.
  ) {
  // Handle the case where it is an array of pins.
  if (jsvIsArray(pinVar)) {
    JsVarRef pinName = jsvGetLastChild(pinVar); // NOTE: start at end and work back!
    while (pinName) {
      JsVar *pinNamePtr = jsvLock(pinName);
      JsVar *pinPtr = jsvSkipName(pinNamePtr);
      jshPinOutput(jshGetPinFromVar(pinPtr), value&1);
      jsvUnLock(pinPtr);
      pinName = jsvGetPrevSibling(pinNamePtr);
      jsvUnLock(pinNamePtr);
      value = value>>1; // next bit down
    }
  } else if (jsvIsObject(pinVar)) {
Exemple #5
0
/*JSON{
  "type" : "method",
  "class" : "SPI",
  "name" : "write",
  "generate" : "jswrap_spi_write",
  "params" : [
    ["data","JsVarArray",["One or more items to write. May be ints, strings, arrays, or objects of the form `{data: ..., count:#}`.","If the last argument is a pin, it is taken to be the NSS pin"]]
  ]
}
Write a character or array of characters to SPI - without reading the result back.

For maximum speeds, please pass either Strings or Typed Arrays as arguments.
 */
void jswrap_spi_write(
    JsVar *parent, //!<
    JsVar *args    //!<
  ) {
  NOT_USED(parent);
  IOEventFlags device = jsiGetDeviceFromClass(parent);

  spi_sender spiSend;
  spi_sender_data spiSendData;
  if (!jsspiGetSendFunction(parent, &spiSend, &spiSendData))
    return;

  Pin nss_pin = PIN_UNDEFINED;
  // If the last value is a pin, use it as the NSS pin
  JsVarInt len = jsvGetArrayLength(args);
  if (len > 0) {
    JsVar *last = jsvGetArrayItem(args, len-1); // look at the last value
    if (jsvIsPin(last)) {
      nss_pin = jshGetPinFromVar(last);    
      jsvUnLock(jsvArrayPop(args));
    }
    jsvUnLock(last);
  }

  // we're only sending (no receive)
  if (DEVICE_IS_SPI(device)) jshSPISetReceive(device, false);

  // assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, false);
  // Write data
  jsvIterateCallback(args, (void (*)(int,  void *))spiSend, &spiSendData);
  // Wait until SPI send is finished, and flush data
  if (DEVICE_IS_SPI(device))
    jshSPIWait(device);
  // de-assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, true);
}
Exemple #6
0
/*JSON{
  "type"     : "method",
  "class"    : "Pin",
  "name"     : "getMode",
  "generate" : "jswrap_pin_getMode",
  "return"   : ["JsVar", "The pin mode, as a string"]
}
Return the current mode of the given pin. See `pinMode` for more information.
 */
JsVar *jswrap_pin_getMode(JsVar *parent) {
  return jswrap_io_getPinMode(jshGetPinFromVar(parent));  
}
Exemple #7
0
                      [ "value", "int", "Whether to pulse high (true) or low (false)"] ]
}*/
void jswrap_io_digitalWrite(JsVar *pinVar, JsVarInt value) {
  if (jsvIsArray(pinVar)) {
    JsVarRef pinName = pinVar->lastChild; // NOTE: start at end and work back!
    while (pinName) {
      JsVar *pinNamePtr = jsvLock(pinName);
      JsVar *pinPtr = jsvSkipName(pinNamePtr);
      jshPinOutput(jshGetPinFromVar(pinPtr), value&1);
      jsvUnLock(pinPtr);
      pinName = pinNamePtr->prevSibling;
      jsvUnLock(pinNamePtr);
      value = value>>1; // next bit down
    }
  } else {
    Pin pin = jshGetPinFromVar(pinVar);
    jshPinOutput(pin, value!=0);
  }
}


/*JSON{ "type":"function", "name" : "digitalRead",
         "description" : ["Get the digital value of the given pin",
                          "If pin is an array of pins, eg. ```[A2,A1,A0]``` the value will be treated as an integer where the first array element is the MSB" ],
         "generate" : "jswrap_io_digitalRead",
         "params" : [ [ "pin", "JsVar", "The pin to use"] ],
         "return" : ["int", "The digital Value of the Pin"]
}*/
JsVarInt jswrap_io_digitalRead(JsVar *pinVar) {
  if (jsvIsArray(pinVar)) {
    int pins = 0;
Exemple #8
0
/*JSON{ "type":"method", "class": "Pin", "name" : "writeAtTime", "ifndef" : "SAVE_ON_FLASH",
         "description" : "Sets the output state of the pin to the parameter given at the specified time",
         "generate" : "jswrap_pin_writeAtTime",
         "params" : [ [ "value", "bool", "Whether to set output high (true/1) or low (false/0)"],
                      ["time", "float", "Time at which to write"] ]
}*/
void jswrap_pin_writeAtTime(JsVar *parent, bool value, JsVarFloat time) {
  Pin pin = jshGetPinFromVar(parent);
  JsSysTime sTime = jshGetTimeFromMilliseconds(time*1000);
  jstPinOutputAtTime(sTime, &pin, 1, value);
}
Exemple #9
0
/*JSON{ "type":"method", "class": "Pin", "name" : "write",
         "description" : "Sets the output state of the pin to the parameter given",
         "generate" : "jswrap_pin_write",
         "params" : [ [ "value", "bool", "Whether to set output high (true/1) or low (false/0)"] ]
}*/
void jswrap_pin_write(JsVar *parent, bool value) {
  Pin pin = jshGetPinFromVar(parent);
  jshPinOutput(pin, value);
}
Exemple #10
0
/*JSON{ "type":"method", "class": "Pin", "name" : "reset",
         "description" : "Sets the output state of the pin to a 0",
         "generate" : "jswrap_pin_reset"
}*/
void jswrap_pin_reset(JsVar *parent) {
  Pin pin = jshGetPinFromVar(parent);
  jshPinOutput(pin, 0);
}
Exemple #11
0
/*JSON{ "type":"method", "class": "Pin", "name" : "read",
         "description" : "Returns the input state of the pin as a boolean",
         "generate" : "jswrap_pin_read",
         "return" : ["bool", "Whether pin is a logical 1 or 0"]
}*/
bool jswrap_pin_read(JsVar *parent) {
  Pin pin = jshGetPinFromVar(parent);
  return jshPinInput(pin);
}
Exemple #12
0
/*JSON{
  "type"     : "constructor",
  "class"    : "Pin",
  "name"     : "Pin",
  "generate" : "jswrap_pin_constructor",
  "params"   : [
    ["value", "JsVar", "A value to be converted to a pin. Can be a number, pin, or String."]
  ],
  "return"   : ["JsVar","A Pin object"]
}
Creates a pin from the given argument (or returns undefined if no argument)
*/
JsVar *jswrap_pin_constructor(JsVar *val) {
  Pin pin = jshGetPinFromVar(val);
  if (!jshIsPinValid(pin)) return 0;
  return jsvNewFromPin(pin);
}
Exemple #13
0
/*JSON{
  "type"     : "method",
  "class"    : "Pin",
  "name"     : "mode",
  "generate" : "jswrap_pin_mode",
  "params" : [
    ["mode", "JsVar", "The mode - a string that is either 'analog', 'input', 'input_pullup', 'input_pulldown', 'output', 'opendrain', 'af_output' or 'af_opendrain'. Do not include this argument if you want to revert to automatic pin mode setting."]
  ]
}
Set the mode of the given pin. See [`pinMode`](#l__global_pinMode) for more information on pin modes.
 */
void jswrap_pin_mode(JsVar *parent, JsVar *mode) {
  jswrap_io_pinMode(jshGetPinFromVar(parent), mode);  
}
Exemple #14
0
/** Write the pin name to a string. String must have at least 8 characters (to be safe) */
void jshGetPinString(char *result, Pin pin) {
  result[0] = 0; // just in case
#ifdef PIN_NAMES_DIRECT
  if (jshIsPinValid(pin)) {
    result[0]='A'+pinInfo[pin].port-JSH_PORTA;
    itostr(pinInfo[pin].pin-JSH_PIN0,&result[1],10);
#else
  if (
#if JSH_PORTA_OFFSET!=0
      pin>=JSH_PORTA_OFFSET &&
#endif
      pin<JSH_PORTA_OFFSET+JSH_PORTA_COUNT) {
    result[0]='A';
    itostr(pin-JSH_PORTA_OFFSET,&result[1],10);
  } else if (pin>=JSH_PORTB_OFFSET && pin<JSH_PORTB_OFFSET+JSH_PORTB_COUNT) {
    result[0]='B';
    itostr(pin-JSH_PORTB_OFFSET,&result[1],10);
  } else if (pin>=JSH_PORTC_OFFSET && pin<JSH_PORTC_OFFSET+JSH_PORTC_COUNT) {
    result[0]='C';
    itostr(pin-JSH_PORTC_OFFSET,&result[1],10);
  } else if (pin>=JSH_PORTD_OFFSET && pin<JSH_PORTD_OFFSET+JSH_PORTD_COUNT) {
    result[0]='D';
    itostr(pin-JSH_PORTD_OFFSET,&result[1],10);
#if JSH_PORTE_OFFSET!=-1
  } else if (pin>=JSH_PORTE_OFFSET && pin<JSH_PORTE_OFFSET+JSH_PORTE_COUNT) {
    result[0]='E';
    itostr(pin-JSH_PORTE_OFFSET,&result[1],10);
#endif
#if JSH_PORTF_OFFSET!=-1
  } else if (pin>=JSH_PORTF_OFFSET && pin<JSH_PORTF_OFFSET+JSH_PORTF_COUNT) {
    result[0]='F';
    itostr(pin-JSH_PORTF_OFFSET,&result[1],10);
#endif
#if JSH_PORTG_OFFSET!=-1
  } else if (pin>=JSH_PORTG_OFFSET && pin<JSH_PORTG_OFFSET+JSH_PORTG_COUNT) {
    result[0]='G';
    itostr(pin-JSH_PORTG_OFFSET,&result[1],10);
#endif
#if JSH_PORTH_OFFSET!=-1
  } else if (pin>=JSH_PORTH_OFFSET && pin<JSH_PORTH_OFFSET+JSH_PORTH_COUNT) {
    result[0]='H';
    itostr(pin-JSH_PORTH_OFFSET,&result[1],10);
#endif
#endif
  } else {
    strncpy(result, "UNKNOWN", 8);
  }
}

/// Given a var, convert it to a pin ID (or -1 if it doesn't exist). safe for undefined!
Pin jshGetPinFromVar(JsVar *pinv) {
  if (jsvIsString(pinv) && pinv->varData.str[5]==0/*should never be more than 4 chars!*/) {
    return jshGetPinFromString(&pinv->varData.str[0]);
  } else if (jsvIsInt(pinv) /* This also tests for the Pin datatype */) {
    return (Pin)jsvGetInteger(pinv);
  } else return PIN_UNDEFINED;
}

Pin jshGetPinFromVarAndUnLock(JsVar *pinv) {
  Pin pin = jshGetPinFromVar(pinv);
  jsvUnLock(pinv);
  return pin;
}
/*JSON{ "type":"function", "name" : "setSleepIndicator",
         "description" : "When Espruino is asleep, set the pin specified here high. Set this to undefined to disable the feature.",
         "generate" : "jswrap_interface_setSleepIndicator",
         "params" : [ [ "pin", "JsVar", ""] ]
}*/
void jswrap_interface_setSleepIndicator(JsVar *pinVar) {
  pinSleepIndicator = jshGetPinFromVar(pinVar);
}
/** Call a function with the given argument specifiers */
JsVar *jsnCallFunction(void *function, JsnArgumentType argumentSpecifier, JsVar *thisParam, JsVar **paramData, int paramCount) {
  JsnArgumentType returnType = (JsnArgumentType)(argumentSpecifier&JSWAT_MASK);
  JsVar *argsArray = 0; // if JSWAT_ARGUMENT_ARRAY is ever used (note it'll only ever be used once)
  int paramNumber = 0; // how many parameters we have
  int argCount = 0;
  size_t argData[MAX_ARGS];
#ifndef ARM // cdecl on x86 puts FP args elsewhere!
  int doubleCount = 0;
  JsVarFloat doubleData[MAX_ARGS];
#endif

  // prepend the 'this' link if we need one
  if (argumentSpecifier&JSWAT_THIS_ARG)
    argData[argCount++] = (size_t)thisParam;
  argumentSpecifier = (argumentSpecifier & JSWAT_ARGUMENTS_MASK) >> JSWAT_BITS;


  // run through all arguments
  while (argumentSpecifier & JSWAT_MASK) {
    // Get the parameter data
    JsVar *param = (paramNumber<paramCount) ? paramData[paramNumber] : (JsVar *)0;
    paramNumber++;
    // try and pack it:
    JsnArgumentType argType = (JsnArgumentType)(argumentSpecifier&JSWAT_MASK);

#ifdef ARM
    if (JSWAT_IS_64BIT(argType))
      argCount = (argCount+1)&~1;
#endif

    if (argCount > MAX_ARGS - (JSWAT_IS_64BIT(argType)?2:1)) {
      jsError("INTERNAL: too many arguments for jsnCallFunction");
    }

    switch (argType) {
      case JSWAT_JSVAR: { // standard variable
        argData[argCount++] = (size_t)param;
        break;
      }
      case JSWAT_ARGUMENT_ARRAY: { // a JsVar array containing all subsequent arguments
        argsArray = jsvNewWithFlags(JSV_ARRAY);
        if (argsArray) {
          // push everything into the array
          while (paramNumber<=paramCount) {
            jsvArrayPush(argsArray, param);
            param = (paramNumber<paramCount) ? paramData[paramNumber] : 0;
            paramNumber++;
          }
        }
        // push the array
        argData[argCount++] = (size_t)argsArray;
        break;
      }
      case JSWAT_BOOL: // boolean
        argData[argCount++] = jsvGetBool(param);
        break;
      case JSWAT_INT32: // 32 bit int
        argData[argCount++] = (uint32_t)jsvGetInteger(param);
        break;
      case JSWAT_PIN: // 16 bit int
        argData[argCount++] = (uint32_t)jshGetPinFromVar(param);
        break;
      case JSWAT_JSVARFLOAT: { // 64 bit float
        JsVarFloat f = jsvGetFloat(param);
#ifdef ARM
        uint64_t i = *(uint64_t*)&f;
#if __WORDSIZE == 64
        argData[argCount++] = (size_t)i;
#else
        argData[argCount++] = (size_t)((i) & 0xFFFFFFFF);
        argData[argCount++] = (size_t)((i>>32) & 0xFFFFFFFF);
#endif
#else
//		  jsiConsolePrintf("doubleData, %d, %d\n", doubleCount, (int)f);
        doubleData[doubleCount++] = f;
#endif
        break;
      }
      default:
        assert(0);
        break;
    }
    // on to next!
    argumentSpecifier >>= JSWAT_BITS;
  }

  uint64_t result;

  // When args<=4 on ARM, everything is passed in registers (so we try and do this case first)
  if (argCount<=4) {
#ifndef ARM
    assert(doubleCount<=4);
    if (doubleCount) {
      if (returnType==JSWAT_JSVARFLOAT) {
        // On x86, doubles are returned in a floating point unit register
        JsVarFloat f = ((JsVarFloat (*)(size_t,size_t,size_t,size_t,JsVarFloat,JsVarFloat,JsVarFloat,JsVarFloat))function)(argData[0],argData[1],argData[2],argData[3],doubleData[0],doubleData[1],doubleData[2],doubleData[3]);
        result = *(uint64_t*)&f;
      } else {
		  // HERE
//		  jsiConsolePrintf("callFunction: %d, %d, %d\n", JSWAT_IS_64BIT(returnType), function == jswrap_interface_setInterval, (int)doubleData[0]);
//		  if (function == jswrap_interface_setInterval) {
//			  result = (uint32_t)jswrap_interface_setInterval((JsVar *)argData[0], doubleData[0]);
//		  }
//		  else

		if (JSWAT_IS_64BIT(returnType))
          result = ((uint64_t (*)(size_t,size_t,size_t,size_t,JsVarFloat,JsVarFloat,JsVarFloat,JsVarFloat))function)(argData[0],argData[1],argData[2],argData[3],doubleData[0],doubleData[1],doubleData[2],doubleData[3]);
		else // HERE
			if (argCount<=2) // ESP8266 fix
				result = ((uint32_t (*)(size_t,size_t,JsVarFloat,JsVarFloat))function)(argData[0],argData[1],doubleData[0],doubleData[1]);
			else
				result = ((uint32_t (*)(size_t,size_t,size_t,size_t,JsVarFloat,JsVarFloat,JsVarFloat,JsVarFloat))function)(argData[0],argData[1],argData[2],argData[3],doubleData[0],doubleData[1],doubleData[2],doubleData[3]);
      }
    } else if (returnType==JSWAT_JSVARFLOAT) {
      // On x86, doubles are returned in a floating point unit register
      JsVarFloat f = ((JsVarFloat (*)(size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3]);
      result = *(uint64_t*)&f;
    } else
#endif
    {
      if (JSWAT_IS_64BIT(returnType))
        result = ((uint64_t (*)(size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3]);
      else
        result = ((uint32_t (*)(size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3]);
    }
  } else { // else it gets tricky...
#ifndef ARM
    assert(doubleCount==0);
    if (returnType==JSWAT_JSVARFLOAT) {
      // On x86, doubles are returned in a floating point unit register
      JsVarFloat f = ((JsVarFloat (*)(size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3],argData[4],argData[5],argData[6],argData[7],argData[8],argData[9],argData[10],argData[11]);
      result = *(uint64_t*)&f;
    } else
#endif
    {
      if (JSWAT_IS_64BIT(returnType))
        result = ((uint64_t (*)(size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3],argData[4],argData[5],argData[6],argData[7],argData[8],argData[9],argData[10],argData[11]);
      else
        result = ((uint32_t (*)(size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3],argData[4],argData[5],argData[6],argData[7],argData[8],argData[9],argData[10],argData[11]);
    }
  }

  jsvUnLock(argsArray);

  switch (returnType) {
    case JSWAT_VOID:
      return 0;
    case JSWAT_JSVAR: // standard variable
    case JSWAT_ARGUMENT_ARRAY: // a JsVar array containing all subsequent arguments
      return (JsVar*)(size_t)result;
    case JSWAT_BOOL: // boolean
      return jsvNewFromBool(result!=0);
    case JSWAT_PIN:
      return jsvNewFromPin((Pin)result);
    case JSWAT_INT32: // 32 bit int
      return jsvNewFromInteger((JsVarInt)result);
    case JSWAT_JSVARFLOAT: // 64 bit float
      return jsvNewFromFloat(*(JsVarFloat*)&result);
    default:
      assert(0);
      return 0;
  }
}
Exemple #17
0
/** Call a function with the given argument specifiers */
JsVar *jsnCallFunction(void *function, JsnArgumentType argumentSpecifier, JsVar *thisParam, JsVar **paramData, int paramCount) {
  /*if(paramCount == 3) {
      jsiConsolePrintf("param[1] = %d\n",jsvGetInteger(paramData[1]));
      jsiConsolePrintf("param[2] = %d\n",jsvGetInteger(paramData[2]));
      jsiConsolePrintf("argType = %d\n",argumentSpecifier);
  }*/
  JsnArgumentType returnType = (JsnArgumentType)(argumentSpecifier&JSWAT_MASK);
  JsVar *argsArray = 0; // if JSWAT_ARGUMENT_ARRAY is ever used (note it'll only ever be used once)
  int paramNumber = 0; // how many parameters we have
  int argCount = 0;
  size_t argData[MAX_ARGS];
#ifndef ARM // cdecl on x86 puts FP args elsewhere!
  int doubleCount = 0;
  JsVarFloat doubleData[MAX_ARGS];
#endif

  // prepend the 'this' link if we need one
  if (argumentSpecifier&JSWAT_THIS_ARG){
	  //jsiConsolePrintf("this var\n");
	  argData[argCount++] = (size_t)thisParam;
  }
  argumentSpecifier = (argumentSpecifier & JSWAT_ARGUMENTS_MASK) >> JSWAT_BITS;

  //jsiConsolePrintf("out while : %d\n",argCount);
  // run through all arguments
  while (argumentSpecifier & JSWAT_MASK) {
    // Get the parameter data
    JsVar *param = (paramNumber<paramCount) ? paramData[paramNumber] : (JsVar *)0;
    paramNumber++;
    // try and pack it:
    JsnArgumentType argType = (JsnArgumentType)(argumentSpecifier&JSWAT_MASK);

#ifdef ARM
    if (JSWAT_IS_64BIT(argType)){
      //jsiConsolePrintf("64 bit\n");
      argCount = (argCount+1)&~1;
    }
#endif

    if (argCount > MAX_ARGS - (JSWAT_IS_64BIT(argType)?2:1)) {
      jsError("INTERNAL: too many arguments for jsnCallFunction");
    }


    //jsiConsolePrintf("in while : %d\n",argCount);
    switch (argType) {
      case JSWAT_JSVAR: { // standard variable

        argData[argCount++] = (size_t)param;
        //jsiConsolePrintf("111  : %d\n",argCount - 1);
        break;
      }
      case JSWAT_ARGUMENT_ARRAY: { // a JsVar array containing all subsequent arguments
        argsArray = jsvNewWithFlags(JSV_ARRAY);
        if (argsArray) {
          // push everything into the array
          while (paramNumber<=paramCount) {
            jsvArrayPush(argsArray, param);
            param = (paramNumber<paramCount) ? paramData[paramNumber] : 0;
            paramNumber++;
          }
        }
        // push the array
        argData[argCount++] = (size_t)argsArray;
        //jsiConsolePrintf("222  : %d\n",argCount - 1);
        break;
      }
      case JSWAT_BOOL:{ // boolean
        argData[argCount++] = jsvGetBool(param);
        //jsiConsolePrintf("666  : %d\n",argCount - 1);
        break;
      }
      case JSWAT_INT32:{ // 32 bit int
        argData[argCount++] = (uint32_t)jsvGetInteger(param);
        //jsiConsolePrintf("333  : %d\n",argCount - 1);
        break;
      }
      case JSWAT_PIN:{ // 16 bit int
        argData[argCount++] = (uint32_t)jshGetPinFromVar(param);
        //jsiConsolePrintf("444  : %d\n",argCount - 1);
        break;
      }
      case JSWAT_JSVARFLOAT: { // 64 bit float
    	  //jsiConsolePrintf("555\n");
        JsVarFloat f = jsvGetFloat(param);
        //jsiConsolePrintf("params[%d] = %f\n",argCount - 1,f);
#ifdef ARM
        uint64_t i = *(uint64_t*)&f;
        //jsiConsolePrintf("define ARM\n");
#if __WORDSIZE == 64
        argData[argCount++] = (size_t)i;
        //jsiConsolePrintf("1 - params[%d] = %f\n",argCount - 1,argData[argCount - 1]);
#else
        argData[argCount++] = (size_t)((i) & 0xFFFFFFFF);
        //jsiConsolePrintf("2 - params[%d] = %d\n",argCount - 1,argData[argCount - 1]);

        argData[argCount++] = (size_t)((i>>32) & 0xFFFFFFFF);
        //jsiConsolePrintf("3 - params[%d] = %d\n",argCount - 1,argData[argCount - 1]);

#endif
#else
        doubleData[doubleCount++] = f;
#endif
        break;
      }
      default:
        assert(0);
        break;
    }
    // on to next!
    argumentSpecifier >>= JSWAT_BITS;
  }  //end for while (argumentSpecifier & JSWAT_MASK)
  //jsiConsolePrintf("native Count = %d\n",argCount - 1);
  /*for(int i = 0 ; i < argCount; i ++ ){
	  jsiConsolePrintf("argData[%d] = %d\n",i,argData[i]);
  }*/
  uint64_t result;
  //jsiConsolePrintf();
  // When args<=4 on ARM, everything is passed in registers (so we try and do this case first)
  if (argCount<=4) {
#ifndef ARM
    assert(doubleCount<=4);
    if (doubleCount) {
      if (returnType==JSWAT_JSVARFLOAT) {
        // On x86, doubles are returned in a floating point unit register
    	  //jsiConsolePrintf("111\n");
        JsVarFloat f = ((JsVarFloat (*)(size_t,size_t,size_t,size_t,JsVarFloat,JsVarFloat,JsVarFloat,JsVarFloat))function)(argData[0],argData[1],argData[2],argData[3],doubleData[0],doubleData[1],doubleData[2],doubleData[3]);
        result = *(uint64_t*)&f;
      } else {
    	  //jsiConsolePrintf("222\n");
        if (JSWAT_IS_64BIT(returnType)){
          result = ((uint64_t (*)(size_t,size_t,size_t,size_t,JsVarFloat,JsVarFloat,JsVarFloat,JsVarFloat))function)(argData[0],argData[1],argData[2],argData[3],doubleData[0],doubleData[1],doubleData[2],doubleData[3]);
          //jsiConsolePrintf("333\n");
        } else
          result = ((uint32_t (*)(size_t,size_t,size_t,size_t,JsVarFloat,JsVarFloat,JsVarFloat,JsVarFloat))function)(argData[0],argData[1],argData[2],argData[3],doubleData[0],doubleData[1],doubleData[2],doubleData[3]);
      }
    } else if (returnType==JSWAT_JSVARFLOAT) {
      // On x86, doubles are returned in a floating point unit register
      JsVarFloat f = ((JsVarFloat (*)(size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3]);
      result = *(uint64_t*)&f;
    } else
#endif
    {
      if (JSWAT_IS_64BIT(returnType))
        result = ((uint64_t (*)(size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3]);
      else{
    	  //jsiConsolePrintf("real exec!!!\n");
        result = ((uint32_t (*)(size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3]);
      }
     }
  } else { // else it gets tricky...
#ifndef ARM
    assert(doubleCount==0);
    if (returnType==JSWAT_JSVARFLOAT) {
      // On x86, doubles are returned in a floating point unit register
      JsVarFloat f = ((JsVarFloat (*)(size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3],argData[4],argData[5],argData[6],argData[7],argData[8],argData[9],argData[10],argData[11]);
      result = *(uint64_t*)&f;
    } else
#endif
    {
      if (JSWAT_IS_64BIT(returnType))
        result = ((uint64_t (*)(size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3],argData[4],argData[5],argData[6],argData[7],argData[8],argData[9],argData[10],argData[11]);
      else
        result = ((uint32_t (*)(size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3],argData[4],argData[5],argData[6],argData[7],argData[8],argData[9],argData[10],argData[11]);
    }
  }

  jsvUnLock(argsArray);
  //jsiConsolePrint("okok\n");
  switch (returnType) {
    case JSWAT_VOID:
      return 0;
    case JSWAT_JSVAR: // standard variable
    case JSWAT_ARGUMENT_ARRAY: // a JsVar array containing all subsequent arguments
      return (JsVar*)(size_t)result;
    case JSWAT_BOOL: // boolean
      return jsvNewFromBool(result!=0);
    case JSWAT_PIN:
      return jsvNewFromPin((Pin)result);
    case JSWAT_INT32: // 32 bit int
      return jsvNewFromInteger((JsVarInt)result);
    case JSWAT_JSVARFLOAT: // 64 bit float
      return jsvNewFromFloat(*(JsVarFloat*)&result);
    default:
      assert(0);
      return 0;
  }
}
Exemple #18
0
/** Call a function with the given argument specifiers */
JsVar *jsnCallFunction(void *function, JsnArgumentType argumentSpecifier, JsVar *thisParam, JsVar **paramData, int paramCount) {
#ifndef SAVE_ON_FLASH
  // Handle common call types quickly:
  // ------- void(void)
  if (argumentSpecifier==JSWAT_VOID) {
    ((void (*)())function)();
    return 0;
  }
  // ------- JsVar*(void)
  if (argumentSpecifier==JSWAT_JSVAR) {
    return ((JsVar *(*)())function)();
  }
  // ------- void('this')
  if (argumentSpecifier==(JSWAT_VOID | JSWAT_THIS_ARG)) {
    ((void (*)(JsVar *))function)(thisParam);
    return 0;
  }
#endif
  // Now do it the hard way...

  JsnArgumentType returnType = (JsnArgumentType)(argumentSpecifier&JSWAT_MASK);
  JsVar *argsArray = 0; // if JSWAT_ARGUMENT_ARRAY is ever used (note it'll only ever be used once)
  int paramNumber = 0; // how many parameters we have
  int argCount = 0;
  size_t argData[MAX_ARGS];
#ifdef USE_SEPARATE_DOUBLES
  int doubleCount = 0;
  JsVarFloat doubleData[MAX_ARGS];
#endif

  // prepend the 'this' link if we need one
  if (argumentSpecifier&JSWAT_THIS_ARG)
    argData[argCount++] = (size_t)thisParam;
  argumentSpecifier = (argumentSpecifier & JSWAT_ARGUMENTS_MASK) >> JSWAT_BITS;

#ifdef USE_ARG_REORDERING
  size_t alignedLongsAfter = 0;
#endif


  // run through all arguments
  while (argumentSpecifier & JSWAT_MASK) {
    // Get the parameter data
    JsVar *param = (paramNumber<paramCount) ? paramData[paramNumber] : (JsVar *)0;
    paramNumber++;
    // try and pack it:
    JsnArgumentType argType = (JsnArgumentType)(argumentSpecifier&JSWAT_MASK);

#ifdef USE_ARG_REORDERING
    if (!JSWAT_IS_64BIT(argType) && !(argCount&1)) {
      argCount += alignedLongsAfter*2;
      alignedLongsAfter = 0;
    }
#endif

    if (argCount > MAX_ARGS - (JSWAT_IS_64BIT(argType)?2:1)) {
      // TODO: can we ever hit this because of JsnArgumentType's restrictions?
      jsError("INTERNAL: too many arguments for jsnCallFunction");
    }

    switch (argType) {
    case JSWAT_JSVAR: { // standard variable
      argData[argCount++] = (size_t)param;
      break;
    }
    case JSWAT_ARGUMENT_ARRAY: { // a JsVar array containing all subsequent arguments
      argsArray = jsvNewEmptyArray();
      if (argsArray) {
        // push everything into the array
        while (paramNumber<=paramCount) {
          jsvArrayPush(argsArray, param);
          param = (paramNumber<paramCount) ? paramData[paramNumber] : 0;
          paramNumber++;
        }
      }
      // push the array
      argData[argCount++] = (size_t)argsArray;
      break;
    }
    case JSWAT_BOOL: // boolean
      argData[argCount++] = jsvGetBool(param);
      break;
    case JSWAT_INT32: // 32 bit int
      argData[argCount++] = (uint32_t)jsvGetInteger(param);
      break;
    case JSWAT_PIN: // 16 bit int
      argData[argCount++] = (uint32_t)jshGetPinFromVar(param);
      break;
    case JSWAT_JSVARFLOAT: { // 64 bit float
      JsVarFloat f = jsvGetFloat(param);
#ifdef USE_SEPARATE_DOUBLES
      doubleData[doubleCount++] = f;
#else
      uint64_t i = *(uint64_t*)&f;
#if USE_64BIT
      argData[argCount++] = (size_t)i;
#else // 32 bit...
 #ifdef USE_ARG_REORDERING
      if (argCount&1) {
        size_t argC = argCount+1;
        argData[argC++] = (size_t)((i) & 0xFFFFFFFF);
        argData[argC++] = (size_t)((i>>32) & 0xFFFFFFFF);
        alignedLongsAfter++;
      } else {
        argData[argCount++] = (size_t)((i) & 0xFFFFFFFF);
        argData[argCount++] = (size_t)((i>>32) & 0xFFFFFFFF);
      }
 #else // no reordering
      if (argCount&1) argCount++;
      argData[argCount++] = (size_t)((i) & 0xFFFFFFFF);
      argData[argCount++] = (size_t)((i>>32) & 0xFFFFFFFF);
 #endif
#endif
#endif
      break;
    }
    default:
      assert(0);
      break;
    }