bool jsfsInit() { #ifndef LINUX if (!fat_initialised) { #ifdef SD_CARD_ANYWHERE if (!isSdSPISetup()) { #ifdef SD_SPI const char *deviceStr = jshGetDeviceString(SD_SPI); JsVar *spi = jsvSkipNameAndUnLock(jspGetNamedVariable(deviceStr)); JshSPIInfo inf; jshSPIInitInfo(&inf); inf.pinMISO = SD_DO_PIN; inf.pinMOSI = SD_DI_PIN; inf.pinSCK = SD_CLK_PIN; jshSPISetup(SD_SPI, &inf); sdSPISetup(spi, SD_CS_PIN); jsvUnLock(spi); #else jsError("SD card must be setup with E.connectSDCard first"); return false; #endif } #endif FRESULT res; if ((res = f_mount(&jsfsFAT, "", 1/*immediate*/)) != FR_OK) { jsfsReportError("Unable to mount SD card", res); return false; } fat_initialised = true; } #endif return true; }
/*JSON{ "type":"function", "name" : "analogWrite", "description" : "Set the analog Value of a pin. It will be output using PWM", "generate" : "jswrap_io_analogWrite", "params" : [ [ "pin", "pin", "The pin to use"], [ "value", "float", "A value between 0 and 1"], [ "options", "JsVar", ["An object containing options.", "Currently only freq (pulse frequency in Hz) is available: ```analogWrite(LED1,0.5,{ freq : 10 });``` ", "Note that specifying a frequency will force PWM output, even if the pin has a DAC"] ] ] }*/ void jswrap_io_analogWrite(Pin pin, JsVarFloat value, JsVar *options) { JsVarFloat freq = 0; if (jsvIsObject(options)) { freq = jsvGetFloatAndUnLock(jsvSkipNameAndUnLock(jsvFindChildFromString(options, "freq", false))); } jshPinAnalogOutput(pin, value, freq); }
/*JSON{ "type":"function", "name" : "edit", "description" : ["Fill the console with the contents of the given function, so you can edit it.", "NOTE: This is a convenience function - it will not edit 'inner functions'. For that, you must edit the 'outer function' and re-execute it."], "generate" : "jswrap_interface_edit", "params" : [ [ "funcName", "JsVar", "The name of the function to edit (either a string or just the unquoted name)"] ] }*/ void jswrap_interface_edit(JsVar *funcName) { JsVar *func = 0; if (jsvIsString(funcName)) { funcName = jsvLockAgain(funcName); func = jsvSkipNameAndUnLock(jsvFindChildFromVar(execInfo.root, funcName, 0)); } else { func = funcName; funcName = jsvGetPathTo(execInfo.root, func, 2); } if (jsvIsString(funcName)) { if (jsvIsFunction(func)) { JsVar *scopeVar = jsvFindChildFromString(func, JSPARSE_FUNCTION_SCOPE_NAME, false); JsVar *inRoot = jsvGetArrayIndexOf(execInfo.root, func, true); bool normalDecl = scopeVar==0 && inRoot!=0; jsvUnLock(inRoot); jsvUnLock(scopeVar); JsVar *newLine = jsvNewFromEmptyString(); if (newLine) { // could be out of memory /* normalDecl: * * function foo() { ... } * * NOT normalDecl: * * foo.replaceWith(function() { ... }); * */ JsVar *funcData = jsvAsString(func, false); if (normalDecl) { jsvAppendString(newLine, "function "); jsvAppendStringVarComplete(newLine, funcName); jsvAppendStringVar(newLine, funcData, 9, JSVAPPENDSTRINGVAR_MAXLENGTH); } else { jsvAppendStringVarComplete(newLine, funcName); jsvAppendString(newLine, ".replaceWith("); jsvAppendStringVarComplete(newLine, funcData); jsvAppendString(newLine, ");"); } jsvUnLock(funcData); jsiReplaceInputLine(newLine); jsvUnLock(newLine); } } else { jsError("Edit should be called with the name of a function"); } } else { jsError("Edit should be called with edit(funcName) or edit('funcName')"); } jsvUnLock(func); jsvUnLock(funcName); }
bool run_test(const char *filename) { printf("----------------------------------\r\n"); printf("----------------------------- TEST %s \r\n", filename); char *buffer = read_file(filename); jshInit(); jsiInit(false /* do not autoload!!! */); jspAddNativeFunction(jsiGetParser(), "function quit()", nativeQuit); jspAddNativeFunction(jsiGetParser(), "function interrupt()", nativeInterrupt); jsvUnLock(jspEvaluate(jsiGetParser(), buffer )); isRunning = true; while (isRunning && jsiHasTimers()) jsiLoop(); JsVar *result = jsvSkipNameAndUnLock(jsvFindChildFromString(jsiGetParser()->root, "result", false/*no create*/)); bool pass = jsvGetBool(result); jsvUnLock(result); if (pass) printf("----------------------------- PASS %s\r\n", filename); else { printf("----------------------------------\r\n"); printf("----------------------------- FAIL %s <-------\r\n", filename); jsvTrace(jsvGetRef(jsiGetParser()->root), 0); printf("----------------------------- FAIL %s <-------\r\n", filename); printf("----------------------------------\r\n"); } printf("BEFORE: %d Memory Records Used\r\n", jsvGetMemoryUsage()); // jsvTrace(jsiGetParser()->root, 0); jsiKill(); printf("AFTER: %d Memory Records Used\r\n", jsvGetMemoryUsage()); jsvGarbageCollect(); printf("AFTER GC: %d Memory Records Used (should be 0!)\r\n", jsvGetMemoryUsage()); jsvShowAllocated(); jshKill(); //jsvDottyOutput(); printf("\r\n"); free(buffer); return pass; }
/*JSON{ "type" : "function", "name" : "changeInterval", "generate" : "jswrap_interface_changeInterval", "params" : [ ["id","JsVar","The id returned by a previous call to setInterval"], ["time","float","The new time period in ms"] ] } Change the Interval on a callback created with setInterval, for example: ```var id = setInterval(function () { print('foo'); }, 1000); // every second``` ```changeInterval(id, 1500); // now runs every 1.5 seconds``` This takes effect the next time the callback is called (so it is not immediate). */ void jswrap_interface_changeInterval(JsVar *idVar, JsVarFloat interval) { JsVar *timerArrayPtr = jsvLock(timerArray); if (interval<TIMER_MIN_INTERVAL) interval=TIMER_MIN_INTERVAL; JsVar *timerName = jsvIsBasic(idVar) ? jsvFindChildFromVar(timerArrayPtr, idVar, false) : 0; if (timerName) { JsVar *timer = jsvSkipNameAndUnLock(timerName); JsVar *v; JsVarInt intervalInt = (JsVarInt)jshGetTimeFromMilliseconds(interval); v = jsvNewFromInteger(intervalInt); jsvUnLock2(jsvSetNamedChild(timer, v, "interval"), v); v = jsvNewFromInteger((JsVarInt)(jshGetSystemTime()-jsiLastIdleTime) + intervalInt); jsvUnLock3(jsvSetNamedChild(timer, v, "time"), v, timer); // timerName already unlocked jsiTimersChanged(); // mark timers as changed } else { jsExceptionHere(JSET_ERROR, "Unknown Interval"); } jsvUnLock(timerArrayPtr); }
void lcdSetPixel_JS(JsGraphics *gfx, short x, short y, unsigned int col) { // look up setPixel and execute it! // JsVar *lcdProto = jsvSkipNameAndUnLock(jsvFindChildFromString(gfx->graphicsVar, JSPARSE_PROTOTYPE_VAR, false)); // if (lcdProto) { JsVar *setPixel = jsvSkipNameAndUnLock(jsvFindChildFromString(gfx->graphicsVar/*lcdProto*/, "setPixel", false)); if (setPixel) { JsVar *args[3]; args[0] = jsvNewFromInteger(x); args[1] = jsvNewFromInteger(y); args[2] = jsvNewFromInteger(col); jspExecuteFunction(jsiGetParser(), setPixel, gfx->graphicsVar, 3, args); jsvUnLock(args[0]); jsvUnLock(args[1]); jsvUnLock(args[2]); jsvUnLock(setPixel); } // jsvUnLock(lcdProto); // } }
/*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); }
/*JSON{ "type":"function", "name" : "changeInterval", "description" : ["Change the Interval on a callback created with setInterval, for example:", "```var id = setInterval(function () { print('foo'); }, 1000); // every second```", "```changeInterval(id, 1500); // now runs every 1.5 seconds```", "This takes effect the text time the callback is called (so it is not immediate)."], "generate" : "jswrap_interface_changeInterval", "params" : [ [ "id", "JsVar", "The id returned by a previous call to setInterval"], [ "time","float","The new time period in ms" ] ] }*/ void jswrap_interface_changeInterval(JsVar *idVar, JsVarFloat interval) { JsVar *timerArrayPtr = jsvLock(timerArray); if (interval<TIMER_MIN_INTERVAL) interval=TIMER_MIN_INTERVAL; JsVar *timerName = jsvIsBasic(idVar) ? jsvFindChildFromVar(timerArrayPtr, idVar, false) : 0; if (timerName) { JsVar *timer = jsvSkipNameAndUnLock(timerName); JsVar *v; v = jsvNewFromInteger(jshGetTimeFromMilliseconds(interval)); jsvUnLock(jsvSetNamedChild(timer, v, "interval")); jsvUnLock(v); v = jsvNewFromInteger(jshGetSystemTime() + jshGetTimeFromMilliseconds(interval)); jsvUnLock(jsvSetNamedChild(timer, v, "time")); jsvUnLock(v); jsvUnLock(timer); // timerName already unlocked } else { jsError("Unknown Interval"); } jsvUnLock(timerArrayPtr); }
/*JSON{ "type":"function", "name" : "edit", "description" : ["Fill the console with the contents of the given function, so you can edit it.", "NOTE: This is a convenience function - it will not edit 'inner functions'. For that, you must edit the 'outer function' and re-execute it."], "generate" : "jswrap_interface_edit", "params" : [ [ "funcName", "JsVarName", "The name of the function to edit (either a string or just the unquoted name)"] ] }*/ void jswrap_interface_edit(JsVar *funcName) { if (jsvIsString(funcName)) { JsVar *func = 0; if (jsvIsName(funcName)) func = jsvSkipName(funcName); else func = jsvSkipNameAndUnLock(jsvFindChildFromVar(jsiGetParser()->root, funcName, 0)); if (jsvIsFunction(func)) { JsVar *scopeVar = jsvFindChildFromString(func, JSPARSE_FUNCTION_SCOPE_NAME, false); JsVarRef scope = jsvGetRef(scopeVar); jsvUnLock(scopeVar); JsVar *newLine = jsvNewFromEmptyString(); if (newLine) { // could be out of memory jsvAppendStringVarComplete(newLine, funcName); if (scope) { // If we have a scope, it's an internal function so we will need to write different code jsvAppendString(newLine, ".replaceWith("); } else { jsvAppendString(newLine, " = "); } JsVar *funcData = jsvAsString(func, false); if (funcData) jsvAppendStringVarComplete(newLine, funcData); jsvUnLock(funcData); if (scope) { jsvAppendString(newLine, ");"); } else { jsvAppendString(newLine, ";"); } jsiReplaceInputLine(newLine); jsvUnLock(newLine); } } else { jsError("Edit should be called with the name of a function"); } jsvUnLock(func); } else { jsError("Edit should be called with edit(funcName) or edit('funcName')"); } }
/*JSON{ "type" : "method", "class" : "Object", "name" : "emit", "generate" : "jswrap_object_emit", "params" : [ ["event","JsVar","The name of the event, for instance 'data'"], ["args","JsVarArray","Optional arguments"] ] } Call the event listeners for this object, for instance ```http.emit('data', 'Foo')```. See Node.js's EventEmitter. */ void jswrap_object_emit(JsVar *parent, JsVar *event, JsVar *argArray) { if (!jsvHasChildren(parent)) { jsWarn("Parent must be an object - not a String, Integer, etc."); return; } if (!jsvIsString(event)) { jsWarn("First argument to EventEmitter.emit(..) must be a string"); return; } JsVar *eventName = jsvVarPrintf(JS_EVENT_PREFIX"%s",event); if (!eventName) return; // no memory // extract data const unsigned int MAX_ARGS = 4; JsVar *args[MAX_ARGS]; unsigned int n = 0; JsvObjectIterator it; jsvObjectIteratorNew(&it, argArray); while (jsvObjectIteratorHasValue(&it)) { if (n>=MAX_ARGS) { jsWarn("Too many arguments"); break; } args[n++] = jsvObjectIteratorGetValue(&it); jsvObjectIteratorNext(&it); } jsvObjectIteratorFree(&it); JsVar *callback = jsvSkipNameAndUnLock(jsvFindChildFromVar(parent, eventName, 0)); jsvUnLock(eventName); if (callback) jsiQueueEvents(parent, callback, args, (int)n); jsvUnLock(callback); // unlock jsvUnLockMany(n, args); }
bool jsfsInit() { #ifndef LINUX if (!fat_initialised) { #ifndef USE_FLASHFS #ifdef SD_CARD_ANYWHERE if (!isSdSPISetup()) { #ifdef SD_SPI const char *deviceStr = jshGetDeviceString(SD_SPI); JsVar *spi = jsvSkipNameAndUnLock(jspGetNamedVariable(deviceStr)); JshSPIInfo inf; jshSPIInitInfo(&inf); inf.baudRate = 4000000; // 4Mhz bit rate for onboard SD cards inf.pinMISO = SD_DO_PIN; inf.pinMOSI = SD_DI_PIN; inf.pinSCK = SD_CLK_PIN; jshSPISetup(SD_SPI, &inf); sdSPISetup(spi, SD_CS_PIN); jsvUnLock(spi); #else jsExceptionHere(JSET_ERROR,"SD card must be setup with E.connectSDCard first"); return false; #endif // SD_SPI } #endif // SD_CARD_ANYWHER #endif // USE_FLASHFS FRESULT res; if ((res = f_mount(&jsfsFAT, "", 1)) != FR_OK) { jsfsReportError("Unable to mount media", res); return false; } fat_initialised = true; } #endif // LINUX return true; }
/*JSON{ "type":"constructor", "class": "Array", "name": "Array", "description" : "Create an Array. Either give it one integer argument (>=0) which is the length of the array, or any number of arguments ", "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" ] }*/ JsVar *jswrap_array_constructor(JsVar *args) { assert(args); if (jsvGetArrayLength(args)==1) { JsVar *firstArg = jsvSkipNameAndUnLock(jsvArrayGetLast(args)); // also the first! if (jsvIsInt(firstArg) && jsvGetInteger(firstArg)>=0) { JsVarInt count = jsvGetInteger(firstArg); // we cheat - no need to fill the array - just the last element if (count>0) { JsVar *arr = jsvNewWithFlags(JSV_ARRAY); if (!arr) return 0; // out of memory JsVar *idx = jsvMakeIntoVariableName(jsvNewFromInteger(count-1), 0); if (idx) { // could be out of memory jsvAddName(arr, idx); jsvUnLock(idx); } jsvUnLock(firstArg); return arr; } } jsvUnLock(firstArg); } // Otherwise, we just return the array! return jsvLockAgain(args); }
/*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); }