示例#1
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);
}
示例#2
0
/*JSON{
  "type" : "method",
  "class" : "Number",
  "name" : "toFixed",
  "generate" : "jswrap_number_toFixed",
  "params" : [
    ["decimalPlaces","int32","A number between 0 and 20 specifying the number of decimal digits after the decimal point"]
  ],
  "return" : ["JsVar","A string"]
}
Format the number as a fixed point number
 */
JsVar *jswrap_number_toFixed(JsVar *parent, int decimals) {
  if (decimals<0) decimals=0;
  if (decimals>20) decimals=20;
  char buf[JS_NUMBER_BUFFER_SIZE];
  ftoa_bounded_extra(jsvGetFloat(parent), buf, sizeof(buf), 10, decimals);
  return jsvNewFromString(buf);
}
示例#3
0
/*JSON{
  "type" : "constructor",
  "class" : "Date",
  "name" : "Date",
  "generate" : "jswrap_date_constructor",
  "params" : [
    ["args","JsVarArray","Either nothing (current time), one numeric argument (milliseconds since 1970), a date string (see `Date.parse`), or [year, month, day, hour, minute, second, millisecond] "]
  ],
  "return" : ["JsVar","A Date object"],
  "return_object" : "Date"
}
Creates a date object
*/
JsVar *jswrap_date_constructor(JsVar *args) {
  JsVarFloat time = 0;

  if (jsvGetArrayLength(args)==0) {
    time = jswrap_date_now();
  } else if (jsvGetArrayLength(args)==1) {
    JsVar *arg = jsvGetArrayItem(args, 0);
    if (jsvIsNumeric(arg))
      time = jsvGetFloat(arg);
    else if (jsvIsString(arg))
      time = jswrap_date_parse(arg);
    else
      jsWarn("Variables of type %t are not supported in date constructor", arg);
    jsvUnLock(arg);
  } else {
    CalendarDate date;
    date.year = (int)jsvGetIntegerAndUnLock(jsvGetArrayItem(args, 0));
    date.month = (int)jsvGetIntegerAndUnLock(jsvGetArrayItem(args, 1));
    date.day = (int)jsvGetIntegerAndUnLock(jsvGetArrayItem(args, 2));
    TimeInDay td;
    td.daysSinceEpoch = fromCalenderDate(&date);
    td.hour = (int)jsvGetIntegerAndUnLock(jsvGetArrayItem(args, 3));
    td.min = (int)jsvGetIntegerAndUnLock(jsvGetArrayItem(args, 4));
    td.sec = (int)jsvGetIntegerAndUnLock(jsvGetArrayItem(args, 5));
    td.ms = (int)jsvGetIntegerAndUnLock(jsvGetArrayItem(args, 6));
    td.zone = 0;
    time = fromTimeInDay(&td);
  }

  return jswrap_date_from_milliseconds(time);
}
示例#4
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;
}
示例#5
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;
}
示例#6
0
/*JSON{ "type":"function", "name" : "isNaN",
         "description" : "Whether the x is NaN (Not a Number) or not",
         "generate" : "jswrap_isNaN",
         "params" :  [ [ "x", "JsVar", ""] ],
         "return" : ["bool", "True is the value is NaN, false if not."]
}*/
bool jswrap_isNaN(JsVar *v) {
  if (jsvIsUndefined(v) ||
      jsvIsObject(v) ||
      (jsvIsFloat(v) && isnan(jsvGetFloat(v)))) return true;
  if (jsvIsString(v)) {
    // this is where is can get a bit crazy
    bool allWhiteSpace = true;
    JsvStringIterator it;
    jsvStringIteratorNew(&it,v,0);
    while (jsvStringIteratorHasChar(&it)) {
      if (!isWhitespace(jsvStringIteratorGetChar(&it))) {
        allWhiteSpace = false;
        break;
      }
      jsvStringIteratorNext(&it);
    }
    jsvStringIteratorFree(&it);
    if (allWhiteSpace) return false;
    return isnan(jsvGetFloat(v));
  }
  return false;
}
示例#7
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);
}
示例#8
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 (jsvIsNumeric(firstArg)) {
      JsVarFloat f = jsvGetFloat(firstArg);
      JsVarInt count = jsvGetInteger(firstArg);
      jsvUnLock(firstArg);
      if (f!=count || count<0) {
        jsExceptionHere(JSET_ERROR, "Invalid array length");
        return 0;
      } else {
        JsVar *arr = jsvNewEmptyArray();
        if (!arr) return 0; // out of memory
        jsvSetArrayLength(arr, count, false);
        return arr;
      } 
    } else {
      jsvUnLock(firstArg); 
    }
  }
  // Otherwise, we just return the array!
  return jsvLockAgain(args);
}
示例#9
0
/*JSON{
  "type" : "function",
  "name" : "digitalPulse",
  "generate" : "jswrap_io_digitalPulse",
  "params" : [
    ["pin","pin","The pin to use"],
    ["value","bool","Whether to pulse high (true) or low (false)"],
    ["time","JsVar","A time in milliseconds, or an array of times (in which case a square wave will be output starting with a pulse of 'value')"]
  ]
}
Pulse the pin with the value for the given time in milliseconds. It uses a hardware timer to produce accurate pulses, and returns immediately (before the pulse has finished). Use `digitalPulse(A0,1,0)` to wait until a previous pulse has finished.

eg. `digitalPulse(A0,1,5);` pulses A0 high for 5ms. `digitalPulse(A0,1,[5,2,4]);` pulses A0 high for 5ms, low for 2ms, and high for 4ms

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

digitalPulse is for SHORT pulses that need to be very accurate. If you're doing anything over a few milliseconds, use setTimeout instead.
 */
void jswrap_io_digitalPulse(Pin pin, bool value, JsVar *times) {
  if (jsvIsNumeric(times)) {
    JsVarFloat time = jsvGetFloat(times);
    if (time<0 || isnan(time)) {
      jsExceptionHere(JSET_ERROR, "Pulse Time given for digitalPulse is less than 0, or not a number");
    } else {
      jshPinPulse(pin, value, time);
    }
  } else if (jsvIsIterable(times)) {
    // iterable, so output a square wave
    JsvIterator it;
    jsvIteratorNew(&it, times);
    while (jsvIteratorHasElement(&it)) {
      JsVarFloat time = jsvIteratorGetFloatValue(&it);
      if (time>=0 && !isnan(time))
        jshPinPulse(pin, value, time);
      value = !value;
      jsvIteratorNext(&it);
    }
    jsvIteratorFree(&it);
  } else {
    jsExceptionHere(JSET_ERROR, "Expecting a number or array, got %t", times);
  }
}
示例#10
0
/** 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;
  }
}
示例#11
0
文件: jsnative.c 项目: xbed/MixIO
/** 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;
  }
}
示例#12
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;
    }